Git development
 help / color / mirror / Atom feed
* [PATCH v2 0/8] repo_config_values: migrate more globals
@ 2026-03-24 12:37 Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
                   ` (8 more replies)
  0 siblings, 9 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

Overview
========
This series continues the effort to migrate repository-specific global
variables into struct repo_config_values, further reducing global
state and improving repository isolation.

The previous series introduced the infrastructure for storing
repository-dependent configuration in repo_config_values. This series
extends that work by moving additional environment-related globals into
that struct and updating their call sites accordingly.

This helps avoid cross-repository interference when multiple
repositories are used within the same process, and continues preparing
Git for improved library usage and better encapsulation of repository
state.

Changes since v1:
- Dropped "Base series" section as the dependency has been merged.
- Fixed handling of pack_compression_level: removed use of a local copy and
  updated code to operate directly on cfg->pack_compression_level to avoid
  inconsistencies with option parsing.

Olamide Caleb Bello (8):
  environment: move "trust_ctime" into `struct repo_config_values`
  environment: move "check_stat" into `struct repo_config_values`
  environment: move `zlib_compression_level` into repo_config_values
  environment: move "pack_compression_level" into `struct
    repo_config_values`
  environment: move "precomposed_unicode" into `struct
    repo_config_values`
  env: move "core_sparse_checkout_cone" into `struct repo_config_values`
  env: put "sparse_expect_files_outside_of_patterns" in
    `repo_config_values`
  env: move "warn_on_object_refname_ambiguity" into `repo_config_values`

 builtin/cat-file.c        |  7 ++++---
 builtin/fast-import.c     |  8 +++++---
 builtin/index-pack.c      |  3 ++-
 builtin/mv.c              |  2 +-
 builtin/pack-objects.c    | 24 +++++++++++++----------
 builtin/sparse-checkout.c | 37 +++++++++++++++++++++---------------
 compat/precompose_utf8.c  | 20 +++++++++++++-------
 diff.c                    |  3 ++-
 dir.c                     |  3 ++-
 entry.c                   |  3 ++-
 environment.c             | 40 +++++++++++++++++++++------------------
 environment.h             | 19 ++++++++++---------
 http-push.c               |  3 ++-
 object-file.c             |  6 ++++--
 object-name.c             |  3 ++-
 revision.c                |  7 ++++---
 sparse-index.c            |  4 ++--
 statinfo.c                | 12 +++++++-----
 submodule.c               |  7 ++++---
 upload-pack.c             |  3 ++-
 20 files changed, 126 insertions(+), 88 deletions(-)

-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-04-14  8:52   ` Karthik Nayak
  2026-03-24 12:37 ` [PATCH v2 2/8] environment: move "check_stat" " Olamide Caleb Bello
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `core.trustctime` configuration is currently stored in the global
variable `trust_ctime`, which makes it shared across repository
instances in a single process.

Store it instead in `repo_config_values`, so the value is tied to the
repository from which it was read. This preserves existing behavior
while avoiding cross-repository state leakage and continues the effort
to reduce reliance on global configuration state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 environment.c | 4 ++--
 environment.h | 2 +-
 statinfo.c    | 6 ++++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/environment.c b/environment.c
index fc3ed8bb1c..0a9067729e 100644
--- a/environment.c
+++ b/environment.c
@@ -42,7 +42,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;
 int minimum_abbrev = 4, default_abbrev = -1;
@@ -309,7 +308,7 @@ int git_default_core_config(const char *var, const char *value,
 		return 0;
 	}
 	if (!strcmp(var, "core.trustctime")) {
-		trust_ctime = git_config_bool(var, value);
+		cfg->trust_ctime = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "core.checkstat")) {
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->attributes_file = NULL;
 	cfg->apply_sparse_checkout = 0;
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
+	cfg->trust_ctime = 1;
 }
diff --git a/environment.h b/environment.h
index 123a71cdc8..64d537686e 100644
--- a/environment.h
+++ b/environment.h
@@ -91,6 +91,7 @@ struct repo_config_values {
 	/* section "core" config values */
 	char *attributes_file;
 	int apply_sparse_checkout;
+	int trust_ctime;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -161,7 +162,6 @@ 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;
 extern int minimum_abbrev, default_abbrev;
diff --git a/statinfo.c b/statinfo.c
index 30a164b0e6..4fc12053f4 100644
--- a/statinfo.c
+++ b/statinfo.c
@@ -3,6 +3,7 @@
 #include "git-compat-util.h"
 #include "environment.h"
 #include "statinfo.h"
+#include "repository.h"
 
 /*
  * Munge st_size into an unsigned int.
@@ -63,17 +64,18 @@ void fake_lstat_data(const struct stat_data *sd, struct stat *st)
 int match_stat_data(const struct stat_data *sd, struct stat *st)
 {
 	int changed = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
+	if (cfg->trust_ctime && check_stat &&
 	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 #ifdef USE_NSEC
 	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
+	if (cfg->trust_ctime && check_stat &&
 	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
 		changed |= CTIME_CHANGED;
 #endif
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 2/8] environment: move "check_stat" into `struct repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-04-14  8:55   ` Karthik Nayak
  2026-03-24 12:37 ` [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values Olamide Caleb Bello
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `core.checkstat` configuration is currently stored in the global
variable `check_stat`, which makes it shared across repository
instances within a single process.

Store it instead in `repo_config_values` so the value is associated
with the repository from which it was read. This preserves existing
behavior while avoiding cross-repository state leakage and continues
the effort to reduce reliance on global configuration state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 entry.c       |  3 ++-
 environment.c |  6 +++---
 environment.h |  2 +-
 statinfo.c    | 10 +++++-----
 4 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/entry.c b/entry.c
index 7817aee362..c55e867d8a 100644
--- a/entry.c
+++ b/entry.c
@@ -443,7 +443,8 @@ static int check_path(const char *path, int len, struct stat *st, int skiplen)
 static void mark_colliding_entries(const struct checkout *state,
 				   struct cache_entry *ce, struct stat *st)
 {
-	int trust_ino = check_stat;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+	int trust_ino = cfg->check_stat;
 
 #if defined(GIT_WINDOWS_NATIVE) || defined(__CYGWIN__)
 	trust_ino = 0;
diff --git a/environment.c b/environment.c
index 0a9067729e..8542ac3141 100644
--- a/environment.c
+++ b/environment.c
@@ -42,7 +42,6 @@ static int pack_compression_seen;
 static int zlib_compression_seen;
 
 int trust_executable_bit = 1;
-int check_stat = 1;
 int has_symlinks = 1;
 int minimum_abbrev = 4, default_abbrev = -1;
 int ignore_case;
@@ -315,9 +314,9 @@ int git_default_core_config(const char *var, const char *value,
 		if (!value)
 			return config_error_nonbool(var);
 		if (!strcasecmp(value, "default"))
-			check_stat = 1;
+			cfg->check_stat = 1;
 		else if (!strcasecmp(value, "minimal"))
-			check_stat = 0;
+			cfg->check_stat = 0;
 		else
 			return error(_("invalid value for '%s': '%s'"),
 				     var, value);
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->apply_sparse_checkout = 0;
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
 	cfg->trust_ctime = 1;
+	cfg->check_stat = 1;
 }
diff --git a/environment.h b/environment.h
index 64d537686e..1d3e2e4f23 100644
--- a/environment.h
+++ b/environment.h
@@ -92,6 +92,7 @@ struct repo_config_values {
 	char *attributes_file;
 	int apply_sparse_checkout;
 	int trust_ctime;
+	int check_stat;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -162,7 +163,6 @@ extern char *git_work_tree_cfg;
 
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
-extern int check_stat;
 extern int has_symlinks;
 extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
diff --git a/statinfo.c b/statinfo.c
index 4fc12053f4..5e00af127d 100644
--- a/statinfo.c
+++ b/statinfo.c
@@ -68,19 +68,19 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
 
 	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (cfg->trust_ctime && check_stat &&
+	if (cfg->trust_ctime && cfg->check_stat &&
 	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 #ifdef USE_NSEC
-	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
+	if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
 		changed |= MTIME_CHANGED;
-	if (cfg->trust_ctime && check_stat &&
+	if (cfg->trust_ctime && cfg->check_stat &&
 	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
 		changed |= CTIME_CHANGED;
 #endif
 
-	if (check_stat) {
+	if (cfg->check_stat) {
 		if (sd->sd_uid != (unsigned int) st->st_uid ||
 			sd->sd_gid != (unsigned int) st->st_gid)
 			changed |= OWNER_CHANGED;
@@ -94,7 +94,7 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
 	 * clients will have different views of what "device"
 	 * the filesystem is on
 	 */
-	if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
+	if (cfg->check_stat && sd->sd_dev != (unsigned int) st->st_dev)
 			changed |= INODE_CHANGED;
 #endif
 
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 2/8] environment: move "check_stat" " Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-04-14  8:58   ` Karthik Nayak
  2026-03-24 12:37 ` [PATCH v2 4/8] environment: move "pack_compression_level" into `struct repo_config_values` Olamide Caleb Bello
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `zlib_compression_level` configuration is currently stored in the
global variable `zlib_compression_level`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values` so the value is associated
with the repository from which it was read. This preserves existing
behavior while avoiding cross-repository state leakage and continues
the effort to reduce reliance on global configuration state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/index-pack.c | 3 ++-
 diff.c               | 3 ++-
 environment.c        | 6 +++---
 environment.h        | 2 +-
 http-push.c          | 3 ++-
 object-file.c        | 3 ++-
 6 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index b67fb0256c..dd82eed76f 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1416,8 +1416,9 @@ static int write_compressed(struct hashfile *f, void *in, unsigned int size)
 	git_zstream stream;
 	int status;
 	unsigned char outbuf[4096];
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	stream.next_in = in;
 	stream.avail_in = size;
 
diff --git a/diff.c b/diff.c
index 501648a5c4..4bc0297873 100644
--- a/diff.c
+++ b/diff.c
@@ -3365,8 +3365,9 @@ static unsigned char *deflate_it(char *data,
 	int bound;
 	unsigned char *deflated;
 	git_zstream stream;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	bound = git_deflate_bound(&stream, size);
 	deflated = xmalloc(bound);
 	stream.next_out = deflated;
diff --git a/environment.c b/environment.c
index 8542ac3141..5b0e88b65c 100644
--- a/environment.c
+++ b/environment.c
@@ -52,7 +52,6 @@ char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
 char *apply_default_ignorewhitespace;
-int zlib_compression_level = Z_BEST_SPEED;
 int pack_compression_level = Z_DEFAULT_COMPRESSION;
 int fsync_object_files = -1;
 int use_fsync = -1;
@@ -377,7 +376,7 @@ int git_default_core_config(const char *var, const char *value,
 			level = Z_DEFAULT_COMPRESSION;
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad zlib compression level %d"), level);
-		zlib_compression_level = level;
+		cfg->zlib_compression_level = level;
 		zlib_compression_seen = 1;
 		return 0;
 	}
@@ -389,7 +388,7 @@ int git_default_core_config(const char *var, const char *value,
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad zlib compression level %d"), level);
 		if (!zlib_compression_seen)
-			zlib_compression_level = level;
+			cfg->zlib_compression_level = level;
 		if (!pack_compression_seen)
 			pack_compression_level = level;
 		return 0;
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
 	cfg->trust_ctime = 1;
 	cfg->check_stat = 1;
+	cfg->zlib_compression_level = Z_BEST_SPEED;
 }
diff --git a/environment.h b/environment.h
index 1d3e2e4f23..93201620af 100644
--- a/environment.h
+++ b/environment.h
@@ -93,6 +93,7 @@ struct repo_config_values {
 	int apply_sparse_checkout;
 	int trust_ctime;
 	int check_stat;
+	int zlib_compression_level;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -170,7 +171,6 @@ extern int assume_unchanged;
 extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
-extern int zlib_compression_level;
 extern int pack_compression_level;
 extern unsigned long pack_size_limit_cfg;
 
diff --git a/http-push.c b/http-push.c
index 9ae6062198..c6bf9ff387 100644
--- a/http-push.c
+++ b/http-push.c
@@ -369,13 +369,14 @@ static void start_put(struct transfer_request *request)
 	int hdrlen;
 	ssize_t size;
 	git_zstream stream;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	unpacked = odb_read_object(the_repository->objects, &request->obj->oid,
 				   &type, &len);
 	hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
 
 	/* Set it up */
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	size = git_deflate_bound(&stream, len + hdrlen);
 	strbuf_grow(&request->buffer.buf, size);
 	request->buffer.posn = 0;
diff --git a/object-file.c b/object-file.c
index 3094140055..8b719a915c 100644
--- a/object-file.c
+++ b/object-file.c
@@ -891,6 +891,7 @@ static int start_loose_object_common(struct odb_source *source,
 	const struct git_hash_algo *algo = source->odb->repo->hash_algo;
 	const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
 	int fd;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	fd = create_tmpfile(source->odb->repo, tmp_file, filename);
 	if (fd < 0) {
@@ -906,7 +907,7 @@ static int start_loose_object_common(struct odb_source *source,
 	}
 
 	/*  Setup zlib stream for compression */
-	git_deflate_init(stream, zlib_compression_level);
+	git_deflate_init(stream, cfg->zlib_compression_level);
 	stream->next_out = buf;
 	stream->avail_out = buflen;
 	algo->init_fn(c);
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 4/8] environment: move "pack_compression_level" into `struct repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (2 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `pack_compression_level` configuration is currently stored in the
global variable `pack_compression_level`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values` so the value is associated
with the repository from which it was read. This preserves existing
behavior while avoiding cross-repository state leakage and is another
step toward eliminating repository-dependent global state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/fast-import.c  |  8 +++++---
 builtin/pack-objects.c | 17 ++++++++++-------
 environment.c          |  8 +++++---
 environment.h          |  2 +-
 object-file.c          |  3 ++-
 5 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index b8a7757cfd..6475cdae85 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -963,6 +963,7 @@ static int store_object(
 	unsigned long hdrlen, deltalen;
 	struct git_hash_ctx c;
 	git_zstream s;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	hdrlen = format_object_header((char *)hdr, sizeof(hdr), type,
 				      dat->len);
@@ -1001,7 +1002,7 @@ static int store_object(
 	} else
 		delta = NULL;
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 	if (delta) {
 		s.next_in = delta;
 		s.avail_in = deltalen;
@@ -1028,7 +1029,7 @@ static int store_object(
 		if (delta) {
 			FREE_AND_NULL(delta);
 
-			git_deflate_init(&s, pack_compression_level);
+			git_deflate_init(&s, cfg->pack_compression_level);
 			s.next_in = (void *)dat->buf;
 			s.avail_in = dat->len;
 			s.avail_out = git_deflate_bound(&s, s.avail_in);
@@ -1111,6 +1112,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 	struct git_hash_ctx c;
 	git_zstream s;
 	struct hashfile_checkpoint checkpoint;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int status = Z_OK;
 
 	/* Determine if we should auto-checkpoint. */
@@ -1130,7 +1132,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 
 	crc32_begin(pack_file);
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 
 	hdrlen = encode_in_pack_object_header(out_buf, out_sz, OBJ_BLOB, len);
 
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index c1ee4d5ed7..7c5bc96916 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -383,8 +383,9 @@ static unsigned long do_compress(void **pptr, unsigned long size)
 	git_zstream stream;
 	void *in, *out;
 	unsigned long maxsize;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, pack_compression_level);
+	git_deflate_init(&stream, cfg->pack_compression_level);
 	maxsize = git_deflate_bound(&stream, size);
 
 	in = *pptr;
@@ -410,8 +411,9 @@ static unsigned long write_large_blob_data(struct odb_read_stream *st, struct ha
 	unsigned char ibuf[1024 * 16];
 	unsigned char obuf[1024 * 16];
 	unsigned long olen = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, pack_compression_level);
+	git_deflate_init(&stream, cfg->pack_compression_level);
 
 	for (;;) {
 		ssize_t readlen;
@@ -4868,6 +4870,7 @@ int cmd_pack_objects(int argc,
 	struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
 	struct list_objects_filter_options filter_options =
 		LIST_OBJECTS_FILTER_INIT;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	struct option pack_objects_options[] = {
 		OPT_CALLBACK_F('q', "quiet", &progress, NULL,
@@ -4951,7 +4954,7 @@ int cmd_pack_objects(int argc,
 			 N_("ignore packs that have companion .keep file")),
 		OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
 				N_("ignore this pack")),
-		OPT_INTEGER(0, "compression", &pack_compression_level,
+		OPT_INTEGER(0, "compression", &cfg->pack_compression_level,
 			    N_("pack compression level")),
 		OPT_BOOL(0, "keep-true-parents", &grafts_keep_true_parents,
 			 N_("do not hide commits by grafts")),
@@ -5110,10 +5113,10 @@ int cmd_pack_objects(int argc,
 
 	if (!reuse_object)
 		reuse_delta = 0;
-	if (pack_compression_level == -1)
-		pack_compression_level = Z_DEFAULT_COMPRESSION;
-	else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)
-		die(_("bad pack compression level %d"), pack_compression_level);
+	if (cfg->pack_compression_level == -1)
+		cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
+	else if (cfg->pack_compression_level < 0 || cfg->pack_compression_level > Z_BEST_COMPRESSION)
+		die(_("bad pack compression level %d"), cfg->pack_compression_level);
 
 	if (!delta_search_threads)	/* --threads=0 means autodetect */
 		delta_search_threads = online_cpus();
diff --git a/environment.c b/environment.c
index 5b0e88b65c..d0d3a4b7d2 100644
--- a/environment.c
+++ b/environment.c
@@ -52,7 +52,6 @@ char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
 char *apply_default_ignorewhitespace;
-int pack_compression_level = Z_DEFAULT_COMPRESSION;
 int fsync_object_files = -1;
 int use_fsync = -1;
 enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
@@ -390,7 +389,7 @@ int git_default_core_config(const char *var, const char *value,
 		if (!zlib_compression_seen)
 			cfg->zlib_compression_level = level;
 		if (!pack_compression_seen)
-			pack_compression_level = level;
+			cfg->pack_compression_level = level;
 		return 0;
 	}
 
@@ -662,6 +661,8 @@ static int git_default_attr_config(const char *var, const char *value)
 int git_default_config(const char *var, const char *value,
 		       const struct config_context *ctx, void *cb)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (starts_with(var, "core."))
 		return git_default_core_config(var, value, ctx, cb);
 
@@ -701,7 +702,7 @@ int git_default_config(const char *var, const char *value,
 			level = Z_DEFAULT_COMPRESSION;
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad pack compression level %d"), level);
-		pack_compression_level = level;
+		cfg->pack_compression_level = level;
 		pack_compression_seen = 1;
 		return 0;
 	}
@@ -721,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->trust_ctime = 1;
 	cfg->check_stat = 1;
 	cfg->zlib_compression_level = Z_BEST_SPEED;
+	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 }
diff --git a/environment.h b/environment.h
index 93201620af..514576b67a 100644
--- a/environment.h
+++ b/environment.h
@@ -94,6 +94,7 @@ struct repo_config_values {
 	int trust_ctime;
 	int check_stat;
 	int zlib_compression_level;
+	int pack_compression_level;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -171,7 +172,6 @@ extern int assume_unchanged;
 extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
-extern int pack_compression_level;
 extern unsigned long pack_size_limit_cfg;
 
 extern int precomposed_unicode;
diff --git a/object-file.c b/object-file.c
index 8b719a915c..87179fc667 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1420,8 +1420,9 @@ static int stream_blob_to_pack(struct transaction_packfile *state,
 	int status = Z_OK;
 	int write_object = (flags & INDEX_WRITE_OBJECT);
 	off_t offset = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 
 	hdrlen = encode_in_pack_object_header(obuf, sizeof(obuf), OBJ_BLOB, size);
 	s.next_out = obuf + hdrlen;
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 5/8] environment: move "precomposed_unicode" into `struct repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (3 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 4/8] environment: move "pack_compression_level" into `struct repo_config_values` Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-04-14  9:07   ` Karthik Nayak
  2026-03-24 12:37 ` [PATCH v2 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `core.precomposeunicode` configuration is currently stored in the
global variable `precomposed_unicode`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values` so the value is associated
with the repository from which it was read. This preserves existing
behavior while avoiding cross-repository state leakage and is another
step toward eliminating repository-dependent global state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 compat/precompose_utf8.c | 20 +++++++++++++-------
 environment.c            |  4 ++--
 environment.h            |  2 +-
 upload-pack.c            |  3 ++-
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 43b3be0114..0e94dbd862 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -48,16 +48,18 @@ void probe_utf8_pathname_composition(void)
 	static const char *auml_nfc = "\xc3\xa4";
 	static const char *auml_nfd = "\x61\xcc\x88";
 	int output_fd;
-	if (precomposed_unicode != -1)
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
+	if (cfg->precomposed_unicode != -1)
 		return; /* We found it defined in the global config, respect it */
 	repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
 	output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600);
 	if (output_fd >= 0) {
 		close(output_fd);
 		repo_git_path_replace(the_repository, &path, "%s", auml_nfd);
-		precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
+		cfg->precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
 		repo_config_set(the_repository, "core.precomposeunicode",
-				precomposed_unicode ? "true" : "false");
+				cfg->precomposed_unicode ? "true" : "false");
 		repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
 		if (unlink(path.buf))
 			die_errno(_("failed to unlink '%s'"), path.buf);
@@ -69,14 +71,16 @@ const char *precompose_string_if_needed(const char *in)
 {
 	size_t inlen;
 	size_t outlen;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (!in)
 		return NULL;
 	if (has_non_ascii(in, (size_t)-1, &inlen)) {
 		iconv_t ic_prec;
 		char *out;
-		if (precomposed_unicode < 0)
-			repo_config_get_bool(the_repository, "core.precomposeunicode", &precomposed_unicode);
-		if (precomposed_unicode != 1)
+		if (cfg->precomposed_unicode < 0)
+			repo_config_get_bool(the_repository, "core.precomposeunicode", &cfg->precomposed_unicode);
+		if (cfg->precomposed_unicode != 1)
 			return in;
 		ic_prec = iconv_open(repo_encoding, path_encoding);
 		if (ic_prec == (iconv_t) -1)
@@ -130,7 +134,9 @@ PREC_DIR *precompose_utf8_opendir(const char *dirname)
 
 struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	struct dirent *res;
+
 	res = readdir(prec_dir->dirp);
 	if (res) {
 		size_t namelenz = strlen(res->d_name) + 1; /* \0 */
@@ -149,7 +155,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
 		prec_dir->dirent_nfc->d_ino  = res->d_ino;
 		prec_dir->dirent_nfc->d_type = res->d_type;
 
-		if ((precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
+		if ((cfg->precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
 			if (prec_dir->ic_precompose == (iconv_t)-1) {
 				die("iconv_open(%s,%s) failed, but needed:\n"
 						"    precomposed unicode is not supported.\n"
diff --git a/environment.c b/environment.c
index d0d3a4b7d2..739b647ebe 100644
--- a/environment.c
+++ b/environment.c
@@ -72,7 +72,6 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
 int core_sparse_checkout_cone;
 int sparse_expect_files_outside_of_patterns;
-int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 unsigned long pack_size_limit_cfg;
 
 #ifndef PROTECT_HFS_DEFAULT
@@ -532,7 +531,7 @@ int git_default_core_config(const char *var, const char *value,
 	}
 
 	if (!strcmp(var, "core.precomposeunicode")) {
-		precomposed_unicode = git_config_bool(var, value);
+		cfg->precomposed_unicode = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->check_stat = 1;
 	cfg->zlib_compression_level = Z_BEST_SPEED;
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
+	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 }
diff --git a/environment.h b/environment.h
index 514576b67a..508cb1afbc 100644
--- a/environment.h
+++ b/environment.h
@@ -95,6 +95,7 @@ struct repo_config_values {
 	int check_stat;
 	int zlib_compression_level;
 	int pack_compression_level;
+	int precomposed_unicode;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -174,7 +175,6 @@ extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
 extern unsigned long pack_size_limit_cfg;
 
-extern int precomposed_unicode;
 extern int protect_hfs;
 extern int protect_ntfs;
 
diff --git a/upload-pack.c b/upload-pack.c
index 88dac1b65c..afa3ef7655 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1288,6 +1288,7 @@ static int upload_pack_config(const char *var, const char *value,
 			      void *cb_data)
 {
 	struct upload_pack_data *data = cb_data;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
 		if (git_config_bool(var, value))
@@ -1318,7 +1319,7 @@ static int upload_pack_config(const char *var, const char *value,
 		if (value)
 			data->allow_packfile_uris = 1;
 	} else if (!strcmp("core.precomposeunicode", var)) {
-		precomposed_unicode = git_config_bool(var, value);
+		cfg->precomposed_unicode = git_config_bool(var, value);
 	} else if (!strcmp("transfer.advertisesid", var)) {
 		data->advertise_sid = git_config_bool(var, value);
 	}
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 6/8] env: move "core_sparse_checkout_cone" into `struct repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (4 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 7/8] env: put "sparse_expect_files_outside_of_patterns" in `repo_config_values` Olamide Caleb Bello
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `core_sparse_checkout_cone` variable was previously a global integer,
uninitialized by default. Storing repository-dependent configuration in
globals can lead to cross-repository state leakage.

Move it into `repo_config_values` and initialize it to 0 by default.
This ensures predictable behavior for repositories that do not set
this configuration while preserving existing semantics.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/mv.c              |  2 +-
 builtin/sparse-checkout.c | 37 ++++++++++++++++++++++---------------
 dir.c                     |  3 ++-
 environment.c             |  4 ++--
 environment.h             |  2 +-
 sparse-index.c            |  2 +-
 6 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/builtin/mv.c b/builtin/mv.c
index 2215d34e31..ef3a326c90 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -574,7 +574,7 @@ int cmd_mv(int argc,
 
 		if (ignore_sparse &&
 		    cfg->apply_sparse_checkout &&
-		    core_sparse_checkout_cone) {
+		    cfg->core_sparse_checkout_cone) {
 			/*
 			 * NEEDSWORK: we are *not* paying attention to
 			 * "out-to-out" move (<source> is out-of-cone and
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index f4aa405da9..92d017b81f 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -73,7 +73,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
 
 	memset(&pl, 0, sizeof(pl));
 
-	pl.use_cone_patterns = core_sparse_checkout_cone;
+	pl.use_cone_patterns = cfg->core_sparse_checkout_cone;
 
 	sparse_filename = get_sparse_checkout_filename();
 	res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0);
@@ -334,6 +334,7 @@ static int write_patterns_and_update(struct repository *repo,
 	FILE *fp;
 	struct lock_file lk = LOCK_INIT;
 	int result;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	sparse_filename = get_sparse_checkout_filename();
 
@@ -353,7 +354,7 @@ static int write_patterns_and_update(struct repository *repo,
 	if (!fp)
 		die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk));
 
-	if (core_sparse_checkout_cone)
+	if (cfg->core_sparse_checkout_cone)
 		write_cone_to_file(fp, pl);
 	else
 		write_patterns_to_file(fp, pl);
@@ -402,15 +403,15 @@ static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
 
 	/* If not specified, use previous definition of cone mode */
 	if (*cone_mode == -1 && cfg->apply_sparse_checkout)
-		*cone_mode = core_sparse_checkout_cone;
+		*cone_mode = cfg->core_sparse_checkout_cone;
 
 	/* Set cone/non-cone mode appropriately */
 	cfg->apply_sparse_checkout = 1;
 	if (*cone_mode == 1 || *cone_mode == -1) {
-		core_sparse_checkout_cone = 1;
+		cfg->core_sparse_checkout_cone = 1;
 		return MODE_CONE_PATTERNS;
 	}
-	core_sparse_checkout_cone = 0;
+	cfg->core_sparse_checkout_cone = 0;
 	return MODE_ALL_PATTERNS;
 }
 
@@ -577,7 +578,9 @@ static void add_patterns_from_input(struct pattern_list *pl,
 				    FILE *file)
 {
 	int i;
-	if (core_sparse_checkout_cone) {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
+	if (cfg->core_sparse_checkout_cone) {
 		struct strbuf line = STRBUF_INIT;
 
 		hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);
@@ -636,13 +639,14 @@ static void add_patterns_cone_mode(int argc, const char **argv,
 	struct pattern_entry *pe;
 	struct hashmap_iter iter;
 	struct pattern_list existing;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char *sparse_filename = get_sparse_checkout_filename();
 
 	add_patterns_from_input(pl, argc, argv,
 				use_stdin ? stdin : NULL);
 
 	memset(&existing, 0, sizeof(existing));
-	existing.use_cone_patterns = core_sparse_checkout_cone;
+	existing.use_cone_patterns = cfg->core_sparse_checkout_cone;
 
 	if (add_patterns_from_file_to_list(sparse_filename, "", 0,
 					   &existing, NULL, 0))
@@ -690,7 +694,7 @@ static int modify_pattern_list(struct repository *repo,
 
 	switch (m) {
 	case ADD:
-		if (core_sparse_checkout_cone)
+		if (cfg->core_sparse_checkout_cone)
 			add_patterns_cone_mode(args->nr, args->v, pl, use_stdin);
 		else
 			add_patterns_literal(args->nr, args->v, pl, use_stdin);
@@ -723,11 +727,12 @@ static void sanitize_paths(struct repository *repo,
 			   const char *prefix, int skip_checks)
 {
 	int i;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!args->nr)
 		return;
 
-	if (prefix && *prefix && core_sparse_checkout_cone) {
+	if (prefix && *prefix && cfg->core_sparse_checkout_cone) {
 		/*
 		 * The args are not pathspecs, so unfortunately we
 		 * cannot imitate how cmd_add() uses parse_pathspec().
@@ -744,10 +749,10 @@ static void sanitize_paths(struct repository *repo,
 	if (skip_checks)
 		return;
 
-	if (prefix && *prefix && !core_sparse_checkout_cone)
+	if (prefix && *prefix && !cfg->core_sparse_checkout_cone)
 		die(_("please run from the toplevel directory in non-cone mode"));
 
-	if (core_sparse_checkout_cone) {
+	if (cfg->core_sparse_checkout_cone) {
 		for (i = 0; i < args->nr; i++) {
 			if (args->v[i][0] == '/')
 				die(_("specify directories rather than patterns (no leading slash)"));
@@ -769,7 +774,7 @@ static void sanitize_paths(struct repository *repo,
 		if (S_ISSPARSEDIR(ce->ce_mode))
 			continue;
 
-		if (core_sparse_checkout_cone)
+		if (cfg->core_sparse_checkout_cone)
 			die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), args->v[i]);
 		else
 			warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), args->v[i]);
@@ -836,6 +841,7 @@ static struct sparse_checkout_set_opts {
 static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 			       struct repository *repo)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int default_patterns_nr = 2;
 	const char *default_patterns[] = {"/*", "!/*/", NULL};
 
@@ -873,7 +879,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 	 * non-cone mode, if nothing is specified, manually select just the
 	 * top-level directory (much as 'init' would do).
 	 */
-	if (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {
+	if (!cfg->core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {
 		for (int i = 0; i < default_patterns_nr; i++)
 			strvec_push(&patterns, default_patterns[i]);
 	} else {
@@ -977,7 +983,7 @@ static int sparse_checkout_clean(int argc, const char **argv,
 	setup_work_tree();
 	if (!cfg->apply_sparse_checkout)
 		die(_("must be in a sparse-checkout to clean directories"));
-	if (!core_sparse_checkout_cone)
+	if (!cfg->core_sparse_checkout_cone)
 		die(_("must be in a cone-mode sparse-checkout to clean directories"));
 
 	argc = parse_options(argc, argv, prefix,
@@ -1141,6 +1147,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
 	FILE *fp;
 	int ret;
 	struct pattern_list pl = {0};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char *sparse_filename;
 	check_rules_opts.cone_mode = -1;
 
@@ -1152,7 +1159,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
 		check_rules_opts.cone_mode = 1;
 
 	update_cone_mode(&check_rules_opts.cone_mode);
-	pl.use_cone_patterns = core_sparse_checkout_cone;
+	pl.use_cone_patterns = cfg->core_sparse_checkout_cone;
 	if (check_rules_opts.rules_file) {
 		fp = xfopen(check_rules_opts.rules_file, "r");
 		add_patterns_from_input(&pl, argc, argv, fp);
diff --git a/dir.c b/dir.c
index 026d8516a9..2744b3e5ca 100644
--- a/dir.c
+++ b/dir.c
@@ -3508,8 +3508,9 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)
 {
 	int res;
 	char *sparse_filename = get_sparse_checkout_filename();
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	pl->use_cone_patterns = core_sparse_checkout_cone;
+	pl->use_cone_patterns = cfg->core_sparse_checkout_cone;
 	res = add_patterns_from_file_to_list(sparse_filename, "", 0, pl, NULL, 0);
 
 	free(sparse_filename);
diff --git a/environment.c b/environment.c
index 739b647ebe..b0e873e9f5 100644
--- a/environment.c
+++ b/environment.c
@@ -70,7 +70,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 #endif
 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
-int core_sparse_checkout_cone;
 int sparse_expect_files_outside_of_patterns;
 unsigned long pack_size_limit_cfg;
 
@@ -526,7 +525,7 @@ int git_default_core_config(const char *var, const char *value,
 	}
 
 	if (!strcmp(var, "core.sparsecheckoutcone")) {
-		core_sparse_checkout_cone = git_config_bool(var, value);
+		cfg->core_sparse_checkout_cone = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->zlib_compression_level = Z_BEST_SPEED;
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
+	cfg->core_sparse_checkout_cone = 0;
 }
diff --git a/environment.h b/environment.h
index 508cb1afbc..befad9a388 100644
--- a/environment.h
+++ b/environment.h
@@ -96,6 +96,7 @@ struct repo_config_values {
 	int zlib_compression_level;
 	int pack_compression_level;
 	int precomposed_unicode;
+	int core_sparse_checkout_cone;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -178,7 +179,6 @@ extern unsigned long pack_size_limit_cfg;
 extern int protect_hfs;
 extern int protect_ntfs;
 
-extern int core_sparse_checkout_cone;
 extern int sparse_expect_files_outside_of_patterns;
 
 enum rebase_setup_type {
diff --git a/sparse-index.c b/sparse-index.c
index 13629c075d..53cb8d64fc 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -154,7 +154,7 @@ int is_sparse_index_allowed(struct index_state *istate, int flags)
 {
 	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)
+	if (!cfg->apply_sparse_checkout || !cfg->core_sparse_checkout_cone)
 		return 0;
 
 	if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 7/8] env: put "sparse_expect_files_outside_of_patterns" in `repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (5 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-03-24 12:37 ` [PATCH v2 8/8] env: move "warn_on_object_refname_ambiguity" into `repo_config_values` Olamide Caleb Bello
  2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `sparse_expect_files_outside_of_patterns` variable was previously
a global variable, which makes it shared across repository
instances within a single process.

Move it into `repo_config_values`, this makes the  value  tied to the
repository from which it was read. This preserves existing behavior
while avoiding cross-repository state leakage and is another step
toward eliminating repository-dependent global state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 environment.c  | 6 ++++--
 environment.h  | 5 +++--
 sparse-index.c | 2 +-
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/environment.c b/environment.c
index b0e873e9f5..57587ede56 100644
--- a/environment.c
+++ b/environment.c
@@ -70,7 +70,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 #endif
 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
-int sparse_expect_files_outside_of_patterns;
 unsigned long pack_size_limit_cfg;
 
 #ifndef PROTECT_HFS_DEFAULT
@@ -550,8 +549,10 @@ int git_default_core_config(const char *var, const char *value,
 
 static int git_default_sparse_config(const char *var, const char *value)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (!strcmp(var, "sparse.expectfilesoutsideofpatterns")) {
-		sparse_expect_files_outside_of_patterns = git_config_bool(var, value);
+		cfg->sparse_expect_files_outside_of_patterns = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +724,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 	cfg->core_sparse_checkout_cone = 0;
+	cfg->sparse_expect_files_outside_of_patterns = 0;
 }
diff --git a/environment.h b/environment.h
index befad9a388..609cdaa07f 100644
--- a/environment.h
+++ b/environment.h
@@ -98,6 +98,9 @@ struct repo_config_values {
 	int precomposed_unicode;
 	int core_sparse_checkout_cone;
 
+	/* section "sparse" config values */
+	int sparse_expect_files_outside_of_patterns;
+
 	/* section "branch" config values */
 	enum branch_track branch_track;
 };
@@ -179,8 +182,6 @@ extern unsigned long pack_size_limit_cfg;
 extern int protect_hfs;
 extern int protect_ntfs;
 
-extern int sparse_expect_files_outside_of_patterns;
-
 enum rebase_setup_type {
 	AUTOREBASE_NEVER = 0,
 	AUTOREBASE_LOCAL,
diff --git a/sparse-index.c b/sparse-index.c
index 53cb8d64fc..1ed769b78d 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -675,7 +675,7 @@ void clear_skip_worktree_from_present_files(struct index_state *istate)
 	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!cfg->apply_sparse_checkout ||
-	    sparse_expect_files_outside_of_patterns)
+	    cfg->sparse_expect_files_outside_of_patterns)
 		return;
 
 	if (clear_skip_worktree_from_present_files_sparse(istate)) {
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v2 8/8] env: move "warn_on_object_refname_ambiguity" into `repo_config_values`
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (6 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 7/8] env: put "sparse_expect_files_outside_of_patterns" in `repo_config_values` Olamide Caleb Bello
@ 2026-03-24 12:37 ` Olamide Caleb Bello
  2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-03-24 12:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, karthik.188, Olamide Caleb Bello

The `warn_on_object_refname_ambiguity` variable was previously a global
integer, which makes it shared across repository instances in a single
process.

Move it into `repo_config_values` so the value is associated with the
repository from which it was read. This preserves existing behavior
while avoiding cross-repository state leakage and is another step
toward eliminating repository-dependent global state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/cat-file.c     | 7 ++++---
 builtin/pack-objects.c | 7 ++++---
 environment.c          | 2 +-
 environment.h          | 2 +-
 object-name.c          | 3 ++-
 revision.c             | 7 ++++---
 submodule.c            | 7 ++++---
 7 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index da059d0e26..32f60f2f64 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -897,6 +897,7 @@ static int batch_objects(struct batch_options *opt)
 	struct strbuf input = STRBUF_INIT;
 	struct strbuf output = STRBUF_INIT;
 	struct expand_data data = EXPAND_DATA_INIT;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int save_warning;
 	int retval = 0;
 
@@ -969,8 +970,8 @@ static int batch_objects(struct batch_options *opt)
 	 * warn) ends up dwarfing the actual cost of the object lookups
 	 * themselves. We can work around it by just turning off the warning.
 	 */
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	if (opt->batch_mode == BATCH_MODE_QUEUE_AND_DISPATCH) {
 		batch_objects_command(opt, &output, &data);
@@ -998,7 +999,7 @@ static int batch_objects(struct batch_options *opt)
  cleanup:
 	strbuf_release(&input);
 	strbuf_release(&output);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 	return retval;
 }
 
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 7c5bc96916..b972449ca1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4653,6 +4653,7 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 	struct setup_revision_opt s_r_opt = {
 		.allow_exclude_promisor_objects = 1,
 	};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char line[1000];
 	int flags = 0;
 	int save_warning;
@@ -4663,8 +4664,8 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 	/* make sure shallows are read */
 	is_repository_shallow(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	while (fgets(line, sizeof(line), stdin) != NULL) {
 		int len = strlen(line);
@@ -4692,7 +4693,7 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 			die(_("bad revision '%s'"), line);
 	}
 
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 
 	if (use_bitmap_index && !get_object_list_from_bitmap(revs))
 		return;
diff --git a/environment.c b/environment.c
index 57587ede56..ba2c60103f 100644
--- a/environment.c
+++ b/environment.c
@@ -47,7 +47,6 @@ int minimum_abbrev = 4, default_abbrev = -1;
 int ignore_case;
 int assume_unchanged;
 int is_bare_repository_cfg = -1; /* unspecified */
-int warn_on_object_refname_ambiguity = 1;
 char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
@@ -725,4 +724,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 	cfg->core_sparse_checkout_cone = 0;
 	cfg->sparse_expect_files_outside_of_patterns = 0;
+	cfg->warn_on_object_refname_ambiguity = 1;
 }
diff --git a/environment.h b/environment.h
index 609cdaa07f..1ff0a7ba8b 100644
--- a/environment.h
+++ b/environment.h
@@ -97,6 +97,7 @@ struct repo_config_values {
 	int pack_compression_level;
 	int precomposed_unicode;
 	int core_sparse_checkout_cone;
+	int warn_on_object_refname_ambiguity;
 
 	/* section "sparse" config values */
 	int sparse_expect_files_outside_of_patterns;
@@ -174,7 +175,6 @@ extern int has_symlinks;
 extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
 extern int assume_unchanged;
-extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
 extern unsigned long pack_size_limit_cfg;
diff --git a/object-name.c b/object-name.c
index 7b14c3bf9b..ddd863d293 100644
--- a/object-name.c
+++ b/object-name.c
@@ -969,11 +969,12 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
 	int refs_found = 0;
 	int at, reflog_len, nth_prior = 0;
 	int fatal = !(flags & GET_OID_QUIETLY);
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
 		if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) &&
 		    repo_settings_get_warn_ambiguous_refs(r) &&
-		    warn_on_object_refname_ambiguity) {
+		    cfg->warn_on_object_refname_ambiguity) {
 			refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
 			if (refs_found > 0) {
 				warning(warn_msg, len, str);
diff --git a/revision.c b/revision.c
index 402eb1b029..cff821132b 100644
--- a/revision.c
+++ b/revision.c
@@ -2904,9 +2904,10 @@ static void read_revisions_from_stdin(struct rev_info *revs,
 	int seen_end_of_options = 0;
 	int save_warning;
 	int flags = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	strbuf_init(&sb, 1000);
 	while (strbuf_getline(&sb, stdin) != EOF) {
@@ -2940,7 +2941,7 @@ static void read_revisions_from_stdin(struct rev_info *revs,
 		read_pathspec_from_stdin(&sb, prune);
 
 	strbuf_release(&sb);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 }
 
 static void NORETURN diagnose_missing_default(const char *def)
diff --git a/submodule.c b/submodule.c
index 508938e4da..486b41011c 100644
--- a/submodule.c
+++ b/submodule.c
@@ -898,12 +898,13 @@ static void collect_changed_submodules(struct repository *r,
 	struct setup_revision_opt s_r_opt = {
 		.assume_dashdash = 1,
 	};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 	repo_init_revisions(r, &rev, NULL);
 	setup_revisions_from_strvec(argv, &rev, &s_r_opt);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 	if (prepare_revision_walk(&rev))
 		die(_("revision walk setup failed"));
 
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-03-24 12:37 ` [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
@ 2026-04-14  8:52   ` Karthik Nayak
  2026-04-14  9:35     ` Phillip Wood
  0 siblings, 1 reply; 44+ messages in thread
From: Karthik Nayak @ 2026-04-14  8:52 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 2301 bytes --]

Olamide Caleb Bello <belkid98@gmail.com> writes:

> The `core.trustctime` configuration is currently stored in the global
> variable `trust_ctime`, which makes it shared across repository
> instances in a single process.
>
> Store it instead in `repo_config_values`, so the value is tied to the
> repository from which it was read. This preserves existing behavior
> while avoiding cross-repository state leakage and continues the effort
> to reduce reliance on global configuration state.
>
> Update all references to use repo_config_values().
>

Nit: I was hoping you'd also shed light on why this can go into
`repo_config_values()`. Does it need to be eagerly parsed? If so, why?

> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
> ---
>  environment.c | 4 ++--
>  environment.h | 2 +-
>  statinfo.c    | 6 ++++--
>  3 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/environment.c b/environment.c
> index fc3ed8bb1c..0a9067729e 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -42,7 +42,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;
>  int minimum_abbrev = 4, default_abbrev = -1;
> @@ -309,7 +308,7 @@ int git_default_core_config(const char *var, const char *value,
>  		return 0;
>  	}
>  	if (!strcmp(var, "core.trustctime")) {
> -		trust_ctime = git_config_bool(var, value);
> +		cfg->trust_ctime = git_config_bool(var, value);
>  		return 0;
>  	}
>  	if (!strcmp(var, "core.checkstat")) {
> @@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
>  	cfg->attributes_file = NULL;
>  	cfg->apply_sparse_checkout = 0;
>  	cfg->branch_track = BRANCH_TRACK_REMOTE;
> +	cfg->trust_ctime = 1;
>  }
> diff --git a/environment.h b/environment.h
> index 123a71cdc8..64d537686e 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -91,6 +91,7 @@ struct repo_config_values {
>  	/* section "core" config values */
>  	char *attributes_file;
>  	int apply_sparse_checkout;
> +	int trust_ctime;
>

Since we parse it as a bool, perhaps we can make the variable to be of
type bool?

[snip]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 2/8] environment: move "check_stat" into `struct repo_config_values`
  2026-03-24 12:37 ` [PATCH v2 2/8] environment: move "check_stat" " Olamide Caleb Bello
@ 2026-04-14  8:55   ` Karthik Nayak
  0 siblings, 0 replies; 44+ messages in thread
From: Karthik Nayak @ 2026-04-14  8:55 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 609 bytes --]

Olamide Caleb Bello <belkid98@gmail.com> writes:

> The `core.checkstat` configuration is currently stored in the global
> variable `check_stat`, which makes it shared across repository
> instances within a single process.
>
> Store it instead in `repo_config_values` so the value is associated
> with the repository from which it was read. This preserves existing
> behavior while avoiding cross-repository state leakage and continues
> the effort to reduce reliance on global configuration state.
>
> Update all references to use repo_config_values().
>

Same comments as the first commit. Rest looks good.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values
  2026-03-24 12:37 ` [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values Olamide Caleb Bello
@ 2026-04-14  8:58   ` Karthik Nayak
  2026-04-14 14:32     ` Bello Olamide
  0 siblings, 1 reply; 44+ messages in thread
From: Karthik Nayak @ 2026-04-14  8:58 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 4068 bytes --]

Olamide Caleb Bello <belkid98@gmail.com> writes:

> The `zlib_compression_level` configuration is currently stored in the
> global variable `zlib_compression_level`, which makes it shared across
> repository instances within a single process.
>
> Store it instead in `repo_config_values` so the value is associated
> with the repository from which it was read. This preserves existing
> behavior while avoiding cross-repository state leakage and continues
> the effort to reduce reliance on global configuration state.
>
> Update all references to use repo_config_values().
>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
> ---
>  builtin/index-pack.c | 3 ++-
>  diff.c               | 3 ++-
>  environment.c        | 6 +++---
>  environment.h        | 2 +-
>  http-push.c          | 3 ++-
>  object-file.c        | 3 ++-
>  6 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/builtin/index-pack.c b/builtin/index-pack.c
> index b67fb0256c..dd82eed76f 100644
> --- a/builtin/index-pack.c
> +++ b/builtin/index-pack.c
> @@ -1416,8 +1416,9 @@ static int write_compressed(struct hashfile *f, void *in, unsigned int size)
>  	git_zstream stream;
>  	int status;
>  	unsigned char outbuf[4096];
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
>
> -	git_deflate_init(&stream, zlib_compression_level);
> +	git_deflate_init(&stream, cfg->zlib_compression_level);
>  	stream.next_in = in;
>  	stream.avail_in = size;
>
> diff --git a/diff.c b/diff.c
> index 501648a5c4..4bc0297873 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -3365,8 +3365,9 @@ static unsigned char *deflate_it(char *data,
>  	int bound;
>  	unsigned char *deflated;
>  	git_zstream stream;
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
>
> -	git_deflate_init(&stream, zlib_compression_level);
> +	git_deflate_init(&stream, cfg->zlib_compression_level);
>  	bound = git_deflate_bound(&stream, size);
>  	deflated = xmalloc(bound);
>  	stream.next_out = deflated;
> diff --git a/environment.c b/environment.c
> index 8542ac3141..5b0e88b65c 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -52,7 +52,6 @@ char *git_commit_encoding;
>  char *git_log_output_encoding;
>  char *apply_default_whitespace;
>  char *apply_default_ignorewhitespace;
> -int zlib_compression_level = Z_BEST_SPEED;
>  int pack_compression_level = Z_DEFAULT_COMPRESSION;
>  int fsync_object_files = -1;
>  int use_fsync = -1;
> @@ -377,7 +376,7 @@ int git_default_core_config(const char *var, const char *value,
>  			level = Z_DEFAULT_COMPRESSION;
>  		else if (level < 0 || level > Z_BEST_COMPRESSION)
>  			die(_("bad zlib compression level %d"), level);
> -		zlib_compression_level = level;
> +		cfg->zlib_compression_level = level;
>  		zlib_compression_seen = 1;
>  		return 0;
>  	}
> @@ -389,7 +388,7 @@ int git_default_core_config(const char *var, const char *value,
>  		else if (level < 0 || level > Z_BEST_COMPRESSION)
>  			die(_("bad zlib compression level %d"), level);
>  		if (!zlib_compression_seen)
> -			zlib_compression_level = level;
> +			cfg->zlib_compression_level = level;
>  		if (!pack_compression_seen)
>  			pack_compression_level = level;
>  		return 0;
> @@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
>  	cfg->branch_track = BRANCH_TRACK_REMOTE;
>  	cfg->trust_ctime = 1;
>  	cfg->check_stat = 1;
> +	cfg->zlib_compression_level = Z_BEST_SPEED;
>  }
> diff --git a/environment.h b/environment.h
> index 1d3e2e4f23..93201620af 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -93,6 +93,7 @@ struct repo_config_values {
>  	int apply_sparse_checkout;
>  	int trust_ctime;
>  	int check_stat;
> +	int zlib_compression_level;

Nit: applies to existing values too:
1. Perhaps it would be nicer if these were sorted alphabetically, I
assume we'll add a lot more fields here.
2. Have a comment stating the purpose of the variable?

The patch looks good to me otherwise.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 5/8] environment: move "precomposed_unicode" into `struct repo_config_values`
  2026-03-24 12:37 ` [PATCH v2 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
@ 2026-04-14  9:07   ` Karthik Nayak
  0 siblings, 0 replies; 44+ messages in thread
From: Karthik Nayak @ 2026-04-14  9:07 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 5930 bytes --]

Olamide Caleb Bello <belkid98@gmail.com> writes:

> The `core.precomposeunicode` configuration is currently stored in the
> global variable `precomposed_unicode`, which makes it shared across
> repository instances within a single process.
>
> Store it instead in `repo_config_values` so the value is associated
> with the repository from which it was read. This preserves existing
> behavior while avoiding cross-repository state leakage and is another
> step toward eliminating repository-dependent global state.
>
> Update all references to use repo_config_values().
>
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
> ---
>  compat/precompose_utf8.c | 20 +++++++++++++-------
>  environment.c            |  4 ++--
>  environment.h            |  2 +-
>  upload-pack.c            |  3 ++-
>  4 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
> index 43b3be0114..0e94dbd862 100644
> --- a/compat/precompose_utf8.c
> +++ b/compat/precompose_utf8.c
> @@ -48,16 +48,18 @@ void probe_utf8_pathname_composition(void)
>  	static const char *auml_nfc = "\xc3\xa4";
>  	static const char *auml_nfd = "\x61\xcc\x88";
>  	int output_fd;
> -	if (precomposed_unicode != -1)
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
> +
> +	if (cfg->precomposed_unicode != -1)
>  		return; /* We found it defined in the global config, respect it */
>  	repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
>  	output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600);
>  	if (output_fd >= 0) {
>  		close(output_fd);
>  		repo_git_path_replace(the_repository, &path, "%s", auml_nfd);
> -		precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
> +		cfg->precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
>  		repo_config_set(the_repository, "core.precomposeunicode",
> -				precomposed_unicode ? "true" : "false");
> +				cfg->precomposed_unicode ? "true" : "false");
>  		repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
>  		if (unlink(path.buf))
>  			die_errno(_("failed to unlink '%s'"), path.buf);
> @@ -69,14 +71,16 @@ const char *precompose_string_if_needed(const char *in)
>  {
>  	size_t inlen;
>  	size_t outlen;
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
> +
>  	if (!in)
>  		return NULL;
>  	if (has_non_ascii(in, (size_t)-1, &inlen)) {
>  		iconv_t ic_prec;
>  		char *out;
> -		if (precomposed_unicode < 0)
> -			repo_config_get_bool(the_repository, "core.precomposeunicode", &precomposed_unicode);
> -		if (precomposed_unicode != 1)
> +		if (cfg->precomposed_unicode < 0)
> +			repo_config_get_bool(the_repository, "core.precomposeunicode", &cfg->precomposed_unicode);

So if the variable is unset, we parse the config again. My question is
why doesn't this flow already have the config parsed, or in other words,
is there a way we reach here without the repository being setup. Would
be nice to add this in the commit message.

> +		if (cfg->precomposed_unicode != 1)
>  			return in;
>  		ic_prec = iconv_open(repo_encoding, path_encoding);
>  		if (ic_prec == (iconv_t) -1)
> @@ -130,7 +134,9 @@ PREC_DIR *precompose_utf8_opendir(const char *dirname)
>
>  struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
>  {
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
>  	struct dirent *res;
> +
>  	res = readdir(prec_dir->dirp);
>  	if (res) {
>  		size_t namelenz = strlen(res->d_name) + 1; /* \0 */
> @@ -149,7 +155,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
>  		prec_dir->dirent_nfc->d_ino  = res->d_ino;
>  		prec_dir->dirent_nfc->d_type = res->d_type;
>
> -		if ((precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
> +		if ((cfg->precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
>  			if (prec_dir->ic_precompose == (iconv_t)-1) {
>  				die("iconv_open(%s,%s) failed, but needed:\n"
>  						"    precomposed unicode is not supported.\n"
> diff --git a/environment.c b/environment.c
> index d0d3a4b7d2..739b647ebe 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -72,7 +72,6 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
>  int grafts_keep_true_parents;
>  int core_sparse_checkout_cone;
>  int sparse_expect_files_outside_of_patterns;
> -int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
>  unsigned long pack_size_limit_cfg;
>
>  #ifndef PROTECT_HFS_DEFAULT
> @@ -532,7 +531,7 @@ int git_default_core_config(const char *var, const char *value,
>  	}
>
>  	if (!strcmp(var, "core.precomposeunicode")) {
> -		precomposed_unicode = git_config_bool(var, value);
> +		cfg->precomposed_unicode = git_config_bool(var, value);

We parse a bool value, but....

>  		return 0;
>  	}
>
> @@ -723,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
>  	cfg->check_stat = 1;
>  	cfg->zlib_compression_level = Z_BEST_SPEED;
>  	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
> +	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
>  }

But set -1 to showcase that this is not set. We should add that comment
here.

> diff --git a/environment.h b/environment.h
> index 514576b67a..508cb1afbc 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -95,6 +95,7 @@ struct repo_config_values {
>  	int check_stat;
>  	int zlib_compression_level;
>  	int pack_compression_level;
> +	int precomposed_unicode;
>
>  	/* section "branch" config values */
>  	enum branch_track branch_track;
> @@ -174,7 +175,6 @@ extern char *apply_default_whitespace;
>  extern char *apply_default_ignorewhitespace;
>  extern unsigned long pack_size_limit_cfg;
>
> -extern int precomposed_unicode;
>  extern int protect_hfs;
>  extern int protect_ntfs;

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 0/8] repo_config_values: migrate more globals
  2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
                   ` (7 preceding siblings ...)
  2026-03-24 12:37 ` [PATCH v2 8/8] env: move "warn_on_object_refname_ambiguity" into `repo_config_values` Olamide Caleb Bello
@ 2026-04-14  9:10 ` Karthik Nayak
  2026-04-14 14:26   ` Bello Olamide
                     ` (2 more replies)
  8 siblings, 3 replies; 44+ messages in thread
From: Karthik Nayak @ 2026-04-14  9:10 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 1357 bytes --]

Olamide Caleb Bello <belkid98@gmail.com> writes:

> Overview
> ========
> This series continues the effort to migrate repository-specific global
> variables into struct repo_config_values, further reducing global
> state and improving repository isolation.
>
> The previous series introduced the infrastructure for storing
> repository-dependent configuration in repo_config_values. This series
> extends that work by moving additional environment-related globals into
> that struct and updating their call sites accordingly.
>
> This helps avoid cross-repository interference when multiple
> repositories are used within the same process, and continues preparing
> Git for improved library usage and better encapsulation of repository
> state.
>
> Changes since v1:
> - Dropped "Base series" section as the dependency has been merged.
> - Fixed handling of pack_compression_level: removed use of a local copy and
>   updated code to operate directly on cfg->pack_compression_level to avoid
>   inconsistencies with option parsing.
>

I had a look at the series, the changes look good. I do think this is a
nice opportunity to set some of the variables to be of type bool as
needed. Apart from that, I'd like to see some more comments about each
of the variables and improved commit messages talking about why this
change is done this way.

Thanks,
Karthik

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-14  8:52   ` Karthik Nayak
@ 2026-04-14  9:35     ` Phillip Wood
  2026-04-14 17:15       ` Junio C Hamano
  2026-04-15 11:16       ` Karthik Nayak
  0 siblings, 2 replies; 44+ messages in thread
From: Phillip Wood @ 2026-04-14  9:35 UTC (permalink / raw)
  To: Karthik Nayak, Olamide Caleb Bello, git
  Cc: gitster, christian.couder, usmanakinyemi202, kaartic.sivaraam, me

On 14/04/2026 09:52, Karthik Nayak wrote:
> Olamide Caleb Bello <belkid98@gmail.com> writes:
> 
>> The `core.trustctime` configuration is currently stored in the global
>> variable `trust_ctime`, which makes it shared across repository
>> instances in a single process.
>>
>> Store it instead in `repo_config_values`, so the value is tied to the
>> repository from which it was read. This preserves existing behavior
>> while avoiding cross-repository state leakage and continues the effort
>> to reduce reliance on global configuration state.
>>
>> Update all references to use repo_config_values().
>>
> 
> Nit: I was hoping you'd also shed light on why this can go into
> `repo_config_values()`. Does it need to be eagerly parsed? If so, why?

If trust_ctime was lazily parsed where it is used we'd end up dying in 
match_stat_data() which would be quite unexpected, make it very hard to 
reason about the code, and hamper the libification efforts. I'd much 
rather we put the onus on patch authors to justify any conversion from 
eager parsing to lazy parsing rather than forcing them to justify 
continuing to parse settings eagerly.

Thanks

Phillip

>> Mentored-by: Christian Couder <christian.couder@gmail.com>
>> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
>> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
>> ---
>>   environment.c | 4 ++--
>>   environment.h | 2 +-
>>   statinfo.c    | 6 ++++--
>>   3 files changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/environment.c b/environment.c
>> index fc3ed8bb1c..0a9067729e 100644
>> --- a/environment.c
>> +++ b/environment.c
>> @@ -42,7 +42,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;
>>   int minimum_abbrev = 4, default_abbrev = -1;
>> @@ -309,7 +308,7 @@ int git_default_core_config(const char *var, const char *value,
>>   		return 0;
>>   	}
>>   	if (!strcmp(var, "core.trustctime")) {
>> -		trust_ctime = git_config_bool(var, value);
>> +		cfg->trust_ctime = git_config_bool(var, value);
>>   		return 0;
>>   	}
>>   	if (!strcmp(var, "core.checkstat")) {
>> @@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
>>   	cfg->attributes_file = NULL;
>>   	cfg->apply_sparse_checkout = 0;
>>   	cfg->branch_track = BRANCH_TRACK_REMOTE;
>> +	cfg->trust_ctime = 1;
>>   }
>> diff --git a/environment.h b/environment.h
>> index 123a71cdc8..64d537686e 100644
>> --- a/environment.h
>> +++ b/environment.h
>> @@ -91,6 +91,7 @@ struct repo_config_values {
>>   	/* section "core" config values */
>>   	char *attributes_file;
>>   	int apply_sparse_checkout;
>> +	int trust_ctime;
>>
> 
> Since we parse it as a bool, perhaps we can make the variable to be of
> type bool?
> 
> [snip]


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 0/8] repo_config_values: migrate more globals
  2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
@ 2026-04-14 14:26   ` Bello Olamide
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
  2 siblings, 0 replies; 44+ messages in thread
From: Bello Olamide @ 2026-04-14 14:26 UTC (permalink / raw)
  To: Karthik Nayak
  Cc: git, phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

On Tue, 14 Apr 2026 at 10:10, Karthik Nayak <karthik.188@gmail.com> wrote:
>
> Olamide Caleb Bello <belkid98@gmail.com> writes:
>
> > Overview
> > ========
> > This series continues the effort to migrate repository-specific global
> > variables into struct repo_config_values, further reducing global
> > state and improving repository isolation.
> >
> > The previous series introduced the infrastructure for storing
> > repository-dependent configuration in repo_config_values. This series
> > extends that work by moving additional environment-related globals into
> > that struct and updating their call sites accordingly.
> >
> > This helps avoid cross-repository interference when multiple
> > repositories are used within the same process, and continues preparing
> > Git for improved library usage and better encapsulation of repository
> > state.
> >
> > Changes since v1:
> > - Dropped "Base series" section as the dependency has been merged.
> > - Fixed handling of pack_compression_level: removed use of a local copy and
> >   updated code to operate directly on cfg->pack_compression_level to avoid
> >   inconsistencies with option parsing.
> >
>
> I had a look at the series, the changes look good. I do think this is a
> nice opportunity to set some of the variables to be of type bool as
> needed. Apart from that, I'd like to see some more comments about each
> of the variables and improved commit messages talking about why this
> change is done this way.
>
> Thanks,
> Karthik

Hi Karthik,

Thanks for taking a look.

I’ll review the series and update variables to use bools where appropriate.

I’ll also improve the commit messages to explain better why each variable is
moved into `repo_config_values`, and add comments describing their purpose
and why they are safe to scope per-repository.

I’ll send a v3 with these updates.

Thanks,
Olamide

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values
  2026-04-14  8:58   ` Karthik Nayak
@ 2026-04-14 14:32     ` Bello Olamide
  0 siblings, 0 replies; 44+ messages in thread
From: Bello Olamide @ 2026-04-14 14:32 UTC (permalink / raw)
  To: Karthik Nayak
  Cc: git, phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

On Tue, 14 Apr 2026 at 09:58, Karthik Nayak <karthik.188@gmail.com> wrote:
>
> Olamide Caleb Bello <belkid98@gmail.com> writes:
>
> > The `zlib_compression_level` configuration is currently stored in the
> > global variable `zlib_compression_level`, which makes it shared across
> > repository instances within a single process.
> >
> > Store it instead in `repo_config_values` so the value is associated
> > with the repository from which it was read. This preserves existing
> > behavior while avoiding cross-repository state leakage and continues
> > the effort to reduce reliance on global configuration state.
> >
> > Update all references to use repo_config_values().
> >
> > Mentored-by: Christian Couder <christian.couder@gmail.com>
> > Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
> > Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
> > ---
> >  builtin/index-pack.c | 3 ++-
> >  diff.c               | 3 ++-
> >  environment.c        | 6 +++---
> >  environment.h        | 2 +-
> >  http-push.c          | 3 ++-
> >  object-file.c        | 3 ++-
> >  6 files changed, 12 insertions(+), 8 deletions(-)
> >
> > diff --git a/builtin/index-pack.c b/builtin/index-pack.c
> > index b67fb0256c..dd82eed76f 100644
> > --- a/builtin/index-pack.c
> > +++ b/builtin/index-pack.c
> > @@ -1416,8 +1416,9 @@ static int write_compressed(struct hashfile *f, void *in, unsigned int size)
> >       git_zstream stream;
> >       int status;
> >       unsigned char outbuf[4096];
> > +     struct repo_config_values *cfg = repo_config_values(the_repository);
> >
> > -     git_deflate_init(&stream, zlib_compression_level);
> > +     git_deflate_init(&stream, cfg->zlib_compression_level);
> >       stream.next_in = in;
> >       stream.avail_in = size;
> >
> > diff --git a/diff.c b/diff.c
> > index 501648a5c4..4bc0297873 100644
> > --- a/diff.c
> > +++ b/diff.c
> > @@ -3365,8 +3365,9 @@ static unsigned char *deflate_it(char *data,
> >       int bound;
> >       unsigned char *deflated;
> >       git_zstream stream;
> > +     struct repo_config_values *cfg = repo_config_values(the_repository);
> >
> > -     git_deflate_init(&stream, zlib_compression_level);
> > +     git_deflate_init(&stream, cfg->zlib_compression_level);
> >       bound = git_deflate_bound(&stream, size);
> >       deflated = xmalloc(bound);
> >       stream.next_out = deflated;
> > diff --git a/environment.c b/environment.c
> > index 8542ac3141..5b0e88b65c 100644
> > --- a/environment.c
> > +++ b/environment.c
> > @@ -52,7 +52,6 @@ char *git_commit_encoding;
> >  char *git_log_output_encoding;
> >  char *apply_default_whitespace;
> >  char *apply_default_ignorewhitespace;
> > -int zlib_compression_level = Z_BEST_SPEED;
> >  int pack_compression_level = Z_DEFAULT_COMPRESSION;
> >  int fsync_object_files = -1;
> >  int use_fsync = -1;
> > @@ -377,7 +376,7 @@ int git_default_core_config(const char *var, const char *value,
> >                       level = Z_DEFAULT_COMPRESSION;
> >               else if (level < 0 || level > Z_BEST_COMPRESSION)
> >                       die(_("bad zlib compression level %d"), level);
> > -             zlib_compression_level = level;
> > +             cfg->zlib_compression_level = level;
> >               zlib_compression_seen = 1;
> >               return 0;
> >       }
> > @@ -389,7 +388,7 @@ int git_default_core_config(const char *var, const char *value,
> >               else if (level < 0 || level > Z_BEST_COMPRESSION)
> >                       die(_("bad zlib compression level %d"), level);
> >               if (!zlib_compression_seen)
> > -                     zlib_compression_level = level;
> > +                     cfg->zlib_compression_level = level;
> >               if (!pack_compression_seen)
> >                       pack_compression_level = level;
> >               return 0;
> > @@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
> >       cfg->branch_track = BRANCH_TRACK_REMOTE;
> >       cfg->trust_ctime = 1;
> >       cfg->check_stat = 1;
> > +     cfg->zlib_compression_level = Z_BEST_SPEED;
> >  }
> > diff --git a/environment.h b/environment.h
> > index 1d3e2e4f23..93201620af 100644
> > --- a/environment.h
> > +++ b/environment.h
> > @@ -93,6 +93,7 @@ struct repo_config_values {
> >       int apply_sparse_checkout;
> >       int trust_ctime;
> >       int check_stat;
> > +     int zlib_compression_level;
>
> Nit: applies to existing values too:
> 1. Perhaps it would be nicer if these were sorted alphabetically, I
> assume we'll add a lot more fields here.
I’ll reorder the fields in `repo_config_values` alphabetically
to keep things consistent as more entries are added.
> 2. Have a comment stating the purpose of the variable?
I’ll also add comments describing the purpose of each variable
>
> The patch looks good to me otherwise.

Thanks, Karthik, for the review.

Olamide Bello

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-14  9:35     ` Phillip Wood
@ 2026-04-14 17:15       ` Junio C Hamano
  2026-04-15 11:16       ` Karthik Nayak
  1 sibling, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2026-04-14 17:15 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Karthik Nayak, Olamide Caleb Bello, git, christian.couder,
	usmanakinyemi202, kaartic.sivaraam, me

Phillip Wood <phillip.wood123@gmail.com> writes:

> On 14/04/2026 09:52, Karthik Nayak wrote:
> ...
>> Nit: I was hoping you'd also shed light on why this can go into
>> `repo_config_values()`. Does it need to be eagerly parsed? If so, why?
>
> If trust_ctime was lazily parsed where it is used we'd end up dying in 
> match_stat_data() which would be quite unexpected, make it very hard to 
> reason about the code, and hamper the libification efforts. I'd much 
> rather we put the onus on patch authors to justify any conversion from 
> eager parsing to lazy parsing rather than forcing them to justify 
> continuing to parse settings eagerly.
>
> Thanks
>
> Phillip

I too often get confused while looking at these "global static
variables holding parsed configuration values are bad, let's move it
elsewhere" patches between the on-demand and upfront parsing.

I agree that what has traditionally been parsed upfront are mostly
fundamental things (e.g., in core.* namespace) that is better parsed
upfront, and what has been parsed on-demand are often very operation
specific thing whose misspelt values do not matter when we are not
running that specific operation, so it is better parsed on-demand.
There may be exceptions and some variables that the current code
parses upfront might be better parsed on-demand and vice versa, but
the default for these rewrite effort ought to be to keep the
existing semantics unless there is a good justification for changing
it.

Thanks for injecting a dose of sanity so clearly.



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-14  9:35     ` Phillip Wood
  2026-04-14 17:15       ` Junio C Hamano
@ 2026-04-15 11:16       ` Karthik Nayak
  2026-04-15 15:49         ` Junio C Hamano
  1 sibling, 1 reply; 44+ messages in thread
From: Karthik Nayak @ 2026-04-15 11:16 UTC (permalink / raw)
  To: phillip.wood, Olamide Caleb Bello, git
  Cc: gitster, christian.couder, usmanakinyemi202, kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 1374 bytes --]

Phillip Wood <phillip.wood123@gmail.com> writes:

> On 14/04/2026 09:52, Karthik Nayak wrote:
>> Olamide Caleb Bello <belkid98@gmail.com> writes:
>>
>>> The `core.trustctime` configuration is currently stored in the global
>>> variable `trust_ctime`, which makes it shared across repository
>>> instances in a single process.
>>>
>>> Store it instead in `repo_config_values`, so the value is tied to the
>>> repository from which it was read. This preserves existing behavior
>>> while avoiding cross-repository state leakage and continues the effort
>>> to reduce reliance on global configuration state.
>>>
>>> Update all references to use repo_config_values().
>>>
>>
>> Nit: I was hoping you'd also shed light on why this can go into
>> `repo_config_values()`. Does it need to be eagerly parsed? If so, why?
>
> If trust_ctime was lazily parsed where it is used we'd end up dying in
> match_stat_data() which would be quite unexpected, make it very hard to
> reason about the code, and hamper the libification efforts. I'd much
> rather we put the onus on patch authors to justify any conversion from
> eager parsing to lazy parsing rather than forcing them to justify
> continuing to parse settings eagerly.
>

Agreed. A note in the commit message that this belongs in
`repo_config_values()` because it's eagerly parsed would be enough.

> Thanks
>
> Phillip
>

[snip]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-15 11:16       ` Karthik Nayak
@ 2026-04-15 15:49         ` Junio C Hamano
  2026-04-15 19:09           ` Karthik Nayak
  0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2026-04-15 15:49 UTC (permalink / raw)
  To: Karthik Nayak
  Cc: phillip.wood, Olamide Caleb Bello, git, christian.couder,
	usmanakinyemi202, kaartic.sivaraam, me

Karthik Nayak <karthik.188@gmail.com> writes:

>>>> Store it instead in `repo_config_values`, so the value is tied to the
>>>> repository from which it was read. This preserves existing behavior
>>>> while avoiding cross-repository state leakage and continues the effort
>>>> to reduce reliance on global configuration state.
>>>>
>>>> Update all references to use repo_config_values().
>>>>
>>>
>>> Nit: I was hoping you'd also shed light on why this can go into
>>> `repo_config_values()`. Does it need to be eagerly parsed? If so, why?
>>
>> If trust_ctime was lazily parsed where it is used we'd end up dying in
>> match_stat_data() which would be quite unexpected, make it very hard to
>> reason about the code, and hamper the libification efforts. I'd much
>> rather we put the onus on patch authors to justify any conversion from
>> eager parsing to lazy parsing rather than forcing them to justify
>> continuing to parse settings eagerly.
>>
>
> Agreed. A note in the commit message that this belongs in
> `repo_config_values()` because it's eagerly parsed would be enough.

I see "preserves existing behavior" above.   Wouldn't it be enough?

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-15 15:49         ` Junio C Hamano
@ 2026-04-15 19:09           ` Karthik Nayak
  0 siblings, 0 replies; 44+ messages in thread
From: Karthik Nayak @ 2026-04-15 19:09 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: phillip.wood, Olamide Caleb Bello, git, christian.couder,
	usmanakinyemi202, kaartic.sivaraam, me

[-- Attachment #1: Type: text/plain, Size: 1437 bytes --]

Junio C Hamano <gitster@pobox.com> writes:

> Karthik Nayak <karthik.188@gmail.com> writes:
>
>>>>> Store it instead in `repo_config_values`, so the value is tied to the
>>>>> repository from which it was read. This preserves existing behavior
>>>>> while avoiding cross-repository state leakage and continues the effort
>>>>> to reduce reliance on global configuration state.
>>>>>
>>>>> Update all references to use repo_config_values().
>>>>>
>>>>
>>>> Nit: I was hoping you'd also shed light on why this can go into
>>>> `repo_config_values()`. Does it need to be eagerly parsed? If so, why?
>>>
>>> If trust_ctime was lazily parsed where it is used we'd end up dying in
>>> match_stat_data() which would be quite unexpected, make it very hard to
>>> reason about the code, and hamper the libification efforts. I'd much
>>> rather we put the onus on patch authors to justify any conversion from
>>> eager parsing to lazy parsing rather than forcing them to justify
>>> continuing to parse settings eagerly.
>>>
>>
>> Agreed. A note in the commit message that this belongs in
>> `repo_config_values()` because it's eagerly parsed would be enough.
>
> I see "preserves existing behavior" above.   Wouldn't it be enough?

Though "preserves existing behavior" implicitly covers this, it would be
cleaner to explicitly mention that eager parsing is the reason it
belongs in `repo_config_values()`. That said, I'm happy with it as is
too.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 0/8] repo_config_values: migrate more globals
  2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
  2026-04-14 14:26   ` Bello Olamide
@ 2026-04-23 16:08   ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 1/8] Revert "compat/posix: introduce writev(3p) wrapper" Olamide Caleb Bello
                       ` (8 more replies)
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
  2 siblings, 9 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

This series continues the effort to remove repository-dependent global
configuration state by moving several core.* configuration variables
into struct `repo_config_values`.

This ensures configuration values are tied to the repository from which
they were read, avoiding cross-repository state leakage in processes
handling multiple repositories, while preserving existing behavior.

All affected configuration values are eagerly parsed. Storing them in
repo_config_values preserves current semantics and avoids introducing
lazy parsing into runtime code paths.

This v3 addresses review feedback by explicitly clarifying the reason
these values belong in repo_config_values (eager parsing) and improving
commit message clarity.

Olamide Caleb Bello (8):
  environment: move "trust_ctime" into struct repo_config_values
  environment: move "check_stat" into struct repo_config_values
  environment: move "zlib_compression_level" into repo_config_values
  environment: move "pack_compression_level" into struct repo_config_values
  environment: move "precomposed_unicode" into struct repo_config_values
  env: move "core_sparse_checkout_cone" into repo_config_values
  env: put "sparse_expect_files_outside_of_patterns" in repo_config_values
  env: move "warn_on_object_refname_ambiguity" into repo_config_values
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 1/8] Revert "compat/posix: introduce writev(3p) wrapper"
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 2/8] rust: we are way beyond 2.53 Olamide Caleb Bello
                       ` (7 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

From: Junio C Hamano <gitster@pobox.com>

This reverts commit 3b9b2c2a29a1d529ca9884fa0a6529f6e2496abe; let's
not use writev() for now.
---
 Makefile         |  4 ----
 compat/posix.h   | 14 --------------
 compat/writev.c  | 44 --------------------------------------------
 config.mak.uname |  2 --
 meson.build      |  1 -
 5 files changed, 65 deletions(-)
 delete mode 100644 compat/writev.c

diff --git a/Makefile b/Makefile
index 5d22394c2e..cedc234173 100644
--- a/Makefile
+++ b/Makefile
@@ -2029,10 +2029,6 @@ ifdef NO_PREAD
 	COMPAT_CFLAGS += -DNO_PREAD
 	COMPAT_OBJS += compat/pread.o
 endif
-ifdef NO_WRITEV
-	COMPAT_CFLAGS += -DNO_WRITEV
-	COMPAT_OBJS += compat/writev.o
-endif
 ifdef NO_FAST_WORKING_DIRECTORY
 	BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
 endif
diff --git a/compat/posix.h b/compat/posix.h
index 94699a03fa..faaae1b655 100644
--- a/compat/posix.h
+++ b/compat/posix.h
@@ -137,9 +137,6 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/statvfs.h>
-#ifndef NO_WRITEV
-#include <sys/uio.h>
-#endif
 #include <termios.h>
 #ifndef NO_SYS_SELECT_H
 #include <sys/select.h>
@@ -326,17 +323,6 @@ int git_lstat(const char *, struct stat *);
 ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
 
-#ifdef NO_WRITEV
-#define writev git_writev
-#define iovec git_iovec
-struct git_iovec {
-	void *iov_base;
-	size_t iov_len;
-};
-
-ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt);
-#endif
-
 #ifdef NO_SETENV
 #define setenv gitsetenv
 int gitsetenv(const char *, const char *, int);
diff --git a/compat/writev.c b/compat/writev.c
deleted file mode 100644
index 3a94870a2f..0000000000
--- a/compat/writev.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "../git-compat-util.h"
-#include "../wrapper.h"
-
-ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt)
-{
-	size_t total_written = 0;
-	size_t sum = 0;
-
-	/*
-	 * According to writev(3p), the syscall shall error with EINVAL in case
-	 * the sum of `iov_len` overflows `ssize_t`.
-	 */
-	 for (int i = 0; i < iovcnt; i++) {
-		if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) ||
-		    iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) {
-			errno = EINVAL;
-			return -1;
-		}
-
-		sum += iov[i].iov_len;
-	}
-
-	for (int i = 0; i < iovcnt; i++) {
-		const char *bytes = iov[i].iov_base;
-		size_t iovec_written = 0;
-
-		while (iovec_written < iov[i].iov_len) {
-			ssize_t bytes_written = xwrite(fd, bytes + iovec_written,
-						       iov[i].iov_len - iovec_written);
-			if (bytes_written < 0) {
-				if (total_written)
-					goto out;
-				return bytes_written;
-			}
-			if (!bytes_written)
-				goto out;
-			iovec_written += bytes_written;
-			total_written += bytes_written;
-		}
-	}
-
-out:
-	return (ssize_t) total_written;
-}
diff --git a/config.mak.uname b/config.mak.uname
index ccb3f71881..5feb582558 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -459,7 +459,6 @@ ifeq ($(uname_S),Windows)
 	SANE_TOOL_PATH ?= $(msvc_bin_dir_msys)
 	HAVE_ALLOCA_H = YesPlease
 	NO_PREAD = YesPlease
-	NO_WRITEV = YesPlease
 	NEEDS_CRYPTO_WITH_SSL = YesPlease
 	NO_LIBGEN_H = YesPlease
 	NO_POLL = YesPlease
@@ -675,7 +674,6 @@ ifeq ($(uname_S),MINGW)
 	pathsep = ;
 	HAVE_ALLOCA_H = YesPlease
 	NO_PREAD = YesPlease
-	NO_WRITEV = YesPlease
 	NEEDS_CRYPTO_WITH_SSL = YesPlease
 	NO_LIBGEN_H = YesPlease
 	NO_POLL = YesPlease
diff --git a/meson.build b/meson.build
index 8309942d18..11488623bf 100644
--- a/meson.build
+++ b/meson.build
@@ -1429,7 +1429,6 @@ checkfuncs = {
   'initgroups' : [],
   'strtoumax' : ['strtoumax.c', 'strtoimax.c'],
   'pread' : ['pread.c'],
-  'writev' : ['writev.c'],
 }
 
 if host_machine.system() == 'windows'
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] rust: we are way beyond 2.53
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 1/8] Revert "compat/posix: introduce writev(3p) wrapper" Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 3/8] doc: am: revert Message-ID trailer claim Olamide Caleb Bello
                       ` (6 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, brian m. carlson, Derrick Stolee

From: Junio C Hamano <gitster@pobox.com>

Earlier we timelined that we'd tune our build procedures to build
with Rust by default in Git 2.53, but we are already in prerelease
freeze for 2.54 now.  Update the BreakingChanges document to delay
it until Git 2.55 (slated for the end of June 2026).

Noticed-by: brian m. carlson <sandals@crustytoothpaste.net>
Helped-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/BreakingChanges.adoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc
index f814450d2f..af59c43f42 100644
--- a/Documentation/BreakingChanges.adoc
+++ b/Documentation/BreakingChanges.adoc
@@ -190,7 +190,7 @@ milestones for the introduction of Rust:
 1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and
    disabled in our Makefile so that the project can sort out the initial
    infrastructure.
-2. In Git 2.53, both build systems will default-enable support for Rust.
+2. In Git 2.55, both build systems will default-enable support for Rust.
    Consequently, builds will break by default if Rust is not available on the
    build host. The use of Rust can still be explicitly disabled via build
    flags.
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 3/8] doc: am: revert Message-ID trailer claim
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 1/8] Revert "compat/posix: introduce writev(3p) wrapper" Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 2/8] rust: we are way beyond 2.53 Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 4/8] doc: am: correct to full --no-message-id Olamide Caleb Bello
                       ` (5 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Kristoffer Haugsbakk

From: Kristoffer Haugsbakk <code@khaugsbakk.name>

I claimed in 3c18135b (doc: am: say that --message-id adds a trailer,
2026-02-09) that `git am --message-id` adds a Git trailer. But that
isn’t the case; for the case of a commit message with a subject, body,
and no trailer block:

    <subject>

    <paragrah>

It just appends the line right after `paragraph`:

    <subject>

    <paragraph>
    Message-ID: <message-id_trailer.323@msgid.xyz>

It does work for two other cases though, namely subject-only and with an
existing trailer block.

This is at best an inconsistency and arguably a bug, but we’re at the
trailing end of the release cycle now. So reverting the doc is safer
than making msg-id act as a trailer, for now.

Revert this hunk from commit 3c18135b except the only useful
change (“Also use inline-verbatim for `Message-ID`”).

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-am.adoc | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc
index 403181baa9..14f83a8920 100644
--- a/Documentation/git-am.adoc
+++ b/Documentation/git-am.adoc
@@ -84,11 +84,10 @@ OPTIONS
 
 -m::
 --message-id::
-	Pass the `-m` flag to linkgit:git-mailinfo[1], so that the
-	`Message-ID` header is added as a trailer (see
-	linkgit:git-interpret-trailers[1]).  The `am.messageid`
-	configuration variable can be used to specify the default
-	behaviour.
+	Pass the `-m` flag to linkgit:git-mailinfo[1],
+	so that the `Message-ID` header is added to the commit message.
+	The `am.messageid` configuration variable can be used to specify
+	the default behaviour.
 
 --no-message-id::
 	Do not add the Message-ID header to the commit message.
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] doc: am: correct to full --no-message-id
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (2 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 3/8] doc: am: revert Message-ID trailer claim Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 5/8] CI: bump actions/checkout from 4 to 5 for rust-analysis job Olamide Caleb Bello
                       ` (4 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Kristoffer Haugsbakk

From: Kristoffer Haugsbakk <code@khaugsbakk.name>

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-am.adoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc
index 14f83a8920..ab71ab7490 100644
--- a/Documentation/git-am.adoc
+++ b/Documentation/git-am.adoc
@@ -91,7 +91,7 @@ OPTIONS
 
 --no-message-id::
 	Do not add the Message-ID header to the commit message.
-	`no-message-id` is useful to override `am.messageid`.
+	`--no-message-id` is useful to override `am.messageid`.
 
 -q::
 --quiet::
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 5/8] CI: bump actions/checkout from 4 to 5 for rust-analysis job
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (3 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 4/8] doc: am: correct to full --no-message-id Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 6/8] gitglossary: fix indentation of sub-lists Olamide Caleb Bello
                       ` (3 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

From: Junio C Hamano <gitster@pobox.com>

GitHub Actions started complaining about use of Node.js 20 and I was
wondering why only one job uses actions/checkout@v4, while everybody
else already uses actions/checkout@v5.

It turns out that it is caused by a semantic mismerge between
e75cd059 (ci: check formatting of our Rust code, 2025-10-15) that
added a new use of actions/checkout@v4 that happened very close to
another change 63541ed9 (build(deps): bump actions/checkout from 4
to 5, 2025-10-16) that updated all uses of actions/checkout@v4 to
use vactions/checkout@v5.

Update the leftover and the last use of actions/checkout@v4 to use
actions/checkout@v5 to help ourselves to move away from Node.js 20.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 .github/workflows/main.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f2e93f5461..8ed268fc09 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -480,7 +480,7 @@ jobs:
       group: rust-analysis-${{ github.ref }}
       cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: ci/install-dependencies.sh
     - run: ci/run-rust-checks.sh
   sparse:
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 6/8] gitglossary: fix indentation of sub-lists
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (4 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 5/8] CI: bump actions/checkout from 4 to 5 for rust-analysis job Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 7/8] Hopefully the final tweak before -rc2 Olamide Caleb Bello
                       ` (2 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Jeff King

From: Jeff King <peff@peff.net>

The glossary entry is a list of terms and their definitions, so
multi-paragraph definitions need "+" continuation lines to indicate
that they are part of a single entry.

When an entry contains a sub-list (say, a bulleted list), the final "+"
may become ambiguous: is it connecting the next paragraph to the final
entry of the sub-list, or to the original list of definition paragraphs?

Asciidoc generally connects it to the former, even when we mean the
latter, and you end up with the next paragraph indented incorrectly,
like this:

  glob
    ...defines glob...

    Two consecutive asterisks ("**") in patterns matched
    against full pathname may have special meaning:

    - ...some special meaning of **...

    - ...another special meaning of **...

    - Other consecutive asterisks are considered invalid.

      Glob magic is incompatible with literal magic.

That final "Glob magic is incompatible" paragraph is in the wrong spot.
It should be at the same level as "Two consecutive asterisks", as it is
not part of the final "Other consecutive asterisks" bullet point.

The same problem appears in several other spots in the glossary.

Usually we'd fix this by using "--" markers, which put the sub-list into
its own block. But there's a catch: in some of these spots we are
already in an open block, and nesting open blocks is a problem. It seems
to work for me using Asciidoc 10.2.1, but Asciidoctor 2.0.26 makes a
mess of it (our intent to open a new block seems to close the old one).

Fortunately there's a work-around: when using a "+" list-continuation,
the number of empty lines above the continuation indicates which level
of parent list to continue. So by adding an empty line after our
unordered list (before the "+"), we should be able to continue the
definition list item.

But asciidoc being asciidoc, of course that is not the end of the story.
That technique works fine for the "glob" and "attr" lists in this patch,
but under the "refs" item it works for only 1 of the 2 lists! I can't
figure out why, and this may be an asciidoctor bug. But we can work
around it by using "--" open-block markers here, since we're not
already in an open block.

So using the extra blank line for the first two instances, and "--"
markers for the second two, this patch produces identical output from
"doc-diff HEAD^ HEAD" for both --asciidoctor and --asciidoc modes.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/glossary-content.adoc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/glossary-content.adoc b/Documentation/glossary-content.adoc
index 20ba121314..8c4e9dd3be 100644
--- a/Documentation/glossary-content.adoc
+++ b/Documentation/glossary-content.adoc
@@ -430,6 +430,7 @@ full pathname may have special meaning:
    matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
 
  - Other consecutive asterisks are considered invalid.
+
 +
 Glob magic is incompatible with literal magic.
 
@@ -452,6 +453,7 @@ these forms:
 
 - "`!ATTR`" requires that the attribute `ATTR` be
   unspecified.
+
 +
 Note that when matching against a tree object, attributes are still
 obtained from working tree, not from the given tree object.
@@ -560,14 +562,17 @@ The ref namespace is hierarchical.
 Ref names must either start with `refs/` or be located in the root of
 the hierarchy. For the latter, their name must follow these rules:
 +
+--
  - The name consists of only upper-case characters or underscores.
 
  - The name ends with "`_HEAD`" or is equal to "`HEAD`".
+--
 +
 There are some irregular refs in the root of the hierarchy that do not
 match these rules. The following list is exhaustive and shall not be
 extended in the future:
 +
+--
  - `AUTO_MERGE`
 
  - `BISECT_EXPECTED_REV`
@@ -577,6 +582,7 @@ extended in the future:
  - `NOTES_MERGE_REF`
 
  - `MERGE_AUTOSTASH`
+--
 +
 Different subhierarchies are used for different purposes. For example,
 the `refs/heads/` hierarchy is used to represent local branches whereas
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 7/8] Hopefully the final tweak before -rc2
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (5 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 6/8] gitglossary: fix indentation of sub-lists Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:08     ` [PATCH v3 8/8] Git 2.54-rc2 Olamide Caleb Bello
  2026-04-23 16:37     ` [PATCH v3 0/8] repo_config_values: migrate more globals Bello Olamide
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

From: Junio C Hamano <gitster@pobox.com>

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/RelNotes/2.54.0.adoc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/RelNotes/2.54.0.adoc b/Documentation/RelNotes/2.54.0.adoc
index 3fa25e06f2..2ad73ff473 100644
--- a/Documentation/RelNotes/2.54.0.adoc
+++ b/Documentation/RelNotes/2.54.0.adoc
@@ -526,6 +526,12 @@ Fixes since v2.53
    conflicts.
    (merge c0ce43376b ng/add-files-to-cache-wo-rename later to maint).
 
+ * Doc mark-up update for entries in the glossary with bulleted lists.
+   (merge a65cbd87ea jk/doc-markup-sub-list-indentation later to maint).
+
+ * CI dependency updates.
+   (merge 4bdb17e3a8 jc/ci-github-actions-use-checkout-v5 later to maint).
+
  * Other code cleanup, docfix, build fix, etc.
    (merge d79fff4a11 jk/remote-tracking-ref-leakfix later to maint).
    (merge 7a747f972d dd/t5403-modernise later to maint).
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 8/8] Git 2.54-rc2
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (6 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 7/8] Hopefully the final tweak before -rc2 Olamide Caleb Bello
@ 2026-04-23 16:08     ` Olamide Caleb Bello
  2026-04-23 16:37     ` [PATCH v3 0/8] repo_config_values: migrate more globals Bello Olamide
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:08 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

From: Junio C Hamano <gitster@pobox.com>

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 GIT-VERSION-GEN | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 9c55beb496..fb11bace12 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEF_VER=v2.54.0-rc1
+DEF_VER=v2.54.0-rc2
 
 LF='
 '
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 0/8] repo_config_values: migrate more globals
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
                       ` (7 preceding siblings ...)
  2026-04-23 16:08     ` [PATCH v3 8/8] Git 2.54-rc2 Olamide Caleb Bello
@ 2026-04-23 16:37     ` Bello Olamide
  8 siblings, 0 replies; 44+ messages in thread
From: Bello Olamide @ 2026-04-23 16:37 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

Hi all,

Apologies, this v3 series was generated with an incorrect commit range,
and includes unrelated upstream commits. Please ignore this series.

I will resend a corrected version shortly based only on the intended
environment.* refactoring changes.

Thanks,
Olamide Bello

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 0/8] environment: move core config globals into repo_config_values
  2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
  2026-04-14 14:26   ` Bello Olamide
  2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
@ 2026-04-23 16:54   ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
                       ` (8 more replies)
  2 siblings, 9 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

This series continues the effort to remove repository-dependent global
configuration state by moving several core.* configuration variables
into struct repo_config_values.

This ensures configuration values are tied to the repository from which
they were read, avoiding cross-repository state leakage in processes
handling multiple repositories, while preserving existing behavior.

All affected configuration values are eagerly parsed. Storing them in
repo_config_values preserves current semantics and avoids introducing
lazy parsing into runtime code paths.

This v3 addresses review feedback by explicitly clarifying the reason
these values belong in repo_config_values (eager parsing) and improving
commit message clarity.

Olamide Caleb Bello (8):
  environment: move "trust_ctime" into `struct repo_config_values`
  environment: move "check_stat" into `struct repo_config_values`
  environment: move `zlib_compression_level` into `struct
    repo_config_values`
  environment: move "pack_compression_level" into `struct
    repo_config_values`
  environment: move "precomposed_unicode" into `struct
    repo_config_values`
  env: move "core_sparse_checkout_cone" into `struct repo_config_values`
  env: move "sparse_expect_files_outside_of_patterns" into
    `repo_config_values`
  env: move "warn_on_object_refname_ambiguity" into `struct
    repo_config_values`

 builtin/cat-file.c        |  7 ++++---
 builtin/fast-import.c     |  8 +++++---
 builtin/index-pack.c      |  3 ++-
 builtin/mv.c              |  2 +-
 builtin/pack-objects.c    | 24 +++++++++++++----------
 builtin/sparse-checkout.c | 37 +++++++++++++++++++++---------------
 compat/precompose_utf8.c  | 20 +++++++++++++-------
 diff.c                    |  3 ++-
 dir.c                     |  3 ++-
 entry.c                   |  3 ++-
 environment.c             | 40 +++++++++++++++++++++------------------
 environment.h             | 19 ++++++++++---------
 http-push.c               |  3 ++-
 object-file.c             |  6 ++++--
 object-name.c             |  3 ++-
 revision.c                |  7 ++++---
 sparse-index.c            |  4 ++--
 statinfo.c                | 12 +++++++-----
 submodule.c               |  7 ++++---
 upload-pack.c             |  3 ++-
 20 files changed, 126 insertions(+), 88 deletions(-)

-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v3 1/8] environment: move "trust_ctime" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 2/8] environment: move "check_stat" " Olamide Caleb Bello
                       ` (7 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.trustctime` configuration is currently stored in the global
variable `trust_ctime`, which makes it shared across repository
instances in a single process.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. `core.trustctime` is parsed eagerly
because it is used in low‑level stat‑matching functions
(`match_stat_data()`), where a lazy parse could cause unexpected
fatal errors and complicate libification efforts. This preserves
that behavior while tying the value to the repository from which it
was read, avoiding cross‑repository state leakage and continuing the
effort to reduce reliance on global configuration state.

Update all references to use repo_config_values().

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 environment.c | 4 ++--
 environment.h | 2 +-
 statinfo.c    | 6 ++++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/environment.c b/environment.c
index fc3ed8bb1c..0a9067729e 100644
--- a/environment.c
+++ b/environment.c
@@ -42,7 +42,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;
 int minimum_abbrev = 4, default_abbrev = -1;
@@ -309,7 +308,7 @@ int git_default_core_config(const char *var, const char *value,
 		return 0;
 	}
 	if (!strcmp(var, "core.trustctime")) {
-		trust_ctime = git_config_bool(var, value);
+		cfg->trust_ctime = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "core.checkstat")) {
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->attributes_file = NULL;
 	cfg->apply_sparse_checkout = 0;
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
+	cfg->trust_ctime = 1;
 }
diff --git a/environment.h b/environment.h
index 123a71cdc8..64d537686e 100644
--- a/environment.h
+++ b/environment.h
@@ -91,6 +91,7 @@ struct repo_config_values {
 	/* section "core" config values */
 	char *attributes_file;
 	int apply_sparse_checkout;
+	int trust_ctime;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -161,7 +162,6 @@ 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;
 extern int minimum_abbrev, default_abbrev;
diff --git a/statinfo.c b/statinfo.c
index 30a164b0e6..4fc12053f4 100644
--- a/statinfo.c
+++ b/statinfo.c
@@ -3,6 +3,7 @@
 #include "git-compat-util.h"
 #include "environment.h"
 #include "statinfo.h"
+#include "repository.h"
 
 /*
  * Munge st_size into an unsigned int.
@@ -63,17 +64,18 @@ void fake_lstat_data(const struct stat_data *sd, struct stat *st)
 int match_stat_data(const struct stat_data *sd, struct stat *st)
 {
 	int changed = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
+	if (cfg->trust_ctime && check_stat &&
 	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 #ifdef USE_NSEC
 	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
+	if (cfg->trust_ctime && check_stat &&
 	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
 		changed |= CTIME_CHANGED;
 #endif
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 2/8] environment: move "check_stat" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 3/8] environment: move `zlib_compression_level` " Olamide Caleb Bello
                       ` (6 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.checkstat` configuration is currently stored in the global
variable `check_stat`, which makes it shared across repository
instances within a single process.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. `core.checkstat` is parsed eagerly
because it controls how `match_stat_data()` and related functions
decide file freshness; a lazy parse could lead to unexpected
behavior or complicate libification. This preserves the existing
eager‑parsing behavior while tying the value to the repository it
was read from, avoiding cross‑repository state leakage, and
continuing the effort to reduce reliance on global configuration
state.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 entry.c       |  3 ++-
 environment.c |  6 +++---
 environment.h |  2 +-
 statinfo.c    | 10 +++++-----
 4 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/entry.c b/entry.c
index 7817aee362..c55e867d8a 100644
--- a/entry.c
+++ b/entry.c
@@ -443,7 +443,8 @@ static int check_path(const char *path, int len, struct stat *st, int skiplen)
 static void mark_colliding_entries(const struct checkout *state,
 				   struct cache_entry *ce, struct stat *st)
 {
-	int trust_ino = check_stat;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+	int trust_ino = cfg->check_stat;
 
 #if defined(GIT_WINDOWS_NATIVE) || defined(__CYGWIN__)
 	trust_ino = 0;
diff --git a/environment.c b/environment.c
index 0a9067729e..8542ac3141 100644
--- a/environment.c
+++ b/environment.c
@@ -42,7 +42,6 @@ static int pack_compression_seen;
 static int zlib_compression_seen;
 
 int trust_executable_bit = 1;
-int check_stat = 1;
 int has_symlinks = 1;
 int minimum_abbrev = 4, default_abbrev = -1;
 int ignore_case;
@@ -315,9 +314,9 @@ int git_default_core_config(const char *var, const char *value,
 		if (!value)
 			return config_error_nonbool(var);
 		if (!strcasecmp(value, "default"))
-			check_stat = 1;
+			cfg->check_stat = 1;
 		else if (!strcasecmp(value, "minimal"))
-			check_stat = 0;
+			cfg->check_stat = 0;
 		else
 			return error(_("invalid value for '%s': '%s'"),
 				     var, value);
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->apply_sparse_checkout = 0;
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
 	cfg->trust_ctime = 1;
+	cfg->check_stat = 1;
 }
diff --git a/environment.h b/environment.h
index 64d537686e..1d3e2e4f23 100644
--- a/environment.h
+++ b/environment.h
@@ -92,6 +92,7 @@ struct repo_config_values {
 	char *attributes_file;
 	int apply_sparse_checkout;
 	int trust_ctime;
+	int check_stat;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -162,7 +163,6 @@ extern char *git_work_tree_cfg;
 
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
-extern int check_stat;
 extern int has_symlinks;
 extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
diff --git a/statinfo.c b/statinfo.c
index 4fc12053f4..5e00af127d 100644
--- a/statinfo.c
+++ b/statinfo.c
@@ -68,19 +68,19 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
 
 	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (cfg->trust_ctime && check_stat &&
+	if (cfg->trust_ctime && cfg->check_stat &&
 	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 #ifdef USE_NSEC
-	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
+	if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
 		changed |= MTIME_CHANGED;
-	if (cfg->trust_ctime && check_stat &&
+	if (cfg->trust_ctime && cfg->check_stat &&
 	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
 		changed |= CTIME_CHANGED;
 #endif
 
-	if (check_stat) {
+	if (cfg->check_stat) {
 		if (sd->sd_uid != (unsigned int) st->st_uid ||
 			sd->sd_gid != (unsigned int) st->st_gid)
 			changed |= OWNER_CHANGED;
@@ -94,7 +94,7 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
 	 * clients will have different views of what "device"
 	 * the filesystem is on
 	 */
-	if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
+	if (cfg->check_stat && sd->sd_dev != (unsigned int) st->st_dev)
 			changed |= INODE_CHANGED;
 #endif
 
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 3/8] environment: move `zlib_compression_level` into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 2/8] environment: move "check_stat" " Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 4/8] environment: move "pack_compression_level" " Olamide Caleb Bello
                       ` (5 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `zlib_compression_level` configuration is currently stored in the
global variable `zlib_compression_level`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. `zlib_compression_level` is parsed
eagerly because it determines compression behaviour for objects and
packs – core operations where a lazy parse could lead to unpredictable
results and hinder libification. This preserves the existing
eager‑parsing behavior while tying the value to the repository it
was read from, avoiding cross‑repository state leakage and continuing
the effort to reduce reliance on global configuration state.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/index-pack.c | 3 ++-
 diff.c               | 3 ++-
 environment.c        | 6 +++---
 environment.h        | 2 +-
 http-push.c          | 3 ++-
 object-file.c        | 3 ++-
 6 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index ca7784dc2c..3942d3e0d0 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1416,8 +1416,9 @@ static int write_compressed(struct hashfile *f, void *in, unsigned int size)
 	git_zstream stream;
 	int status;
 	unsigned char outbuf[4096];
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	stream.next_in = in;
 	stream.avail_in = size;
 
diff --git a/diff.c b/diff.c
index 397e38b41c..7d17b0bf3f 100644
--- a/diff.c
+++ b/diff.c
@@ -3589,8 +3589,9 @@ static unsigned char *deflate_it(char *data,
 	int bound;
 	unsigned char *deflated;
 	git_zstream stream;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	bound = git_deflate_bound(&stream, size);
 	deflated = xmalloc(bound);
 	stream.next_out = deflated;
diff --git a/environment.c b/environment.c
index 8542ac3141..5b0e88b65c 100644
--- a/environment.c
+++ b/environment.c
@@ -52,7 +52,6 @@ char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
 char *apply_default_ignorewhitespace;
-int zlib_compression_level = Z_BEST_SPEED;
 int pack_compression_level = Z_DEFAULT_COMPRESSION;
 int fsync_object_files = -1;
 int use_fsync = -1;
@@ -377,7 +376,7 @@ int git_default_core_config(const char *var, const char *value,
 			level = Z_DEFAULT_COMPRESSION;
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad zlib compression level %d"), level);
-		zlib_compression_level = level;
+		cfg->zlib_compression_level = level;
 		zlib_compression_seen = 1;
 		return 0;
 	}
@@ -389,7 +388,7 @@ int git_default_core_config(const char *var, const char *value,
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad zlib compression level %d"), level);
 		if (!zlib_compression_seen)
-			zlib_compression_level = level;
+			cfg->zlib_compression_level = level;
 		if (!pack_compression_seen)
 			pack_compression_level = level;
 		return 0;
@@ -721,4 +720,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->branch_track = BRANCH_TRACK_REMOTE;
 	cfg->trust_ctime = 1;
 	cfg->check_stat = 1;
+	cfg->zlib_compression_level = Z_BEST_SPEED;
 }
diff --git a/environment.h b/environment.h
index 1d3e2e4f23..93201620af 100644
--- a/environment.h
+++ b/environment.h
@@ -93,6 +93,7 @@ struct repo_config_values {
 	int apply_sparse_checkout;
 	int trust_ctime;
 	int check_stat;
+	int zlib_compression_level;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -170,7 +171,6 @@ extern int assume_unchanged;
 extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
-extern int zlib_compression_level;
 extern int pack_compression_level;
 extern unsigned long pack_size_limit_cfg;
 
diff --git a/http-push.c b/http-push.c
index d143fe2845..8ac107a56e 100644
--- a/http-push.c
+++ b/http-push.c
@@ -369,13 +369,14 @@ static void start_put(struct transfer_request *request)
 	int hdrlen;
 	ssize_t size;
 	git_zstream stream;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	unpacked = odb_read_object(the_repository->objects, &request->obj->oid,
 				   &type, &len);
 	hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
 
 	/* Set it up */
-	git_deflate_init(&stream, zlib_compression_level);
+	git_deflate_init(&stream, cfg->zlib_compression_level);
 	size = git_deflate_bound(&stream, len + hdrlen);
 	strbuf_grow(&request->buffer.buf, size);
 	request->buffer.posn = 0;
diff --git a/object-file.c b/object-file.c
index 2acc9522df..7c122ac419 100644
--- a/object-file.c
+++ b/object-file.c
@@ -906,6 +906,7 @@ static int start_loose_object_common(struct odb_source *source,
 	const struct git_hash_algo *algo = source->odb->repo->hash_algo;
 	const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
 	int fd;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	fd = create_tmpfile(source->odb->repo, tmp_file, filename);
 	if (fd < 0) {
@@ -921,7 +922,7 @@ static int start_loose_object_common(struct odb_source *source,
 	}
 
 	/*  Setup zlib stream for compression */
-	git_deflate_init(stream, zlib_compression_level);
+	git_deflate_init(stream, cfg->zlib_compression_level);
 	stream->next_out = buf;
 	stream->avail_out = buflen;
 	algo->init_fn(c);
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 4/8] environment: move "pack_compression_level" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (2 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 3/8] environment: move `zlib_compression_level` " Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
                       ` (4 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `pack_compression_level` configuration is currently stored in the
global variable `pack_compression_level`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. `pack_compression_level` is parsed
eagerly because it influences packfile compression, a core operation
where a lazy parse could cause inconsistent behavior and hamper
libification. This preserves the existing eager‑parsing behavior while
tying the value to the repository from which it was read, avoiding
cross‑repository state leakage and continuing the effort to reduce
reliance on global configuration state.

The type remains `int` as it represents a numeric compression level,
not a boolean toggle.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/fast-import.c  |  8 +++++---
 builtin/pack-objects.c | 17 ++++++++++-------
 environment.c          |  8 +++++---
 environment.h          |  2 +-
 object-file.c          |  3 ++-
 5 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 82bc6dcc00..070a5af3e4 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -965,6 +965,7 @@ static int store_object(
 	unsigned long hdrlen, deltalen;
 	struct git_hash_ctx c;
 	git_zstream s;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	hdrlen = format_object_header((char *)hdr, sizeof(hdr), type,
 				      dat->len);
@@ -1005,7 +1006,7 @@ static int store_object(
 	} else
 		delta = NULL;
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 	if (delta) {
 		s.next_in = delta;
 		s.avail_in = deltalen;
@@ -1032,7 +1033,7 @@ static int store_object(
 		if (delta) {
 			FREE_AND_NULL(delta);
 
-			git_deflate_init(&s, pack_compression_level);
+			git_deflate_init(&s, cfg->pack_compression_level);
 			s.next_in = (void *)dat->buf;
 			s.avail_in = dat->len;
 			s.avail_out = git_deflate_bound(&s, s.avail_in);
@@ -1115,6 +1116,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 	struct git_hash_ctx c;
 	git_zstream s;
 	struct hashfile_checkpoint checkpoint;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int status = Z_OK;
 
 	/* Determine if we should auto-checkpoint. */
@@ -1134,7 +1136,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
 
 	crc32_begin(pack_file);
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 
 	hdrlen = encode_in_pack_object_header(out_buf, out_sz, OBJ_BLOB, len);
 
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index dd2480a73d..8ccbe7e178 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -386,8 +386,9 @@ static unsigned long do_compress(void **pptr, unsigned long size)
 	git_zstream stream;
 	void *in, *out;
 	unsigned long maxsize;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, pack_compression_level);
+	git_deflate_init(&stream, cfg->pack_compression_level);
 	maxsize = git_deflate_bound(&stream, size);
 
 	in = *pptr;
@@ -413,8 +414,9 @@ static unsigned long write_large_blob_data(struct odb_read_stream *st, struct ha
 	unsigned char ibuf[1024 * 16];
 	unsigned char obuf[1024 * 16];
 	unsigned long olen = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&stream, pack_compression_level);
+	git_deflate_init(&stream, cfg->pack_compression_level);
 
 	for (;;) {
 		ssize_t readlen;
@@ -5003,6 +5005,7 @@ int cmd_pack_objects(int argc,
 	struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
 	struct list_objects_filter_options filter_options =
 		LIST_OBJECTS_FILTER_INIT;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	struct option pack_objects_options[] = {
 		OPT_CALLBACK_F('q', "quiet", &progress, NULL,
@@ -5084,7 +5087,7 @@ int cmd_pack_objects(int argc,
 			 N_("ignore packs that have companion .keep file")),
 		OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
 				N_("ignore this pack")),
-		OPT_INTEGER(0, "compression", &pack_compression_level,
+		OPT_INTEGER(0, "compression", &cfg->pack_compression_level,
 			    N_("pack compression level")),
 		OPT_BOOL(0, "keep-true-parents", &grafts_keep_true_parents,
 			 N_("do not hide commits by grafts")),
@@ -5243,10 +5246,10 @@ int cmd_pack_objects(int argc,
 
 	if (!reuse_object)
 		reuse_delta = 0;
-	if (pack_compression_level == -1)
-		pack_compression_level = Z_DEFAULT_COMPRESSION;
-	else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)
-		die(_("bad pack compression level %d"), pack_compression_level);
+	if (cfg->pack_compression_level == -1)
+		cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
+	else if (cfg->pack_compression_level < 0 || cfg->pack_compression_level > Z_BEST_COMPRESSION)
+		die(_("bad pack compression level %d"), cfg->pack_compression_level);
 
 	if (!delta_search_threads)	/* --threads=0 means autodetect */
 		delta_search_threads = online_cpus();
diff --git a/environment.c b/environment.c
index 5b0e88b65c..d0d3a4b7d2 100644
--- a/environment.c
+++ b/environment.c
@@ -52,7 +52,6 @@ char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
 char *apply_default_ignorewhitespace;
-int pack_compression_level = Z_DEFAULT_COMPRESSION;
 int fsync_object_files = -1;
 int use_fsync = -1;
 enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
@@ -390,7 +389,7 @@ int git_default_core_config(const char *var, const char *value,
 		if (!zlib_compression_seen)
 			cfg->zlib_compression_level = level;
 		if (!pack_compression_seen)
-			pack_compression_level = level;
+			cfg->pack_compression_level = level;
 		return 0;
 	}
 
@@ -662,6 +661,8 @@ static int git_default_attr_config(const char *var, const char *value)
 int git_default_config(const char *var, const char *value,
 		       const struct config_context *ctx, void *cb)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (starts_with(var, "core."))
 		return git_default_core_config(var, value, ctx, cb);
 
@@ -701,7 +702,7 @@ int git_default_config(const char *var, const char *value,
 			level = Z_DEFAULT_COMPRESSION;
 		else if (level < 0 || level > Z_BEST_COMPRESSION)
 			die(_("bad pack compression level %d"), level);
-		pack_compression_level = level;
+		cfg->pack_compression_level = level;
 		pack_compression_seen = 1;
 		return 0;
 	}
@@ -721,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->trust_ctime = 1;
 	cfg->check_stat = 1;
 	cfg->zlib_compression_level = Z_BEST_SPEED;
+	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 }
diff --git a/environment.h b/environment.h
index 93201620af..514576b67a 100644
--- a/environment.h
+++ b/environment.h
@@ -94,6 +94,7 @@ struct repo_config_values {
 	int trust_ctime;
 	int check_stat;
 	int zlib_compression_level;
+	int pack_compression_level;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -171,7 +172,6 @@ extern int assume_unchanged;
 extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
-extern int pack_compression_level;
 extern unsigned long pack_size_limit_cfg;
 
 extern int precomposed_unicode;
diff --git a/object-file.c b/object-file.c
index 7c122ac419..37def5cc59 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1437,8 +1437,9 @@ static int stream_blob_to_pack(struct transaction_packfile *state,
 	int status = Z_OK;
 	int write_object = (flags & INDEX_WRITE_OBJECT);
 	off_t offset = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	git_deflate_init(&s, pack_compression_level);
+	git_deflate_init(&s, cfg->pack_compression_level);
 
 	hdrlen = encode_in_pack_object_header(obuf, sizeof(obuf), OBJ_BLOB, size);
 	s.next_out = obuf + hdrlen;
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 5/8] environment: move "precomposed_unicode" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (3 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 4/8] environment: move "pack_compression_level" " Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-05-15 17:15       ` Tian Yuchen
  2026-04-23 16:54     ` [PATCH v3 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
                       ` (3 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.precomposeunicode` configuration is currently stored in the
global variable `precomposed_unicode`, which makes it shared across
repository instances within a single process.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. `core.precomposeunicode` is parsed
eagerly because it controls Unicode path normalization on macOS,
a fundamental filesystem‑level behavior that many operations depend
on; a lazy parse could lead to inconsistent results and hamper
libification. This preserves the existing behavior while tying the
value to the repository from which it was read, avoiding cross‑
repository state leakage and continuing the effort to reduce reliance
on global configuration state.

Change the type of the field from `int` to `bool` since it is parsed
as a boolean value.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 compat/precompose_utf8.c | 20 +++++++++++++-------
 environment.c            |  4 ++--
 environment.h            |  2 +-
 upload-pack.c            |  3 ++-
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 43b3be0114..0e94dbd862 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -48,16 +48,18 @@ void probe_utf8_pathname_composition(void)
 	static const char *auml_nfc = "\xc3\xa4";
 	static const char *auml_nfd = "\x61\xcc\x88";
 	int output_fd;
-	if (precomposed_unicode != -1)
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
+	if (cfg->precomposed_unicode != -1)
 		return; /* We found it defined in the global config, respect it */
 	repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
 	output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600);
 	if (output_fd >= 0) {
 		close(output_fd);
 		repo_git_path_replace(the_repository, &path, "%s", auml_nfd);
-		precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
+		cfg->precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
 		repo_config_set(the_repository, "core.precomposeunicode",
-				precomposed_unicode ? "true" : "false");
+				cfg->precomposed_unicode ? "true" : "false");
 		repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
 		if (unlink(path.buf))
 			die_errno(_("failed to unlink '%s'"), path.buf);
@@ -69,14 +71,16 @@ const char *precompose_string_if_needed(const char *in)
 {
 	size_t inlen;
 	size_t outlen;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (!in)
 		return NULL;
 	if (has_non_ascii(in, (size_t)-1, &inlen)) {
 		iconv_t ic_prec;
 		char *out;
-		if (precomposed_unicode < 0)
-			repo_config_get_bool(the_repository, "core.precomposeunicode", &precomposed_unicode);
-		if (precomposed_unicode != 1)
+		if (cfg->precomposed_unicode < 0)
+			repo_config_get_bool(the_repository, "core.precomposeunicode", &cfg->precomposed_unicode);
+		if (cfg->precomposed_unicode != 1)
 			return in;
 		ic_prec = iconv_open(repo_encoding, path_encoding);
 		if (ic_prec == (iconv_t) -1)
@@ -130,7 +134,9 @@ PREC_DIR *precompose_utf8_opendir(const char *dirname)
 
 struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	struct dirent *res;
+
 	res = readdir(prec_dir->dirp);
 	if (res) {
 		size_t namelenz = strlen(res->d_name) + 1; /* \0 */
@@ -149,7 +155,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
 		prec_dir->dirent_nfc->d_ino  = res->d_ino;
 		prec_dir->dirent_nfc->d_type = res->d_type;
 
-		if ((precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
+		if ((cfg->precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
 			if (prec_dir->ic_precompose == (iconv_t)-1) {
 				die("iconv_open(%s,%s) failed, but needed:\n"
 						"    precomposed unicode is not supported.\n"
diff --git a/environment.c b/environment.c
index d0d3a4b7d2..739b647ebe 100644
--- a/environment.c
+++ b/environment.c
@@ -72,7 +72,6 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
 int core_sparse_checkout_cone;
 int sparse_expect_files_outside_of_patterns;
-int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 unsigned long pack_size_limit_cfg;
 
 #ifndef PROTECT_HFS_DEFAULT
@@ -532,7 +531,7 @@ int git_default_core_config(const char *var, const char *value,
 	}
 
 	if (!strcmp(var, "core.precomposeunicode")) {
-		precomposed_unicode = git_config_bool(var, value);
+		cfg->precomposed_unicode = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->check_stat = 1;
 	cfg->zlib_compression_level = Z_BEST_SPEED;
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
+	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 }
diff --git a/environment.h b/environment.h
index 514576b67a..508cb1afbc 100644
--- a/environment.h
+++ b/environment.h
@@ -95,6 +95,7 @@ struct repo_config_values {
 	int check_stat;
 	int zlib_compression_level;
 	int pack_compression_level;
+	int precomposed_unicode;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -174,7 +175,6 @@ extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
 extern unsigned long pack_size_limit_cfg;
 
-extern int precomposed_unicode;
 extern int protect_hfs;
 extern int protect_ntfs;
 
diff --git a/upload-pack.c b/upload-pack.c
index 9f6d6fe48c..3a52237134 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1336,6 +1336,7 @@ static int upload_pack_config(const char *var, const char *value,
 			      void *cb_data)
 {
 	struct upload_pack_data *data = cb_data;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
 		if (git_config_bool(var, value))
@@ -1366,7 +1367,7 @@ static int upload_pack_config(const char *var, const char *value,
 		if (value)
 			data->allow_packfile_uris = 1;
 	} else if (!strcmp("core.precomposeunicode", var)) {
-		precomposed_unicode = git_config_bool(var, value);
+		cfg->precomposed_unicode = git_config_bool(var, value);
 	} else if (!strcmp("transfer.advertisesid", var)) {
 		data->advertise_sid = git_config_bool(var, value);
 	}
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 6/8] env: move "core_sparse_checkout_cone" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (4 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 7/8] env: move "sparse_expect_files_outside_of_patterns" into `repo_config_values` Olamide Caleb Bello
                       ` (2 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.sparseCheckoutCone` configuration was previously stored in an
uninitialized global `int` variable, risking cross‑repository state
leakage.

Move it into `repo_config_values`, where eagerly‑parsed repository
configuration lives. `core.sparseCheckoutCone` is parsed eagerly
because it determines the fundamental sparse‑checkout mode and is
consulted very early during repository setup; a lazy parse could
leave the sparse‑checkout state undefined and complicate
libification. This preserves the existing behavior while tying the
value to the repository from which it was read, avoiding cross‑
repository state leakage and continuing the effort to reduce reliance
on global configuration state.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/mv.c              |  2 +-
 builtin/sparse-checkout.c | 37 ++++++++++++++++++++++---------------
 dir.c                     |  3 ++-
 environment.c             |  4 ++--
 environment.h             |  2 +-
 sparse-index.c            |  2 +-
 6 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/builtin/mv.c b/builtin/mv.c
index 2215d34e31..ef3a326c90 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -574,7 +574,7 @@ int cmd_mv(int argc,
 
 		if (ignore_sparse &&
 		    cfg->apply_sparse_checkout &&
-		    core_sparse_checkout_cone) {
+		    cfg->core_sparse_checkout_cone) {
 			/*
 			 * NEEDSWORK: we are *not* paying attention to
 			 * "out-to-out" move (<source> is out-of-cone and
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index f4aa405da9..92d017b81f 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -73,7 +73,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
 
 	memset(&pl, 0, sizeof(pl));
 
-	pl.use_cone_patterns = core_sparse_checkout_cone;
+	pl.use_cone_patterns = cfg->core_sparse_checkout_cone;
 
 	sparse_filename = get_sparse_checkout_filename();
 	res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0);
@@ -334,6 +334,7 @@ static int write_patterns_and_update(struct repository *repo,
 	FILE *fp;
 	struct lock_file lk = LOCK_INIT;
 	int result;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	sparse_filename = get_sparse_checkout_filename();
 
@@ -353,7 +354,7 @@ static int write_patterns_and_update(struct repository *repo,
 	if (!fp)
 		die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk));
 
-	if (core_sparse_checkout_cone)
+	if (cfg->core_sparse_checkout_cone)
 		write_cone_to_file(fp, pl);
 	else
 		write_patterns_to_file(fp, pl);
@@ -402,15 +403,15 @@ static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
 
 	/* If not specified, use previous definition of cone mode */
 	if (*cone_mode == -1 && cfg->apply_sparse_checkout)
-		*cone_mode = core_sparse_checkout_cone;
+		*cone_mode = cfg->core_sparse_checkout_cone;
 
 	/* Set cone/non-cone mode appropriately */
 	cfg->apply_sparse_checkout = 1;
 	if (*cone_mode == 1 || *cone_mode == -1) {
-		core_sparse_checkout_cone = 1;
+		cfg->core_sparse_checkout_cone = 1;
 		return MODE_CONE_PATTERNS;
 	}
-	core_sparse_checkout_cone = 0;
+	cfg->core_sparse_checkout_cone = 0;
 	return MODE_ALL_PATTERNS;
 }
 
@@ -577,7 +578,9 @@ static void add_patterns_from_input(struct pattern_list *pl,
 				    FILE *file)
 {
 	int i;
-	if (core_sparse_checkout_cone) {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
+	if (cfg->core_sparse_checkout_cone) {
 		struct strbuf line = STRBUF_INIT;
 
 		hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);
@@ -636,13 +639,14 @@ static void add_patterns_cone_mode(int argc, const char **argv,
 	struct pattern_entry *pe;
 	struct hashmap_iter iter;
 	struct pattern_list existing;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char *sparse_filename = get_sparse_checkout_filename();
 
 	add_patterns_from_input(pl, argc, argv,
 				use_stdin ? stdin : NULL);
 
 	memset(&existing, 0, sizeof(existing));
-	existing.use_cone_patterns = core_sparse_checkout_cone;
+	existing.use_cone_patterns = cfg->core_sparse_checkout_cone;
 
 	if (add_patterns_from_file_to_list(sparse_filename, "", 0,
 					   &existing, NULL, 0))
@@ -690,7 +694,7 @@ static int modify_pattern_list(struct repository *repo,
 
 	switch (m) {
 	case ADD:
-		if (core_sparse_checkout_cone)
+		if (cfg->core_sparse_checkout_cone)
 			add_patterns_cone_mode(args->nr, args->v, pl, use_stdin);
 		else
 			add_patterns_literal(args->nr, args->v, pl, use_stdin);
@@ -723,11 +727,12 @@ static void sanitize_paths(struct repository *repo,
 			   const char *prefix, int skip_checks)
 {
 	int i;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!args->nr)
 		return;
 
-	if (prefix && *prefix && core_sparse_checkout_cone) {
+	if (prefix && *prefix && cfg->core_sparse_checkout_cone) {
 		/*
 		 * The args are not pathspecs, so unfortunately we
 		 * cannot imitate how cmd_add() uses parse_pathspec().
@@ -744,10 +749,10 @@ static void sanitize_paths(struct repository *repo,
 	if (skip_checks)
 		return;
 
-	if (prefix && *prefix && !core_sparse_checkout_cone)
+	if (prefix && *prefix && !cfg->core_sparse_checkout_cone)
 		die(_("please run from the toplevel directory in non-cone mode"));
 
-	if (core_sparse_checkout_cone) {
+	if (cfg->core_sparse_checkout_cone) {
 		for (i = 0; i < args->nr; i++) {
 			if (args->v[i][0] == '/')
 				die(_("specify directories rather than patterns (no leading slash)"));
@@ -769,7 +774,7 @@ static void sanitize_paths(struct repository *repo,
 		if (S_ISSPARSEDIR(ce->ce_mode))
 			continue;
 
-		if (core_sparse_checkout_cone)
+		if (cfg->core_sparse_checkout_cone)
 			die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), args->v[i]);
 		else
 			warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), args->v[i]);
@@ -836,6 +841,7 @@ static struct sparse_checkout_set_opts {
 static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 			       struct repository *repo)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int default_patterns_nr = 2;
 	const char *default_patterns[] = {"/*", "!/*/", NULL};
 
@@ -873,7 +879,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
 	 * non-cone mode, if nothing is specified, manually select just the
 	 * top-level directory (much as 'init' would do).
 	 */
-	if (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {
+	if (!cfg->core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {
 		for (int i = 0; i < default_patterns_nr; i++)
 			strvec_push(&patterns, default_patterns[i]);
 	} else {
@@ -977,7 +983,7 @@ static int sparse_checkout_clean(int argc, const char **argv,
 	setup_work_tree();
 	if (!cfg->apply_sparse_checkout)
 		die(_("must be in a sparse-checkout to clean directories"));
-	if (!core_sparse_checkout_cone)
+	if (!cfg->core_sparse_checkout_cone)
 		die(_("must be in a cone-mode sparse-checkout to clean directories"));
 
 	argc = parse_options(argc, argv, prefix,
@@ -1141,6 +1147,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
 	FILE *fp;
 	int ret;
 	struct pattern_list pl = {0};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char *sparse_filename;
 	check_rules_opts.cone_mode = -1;
 
@@ -1152,7 +1159,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
 		check_rules_opts.cone_mode = 1;
 
 	update_cone_mode(&check_rules_opts.cone_mode);
-	pl.use_cone_patterns = core_sparse_checkout_cone;
+	pl.use_cone_patterns = cfg->core_sparse_checkout_cone;
 	if (check_rules_opts.rules_file) {
 		fp = xfopen(check_rules_opts.rules_file, "r");
 		add_patterns_from_input(&pl, argc, argv, fp);
diff --git a/dir.c b/dir.c
index fcb8f6dd2a..4f493b64c6 100644
--- a/dir.c
+++ b/dir.c
@@ -3508,8 +3508,9 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)
 {
 	int res;
 	char *sparse_filename = get_sparse_checkout_filename();
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	pl->use_cone_patterns = core_sparse_checkout_cone;
+	pl->use_cone_patterns = cfg->core_sparse_checkout_cone;
 	res = add_patterns_from_file_to_list(sparse_filename, "", 0, pl, NULL, 0);
 
 	free(sparse_filename);
diff --git a/environment.c b/environment.c
index 739b647ebe..b0e873e9f5 100644
--- a/environment.c
+++ b/environment.c
@@ -70,7 +70,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 #endif
 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
-int core_sparse_checkout_cone;
 int sparse_expect_files_outside_of_patterns;
 unsigned long pack_size_limit_cfg;
 
@@ -526,7 +525,7 @@ int git_default_core_config(const char *var, const char *value,
 	}
 
 	if (!strcmp(var, "core.sparsecheckoutcone")) {
-		core_sparse_checkout_cone = git_config_bool(var, value);
+		cfg->core_sparse_checkout_cone = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +722,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->zlib_compression_level = Z_BEST_SPEED;
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
+	cfg->core_sparse_checkout_cone = 0;
 }
diff --git a/environment.h b/environment.h
index 508cb1afbc..befad9a388 100644
--- a/environment.h
+++ b/environment.h
@@ -96,6 +96,7 @@ struct repo_config_values {
 	int zlib_compression_level;
 	int pack_compression_level;
 	int precomposed_unicode;
+	int core_sparse_checkout_cone;
 
 	/* section "branch" config values */
 	enum branch_track branch_track;
@@ -178,7 +179,6 @@ extern unsigned long pack_size_limit_cfg;
 extern int protect_hfs;
 extern int protect_ntfs;
 
-extern int core_sparse_checkout_cone;
 extern int sparse_expect_files_outside_of_patterns;
 
 enum rebase_setup_type {
diff --git a/sparse-index.c b/sparse-index.c
index 13629c075d..53cb8d64fc 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -154,7 +154,7 @@ int is_sparse_index_allowed(struct index_state *istate, int flags)
 {
 	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)
+	if (!cfg->apply_sparse_checkout || !cfg->core_sparse_checkout_cone)
 		return 0;
 
 	if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 7/8] env: move "sparse_expect_files_outside_of_patterns" into `repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (5 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-23 16:54     ` [PATCH v3 8/8] env: move "warn_on_object_refname_ambiguity" into `struct repo_config_values` Olamide Caleb Bello
  2026-04-26  0:01     ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Junio C Hamano
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.sparseCheckoutExpectFilesOutsideOfPatterns` configuration was
previously stored in a global `int` variable, making it shared across
repository instances and risking cross‑repository state leakage.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. This option is parsed eagerly because
it controls how sparse‑checkout paths are interpreted – a fundamental
behavior that many commands rely on; a lazy parse could cause
inconsistent sparse‑checkout handling and complicate libification.
This preserves the existing behavior while tying the value to the
repository from which it was read, avoiding cross‑repository state
leakage and continuing the effort to reduce reliance on global
configuration state.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 environment.c  | 6 ++++--
 environment.h  | 5 +++--
 sparse-index.c | 2 +-
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/environment.c b/environment.c
index b0e873e9f5..57587ede56 100644
--- a/environment.c
+++ b/environment.c
@@ -70,7 +70,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 #endif
 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 int grafts_keep_true_parents;
-int sparse_expect_files_outside_of_patterns;
 unsigned long pack_size_limit_cfg;
 
 #ifndef PROTECT_HFS_DEFAULT
@@ -550,8 +549,10 @@ int git_default_core_config(const char *var, const char *value,
 
 static int git_default_sparse_config(const char *var, const char *value)
 {
+	struct repo_config_values *cfg = repo_config_values(the_repository);
+
 	if (!strcmp(var, "sparse.expectfilesoutsideofpatterns")) {
-		sparse_expect_files_outside_of_patterns = git_config_bool(var, value);
+		cfg->sparse_expect_files_outside_of_patterns = git_config_bool(var, value);
 		return 0;
 	}
 
@@ -723,4 +724,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 	cfg->core_sparse_checkout_cone = 0;
+	cfg->sparse_expect_files_outside_of_patterns = 0;
 }
diff --git a/environment.h b/environment.h
index befad9a388..609cdaa07f 100644
--- a/environment.h
+++ b/environment.h
@@ -98,6 +98,9 @@ struct repo_config_values {
 	int precomposed_unicode;
 	int core_sparse_checkout_cone;
 
+	/* section "sparse" config values */
+	int sparse_expect_files_outside_of_patterns;
+
 	/* section "branch" config values */
 	enum branch_track branch_track;
 };
@@ -179,8 +182,6 @@ extern unsigned long pack_size_limit_cfg;
 extern int protect_hfs;
 extern int protect_ntfs;
 
-extern int sparse_expect_files_outside_of_patterns;
-
 enum rebase_setup_type {
 	AUTOREBASE_NEVER = 0,
 	AUTOREBASE_LOCAL,
diff --git a/sparse-index.c b/sparse-index.c
index 53cb8d64fc..1ed769b78d 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -675,7 +675,7 @@ void clear_skip_worktree_from_present_files(struct index_state *istate)
 	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (!cfg->apply_sparse_checkout ||
-	    sparse_expect_files_outside_of_patterns)
+	    cfg->sparse_expect_files_outside_of_patterns)
 		return;
 
 	if (clear_skip_worktree_from_present_files_sparse(istate)) {
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v3 8/8] env: move "warn_on_object_refname_ambiguity" into `struct repo_config_values`
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (6 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 7/8] env: move "sparse_expect_files_outside_of_patterns" into `repo_config_values` Olamide Caleb Bello
@ 2026-04-23 16:54     ` Olamide Caleb Bello
  2026-04-26  0:01     ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Junio C Hamano
  8 siblings, 0 replies; 44+ messages in thread
From: Olamide Caleb Bello @ 2026-04-23 16:54 UTC (permalink / raw)
  To: git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me, Olamide Caleb Bello

The `core.warnAmbiguousRefs` configuration was previously stored in a
global `int` variable, making it shared across repository instances
and risking cross‑repository state leakage.

Store it instead in `repo_config_values`, where eagerly‑parsed
repository configuration lives. This option is parsed eagerly because
ambiguity warnings influence how users interpret object references in
many commands; a lazy parse could cause these warnings to behave
inconsistently or to appear for the wrong repository, confusing users
and hindering libification. This preserves the existing behavior while
tying the value to the repository from which it was read, avoiding
cross‑repository state leakage and continuing the effort to reduce
reliance on global configuration state.

Update all references to use `repo_config_values()`.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
---
 builtin/cat-file.c     | 7 ++++---
 builtin/pack-objects.c | 7 ++++---
 environment.c          | 2 +-
 environment.h          | 2 +-
 object-name.c          | 3 ++-
 revision.c             | 7 ++++---
 submodule.c            | 7 ++++---
 7 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index d9fbad5358..cfc5430186 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -901,6 +901,7 @@ static int batch_objects(struct batch_options *opt)
 	struct strbuf input = STRBUF_INIT;
 	struct strbuf output = STRBUF_INIT;
 	struct expand_data data = EXPAND_DATA_INIT;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	int save_warning;
 	int retval = 0;
 
@@ -973,8 +974,8 @@ static int batch_objects(struct batch_options *opt)
 	 * warn) ends up dwarfing the actual cost of the object lookups
 	 * themselves. We can work around it by just turning off the warning.
 	 */
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	if (opt->batch_mode == BATCH_MODE_QUEUE_AND_DISPATCH) {
 		batch_objects_command(opt, &output, &data);
@@ -1002,7 +1003,7 @@ static int batch_objects(struct batch_options *opt)
  cleanup:
 	strbuf_release(&input);
 	strbuf_release(&output);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 	return retval;
 }
 
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 8ccbe7e178..7df75fe91e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4788,6 +4788,7 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 	struct setup_revision_opt s_r_opt = {
 		.allow_exclude_promisor_objects = 1,
 	};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 	char line[1000];
 	int flags = 0;
 	int save_warning;
@@ -4798,8 +4799,8 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 	/* make sure shallows are read */
 	is_repository_shallow(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	while (fgets(line, sizeof(line), stdin) != NULL) {
 		int len = strlen(line);
@@ -4827,7 +4828,7 @@ static void get_object_list(struct rev_info *revs, struct strvec *argv)
 			die(_("bad revision '%s'"), line);
 	}
 
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 
 	if (use_bitmap_index && !get_object_list_from_bitmap(revs))
 		return;
diff --git a/environment.c b/environment.c
index 57587ede56..ba2c60103f 100644
--- a/environment.c
+++ b/environment.c
@@ -47,7 +47,6 @@ int minimum_abbrev = 4, default_abbrev = -1;
 int ignore_case;
 int assume_unchanged;
 int is_bare_repository_cfg = -1; /* unspecified */
-int warn_on_object_refname_ambiguity = 1;
 char *git_commit_encoding;
 char *git_log_output_encoding;
 char *apply_default_whitespace;
@@ -725,4 +724,5 @@ void repo_config_values_init(struct repo_config_values *cfg)
 	cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 	cfg->core_sparse_checkout_cone = 0;
 	cfg->sparse_expect_files_outside_of_patterns = 0;
+	cfg->warn_on_object_refname_ambiguity = 1;
 }
diff --git a/environment.h b/environment.h
index 609cdaa07f..1ff0a7ba8b 100644
--- a/environment.h
+++ b/environment.h
@@ -97,6 +97,7 @@ struct repo_config_values {
 	int pack_compression_level;
 	int precomposed_unicode;
 	int core_sparse_checkout_cone;
+	int warn_on_object_refname_ambiguity;
 
 	/* section "sparse" config values */
 	int sparse_expect_files_outside_of_patterns;
@@ -174,7 +175,6 @@ extern int has_symlinks;
 extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
 extern int assume_unchanged;
-extern int warn_on_object_refname_ambiguity;
 extern char *apply_default_whitespace;
 extern char *apply_default_ignorewhitespace;
 extern unsigned long pack_size_limit_cfg;
diff --git a/object-name.c b/object-name.c
index 21dcdc4a0e..319d3db01d 100644
--- a/object-name.c
+++ b/object-name.c
@@ -684,11 +684,12 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
 	int refs_found = 0;
 	int at, reflog_len, nth_prior = 0;
 	int fatal = !(flags & GET_OID_QUIETLY);
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
 	if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
 		if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) &&
 		    repo_settings_get_warn_ambiguous_refs(r) &&
-		    warn_on_object_refname_ambiguity) {
+		    cfg->warn_on_object_refname_ambiguity) {
 			refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
 			if (refs_found > 0) {
 				warning(warn_msg, len, str);
diff --git a/revision.c b/revision.c
index 599b3a66c3..4e7faa7eb1 100644
--- a/revision.c
+++ b/revision.c
@@ -2922,9 +2922,10 @@ static void read_revisions_from_stdin(struct rev_info *revs,
 	int seen_end_of_options = 0;
 	int save_warning;
 	int flags = 0;
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 
 	strbuf_init(&sb, 1000);
 	while (strbuf_getline(&sb, stdin) != EOF) {
@@ -2958,7 +2959,7 @@ static void read_revisions_from_stdin(struct rev_info *revs,
 		read_pathspec_from_stdin(&sb, prune);
 
 	strbuf_release(&sb);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 }
 
 static void NORETURN diagnose_missing_default(const char *def)
diff --git a/submodule.c b/submodule.c
index b1a0363f9d..f26235bbb7 100644
--- a/submodule.c
+++ b/submodule.c
@@ -898,12 +898,13 @@ static void collect_changed_submodules(struct repository *r,
 	struct setup_revision_opt s_r_opt = {
 		.assume_dashdash = 1,
 	};
+	struct repo_config_values *cfg = repo_config_values(the_repository);
 
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
+	save_warning = cfg->warn_on_object_refname_ambiguity;
+	cfg->warn_on_object_refname_ambiguity = 0;
 	repo_init_revisions(r, &rev, NULL);
 	setup_revisions_from_strvec(argv, &rev, &s_r_opt);
-	warn_on_object_refname_ambiguity = save_warning;
+	cfg->warn_on_object_refname_ambiguity = save_warning;
 	if (prepare_revision_walk(&rev))
 		die(_("revision walk setup failed"));
 
-- 
2.53.0.155.g9f36b15afa


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 0/8] environment: move core config globals into repo_config_values
  2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
                       ` (7 preceding siblings ...)
  2026-04-23 16:54     ` [PATCH v3 8/8] env: move "warn_on_object_refname_ambiguity" into `struct repo_config_values` Olamide Caleb Bello
@ 2026-04-26  0:01     ` Junio C Hamano
  2026-04-26  0:31       ` Bello Olamide
  8 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2026-04-26  0:01 UTC (permalink / raw)
  To: Olamide Caleb Bello
  Cc: git, phillip.wood123, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

Olamide Caleb Bello <belkid98@gmail.com> writes:

> Olamide Caleb Bello (8):
>   environment: move "trust_ctime" into `struct repo_config_values`
>   environment: move "check_stat" into `struct repo_config_values`
>   environment: move `zlib_compression_level` into `struct
>     repo_config_values`
>   environment: move "pack_compression_level" into `struct
>     repo_config_values`
>   environment: move "precomposed_unicode" into `struct
>     repo_config_values`
>   env: move "core_sparse_checkout_cone" into `struct repo_config_values`
>   env: move "sparse_expect_files_outside_of_patterns" into
>     `repo_config_values`
>   env: move "warn_on_object_refname_ambiguity" into `struct
>     repo_config_values`

Are there differences between the ones that start with "environment:"
vs the ones with "env:"?

>
>  builtin/cat-file.c        |  7 ++++---
>  builtin/fast-import.c     |  8 +++++---
>  builtin/index-pack.c      |  3 ++-
>  builtin/mv.c              |  2 +-
>  builtin/pack-objects.c    | 24 +++++++++++++----------
>  builtin/sparse-checkout.c | 37 +++++++++++++++++++++---------------
>  compat/precompose_utf8.c  | 20 +++++++++++++-------
>  diff.c                    |  3 ++-
>  dir.c                     |  3 ++-
>  entry.c                   |  3 ++-
>  environment.c             | 40 +++++++++++++++++++++------------------
>  environment.h             | 19 ++++++++++---------
>  http-push.c               |  3 ++-
>  object-file.c             |  6 ++++--
>  object-name.c             |  3 ++-
>  revision.c                |  7 ++++---
>  sparse-index.c            |  4 ++--
>  statinfo.c                | 12 +++++++-----
>  submodule.c               |  7 ++++---
>  upload-pack.c             |  3 ++-
>  20 files changed, 126 insertions(+), 88 deletions(-)

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 0/8] environment: move core config globals into repo_config_values
  2026-04-26  0:01     ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Junio C Hamano
@ 2026-04-26  0:31       ` Bello Olamide
  2026-05-11  2:56         ` Junio C Hamano
  0 siblings, 1 reply; 44+ messages in thread
From: Bello Olamide @ 2026-04-26  0:31 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, phillip.wood123, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

On Sun, 26 Apr 2026 at 01:02, Junio C Hamano <gitster@pobox.com> wrote:
>
> Olamide Caleb Bello <belkid98@gmail.com> writes:
>
> > Olamide Caleb Bello (8):
> >   environment: move "trust_ctime" into `struct repo_config_values`
> >   environment: move "check_stat" into `struct repo_config_values`
> >   environment: move `zlib_compression_level` into `struct
> >     repo_config_values`
> >   environment: move "pack_compression_level" into `struct
> >     repo_config_values`
> >   environment: move "precomposed_unicode" into `struct
> >     repo_config_values`
> >   env: move "core_sparse_checkout_cone" into `struct repo_config_values`
> >   env: move "sparse_expect_files_outside_of_patterns" into
> >     `repo_config_values`
> >   env: move "warn_on_object_refname_ambiguity" into `struct
> >     repo_config_values`
>
> Are there differences between the ones that start with "environment:"
> vs the ones with "env:"?
>
Hi Junio,

There isn’t any semantic difference intended between
the "environment:" and "env:" prefixes

I shortened some of them to stay within the recommended subject length,
but on a second thought I agree that consistency is more important here.

I’ll standardize them in the next revision.
Thanks.
> >
> >  builtin/cat-file.c        |  7 ++++---
> >  builtin/fast-import.c     |  8 +++++---
> >  builtin/index-pack.c      |  3 ++-
> >  builtin/mv.c              |  2 +-
> >  builtin/pack-objects.c    | 24 +++++++++++++----------
> >  builtin/sparse-checkout.c | 37 +++++++++++++++++++++---------------
> >  compat/precompose_utf8.c  | 20 +++++++++++++-------
> >  diff.c                    |  3 ++-
> >  dir.c                     |  3 ++-
> >  entry.c                   |  3 ++-
> >  environment.c             | 40 +++++++++++++++++++++------------------
> >  environment.h             | 19 ++++++++++---------
> >  http-push.c               |  3 ++-
> >  object-file.c             |  6 ++++--
> >  object-name.c             |  3 ++-
> >  revision.c                |  7 ++++---
> >  sparse-index.c            |  4 ++--
> >  statinfo.c                | 12 +++++++-----
> >  submodule.c               |  7 ++++---
> >  upload-pack.c             |  3 ++-
> >  20 files changed, 126 insertions(+), 88 deletions(-)

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 0/8] environment: move core config globals into repo_config_values
  2026-04-26  0:31       ` Bello Olamide
@ 2026-05-11  2:56         ` Junio C Hamano
  0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2026-05-11  2:56 UTC (permalink / raw)
  To: Bello Olamide
  Cc: git, phillip.wood123, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

Bello Olamide <belkid98@gmail.com> writes:

> On Sun, 26 Apr 2026 at 01:02, Junio C Hamano <gitster@pobox.com> wrote:
>>
>> Olamide Caleb Bello <belkid98@gmail.com> writes:
>>
>> > Olamide Caleb Bello (8):
>> >   environment: move "trust_ctime" into `struct repo_config_values`
>> >   environment: move "check_stat" into `struct repo_config_values`
>> >   environment: move `zlib_compression_level` into `struct
>> >     repo_config_values`
>> >   environment: move "pack_compression_level" into `struct
>> >     repo_config_values`
>> >   environment: move "precomposed_unicode" into `struct
>> >     repo_config_values`
>> >   env: move "core_sparse_checkout_cone" into `struct repo_config_values`
>> >   env: move "sparse_expect_files_outside_of_patterns" into
>> >     `repo_config_values`
>> >   env: move "warn_on_object_refname_ambiguity" into `struct
>> >     repo_config_values`
>>
>> Are there differences between the ones that start with "environment:"
>> vs the ones with "env:"?
>>
> Hi Junio,
>
> There isn’t any semantic difference intended between
> the "environment:" and "env:" prefixes
>
> I shortened some of them to stay within the recommended subject length,
> but on a second thought I agree that consistency is more important here.
>
> I’ll standardize them in the next revision.

Does anybody listed on the CC: in the original submission have any
comments on this round?  It seems that v2 iteration was commented on
quite a bit, but has anybody checked the latest iteration since it
was posted?

Thanks.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v3 5/8] environment: move "precomposed_unicode" into `struct repo_config_values`
  2026-04-23 16:54     ` [PATCH v3 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
@ 2026-05-15 17:15       ` Tian Yuchen
  0 siblings, 0 replies; 44+ messages in thread
From: Tian Yuchen @ 2026-05-15 17:15 UTC (permalink / raw)
  To: Olamide Caleb Bello, git
  Cc: phillip.wood123, gitster, christian.couder, usmanakinyemi202,
	kaartic.sivaraam, me

On 4/24/26 00:54, Olamide Caleb Bello wrote:
>   struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
>   {
> +	struct repo_config_values *cfg = repo_config_values(the_repository);
>   	struct dirent *res;
> +
>   	res = readdir(prec_dir->dirp);
>   	if (res) {
>   		size_t namelenz = strlen(res->d_name) + 1; /* \0 */
This 'precompose_utf8_readdir()' appears to be a wrapper for 
'readdir()', so that Git thinks it is calling a standard POSIX function. 
Looking at it this way, I feel the architectural design here is a bit 
ambiguous. I think the role of 'readdir()' (or its wrapper) should be: 
"You give me a directory handle, and I give you a file entry". 
Conceptually, it shouldn’t even be related to Git: you can take a look 
at the rest of code of this wrapper.

Since there is a wrapper for 'readdir()', there must also be one for 
'opendir()'. To me, initializing a flag like 'perform_precompose' when 
the PREC_DIR handle is created in 'opendir()' , and pass it down through 
the handle looks a bit more optimal. In other words, If one of them has 
to handle the repo pointer, I think it would be better to leave that to 
'opendir()' ;)

Good night, yuchen

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2026-05-15 17:15 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-24 12:37 [PATCH v2 0/8] repo_config_values: migrate more globals Olamide Caleb Bello
2026-03-24 12:37 ` [PATCH v2 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
2026-04-14  8:52   ` Karthik Nayak
2026-04-14  9:35     ` Phillip Wood
2026-04-14 17:15       ` Junio C Hamano
2026-04-15 11:16       ` Karthik Nayak
2026-04-15 15:49         ` Junio C Hamano
2026-04-15 19:09           ` Karthik Nayak
2026-03-24 12:37 ` [PATCH v2 2/8] environment: move "check_stat" " Olamide Caleb Bello
2026-04-14  8:55   ` Karthik Nayak
2026-03-24 12:37 ` [PATCH v2 3/8] environment: move `zlib_compression_level` into repo_config_values Olamide Caleb Bello
2026-04-14  8:58   ` Karthik Nayak
2026-04-14 14:32     ` Bello Olamide
2026-03-24 12:37 ` [PATCH v2 4/8] environment: move "pack_compression_level" into `struct repo_config_values` Olamide Caleb Bello
2026-03-24 12:37 ` [PATCH v2 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
2026-04-14  9:07   ` Karthik Nayak
2026-03-24 12:37 ` [PATCH v2 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
2026-03-24 12:37 ` [PATCH v2 7/8] env: put "sparse_expect_files_outside_of_patterns" in `repo_config_values` Olamide Caleb Bello
2026-03-24 12:37 ` [PATCH v2 8/8] env: move "warn_on_object_refname_ambiguity" into `repo_config_values` Olamide Caleb Bello
2026-04-14  9:10 ` [PATCH v2 0/8] repo_config_values: migrate more globals Karthik Nayak
2026-04-14 14:26   ` Bello Olamide
2026-04-23 16:08   ` [PATCH v3 " Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 1/8] Revert "compat/posix: introduce writev(3p) wrapper" Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 2/8] rust: we are way beyond 2.53 Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 3/8] doc: am: revert Message-ID trailer claim Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 4/8] doc: am: correct to full --no-message-id Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 5/8] CI: bump actions/checkout from 4 to 5 for rust-analysis job Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 6/8] gitglossary: fix indentation of sub-lists Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 7/8] Hopefully the final tweak before -rc2 Olamide Caleb Bello
2026-04-23 16:08     ` [PATCH v3 8/8] Git 2.54-rc2 Olamide Caleb Bello
2026-04-23 16:37     ` [PATCH v3 0/8] repo_config_values: migrate more globals Bello Olamide
2026-04-23 16:54   ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 1/8] environment: move "trust_ctime" into `struct repo_config_values` Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 2/8] environment: move "check_stat" " Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 3/8] environment: move `zlib_compression_level` " Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 4/8] environment: move "pack_compression_level" " Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 5/8] environment: move "precomposed_unicode" " Olamide Caleb Bello
2026-05-15 17:15       ` Tian Yuchen
2026-04-23 16:54     ` [PATCH v3 6/8] env: move "core_sparse_checkout_cone" " Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 7/8] env: move "sparse_expect_files_outside_of_patterns" into `repo_config_values` Olamide Caleb Bello
2026-04-23 16:54     ` [PATCH v3 8/8] env: move "warn_on_object_refname_ambiguity" into `struct repo_config_values` Olamide Caleb Bello
2026-04-26  0:01     ` [PATCH v3 0/8] environment: move core config globals into repo_config_values Junio C Hamano
2026-04-26  0:31       ` Bello Olamide
2026-05-11  2:56         ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox