X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;ds=inline;f=read-cache.c;h=042b0c2107330c35731a4d42c9907e0b34ad5257;hb=e8871e88adca0637eb0299a41d85400beac928bd;hp=acc6e236d307c87a20468b25a765426eaebb5137;hpb=95fd5bf82ae28da47dcbf8e6e4570e64d71dc532;p=git.git diff --git a/read-cache.c b/read-cache.c index acc6e236..042b0c21 100644 --- a/read-cache.c +++ b/read-cache.c @@ -303,7 +303,8 @@ int cache_match_stat(struct cache_entry *ce, struct stat *st) if (ce->ce_uid != htonl(st->st_uid) || ce->ce_gid != htonl(st->st_gid)) changed |= OWNER_CHANGED; - if (ce->ce_mode != htonl(st->st_mode)) + /* We consider only the owner x bit to be relevant for "mode changes" */ + if (0100 & (ntohl(ce->ce_mode) ^ st->st_mode)) changed |= MODE_CHANGED; if (ce->ce_dev != htonl(st->st_dev) || ce->ce_ino != htonl(st->st_ino)) @@ -355,17 +356,32 @@ int cache_name_pos(const char *name, int namelen) return -first-1; } +/* Remove entry, return true if there are more entries to go.. */ +static int remove_entry_at(int pos) +{ + active_nr--; + if (pos >= active_nr) + return 0; + memmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *)); + return 1; +} + int remove_file_from_cache(char *path) { int pos = cache_name_pos(path, strlen(path)); - if (pos >= 0) { - active_nr--; - if (pos < active_nr) - memmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *)); - } + if (pos < 0) + pos = -pos-1; + while (pos < active_nr && !strcmp(active_cache[pos]->name, path)) + remove_entry_at(pos); return 0; } +static int same_name(struct cache_entry *a, struct cache_entry *b) +{ + int len = ce_namelen(a); + return ce_namelen(b) == len && !memcmp(a->name, b->name, len); +} + int add_cache_entry(struct cache_entry *ce, int ok_to_add) { int pos; @@ -379,6 +395,19 @@ int add_cache_entry(struct cache_entry *ce, int ok_to_add) } pos = -pos-1; + /* + * Inserting a merged entry ("stage 0") into the index + * will always replace all non-merged entries.. + */ + if (pos < active_nr && ce_stage(ce) == 0) { + while (same_name(active_cache[pos], ce)) { + ok_to_add = 1; + active_nr--; + if (!remove_entry_at(pos)) + break; + } + } + if (!ok_to_add) return -1;