diff options
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 119 |
1 files changed, 83 insertions, 36 deletions
diff --git a/read-cache.c b/read-cache.c index 9cff715d6b..5dee4e2b7f 100644 --- a/read-cache.c +++ b/read-cache.c @@ -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, @@ -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; @@ -681,15 +698,18 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, alias = index_file_exists(istate, ce->name, ce_namelen(ce), ignore_case); if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) { /* Nothing changed, really */ - free(ce); if (!S_ISGITLINK(alias->ce_mode)) ce_mark_uptodate(alias); alias->ce_flags |= CE_ADDED; + + free(ce); return 0; } if (!intent_only) { - if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT)) + if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT)) { + free(ce); return error("unable to index file %s", path); + } } else set_object_name_for_intent_to_add_entry(ce); @@ -704,9 +724,11 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, ce->ce_mode == alias->ce_mode); if (pretend) - ; - else if (add_index_entry(istate, ce, add_option)) - return error("unable to add %s to index",path); + free(ce); + else if (add_index_entry(istate, ce, add_option)) { + free(ce); + return error("unable to add %s to index", path); + } if (verbose && !was_same) printf("add '%s'\n", path); return 0; @@ -725,7 +747,7 @@ struct cache_entry *make_cache_entry(unsigned int mode, unsigned int refresh_options) { int size, len; - struct cache_entry *ce; + struct cache_entry *ce, *ret; if (!verify_path(path)) { error("Invalid path '%s'", path); @@ -742,7 +764,10 @@ struct cache_entry *make_cache_entry(unsigned int mode, ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); - return refresh_cache_entry(ce, refresh_options); + ret = refresh_cache_entry(ce, refresh_options); + if (ret != ce) + free(ce); + return ret; } int ce_same_name(const struct cache_entry *a, const struct cache_entry *b) @@ -974,6 +999,8 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e } pos = -pos-1; + untracked_cache_add_to_index(istate, ce->name); + /* * Inserting a merged entry ("stage 0") into the index * will always replace all non-merged entries.. @@ -1364,6 +1391,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", @@ -1480,18 +1510,25 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk, return ce; } -static void check_ce_order(struct cache_entry *ce, struct cache_entry *next_ce) +static void check_ce_order(struct index_state *istate) { - int name_compare = strcmp(ce->name, next_ce->name); - if (0 < name_compare) - die("unordered stage entries in index"); - if (!name_compare) { - if (!ce_stage(ce)) - die("multiple stage entries for merged file '%s'", - ce->name); - if (ce_stage(ce) > ce_stage(next_ce)) - die("unordered stage entries for '%s'", - ce->name); + unsigned int i; + + for (i = 1; i < istate->cache_nr; i++) { + struct cache_entry *ce = istate->cache[i - 1]; + struct cache_entry *next_ce = istate->cache[i]; + int name_compare = strcmp(ce->name, next_ce->name); + + if (0 < name_compare) + die("unordered stage entries in index"); + if (!name_compare) { + if (!ce_stage(ce)) + die("multiple stage entries for merged file '%s'", + ce->name); + if (ce_stage(ce) > ce_stage(next_ce)) + die("unordered stage entries for '%s'", + ce->name); + } } } @@ -1525,7 +1562,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist) if (mmap_size < sizeof(struct cache_header) + 20) die("index file smaller than expected"); - mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + mmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mmap == MAP_FAILED) die_errno("unable to map index file"); close(fd); @@ -1556,9 +1593,6 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist) ce = create_from_disk(disk_ce, &consumed, previous_name); set_index_entry(istate, i, ce); - if (i > 0) - check_ce_order(istate->cache[i - 1], ce); - src_offset += consumed; } strbuf_release(&previous_name_buf); @@ -1602,11 +1636,10 @@ int read_index_from(struct index_state *istate, const char *path) ret = do_read_index(istate, path, 0); split_index = istate->split_index; - if (!split_index) - return ret; - - if (is_null_sha1(split_index->base_sha1)) + if (!split_index || is_null_sha1(split_index->base_sha1)) { + check_ce_order(istate); return ret; + } if (split_index->base) discard_index(split_index->base); @@ -1622,6 +1655,7 @@ int read_index_from(struct index_state *istate, const char *path) sha1_to_hex(split_index->base_sha1)), sha1_to_hex(split_index->base->sha1)); merge_base_index(istate); + check_ce_order(istate); return ret; } @@ -1655,6 +1689,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; } @@ -2041,6 +2077,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; |