X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=read-cache.c;h=35fec468b1951cc17606fca8edc47f809471f652;hb=34baebcee1d66be4cc096a69ba448cd24dcedf21;hp=a50a851125db765f06f3869873623bf7592de405;hpb=d9d9e6ee6366fed93a4beff3994bad376f81eabd;p=git.git diff --git a/read-cache.c b/read-cache.c index a50a85112..35fec468b 100644 --- a/read-cache.c +++ b/read-cache.c @@ -38,6 +38,22 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache istate->cache_changed = 1; } +void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name) +{ + struct cache_entry *old = istate->cache[nr], *new; + int namelen = strlen(new_name); + + new = xmalloc(cache_entry_size(namelen)); + copy_cache_entry(new, old); + new->ce_flags &= ~(CE_STATE_MASK | CE_NAMEMASK); + new->ce_flags |= (namelen >= CE_NAMEMASK ? CE_NAMEMASK : namelen); + memcpy(new->name, new_name, namelen + 1); + + cache_tree_invalidate_path(istate->cache_tree, old->name); + remove_index_entry_at(istate, nr); + add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); +} + /* * This only updates the "non-critical" parts of the directory * cache, ie the parts that aren't tracked by GIT, and only used @@ -131,7 +147,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st) break; case S_IFDIR: if (S_ISGITLINK(ce->ce_mode)) - return 0; + return ce_compare_gitlink(ce) ? DATA_CHANGED : 0; default: return TYPE_CHANGED; } @@ -171,6 +187,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) changed |= TYPE_CHANGED; break; case S_IFGITLINK: + /* We ignore most of the st_xxx fields for gitlinks */ if (!S_ISDIR(st->st_mode)) changed |= TYPE_CHANGED; else if (ce_compare_gitlink(ce)) @@ -181,7 +198,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) } if (ce->ce_mtime != (unsigned int) st->st_mtime) changed |= MTIME_CHANGED; - if (ce->ce_ctime != (unsigned int) st->st_ctime) + if (trust_ctime && ce->ce_ctime != (unsigned int) st->st_ctime) changed |= CTIME_CHANGED; if (ce->ce_uid != (unsigned int) st->st_uid || @@ -277,11 +294,22 @@ int ie_modified(const struct index_state *istate, if (changed & (MODE_CHANGED | TYPE_CHANGED)) return changed; - /* Immediately after read-tree or update-index --cacheinfo, - * the length field is zero. For other cases the ce_size - * should match the SHA1 recorded in the index entry. + /* + * Immediately after read-tree or update-index --cacheinfo, + * the length field is zero, as we have never even read the + * lstat(2) information once, and we cannot trust DATA_CHANGED + * returned by ie_match_stat() which in turn was returned by + * ce_match_stat_basic() to signal that the filesize of the + * blob changed. We have to actually go to the filesystem to + * see if the contents match, and if so, should answer "unchanged". + * + * The logic does not apply to gitlinks, as ce_match_stat_basic() + * already has checked the actual HEAD from the filesystem in the + * subproject. If ie_match_stat() already said it is different, + * then we know it is. */ - if ((changed & DATA_CHANGED) && ce->ce_size != 0) + if ((changed & DATA_CHANGED) && + (S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0)) return changed; changed_fs = ce_modified_check_fs(ce, st); @@ -1127,7 +1155,7 @@ int read_index_from(struct index_state *istate, const char *path) size_t mmap_size; errno = EBUSY; - if (istate->alloc) + if (istate->initialized) return istate->cache_nr; errno = ENOENT; @@ -1167,6 +1195,7 @@ int read_index_from(struct index_state *istate, const char *path) * index size */ istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr)); + istate->initialized = 1; src_offset = sizeof(*hdr); dst_offset = 0; @@ -1219,6 +1248,7 @@ int discard_index(struct index_state *istate) cache_tree_free(&(istate->cache_tree)); free(istate->alloc); istate->alloc = NULL; + istate->initialized = 0; /* no need to throw away allocated active_cache */ return 0; @@ -1310,6 +1340,11 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) * falsely clean entry due to touch-update-touch race, so we leave * everything else as they are. We are called for entries whose * ce_mtime match the index file mtime. + * + * Note that this actually does not do much for gitlinks, for + * which ce_match_stat_basic() always goes to the actual + * contents. The caller checks with is_racy_timestamp() which + * always says "no" for gitlinks, so we are not called for them ;-) */ struct stat st;