store git_default_config() parsed values in new config struct
cover store git_default_config() parsed values in new config struct
Hi Git Community,
Over the course of my ongoing internship, which focused on moving global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there have been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store the parsed config values per repo. This would mean we would not need to remove code from git_default_config(), and hence the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into struct config_values
attr.c | 8 +++++--- builtin/backfill.c | 3 +-- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- config.c | 10 ++++++++++ config.h | 13 +++++++++++++ dir.c | 2 +- environment.c | 20 ++++++++++---------- environment.h | 2 -- repository.c | 7 +++++++ repository.h | 4 ++++ sparse-index.c | 4 ++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 20 files changed, 74 insertions(+), 40 deletions(-)
Signature · 1 line
2.34.1
RFC PATCH 1/3 environment: stop storing `core.attributesFile` globally
The config value parsed in git_default_core_config() is loaded eagerly and stored in the global variable git_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
Move this value into a struct config_values which holds all the values parsed by git_default_config() and can be accessed per repository via git_default_config(). This will prevent us from moving any code from git_default_core_config(), ensuring the current behaviour remains the same while also enabling the libification of Git.
It is important to note that git_default_config() is a wrapper to other git_default_*_config() such as git_default_core_config(). Therefore to access and modify this global variable,
the change has to be made in the function which parses and stores the value in the global variable.
--- attr.c | 8 +++++--- config.c | 5 +++++ config.h | 8 ++++++++ environment.c | 7 ++++--- environment.h | 1 - repository.c | 6 ++++++ repository.h | 4 ++++ 7 files changed, 32 insertions(+), 7 deletions(-)
attr.c +5 -3
@@ -881,10 +881,12 @@ 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 config_values *cfg = the_repository->cfg_values; -return git_attributes_file; +if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); + +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )
config.c +5 -0
@@ -1761,6 +1761,11 @@ static int config_set_element_cmp(const void *cmp_data UNUSED,return strcmp (e1->key, e2->key); } +void config_values_clear (struct config_values *cfg) +{ +free (cfg->attributes_file_path); +} +void git_configset_init (struct config_set *set) {hashmap_init (&set->config_hash, config_set_element_cmp,NULL ,0 );
config.h +8 -0
@@ -135,6 +135,13 @@ struct config_context {/* Config source metadata for key and value. */ const struct key_value_info *kvi; }; + +/* Holds values parsed by git_default_config() */ +struct config_values { +/* core config values */ +char *attributes_file_path; + +};#define CONFIG_CONTEXT_INIT { 0 }/**
@@ -187,6 +194,7 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,void git_config_push_parameter (const char *text);void git_config_push_env (const char *spec);int git_config_from_parameters (config_fn_t fn,void *data); +void config_values_clear (struct config_values *cfg);/* * Read config when the Git directory has not yet been set up. In case
environment.c +4 -3
@@ -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 config_values *cfg = the_repository->cfg_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, var, value); }if (!strcmp (var,"core.bare" )) {
environment.h +0 -1
@@ -152,7 +152,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;
repository.c +6 -0
@@ -55,6 +55,7 @@ void initialize_repository(struct repository *repo) repo->remote_state =remote_state_new (); repo->parsed_objects =parsed_object_pool_new (repo);ALLOC_ARRAY (repo->index,1 ); +CALLOC_ARRAY (repo->cfg_values,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true;
@@ -403,6 +404,11 @@ void repo_clear(struct repository *repo)FREE_AND_NULL (repo->remote_state); } +if (repo->cfg_values) { +config_values_clear (repo->cfg_values); +FREE_AND_NULL (repo->cfg_values); + } +strmap_for_each_entry (&repo->submodule_ref_stores, &iter, e)ref_store_release (e->value);strmap_clear (&repo->submodule_ref_stores,1 );
repository.h +4 -0
@@ -13,6 +13,7 @@ struct object_database;struct submodule_cache ;struct promisor_remote_config ;struct remote_state ; +struct config_values ;enum ref_storage_format {REF_STORAGE_FORMAT_UNKNOWN ,
@@ -171,6 +172,9 @@ struct repository {/* Should repo_config() check for deprecated settings */ bool check_deprecated_config; + +/* Repository's config values parsed by git_default_config() */ +struct config_values *cfg_values; };#ifdef USE_THE_REPOSITORY_VARIABLE
Signature · 1 line
2.34.1
Re: [Outreachy PATCH RFC 1/3] environment: stop storing `core.attributesFile` globally
Hi Olamide
Quoted 10 lines · Olamide Caleb Bello
The config value parsed in
git_default_core_config()is loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.Move this value into a
struct config_valueswhich holds all the values parsed bygit_default_config()and can be accessed per repository viagit_default_config(). This will prevent us from moving any code fromgit_default_core_config(), ensuring the current behaviour remains the same while also enabling the libification of Git.
The important thing is that we're not changing when the config is parsed, not that we're not removing code from git_default_core_config().
Looking at the changes below, I think it would be simpler to embed struct config_values in struct repository as we do for struct repo_settings. That would simplify things as we wouldn't have to mess about allocating an instance on the heap and freeing it in repo_clear(). I'd be tempted to call the new struct repo_config rather than config_values which is rather non-specific. I'm also not sure config.[ch] is the best home for it, maybe it should live in environment.[ch] for now - we might want to move it to it's own file at some point.
Thanks
Phillip
Quoted 172 lines
It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()such asgit_default_core_config(). Therefore to access and modify this global variable,
the change has to be made in the function which parses and stores the value in the global variable.Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>--- attr.c | 8 +++++--- config.c | 5 +++++ config.h | 8 ++++++++ environment.c | 7 ++++--- environment.h | 1 - repository.c | 6 ++++++ repository.h | 4 ++++ 7 files changed, 32 insertions(+), 7 deletions(-)attr.c +5
-3@@ -881,10 +881,12 @@ 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 config_values *cfg = the_repository->cfg_values; -return git_attributes_file; +if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); + +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )config.c +5
-0@@ -1761,6 +1761,11 @@ static int config_set_element_cmp(const void *cmp_data UNUSED,return strcmp (e1->key, e2->key); } +void config_values_clear (struct config_values *cfg) +{ +free (cfg->attributes_file_path); +} +void git_configset_init (struct config_set *set) {hashmap_init (&set->config_hash, config_set_element_cmp,NULL ,0 );config.h +8
-0@@ -135,6 +135,13 @@ struct config_context {/* Config source metadata for key and value. */ const struct key_value_info *kvi; }; + +/* Holds values parsed by git_default_config() */ +struct config_values { +/* core config values */ +char *attributes_file_path; + +};#define CONFIG_CONTEXT_INIT { 0 }/** @@ -187,6 +194,7 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,void git_config_push_parameter (const char *text);void git_config_push_env (const char *spec);int git_config_from_parameters (config_fn_t fn,void *data); +void config_values_clear (struct config_values *cfg);/* * Read config when the Git directory has not yet been set up. In case environment.c +4
-3@@ -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 config_values *cfg = the_repository->cfg_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, var, value); }if (!strcmp (var,"core.bare" )) {environment.h +0
-1@@ -152,7 +152,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;repository.c +6
-0@@ -55,6 +55,7 @@ void initialize_repository(struct repository *repo) repo->remote_state =remote_state_new (); repo->parsed_objects =parsed_object_pool_new (repo);ALLOC_ARRAY (repo->index,1 ); +CALLOC_ARRAY (repo->cfg_values,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true;@@ -403,6 +404,11 @@ void repo_clear(struct repository *repo)FREE_AND_NULL (repo->remote_state); } +if (repo->cfg_values) { +config_values_clear (repo->cfg_values); +FREE_AND_NULL (repo->cfg_values); + } +strmap_for_each_entry (&repo->submodule_ref_stores, &iter, e)ref_store_release (e->value);strmap_clear (&repo->submodule_ref_stores,1 );repository.h +4
-0@@ -13,6 +13,7 @@ struct object_database;struct submodule_cache ;struct promisor_remote_config ;struct remote_state ; +struct config_values ;enum ref_storage_format {REF_STORAGE_FORMAT_UNKNOWN ,@@ -171,6 +172,9 @@ struct repository {/* Should repo_config() check for deprecated settings */ bool check_deprecated_config; + +/* Repository's config values parsed by git_default_config() */ +struct config_values *cfg_values; };#ifdef USE_THE_REPOSITORY_VARIABLE
Re: [Outreachy PATCH RFC 1/3] environment: stop storing `core.attributesFile` globally
Quoted 2 lines · Phillip Wood
Hi Olamide
Hellp Phillip
Quoted 7 lines · Olamide Caleb Bello
Quoted 5 lines
The config value parsed in
git_default_core_config()is loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
Quoted 8 lines
Quoted 5 lines
Move this value into a
struct config_valueswhich holds all the values parsed bygit_default_config()and can be accessed per repository viagit_default_config(). This will prevent us from moving any code fromgit_default_core_config(), ensuring the current behaviour remains the same while also enabling the libification of Git.The important thing is that we're not changing when the config is parsed, not that we're not removing code from
git_default_core_config().
Okay thanks for clarifying
Quoted 5 lines
Looking at the changes below, I think it would be simpler to embed
struct config_valuesinstruct repositoryas we do forstruct repo_settings. That would simplify things as we wouldn't have to mess about allocating an instance on the heap and freeing it inrepo_clear().
Okay I will try this approach
Quoted 2 lines
I'd be tempted to call the new struct
repo_configrather thanconfig_valueswhich is rather non-specific.
I initially considered repo_config, but a struct with the name already exists
Quoted 4 lines
I'm also not sure
config.[ch] is the best home for it, maybe it should live in environment.[ch] for now - we might want to move it to it's own file at some point.
Okay this is noted.
Thanks
RFC PATCH 2/3 environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_appy_sparse_checkout. This could cause unintended behaviours when different Git repositories running in the same process access this variable.
Move the parsed value into struct config_values which holds all the values parsed by git_default_config() and can be accessed per repo via git_default_config(). This would mean we do not need to remove code from git_default_core_config(), thereby retaining current behaviours.
--- builtin/backfill.c | 3 +-- builtin/clone.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/worktree.c | 2 +- config.h | 1 + dir.c | 2 +- environment.c | 3 +-- environment.h | 1 - sparse-index.c | 4 ++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 12 files changed, 23 insertions(+), 24 deletions(-)
builtin/backfill.c +1 -2
@@ -1,4 +1,3 @@ -/* We need this macro to access core_apply_sparse_checkout */ #define USE_THE_REPOSITORY_VARIABLE #include "builtin.h"
@@ -139,7 +138,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->cfg_values->sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +1 -1
@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->cfg_values->sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/mv.c +1 -1
@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->cfg_values->sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +11 -11
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->cfg_values->sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->cfg_values->sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->cfg_values->sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -418,7 +418,7 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !repo->cfg_values->sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -699,9 +699,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!repo->cfg_values->sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + repo->cfg_values->sparse_checkout =1 ; changed_config =1 ; }
@@ -798,7 +798,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->cfg_values->sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -907,7 +907,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->cfg_values->sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -969,7 +969,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->cfg_values->sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1035,7 +1035,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->cfg_values->sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1061,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + repo->cfg_values->sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +1 -1
@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (the_repository->cfg_values->sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
config.h +1 -0
@@ -140,6 +140,7 @@ struct config_context {struct config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout; };#define CONFIG_CONTEXT_INIT { 0 }
dir.c +1 -1
@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!istate->repo->cfg_values->sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +1 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->sparse_checkout =git_config_bool (var, value);return 0 ; }
environment.h +0 -1
@@ -161,7 +161,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +2 -2
@@ -152,7 +152,7 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +if (!istate->repo->cfg_values->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +670,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +if (!istate->repo->cfg_values->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +1 -1
@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->cfg_values->sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +2 -1
@@ -35,6 +35,7 @@#include "lockfile.h" #include "sequencer.h" #include "fsmonitor-settings.h" +#include "config.h" #define AB_DELAY_WARNING_IN_MS (2 * 1000)#define UF_DELAY_WARNING_IN_MS (2 * 1000)
@@ -1764,7 +1765,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->cfg_values->sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
RFC PATCH 3/3 environment: move "branch.autoSetupMerge" into `struct config_values`
In reply to Olamide Caleb BelloThe config value brach.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.
Move this value into struct config_values which holds all values parsed by git_default_config() and can be accessed per
repo via git_default_config(). This would mean we do not have to remove code from git_default_branch_config(), thereby retaining the same behaviour.
--- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/push.c | 2 +- builtin/submodule--helper.c | 2 +- config.c | 5 +++++ config.h | 4 ++++ environment.c | 10 +++++----- repository.c | 1 + 8 files changed, 19 insertions(+), 9 deletions(-)
builtin/branch.c +1 -1
@@ -795,7 +795,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = the_repository->cfg_values->git_branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +1 -1
@@ -1631,7 +1631,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = the_repository->cfg_values->git_branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +1 -1
@@ -162,7 +162,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (the_repository->cfg_values->git_branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +1 -1
@@ -3128,7 +3128,7 @@ static int module_create_branch(int argc, const char **argv, const char *prefix, };repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = the_repository->cfg_values->git_branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
config.c +5 -0
@@ -1766,6 +1766,11 @@ void config_values_clear(struct config_values *cfg)free (cfg->attributes_file_path); } +void config_values_init_defaults (struct config_values *cfg) +{ + cfg->git_branch_track =BRANCH_TRACK_REMOTE ; +} +void git_configset_init (struct config_set *set) {hashmap_init (&set->config_hash, config_set_element_cmp,NULL ,0 );
config.h +4 -0
@@ -5,6 +5,7 @@#include "string-list.h" #include "repository.h" #include "parse.h" +#include "branch.h" /** * The config API gives callers a way to access Git configuration files
@@ -142,6 +143,8 @@ struct config_values {char *attributes_file_path;int sparse_checkout; +/* branch config values */ +enum branch_track git_branch_track; };#define CONFIG_CONTEXT_INIT { 0 }
@@ -195,6 +198,7 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,void git_config_push_parameter (const char *text);void git_config_push_env (const char *spec);int git_config_from_parameters (config_fn_t fn,void *data); +void config_values_init_defaults (struct config_values *cfg);void config_values_clear (struct config_values *cfg);/*
environment.c +5 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,19 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct config_values *cfg = the_repository->cfg_values;if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->git_branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->git_branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->git_branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->git_branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
repository.c +1 -0
@@ -56,6 +56,7 @@ void initialize_repository(struct repository *repo) repo->parsed_objects =parsed_object_pool_new (repo);ALLOC_ARRAY (repo->index,1 );CALLOC_ARRAY (repo->cfg_values,1 ); +config_values_init_defaults (repo->cfg_values);index_state_init (repo->index, repo); repo->check_deprecated_config = true;
Signature · 1 line
2.34.1
v2 cover store git_default_config() parsed values in new config struct
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there have been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store the parsed config values per repo. This ensures the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://github.com/git/git/actions/runs/20953059862
Changes in v2:
==============
- Renamed new struct to repo_config_values
- Moved struct and functions declaration and definition to environment.[ch]
- embedded the new struct in the repository struct thereby removing the need to allocate memory on the heap
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 3 +-- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 26 ++++++++++++++++---------- environment.h | 15 +++++++++++++-- repository.c | 1 + repository.h | 4 ++++ sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 20 files changed, 65 insertions(+), 43 deletions(-)
Range diff versus v2
====================
1: 25fc10854e < -: ---------- environment: stop storing `core.attributesFile` globally
-: ---------- > 1: b6f8deaa40 environment: stop storing `core.attributesFile` globally
2: f25afc6f68 ! 2: 1e83c077f2 environment: stop using core.sparseCheckout globally
@@ Metadata
Author: Olamide Caleb Bello <[email protected]>
## Commit message ##
- environment: stop using core.sparseCheckout globally
+ environment: environment: stop using core.sparseCheckout globally
The config value `core.sparseCheckout` is parsed in
`git_default_core_config()` and stored globally in
@@ Commit message
when different Git repositories running in the same process access this
variable.
- Move the parsed value into `struct config_values` which can be accessed
- per repo via `git_default_config()`. This would mean we do not need to
- remove code from `git_default_core_config()`, thereby retaining current
- behaviours.
+ Move the parsed value into `struct repo_config_values` which holds all the
+ values parsed by `git_default_config()` and can be accessed
+ per repo via `git_default_config()`. This retains current
+ behaviours while achieving the repository scoped access.
Suggested-by: Phillip Wood <[email protected]>
Mentored-by: Christian Couder <[email protected]>
@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *pr
if (ctx.sparse < 0)
- ctx.sparse = core_apply_sparse_checkout;
-+ ctx.sparse = repo->cfg_values->sparse_checkout;
++ ctx.sparse = repo->config_values.sparse_checkout;
result = do_backfill(&ctx);
backfill_context_clear(&ctx);
@@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)
* for the later checkout to use the sparse-checkout file.
*/
- core_apply_sparse_checkout = 1;
-+ the_repository->cfg_values->sparse_checkout = 1;
++ the_repository->config_values.sparse_checkout = 1;
cmd.git_cmd = 1;
if (run_command(&cmd)) {
+ ## builtin/grep.c ##
+@@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,
+ * "forget" the sparse-index feature switch. As a result, the index
+ * of these submodules are expanded unexpectedly.
+ *
+- * 2. "core_apply_sparse_checkout"
++ * 2. "sparse_checkout"
+ * When running `grep` in the superproject, this setting is
+ * populated using the superproject's configs. However, once
+ * initialized, this config is globally accessible and is read by
+
## builtin/mv.c ##
@@ builtin/mv.c: int cmd_mv(int argc,
rename_index_entry_at(the_repository->index, pos, dst);
if (ignore_sparse &&
- core_apply_sparse_checkout &&
-+ the_repository->cfg_values->sparse_checkout &&
++ the_repository->config_values.sparse_checkout &&
core_sparse_checkout_cone) {
/*
* NEEDSWORK: we are *not* paying attention to
@@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->cfg_values->sparse_checkout)
++ if (!the_repository->config_values.sparse_checkout)
die(_("this worktree is not sparse"));
argc = parse_options(argc, argv, prefix,
@@ builtin/sparse-checkout.c: static int set_config(struct repository *repo,
static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
/* If not specified, use previous definition of cone mode */
- if (*cone_mode == -1 && core_apply_sparse_checkout)
-+ if (*cone_mode == -1 && the_repository->cfg_values->sparse_checkout)
++ if (*cone_mode == -1 && the_repository->config_values.sparse_checkout)
*cone_mode = core_sparse_checkout_cone;
/* Set cone/non-cone mode appropriately */
- core_apply_sparse_checkout = 1;
-+ the_repository->cfg_values->sparse_checkout = 1;
++ the_repository->config_values.sparse_checkout = 1;
if (*cone_mode == 1 || *cone_mode == -1) {
core_sparse_checkout_cone = 1;
return MODE_CONE_PATTERNS;
@@ builtin/sparse-checkout.c: static int update_modes(struct repository *repo, int
/* Determine if we need to record the mode; ensure sparse checkout on */
- record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;
-+ record_mode = (*cone_mode != -1) || !repo->cfg_values->sparse_checkout;
++ record_mode = (*cone_mode != -1) || !repo->config_values.sparse_checkout;
mode = update_cone_mode(cone_mode);
if (record_mode && set_config(repo, mode))
@@ builtin/sparse-checkout.c: static int modify_pattern_list(struct repository *rep
}
- if (!core_apply_sparse_checkout) {
-+ if (!repo->cfg_values->sparse_checkout) {
++ if (!repo->config_values.sparse_checkout) {
set_config(repo, MODE_ALL_PATTERNS);
- core_apply_sparse_checkout = 1;
-+ repo->cfg_values->sparse_checkout = 1;
++ repo->config_values.sparse_checkout = 1;
changed_config = 1;
}
@@ builtin/sparse-checkout.c: static int sparse_checkout_add(int argc, const char *
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!repo->cfg_values->sparse_checkout)
++ if (!repo->config_values.sparse_checkout)
die(_("no sparse-checkout to add to"));
repo_read_index(repo);
@@ builtin/sparse-checkout.c: static int sparse_checkout_reapply(int argc, const ch
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!repo->cfg_values->sparse_checkout)
++ if (!repo->config_values.sparse_checkout)
die(_("must be in a sparse-checkout to reapply sparsity patterns"));
reapply_opts.cone_mode = -1;
@@ builtin/sparse-checkout.c: static int sparse_checkout_clean(int argc, const char
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!repo->cfg_values->sparse_checkout)
++ if (!repo->config_values.sparse_checkout)
die(_("must be in a sparse-checkout to clean directories"));
if (!core_sparse_checkout_cone)
die(_("must be in a cone-mode sparse-checkout to clean directories"));
@@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch
/*
- * We do not exit early if !core_apply_sparse_checkout; due to the
-+ * We do not exit early if !repo->cfg_values->sparse_checkout; due to the
++ * We do not exit early if !repo->config_values.sparse_checkout; due to the
* ability for users to manually muck things up between
* direct editing of .git/info/sparse-checkout
* running read-tree -m u HEAD or update-index --skip-worktree
@@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch
hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);
pl.use_cone_patterns = 0;
- core_apply_sparse_checkout = 1;
-+ repo->cfg_values->sparse_checkout = 1;
++ repo->config_values.sparse_checkout = 1;
add_pattern("/*", empty_base, 0, &pl, 0);
@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam
* the sparse-checkout patterns from the current worktree.
*/
- if (core_apply_sparse_checkout)
-+ if (the_repository->cfg_values->sparse_checkout)
++ if (wt->repo->config_values.sparse_checkout)
copy_sparse_checkout(sb_repo.buf);
/*
- ## config.h ##
-@@ config.h: struct config_context {
- struct config_values {
- /* core config values */
- char *attributes_file_path;
-+ int sparse_checkout;
-
- };
- #define CONFIG_CONTEXT_INIT { 0 }
-
## dir.c ##
@@ dir.c: enum pattern_match_result path_matches_pattern_list(
int init_sparse_checkout_patterns(struct index_state *istate)
{
- if (!core_apply_sparse_checkout)
-+ if (!istate->repo->cfg_values->sparse_checkout)
++ if (!istate->repo->config_values.sparse_checkout)
return 1;
if (istate->sparse_checkout_patterns)
return 0;
@@ environment.c: static int git_default_core_config(const char *var, const char *v
## environment.h ##
+@@ environment.h: struct strvec;
+ struct repo_config_values {
+ /* core config values */
+ char *attributes_file_path;
++ int sparse_checkout;
+ };
+
+ /*
@@ environment.h: extern int precomposed_unicode;
extern int protect_hfs;
extern int protect_ntfs;
@@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate
int is_sparse_index_allowed(struct index_state *istate, int flags)
{
- if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
-+ if (!istate->repo->cfg_values->sparse_checkout || !core_sparse_checkout_cone)
++ struct repo_config_values *cfg = &istate->repo->config_values;
++ if (!cfg->sparse_checkout || !core_sparse_checkout_cone)
return 0;
if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
@@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct i
void clear_skip_worktree_from_present_files(struct index_state *istate)
{
- if (!core_apply_sparse_checkout ||
-+ if (!istate->repo->cfg_values->sparse_checkout ||
++ struct repo_config_values *cfg = &istate->repo->config_values;
++ if (!cfg->sparse_checkout ||
sparse_expect_files_outside_of_patterns)
return;
@@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpac
update_sparsity_for_prefix(o->prefix, o->src_index);
- if (!core_apply_sparse_checkout || !o->update)
-+ if (!repo->cfg_values->sparse_checkout || !o->update)
++ if (!repo->config_values.sparse_checkout || !o->update)
o->skip_sparse_checkout = 1;
if (!o->skip_sparse_checkout) {
memset(&pl, 0, sizeof(pl));
## wt-status.c ##
-@@
- #include "lockfile.h"
- #include "sequencer.h"
- #include "fsmonitor-settings.h"
-+#include "config.h"
-
- #define AB_DELAY_WARNING_IN_MS (2 * 1000)
- #define UF_DELAY_WARNING_IN_MS (2 * 1000)
@@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r,
int skip_worktree = 0;
int i;
- if (!core_apply_sparse_checkout || r->index->cache_nr == 0) {
-+ if (!r->cfg_values->sparse_checkout || r->index->cache_nr == 0) {
++ if (!r->config_values.sparse_checkout || r->index->cache_nr == 0) {
/*
* Don't compute percentage of checked out files if we
* aren't in a sparse checkout or would get division by 0.
3: 1c86c72f2d < -: ---------- environment: move "branch.autoSetupMerge" into `struct config_values`
-: ---------- > 3: 6e54e22ac7 environment: move "branch.autoSetupMerge" into `struct repo_config_values`Signature · 1 line
2.34.1
PATCH v2 1/3 environment: stop storing `core.attributesFile` globally
The config value parsed in git_default_core_config() is loaded eagerly and stored in the global variable git_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
Move this value into a struct repo_config_values which holds all the values parsed by git_default_config() and can be accessed per repository via git_default_config(). This will ensure the current behaviour remains the same while also enabling the libification of Git.
It is important to note that git_default_config() is a wrapper to other git_default_*_config() such as git_default_core_config(). Therefore to access and modify this global variable,
the change has to be made in the function which parses and stores the value in the global variable.
--- attr.c | 7 ++++--- environment.c | 7 ++++--- environment.h | 7 ++++++- repository.h | 4 ++++ 4 files changed, 18 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 = &the_repository->config_values; +if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); -return git_attributes_file; +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )
environment.c +4 -3
@@ -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 = &the_repository->config_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, var, value); }if (!strcmp (var,"core.bare" )) {
environment.h +6 -1
@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];struct strvec ; +/* Config values parsed by git_default_config() */ +struct repo_config_values { +/* core config values */ +char *attributes_file_path; +}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later.
@@ -152,7 +158,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;
repository.h +4 -0
@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v2 1/3] environment: stop storing `core.attributesFile` globally
Quoted 4 lines · Olamide Caleb Bello
The config value parsed in
git_default_core_config()is loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
There are quite a many global singleton variables that are accessed by git_default_core_config(), and this patch addresses only one of them. Are most of these variables per repository, or are there some variables that are inherently just one for a user or for a system?
Quoted 7 lines
extern int
warn_on_object_refname_ambiguity;
extern char*apply_default_whitespace;
extern char*apply_default_ignorewhitespace;
-extern char*git_attributes_file;
extern intzlib_compression_level;
extern intpack_compression_level;
extern unsigned longpack_size_limit_cfg;
Re: [Outreachy PATCH v2 1/3] environment: stop storing `core.attributesFile` globally
Quoted 8 lines · Junio C Hamano
Quoted 4 lines · Olamide Caleb Bello
The config value parsed in
git_default_core_config()is loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
Quoted 4 lines
There are quite a many global singleton variables that are accessed by
git_default_core_config(), and this patch addresses only one of them. Are most of these variables per repository, or are there some variables that are inherently just one for a user or for a system?
Hello Junio,
From my understanding of the code in git_default_config(), some config are just one for a user such
as the ones in git_default_ident_config(), git_default_mailmap_config(). However a majority of them are repository specific such as the ones in git_default_core_config(),git_default_branch_config(), git_default_push_config(). These are the ones that the movement to struct repo_config_values targets.
PATCH v2 2/3 environment: environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_appy_sparse_checkout. This could cause unintended behaviours when different Git repositories running in the same process access this variable.
Move the parsed value into struct repo_config_values which holds all the values parsed by git_default_config() and can be accessed per repo via git_default_config(). This retains current behaviours while achieving the repository scoped access.
--- builtin/backfill.c | 3 +-- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 3 +-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 12 files changed, 25 insertions(+), 25 deletions(-)
builtin/backfill.c +1 -2
@@ -1,4 +1,3 @@ -/* We need this macro to access core_apply_sparse_checkout */ #define USE_THE_REPOSITORY_VARIABLE #include "builtin.h"
@@ -139,7 +138,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +1 -1
@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +1 -1
@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +11 -11
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -418,7 +418,7 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !repo->config_values.sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -699,9 +699,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!repo->config_values.sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ; changed_config =1 ; }
@@ -798,7 +798,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -907,7 +907,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -969,7 +969,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1035,7 +1035,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1061,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +1 -1
@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (wt->repo->config_values.sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +1 -1
@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!istate->repo->config_values.sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +1 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->sparse_checkout =git_config_bool (var, value);return 0 ; }
environment.h +1 -1
@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout; };/*
@@ -167,7 +168,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +4 -2
@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +1 -1
@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +1 -1
@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v2 2/3] environment: environment: stop using core.sparseCheckout globally
builtin/backfill.c line 1
Quoted 6 lines · Olamide Caleb Bello
builtin/backfill.c +0
-1@@ -1,4 +1,3 @@ -/* We need this macro to access core_apply_sparse_checkout */
Why this removal? You'll need to be able to access the_repository because ...
Quoted 17 lines
builtin/backfill.c +1
-1#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" @@ -139,7 +138,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +0
-0
builtin/clone.c static int git_sparse_checkout_init(const char *repo) · line 626
Quoted 5 lines
builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;
... you'd need to access this, even if it is now called slightly differently, no?
Re: [Outreachy PATCH v2 2/3] environment: environment: stop using core.sparseCheckout globally
Quoted 23 lines · Junio C Hamano
builtin/backfill.c line 1
Quoted 6 lines · Olamide Caleb Bello
builtin/backfill.c +0
-1@@ -1,4 +1,3 @@ -/* We need this macro to access core_apply_sparse_checkout */ Why this removal? You'll need to be able to access
the_repositorybecause ...Quoted 10 lines
builtin/backfill.c +1
-1#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" @@ -139,7 +138,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout;
Quoted 15 lines
builtin/clone.c static int git_sparse_checkout_init(const char *repo) · line 626
Quoted 12 lines
builtin/backfill.c +0
-0result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;... you'd need to access this, even if it is now called slightly differently, no?
Oh yes you are right.
I will return it.
PATCH v2 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value brach.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.
Move this value into struct repo_config_values which holds all values parsed by git_default_config() and can be accessed per repo via git_default_config(). This would retain the same behaviours while achieving repository scoped access.
--- branch.h | 2 -- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/push.c | 2 +- builtin/submodule--helper.c | 2 +- environment.c | 16 +++++++++++----- environment.h | 6 ++++++ repository.c | 1 + 8 files changed, 22 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +1 -1
@@ -795,7 +795,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = the_repository->config_values.git_branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +1 -1
@@ -1631,7 +1631,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = the_repository->config_values.git_branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +1 -1
@@ -162,7 +162,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (the_repository->config_values.git_branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +1 -1
@@ -3128,7 +3128,7 @@ static int module_create_branch(int argc, const char **argv, const char *prefix, };repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = the_repository->config_values.git_branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +11 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg = &the_repository->config_values; +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->git_branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->git_branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->git_branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->git_branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -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->git_branch_track =BRANCH_TRACK_REMOTE ; +}
environment.h +6 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -89,6 +90,9 @@ struct repo_config_values {/* core config values */ char *attributes_file_path;int sparse_checkout; + +/* branch config values */ +enum branch_track git_branch_track; };/*
@@ -114,6 +118,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
repository.c +1 -0
@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v2 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 10 lines · Olamide Caleb Bello
The config value
brach.autoSetupMergeis parsed ingit_default_branch_config()and stored in the global variablegit_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.Move this value into
struct repo_config_valueswhich holds all values parsed bygit_default_config()and can be accessed per repo viagit_default_config(). This would retain the same behaviours while achieving repository scoped access.
Quoted 5 lines
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>---
Currently the code flow is for git_config(git_default_config) to be called fairly early in the program, updating the singleton globals that are independent from individual repository. This moves these global variables to be stored in the config_values structure that is tied to the_repository.
The claim in the cover letter was that this will make it possible for us to later work on more than one repositories at once and each repository can keep its own independent value. While the updated data structure may make it _possible_, I am not sure if this is a safe approach to get to the final state, without seeing how the config_values structure in the second "repo" structure is populated.
And before moving all these globals into config_values, it is not possible to safely populate the config_values structure in the second "repo" structure, if git_config(git_default_config) is what we plan to use. The settings that are still stored in globals will then get overwritten.
That is why my first question for this round of patches was "are all these settings inherently per repository?", because the scheme would not work if there are globals that cannot be moved to config_value structure to be per-repo.
repository.c void initialize_repository(struct repository *repo) · line 60
Quoted 9 lines
repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);
Having a call to repo_config_values_init() when initializing an in-core repository instance is a reasonable design, and I see this step has an initialization of git_branch_track in that function. Shouldn't we be doing similar initialization in the same config_values_init() function for other members of the structure, namely, attributes_file_path and sparse_checkout?
The function also may be a good place to do an equivalent of calling git_config(git_default_config) there to grab values that are suitable for the given repository, but I didn't think things through.
Thanks.
Re: [Outreachy PATCH v2 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 19 lines · Junio C Hamano
Quoted 10 lines · Olamide Caleb Bello
The config value
brach.autoSetupMergeis parsed ingit_default_branch_config()and stored in the global variablegit_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.Move this value into
struct repo_config_valueswhich holds all values parsed bygit_default_config()and can be accessed per repo viagit_default_config(). This would retain the same behaviours while achieving repository scoped access.Quoted 5 lines
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>---
Quoted 5 lines
Currently the code flow is for
git_config(git_default_config)to be called fairly early in the program, updating the singleton globals that are independent from individual repository. This moves these global variables to be stored in theconfig_valuesstructure that is tied tothe_repository.
This will move those global variables that are repository dependent into the struct repo_config_values.
I admit the mistake is from my end. I should have been clear on that in the commit message rather than say '...holds all variables parsed by git_default_config()'.
Sorry
Quoted 8 lines
The claim in the cover letter was that this will make it possible for us to later work on more than one repositories at once and each repository can keep its own independent value. While the updated data structure may make it _possible_, I am not sure if this is a safe approach to get to the final state, without seeing how the
config_valuesstructure in the second "repo" structure is populated.
Quoted 5 lines
And before moving all these globals into
config_values, it is not possible to safely populate theconfig_valuesstructure in the second "repo" structure, ifgit_config(git_default_config)is what we plan to use. The settings that are still stored in globals will then get overwritten.
The idea proposed by Phillip is that we pass the repository parameter as the call back to git_default_config().
But since that will be quite invasive, you proposed we use the_repository for now. Then later we can pass the repository parameter as the call back and handle the invasiveness by simply checking in git_default_config() struct repository *r = cb ? cb : the_repository
Quoted 5 lines
That is why my first question for this round of patches was "are all these settings inherently per repository?", because the scheme would not work if there are globals that cannot be moved to
config_valuestructure to be per-repo.
The movement does not target all the global variables, but only those that are dependent on a repository.
Quoted 18 lines
repository.c void initialize_repository(struct repository *repo) · line 60
Quoted 11 lines
repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);Having a call to
repo_config_values_init()when initializing an in-core repository instance is a reasonable design, and I see this step has an initialization ofgit_branch_trackin that function. Shouldn't we be doing similar initialization in the sameconfig_values_init()function for other members of the structure, namely,attributes_file_pathandsparse_checkout?
I opted to initialize only the git_branch_track because in the original code, it is set to a default value BRANCH_TRACK_REMOTE before the call to git_default_config()
But attributes_file_path and sparse_checkout were only declared and not initialized
before the call to 'git_default_config'.
I just tried to replicate the current behaviour be initializing git_branch_track and those default
values early before the call to git_default_config
Quoted 5 lines
The function also may be a good place to do an equivalent of calling
git_config(git_default_config)there to grab values that are suitable for the given repository, but I didn't think things through.
Thanks
Quoted 30 lines · Olamide Caleb Bello
Hi Git Community,
Over the course of my ongoing internship, which focused on moving global variables inenvironment.hinto local scope, I have attempted to move some variables into the struct repo-settings.
However there have been some design concerns as regards the use ofprepare_repo_settings()with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to
git_default_config()to store the parsed config values per repo. This ensures the current behaviours will be retained.I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to
git_default_config().For now, the parsed value is stored in
the_repositoryingit_default_*_config()and further efforts to pass the repository parameter togit_default_config()as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://github.com/git/git/actions/runs/20953059862
Quoted 8 lines
Changes in v2:
==============
- Renamed new struct torepo_config_values
- Moved struct and functions declaration and definition to environment.[ch]
- embedded the new struct in the repository struct thereby removing the need to allocate memory on the heap
Hello,
I would like to know if there are new comments.
I want to send a new patch version.
Thanks
v3 cover store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2266020513
Changes in v3:
==============
- Moved declaration and definition of repo_config_values_init into patch 1
- Returned commit message in line 1 of builtin/backfill.c
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 2 +- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 28 ++++++++++++++++++---------- environment.h | 15 +++++++++++++-- repository.c | 1 + repository.h | 4 ++++ sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 20 files changed, 67 insertions(+), 42 deletions(-)
Range diff versus v2:
=====================
1: b6f8deaa40 ! 1: 1aa41da833 environment: stop storing core.attributesFile globally
@@ Metadata
## Commit message ##
environment: stop storing core.attributesFile globally
- The config value parsed in git_default_core_config() is loaded eagerly
+ The 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 unexpected behaviours when more than one Git repository run in the same Git process.
- Move this value into a struct repo_config_values which holds all the
- values parsed by git_default_config() and can be accessed per
- repository via git_default_config(). This will ensure the current
- behaviour remains the same while also enabling the libification of Git.
+ Create a new struct repo_config_values to hold this value and
+ other repository dependent values parsed by git_default_config() and
+ can be accessed per repository via git_default_config().
+ This will ensure the current behaviour remains the same while also
+ enabling the libification of Git.
It is important to note that git_default_config() is a wrapper to other git_default_*_config() such as git_default_core_config().
@@ environment.c: static int git_default_core_config(const char *var, const char *v
}
if (!strcmp(var, "core.bare")) {
+@@ environment.c: 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_path = NULL;
++}
## environment.h ##
@@ environment.h: extern const char * const local_repo_env[];
@@ environment.h: extern const char * const local_repo_env[];
/*
* Wrapper of getenv() that returns a strdup value. This value is kept
* in argv to be freed later.
+@@ environment.h: 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 @@ environment.h: extern int assume_unchanged;
extern int warn_on_object_refname_ambiguity;
extern char *apply_default_whitespace;
@@ environment.h: extern int assume_unchanged;
extern int pack_compression_level;
extern unsigned long pack_size_limit_cfg;
+ ## repository.c ##
+@@ repository.c: void initialize_repository(struct repository *repo)
+ ALLOC_ARRAY(repo->index, 1);
+ index_state_init(repo->index, repo);
+ repo->check_deprecated_config = true;
++ repo_config_values_init(&repo->config_values);
+
+ /*
+ * When a command runs inside a repository, it learns what
+
## repository.h ##
@@
2: 1e83c077f2 ! 2: fd95169de4 environment: environment: stop using core.sparseCheckout globally
@@ Commit message
when different Git repositories running in the same process access this variable.
- Move the parsed value into struct repo_config_values which holds all the
- values parsed by git_default_config() and can be accessed
- per repo via git_default_config(). This retains current
+ Move the parsed value into struct repo_config_values to retains current
behaviours while achieving the repository scoped access.
@@ Commit message
## builtin/backfill.c ##
-@@
--/* We need this macro to access core_apply_sparse_checkout */
- #define USE_THE_REPOSITORY_VARIABLE
-
- #include "builtin.h"
@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
repo_config(repo, git_default_config, NULL);
@@ environment.c: static int git_default_core_config(const char *var, const char *v
return 0;
}
+@@ environment.c: int git_default_config(const char *var, const char *value,
+ void repo_config_values_init(struct repo_config_values *cfg)
+ {
+ cfg->attributes_file_path = NULL;
++ cfg->sparse_checkout = 0;
+ }
## environment.h ##
@@ environment.h: struct strvec;
3: 6e54e22ac7 ! 3: 9a411db9f8 environment: move "branch.autoSetupMerge" into struct repo_config_values
@@ Commit message
git_branch_track. This global variable can cause unexpected behaviours
when multiple Git repos run in the the same process.
- Move this value into struct repo_config_values which holds all values
- parsed by git_default_config() and can be accessed per
- repo via git_default_config(). This would retain the same
+ Move this value into struct repo_config_values to retain current
behaviours while achieving repository scoped access.
@@ environment.c: static int git_default_i18n_config(const char *var, const char *v
return 0;
}
if (!strcmp(var, "branch.autosetuprebase")) {
-@@ environment.c: 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)
-+{
+@@ environment.c: void repo_config_values_init(struct repo_config_values *cfg)
+ {
+ cfg->attributes_file_path = NULL;
+ cfg->sparse_checkout = 0;
+ cfg->git_branch_track = BRANCH_TRACK_REMOTE;
-+}
+ }
## environment.h ##
@@
@@ environment.h: struct repo_config_values {
};
/*
-@@ environment.h: 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 -
- ## repository.c ##
-@@ repository.c: void initialize_repository(struct repository *repo)
- ALLOC_ARRAY(repo->index, 1);
- index_state_init(repo->index, repo);
- repo->check_deprecated_config = true;
-+ repo_config_values_init(&repo->config_values);
-
- /*
- * When a command runs inside a repository, it learns what
Signature · 1 line
2.34.1
PATCH v3 1/3 environment: stop storing `core.attributesFile` globally
The 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 unexpected behaviours 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() and can be accessed per repository via git_default_config(). This will ensure the current behaviour remains the same while also enabling the libification of Git.
It is important to note that git_default_config() is a wrapper to other git_default_*_config() such as git_default_core_config(). Therefore to access and modify this global variable,
the change has to be made in the function which parses and stores the value in the global variable.
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 9 ++++++++- repository.c | 1 + repository.h | 4 ++++ 5 files changed, 26 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 = &the_repository->config_values; +if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); -return git_attributes_file; +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )
environment.c +9 -3
@@ -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 = &the_repository->config_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, 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_path =NULL ; +}
environment.h +8 -1
@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];struct strvec ; +/* Config values parsed by git_default_config() */ +struct repo_config_values { +/* core config values */ +char *attributes_file_path; +}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later.
@@ -107,6 +113,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 +160,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;
repository.c +1 -0
@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what
repository.h +4 -0
@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v3 1/3] environment: stop storing `core.attributesFile` globally
Quoted 1 line · Olamide Caleb Bello
The config value is parsed in
git_default_core_config(), loaded
I assume you mean 'core.attributesFile' because it's in the title. But personnally I don't mind seeing the name repeated in the body to make it more clear.
Quoted 7 lines
eagerly and stored in the global variable
git_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.Create a new struct
repo_config_valuesto hold this value and other repository dependent values parsed bygit_default_config()and can be accessed per repository viagit_default_config().
I'd suggest to split off the part after the second 'and' into a new sentence.
Quoted 2 lines
This will ensure the current behaviour remains the same while also enabling the libification of Git.
How is this true? Was that value already accessible through git_default_config()?
Quoted 2 lines
It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()such asgit_default_core_config().
I'd suggest to insert 'functions' before 'such'.
Quoted 3 lines
Therefore to access and modify this global variable, the change has to be made in the function which parses and stores the value in the global variable.
This doesn't clarify much for me. Do you mean 'git_attr_global_file()' and 'git_default_core_config()'?
Quoted 18 lines
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 9 ++++++++- repository.c | 1 + repository.h | 4 ++++ 5 files changed, 26 insertions(+), 7 deletions(-)attr.c +0
-0
attr.c const char *git_attr_system_file(void) · line 884
Quoted 6 lines
attr.c +1
-2@@ -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 = &the_repository->config_values;
Is 'cfg' guaranteed to be != NULL?
Quoted 41 lines
attr.c +3
-1+if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); -return git_attributes_file; +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )environment.c +4
-3@@ -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 = &the_repository->config_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, var, value); }if (!strcmp (var,"core.bare" )) {
environment.c int git_default_config(const char *var, const char *value, · line 764
Quoted 8 lines
environment.c +5
-0@@ -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_path =NULL ; +}
I assume the reason for adding this function becomes clear in a later commit?
environment.h extern const char * const local_repo_env[]; · line 87
Quoted 9 lines
environment.h +1
-0@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];struct strvec ; +/* Config values parsed by git_default_config() */
Mentioning here they get filled from git_default_config() doesn't feel really correct? Although I'm sure what comment would fit better, maybe just drop the comment above the struct. I see you have a similar comment in 'struct repository', where it *does* make sense.
environment.h extern const char * const local_repo_env[]; · line 89
Quoted 2 lines
environment.h +2
-0+struct repo_config_values { +/* core config values */
I prefer emphasizing it's the "section 'core'" or something like that.
environment.h extern const char * const local_repo_env[]; · line 90
Quoted 1 line
environment.h +1
-0+char *attributes_file_path;
Would it be overkill to append: /* core.attributesFile */? This can help when grepping through the codebase to find where some settings are being parsed into. What do you think?
Quoted 60 lines
environment.h +4
-1+}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later. @@ -107,6 +113,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 +160,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;repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what repository.h +4
-0@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;Signature · 1 line
2.34.1
Signature · 2 lines
Cheers, Toon
Re: [Outreachy PATCH v3 1/3] environment: stop storing `core.attributesFile` globally
Quoted 8 lines · Toon Claes
Quoted 1 line · Olamide Caleb Bello
The config value is parsed in
git_default_core_config(), loadedI assume you mean 'core.attributesFile' because it's in the title. But personnally I don't mind seeing the name repeated in the body to make it more clear.
Hello Toon,
Okay thank you for your review.
I will take note of this.
Quoted 11 lines
Quoted 8 lines
eagerly and stored in the global variable
git_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.Create a new struct
repo_config_valuesto hold this value and other repository dependent values parsed bygit_default_config()and can be accessed per repository viagit_default_config().I'd suggest to split off the part after the second 'and' into a new sentence.
Okay
Quoted 11 lines
Quoted 3 lines
This will ensure the current behaviour remains the same while also enabling the libification of Git.
How is this true? Was that value already accessible through
git_default_config()?Quoted 2 lines
It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()such asgit_default_core_config().I'd suggest to insert 'functions' before 'such'.
Alright, noted.
Quoted 7 lines
Quoted 4 lines
Therefore to access and modify this global variable, the change has to be made in the function which parses and stores the value in the global variable.
This doesn't clarify much for me. Do you mean '
git_attr_global_file()' and 'git_default_core_config()'?
Okay I meant git_default_core_config().
I will modify it.
Quoted 67 lines
Quoted 19 lines
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 9 ++++++++- repository.c | 1 + repository.h | 4 ++++ 5 files changed, 26 insertions(+), 7 deletions(-)attr.c +0
-0attr.c const char *git_attr_system_file(void) · line 884
Quoted 6 lines
attr.c +1
-2@@ -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 = &the_repository->config_values;Is 'cfg' guaranteed to be != NULL?
Quoted 39 lines
attr.c +3
-1+if (!cfg->attributes_file_path) + cfg->attributes_file_path =xdg_config_home ("attributes" ); -return git_attributes_file; +return cfg->attributes_file_path; }int git_attr_system_is_enabled (void )environment.c +4
-3@@ -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 = &the_repository->config_values; +/* 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_path); +return git_config_pathname (&cfg->attributes_file_path, var, value); }
Quoted 13 lines
environment.c int git_default_config(const char *var, const char *value, · line 764
Quoted 10 lines
environment.c +5
-0if (!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_path =NULL ; +}I assume the reason for adding this function becomes clear in a later commit?
Yes.
Quoted 7 lines
Quoted 7 lines
environment.h +0
-0@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];
Quoted 8 lines
environment.h extern const char * const local_repo_env[]; · line 87
Quoted 3 lines
environment.h +1
-0struct strvec ; +/* Config values parsed by git_default_config() */ Mentioning here they get filled from
git_default_config()doesn't feel really correct? Although I'm sure what comment would fit better, maybe just drop the comment above the struct. I see you have a similar comment in 'struct repository', where it *does* make sense.
Okay thank you
Quoted 5 lines
environment.h extern const char * const local_repo_env[]; · line 89
Quoted 3 lines
environment.h +2
-0+struct repo_config_values { +/* core config values */ I prefer emphasizing it's the "section 'core'" or something like that.
Noted
Quoted 6 lines
environment.h extern const char * const local_repo_env[]; · line 90
Quoted 2 lines
environment.h +1
-0+char *attributes_file_path;Would it be overkill to append: /*
core.attributesFile*/? This can help when grepping through the codebase to find where some settings are being parsed into. What do you think?
Alright
Quoted 65 lines
Quoted 58 lines
environment.h +4
-1+}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later. @@ -107,6 +113,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 +160,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;repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what repository.h +4
-1@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format; --Quoted 3 lines
2.34.1
--
Cheers,
Toon
Re: [Outreachy PATCH v3 1/3] environment: stop storing `core.attributesFile` globally
In reply to Olamide Caleb BelloHi Olamide
Quoted 4 lines · Olamide Caleb Bello
The config value is parsed in
git_default_core_config(), loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.
It would maybe be helpful to explain what the unexpected behavior is and how it is caused.
environment.h extern const char * const local_repo_env[]; · line 90
Quoted 12 lines
environment.h +4
-0@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];struct strvec ; +/* Config values parsed by git_default_config() */ +struct repo_config_values { +/* core config values */ +char *attributes_file_path;
The variable we're converting is called "attributes_file", do we really need to add a "_path" suffix?
Apart from that everything here looks good
Thanks
Phillip
Quoted 56 lines
environment.h +4
-1+}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later. @@ -107,6 +113,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 +160,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;repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what repository.h +4
-0@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
Re: [Outreachy PATCH v3 1/3] environment: stop storing `core.attributesFile` globally
Quoted 2 lines · Phillip Wood
Hi Olamide
Hello Phillip
Quoted 9 lines · Olamide Caleb Bello
Quoted 4 lines
The config value is parsed in
git_default_core_config(), loaded eagerly and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.It would maybe be helpful to explain what the unexpected behavior is and how it is caused.
Okay thank you.
Quoted 9 lines
Quoted 9 lines
environment.h +0
-0@@ -84,6 +84,12 @@ extern const char * const local_repo_env[];struct strvec ;
Quoted 7 lines
environment.h extern const char * const local_repo_env[]; · line 90
Quoted 4 lines
environment.h +4
-0+/* Config values parsed by git_default_config() */ +struct repo_config_values { +/* core config values */ +char *attributes_file_path;The variable we're converting is called "
attributes_file", do we really need to add a "_path" suffix?
Okay I will remove it
Quoted 6 lines
Apart from that everything here looks good
Thanks
Phillip
Thank you
PATCH v3 2/3 environment: environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_appy_sparse_checkout. This could cause unintended behaviours when different Git repositories running in the same process access this variable.
Move the parsed value into struct repo_config_values to retains current behaviours while achieving the repository scoped access.
--- builtin/backfill.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 12 files changed, 26 insertions(+), 24 deletions(-)
builtin/backfill.c +1 -1
@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +1 -1
@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +1 -1
@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +11 -11
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -418,7 +418,7 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !repo->config_values.sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -699,9 +699,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!repo->config_values.sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ; changed_config =1 ; }
@@ -798,7 +798,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -907,7 +907,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -969,7 +969,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1035,7 +1035,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1061,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +1 -1
@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (wt->repo->config_values.sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +1 -1
@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!istate->repo->config_values.sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +2 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->sparse_checkout =git_config_bool (var, value);return 0 ; }
@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file_path =NULL ; + cfg->sparse_checkout =0 ; }
environment.h +1 -1
@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout; };/*
@@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +4 -2
@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +1 -1
@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +1 -1
@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
Olamide Caleb Bello <[email protected]> writes:
It seems you have 'environment:' twice in the title?
Quoted 3 lines
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_appy_sparse_checkout. This could cause unintended behaviours
s/core_appy_sparse_checkout/core_apply_sparse_checkout/ ?
Quoted 236 lines
when different Git repositories running in the same process access this variable.
Move the parsed value into
struct repo_config_valuesto retains current behaviours while achieving the repository scoped access.Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>--- builtin/backfill.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 12 files changed, 26 insertions(+), 24 deletions(-)builtin/backfill.c +1
-1@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {builtin/grep.c +1
-1@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by builtin/mv.c +1
-1@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to builtin/sparse-checkout.c +11
-11@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;@@ -418,7 +418,7 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !repo->config_values.sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))@@ -699,9 +699,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!repo->config_values.sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ; changed_config =1 ; }@@ -798,7 +798,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);@@ -907,7 +907,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;@@ -969,7 +969,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));@@ -1035,7 +1035,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree @@ -1061,7 +1061,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );builtin/worktree.c +1
-1@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (wt->repo->config_values.sparse_checkout)copy_sparse_checkout (sb_repo.buf);/* dir.c +1
-1@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!istate->repo->config_values.sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;environment.c +2
-2@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */ @@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->sparse_checkout =git_config_bool (var, value);return 0 ; }@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file_path =NULL ; + cfg->sparse_checkout =0 ; }environment.h +1
-0@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout; };/*
environment.h extern int precomposed_unicode; · line 172
Quoted 4 lines
environment.h +0
-1@@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;
In the field you're adding to 'struct repo_config_values' you have dropped the 'core_' prefix, what the reason for that? If I understand it correctly also settings from other sections might end up in that struct, so wouldn't it be better to keep the prefix?
Quoted 57 lines
environment.h +0
-0extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;unpack-trees.c +1
-1@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));wt-status.c +1
-1@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0. Signature · 1 line
2.34.1
Signature · 2 lines
Cheers, Toon
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
Quoted 4 lines · Toon Claes
Olamide Caleb Bello <[email protected]> writes:
It seems you have 'environment:' twice in the title?
Arh! Thank you for spotting it
Quoted 6 lines
Quoted 4 lines
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_appy_sparse_checkout. This could cause unintended behaviourss/core_appy_sparse_checkout/core_apply_sparse_checkout/ ?
Thank you.
Quoted 240 lines
Quoted 240 lines
when different Git repositories running in the same process access this variable.
Move the parsed value into
struct repo_config_valuesto retains current behaviours while achieving the repository scoped access.Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>--- builtin/backfill.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 12 files changed, 26 insertions(+), 24 deletions(-)builtin/backfill.c +1
-1@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {builtin/grep.c +1
-1@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by builtin/mv.c +1
-1@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to builtin/sparse-checkout.c +11
-11@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;@@ -418,7 +418,7 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !repo->config_values.sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))@@ -699,9 +699,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!repo->config_values.sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ; changed_config =1 ; }@@ -798,7 +798,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);@@ -907,7 +907,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;@@ -969,7 +969,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!repo->config_values.sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));@@ -1035,7 +1035,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree @@ -1061,7 +1061,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + repo->config_values.sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );builtin/worktree.c +1
-1@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (wt->repo->config_values.sparse_checkout)copy_sparse_checkout (sb_repo.buf);/* dir.c +1
-1@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!istate->repo->config_values.sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;environment.c +2
-2@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */ @@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->sparse_checkout =git_config_bool (var, value);return 0 ; }@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file_path =NULL ; + cfg->sparse_checkout =0 ; }environment.h +1
-0@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout; };/* @@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs;
Quoted 6 lines
environment.h extern int precomposed_unicode; · line 172
Quoted 1 line
environment.h +0
-1-extern int core_apply_sparse_checkout;In the field you're adding to 'struct
repo_config_values' you have dropped the 'core_' prefix, what the reason for that? If I understand it correctly also settings from other sections might end up in that struct, so wouldn't it be better to keep the prefix?
Okay, noted
Quoted 62 lines
Quoted 55 lines
environment.h +0
-0extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;unpack-trees.c +1
-1@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));wt-status.c +1
-2@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0. -- Quoted 3 lines
2.34.1
--
Cheers,
Toon
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloHi Olamide
Quoted 8 lines · Olamide Caleb Bello
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_appy_sparse_checkout. This could cause unintended behaviours when different Git repositories running in the same process access this variable.Move the parsed value into
struct repo_config_valuesto retains current behaviours while achieving the repository scoped access.
It doesn't achieve repository scoped access though because we only ever populate the values in "the_repository", all other instances of "struct repository" are initialized by config_values_init() but not the config settings.
builtin/backfill.c int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit · line 142
Quoted 10 lines
builtin/backfill.c +1
-1@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout;
Using "repo" rather than "the_repository" here is dangerous because only "the_repository" contains the parsed config. This applies throughout this patch.
Quoted 21 lines
builtin/backfill.c +0
-0result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {builtin/grep.c +0
-0
builtin/grep.c static int grep_submodule(struct grep_opt *opt, · line 485
Quoted 5 lines
builtin/grep.c +1
-1@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout"
That should be something like config_values.sparse_checkout to make it clear that "sparse_checkout" is the name of a member of a struct, not the name of a variable.
environment.h struct strvec; · line 91
Quoted 9 lines
environment.h +1
-0@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout;
There are several other sparse checkout variables like core_sparse_checkout_cone that we'll need to convert in the future so "apply_sparse_checkout" or "sparse_checkout_apply" would be better names.
Thanks
Phillip
Quoted 61 lines
environment.h +0
-1};/* @@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;unpack-trees.c +1
-1@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));wt-status.c +1
-1@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
Quoted 10 lines · Phillip Wood
Hi Olamide
Quoted 6 lines · Olamide Caleb Bello
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_appy_sparse_checkout. This could cause unintended behaviours when different Git repositories running in the same process access this variable.
Quoted 7 lines
Quoted 2 lines
Move the parsed value into
struct repo_config_valuesto retains current behaviours while achieving the repository scoped access.It doesn't achieve repository scoped access though because we only ever populate the values in "
the_repository", all other instances of "struct repository" are initialized byconfig_values_init()but not the config settings.
Okay I understand.
Thank you for clarifying.
Quoted 8 lines
Quoted 8 lines
builtin/backfill.c +0
-0@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );
Quoted 7 lines
builtin/backfill.c int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit · line 142
Quoted 3 lines
builtin/backfill.c +1
-1if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout;Using "repo" rather than "
the_repository" here is dangerous because only "the_repository" contains the parsed config. This applies throughout this patch.
Okay noted...
Sorry but I have a question.
I observed that the address of "repo" is passed to builtin/backfill.c, is gotten from git.c:handle_builtin
which passed run_builtin "the_repository" as a parameter.
Won't the address of "repo" and "the_repository be the same"?
Quoted 15 lines
Quoted 15 lines
builtin/backfill.c +0
-0result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;
Quoted 16 lines
builtin/grep.c static int grep_submodule(struct grep_opt *opt, · line 485
Quoted 12 lines
builtin/clone.c +0
-0cmd.git_cmd =1 ;if (run_command (&cmd)) {builtin/grep.c +1
-1@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" That should be something like config_values.sparse_checkout to make it clear that "
sparse_checkout" is the name of a member of a struct, not the name of a variable.
Okay noted
Quoted 14 lines
environment.h struct strvec; · line 91
Quoted 10 lines
environment.h +1
-0@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout;There are several other sparse checkout variables like
core_sparse_checkout_conethat we'll need to convert in the future so "apply_sparse_checkout" or "sparse_checkout_apply" would be better names.
Okay noted.
Quoted 68 lines
Thanks
Phillip
Quoted 61 lines
environment.h +0
-1};/* @@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;unpack-trees.c +1
-1@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));wt-status.c +1
-1@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
Quoted 17 lines · Bello Olamide
Quoted 8 lines · Phillip Wood
Quoted 8 lines
builtin/backfill.c +0
-0@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );Quoted 7 lines
builtin/backfill.c int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit · line 142
Quoted 3 lines
builtin/backfill.c +1
-1if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout;Using "repo" rather than "
the_repository" here is dangerous because only "the_repository" contains the parsed config. This applies throughout this patch.
Quoted 2 lines
Okay noted...
Sorry but I have a question.
You don't need to be sorry for having a question - it shows you have been thinking about the feedback you have received which is very good.
Quoted 5 lines
I observed that the address of "repo" is passed to
builtin/backfill.c, is gotten from git.c:handle_builtin
which passedrun_builtin"the_repository" as a parameter.Won't the address of "repo" and "
the_repositorybe the same"?
Yes, but I think it is safer to explicitly say "the_repository" so that
if any of the functions you convert here are ever passed another repository instance the code will keep working as expected. It also documents that the config value is only stored in "the_repository". Once we make these config values per-repository then we can use the repository instance passed to the function.
Thanks
Phillip
Quoted 119 lines
Quoted 15 lines
Quoted 15 lines
builtin/backfill.c +0
-0result =do_backfill (&ctx);backfill_context_clear (&ctx);builtin/clone.c +1
-1@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.sparse_checkout =1 ;Quoted 16 lines
builtin/grep.c static int grep_submodule(struct grep_opt *opt, · line 485
Quoted 12 lines
builtin/clone.c +0
-0cmd.git_cmd =1 ;if (run_command (&cmd)) {builtin/grep.c +1
-1@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "sparse_checkout" That should be something like config_values.sparse_checkout to make it clear that "
sparse_checkout" is the name of a member of a struct, not the name of a variable.Okay noted
Quoted 14 lines
environment.h struct strvec; · line 91
Quoted 10 lines
environment.h +1
-0@@ -88,6 +88,7 @@ struct strvec;struct repo_config_values {/* core config values */ char *attributes_file_path; +int sparse_checkout;There are several other sparse checkout variables like
core_sparse_checkout_conethat we'll need to convert in the future so "apply_sparse_checkout" or "sparse_checkout_apply" would be better names.Okay noted.
Quoted 68 lines
Thanks
Phillip
Quoted 61 lines
environment.h +0
-1};/* @@ -169,7 +170,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &istate->repo->config_values; +if (!cfg->sparse_checkout || sparse_expect_files_outside_of_patterns)return ;unpack-trees.c +1
-1@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!repo->config_values.sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));wt-status.c +1
-1@@ -1764,7 +1764,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!r->config_values.sparse_checkout || r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Re: [Outreachy PATCH v3 2/3] environment: environment: stop using core.sparseCheckout globally
Quoted 19 lines · Phillip Wood
Quoted 17 lines · Bello Olamide
Quoted 15 lines · Phillip Wood
builtin/backfill.c int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit · line 142
Quoted 11 lines
builtin/backfill.c +1
-1@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = repo->config_values.sparse_checkout;Using "repo" rather than "
the_repository" here is dangerous because only "the_repository" contains the parsed config. This applies throughout this patch.
Quoted 5 lines
Quoted 2 lines
Okay noted...
Sorry but I have a question.You don't need to be sorry for having a question - it shows you have been thinking about the feedback you have received which is very good.
Thank you
Quoted 5 lines
Quoted 5 lines
I observed that the address of "repo" is passed to
builtin/backfill.c, is gotten from git.c:handle_builtin
which passedrun_builtin"the_repository" as a parameter.
Quoted 8 lines
Quoted 1 line
Won't the address of "repo" and "
the_repositorybe the same"?Yes, but I think it is safer to explicitly say "
the_repository" so that if any of the functions you convert here are ever passed another repository instance the code will keep working as expected. It also documents that the config value is only stored in "the_repository". Once we make these config values per-repository then we can use the repository instance passed to the function.
Okay thank you for clarifying.
PATCH v3 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value brach.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.
Move this value into struct repo_config_values to retain current behaviours while achieving repository scoped access.
--- branch.h | 2 -- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/push.c | 2 +- builtin/submodule--helper.c | 2 +- environment.c | 12 +++++++----- environment.h | 4 ++++ 7 files changed, 15 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +1 -1
@@ -795,7 +795,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = the_repository->config_values.git_branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +1 -1
@@ -1631,7 +1631,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = the_repository->config_values.git_branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +1 -1
@@ -162,7 +162,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (the_repository->config_values.git_branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +1 -1
@@ -3128,7 +3128,7 @@ static int module_create_branch(int argc, const char **argv, const char *prefix, };repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = the_repository->config_values.git_branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +7 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg = &the_repository->config_values; +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->git_branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->git_branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->git_branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->git_branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -761,4 +762,5 @@ void repo_config_values_init(struct repo_config_values *cfg) { cfg->attributes_file_path =NULL ; cfg->sparse_checkout =0 ; + cfg->git_branch_track =BRANCH_TRACK_REMOTE ; }
environment.h +4 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -89,6 +90,9 @@ struct repo_config_values {/* core config values */ char *attributes_file_path;int sparse_checkout; + +/* branch config values */ +enum branch_track git_branch_track; };/*
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v3 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Hi Olamide
Quoted 7 lines · Olamide Caleb Bello
The config value
brach.autoSetupMergeis parsed ingit_default_branch_config()and stored in the global variablegit_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.Move this value into
struct repo_config_valuesto retain current behaviours while achieving repository scoped access.
Same comment as the previous patch about repository scoped access.
Quoted 13 lines
environment.h +1
-0@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
environment.h struct repo_config_values { · line 95
Quoted 6 lines
environment.h +3
-0@@ -89,6 +90,9 @@ struct repo_config_values {/* core config values */ char *attributes_file_path;int sparse_checkout; + +/* branch config values */ +enum branch_track git_branch_track;
We could probably drop the "git_" prefix now that it is not a global variable.
Thanks
Phillip
Re: [Outreachy PATCH v3 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 9 lines · Phillip Wood
Hi Olamide
Quoted 5 lines · Olamide Caleb Bello
The config value
brach.autoSetupMergeis parsed ingit_default_branch_config()and stored in the global variablegit_branch_track. This global variable can cause unexpected behaviours when multiple Git repos run in the the same process.
Quoted 4 lines
Quoted 2 lines
Move this value into
struct repo_config_valuesto retain current behaviours while achieving repository scoped access.Same comment as the previous patch about repository scoped access.
Okay thank you
Quoted 11 lines
Quoted 11 lines
environment.h +1
-0@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h"
Quoted 12 lines
environment.h struct repo_config_values { · line 95
Quoted 9 lines
environment.h +3
-0/* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"@@ -89,6 +90,9 @@ struct repo_config_values {/* core config values */ char *attributes_file_path;int sparse_checkout; + +/* branch config values */ +enum branch_track git_branch_track;We could probably drop the "
git_" prefix now that it is not a global variable.
Alright thank you for the review.
Quoted 5 lines
Thanks
Phillip
Re: [Outreachy PATCH v3 0/3] store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloQuoted 223 lines · Olamide Caleb Bello
Hi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables inenvironment.hinto local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use ofprepare_repo_settings()with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to
git_default_config()to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to
git_default_config().For now, the parsed value is stored in
the_repositoryingit_default_*_config()and further efforts to pass the repository parameter togit_default_config()as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2266020513Changes in v3:
==============
- Moved declaration and definition ofrepo_config_values_initinto patch 1
- Returned commit message in line 1 ofbuiltin/backfill.cOlamide Caleb Bello (3):
environment: stop storingcore.attributesFileglobally
environment: environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 2 +- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 22 +++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 28 ++++++++++++++++++---------- environment.h | 15 +++++++++++++-- repository.c | 1 + repository.h | 4 ++++ sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 2 +- 20 files changed, 67 insertions(+), 42 deletions(-)Range diff versus v2:
=====================1:
b6f8deaa40! 1:1aa41da833environment: stop storingcore.attributesFileglobally
@@ Metadata
## Commit message ##
environment: stop storingcore.attributesFileglobally- The config value parsed in
git_default_core_config()is loaded eagerly
+ The config value is parsed ingit_default_core_config(), loaded eagerly
and stored in the global variablegit_attributes_file. Storing this value in a global variable can lead to unexpected behaviours when more than one Git repository run in the same Git process.- Move this value into a
struct repo_config_valueswhich holds all the
- values parsed bygit_default_config()and can be accessed per
- repository viagit_default_config(). This will ensure the current
- behaviour remains the same while also enabling the libification of Git.
+ Create a new structrepo_config_valuesto hold this value and
+ other repository dependent values parsed bygit_default_config()and
+ can be accessed per repository viagit_default_config().
+ This will ensure the current behaviour remains the same while also
+ enabling the libification of Git.It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()such asgit_default_core_config().
@@environment.c: static int git_default_core_config(const char *var, const char *v
}if (!strcmp(var, "core.bare")) {
+@@environment.c: int git_default_config(const char *var, const char *value,
+ /* Add other config variables here and toDocumentation/config.adoc. */
+ return 0;
+ }
++
++voidrepo_config_values_init(struct repo_config_values *cfg)++{
++cfg->attributes_file_path= NULL;
++}##
environment.h##
@@environment.h: extern const char * const local_repo_env[];
@@environment.h: extern const char * const local_repo_env[];
/*
* Wrapper ofgetenv()that returns a strdup value. This value is kept
* in argv to be freed later.
+@@environment.h: const char *strip_namespace(const char*namespaced_ref);
+ int git_default_config(const char *, const char *,
+ const structconfig_context*, void *);
+
++voidrepo_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 @@environment.h: extern intassume_unchanged;
extern intwarn_on_object_refname_ambiguity;
extern char*apply_default_whitespace;
@@environment.h: extern intassume_unchanged;
extern intpack_compression_level;
extern unsigned longpack_size_limit_cfg;+ ##
repository.c##
+@@repository.c: voidinitialize_repository(struct repository *repo)
+ALLOC_ARRAY(repo->index, 1);
+index_state_init(repo->index, repo);
+repo->check_deprecated_config= true;
++repo_config_values_init(&repo->config_values);
+
+ /*
+ * When a command runs inside a repository, it learns what
+
##repository.h##
@@2:
1e83c077f2! 2:fd95169de4environment: environment: stop using core.sparseCheckout globally
@@ Commit message
when different Git repositories running in the same process access this variable.- Move the parsed value into
struct repo_config_valueswhich holds all the
- values parsed bygit_default_config()and can be accessed
- per repo viagit_default_config(). This retains current
+ Move the parsed value intostruct repo_config_valuesto retains current
behaviours while achieving the repository scoped access.Suggested-by Phillip Wood <[email protected]>@@ Commit message
Signed-off-by Olamide Caleb Bello <[email protected]>##
builtin/backfill.c##
-@@
--/* We need this macro to accesscore_apply_sparse_checkout*/
- #defineUSE_THE_REPOSITORY_VARIABLE
-
- #include "builtin.h"
@@builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
repo_config(repo, git_default_config, NULL);@@
environment.c: static int git_default_core_config(const char *var, const char *v
return 0;
}+@@
environment.c: int git_default_config(const char *var, const char *value,
+ voidrepo_config_values_init(struct repo_config_values *cfg)
+ {
+cfg->attributes_file_path= NULL;
++cfg->sparse_checkout= 0;
+ }##
environment.h##
@@environment.h: struct strvec;
3:6e54e22ac7! 3:9a411db9f8environment: move "branch.autoSetupMerge" intostruct repo_config_values
@@ Commit message
git_branch_track. This global variable can cause unexpected behaviours
when multiple Git repos run in the the same process.- Move this value into
struct repo_config_valueswhich holds all values
- parsed bygit_default_config()and can be accessed per
- repo viagit_default_config(). This would retain the same
+ Move this value intostruct repo_config_valuesto retain current
behaviours while achieving repository scoped access.Suggested-by Phillip Wood <[email protected]>@@
environment.c: static int git_default_i18n_config(const char *var, const char *v
return 0;
}
if (!strcmp(var, "branch.autosetuprebase")) {
-@@environment.c: int git_default_config(const char *var, const char *value,
- /* Add other config variables here and toDocumentation/config.adoc. */
- return 0;
- }
-+
-+voidrepo_config_values_init(struct repo_config_values *cfg)
-+{
+@@environment.c: voidrepo_config_values_init(struct repo_config_values *cfg)
+ {
+cfg->attributes_file_path= NULL;
+cfg->sparse_checkout= 0;
+cfg->git_branch_track=BRANCH_TRACK_REMOTE;
-+}
+ }##
environment.h##
@@
@@environment.h: structrepo_config_values{
};/*
-@@environment.h: const char *strip_namespace(const char*namespaced_ref);
- int git_default_config(const char *, const char *,
- const structconfig_context*, void *);
-
-+voidrepo_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 -
- ##repository.c##
Quoted 10 lines
-@@
repository.c: voidinitialize_repository(struct repository *repo)
-ALLOC_ARRAY(repo->index, 1);
-index_state_init(repo->index, repo);
-repo->check_deprecated_config= true;
-+repo_config_values_init(&repo->config_values);
-
- /*
- * When a command runs inside a repository, it learns what
Hello
Replying to this to get reviews and feedback.
Thanks
v4 cover store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2266020513
Changes in v4:
==============
- Changed variable name in the struct to attributes_file
- Modified commit messages in all patches to explain how the variable being global can be overwritten when the process has multiple repositories
- Changed the variable name in patch 2 to apply_sparse_checkout
- Changes the variable name in patch 3 to branch_track
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 2 +- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 23 ++++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 28 ++++++++++++++++++---------- environment.h | 14 ++++++++++++-- repository.c | 1 + repository.h | 4 ++++ sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 20 files changed, 68 insertions(+), 42 deletions(-)
Range diff versus v3:
=====================
1: 1aa41da833 ! 1: d28850bcdb environment: stop storing core.attributesFile globally
@@ Metadata
## Commit message ##
environment: stop storing `core.attributesFile` globally
- The 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 unexpected
- behaviours when more than one Git repository run in the same Git process.
+ 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()` and
- can be accessed per repository via `git_default_config()`.
+ other repository dependent values parsed by `git_default_config()`.
+ For now the value can be accessed via the_repository in
+ `git_default_config()`.
This will ensure the current behaviour remains the same while also
enabling the libification of Git.
It is important to note that `git_default_config()` is a wrapper to other
- `git_default_*_config()` such as `git_default_core_config()`.
+ `git_default_*_config()` functions such as `git_default_core_config()`.
Therefore to access and modify this global variable,
- the change has to be made in the function which parses and
- stores the value in the global variable.
+ the change has to be made `git_default_core_config()`.
Suggested-by: Phillip Wood <[email protected]>
Mentored-by: Christian Couder <[email protected]>
@@ attr.c: const char *git_attr_system_file(void)
- if (!git_attributes_file)
- git_attributes_file = xdg_config_home("attributes");
+ struct repo_config_values *cfg = &the_repository->config_values;
-+ if (!cfg->attributes_file_path)
-+ cfg->attributes_file_path = xdg_config_home("attributes");
++ if (!cfg->attributes_file)
++ cfg->attributes_file = xdg_config_home("attributes");
- return git_attributes_file;
-+ return cfg->attributes_file_path;
++ return cfg->attributes_file;
}
int git_attr_system_is_enabled(void)
@@ environment.c: static int git_default_core_config(const char *var, const char *v
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_path);
-+ return git_config_pathname(&cfg->attributes_file_path, var, value);
++ FREE_AND_NULL(cfg->attributes_file);
++ return git_config_pathname(&cfg->attributes_file, var, value);
}
if (!strcmp(var, "core.bare")) {
@@ environment.c: int git_default_config(const char *var, const char *value,
+
+void repo_config_values_init(struct repo_config_values *cfg)
+{
-+ cfg->attributes_file_path = NULL;
++ cfg->attributes_file = NULL;
+}
## environment.h ##
@@ environment.h: extern const char * const local_repo_env[];
struct strvec;
-+/* Config values parsed by git_default_config() */
+struct repo_config_values {
-+ /* core config values */
-+ char *attributes_file_path;
++ /* section "core" config values */
++ char *attributes_file;
+};
+
/*
2: fd95169de4 ! 2: e44ce7be3d environment: environment: stop using core.sparseCheckout globally
@@ Metadata
Author: Olamide Caleb Bello <[email protected]>
## Commit message ##
- environment: environment: stop using core.sparseCheckout globally
+ environment: stop using core.sparseCheckout globally
The config value `core.sparseCheckout` is parsed in
`git_default_core_config()` and stored globally in
- `core_appy_sparse_checkout`. This could cause unintended behaviours
- when different Git repositories running in the same process access this
- variable.
+ `core_apply_sparse_checkout`. This could cause it to be overwritten
+ by another repository when different Git repositories run in the same
+ process.
- Move the parsed value into `struct repo_config_values` to retains current
- behaviours while achieving the repository scoped access.
+ Move the parsed value into `struct repo_config_values` in the_repository
+ to retain current behaviours and move towards libifying Git.
Suggested-by: Phillip Wood <[email protected]>
Mentored-by: Christian Couder <[email protected]>
@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *pr
if (ctx.sparse < 0)
- ctx.sparse = core_apply_sparse_checkout;
-+ ctx.sparse = repo->config_values.sparse_checkout;
++ ctx.sparse = the_repository->config_values.apply_sparse_checkout;
result = do_backfill(&ctx);
backfill_context_clear(&ctx);
@@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)
* for the later checkout to use the sparse-checkout file.
*/
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.sparse_checkout = 1;
++ the_repository->config_values.apply_sparse_checkout = 1;
cmd.git_cmd = 1;
if (run_command(&cmd)) {
@@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,
* of these submodules are expanded unexpectedly.
*
- * 2. "core_apply_sparse_checkout"
-+ * 2. "sparse_checkout"
++ * 2. "config_values.apply_sparse_checkout"
* When running `grep` in the superproject, this setting is
* populated using the superproject's configs. However, once
* initialized, this config is globally accessible and is read by
@@ builtin/mv.c: int cmd_mv(int argc,
if (ignore_sparse &&
- core_apply_sparse_checkout &&
-+ the_repository->config_values.sparse_checkout &&
++ the_repository->config_values.apply_sparse_checkout &&
core_sparse_checkout_cone) {
/*
* NEEDSWORK: we are *not* paying attention to
@@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.sparse_checkout)
++ if (!the_repository->config_values.apply_sparse_checkout)
die(_("this worktree is not sparse"));
argc = parse_options(argc, argv, prefix,
@@ builtin/sparse-checkout.c: static int set_config(struct repository *repo,
static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
/* If not specified, use previous definition of cone mode */
- if (*cone_mode == -1 && core_apply_sparse_checkout)
-+ if (*cone_mode == -1 && the_repository->config_values.sparse_checkout)
++ if (*cone_mode == -1 && the_repository->config_values.apply_sparse_checkout)
*cone_mode = core_sparse_checkout_cone;
/* Set cone/non-cone mode appropriately */
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.sparse_checkout = 1;
++ the_repository->config_values.apply_sparse_checkout = 1;
if (*cone_mode == 1 || *cone_mode == -1) {
core_sparse_checkout_cone = 1;Signature · 1 line
2.34.1
PATCH v4 1/3 environment: stop storing `core.attributesFile` globally
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(). For now the value can be accessed via the_repository in git_default_config().
This will ensure the current behaviour remains the same while also enabling the libification of Git.
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().
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 8 +++++++- repository.c | 1 + repository.h | 4 ++++ 5 files changed, 25 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 = &the_repository->config_values; +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 )
environment.c +9 -3
@@ -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 = &the_repository->config_values; +/* 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 ; +}
environment.h +7 -1
@@ -84,6 +84,11 @@ extern const char * const local_repo_env[];struct strvec ; +struct repo_config_values { +/* section "core" config values */ +char *attributes_file; +}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later.
@@ -107,6 +112,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 +159,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;
repository.c +1 -0
@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what
repository.h +4 -0
@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
Signature · 1 line
2.34.1
PATCH v4 2/3 environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.
Move the parsed value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git.
--- builtin/backfill.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 23 ++++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 12 files changed, 28 insertions(+), 24 deletions(-)
builtin/backfill.c +1 -1
@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = the_repository->config_values.apply_sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +1 -1
@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "config_values.apply_sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +1 -1
@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.apply_sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +12 -11
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.apply_sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -418,7 +418,8 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || + !the_repository->config_values.apply_sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -699,9 +700,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!the_repository->config_values.apply_sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ; changed_config =1 ; }
@@ -798,7 +799,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -907,7 +908,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -969,7 +970,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1035,7 +1036,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.apply_sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1062,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +1 -1
@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (the_repository->config_values.apply_sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +1 -1
@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +2 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->apply_sparse_checkout =git_config_bool (var, value);return 0 ; }
@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file =NULL ; + cfg->apply_sparse_checkout =0 ; }
environment.h +1 -1
@@ -87,6 +87,7 @@ struct strvec;struct repo_config_values {/* section "core" config values */ char *attributes_file; +int apply_sparse_checkout; };/*
@@ -168,7 +169,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +4 -2
@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &the_repository->config_values; +if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &the_repository->config_values; +if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +1 -1
@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!the_repository->config_values.apply_sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +2 -1
@@ -1764,7 +1764,8 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!the_repository->config_values.apply_sparse_checkout || + r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
PATCH v4 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value brach.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can be overwritten
by another repository when multiple Git repos run in the the same process.
Move this value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git. Since the variable is no longer a global variable, it has been renamed to branch_track in the struct repo_config_values.
--- branch.h | 2 -- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/push.c | 2 +- builtin/submodule--helper.c | 2 +- environment.c | 12 +++++++----- environment.h | 4 ++++ 7 files changed, 15 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +1 -1
@@ -795,7 +795,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = the_repository->config_values.branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +1 -1
@@ -1631,7 +1631,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = the_repository->config_values.branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +1 -1
@@ -162,7 +162,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (the_repository->config_values.branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +1 -1
@@ -3128,7 +3128,7 @@ static int module_create_branch(int argc, const char **argv, const char *prefix, };repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = the_repository->config_values.branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +7 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg = &the_repository->config_values; +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -761,4 +762,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 ; }
environment.h +4 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -88,6 +89,9 @@ struct repo_config_values {/* section "core" config values */ char *attributes_file;int apply_sparse_checkout; + +/* section "branch" config values */ +enum branch_track branch_track; };/*
Signature · 1 line
2.34.1
v5 cover store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2266020513
Changes in v5:
==============
- Corrected mistake in commit message of patch 3 which spelt branch wrongly in branch.autoSetupmerge
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 2 +- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/push.c | 2 +- builtin/sparse-checkout.c | 23 ++++++++++++----------- builtin/submodule--helper.c | 2 +- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 28 ++++++++++++++++++---------- environment.h | 14 ++++++++++++-- repository.c | 1 + repository.h | 4 ++++ sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 20 files changed, 68 insertions(+), 42 deletions(-)
Range diff versus v4:
====================
1: d28850bcdb = 1: d28850bcdb environment: stop storing `core.attributesFile` globally 2: 5e56e1cc41 = 2: 5e56e1cc41 environment: stop using core.sparseCheckout globally 3: aed3183321 ! 3: e7f37bac87 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
@@ Metadata
## Commit message ##
environment: move "branch.autoSetupMerge" into struct repo_config_values
- The config value brach.autoSetupMerge is parsed in
+ The config value branch.autoSetupMerge is parsed in
git_default_branch_config() and stored in the global variable git_branch_track. This global variable can be overwritten by another repository when multiple Git repos run in the the same process.
Signature · 1 line
2.34.1
PATCH v5 1/3 environment: stop storing `core.attributesFile` globally
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(). For now the value can be accessed via the_repository in git_default_config().
This will ensure the current behaviour remains the same while also enabling the libification of Git.
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().
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 8 +++++++- repository.c | 1 + repository.h | 4 ++++ 5 files changed, 25 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 = &the_repository->config_values; +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 )
environment.c +9 -3
@@ -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 = &the_repository->config_values; +/* 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 ; +}
environment.h +7 -1
@@ -84,6 +84,11 @@ extern const char * const local_repo_env[];struct strvec ; +struct repo_config_values { +/* section "core" config values */ +char *attributes_file; +}; +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later.
@@ -107,6 +112,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 +159,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;
repository.c +1 -0
@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what
repository.h +4 -0
@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v5 1/3] environment: stop storing `core.attributesFile` globally
attr.c const char *git_attr_system_file(void) · line 884
Quoted 5 lines · Olamide Caleb Bello
const char
*git_attr_global_file(void)
{attr.c +1
-2-if (!git_attributes_file) - git_attributes_file =xdg_config_home ("attributes" ); +struct repo_config_values *cfg = &the_repository->config_values;
Here, the_repository, being defined in repository.c as the address of a singleton "the_repo" instance, cannot be NULL even outside a repository, so taking the address of its config_values member is always safe. OK.
Quoted 20 lines
attr.c +3
-1+if (!cfg->attributes_file) + cfg->attributes_file =xdg_config_home ("attributes" ); -return git_attributes_file; +return cfg->attributes_file; }repository.h +1
-0@@ -3,6 +3,7 @@#include "strmap.h" #include "repo-settings.h" +#include "environment.h" struct config_set ;struct git_hash_algo ;
repository.h struct repository { · line 156
Quoted 8 lines
repository.h +3
-0@@ -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; +/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
And because this new config_values member is directly embedded in the repository structure, and "the_repo" instance is a global in BSS, its members are initialized exactly the same way as the global variables like git_attributes_file were initialized. Good.
environment.c char *git_commit_encoding; · line 56
Quoted 9 lines
environment.c +0
-1@@ -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;
And we lose this global, that used to be zero-initialized for being in BSS.
Quoted 21 lines
environment.c +4
-2@@ -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 = &the_repository->config_values; +/* 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" )) {
environment.c int git_default_config(const char *var, const char *value, · line 759
Quoted 3 lines
environment.c +0
-0@@ -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 ; }
And instead of assigning to the global git_attributes_file, we assign to the config_values.attributes_file member via the global "the_repository". No functional changes. OK.
environment.c int git_default_config(const char *var, const char *value, · line 764
Quoted 4 lines
environment.c +4
-0+void repo_config_values_init (struct repo_config_values *cfg) +{ + cfg->attributes_file =NULL ; +}
This is not strictly needed, as git_attributes_file is left to be zero-initialized for being in BSS; its replacement, i.e., the_repo.config_values.attributes_file, will be zero-initialized the same way.
But other members we may want add later to the struct may need a place to initialize them. Or we can do a static initialization for the_repo in repository.c then we do not have to have this function and we do not have to call it. Either would work fine, as long as everybody calls initialize_repository() function, which is the only caller of this helper.
environment.h extern const char * const local_repo_env[]; · line 90
Quoted 12 lines
environment.h +4
-0@@ -84,6 +84,11 @@ extern const char * const local_repo_env[];struct strvec ; +struct repo_config_values { +/* section "core" config values */ +char *attributes_file; +};
OK.
repository.c void initialize_repository(struct repository *repo) · line 63
Quoted 12 lines
repository.c +1
-0@@ -57,6 +57,7 @@ void initialize_repository(struct repository *repo)ALLOC_ARRAY (repo->index,1 );index_state_init (repo->index, repo); repo->check_deprecated_config = true; +repo_config_values_init (&repo->config_values);/* * When a command runs inside a repository, it learns what
Continuing the discussion on repo_config_values_init(), currently, initialize_repository() is called by init_git(), which is called from "main()", so it should be fairly safe to assume that all in Git codebase will call repo_config_values_init().
But those who replace "main()" for their own libified use of Git code may not call init_git() hence initialize_repository() hence your repo_config_values_init(). In that sense, this is less safe than the other alternative.
PATCH v5 2/3 environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.
Move the parsed value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git.
--- builtin/backfill.c | 2 +- builtin/clone.c | 2 +- builtin/grep.c | 2 +- builtin/mv.c | 2 +- builtin/sparse-checkout.c | 23 ++++++++++++----------- builtin/worktree.c | 2 +- dir.c | 2 +- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 2 +- wt-status.c | 3 ++- 12 files changed, 28 insertions(+), 24 deletions(-)
builtin/backfill.c +1 -1
@@ -139,7 +139,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = the_repository->config_values.apply_sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +1 -1
@@ -623,7 +623,7 @@ static int git_sparse_checkout_init(const char *repo)* We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "config_values.apply_sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +1 -1
@@ -572,7 +572,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + the_repository->config_values.apply_sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +12 -11
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,int res;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -400,11 +400,11 @@ static int set_config(struct repository *repo,static enum sparse_checkout_mode update_cone_mode (int *cone_mode) {/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && the_repository->config_values.apply_sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -418,7 +418,8 @@ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_indint mode, record_mode;/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || + !the_repository->config_values.apply_sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -699,9 +700,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!the_repository->config_values.apply_sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ; changed_config =1 ; }
@@ -798,7 +799,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,int ret;setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -907,7 +908,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -969,7 +970,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1035,7 +1036,7 @@ static int sparse_checkout_disable(int argc, const char **argv,struct pattern_list pl;/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.apply_sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1062,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + the_repository->config_values.apply_sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +1 -1
@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (the_repository->config_values.apply_sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +1 -1
@@ -1551,7 +1551,7 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +if (!the_repository->config_values.apply_sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +2 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->apply_sparse_checkout =git_config_bool (var, value);return 0 ; }
@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file =NULL ; + cfg->apply_sparse_checkout =0 ; }
environment.h +1 -1
@@ -87,6 +87,7 @@ struct strvec;struct repo_config_values {/* section "core" config values */ char *attributes_file; +int apply_sparse_checkout; };/*
@@ -168,7 +169,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +4 -2
@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg = &the_repository->config_values; +if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg = &the_repository->config_values; +if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +1 -1
@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!the_repository->config_values.apply_sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +2 -1
@@ -1764,7 +1764,8 @@ static void wt_status_check_sparse_checkout(struct repository *r,int skip_worktree =0 ;int i; -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!the_repository->config_values.apply_sparse_checkout || + r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v5 2/3] environment: stop using core.sparseCheckout globally
Quoted 6 lines · Olamide Caleb Bello
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.
Quoted 8 lines
Move the parsed value into
struct repo_config_valuesinthe_repositoryto retain current behaviours and move towards libifying Git.Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>---
A lot of changes, almost all of which are mechanical
s/core_apply_sparse_checkout/the_repository->config_values.apply_sparse_checkout/
changes, which is very straight-forward.
The same comment applies. Do we want programs to require calling repo_config_values_init(), or should we rely on program load-time initialization, like all these globals that are moved to the repo_config_values struct used to do?
I do not have a good answer to this question, but so far, these two global variables that were both zero initialized for being in BSS do not *need* initialization byh an explicit runtime assignment that repo_config_values_init() allows us to do.
PATCH v5 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value branch.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can be overwritten
by another repository when multiple Git repos run in the the same process.
Move this value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git. Since the variable is no longer a global variable, it has been renamed to branch_track in the struct repo_config_values.
--- branch.h | 2 -- builtin/branch.c | 2 +- builtin/checkout.c | 2 +- builtin/push.c | 2 +- builtin/submodule--helper.c | 2 +- environment.c | 12 +++++++----- environment.h | 4 ++++ 7 files changed, 15 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +1 -1
@@ -795,7 +795,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = the_repository->config_values.branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +1 -1
@@ -1631,7 +1631,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = the_repository->config_values.branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +1 -1
@@ -162,7 +162,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (the_repository->config_values.branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +1 -1
@@ -3128,7 +3128,7 @@ static int module_create_branch(int argc, const char **argv, const char *prefix, };repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = the_repository->config_values.branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +7 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg = &the_repository->config_values; +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -761,4 +762,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 ; }
environment.h +4 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -88,6 +89,9 @@ struct repo_config_values {/* section "core" config values */ char *attributes_file;int apply_sparse_checkout; + +/* section "branch" config values */ +enum branch_track branch_track; };/*
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v5 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 1 line · Olamide Caleb Bello
-enum
branch_trackgit_branch_track=BRANCH_TRACK_REMOTE;
Unlike the other two, this global variable was not zero-initialized, so we can do something like this to initialize it statically in the new world order. That way, we do not need to worry about the repo_config_values_init() helper function, which (1) we can easily forget to adjust, and (2) third-party may not be able to call.
repository.c +5 -1
@@ -25,7 +25,11 @@extern struct repository *the_repository;/* The main repository */ -static struct repository the_repo; +static struct repository the_repo = { + .config_values = { + .branch_track =BRANCH_TRACK_REMOTE , + }, +};struct repository *the_repository = &the_repo;/*
Quoted 56 lines
enum
rebase_setup_typeautorebase =AUTOREBASE_NEVER; enumpush_default_typepush_default=PUSH_DEFAULT_UNSPECIFIED; #ifndefOBJECT_CREATION_MODE(quoted diff) +7
-4@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value) static int git_default_branch_config(const char *var, const char *value) { + struct repo_config_values *cfg = &the_repository->config_values; + if (!strcmp(var, "branch.autosetupmerge")) { if (value && !strcmp(value, "always")) { - git_branch_track = BRANCH_TRACK_ALWAYS; + cfg->branch_track = BRANCH_TRACK_ALWAYS; return 0; } else if (value && !strcmp(value, "inherit")) { - git_branch_track = BRANCH_TRACK_INHERIT; + cfg->branch_track = BRANCH_TRACK_INHERIT; return 0; } else if (value && !strcmp(value, "simple")) { - git_branch_track = BRANCH_TRACK_SIMPLE; + cfg->branch_track = BRANCH_TRACK_SIMPLE; return 0; } - git_branch_track = git_config_bool(var, value); + cfg->branch_track = git_config_bool(var, value); return 0; } if (!strcmp(var, "branch.autosetuprebase")) {@@ -761,4 +762,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; }environment.h +4
-0@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"@@ -88,6 +89,9 @@ struct repo_config_values {/* section "core" config values */ char *attributes_file;int apply_sparse_checkout; + +/* section "branch" config values */ +enum branch_track branch_track; };/*
Re: [Outreachy PATCH v5 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 15 lines · Junio C Hamano
Quoted 1 line · Olamide Caleb Bello
-enum
branch_trackgit_branch_track=BRANCH_TRACK_REMOTE;Unlike the other two, this global variable was not zero-initialized, so we can do something like this to initialize it statically in the new world order. That way, we do not need to worry about the
repo_config_values_init()helper function, which (1) we can easily forget to adjust, and (2) third-party may not be able to call.repository.c +0
-0
repository.c line 32
Quoted 9 lines
repository.c +5
-1@@ -25,7 +25,11 @@extern struct repository *the_repository;/* The main repository */ -static struct repository the_repo; +static struct repository the_repo = { + .config_values = { + .branch_track =BRANCH_TRACK_REMOTE , + }, +};
After having slept over this one, I think a static initialization, which mimicks what we have been doing with the global variables very closely, is not what we want in the longer term.
The aim of these patches is to prepare for a new world order in which we can add new Git subcommands that operates in two or more repositories at the same time, and have these repositories use their own versions of these "global" variables independently. While the static initialization has these advantages:
* Once the code is written, no new command can forget to initialize them; initialization happens at the program load time.
* No programming error can wipe what has already been read from the configuration by making a second repo_config_values_init() call by mistake.
neither of these advantages apply to second and subsequent repositories. We'd need to somehow initialize an instance of a repository that is not "the_repo".
And for that, repo_config_values_init() is needed, even though it adds the downsides that are opposite of the above two advantages of not having to have an "initialization" step.
So, we need to take it as a given that repo_config_values_init() needs to exist. Under that condition, I wonder if we can somehow have a cheap way to assert the following two things:
* Before a repository instance is used, repo_config_values_init() has been called on it, as using an instance without initializing is a no-no.
* repo_config_values_init() is never called twice on a repository instance, as the second call will wipe what the first call and subsequent reading of the configuration files have done.
Thanks.
Re: [Outreachy PATCH v5 3/3] environment: move "branch.autoSetupMerge" into `struct repo_config_values`
Quoted 11 lines · Junio C Hamano
So, we need to take it as a given that
repo_config_values_init()needs to exist. Under that condition, I wonder if we can somehow have a cheap way to assert the following two things:* Before a repository instance is used,
repo_config_values_init()has been called on it, as using an instance without initializing is a no-no.*
repo_config_values_init()is never called twice on a repository instance, as the second call will wipe what the first call and subsequent reading of the configuration files have done.
Something like this squashed into your [1/3] would give us these two assertions, but I am not sure if it is a good idea or if I am overly paranoid.
The main ideas are:
* "struct repository" now knows if it has been initialized via its "bool initialized" member.
* "initialize_repository()" detects double initialization of the repository struct itself.
* "repo_config_values" member in "struct repository" has been renamed to make it clear it is "private", and there is an accessor function of the same name. It barfs if you ask the address of repo_config_values in a repository instance that hasn't been initialized.
* Any code outside what implement the above are supposed to call repo_config_values() on the repository they are working in, to request the address of the repo_config_values instance to use.
It didn't barf when I ran all the tests, which means there isn't anybody who calls initialize_repository() twice in the current code.
I am not sure if this is being overly paranoid, or exercising a reasonable caution, but anyway,...
attr.c | 3 ++- environment.c | 2 +- environment.h | 3 +++ repository.c | 13 ++++++++++++- repository.h | 5 ++++- 5 files changed, 22 insertions(+), 4 deletions(-)
attr.c +2 -1
@@ -881,7 +881,8 @@ const char *git_attr_system_file(void)const char *git_attr_global_file (void ) { -struct repo_config_values *cfg = &the_repository->config_values; +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->attributes_file) cfg->attributes_file =xdg_config_home ("attributes" );
environment.c +1 -1
@@ -302,7 +302,7 @@ static enum fsync_component parse_fsync_components(const char *var, const char *int git_default_core_config (const char *var,const char *value,const struct config_context *ctx,void *cb) { -struct repo_config_values *cfg = &the_repository->config_values; +struct repo_config_values *cfg =repo_config_values (the_repository);/* This needs a better name */ if (!strcmp (var,"core.filemode" )) {
environment.h +3 -0
@@ -84,11 +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 *); +/* * Wrapper of getenv() that returns a strdup value. This value is kept * in argv to be freed later.
repository.c +12 -1
@@ -50,14 +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 uninitialied 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_config_values_init (repo_config_values (repo));/* * When a command runs inside a repository, it learns what
repository.h +4 -1
@@ -150,7 +150,7 @@ struct repository {const struct git_hash_algo *compat_hash_algo;/* Repository's config values parsed by git_default_config() */ -struct repo_config_values config_values; +struct repo_config_values config_values_private_;/* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format;
@@ -175,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
Re: [Outreachy PATCH v5 0/3] store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloQuoted 30 lines · Olamide Caleb Bello
Hi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables inenvironment.hinto local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use ofprepare_repo_settings()with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to
git_default_config()to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to
git_default_config().For now, the parsed value is stored in
the_repositoryingit_default_*_config()and further efforts to pass the repository parameter togit_default_config()as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4]1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]/
4. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2266020513
Quoted 4 lines
Changes in v5:
==============
- Corrected mistake in commit message of patch 3 which spelt branch wrongly inbranch.autoSetupmerge
Hello,
Just a gentle nudge for a review
Thanks
v6 cover store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.
I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to git_default_config().
For now, the parsed value is stored in the_repository in git_default_*_config() and further efforts to pass the repository parameter to git_default_config() as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4] and [5]
in the CI, some BUGs were gotten as a result of double initialization
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]
4. https://github.com/git/git/actions/runs/21633462506/job/62352191148?pr=2166
5. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2303203992
Changes in v6:
==============
- Added a new accessor function 'repo_config_values()' which ensures we detect if a repository has been initialized already
- Changed the member name to 'config_values_private_' to indicate this member is private
- Modified commit message of patch 1 to reflect these changes
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 3 ++- builtin/branch.c | 3 ++- builtin/checkout.c | 3 ++- builtin/clone.c | 3 ++- builtin/grep.c | 2 +- builtin/mv.c | 3 ++- builtin/push.c | 3 ++- builtin/sparse-checkout.c | 31 ++++++++++++++++++++----------- builtin/submodule--helper.c | 3 ++- builtin/worktree.c | 3 ++- dir.c | 3 ++- environment.c | 28 ++++++++++++++++++---------- environment.h | 17 +++++++++++++++-- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ sparse-index.c | 6 ++++-- unpack-trees.c | 3 ++- wt-status.c | 4 +++- 20 files changed, 104 insertions(+), 42 deletions(-)
Range diff versus v5:
=====================
1: d28850bcdb ! 1: 7e3082125d environment: stop storing core.attributesFile globally
@@ Commit message
Create a new struct `repo_config_values` to hold this value and
other repository dependent values parsed by `git_default_config()`.
- For now the value can be accessed via the_repository in
- `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,
@@ Commit message
Suggested-by: Phillip Wood <[email protected]>
Mentored-by: Christian Couder <[email protected]>
Mentored-by: Usman Akinyemi <[email protected]>
+ Helped-by: Junio C Hamano <[email protected]>
Signed-off-by: Olamide Caleb Bello <[email protected]>
## attr.c ##
@@ attr.c: const char *git_attr_system_file(void)
{
- if (!git_attributes_file)
- git_attributes_file = xdg_config_home("attributes");
-+ struct repo_config_values *cfg = &the_repository->config_values;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ if (!cfg->attributes_file)
+ cfg->attributes_file = xdg_config_home("attributes");
@@ environment.c: static enum fsync_component parse_fsync_components(const char *va
static int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
-+ struct repo_config_values *cfg = &the_repository->config_values;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
/* This needs a better name */
if (!strcmp(var, "core.filemode")) {
@@ environment.h: 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
@@ environment.h: extern int assume_unchanged;
extern unsigned long pack_size_limit_cfg;
## repository.c ##
-@@ repository.c: void initialize_repository(struct repository *repo)
+@@ repository.c: 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_config_values_init(repo_config_values(repo));
/*
* When a command runs inside a repository, it learns what
@@ repository.h: struct repository {
const struct git_hash_algo *compat_hash_algo;
+ /* Repository's config values parsed by git_default_config() */
-+ struct repo_config_values config_values;
++ struct repo_config_values config_values_private_;
+
/* Repository's reference storage format, as serialized on disk. */
enum ref_storage_format ref_storage_format;
+@@ repository.h: 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: 5e56e1cc41 ! 2: 8645b4f595 environment: stop using core.sparseCheckout globally
@@ Commit message
Signed-off-by: Olamide Caleb Bello <[email protected]>
## builtin/backfill.c ##
+@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
+ N_("Restrict the missing objects to the current sparse-checkout")),
+ OPT_END(),
+ };
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_backfill_usage, options);
@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
repo_config(repo, git_default_config, NULL);
if (ctx.sparse < 0)
- ctx.sparse = core_apply_sparse_checkout;
-+ ctx.sparse = the_repository->config_values.apply_sparse_checkout;
++ ctx.sparse = cfg->apply_sparse_checkout;
result = do_backfill(&ctx);
backfill_context_clear(&ctx);
## builtin/clone.c ##
@@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)
+ {
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ int result = 0;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ strvec_pushl(&cmd.args, "-C", repo, "sparse-checkout", "set", NULL);
+
+ /*
* We must apply the setting in the current process
* for the later checkout to use the sparse-checkout file.
*/
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.apply_sparse_checkout = 1;
++ cfg->apply_sparse_checkout = 1;
cmd.git_cmd = 1;
if (run_command(&cmd)) {
@@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,
* of these submodules are expanded unexpectedly.
*
- * 2. "core_apply_sparse_checkout"
-+ * 2. "config_values.apply_sparse_checkout"
++ * 2. "config_values_private_.apply_sparse_checkout"
* When running `grep` in the superproject, this setting is
* populated using the superproject's configs. However, once
* initialized, this config is globally accessible and is read by
## builtin/mv.c ##
+@@ builtin/mv.c: int cmd_mv(int argc,
+ struct hashmap moved_dirs = HASHMAP_INIT(pathmap_cmp, NULL);
+ struct strbuf pathbuf = STRBUF_INIT;
+ int ret;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ repo_config(the_repository, git_default_config, NULL);
+
@@ builtin/mv.c: int cmd_mv(int argc,
rename_index_entry_at(the_repository->index, pos, dst);
if (ignore_sparse &&
- core_apply_sparse_checkout &&
-+ the_repository->config_values.apply_sparse_checkout &&
++ cfg->apply_sparse_checkout &&
core_sparse_checkout_cone) {
/*
* NEEDSWORK: we are *not* paying attention to
## builtin/sparse-checkout.c ##
@@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
+ struct pattern_list pl;
+ char *sparse_filename;
int res;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.apply_sparse_checkout)
++ if (!cfg->apply_sparse_checkout)
die(_("this worktree is not sparse"));
argc = parse_options(argc, argv, prefix,
@@ builtin/sparse-checkout.c: static int set_config(struct repository *repo,
+ }
static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
++ struct repo_config_values *cfg = repo_config_values(the_repository);
++
/* If not specified, use previous definition of cone mode */
- if (*cone_mode == -1 && core_apply_sparse_checkout)
-+ if (*cone_mode == -1 && the_repository->config_values.apply_sparse_checkout)
++ if (*cone_mode == -1 && cfg->apply_sparse_checkout)
*cone_mode = core_sparse_checkout_cone;
/* Set cone/non-cone mode appropriately */
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.apply_sparse_checkout = 1;
++ cfg->apply_sparse_checkout = 1;
if (*cone_mode == 1 || *cone_mode == -1) {
core_sparse_checkout_cone = 1;
return MODE_CONE_PATTERNS;
-@@ builtin/sparse-checkout.c: static int update_modes(struct repository *repo, int *cone_mode, int *sparse_ind
+@@ builtin/sparse-checkout.c: static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {
+ static int update_modes(struct repository *repo, int *cone_mode, int *sparse_index)
+ {
int mode, record_mode;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
/* Determine if we need to record the mode; ensure sparse checkout on */
- record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;
-+ record_mode = (*cone_mode != -1) ||
-+ !the_repository->config_values.apply_sparse_checkout;
++ record_mode = (*cone_mode != -1) || !cfg->apply_sparse_checkout;
mode = update_cone_mode(cone_mode);
if (record_mode && set_config(repo, mode))
+@@ builtin/sparse-checkout.c: static int modify_pattern_list(struct repository *repo,
+ int result;
+ int changed_config = 0;
+ struct pattern_list *pl = xcalloc(1, sizeof(*pl));
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ switch (m) {
+ case ADD:
@@ builtin/sparse-checkout.c: static int modify_pattern_list(struct repository *repo,
break;
}
- if (!core_apply_sparse_checkout) {
-+ if (!the_repository->config_values.apply_sparse_checkout) {
++ if (!cfg->apply_sparse_checkout) {
set_config(repo, MODE_ALL_PATTERNS);
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.apply_sparse_checkout = 1;
++ cfg->apply_sparse_checkout = 1;
changed_config = 1;
}
@@ builtin/sparse-checkout.c: static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
+ };
+ struct strvec patterns = STRVEC_INIT;
int ret;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.apply_sparse_checkout)
++ if (!cfg->apply_sparse_checkout)
die(_("no sparse-checkout to add to"));
repo_read_index(repo);
@@ builtin/sparse-checkout.c: static int sparse_checkout_reapply(int argc, const char **argv,
+ N_("toggle the use of a sparse index")),
+ OPT_END(),
};
++ struct repo_config_values *cfg = repo_config_values(the_repository);
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.apply_sparse_checkout)
++ if (!cfg->apply_sparse_checkout)
die(_("must be in a sparse-checkout to reapply sparsity patterns"));
reapply_opts.cone_mode = -1;
+@@ builtin/sparse-checkout.c: static int sparse_checkout_clean(int argc, const char **argv,
+ size_t worktree_len;
+ int force = 0, dry_run = 0, verbose = 0;
+ int require_force = 1;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ struct option builtin_sparse_checkout_clean_options[] = {
+ OPT__DRY_RUN(&dry_run, N_("dry run")),
@@ builtin/sparse-checkout.c: static int sparse_checkout_clean(int argc, const char **argv,
};
setup_work_tree();
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.apply_sparse_checkout)
++ if (!cfg->apply_sparse_checkout)
die(_("must be in a sparse-checkout to clean directories"));
if (!core_sparse_checkout_cone)
die(_("must be in a cone-mode sparse-checkout to clean directories"));
@@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const char **argv,
+ OPT_END(),
+ };
struct pattern_list pl;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
/*
- * We do not exit early if !core_apply_sparse_checkout; due to the
@@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch
hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);
pl.use_cone_patterns = 0;
- core_apply_sparse_checkout = 1;
-+ the_repository->config_values.apply_sparse_checkout = 1;
++ cfg->apply_sparse_checkout = 1;
add_pattern("/*", empty_base, 0, &pl, 0);
## builtin/worktree.c ##
+@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refname,
+ struct strbuf sb_name = STRBUF_INIT;
+ struct worktree **worktrees, *wt = NULL;
+ struct ref_store *wt_refs;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ worktrees = get_worktrees();
+ check_candidate_path(path, opts->force, worktrees, "add");
@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refname,
* If the current worktree has sparse-checkout enabled, then copy
* the sparse-checkout patterns from the current worktree.
*/
- if (core_apply_sparse_checkout)
-+ if (the_repository->config_values.apply_sparse_checkout)
++ if (cfg->apply_sparse_checkout)
copy_sparse_checkout(sb_repo.buf);
/*
@@ dir.c: enum pattern_match_result path_matches_pattern_list(
int init_sparse_checkout_patterns(struct index_state *istate)
{
- if (!core_apply_sparse_checkout)
-+ if (!the_repository->config_values.apply_sparse_checkout)
++ struct repo_config_values *cfg = repo_config_values(the_repository);
++ if (!cfg->apply_sparse_checkout)
return 1;
if (istate->sparse_checkout_patterns)
return 0;
@@ environment.c: int git_default_config(const char *var, const char *value,
}
## environment.h ##
-@@ environment.h: struct strvec;
+@@ environment.h: struct repository;
struct repo_config_values {
/* section "core" config values */
char *attributes_file;
+ int apply_sparse_checkout;
};
- /*
+ struct repo_config_values *repo_config_values(struct repository *repo);
@@ environment.h: extern int precomposed_unicode;
extern int protect_hfs;
extern int protect_ntfs;
@@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate
int is_sparse_index_allowed(struct index_state *istate, int flags)
{
- if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
-+ struct repo_config_values *cfg = &the_repository->config_values;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)
return 0;
@@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct i
void clear_skip_worktree_from_present_files(struct index_state *istate)
{
- if (!core_apply_sparse_checkout ||
-+ struct repo_config_values *cfg = &the_repository->config_values;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ if (!cfg->apply_sparse_checkout ||
sparse_expect_files_outside_of_patterns)
return;
## unpack-trees.c ##
+@@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
+ struct pattern_list pl;
+ int free_pattern_list = 0;
+ struct dir_struct dir = DIR_INIT;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ if (o->reset == UNPACK_RESET_INVALID)
+ BUG("o->reset had a value of 1; should be UNPACK_TREES_*_UNTRACKED");
@@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
if (o->prefix)
update_sparsity_for_prefix(o->prefix, o->src_index);
- if (!core_apply_sparse_checkout || !o->update)
-+ if (!the_repository->config_values.apply_sparse_checkout || !o->update)
++ if (!cfg->apply_sparse_checkout || !o->update)
o->skip_sparse_checkout = 1;
if (!o->skip_sparse_checkout) {
memset(&pl, 0, sizeof(pl));
## wt-status.c ##
@@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r,
+ {
int skip_worktree = 0;
int i;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
- if (!core_apply_sparse_checkout || r->index->cache_nr == 0) {
-+ if (!the_repository->config_values.apply_sparse_checkout ||
++ if (!cfg->apply_sparse_checkout ||
+ r->index->cache_nr == 0) {
/*
* Don't compute percentage of checked out files if we
3: e7f37bac87 ! 3: 60451b93a5 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
@@ branch.h: enum branch_track {
/**
## builtin/branch.c ##
+@@ builtin/branch.c: int cmd_branch(int argc,
+ static struct ref_sorting *sorting;
+ struct string_list sorting_options = STRING_LIST_INIT_DUP;
+ struct ref_format format = REF_FORMAT_INIT;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ int ret;
+
+ struct option options[] = {
@@ builtin/branch.c: int cmd_branch(int argc,
if (!sorting_options.nr)
string_list_append(&sorting_options, "refname");
- track = git_branch_track;
-+ track = the_repository->config_values.branch_track;
++ track = cfg->branch_track;
head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
0, &head_oid, NULL);
## builtin/checkout.c ##
+@@ builtin/checkout.c: static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts,
+ static int checkout_branch(struct checkout_opts *opts,
+ struct branch_info *new_branch_info)
+ {
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+ int noop_switch = (!new_branch_info->name &&
+ !opts->new_branch &&
+ !opts->force_detach);
@@ builtin/checkout.c: static int checkout_branch(struct checkout_opts *opts,
if (opts->track != BRANCH_TRACK_UNSPECIFIED)
die(_("'%s' cannot be used with '%s'"), "--detach", "-t");
} else if (opts->track == BRANCH_TRACK_UNSPECIFIED)
- opts->track = git_branch_track;
-+ opts->track = the_repository->config_values.branch_track;
++ opts->track = cfg->branch_track;
if (new_branch_info->name && !new_branch_info->commit)
die(_("Cannot switch branch to a non-commit '%s'"),
## builtin/push.c ##
+@@ builtin/push.c: static NORETURN void die_push_simple(struct branch *branch,
+ const char *advice_pushdefault_maybe = "";
+ const char *advice_automergesimple_maybe = "";
+ const char *short_upstream = branch->merge[0]->src;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
+ skip_prefix(short_upstream, "refs/heads/", &short_upstream);
+
@@ builtin/push.c: static NORETURN void die_push_simple(struct branch *branch,
advice_pushdefault_maybe = _("\n"
"To choose either option permanently, "
"see push.default in 'git help config'.\n");
- if (git_branch_track != BRANCH_TRACK_SIMPLE)
-+ if (the_repository->config_values.branch_track != BRANCH_TRACK_SIMPLE)
++ if (cfg->branch_track != BRANCH_TRACK_SIMPLE)
advice_automergesimple_maybe = _("\n"
"To avoid automatically configuring "
"an upstream branch when its name\n"
## builtin/submodule--helper.c ##
@@ builtin/submodule--helper.c: static int module_create_branch(int argc, const char **argv, const char *prefix,
+ N_("git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>"),
+ NULL
};
++ struct repo_config_values *cfg = repo_config_values(the_repository);
repo_config(the_repository, git_default_config, NULL);
- track = git_branch_track;
-+ track = the_repository->config_values.branch_track;
++ track = cfg->branch_track;
argc = parse_options(argc, argv, prefix, options, usage, 0);
if (argc != 3)
@@ environment.c: static int git_default_i18n_config(const char *var, const char *v
static int git_default_branch_config(const char *var, const char *value)
{
-+ struct repo_config_values *cfg = &the_repository->config_values;
++ struct repo_config_values *cfg = repo_config_values(the_repository);
+
if (!strcmp(var, "branch.autosetupmerge")) {
if (value && !strcmp(value, "always")) {
@@ environment.h: struct repo_config_values {
+ enum branch_track branch_track;
};
- /*
+ struct repo_config_values *repo_config_values(struct repository *repo);Signature · 1 line
2.34.1
PATCH v6 1/3 environment: stop storing `core.attributesFile` globally
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().
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 )
environment.c +9 -3
@@ -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 ; +}
environment.h +10 -1
@@ -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;
repository.c +12 -0
@@ -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
repository.h +7 -0
@@ -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
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
Quoted 11 lines · Olamide Caleb Bello
The
core.attributeFileconfig value is parsed ingit_default_core_config(), loaded eagerly and stored in the global variablegit_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_valuesto hold this value and other repository dependent values parsed bygit_default_config(). This will ensure the current behaviour remains the same while also enabling the libification of Git.
Quoted 4 lines
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.
Sounds sensible. This paragraph could be reflowed.
Quoted 4 lines
It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()functions such asgit_default_core_config(). Therefore to access and modify this global variable,
the change has to be madegit_default_core_config().
I'm not sure what this paragraph is saying with regard to the changes in this patch.
environment.c int git_default_config(const char *var, const char *value, · line 764
Quoted 11 lines
environment.c +5
-0@@ -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 ; +}
Should we be free()ing cfg->attributes_file when the repository instance is free()d? At the moment we're using "the_repository" which points to a static instance so it does not make any practical difference but once we start storing the config per-repository instance we will need to free the config when the repository instance is free()d.
repository.c static void set_default_hash_algo(struct repository *repo) · line 56
Quoted 12 lines
repository.c +4
-0@@ -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" );
This check and the one in initialize_repository() below assume that the repository instance is zeroed out when it is created, that's a reasonable requirement but we should probably document it as our other data structures tend not to require that they're zeroed out before they are initialized. For example
struct strbuf buf; strbuf_init(&buf, 0);
is perfectly fine as strbuf_init() does not assume the instance passed to it has been zeroed out.
As we only support retrieving values from "the_repository" at the moment we should perhaps add
if (repo != the_repository)
BUG("trying to read config from wrong repository instance");Everything else looks fine to me
Thanks
Phillip
Quoted 50 lines
repository.c +8
-0+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 repository.h +7
-0@@ -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
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
Quoted 13 lines · Phillip Wood
Quoted 11 lines · Olamide Caleb Bello
The
core.attributeFileconfig value is parsed ingit_default_core_config(), loaded eagerly and stored in the global variablegit_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_valuesto hold this value and other repository dependent values parsed bygit_default_config(). This will ensure the current behaviour remains the same while also enabling the libification of Git.
Quoted 6 lines
Quoted 4 lines
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.Sounds sensible. This paragraph could be reflowed.
Okay
Quoted 8 lines
Quoted 5 lines
It is important to note that
git_default_config()is a wrapper to othergit_default_*_config()functions such asgit_default_core_config(). Therefore to access and modify this global variable,
the change has to be madegit_default_core_config().I'm not sure what this paragraph is saying with regard to the changes in this patch.
Okay I will fix it.
Quoted 10 lines
Quoted 10 lines
environment.c +3
-0@@ -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) +{
Quoted 8 lines
environment.c int git_default_config(const char *var, const char *value, · line 764
Quoted 2 lines
environment.c +2
-0+ cfg->attributes_file =NULL ; +}Should we be free()ing
cfg->attributes_filewhen the repository instance is free()d? At the moment we're using "the_repository" which points to a static instance so it does not make any practical difference but once we start storing the config per-repository instance we will need to free the config when the repository instance is free()d.
Okay I will keep this in mind.
Quoted 23 lines
repository.c static void set_default_hash_algo(struct repository *repo) · line 56
Quoted 13 lines
repository.c +4
-0@@ -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" );This check and the one in
initialize_repository()below assume that the repository instance is zeroed out when it is created, that's a reasonable requirement but we should probably document it as our other data structures tend not to require that they're zeroed out before they are initialized. For examplestruct strbuf buf; strbuf_init(&buf, 0);
Quoted 8 lines
is perfectly fine as
strbuf_init()does not assume the instance passed to it has been zeroed out.As we only support retrieving values from "
the_repository" at the moment we should perhaps addif (repo != the_repository) BUG("trying to read config from wrong repository instance");
Okay noted
Quoted 3 lines
Everything else looks fine to me
Thanks
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
In reply to Olamide Caleb BelloQuoted 5 lines · Olamide Caleb Bello
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Helped-by Junio C Hamano <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>
Quoted 7 lines
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-)
I bisected our recent CI failures that break fuzz smoke test down to this change.
$ make -j32 \
NO_CURL=NoThanks \
CC=clang \
FUZZ_CXX=clang++ \
CFLAGS="-fsanitize=fuzzer-no-link,address" \
LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
fuzz-all >/dev/null &&
$ oss-fuzz/fuzz-commit-graph -verbosity=0 -runs=1INFO: Running with entropic power schedule (0xFF, 100).
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
BUG: repository.c:63: repository initialized already
==2050473== ERROR: libFuzzer: deadly signal
#0 0x56169aaf4065 in __sanitizer_print_stack_trace (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x32a065) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#1 0x56169aa4835c in fuzzer::PrintStackTrace() (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x27e35c) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#2 0x56169aa2d2d7 in fuzzer::Fuzzer::CrashCallback() (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x2632d7) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#3 0x7fb4c6f59def (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: 61e1dea1f540b3b4b4d8ec76716e409cec096ece)
#4 0x7fb4c6fae95b in __pthread_kill_implementation nptl/pthread_kill.c:43:17
#5 0x7fb4c6f59cc1 in raise signal/../sysdeps/posix/raise.c:26:13
#6 0x7fb4c6f424ab in abort stdlib/abort.c:73:3
#7 0x56169ae91316 in BUG_vfl usage.c
#8 0x56169ae8f527 in BUG_fl (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x6c5527) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#9 0x56169ad79d07 in initialize_repository (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x5afd07) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#10 0x56169ab2c4e2 in LLVMFuzzerTestOneInput (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x3624e2) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#11 0x56169aa2e9da in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x2649da) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#12 0x56169aa2dfe9 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x263fe9) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#13 0x56169aa2fdaf in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x265daf) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#14 0x56169aa30390 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x266390) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#15 0x56169aa1cb65 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x252b65) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#16 0x56169aa48ec6 in main (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x27eec6) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)
#17 0x7fb4c6f43ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#18 0x7fb4c6f43d64 in __libc_start_main csu/../csu/libc-start.c:360:3
#19 0x56169aa10ec0 in _start (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x246ec0) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)NOTE: libFuzzer has rudimentary signal handlers.
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
Quoted 15 lines · Junio C Hamano
Quoted 5 lines · Olamide Caleb Bello
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Helped-by Junio C Hamano <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>Quoted 7 lines
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-)
Quoted 2 lines
I bisected our recent CI failures that break fuzz smoke test down to this change.
The documentation for the LibFuzzer [1] notes
* The fuzzing engine will execute the fuzz target many times with different inputs in the same process.
and the first thing that the callback in oss-fuzz/fuzz-commit-graph.c does is
initialize_repository(the_repository);
so I think the problem is that the assumption that a process will only initialize "the_repository" once is incompatible with the way LibFuzzer works. Maybe we should add
memset(the_repository, 0, sizeof(*the_repository));
before the call in initialize_repository()?
Thanks
Phillip
[1] https://llvm.org/docs/LibFuzzer.html
Quoted 36 lines
$ make -j32 \ NO_CURL=NoThanks \ CC=clang \ FUZZ_CXX=clang++ \ CFLAGS="-fsanitize=fuzzer-no-link,address" \ LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \ fuzz-all >/dev/null && $ oss-fuzz/fuzz-commit-graph -verbosity=0 -runs=1INFO: Running with entropic power schedule (
0xFF, 100).
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpusBUG: repository.c:63: repository initialized already ==2050473== ERROR: libFuzzer: deadly signal #0 0x56169aaf4065 in __sanitizer_print_stack_trace (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x32a065) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #1 0x56169aa4835c in fuzzer::PrintStackTrace() (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x27e35c) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #2 0x56169aa2d2d7 in fuzzer::Fuzzer::CrashCallback() (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x2632d7) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #3 0x7fb4c6f59def (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: 61e1dea1f540b3b4b4d8ec76716e409cec096ece) #4 0x7fb4c6fae95b in __pthread_kill_implementation nptl/pthread_kill.c:43:17 #5 0x7fb4c6f59cc1 in raise signal/../sysdeps/posix/raise.c:26:13 #6 0x7fb4c6f424ab in abort stdlib/abort.c:73:3 #7 0x56169ae91316 in BUG_vfl usage.c #8 0x56169ae8f527 in BUG_fl (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x6c5527) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #9 0x56169ad79d07 in initialize_repository (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x5afd07) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #10 0x56169ab2c4e2 in LLVMFuzzerTestOneInput (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x3624e2) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #11 0x56169aa2e9da in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x2649da) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #12 0x56169aa2dfe9 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x263fe9) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #13 0x56169aa2fdaf in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x265daf) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #14 0x56169aa30390 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x266390) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #15 0x56169aa1cb65 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x252b65) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #16 0x56169aa48ec6 in main (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x27eec6) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92) #17 0x7fb4c6f43ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #18 0x7fb4c6f43d64 in __libc_start_main csu/../csu/libc-start.c:360:3 #19 0x56169aa10ec0 in _start (/home/gitster/git.git/oss-fuzz/fuzz-commit-graph+0x246ec0) (BuildId: ec362419d512b5bd707ae18eef56a6a12a18fc92)NOTE: libFuzzer has rudimentary signal handlers.
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
Quoted 38 lines · Phillip Wood
Quoted 15 lines · Junio C Hamano
Quoted 5 lines · Olamide Caleb Bello
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Helped-by Junio C Hamano <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>Quoted 7 lines
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-)Quoted 2 lines
I bisected our recent CI failures that break fuzz smoke test down to this change.
The documentation for the LibFuzzer [1] notes
* The fuzzing engine will execute the fuzz target many times with different inputs in the same process.
and the first thing that the callback in
oss-fuzz/fuzz-commit-graph.cdoes isinitialize_repository(the_repository);so I think the problem is that the assumption that a process will only initialize "
the_repository" once is incompatible with the way LibFuzzer works. Maybe we should addmemset(the_repository, 0, sizeof(*the_repository));
Quoted 8 lines
before the call in
initialize_repository()?Thanks
Phillip
Thank you Phillip, I will try this.
I noticed something like this.
Re: [Outreachy PATCH v6 1/3] environment: stop storing `core.attributesFile` globally
In reply to Phillip WoodQuoted 38 lines · Phillip Wood
Quoted 15 lines · Junio C Hamano
Quoted 5 lines · Olamide Caleb Bello
Suggested-by Phillip Wood <[email protected]>Mentored-by Christian Couder <[email protected]>Mentored-by Usman Akinyemi <[email protected]>Helped-by Junio C Hamano <[email protected]>Signed-off-by Olamide Caleb Bello <[email protected]>Quoted 7 lines
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ 5 files changed, 42 insertions(+), 7 deletions(-)Quoted 2 lines
I bisected our recent CI failures that break fuzz smoke test down to this change.
The documentation for the LibFuzzer [1] notes
* The fuzzing engine will execute the fuzz target many times with different inputs in the same process.
and the first thing that the callback in
oss-fuzz/fuzz-commit-graph.cdoes isinitialize_repository(the_repository);so I think the problem is that the assumption that a process will only initialize "
the_repository" once is incompatible with the way LibFuzzer works. Maybe we should addmemset(the_repository, 0, sizeof(*the_repository));
Quoted 8 lines
before the call in
initialize_repository()?Thanks
Phillip
Hello Phillip,
thank you for your reviews and assistance so far.
So I moved the code
memset(the_repository, 0, sizeof(*the_repository))
into the fuzz-commit-graph.c Fuzzer test before the call to initialize_repository().
This made the fuzzer smoke tests pass.
But the line below,
`if (repo != the_repository)
BUG("trying to read config from wrong repository instance")`,
in the repo_config_values() accessor function
to make sure we are reading the config_values only for the_repository , makes many tests fail.
I believe this is because repo_init() calls initialize_repository() and repo_init() is also called in repo_submodule_init() when creating a subrepo from a super project, and this subrepo passed to repo_init() is not the_repository.
PATCH v6 2/3 environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.
Move the parsed value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git.
--- builtin/backfill.c | 3 ++- builtin/clone.c | 3 ++- builtin/grep.c | 2 +- builtin/mv.c | 3 ++- builtin/sparse-checkout.c | 31 ++++++++++++++++++++----------- builtin/worktree.c | 3 ++- dir.c | 3 ++- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 6 ++++-- unpack-trees.c | 3 ++- wt-status.c | 4 +++- 12 files changed, 43 insertions(+), 24 deletions(-)
builtin/backfill.c +2 -1
@@ -129,6 +129,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit N_("Restrict the missing objects to the current sparse-checkout")), OPT_END(), }; +struct repo_config_values *cfg =repo_config_values (the_repository);show_usage_with_options_if_asked (argc, argv, builtin_backfill_usage, options);
@@ -139,7 +140,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = cfg->apply_sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +2 -1
@@ -617,13 +617,14 @@ static int git_sparse_checkout_init(const char *repo) {struct child_process cmd =CHILD_PROCESS_INIT ;int result =0 ; +struct repo_config_values *cfg =repo_config_values (the_repository);strvec_pushl (&cmd.args,"-C" , repo,"sparse-checkout" ,"set" ,NULL );/* * We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "config_values_private_.apply_sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +2 -1
@@ -238,6 +238,7 @@ int cmd_mv(int argc,struct hashmap moved_dirs =HASHMAP_INIT (pathmap_cmp,NULL );struct strbuf pathbuf =STRBUF_INIT ;int ret; +struct repo_config_values *cfg =repo_config_values (the_repository);repo_config (the_repository, git_default_config,NULL );
@@ -572,7 +573,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + cfg->apply_sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +20 -11
@@ -61,9 +61,10 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,struct pattern_list pl;char *sparse_filename;int res; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -399,12 +400,14 @@ static int set_config(struct repository *repo, }static enum sparse_checkout_mode update_cone_mode (int *cone_mode) { +struct repo_config_values *cfg =repo_config_values (the_repository); +/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && cfg->apply_sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -416,9 +419,10 @@ static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {static int update_modes (struct repository *repo,int *cone_mode,int *sparse_index) {int mode, record_mode; +struct repo_config_values *cfg =repo_config_values (the_repository);/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !cfg->apply_sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -684,6 +688,7 @@ static int modify_pattern_list(struct repository *repo,int result;int changed_config =0 ;struct pattern_list *pl =xcalloc (1 ,sizeof (*pl)); +struct repo_config_values *cfg =repo_config_values (the_repository);switch (m) {case ADD :
@@ -699,9 +704,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!cfg->apply_sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ; changed_config =1 ; }
@@ -796,9 +801,10 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix, };struct strvec patterns =STRVEC_INIT ;int ret; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -905,9 +911,10 @@ static int sparse_checkout_reapply(int argc, const char **argv, N_("toggle the use of a sparse index")), OPT_END(), }; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -960,6 +967,7 @@ static int sparse_checkout_clean(int argc, const char **argv,size_t worktree_len;int force =0 , dry_run =0 , verbose =0 ;int require_force =1 ; +struct repo_config_values *cfg =repo_config_values (the_repository);struct option builtin_sparse_checkout_clean_options[] = {OPT__DRY_RUN (&dry_run,N_ ("dry run" )),
@@ -969,7 +977,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1033,9 +1041,10 @@ static int sparse_checkout_disable(int argc, const char **argv, OPT_END(), };struct pattern_list pl; +struct repo_config_values *cfg =repo_config_values (the_repository);/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.apply_sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1070,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +2 -1
@@ -440,6 +440,7 @@ static int add_worktree(const char *path, const char *refname,struct strbuf sb_name =STRBUF_INIT ;struct worktree **worktrees, *wt =NULL ;struct ref_store *wt_refs; +struct repo_config_values *cfg =repo_config_values (the_repository); worktrees =get_worktrees ();check_candidate_path (path, opts->force, worktrees,"add" );
@@ -536,7 +537,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (cfg->apply_sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +2 -1
@@ -1551,7 +1551,8 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +2 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->apply_sparse_checkout =git_config_bool (var, value);return 0 ; }
@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file =NULL ; + cfg->apply_sparse_checkout =0 ; }
environment.h +1 -1
@@ -88,6 +88,7 @@ struct repository;struct repo_config_values {/* section "core" config values */ char *attributes_file; +int apply_sparse_checkout; };struct repo_config_values *repo_config_values (struct repository *repo);
@@ -171,7 +172,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +4 -2
@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +2 -1
@@ -1888,6 +1888,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsstruct pattern_list pl;int free_pattern_list =0 ;struct dir_struct dir =DIR_INIT ; +struct repo_config_values *cfg =repo_config_values (the_repository);if (o->reset ==UNPACK_RESET_INVALID )BUG ("o->reset had a value of 1; should be UNPACK_TREES_*_UNTRACKED" );
@@ -1924,7 +1925,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!cfg->apply_sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +3 -1
@@ -1763,8 +1763,10 @@ static void wt_status_check_sparse_checkout(struct repository *r, {int skip_worktree =0 ;int i; +struct repo_config_values *cfg =repo_config_values (the_repository); -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!cfg->apply_sparse_checkout || + r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v6 2/3] environment: stop using core.sparseCheckout globally
Quoted 8 lines · Olamide Caleb Bello
The config value
core.sparseCheckoutis parsed ingit_default_core_config()and stored globally incore_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.Move the parsed value into
struct repo_config_valuesinthe_repositoryto retain current behaviours and move towards libifying Git.
This looks good, I've left a small style comment below
builtin/clone.c static int git_sparse_checkout_init(const char *repo) · line 620
Quoted 9 lines
builtin/clone.c +1
-0@@ -617,13 +617,14 @@ static int git_sparse_checkout_init(const char *repo) {struct child_process cmd =CHILD_PROCESS_INIT ;int result =0 ; +struct repo_config_values *cfg =repo_config_values (the_repository);
We normally have a blank line between the varibale declarations and statements. As you're adding a new declaration here it would be good to add a blank line as well. The same goes for dir.c and sparse-index.c below.
Thanks
Phillip
Quoted 41 lines
builtin/clone.c +0
-0strvec_pushl (&cmd.args,"-C" , repo,"sparse-checkout" ,"set" ,NULL );dir.c +2
-1@@ -1551,7 +1551,8 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;sparse-index.c +4
-2@@ -152,7 +152,8 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {@@ -670,7 +671,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
PATCH v6 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value branch.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can be overwritten
by another repository when multiple Git repos run in the the same process.
Move this value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git. Since the variable is no longer a global variable, it has been renamed to branch_track in the struct repo_config_values.
--- branch.h | 2 -- builtin/branch.c | 3 ++- builtin/checkout.c | 3 ++- builtin/push.c | 3 ++- builtin/submodule--helper.c | 3 ++- environment.c | 12 +++++++----- environment.h | 4 ++++ 7 files changed, 19 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +2 -1
@@ -724,6 +724,7 @@ int cmd_branch(int argc,static struct ref_sorting *sorting;struct string_list sorting_options =STRING_LIST_INIT_DUP ;struct ref_format format =REF_FORMAT_INIT ; +struct repo_config_values *cfg =repo_config_values (the_repository);int ret;struct option options[] = {
@@ -795,7 +796,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = cfg->branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +2 -1
@@ -1588,6 +1588,7 @@ static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts,static int checkout_branch (struct checkout_opts *opts,struct branch_info *new_branch_info) { +struct repo_config_values *cfg =repo_config_values (the_repository);int noop_switch = (!new_branch_info->name && !opts->new_branch && !opts->force_detach);
@@ -1631,7 +1632,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = cfg->branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +2 -1
@@ -151,6 +151,7 @@ static NORETURN void die_push_simple(struct branch *branch,const char *advice_pushdefault_maybe ="" ;const char *advice_automergesimple_maybe ="" ;const char *short_upstream = branch->merge[0 ]->src; +struct repo_config_values *cfg =repo_config_values (the_repository);skip_prefix (short_upstream,"refs/heads/" , &short_upstream);
@@ -162,7 +163,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (cfg->branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +2 -1
@@ -3126,9 +3126,10 @@ static int module_create_branch(int argc, const char **argv, const char *prefix,N_ ("git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" ), NULL }; +struct repo_config_values *cfg =repo_config_values (the_repository);repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = cfg->branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +7 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -761,4 +762,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 ; }
environment.h +4 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -89,6 +90,9 @@ struct repo_config_values {/* section "core" config values */ char *attributes_file;int apply_sparse_checkout; + +/* section "branch" config values */ +enum branch_track branch_track; };struct repo_config_values *repo_config_values (struct repository *repo);
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v6 0/3] store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Olamide
This version looks pretty good. I've left a couple of suggestions, but the changes since v4 look good.
Thanks
Phillip
Quoted 578 lines · Olamide Caleb Bello
Hi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables inenvironment.hinto local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use ofprepare_repo_settings()with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to
git_default_config()to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.I have experimented with this approach for some values and I would appreciate feedbacks about this approach before we can move forward and use it for more variables related to
git_default_config().For now, the parsed value is stored in
the_repositoryingit_default_*_config()and further efforts to pass the repository parameter togit_default_config()as the callback parameter will be looked into later on.
The link to the CI tests can be see in [4] and [5]
in the CI, some BUGs were gotten as a result of double initialization1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]
4. https://github.com/git/git/actions/runs/21633462506/job/62352191148?pr=2166
5. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2303203992Changes in v6:
==============
- Added a new accessor function 'repo_config_values()' which ensures we detect if a repository has been initialized already
- Changed the member name to 'config_values_private_' to indicate this member is private
- Modified commit message of patch 1 to reflect these changesOlamide Caleb Bello (3):
environment: stop storingcore.attributesFileglobally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 3 ++- builtin/branch.c | 3 ++- builtin/checkout.c | 3 ++- builtin/clone.c | 3 ++- builtin/grep.c | 2 +- builtin/mv.c | 3 ++- builtin/push.c | 3 ++- builtin/sparse-checkout.c | 31 ++++++++++++++++++++----------- builtin/submodule--helper.c | 3 ++- builtin/worktree.c | 3 ++- dir.c | 3 ++- environment.c | 28 ++++++++++++++++++---------- environment.h | 17 +++++++++++++++-- repository.c | 12 ++++++++++++ repository.h | 7 +++++++ sparse-index.c | 6 ++++-- unpack-trees.c | 3 ++- wt-status.c | 4 +++- 20 files changed, 104 insertions(+), 42 deletions(-)Range diff versus v5:
=====================1:
d28850bcdb! 1:7e3082125denvironment: stop storingcore.attributesFileglobally@@ Commit message Create a new struct `repo_config_values` to hold this value and other repository dependent values parsed by `git_default_config()`. - For now the value can be accessed via the_repository in - `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, @@ Commit message Suggested-by: Phillip Wood <[email protected]> Mentored-by: Christian Couder <[email protected]> Mentored-by: Usman Akinyemi <[email protected]> + Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Olamide Caleb Bello <[email protected]> ## attr.c ## @@ attr.c: const char *git_attr_system_file(void) { - if (!git_attributes_file) - git_attributes_file = xdg_config_home("attributes"); -+ struct repo_config_values *cfg = &the_repository->config_values; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + if (!cfg->attributes_file) + cfg->attributes_file = xdg_config_home("attributes"); @@ environment.c: static enum fsync_component parse_fsync_components(const char *va static int git_default_core_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { -+ struct repo_config_values *cfg = &the_repository->config_values; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + /* This needs a better name */ if (!strcmp(var, "core.filemode")) { @@ environment.h: 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 @@ environment.h: extern int assume_unchanged; extern unsigned long pack_size_limit_cfg; ## repository.c ## -@@ repository.c: void initialize_repository(struct repository *repo) +@@ repository.c: 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_config_values_init(repo_config_values(repo)); /* * When a command runs inside a repository, it learns what @@ repository.h: struct repository { const struct git_hash_algo *compat_hash_algo; + /* Repository's config values parsed by git_default_config() */ -+ struct repo_config_values config_values; ++ struct repo_config_values config_values_private_; + /* Repository's reference storage format, as serialized on disk. */ enum ref_storage_format ref_storage_format; +@@ repository.h: 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: 5e56e1cc41 ! 2: 8645b4f595 environment: stop using core.sparseCheckout globally @@ Commit message Signed-off-by: Olamide Caleb Bello <[email protected]> ## builtin/backfill.c ## +@@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit + N_("Restrict the missing objects to the current sparse-checkout")), + OPT_END(), + }; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + show_usage_with_options_if_asked(argc, argv, + builtin_backfill_usage, options); @@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit repo_config(repo, git_default_config, NULL); if (ctx.sparse < 0) - ctx.sparse = core_apply_sparse_checkout; -+ ctx.sparse = the_repository->config_values.apply_sparse_checkout; ++ ctx.sparse = cfg->apply_sparse_checkout; result = do_backfill(&ctx); backfill_context_clear(&ctx); ## builtin/clone.c ## @@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo) + { + struct child_process cmd = CHILD_PROCESS_INIT; + int result = 0; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + strvec_pushl(&cmd.args, "-C", repo, "sparse-checkout", "set", NULL); + + /* * We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout = 1; -+ the_repository->config_values.apply_sparse_checkout = 1; ++ cfg->apply_sparse_checkout = 1; cmd.git_cmd = 1; if (run_command(&cmd)) { @@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt, * of these submodules are expanded unexpectedly. * - * 2. "core_apply_sparse_checkout" -+ * 2. "config_values.apply_sparse_checkout" ++ * 2. "config_values_private_.apply_sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by ## builtin/mv.c ## +@@ builtin/mv.c: int cmd_mv(int argc, + struct hashmap moved_dirs = HASHMAP_INIT(pathmap_cmp, NULL); + struct strbuf pathbuf = STRBUF_INIT; + int ret; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + repo_config(the_repository, git_default_config, NULL); + @@ builtin/mv.c: int cmd_mv(int argc, rename_index_entry_at(the_repository->index, pos, dst); if (ignore_sparse && - core_apply_sparse_checkout && -+ the_repository->config_values.apply_sparse_checkout && ++ cfg->apply_sparse_checkout && core_sparse_checkout_cone) { /* * NEEDSWORK: we are *not* paying attention to ## builtin/sparse-checkout.c ## @@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char **argv, const char *prefix, + struct pattern_list pl; + char *sparse_filename; int res; ++ struct repo_config_values *cfg = repo_config_values(the_repository); setup_work_tree(); - if (!core_apply_sparse_checkout) -+ if (!the_repository->config_values.apply_sparse_checkout) ++ if (!cfg->apply_sparse_checkout) die(_("this worktree is not sparse")); argc = parse_options(argc, argv, prefix, @@ builtin/sparse-checkout.c: static int set_config(struct repository *repo, + } static enum sparse_checkout_mode update_cone_mode(int *cone_mode) { ++ struct repo_config_values *cfg = repo_config_values(the_repository); ++ /* If not specified, use previous definition of cone mode */ - if (*cone_mode == -1 && core_apply_sparse_checkout) -+ if (*cone_mode == -1 && the_repository->config_values.apply_sparse_checkout) ++ if (*cone_mode == -1 && cfg->apply_sparse_checkout) *cone_mode = core_sparse_checkout_cone; /* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout = 1; -+ the_repository->config_values.apply_sparse_checkout = 1; ++ cfg->apply_sparse_checkout = 1; if (*cone_mode == 1 || *cone_mode == -1) { core_sparse_checkout_cone = 1; return MODE_CONE_PATTERNS; -@@ builtin/sparse-checkout.c: static int update_modes(struct repository *repo, int *cone_mode, int *sparse_ind +@@ builtin/sparse-checkout.c: static enum sparse_checkout_mode update_cone_mode(int *cone_mode) { + static int update_modes(struct repository *repo, int *cone_mode, int *sparse_index) + { int mode, record_mode; ++ struct repo_config_values *cfg = repo_config_values(the_repository); /* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode != -1) || !core_apply_sparse_checkout; -+ record_mode = (*cone_mode != -1) || -+ !the_repository->config_values.apply_sparse_checkout; ++ record_mode = (*cone_mode != -1) || !cfg->apply_sparse_checkout; mode = update_cone_mode(cone_mode); if (record_mode && set_config(repo, mode)) +@@ builtin/sparse-checkout.c: static int modify_pattern_list(struct repository *repo, + int result; + int changed_config = 0; + struct pattern_list *pl = xcalloc(1, sizeof(*pl)); ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + switch (m) { + case ADD: @@ builtin/sparse-checkout.c: static int modify_pattern_list(struct repository *repo, break; } - if (!core_apply_sparse_checkout) { -+ if (!the_repository->config_values.apply_sparse_checkout) { ++ if (!cfg->apply_sparse_checkout) { set_config(repo, MODE_ALL_PATTERNS); - core_apply_sparse_checkout = 1; -+ the_repository->config_values.apply_sparse_checkout = 1; ++ cfg->apply_sparse_checkout = 1; changed_config = 1; } @@ builtin/sparse-checkout.c: static int sparse_checkout_add(int argc, const char **argv, const char *prefix, + }; + struct strvec patterns = STRVEC_INIT; int ret; ++ struct repo_config_values *cfg = repo_config_values(the_repository); setup_work_tree(); - if (!core_apply_sparse_checkout) -+ if (!the_repository->config_values.apply_sparse_checkout) ++ if (!cfg->apply_sparse_checkout) die(_("no sparse-checkout to add to")); repo_read_index(repo); @@ builtin/sparse-checkout.c: static int sparse_checkout_reapply(int argc, const char **argv, + N_("toggle the use of a sparse index")), + OPT_END(), }; ++ struct repo_config_values *cfg = repo_config_values(the_repository); setup_work_tree(); - if (!core_apply_sparse_checkout) -+ if (!the_repository->config_values.apply_sparse_checkout) ++ if (!cfg->apply_sparse_checkout) die(_("must be in a sparse-checkout to reapply sparsity patterns")); reapply_opts.cone_mode = -1; +@@ builtin/sparse-checkout.c: static int sparse_checkout_clean(int argc, const char **argv, + size_t worktree_len; + int force = 0, dry_run = 0, verbose = 0; + int require_force = 1; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + struct option builtin_sparse_checkout_clean_options[] = { + OPT__DRY_RUN(&dry_run, N_("dry run")), @@ builtin/sparse-checkout.c: static int sparse_checkout_clean(int argc, const char **argv, }; setup_work_tree(); - if (!core_apply_sparse_checkout) -+ if (!the_repository->config_values.apply_sparse_checkout) ++ if (!cfg->apply_sparse_checkout) die(_("must be in a sparse-checkout to clean directories")); if (!core_sparse_checkout_cone) die(_("must be in a cone-mode sparse-checkout to clean directories")); @@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const char **argv, + OPT_END(), + }; struct pattern_list pl; ++ struct repo_config_values *cfg = repo_config_values(the_repository); /* - * We do not exit early if !core_apply_sparse_checkout; due to the @@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0); pl.use_cone_patterns = 0; - core_apply_sparse_checkout = 1; -+ the_repository->config_values.apply_sparse_checkout = 1; ++ cfg->apply_sparse_checkout = 1; add_pattern("/*", empty_base, 0, &pl, 0); ## builtin/worktree.c ## +@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refname, + struct strbuf sb_name = STRBUF_INIT; + struct worktree **worktrees, *wt = NULL; + struct ref_store *wt_refs; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + worktrees = get_worktrees(); + check_candidate_path(path, opts->force, worktrees, "add"); @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refname, * If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ - if (core_apply_sparse_checkout) -+ if (the_repository->config_values.apply_sparse_checkout) ++ if (cfg->apply_sparse_checkout) copy_sparse_checkout(sb_repo.buf); /* @@ dir.c: enum pattern_match_result path_matches_pattern_list( int init_sparse_checkout_patterns(struct index_state *istate) { - if (!core_apply_sparse_checkout) -+ if (!the_repository->config_values.apply_sparse_checkout) ++ struct repo_config_values *cfg = repo_config_values(the_repository); ++ if (!cfg->apply_sparse_checkout) return 1; if (istate->sparse_checkout_patterns) return 0; @@ environment.c: int git_default_config(const char *var, const char *value, } ## environment.h ## -@@ environment.h: struct strvec; +@@ environment.h: struct repository; struct repo_config_values { /* section "core" config values */ char *attributes_file; + int apply_sparse_checkout; }; - /* + struct repo_config_values *repo_config_values(struct repository *repo); @@ environment.h: extern int precomposed_unicode; extern int protect_hfs; extern int protect_ntfs; @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate int is_sparse_index_allowed(struct index_state *istate, int flags) { - if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) -+ struct repo_config_values *cfg = &the_repository->config_values; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone) return 0; @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct i void clear_skip_worktree_from_present_files(struct index_state *istate) { - if (!core_apply_sparse_checkout || -+ struct repo_config_values *cfg = &the_repository->config_values; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns) return; ## unpack-trees.c ## +@@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options + struct pattern_list pl; + int free_pattern_list = 0; + struct dir_struct dir = DIR_INIT; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + if (o->reset == UNPACK_RESET_INVALID) + BUG("o->reset had a value of 1; should be UNPACK_TREES_*_UNTRACKED"); @@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options if (o->prefix) update_sparsity_for_prefix(o->prefix, o->src_index); - if (!core_apply_sparse_checkout || !o->update) -+ if (!the_repository->config_values.apply_sparse_checkout || !o->update) ++ if (!cfg->apply_sparse_checkout || !o->update) o->skip_sparse_checkout = 1; if (!o->skip_sparse_checkout) { memset(&pl, 0, sizeof(pl)); ## wt-status.c ## @@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r, + { int skip_worktree = 0; int i; ++ struct repo_config_values *cfg = repo_config_values(the_repository); - if (!core_apply_sparse_checkout || r->index->cache_nr == 0) { -+ if (!the_repository->config_values.apply_sparse_checkout || ++ if (!cfg->apply_sparse_checkout || + r->index->cache_nr == 0) { /* * Don't compute percentage of checked out files if we 3: e7f37bac87 ! 3: 60451b93a5 environment: move "branch.autoSetupMerge" into `struct repo_config_values` @@ branch.h: enum branch_track { /** ## builtin/branch.c ## +@@ builtin/branch.c: int cmd_branch(int argc, + static struct ref_sorting *sorting; + struct string_list sorting_options = STRING_LIST_INIT_DUP; + struct ref_format format = REF_FORMAT_INIT; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + int ret; + + struct option options[] = { @@ builtin/branch.c: int cmd_branch(int argc, if (!sorting_options.nr) string_list_append(&sorting_options, "refname"); - track = git_branch_track; -+ track = the_repository->config_values.branch_track; ++ track = cfg->branch_track; head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD", 0, &head_oid, NULL); ## builtin/checkout.c ## +@@ builtin/checkout.c: static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts, + static int checkout_branch(struct checkout_opts *opts, + struct branch_info *new_branch_info) + { ++ struct repo_config_values *cfg = repo_config_values(the_repository); + int noop_switch = (!new_branch_info->name && + !opts->new_branch && + !opts->force_detach); @@ builtin/checkout.c: static int checkout_branch(struct checkout_opts *opts, if (opts->track != BRANCH_TRACK_UNSPECIFIED) die(_("'%s' cannot be used with '%s'"), "--detach", "-t"); } else if (opts->track == BRANCH_TRACK_UNSPECIFIED) - opts->track = git_branch_track; -+ opts->track = the_repository->config_values.branch_track; ++ opts->track = cfg->branch_track; if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"), ## builtin/push.c ## +@@ builtin/push.c: static NORETURN void die_push_simple(struct branch *branch, + const char *advice_pushdefault_maybe = ""; + const char *advice_automergesimple_maybe = ""; + const char *short_upstream = branch->merge[0]->src; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + + skip_prefix(short_upstream, "refs/heads/", &short_upstream); + @@ builtin/push.c: static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe = _("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n"); - if (git_branch_track != BRANCH_TRACK_SIMPLE) -+ if (the_repository->config_values.branch_track != BRANCH_TRACK_SIMPLE) ++ if (cfg->branch_track != BRANCH_TRACK_SIMPLE) advice_automergesimple_maybe = _("\n" "To avoid automatically configuring " "an upstream branch when its name\n" ## builtin/submodule--helper.c ## @@ builtin/submodule--helper.c: static int module_create_branch(int argc, const char **argv, const char *prefix, + N_("git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>"), + NULL }; ++ struct repo_config_values *cfg = repo_config_values(the_repository); repo_config(the_repository, git_default_config, NULL); - track = git_branch_track; -+ track = the_repository->config_values.branch_track; ++ track = cfg->branch_track; argc = parse_options(argc, argv, prefix, options, usage, 0); if (argc != 3) @@ environment.c: static int git_default_i18n_config(const char *var, const char *v static int git_default_branch_config(const char *var, const char *value) { -+ struct repo_config_values *cfg = &the_repository->config_values; ++ struct repo_config_values *cfg = repo_config_values(the_repository); + if (!strcmp(var, "branch.autosetupmerge")) { if (value && !strcmp(value, "always")) { @@ environment.h: struct repo_config_values { + enum branch_track branch_track; }; - /* + struct repo_config_values *repo_config_values(struct repository *repo);
v7 cover store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloHi Git Community,
Over the course of my ongoing internship, which focused on moving repo specific global variables in environment.h into local scope, I have attempted to move some variables into the struct repo-settings.
However there has been some design concerns as regards the use of prepare_repo_settings() with respect to when and where to call the function, and also the change in behaviours when the variable is lazily loaded as discussed in [1] and [2].
After different deliberations, Phillip Wood proposed creating a new config struct [3], adding it to the repository struct and passing the repo struct to git_default_config() to store parsed repo specific config values per repo. This ensures the current behaviours will be retained.
In version v6, the fuzz-commit-graph failed due to the test being run multiples times in the same process. This makes us get a BUG due to the repository being reinitialized in the same process. But now resetting the initialization using memset before rerunning the test, the failure is not longer experienced.
1. https://lore.kernel.org/git/[email protected]/
2. https://lore.kernel.org/git/[email protected]/
3. https://lore.kernel.org/git/[email protected]
4. https://github.com/git/git/actions/runs/21633462506/job/62352191148?pr=2166
5. https://gitlab.com/gitlab-community/gitlab-org/git/-/pipelines/2303203992
Changes in v7:
==============
- Added the code to reset the initialization of the_repository in the fuzz-commit-graph test in Patch 1.
- Changed the call to rep_config_values_init() in initialze_repository() by passing it the repo config_values_private_ struct instead of the accessor function in Patch 1.
- Modified the commit message in Patch 1
- Added extra lines between variable declarations and code
Olamide Caleb Bello (3):
environment: stop storing core.attributesFile globally
environment: stop using core.sparseCheckout globally
environment: move "branch.autoSetupMerge" into `struct
repo_config_values`
attr.c | 7 ++++--- branch.h | 2 -- builtin/backfill.c | 3 ++- builtin/branch.c | 3 ++- builtin/checkout.c | 3 ++- builtin/clone.c | 4 +++- builtin/grep.c | 2 +- builtin/mv.c | 3 ++- builtin/push.c | 3 ++- builtin/sparse-checkout.c | 31 ++++++++++++++++++++----------- builtin/submodule--helper.c | 3 ++- builtin/worktree.c | 3 ++- dir.c | 4 +++- environment.c | 28 ++++++++++++++++++---------- environment.h | 17 +++++++++++++++-- oss-fuzz/fuzz-commit-graph.c | 1 + repository.c | 14 ++++++++++++++ repository.h | 7 +++++++ sparse-index.c | 7 +++++-- unpack-trees.c | 3 ++- wt-status.c | 4 +++- 21 files changed, 110 insertions(+), 42 deletions(-)
Range diff versus v6:
=====================
1: 7e3082125d ! 1: 48821a3848 environment: stop storing core.attributesFile globally
@@ Commit message
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.
+ 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().
+ An accessor function 'repo_config_values()' to ensure that we do not
+ access an uninitialized repository, or an instance of a different
+ repository than the current one.
@@ environment.h: extern int assume_unchanged;
extern int pack_compression_level; extern unsigned long pack_size_limit_cfg;
+ ## oss-fuzz/fuzz-commit-graph.c ##
+@@ oss-fuzz/fuzz-commit-graph.c: int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+ {
+ struct commit_graph *g;
+
++ memset(the_repository, 0, sizeof(*the_repository));
+ initialize_repository(the_repository);
+
+ /*
+
## repository.c ##
@@ repository.c: static void set_default_hash_algo(struct repository *repo)
repo_set_hash_algo(repo, algo);
@@ repository.c: static void set_default_hash_algo(struct repository *repo)
+struct repo_config_values *repo_config_values(struct repository *repo) +{
++ if (repo != the_repository)
++ BUG("trying to read config from wrong repository instance");
+ if(!repo->initialized)
+ BUG("config values from uninitialized repository");
+ return &repo->config_values_private_;
@@ repository.c: static void set_default_hash_algo(struct repository *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));
++ repo_config_values_init(&repo->config_values_private_);
/*
* When a command runs inside a repository, it learns what
2: 8645b4f595 ! 2: 7d33f1ef0f environment: stop using core.sparseCheckout globally
@@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)
struct child_process cmd = CHILD_PROCESS_INIT;
int result = 0;
+ struct repo_config_values *cfg = repo_config_values(the_repository);
++
strvec_pushl(&cmd.args, "-C", repo, "sparse-checkout", "set", NULL);
/*
@@ dir.c: enum pattern_match_result path_matches_pattern_list(
{
- if (!core_apply_sparse_checkout)
+ struct repo_config_values *cfg = repo_config_values(the_repository);
++
+ if (!cfg->apply_sparse_checkout)
return 1;
if (istate->sparse_checkout_patterns)
@@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate
{
- if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
+ struct repo_config_values *cfg = repo_config_values(the_repository);
++
+ if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)
return 0;3: 60451b93a5 = 3: c3ecfa63b9 environment: move "branch.autoSetupMerge" into struct repo_config_values
Signature · 1 line
2.34.1
PATCH v7 1/3 environment: stop storing `core.attributesFile` globally
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()' s created to ensure that we do not access an uninitialized repository, or an instance of a different repository than the current one.
--- attr.c | 7 ++++--- environment.c | 12 +++++++++--- environment.h | 11 ++++++++++- oss-fuzz/fuzz-commit-graph.c | 1 + repository.c | 14 ++++++++++++++ repository.h | 7 +++++++ 6 files changed, 45 insertions(+), 7 deletions(-)
attr.c +4 -3
@@ -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 )
environment.c +9 -3
@@ -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 ; +}
environment.h +10 -1
@@ -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;
oss-fuzz/fuzz-commit-graph.c +1 -0
@@ -10,6 +10,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {struct commit_graph *g; +memset (the_repository,0 ,sizeof (*the_repository));initialize_repository (the_repository);/*
repository.c +14 -0
@@ -50,13 +50,27 @@ 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 != the_repository) +BUG ("trying to read config from wrong repository instance" ); +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_private_);/* * When a command runs inside a repository, it learns what
repository.h +7 -0
@@ -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
Signature · 1 line
2.34.1
PATCH v7 2/3 environment: stop using core.sparseCheckout globally
In reply to Olamide Caleb BelloThe config value core.sparseCheckout is parsed in git_default_core_config() and stored globally in core_apply_sparse_checkout. This could cause it to be overwritten by another repository when different Git repositories run in the same process.
Move the parsed value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git.
--- builtin/backfill.c | 3 ++- builtin/clone.c | 4 +++- builtin/grep.c | 2 +- builtin/mv.c | 3 ++- builtin/sparse-checkout.c | 31 ++++++++++++++++++++----------- builtin/worktree.c | 3 ++- dir.c | 4 +++- environment.c | 4 ++-- environment.h | 2 +- sparse-index.c | 7 +++++-- unpack-trees.c | 3 ++- wt-status.c | 4 +++- 12 files changed, 46 insertions(+), 24 deletions(-)
builtin/backfill.c +2 -1
@@ -129,6 +129,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit N_("Restrict the missing objects to the current sparse-checkout")), OPT_END(), }; +struct repo_config_values *cfg =repo_config_values (the_repository);show_usage_with_options_if_asked (argc, argv, builtin_backfill_usage, options);
@@ -139,7 +140,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct repositrepo_config (repo, git_default_config,NULL );if (ctx.sparse <0 ) - ctx.sparse = core_apply_sparse_checkout; + ctx.sparse = cfg->apply_sparse_checkout; result =do_backfill (&ctx);backfill_context_clear (&ctx);
builtin/clone.c +3 -1
@@ -617,13 +617,15 @@ static int git_sparse_checkout_init(const char *repo) {struct child_process cmd =CHILD_PROCESS_INIT ;int result =0 ; +struct repo_config_values *cfg =repo_config_values (the_repository); +strvec_pushl (&cmd.args,"-C" , repo,"sparse-checkout" ,"set" ,NULL );/* * We must apply the setting in the current process * for the later checkout to use the sparse-checkout file. */ - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ; cmd.git_cmd =1 ;if (run_command (&cmd)) {
builtin/grep.c +1 -1
@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,* "forget" the sparse-index feature switch. As a result, the index * of these submodules are expanded unexpectedly. * -* 2. "core_apply_sparse_checkout" +* 2. "config_values_private_.apply_sparse_checkout" * When running `grep` in the superproject, this setting is * populated using the superproject's configs. However, once * initialized, this config is globally accessible and is read by
builtin/mv.c +2 -1
@@ -238,6 +238,7 @@ int cmd_mv(int argc,struct hashmap moved_dirs =HASHMAP_INIT (pathmap_cmp,NULL );struct strbuf pathbuf =STRBUF_INIT ;int ret; +struct repo_config_values *cfg =repo_config_values (the_repository);repo_config (the_repository, git_default_config,NULL );
@@ -572,7 +573,7 @@ int cmd_mv(int argc,rename_index_entry_at (the_repository->index, pos, dst);if (ignore_sparse && - core_apply_sparse_checkout && + cfg->apply_sparse_checkout && core_sparse_checkout_cone) {/* * NEEDSWORK: we are *not* paying attention to
builtin/sparse-checkout.c +20 -11
@@ -61,9 +61,10 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,struct pattern_list pl;char *sparse_filename;int res; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("this worktree is not sparse" )); argc = parse_options(argc, argv, prefix,
@@ -399,12 +400,14 @@ static int set_config(struct repository *repo, }static enum sparse_checkout_mode update_cone_mode (int *cone_mode) { +struct repo_config_values *cfg =repo_config_values (the_repository); +/* If not specified, use previous definition of cone mode */ -if (*cone_mode ==-1 && core_apply_sparse_checkout) +if (*cone_mode ==-1 && cfg->apply_sparse_checkout) *cone_mode = core_sparse_checkout_cone;/* Set cone/non-cone mode appropriately */ - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ;if (*cone_mode ==1 || *cone_mode ==-1 ) { core_sparse_checkout_cone =1 ;return MODE_CONE_PATTERNS ;
@@ -416,9 +419,10 @@ static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {static int update_modes (struct repository *repo,int *cone_mode,int *sparse_index) {int mode, record_mode; +struct repo_config_values *cfg =repo_config_values (the_repository);/* Determine if we need to record the mode; ensure sparse checkout on */ - record_mode = (*cone_mode !=-1 ) || !core_apply_sparse_checkout; + record_mode = (*cone_mode !=-1 ) || !cfg->apply_sparse_checkout; mode =update_cone_mode (cone_mode);if (record_mode &&set_config (repo, mode))
@@ -684,6 +688,7 @@ static int modify_pattern_list(struct repository *repo,int result;int changed_config =0 ;struct pattern_list *pl =xcalloc (1 ,sizeof (*pl)); +struct repo_config_values *cfg =repo_config_values (the_repository);switch (m) {case ADD :
@@ -699,9 +704,9 @@ static int modify_pattern_list(struct repository *repo,break ; } -if (!core_apply_sparse_checkout) { +if (!cfg->apply_sparse_checkout) {set_config (repo,MODE_ALL_PATTERNS ); - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ; changed_config =1 ; }
@@ -796,9 +801,10 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix, };struct strvec patterns =STRVEC_INIT ;int ret; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("no sparse-checkout to add to" ));repo_read_index (repo);
@@ -905,9 +911,10 @@ static int sparse_checkout_reapply(int argc, const char **argv, N_("toggle the use of a sparse index")), OPT_END(), }; +struct repo_config_values *cfg =repo_config_values (the_repository);setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("must be in a sparse-checkout to reapply sparsity patterns" )); reapply_opts.cone_mode =-1 ;
@@ -960,6 +967,7 @@ static int sparse_checkout_clean(int argc, const char **argv,size_t worktree_len;int force =0 , dry_run =0 , verbose =0 ;int require_force =1 ; +struct repo_config_values *cfg =repo_config_values (the_repository);struct option builtin_sparse_checkout_clean_options[] = {OPT__DRY_RUN (&dry_run,N_ ("dry run" )),
@@ -969,7 +977,7 @@ static int sparse_checkout_clean(int argc, const char **argv, };setup_work_tree (); -if (!core_apply_sparse_checkout) +if (!cfg->apply_sparse_checkout)die (_ ("must be in a sparse-checkout to clean directories" ));if (!core_sparse_checkout_cone)die (_ ("must be in a cone-mode sparse-checkout to clean directories" ));
@@ -1033,9 +1041,10 @@ static int sparse_checkout_disable(int argc, const char **argv, OPT_END(), };struct pattern_list pl; +struct repo_config_values *cfg =repo_config_values (the_repository);/* -* We do not exit early if !core_apply_sparse_checkout; due to the +* We do not exit early if !repo->config_values.apply_sparse_checkout; due to the * ability for users to manually muck things up between * direct editing of .git/info/sparse-checkout * running read-tree -m u HEAD or update-index --skip-worktree
@@ -1061,7 +1070,7 @@ static int sparse_checkout_disable(int argc, const char **argv,hashmap_init (&pl.recursive_hashmap, pl_hashmap_cmp,NULL ,0 );hashmap_init (&pl.parent_hashmap, pl_hashmap_cmp,NULL ,0 ); pl.use_cone_patterns =0 ; - core_apply_sparse_checkout =1 ; + cfg->apply_sparse_checkout =1 ;add_pattern ("/*" , empty_base,0 , &pl,0 );
builtin/worktree.c +2 -1
@@ -440,6 +440,7 @@ static int add_worktree(const char *path, const char *refname,struct strbuf sb_name =STRBUF_INIT ;struct worktree **worktrees, *wt =NULL ;struct ref_store *wt_refs; +struct repo_config_values *cfg =repo_config_values (the_repository); worktrees =get_worktrees ();check_candidate_path (path, opts->force, worktrees,"add" );
@@ -536,7 +537,7 @@ static int add_worktree(const char *path, const char *refname,* If the current worktree has sparse-checkout enabled, then copy * the sparse-checkout patterns from the current worktree. */ -if (core_apply_sparse_checkout) +if (cfg->apply_sparse_checkout)copy_sparse_checkout (sb_repo.buf);/*
dir.c +3 -1
@@ -1551,7 +1551,9 @@ enum pattern_match_result path_matches_pattern_list(int init_sparse_checkout_patterns (struct index_state *istate) { -if (!core_apply_sparse_checkout) +struct repo_config_values *cfg =repo_config_values (the_repository); + +if (!cfg->apply_sparse_checkout)return 1 ;if (istate->sparse_checkout_patterns)return 0 ;
environment.c +2 -2
@@ -74,7 +74,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_apply_sparse_checkout;int core_sparse_checkout_cone;int sparse_expect_files_outside_of_patterns;int precomposed_unicode =-1 ;/* see probe_utf8_pathname_composition() */
@@ -546,7 +545,7 @@ static int git_default_core_config(const char *var, const char *value, }if (!strcmp (var,"core.sparsecheckout" )) { - core_apply_sparse_checkout =git_config_bool (var, value); + cfg->apply_sparse_checkout =git_config_bool (var, value);return 0 ; }
@@ -761,4 +760,5 @@ int git_default_config(const char *var, const char *value,void repo_config_values_init (struct repo_config_values *cfg) { cfg->attributes_file =NULL ; + cfg->apply_sparse_checkout =0 ; }
environment.h +1 -1
@@ -88,6 +88,7 @@ struct repository;struct repo_config_values {/* section "core" config values */ char *attributes_file; +int apply_sparse_checkout; };struct repo_config_values *repo_config_values (struct repository *repo);
@@ -171,7 +172,6 @@ extern int precomposed_unicode;extern int protect_hfs;extern int protect_ntfs; -extern int core_apply_sparse_checkout;extern int core_sparse_checkout_cone;extern int sparse_expect_files_outside_of_patterns;
sparse-index.c +5 -2
@@ -152,7 +152,9 @@ static int index_has_unmerged_entries(struct index_state *istate)int is_sparse_index_allowed (struct index_state *istate,int flags) { -if (!core_apply_sparse_checkout || !core_sparse_checkout_cone) +struct repo_config_values *cfg =repo_config_values (the_repository); + +if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)return 0 ;if (!(flags &SPARSE_INDEX_MEMORY_ONLY )) {
@@ -670,7 +672,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { -if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
unpack-trees.c +2 -1
@@ -1888,6 +1888,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsstruct pattern_list pl;int free_pattern_list =0 ;struct dir_struct dir =DIR_INIT ; +struct repo_config_values *cfg =repo_config_values (the_repository);if (o->reset ==UNPACK_RESET_INVALID )BUG ("o->reset had a value of 1; should be UNPACK_TREES_*_UNTRACKED" );
@@ -1924,7 +1925,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_optionsif (o->prefix)update_sparsity_for_prefix (o->prefix, o->src_index); -if (!core_apply_sparse_checkout || !o->update) +if (!cfg->apply_sparse_checkout || !o->update) o->skip_sparse_checkout =1 ;if (!o->skip_sparse_checkout) {memset (&pl,0 ,sizeof (pl));
wt-status.c +3 -1
@@ -1763,8 +1763,10 @@ static void wt_status_check_sparse_checkout(struct repository *r, {int skip_worktree =0 ;int i; +struct repo_config_values *cfg =repo_config_values (the_repository); -if (!core_apply_sparse_checkout || r->index->cache_nr ==0 ) { +if (!cfg->apply_sparse_checkout || + r->index->cache_nr ==0 ) {/* * Don't compute percentage of checked out files if we * aren't in a sparse checkout or would get division by 0.
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v7 2/3] environment: stop using core.sparseCheckout globally
sparse-index.c static void clear_skip_worktree_from_present_files_full(struct index_state *ista · line 675
Quoted 6 lines · Olamide Caleb Bello
sparse-index.c +1
-1@@ -670,7 +672,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { - if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository);
Nit: it would be better with a blank line here.
Quoted 3 lines
sparse-index.c +1
-0+if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
Re: [Outreachy PATCH v7 2/3] environment: stop using core.sparseCheckout globally
Quoted 14 lines · Christian Couder
sparse-index.c static void clear_skip_worktree_from_present_files_full(struct index_state *ista · line 675
Quoted 6 lines · Olamide Caleb Bello
sparse-index.c +1
-1@@ -670,7 +672,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { - if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository);Nit: it would be better with a blank line here.
Quoted 3 lines
sparse-index.c +1
-0+if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;
OK. Agreed and locally amended.
Let's merge the topic down to 'next'.
Re: [Outreachy PATCH v7 2/3] environment: stop using core.sparseCheckout globally
Quoted 14 lines · Junio C Hamano
Quoted 11 lines · Christian Couder
sparse-index.c static void clear_skip_worktree_from_present_files_full(struct index_state *ista · line 675
Quoted 6 lines · Olamide Caleb Bello
sparse-index.c +1
-1@@ -670,7 +672,8 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *istavoid clear_skip_worktree_from_present_files (struct index_state *istate) { - if (!core_apply_sparse_checkout || +struct repo_config_values *cfg =repo_config_values (the_repository);Nit: it would be better with a blank line here.
Quoted 7 lines
Quoted 3 lines
sparse-index.c static void clear_skip_worktree_from_present_files_full(struct index_state *ista · line 678
Quoted 3 lines
sparse-index.c +1
-0+if (!cfg->apply_sparse_checkout || sparse_expect_files_outside_of_patterns)return ;OK. Agreed and locally amended.
Let's merge the topic down to 'next'.
Thank you very much for all your assistance.
PATCH v7 3/3 environment: move "branch.autoSetupMerge" into `struct repo_config_values`
In reply to Olamide Caleb BelloThe config value branch.autoSetupMerge is parsed in git_default_branch_config() and stored in the global variable git_branch_track. This global variable can be overwritten
by another repository when multiple Git repos run in the the same process.
Move this value into struct repo_config_values in the_repository to retain current behaviours and move towards libifying Git. Since the variable is no longer a global variable, it has been renamed to branch_track in the struct repo_config_values.
--- branch.h | 2 -- builtin/branch.c | 3 ++- builtin/checkout.c | 3 ++- builtin/push.c | 3 ++- builtin/submodule--helper.c | 3 ++- environment.c | 12 +++++++----- environment.h | 4 ++++ 7 files changed, 19 insertions(+), 11 deletions(-)
branch.h +0 -2
@@ -15,8 +15,6 @@ enum branch_track { BRANCH_TRACK_SIMPLE, }; -extern enum branch_track git_branch_track; -/* Functions for acting on the information about branches. */ /**
builtin/branch.c +2 -1
@@ -724,6 +724,7 @@ int cmd_branch(int argc,static struct ref_sorting *sorting;struct string_list sorting_options =STRING_LIST_INIT_DUP ;struct ref_format format =REF_FORMAT_INIT ; +struct repo_config_values *cfg =repo_config_values (the_repository);int ret;struct option options[] = {
@@ -795,7 +796,7 @@ int cmd_branch(int argc,if (!sorting_options.nr)string_list_append (&sorting_options,"refname" ); - track = git_branch_track; + track = cfg->branch_track; head =refs_resolve_refdup (get_main_ref_store (the_repository),"HEAD" ,0 , &head_oid,NULL );
builtin/checkout.c +2 -1
@@ -1588,6 +1588,7 @@ static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts,static int checkout_branch (struct checkout_opts *opts,struct branch_info *new_branch_info) { +struct repo_config_values *cfg =repo_config_values (the_repository);int noop_switch = (!new_branch_info->name && !opts->new_branch && !opts->force_detach);
@@ -1631,7 +1632,7 @@ static int checkout_branch(struct checkout_opts *opts,if (opts->track !=BRANCH_TRACK_UNSPECIFIED )die (_ ("'%s' cannot be used with '%s'" ),"--detach" ,"-t" ); }else if (opts->track ==BRANCH_TRACK_UNSPECIFIED ) - opts->track = git_branch_track; + opts->track = cfg->branch_track;if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"),
builtin/push.c +2 -1
@@ -151,6 +151,7 @@ static NORETURN void die_push_simple(struct branch *branch,const char *advice_pushdefault_maybe ="" ;const char *advice_automergesimple_maybe ="" ;const char *short_upstream = branch->merge[0 ]->src; +struct repo_config_values *cfg =repo_config_values (the_repository);skip_prefix (short_upstream,"refs/heads/" , &short_upstream);
@@ -162,7 +163,7 @@ static NORETURN void die_push_simple(struct branch *branch, advice_pushdefault_maybe =_ ("\n" "To choose either option permanently, " "see push.default in 'git help config'.\n" ); -if (git_branch_track !=BRANCH_TRACK_SIMPLE ) +if (cfg->branch_track !=BRANCH_TRACK_SIMPLE ) advice_automergesimple_maybe =_ ("\n" "To avoid automatically configuring " "an upstream branch when its name\n"
builtin/submodule--helper.c +2 -1
@@ -3126,9 +3126,10 @@ static int module_create_branch(int argc, const char **argv, const char *prefix,N_ ("git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" ), NULL }; +struct repo_config_values *cfg =repo_config_values (the_repository);repo_config (the_repository, git_default_config,NULL ); - track = git_branch_track; + track = cfg->branch_track; argc =parse_options (argc, argv, prefix, options, usage,0 );if (argc !=3 )
environment.c +7 -5
@@ -66,7 +66,6 @@ enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;enum eol core_eol =EOL_UNSET ;int global_conv_flags_eol =CONV_EOL_RNDTRP_WARN ;char *check_roundtrip_encoding; -enum branch_track git_branch_track =BRANCH_TRACK_REMOTE ;enum rebase_setup_type autorebase =AUTOREBASE_NEVER ;enum push_default_type push_default =PUSH_DEFAULT_UNSPECIFIED ;#ifndef OBJECT_CREATION_MODE
@@ -607,18 +606,20 @@ static int git_default_i18n_config(const char *var, const char *value)static int git_default_branch_config (const char *var,const char *value) { +struct repo_config_values *cfg =repo_config_values (the_repository); +if (!strcmp (var,"branch.autosetupmerge" )) {if (value && !strcmp (value,"always" )) { - git_branch_track =BRANCH_TRACK_ALWAYS ; + cfg->branch_track =BRANCH_TRACK_ALWAYS ;return 0 ; }else if (value && !strcmp (value,"inherit" )) { - git_branch_track =BRANCH_TRACK_INHERIT ; + cfg->branch_track =BRANCH_TRACK_INHERIT ;return 0 ; }else if (value && !strcmp (value,"simple" )) { - git_branch_track =BRANCH_TRACK_SIMPLE ; + cfg->branch_track =BRANCH_TRACK_SIMPLE ;return 0 ; } - git_branch_track =git_config_bool (var, value); + cfg->branch_track =git_config_bool (var, value);return 0 ; }if (!strcmp (var,"branch.autosetuprebase" )) {
@@ -761,4 +762,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 ; }
environment.h +4 -0
@@ -2,6 +2,7 @@#define ENVIRONMENT_H #include "repo-settings.h" +#include "branch.h" /* Double-check local_repo_env below if you add to this list. */ #define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -89,6 +90,9 @@ struct repo_config_values {/* section "core" config values */ char *attributes_file;int apply_sparse_checkout; + +/* section "branch" config values */ +enum branch_track branch_track; };struct repo_config_values *repo_config_values (struct repository *repo);
Signature · 1 line
2.34.1
Re: [Outreachy PATCH v7 0/3] store repo specific config values in new `struct repo_config_values`
In reply to Olamide Caleb BelloQuoted 10 lines · Olamide Caleb Bello
Changes in v7:
==============
- Added the code to reset the initialization ofthe_repositoryin the fuzz-commit-graph test in Patch 1.
- Changed the call torep_config_values_init()ininitialze_repository()by passing it the repoconfig_values_private_struct instead of the accessor function in Patch 1.
- Modified the commit message in Patch 1
- Added extra lines between variable declarations and code
Quoted 5 lines
+struct repo_config_values *repo_config_values(struct repository *repo)
+{
++ if (repo != the_repository)
++ BUG("trying to read config from wrong repository instance");
+ if(!repo->initialized)$ git clang-format --diff $(git merge-base master HEAD)
would have pointed out the style issue here.
Will amend while queuing but it would be a bit before I can get to this patch set for real reviews.
Thanks.
Re: [Outreachy PATCH v7 0/3] store repo specific config values in new `struct repo_config_values`
Quoted 19 lines · Junio C Hamano
Quoted 10 lines · Olamide Caleb Bello
Changes in v7:
==============
- Added the code to reset the initialization ofthe_repositoryin the fuzz-commit-graph test in Patch 1.
- Changed the call torep_config_values_init()ininitialze_repository()by passing it the repoconfig_values_private_struct instead of the accessor function in Patch 1.
- Modified the commit message in Patch 1
- Added extra lines between variable declarations and codeQuoted 5 lines
+struct repo_config_values *repo_config_values(struct repository *repo) +{ ++ if (repo != the_repository) ++ BUG("trying to read config from wrong repository instance"); + if(!repo->initialized)
Quoted 9 lines
$ git clang-format --diff $(git merge-base master HEAD)would have pointed out the style issue here.
Will amend while queuing but it would be a bit before I can get to this patch set for real reviews.
Thanks.
Sorry about missing this style issue and thank you for your reviews and guidance Do I wait for this before continuing to move other repo specific config values into the struct since I might need to rebase?
Thanks
Re: [Outreachy PATCH v7 0/3] store repo specific config values in new `struct repo_config_values`
In reply to Junio C HamanoQuoted 19 lines · Junio C Hamano
Quoted 10 lines · Olamide Caleb Bello
Changes in v7:
==============
- Added the code to reset the initialization ofthe_repositoryin the fuzz-commit-graph test in Patch 1.
- Changed the call torep_config_values_init()ininitialze_repository()by passing it the repoconfig_values_private_struct instead of the accessor function in Patch 1.
- Modified the commit message in Patch 1
- Added extra lines between variable declarations and codeQuoted 5 lines
+struct repo_config_values *repo_config_values(struct repository *repo) +{ ++ if (repo != the_repository) ++ BUG("trying to read config from wrong repository instance"); + if(!repo->initialized)
Quoted 6 lines
$ git clang-format --diff $(git merge-base master HEAD)would have pointed out the style issue here.
Will amend while queuing but it would be a bit before I can get to this patch set for real reviews.
I took another look at the series and found only another nit (a missing blank line). Otherwise the series looks good to me.
Thanks.
Re: [Outreachy PATCH v7 0/3] store repo specific config values in new `struct repo_config_values`
Quoted 4 lines · Christian Couder
I took another look at the series and found only another nit (a missing blank line). Otherwise the series looks good to me.
Thanks.
Thanks for reviewing.