All of lore.kernel.org
 help / color / mirror / Atom feed
From: drona <dronarajgyawali@gmail.com>
To: git@vger.kernel.org
Cc: Dorna Raj Gyawali <dronarajgyawali@gmail.com>
Subject: [PATCH] Refactor 'trust_executable_bit' to repository-scoped setting
Date: Mon,  2 Mar 2026 00:44:49 +0545	[thread overview]
Message-ID: <20260301190017.53539-1-dronarajgyawali@gmail.com> (raw)

From: Dorna Raj Gyawali <dronarajgyawali@gmail.com>

Currently, 'trust_executable_bit' is a global variable in environment.c,
which controls how executable bits are interpreted when creating/updating
cache entries.

This patch moves 'trust_executable_bit' into 'struct repo_settings', making
it a repository-scoped configuration. All references in files have been updated to use
'the_repository->settings.trust_executable_bit'.

Why this is a good candidate:
- It's a self-contained global variable that only affects file mode logic.
- Low risk: changes only impact mode calculations and related apply/update
  operations.
- Makes Git codebase more maintainable and prepares for future multi-repo
  support.

- Manual sanity check with a test repo confirms executable bits behave correctly.

Signed-off-by: Dorna Raj Gyawali <dronarajgyawali@gmail.com>
---
 apply.c                |  4 ++--
 builtin/update-index.c |  2 +-
 diff-lib.c             | 10 +++++-----
 environment.c          |  3 +--
 environment.h          |  1 -
 read-cache.c           | 10 +++++-----
 read-cache.h           | 11 +++++++----
 repo-settings.h        |  6 +++++-
 8 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/apply.c b/apply.c
