From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 3/4] read-cache: hide refresh_cache_entry()
Date: Fri, 30 Oct 2026 10:39:55 -0700 [thread overview]
Message-ID: <20261030173956.585250-4-gitster@pobox.com> (raw)
In-Reply-To: <20261030173956.585250-1-gitster@pobox.com>
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 <gitster@pobox.com>
---
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
next prev parent reply other threads:[~2026-10-30 17:40 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 17:39 [PATCH 0/4] mark symbols that are unnecessarily public static Junio C Hamano
2026-10-30 17:39 ` [PATCH 1/4] ident: remove unused author_ident_sufficiently_given() Junio C Hamano
2026-10-30 18:22 ` Jeff King
2026-10-30 17:39 ` [PATCH 2/4] add -i: hide init/clear_add_i_state() functions Junio C Hamano
2026-10-30 17:39 ` Junio C Hamano [this message]
2026-10-30 18:25 ` [PATCH 3/4] read-cache: hide refresh_cache_entry() Jeff King
2026-10-30 17:39 ` [PATCH 4/4] unpack-trees: hide verify_uptodate() Junio C Hamano
2026-10-30 18:26 ` [PATCH 0/4] mark symbols that are unnecessarily public static Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030173956.585250-4-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.