summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c157
1 files changed, 89 insertions, 68 deletions
diff --git a/read-cache.c b/read-cache.c
index bf322708f0..db27766055 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -5,6 +5,7 @@
*/
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
+#include "tempfile.h"
#include "lockfile.h"
#include "cache-tree.h"
#include "refs.h"
@@ -16,7 +17,6 @@
#include "strbuf.h"
#include "varint.h"
#include "split-index.h"
-#include "sigchain.h"
#include "utf8.h"
static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
@@ -39,11 +39,12 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
#define CACHE_EXT_TREE 0x54524545 /* "TREE" */
#define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUC" */
#define CACHE_EXT_LINK 0x6c696e6b /* "link" */
+#define CACHE_EXT_UNTRACKED 0x554E5452 /* "UNTR" */
/* changes that can be kept in $GIT_DIR/index (basically all extensions) */
#define EXTMASK (RESOLVE_UNDO_CHANGED | CACHE_TREE_CHANGED | \
CE_ENTRY_ADDED | CE_ENTRY_REMOVED | CE_ENTRY_CHANGED | \
- SPLIT_INDEX_ORDERED)
+ SPLIT_INDEX_ORDERED | UNTRACKED_CHANGED)
struct index_state the_index;
static const char *alternate_index_output;
@@ -79,6 +80,7 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
memcpy(new->name, new_name, namelen + 1);
cache_tree_invalidate_path(istate, old->name);
+ untracked_cache_remove_from_index(istate, old->name);
remove_index_entry_at(istate, nr);
add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
}
@@ -270,20 +272,34 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
return changed;
}
-static int is_racy_timestamp(const struct index_state *istate,
- const struct cache_entry *ce)
+static int is_racy_stat(const struct index_state *istate,
+ const struct stat_data *sd)
{
- return (!S_ISGITLINK(ce->ce_mode) &&
- istate->timestamp.sec &&
+ return (istate->timestamp.sec &&
#ifdef USE_NSEC
/* nanosecond timestamped files can also be racy! */
- (istate->timestamp.sec < ce->ce_stat_data.sd_mtime.sec ||
- (istate->timestamp.sec == ce->ce_stat_data.sd_mtime.sec &&
- istate->timestamp.nsec <= ce->ce_stat_data.sd_mtime.nsec))
+ (istate->timestamp.sec < sd->sd_mtime.sec ||
+ (istate->timestamp.sec == sd->sd_mtime.sec &&
+ istate->timestamp.nsec <= sd->sd_mtime.nsec))
#else
- istate->timestamp.sec <= ce->ce_stat_data.sd_mtime.sec
+ istate->timestamp.sec <= sd->sd_mtime.sec
#endif
- );
+ );
+}
+
+static int is_racy_timestamp(const struct index_state *istate,
+ const struct cache_entry *ce)
+{
+ return (!S_ISGITLINK(ce->ce_mode) &&
+ is_racy_stat(istate, &ce->ce_stat_data));
+}
+
+int match_stat_data_racy(const struct index_state *istate,
+ const struct stat_data *sd, struct stat *st)
+{
+ if (is_racy_stat(istate, sd))
+ return MTIME_CHANGED;
+ return match_stat_data(sd, st);
}
int ie_match_stat(const struct index_state *istate,
@@ -311,7 +327,7 @@ int ie_match_stat(const struct index_state *istate,
* by definition never matches what is in the work tree until it
* actually gets added.
*/
- if (ce->ce_flags & CE_INTENT_TO_ADD)
+ if (ce_intent_to_add(ce))
return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
changed = ce_match_stat_basic(ce, st);
@@ -538,6 +554,7 @@ int remove_file_from_index(struct index_state *istate, const char *path)
if (pos < 0)
pos = -pos-1;
cache_tree_invalidate_path(istate, path);
+ untracked_cache_remove_from_index(istate, path);
while (pos < istate->cache_nr && !strcmp(istate->cache[pos]->name, path))
remove_index_entry_at(istate, pos);
return 0;
@@ -613,7 +630,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
hashcpy(ce->sha1, sha1);
}
-int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
+int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags, int force_mode)
{
int size, namelen, was_same;
mode_t st_mode = st->st_mode;
@@ -642,7 +659,9 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
else
ce->ce_flags |= CE_INTENT_TO_ADD;
- if (trust_executable_bit && has_symlinks)
+ if (S_ISREG(st_mode) && force_mode)
+ ce->ce_mode = create_ce_mode(force_mode);
+ else if (trust_executable_bit && has_symlinks)
ce->ce_mode = create_ce_mode(st_mode);
else {
/* If there is an existing entry, pick the mode bits and type
@@ -661,21 +680,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
* entry's directory case.
*/
if (ignore_case) {
- const char *startPtr = ce->name;
- const char *ptr = startPtr;
- while (*ptr) {
- while (*ptr && *ptr != '/')
- ++ptr;
- if (*ptr == '/') {
- struct cache_entry *foundce;
- ++ptr;
- foundce = index_dir_exists(istate, ce->name, ptr - ce->name - 1);
- if (foundce) {
- memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr);
- startPtr = ptr;
- }
- }
- }
+ adjust_dirname_case(istate, ce->name);
}
alias = index_file_exists(istate, ce->name, ce_namelen(ce), ignore_case);
@@ -717,12 +722,13 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
return 0;
}
-int add_file_to_index(struct index_state *istate, const char *path, int flags)
+int add_file_to_index(struct index_state *istate, const char *path,
+ int flags, int force_mode)
{
struct stat st;
if (lstat(path, &st))
die_errno("unable to stat '%s'", path);
- return add_to_index(istate, path, &st, flags);
+ return add_to_index(istate, path, &st, flags, force_mode);
}
struct cache_entry *make_cache_entry(unsigned int mode,
@@ -982,6 +988,9 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
}
pos = -pos-1;
+ if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
+ untracked_cache_add_to_index(istate, ce->name);
+
/*
* Inserting a merged entry ("stage 0") into the index
* will always replace all non-merged entries..
@@ -1231,7 +1240,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
if (cache_errno == ENOENT)
fmt = deleted_fmt;
- else if (ce->ce_flags & CE_INTENT_TO_ADD)
+ else if (ce_intent_to_add(ce))
fmt = added_fmt; /* must be before other checks */
else if (changed & TYPE_CHANGED)
fmt = typechange_fmt;
@@ -1372,6 +1381,9 @@ static int read_index_extension(struct index_state *istate,
if (read_link_extension(istate, data, sz))
return -1;
break;
+ case CACHE_EXT_UNTRACKED:
+ istate->untracked = read_untracked_extension(data, sz);
+ break;
default:
if (*ext < 'A' || 'Z' < *ext)
return error("index uses %.4s extension, which we do not understand",
@@ -1510,6 +1522,28 @@ static void check_ce_order(struct index_state *istate)
}
}
+static void tweak_untracked_cache(struct index_state *istate)
+{
+ switch (git_config_get_untracked_cache()) {
+ case -1: /* keep: do nothing */
+ break;
+ case 0: /* false */
+ remove_untracked_cache(istate);
+ break;
+ case 1: /* true */
+ add_untracked_cache(istate);
+ break;
+ default: /* unknown value: do nothing */
+ break;
+ }
+}
+
+static void post_read_index_from(struct index_state *istate)
+{
+ check_ce_order(istate);
+ tweak_untracked_cache(istate);
+}
+
/* remember to discard_cache() before reading a different cache! */
int do_read_index(struct index_state *istate, const char *path, int must_exist)
{
@@ -1613,9 +1647,10 @@ int read_index_from(struct index_state *istate, const char *path)
return istate->cache_nr;
ret = do_read_index(istate, path, 0);
+
split_index = istate->split_index;
if (!split_index || is_null_sha1(split_index->base_sha1)) {
- check_ce_order(istate);
+ post_read_index_from(istate);
return ret;
}
@@ -1630,10 +1665,10 @@ int read_index_from(struct index_state *istate, const char *path)
die("broken index, expect %s in %s, got %s",
sha1_to_hex(split_index->base_sha1),
git_path("sharedindex.%s",
- sha1_to_hex(split_index->base_sha1)),
+ sha1_to_hex(split_index->base_sha1)),
sha1_to_hex(split_index->base->sha1));
merge_base_index(istate);
- check_ce_order(istate);
+ post_read_index_from(istate);
return ret;
}
@@ -1667,6 +1702,8 @@ int discard_index(struct index_state *istate)
istate->cache = NULL;
istate->cache_alloc = 0;
discard_split_index(istate);
+ free_untracked_cache(istate->untracked);
+ istate->untracked = NULL;
return 0;
}
@@ -2053,6 +2090,17 @@ static int do_write_index(struct index_state *istate, int newfd,
if (err)
return -1;
}
+ if (!strip_extensions && istate->untracked) {
+ struct strbuf sb = STRBUF_INIT;
+
+ write_untracked_extension(&sb, istate->untracked);
+ err = write_index_ext_header(&c, newfd, CACHE_EXT_UNTRACKED,
+ sb.len) < 0 ||
+ ce_write(&c, newfd, sb.buf, sb.len) < 0;
+ strbuf_release(&sb);
+ if (err)
+ return -1;
+ }
if (ce_flush(&c, newfd, istate->sha1) || fstat(newfd, &st))
return -1;
@@ -2077,7 +2125,7 @@ static int commit_locked_index(struct lock_file *lk)
static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
unsigned flags)
{
- int ret = do_write_index(istate, lock->fd, 0);
+ int ret = do_write_index(istate, get_lock_file_fd(lock), 0);
if (ret)
return ret;
assert((flags & (COMMIT_LOCK | CLOSE_LOCK)) !=
@@ -2101,54 +2149,27 @@ static int write_split_index(struct index_state *istate,
return ret;
}
-static char *temporary_sharedindex;
-
-static void remove_temporary_sharedindex(void)
-{
- if (temporary_sharedindex) {
- unlink_or_warn(temporary_sharedindex);
- free(temporary_sharedindex);
- temporary_sharedindex = NULL;
- }
-}
-
-static void remove_temporary_sharedindex_on_signal(int signo)
-{
- remove_temporary_sharedindex();
- sigchain_pop(signo);
- raise(signo);
-}
+static struct tempfile temporary_sharedindex;
static int write_shared_index(struct index_state *istate,
struct lock_file *lock, unsigned flags)
{
struct split_index *si = istate->split_index;
- static int installed_handler;
int fd, ret;
- temporary_sharedindex = git_pathdup("sharedindex_XXXXXX");
- fd = mkstemp(temporary_sharedindex);
+ fd = mks_tempfile(&temporary_sharedindex, git_path("sharedindex_XXXXXX"));
if (fd < 0) {
- free(temporary_sharedindex);
- temporary_sharedindex = NULL;
hashclr(si->base_sha1);
return do_write_locked_index(istate, lock, flags);
}
- if (!installed_handler) {
- atexit(remove_temporary_sharedindex);
- sigchain_push_common(remove_temporary_sharedindex_on_signal);
- }
move_cache_to_base_index(istate);
ret = do_write_index(si->base, fd, 1);
- close(fd);
if (ret) {
- remove_temporary_sharedindex();
+ delete_tempfile(&temporary_sharedindex);
return ret;
}
- ret = rename(temporary_sharedindex,
- git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
- free(temporary_sharedindex);
- temporary_sharedindex = NULL;
+ ret = rename_tempfile(&temporary_sharedindex,
+ git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
if (!ret)
hashcpy(si->base_sha1, si->base->sha1);
return ret;