read-cache: pass 'repo' to 'ce_mode_from_stat()'

The ce_mode_from_stat() function is a performance-critical static inline helper in 'read-cache.h'. As we migrate configuration variables into the repository struct, this helper needs access to the repository context. Update the signature of ce_mode_from_stat() to take a 'struct repository *' parameter, and update all callers to pass the appropriate repository instance. To prepare for the overhead of replacing cheap global variable accesses with getter functions, the boolean expressions are reordered to evaluate 'S_ISREG(mode)' first. While at it, add a comment for ce_mode_from_stat(). Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com> Mentored-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Tian Yuchen <cat@malon.dev> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tian Yuchen committed Jul 20, 2026 at 18:53 UTC b7b6e9e02f6b6b84848b2458d5d2b3d47260d4bb
5 files changed +20 -11
apply.c
+1 -1
@@ -3894,7 +3894,7 @@ static int check_preimage(struct apply_state *state,
3894 BUG("ce_mode == 0 for path '%s'", old_name);
3895
3896 if (trust_executable_bit || !S_ISREG(st->st_mode))
3897 - st_mode = ce_mode_from_stat(*ce, st->st_mode);
3897 + st_mode = ce_mode_from_stat(state->repo, *ce, st->st_mode);
3898 else if (*ce)
3899 st_mode = (*ce)->ce_mode;
3900 else
builtin/update-index.c
+1 -1
@@ -294,7 +294,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
294 ce->ce_flags = create_ce_flags(0);
295 ce->ce_namelen = len;
296 fill_stat_cache_info(the_repository->index, ce, st);
297 - ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
297 + ce->ce_mode = ce_mode_from_stat(the_repository, old, st->st_mode);
298
299 if (index_path(the_repository->index, &ce->oid, path, st,
300 info_only ? 0 : INDEX_WRITE_OBJECT)) {
diff-lib.c
+5 -5
@@ -160,7 +160,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
160
161 changed = check_removed(ce, &st);
162 if (!changed)
163 - wt_mode = ce_mode_from_stat(ce, st.st_mode);
163 + wt_mode = ce_mode_from_stat(revs->repo, ce, st.st_mode);
164 else {
165 if (changed < 0) {
166 perror(ce->name);
@@ -193,7 +193,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
193 num_compare_stages++;
194 oidcpy(&dpath->parent[stage - 2].oid,
195 &nce->oid);
196 - dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode);
196 + dpath->parent[stage-2].mode = ce_mode_from_stat(revs->repo, nce, mode);
197 dpath->parent[stage-2].status =
198 DIFF_STATUS_MODIFIED;
199 }
@@ -262,7 +262,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
262 continue;
263 } else if (revs->diffopt.ita_invisible_in_index &&
264 ce_intent_to_add(ce)) {
265 - newmode = ce_mode_from_stat(ce, st.st_mode);
265 + newmode = ce_mode_from_stat(revs->repo, ce, st.st_mode);
266 diff_addremove(&revs->diffopt, '+', newmode,
267 null_oid(the_hash_algo), 0, ce->name, 0);
268 continue;
@@ -270,7 +270,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
270
271 changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
272 ce_option, &dirty_submodule);
273 - newmode = ce_mode_from_stat(ce, st.st_mode);
273 + newmode = ce_mode_from_stat(revs->repo, ce, st.st_mode);
274 }
275
276 if (!changed && !dirty_submodule) {
@@ -338,7 +338,7 @@ static int get_stat_data(const struct cache_entry *ce,
338 changed = match_stat_with_submodule(diffopt, ce, &st,
339 0, dirty_submodule);
340 if (changed) {
341 - mode = ce_mode_from_stat(ce, st.st_mode);
341 + mode = ce_mode_from_stat(diffopt->repo, ce, st.st_mode);
342 oid = null_oid(the_hash_algo);
343 }
344 }
read-cache.c
+1 -1
@@ -750,7 +750,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
750 int pos = index_name_pos_also_unmerged(istate, path, namelen);
751
752 ent = (0 <= pos) ? istate->cache[pos] : NULL;
753 - ce->ce_mode = ce_mode_from_stat(ent, st_mode);
753 + ce->ce_mode = ce_mode_from_stat(istate->repo, ent, st_mode);
754 }
755
756 /* When core.ignorecase=true, determine if a directory of the same name but differing
read-cache.h
+12 -3
@@ -4,15 +4,24 @@
4 #include "read-cache-ll.h"
5 #include "object.h"
6 #include "pathspec.h"
7 +#include "environment.h"
8
8 -static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
9 +/*
10 + * Determine the appropriate index mode for a file based on its stat()
11 + * information and the existing cache entry (if any).
12 + *
13 + * This function handles degradation for filesystems that lack
14 + * symlink support or reliable executable bits.
15 + */
16 +static inline unsigned int ce_mode_from_stat(struct repository *repo UNUSED,
17 + const struct cache_entry *ce,
18 unsigned int mode)
19 {
20 extern int trust_executable_bit, has_symlinks;
12 - if (!has_symlinks && S_ISREG(mode) &&
21 + if (S_ISREG(mode) && !has_symlinks &&
22 ce && S_ISLNK(ce->ce_mode))
23 return ce->ce_mode;
15 - if (!trust_executable_bit && S_ISREG(mode)) {
24 + if (S_ISREG(mode) && !trust_executable_bit) {
25 if (ce && S_ISREG(ce->ce_mode))
26 return ce->ce_mode;
27 return create_ce_mode(0666);