From: Olamide Caleb Bello Date: Tue, 03 Feb 2026 15:42:09 GMT Subject: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally Message-ID: <7e3082125df08d3e5fb2195d73698c4c28c6645e.1770127568.git.belkid98@gmail.com> In-Reply-To: The `core.attributeFile` config value is parsed in git_default_core_config(), loaded eagerly and stored in the global variable `git_attributes_file`. Storing this value in a global variable can lead to it being overwritten by another repository when more than one Git repository run in the same Git process. Create a new struct `repo_config_values` to hold this value and other repository dependent values parsed by `git_default_config()`. This will ensure the current behaviour remains the same while also enabling the libification of Git. An accessor function 'repo_config_values()' is created and used to access the new struct member of the repository struct. This is to ensure that we detect if the struct repository has been initialized and also prevent double initialization of the repository. It is important to note that `git_default_config()` is a wrapper to other `git_default_*_config()` functions such as `git_default_core_config()`. Therefore to access and modify this global variable, the change has to be made `git_default_core_config()`. Suggested-by: Phillip Wood Mentored-by: Christian Couder Mentored-by: Usman Akinyemi Helped-by: Junio C Hamano Signed-off-by: Olamide Caleb Bello --- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/attr.c b/attr.c index 4999b7e09d..75369547b3 100644 --- a/attr.c +++ b/attr.c @@ -881,10 +881,11 @@ const char *git_attr_system_file(void) const char *git_attr_global_file(void) { - if (!git_attributes_file) - git_attributes_file = xdg_config_home("attributes"); + struct repo_config_values *cfg = repo_config_values(the_repository); + if (!cfg->attributes_file) + cfg->attributes_file = xdg_config_home("attributes"); - return git_attributes_file; + return cfg->attributes_file; } int git_attr_system_is_enabled(void) diff --git a/environment.c b/environment.c index a770b5921d..4b5c701e80 100644 --- a/environment.c +++ b/environment.c @@ -53,7 +53,6 @@ char *git_commit_encoding; char *git_log_output_encoding; char *apply_default_whitespace; char *apply_default_ignorewhitespace; -char *git_attributes_file; int zlib_compression_level = Z_BEST_SPEED; int pack_compression_level = Z_DEFAULT_COMPRESSION; int fsync_object_files = -1; @@ -327,6 +326,8 @@ static enum fsync_component parse_fsync_components(const char *var, const char * static int git_default_core_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { + struct repo_config_values *cfg = repo_config_values(the_repository); + /* This needs a better name */ if (!strcmp(var, "core.filemode")) { trust_executable_bit = git_config_bool(var, value); @@ -364,8 +365,8 @@ static int git_default_core_config(const char *var, const char *value, } if (!strcmp(var, "core.attributesfile")) { - FREE_AND_NULL(git_attributes_file); - return git_config_pathname(&git_attributes_file, var, value); + FREE_AND_NULL(cfg->attributes_file); + return git_config_pathname(&cfg->attributes_file, var, value); } if (!strcmp(var, "core.bare")) { @@ -756,3 +757,8 @@ int git_default_config(const char *var, const char *value, /* Add other config variables here and to Documentation/config.adoc. */ return 0; } + +void repo_config_values_init(struct repo_config_values *cfg) +{ + cfg->attributes_file = NULL; +} diff --git a/environment.h b/environment.h index 51898c99cd..dfc31b794d 100644 --- a/environment.h +++ b/environment.h @@ -84,6 +84,14 @@ extern const char * const local_repo_env[]; struct strvec; +struct repository; +struct repo_config_values { + /* section "core" config values */ + char *attributes_file; +}; + +struct repo_config_values *repo_config_values(struct repository *repo); + /* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later. @@ -107,6 +115,8 @@ const char *strip_namespace(const char *namespaced_ref); int git_default_config(const char *, const char *, const struct config_context *, void *); +void repo_config_values_init(struct repo_config_values *cfg); + /* * TODO: All the below state either explicitly or implicitly relies on * `the_repository`. We should eventually get rid of these and make the @@ -152,7 +162,6 @@ extern int assume_unchanged; extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; -extern char *git_attributes_file; extern int zlib_compression_level; extern int pack_compression_level; extern unsigned long pack_size_limit_cfg; diff --git a/repository.c b/repository.c index c7e75215ac..a9b727540f 100644 --- a/repository.c +++ b/repository.c @@ -50,13 +50,25 @@ static void set_default_hash_algo(struct repository *repo) repo_set_hash_algo(repo, algo); } +struct repo_config_values *repo_config_values(struct repository *repo) +{ + if(!repo->initialized) + BUG("config values from uninitialized repository"); + return &repo->config_values_private_; +} + void initialize_repository(struct repository *repo) { + if (repo->initialized) + BUG("repository initialized already"); + repo->initialized = true; + repo->remote_state = remote_state_new(); repo->parsed_objects = parsed_object_pool_new(repo); ALLOC_ARRAY(repo->index, 1); index_state_init(repo->index, repo); repo->check_deprecated_config = true; + repo_config_values_init(repo_config_values(repo)); /* * When a command runs inside a repository, it learns what diff --git a/repository.h b/repository.h index 6063c4b846..9717e45000 100644 --- a/repository.h +++ b/repository.h @@ -3,6 +3,7 @@ #include "strmap.h" #include "repo-settings.h" +#include "environment.h" struct config_set; struct git_hash_algo; @@ -148,6 +149,9 @@ struct repository { /* Repository's compatibility hash algorithm. */ const struct git_hash_algo *compat_hash_algo; + /* Repository's config values parsed by git_default_config() */ + struct repo_config_values config_values_private_; + /* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format; @@ -171,6 +175,9 @@ struct repository { /* Should repo_config() check for deprecated settings */ bool check_deprecated_config; + + /* Has this repository instance been initialized? */ + bool initialized; }; #ifdef USE_THE_REPOSITORY_VARIABLE -- 2.34.1