index d044c95d50..2bcb22a4bc 100644
--- a/apply.c
+++ b/apply.c
@@ -3838,8 +3838,8 @@ static int check_preimage(struct apply_state *state,
 		if (*ce && !(*ce)->ce_mode)
 			BUG("ce_mode == 0 for path '%s'", old_name);
 
-		if (trust_executable_bit || !S_ISREG(st->st_mode))
-			st_mode = ce_mode_from_stat(*ce, st->st_mode);
+		if (the_repository->settings.trust_executable_bit  || !S_ISREG(st->st_mode))
+			st_mode = ce_mode_from_stat(the_repository, *ce, st->st_mode);
 		else if (*ce)
 			st_mode = (*ce)->ce_mode;
 		else
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 8a5907767b..7917bd286f 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -293,7 +293,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
 	ce->ce_flags = create_ce_flags(0);
 	ce->ce_namelen = len;
 	fill_stat_cache_info(the_repository->index, ce, st);
-	ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
+	ce->ce_mode = ce_mode_from_stat(the_repository, old, st->st_mode);
 
 	if (index_path(the_repository->index, &ce->oid, path, st,
 		       info_only ? 0 : INDEX_WRITE_OBJECT)) {
diff --git a/diff-lib.c b/diff-lib.c
index ae91027a02..894358c8b0 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -160,7 +160,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
 
 			changed = check_removed(ce, &st);
 			if (!changed)
-				wt_mode = ce_mode_from_stat(ce, st.st_mode);
+				wt_mode = ce_mode_from_stat(the_repository, ce, st.st_mode);
 			else {
 				if (changed < 0) {
 					perror(ce->name);
@@ -193,7 +193,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
 					num_compare_stages++;
 					oidcpy(&dpath->parent[stage - 2].oid,
 					       &nce->oid);
-					dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode);
+					dpath->parent[stage-2].mode = ce_mode_from_stat(the_repository,nce, mode);
 					dpath->parent[stage-2].status =
 						DIFF_STATUS_MODIFIED;
 				}
@@ -262,7 +262,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
 				continue;
 			} else if (revs->diffopt.ita_invisible_in_index &&
 				   ce_intent_to_add(ce)) {
-				newmode = ce_mode_from_stat(ce, st.st_mode);
+				newmode = ce_mode_from_stat(the_repository, ce, st.st_mode);
 				diff_addremove(&revs->diffopt, '+', newmode,
 					       null_oid(the_hash_algo), 0, ce->name, 0);
 				continue;
@@ -270,7 +270,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
 
 			changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
 							    ce_option, &dirty_submodule);
-			newmode = ce_mode_from_stat(ce, st.st_mode);
+			newmode = ce_mode_from_stat(the_repository, ce, st.st_mode);
 		}
 
 		if (!changed && !dirty_submodule) {
@@ -338,7 +338,7 @@ static int get_stat_data(const struct cache_entry *ce,
 		changed = match_stat_with_submodule(diffopt, ce, &st,
 						    0, dirty_submodule);
 		if (changed) {
-			mode = ce_mode_from_stat(ce, st.st_mode);
+			mode = ce_mode_from_stat(the_repository, ce, st.st_mode);
 			oid = null_oid(the_hash_algo);
 		}
 	}
diff --git a/environment.c b/environment.c
index 0026eb2274..861ef084dc 100644
--- a/environment.c
+++ b/environment.c
@@ -41,7 +41,6 @@
 static int pack_compression_seen;
 static int zlib_compression_seen;
 
-int trust_executable_bit = 1;
 int trust_ctime = 1;
 int check_stat = 1;
 int has_symlinks = 1;
@@ -306,7 +305,7 @@ int git_default_core_config(const char *var, const char *value,
 {
 	/* This needs a better name */
 	if (!strcmp(var, "core.filemode")) {
-		trust_executable_bit = git_config_bool(var, value);
+		the_repository->settings.trust_executable_bit = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "core.trustctime")) {
diff --git a/environment.h b/environment.h
index 27f657af04..7f3437f369 100644
--- a/environment.h
+++ b/environment.h
@@ -144,7 +144,6 @@ int is_bare_repository(void);
 extern char *git_work_tree_cfg;
 
 /* Environment bits from configuration mechanism */
-extern int trust_executable_bit;
 extern int trust_ctime;
 extern int check_stat;
 extern int has_symlinks;
diff --git a/read-cache.c b/read-cache.c
index 0c07c3aef7..b1fcb9e1a0 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -201,13 +201,13 @@ void fill_stat_cache_info(struct index_state *istate, struct cache_entry *ce, st
 
 static unsigned int st_mode_from_ce(const struct cache_entry *ce)
 {
-	extern int trust_executable_bit, has_symlinks;
+	extern int has_symlinks;
 
 	switch (ce->ce_mode & S_IFMT) {
 	case S_IFLNK:
 		return has_symlinks ? S_IFLNK : (S_IFREG | 0644);
 	case S_IFREG:
-		return (ce->ce_mode & (trust_executable_bit ? 0755 : 0644)) | S_IFREG;
+		return (ce->ce_mode & (the_repository->settings.trust_executable_bit ? 0755 : 0644)) | S_IFREG;
 	case S_IFGITLINK:
 		return S_IFDIR | 0755;
 	case S_IFDIR:
@@ -317,7 +317,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
 		/* We consider only the owner x bit to be relevant for
 		 * "mode changes"
 		 */
-		if (trust_executable_bit &&
+		if (the_repository->settings.trust_executable_bit &&
 		    (0100 & (ce->ce_mode ^ st->st_mode)))
 			changed |= MODE_CHANGED;
 		break;
@@ -738,7 +738,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 		ce->ce_flags |= CE_INTENT_TO_ADD;
 
 
-	if (trust_executable_bit && has_symlinks) {
+	if (the_repository->settings.trust_executable_bit && has_symlinks) {
 		ce->ce_mode = create_ce_mode(st_mode);
 	} else {
 		/* If there is an existing entry, pick the mode bits and type
@@ -748,7 +748,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 		int pos = index_name_pos_also_unmerged(istate, path, namelen);
 
 		ent = (0 <= pos) ? istate->cache[pos] : NULL;
-		ce->ce_mode = ce_mode_from_stat(ent, st_mode);
+		ce->ce_mode = ce_mode_from_stat(the_repository, ent, st_mode);
 	}
 
 	/* When core.ignorecase=true, determine if a directory of the same name but differing
diff --git a/read-cache.h b/read-cache.h
index 043da1f1aa..4e88d476aa 100644
--- a/read-cache.h
+++ b/read-cache.h
@@ -4,15 +4,18 @@
 #include "read-cache-ll.h"
 #include "object.h"
 #include "pathspec.h"
+#include "repository.h"
 
-static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
-					     unsigned int mode)
+static inline unsigned int ce_mode_from_stat(
+						struct repository *repo,
+						const struct cache_entry *ce,
+					    unsigned int mode)
 {
-	extern int trust_executable_bit, has_symlinks;
+	extern int has_symlinks;
 	if (!has_symlinks && S_ISREG(mode) &&
 	    ce && S_ISLNK(ce->ce_mode))
 		return ce->ce_mode;
-	if (!trust_executable_bit && S_ISREG(mode)) {
+	if (!repo->settings.trust_executable_bit && S_ISREG(mode)) {
 		if (ce && S_ISREG(ce->ce_mode))
 			return ce->ce_mode;
 		return create_ce_mode(0666);
diff --git a/repo-settings.h b/repo-settings.h
index cad9c3f0cc..a12e763f4f 100644
--- a/repo-settings.h
+++ b/repo-settings.h
@@ -48,7 +48,10 @@ struct repo_settings {
 	 * replace_refs_enabled() for more details.
 	 */
 	int read_replace_refs;
-
+	
+	/* Whether to trust executable bit on filesystem (core.filemode) */
+	int trust_executable_bit;
+	
 	struct fsmonitor_settings *fsmonitor; /* lazily loaded */
 
 	int index_version;
@@ -74,6 +77,7 @@ struct repo_settings {
 #define REPO_SETTINGS_INIT { \
 	.shared_repository = -1, \
 	.index_version = -1, \
+	.trust_executable_bit = 1, \
 	.core_untracked_cache = UNTRACKED_CACHE_KEEP, \
 	.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \
 	.warn_ambiguous_refs = -1, \
-- 
2.43.0


             reply	other threads:[~2026-03-01 19:00 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-01 18:59 drona [this message]
2026-03-06 18:02 ` [PATCH] Refactor 'trust_executable_bit' to repository-scoped setting Tian Yuchen
2026-03-08 18:24 ` [PATCH] Make 'trust_executable_bit' repository-scoped drona
2026-03-08 18:34 ` [PATCH] [PATCH v2] " drona
2026-03-08 18:37 ` drona
     [not found]   ` <f03d40072ab106d1a0a7852718d42f56@purelymail.com>
2026-03-09  7:13     ` cat
2026-03-09 13:33       ` Dronaraj Gyawali
2026-03-09 16:23         ` Tian Yuchen
2026-03-09 22:03           ` Junio C Hamano
2026-03-09 15:07       ` Junio C Hamano
2026-03-09 17:51         ` Dronaraj Gyawali

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=20260301190017.53539-1-dronarajgyawali@gmail.com \
    --to=dronarajgyawali@gmail.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.