[PATCH 3/4] read-cache: hide refresh_cache_entry()
flat view
WARM1d
From: Junio C Hamano <hidden>
Date: 2026-10-30 17:40:05
Subsystem:
the rest · Maintainer:
Linus Torvalds
Once upon a time, there was a merge strategy called "recursive", which was added in 6d297f8137 (Status update on merge-recursive in C, 2006-07-08). This implementation came with its own machinery that creates an in-core index entry, and then refreshed the index entry it created by calling the refresh_cache_entry() function borrowed from the read-cache.c API. refresh_cache_entry() used to be file-scope static, but was made public with this change. When ad45b327c0 (merge-recursive.[ch]: thoroughly debug these, 2025-04-08) finally removed the entire code for the "recursive" merge strategy, the last external caller of refresh_cache_entry() went with it. Hide the low-level implementation detail again by making it a file-scope static function. The external callers would indirectly call it when they call make_cache_entry() or rename_index_entry_at() external interface, which "ort" (the successor of "recursive") does. Signed-off-by: Junio C Hamano <redacted> --- read-cache-ll.h | 2 - read-cache.c | 258 ++++++++++++++++++++++++------------------------ 2 files changed, 129 insertions(+), 131 deletions(-)
diff --git a/read-cache-ll.h b/read-cache-ll.h
index 066dd8bc3b..dd30befbb3 100644
--- a/read-cache-ll.h
+++ b/read-cache-ll.h@@ -475,8 +475,6 @@ int refresh_index(struct index_state *, unsigned int flags, const struct pathspe */ int repo_refresh_and_write_index(struct repository*, unsigned int refresh_flags, unsigned int write_flags, int gentle, const struct pathspec *, char *seen, const char *header_msg); -struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int); - void set_alternate_index_output(const char *); extern int verify_index_checksum;
diff --git a/read-cache.c b/read-cache.c
index e40f290bb3..555bf55132 100644
--- a/read-cache.c
+++ b/read-cache.c@@ -129,6 +129,135 @@ static struct mem_pool *find_mem_pool(struct index_state *istate) return *pool_ptr; } +/* + * "refresh" does not calculate a new sha1 file or bring the + * cache up-to-date for mode/content changes. But what it + * _does_ do is to "re-match" the stat information of a file + * with the cache, so that you can refresh the cache for a + * file that hasn't been changed but where the stat entry is + * out of date. + * + * For example, you'd want to do this after doing a "git-read-tree", + * to link up the stat cache details with the proper files. + */ +static struct cache_entry *refresh_cache_ent(struct index_state *istate, + struct cache_entry *ce, + unsigned int options, int *err, + int *changed_ret, + int *t2_did_lstat, + int *t2_did_scan) +{ + struct stat st; + struct cache_entry *updated; + int changed; + int refresh = options & CE_MATCH_REFRESH; + int ignore_valid = options & CE_MATCH_IGNORE_VALID; + int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE; + int ignore_missing = options & CE_MATCH_IGNORE_MISSING; + int ignore_fsmonitor = options & CE_MATCH_IGNORE_FSMONITOR; + + if (!refresh || ce_uptodate(ce)) + return ce; + + if (!ignore_fsmonitor) + refresh_fsmonitor(istate); + /* + * CE_VALID or CE_SKIP_WORKTREE means the user promised us + * that the change to the work tree does not matter and told + * us not to worry. + */ + if (!ignore_skip_worktree && ce_skip_worktree(ce)) { + ce_mark_uptodate(ce); + return ce; + } + if (!ignore_valid && (ce->ce_flags & CE_VALID)) { + ce_mark_uptodate(ce); + return ce; + } + if (!ignore_fsmonitor && (ce->ce_flags & CE_FSMONITOR_VALID)) { + ce_mark_uptodate(ce); + return ce; + } + + if (has_symlink_leading_path(ce->name, ce_namelen(ce))) { + if (ignore_missing) + return ce; + if (err) + *err = ENOENT; + return NULL; + } + + if (t2_did_lstat) + *t2_did_lstat = 1; + if (lstat(ce->name, &st) < 0) { + if (ignore_missing && errno == ENOENT) + return ce; + if (err) + *err = errno; + return NULL; + } + + changed = ie_match_stat(istate, ce, &st, options); + if (changed_ret) + *changed_ret = changed; + if (!changed) { + /* + * The path is unchanged. If we were told to ignore + * valid bit, then we did the actual stat check and + * found that the entry is unmodified. If the entry + * is not marked VALID, this is the place to mark it + * valid again, under "assume unchanged" mode. + */ + if (ignore_valid && assume_unchanged && + !(ce->ce_flags & CE_VALID)) + ; /* mark this one VALID again */ + else { + /* + * We do not mark the index itself "modified" + * because CE_UPTODATE flag is in-core only; + * we are not going to write this change out. + */ + if (!S_ISGITLINK(ce->ce_mode)) { + ce_mark_uptodate(ce); + mark_fsmonitor_valid(istate, ce); + } + return ce; + } + } + + if (t2_did_scan) + *t2_did_scan = 1; + if (ie_modified(istate, ce, &st, options)) { + if (err) + *err = EINVAL; + return NULL; + } + + updated = make_empty_cache_entry(istate, ce_namelen(ce)); + copy_cache_entry(updated, ce); + memcpy(updated->name, ce->name, ce->ce_namelen + 1); + fill_stat_cache_info(istate, updated, &st); + /* + * If ignore_valid is not set, we should leave CE_VALID bit + * alone. Otherwise, paths marked with --no-assume-unchanged + * (i.e. things to be edited) will reacquire CE_VALID bit + * automatically, which is not really what we want. + */ + if (!ignore_valid && assume_unchanged && + !(ce->ce_flags & CE_VALID)) + updated->ce_flags &= ~CE_VALID; + + /* istate->cache_changed is updated in the caller */ + return updated; +} + +static struct cache_entry *refresh_cache_entry(struct index_state *istate, + struct cache_entry *ce, + unsigned int options) +{ + return refresh_cache_ent(istate, ce, options, NULL, NULL, NULL, NULL); +} + static const char *alternate_index_output; static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
@@ -1339,128 +1468,6 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti return 0; } -/* - * "refresh" does not calculate a new sha1 file or bring the - * cache up-to-date for mode/content changes. But what it - * _does_ do is to "re-match" the stat information of a file - * with the cache, so that you can refresh the cache for a - * file that hasn't been changed but where the stat entry is - * out of date. - * - * For example, you'd want to do this after doing a "git-read-tree", - * to link up the stat cache details with the proper files. - */ -static struct cache_entry *refresh_cache_ent(struct index_state *istate, - struct cache_entry *ce, - unsigned int options, int *err, - int *changed_ret, - int *t2_did_lstat, - int *t2_did_scan) -{ - struct stat st; - struct cache_entry *updated; - int changed; - int refresh = options & CE_MATCH_REFRESH; - int ignore_valid = options & CE_MATCH_IGNORE_VALID; - int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE; - int ignore_missing = options & CE_MATCH_IGNORE_MISSING; - int ignore_fsmonitor = options & CE_MATCH_IGNORE_FSMONITOR; - - if (!refresh || ce_uptodate(ce)) - return ce; - - if (!ignore_fsmonitor) - refresh_fsmonitor(istate); - /* - * CE_VALID or CE_SKIP_WORKTREE means the user promised us - * that the change to the work tree does not matter and told - * us not to worry. - */ - if (!ignore_skip_worktree && ce_skip_worktree(ce)) { - ce_mark_uptodate(ce); - return ce; - } - if (!ignore_valid && (ce->ce_flags & CE_VALID)) { - ce_mark_uptodate(ce); - return ce; - } - if (!ignore_fsmonitor && (ce->ce_flags & CE_FSMONITOR_VALID)) { - ce_mark_uptodate(ce); - return ce; - } - - if (has_symlink_leading_path(ce->name, ce_namelen(ce))) { - if (ignore_missing) - return ce; - if (err) - *err = ENOENT; - return NULL; - } - - if (t2_did_lstat) - *t2_did_lstat = 1; - if (lstat(ce->name, &st) < 0) { - if (ignore_missing && errno == ENOENT) - return ce; - if (err) - *err = errno; - return NULL; - } - - changed = ie_match_stat(istate, ce, &st, options); - if (changed_ret) - *changed_ret = changed; - if (!changed) { - /* - * The path is unchanged. If we were told to ignore - * valid bit, then we did the actual stat check and - * found that the entry is unmodified. If the entry - * is not marked VALID, this is the place to mark it - * valid again, under "assume unchanged" mode. - */ - if (ignore_valid && assume_unchanged && - !(ce->ce_flags & CE_VALID)) - ; /* mark this one VALID again */ - else { - /* - * We do not mark the index itself "modified" - * because CE_UPTODATE flag is in-core only; - * we are not going to write this change out. - */ - if (!S_ISGITLINK(ce->ce_mode)) { - ce_mark_uptodate(ce); - mark_fsmonitor_valid(istate, ce); - } - return ce; - } - } - - if (t2_did_scan) - *t2_did_scan = 1; - if (ie_modified(istate, ce, &st, options)) { - if (err) - *err = EINVAL; - return NULL; - } - - updated = make_empty_cache_entry(istate, ce_namelen(ce)); - copy_cache_entry(updated, ce); - memcpy(updated->name, ce->name, ce->ce_namelen + 1); - fill_stat_cache_info(istate, updated, &st); - /* - * If ignore_valid is not set, we should leave CE_VALID bit - * alone. Otherwise, paths marked with --no-assume-unchanged - * (i.e. things to be edited) will reacquire CE_VALID bit - * automatically, which is not really what we want. - */ - if (!ignore_valid && assume_unchanged && - !(ce->ce_flags & CE_VALID)) - updated->ce_flags &= ~CE_VALID; - - /* istate->cache_changed is updated in the caller */ - return updated; -} - static void show_file(const char * fmt, const char * name, int in_porcelain, int * first, const char *header_msg) {
@@ -1627,13 +1634,6 @@ int refresh_index(struct index_state *istate, unsigned int flags, return has_errors; } -struct cache_entry *refresh_cache_entry(struct index_state *istate, - struct cache_entry *ce, - unsigned int options) -{ - return refresh_cache_ent(istate, ce, options, NULL, NULL, NULL, NULL); -} - /***************************************************************** * Index File I/O
--
2.56.0-486-gd49ba3b80a