{"thread":{"id":"63571","subject":"[GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","startedAt":"2025-06-03T13:18:32Z","lastAt":"2025-09-05T17:10:15Z","messageCount":50,"participants":["Ayush Chandekar","Patrick Steinhardt","Ben Knoble","Christian Couder","Junio C Hamano","Phillip Wood","Derrick Stolee"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"519551","messageId":"20250603131806.14915-1-ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":null,"subject":"[GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-03T13:18:06Z","receivedAt":"2025-06-03T13:18:32Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it inside the struct `repo_settings`. Also, create\nfunctions to set and get the value of the setting and update all the\noccurrences.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/backfill.c        |  5 +----\n builtin/clone.c           |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 18 +++++++++---------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           | 11 +++++++++++\n repo-settings.h           |  5 +++++\n sparse-index.c            |  4 ++--\n unpack-trees.c            |  2 +-\n wt-status.c               |  2 +-\n 14 files changed, 34 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex fa82ad2f6f..d397b8e721 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -139,7 +136,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \trepo_config(repo, git_default_config, NULL);\n \n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo_settings_get_apply_sparse_checkout(repo);\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 91b9cd0d16..1d1cd880c4 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -621,7 +621,7 @@ static int git_sparse_checkout_init(const char *repo)\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..dc9d0b1ab3 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -572,7 +572,7 @@ int cmd_mv(int argc,\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n \n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    repo_settings_get_apply_sparse_checkout(the_repository) &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..41e3a9d61d 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && repo_settings_get_apply_sparse_checkout(the_repository))\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !repo_settings_get_apply_sparse_checkout(the_repository);\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!repo_settings_get_apply_sparse_checkout(the_repository)) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -961,7 +961,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 88a36ea9f8..a6044dbe5f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (repo_settings_get_apply_sparse_checkout(the_repository))\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex b18b5617fc..8fd4dd8c81 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex a374972b62..2df307bb48 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1503,7 +1503,7 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex c61d773e7e..a379a9149e 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d98461a06..6a30512f3c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 4129f8fb2b..406c70601c 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.core_apply_sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n@@ -227,3 +228,13 @@ void repo_settings_reset_shared_repository(struct repository *repo)\n {\n \trepo->settings.shared_repository_initialized = 0;\n }\n+\n+int repo_settings_get_apply_sparse_checkout(struct repository *repo)\n+{\n+\treturn repo->settings.core_apply_sparse_checkout;\n+}\n+\n+void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n+{\n+\trepo->settings.core_apply_sparse_checkout = value;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 2bf24b2597..e4e797e85c 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint core_apply_sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\n@@ -98,4 +99,8 @@ int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\n void repo_settings_reset_shared_repository(struct repository *repo);\n \n+/* Read, set or reset the value for \"core.sparsecheckout\". */\n+int repo_settings_get_apply_sparse_checkout(struct repository *repo);\n+void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..1565708190 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!repo_settings_get_apply_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!repo_settings_get_apply_sparse_checkout(istate->repo) ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 471837f032..b3bf992067 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo_settings_get_apply_sparse_checkout(repo) || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..afe98a1bb9 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tif (!repo_settings_get_apply_sparse_checkout(r) || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n-- \n2.43.0\n\n"},{"id":"519552","messageId":"aD77fz3N-fLI8DjM@pks.im","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-06-03T13:41:19Z","receivedAt":"2025-06-03T13:41:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Jun 03, 2025 at 06:48:06PM +0530, Ayush Chandekar wrote:\n> diff --git a/repo-settings.c b/repo-settings.c\n> index 4129f8fb2b..406c70601c 100644\n> --- a/repo-settings.c\n> +++ b/repo-settings.c\n> @@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n>  \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n>  \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n>  \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n> +\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.core_apply_sparse_checkout, 0);\n\nThe config is called \"core.sparseCheckout\", so why is the variable\ncalled `core_apply_sparse_checkout`? `core_sparse_checkout` I would've\nunderstood, but where does \"apply\" come from? Also, for brevity I think\nwe could just call it `settings.sparse_checkout`.\n\n> @@ -227,3 +228,13 @@ void repo_settings_reset_shared_repository(struct repository *repo)\n>  {\n>  \trepo->settings.shared_repository_initialized = 0;\n>  }\n> +\n> +int repo_settings_get_apply_sparse_checkout(struct repository *repo)\n\nSame remark here -- where does the \"apply\" part come from?\n\n> +{\n> +\treturn repo->settings.core_apply_sparse_checkout;\n> +}\n> +\n> +void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n> +{\n> +\trepo->settings.core_apply_sparse_checkout = value;\n> +}\n\nGetters and setters only really help in the case where they actually\nprovide a benefit. These don't though, so it's dubious whether we should\nhave them.\n\nAlso, shouldn't these functions call `prepare_repo_settings()`?\nOtherwise we cannot guarantee that those settings have already been\nparsed at all. And for the setter it could happen that the settings get\noverwritten by the next caller of `prepare_repo_settings()`.\n\nPatrick\n"},{"id":"519580","messageId":"CAE7as+Y0hzkPUC-q7dd-eSJVi0H_nwzQL1AGZJnKMyYcrX1dLw@mail.gmail.com","threadId":"63571","inReplyTo":"aD77fz3N-fLI8DjM@pks.im","subject":"Re: [GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-03T16:20:53Z","receivedAt":"2025-06-03T16:21:04Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"> The config is called \"core.sparseCheckout\", so why is the variable\n> called `core_apply_sparse_checkout`? `core_sparse_checkout` I would've\n> understood, but where does \"apply\" come from? Also, for brevity I think\n> we could just call it `settings.sparse_checkout`.\n>\nYes, I had this thought as well that adding \"apply\" doesn't make a lot of sense.\nBut I thought since the global variable has this name for a long time, there\nmust have been some reason. I can change the name if the \"apply\" doesn't hold\nany value.\n\n>\n> > +{\n> > +     return repo->settings.core_apply_sparse_checkout;\n> > +}\n> > +\n> > +void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n> > +{\n> > +     repo->settings.core_apply_sparse_checkout = value;\n> > +}\n>\n> Getters and setters only really help in the case where they actually\n> provide a benefit. These don't though, so it's dubious whether we should\n> have them.\n>\n> Also, shouldn't these functions call `prepare_repo_settings()`?\n> Otherwise we cannot guarantee that those settings have already been\n> parsed at all. And for the setter it could happen that the settings get\n> overwritten by the next caller of `prepare_repo_settings()`.\n>\n\nOh, yeah, you're right. So, if we use `prepare_repo_settings()` in\nthem, wouldn't\nit be better to use getter and setter functions? Otherwise, I'd have to call\n`prepare_repo_settings()` everywhere I'm using the setting.\n"},{"id":"519623","messageId":"4F074544-4E25-472D-A42C-C50A1E1CAC69@gmail.com","threadId":"63571","inReplyTo":"CAE7as+Y0hzkPUC-q7dd-eSJVi0H_nwzQL1AGZJnKMyYcrX1dLw@mail.gmail.com","subject":"Re: [GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-06-04T02:20:38Z","receivedAt":"2025-06-04T02:20:49Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"\n> Le 3 juin 2025 à 12:21, Ayush Chandekar <ayu.chandekar@gmail.com> a écrit :\n> \n> ﻿\n>> The config is called \"core.sparseCheckout\", so why is the variable\n>> called `core_apply_sparse_checkout`? `core_sparse_checkout` I would've\n>> understood, but where does \"apply\" come from? Also, for brevity I think\n>> we could just call it `settings.sparse_checkout`.\n> Yes, I had this thought as well that adding \"apply\" doesn't make a lot of sense.\n> But I thought since the global variable has this name for a long time, there\n> must have been some reason. I can change the name if the \"apply\" doesn't hold\n> any value.\n\nPerhaps \"git log -S core_apply_sparse_checkout config.c\" or similar will reveal a reason? Or point us at a patch series that has some discussion?\n\n> \n>>> +{\n>>> +     return repo->settings.core_apply_sparse_checkout;\n>>> +}\n>>> +\n>>> +void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n>>> +{\n>>> +     repo->settings.core_apply_sparse_checkout = value;\n>>> +}\n>> Getters and setters only really help in the case where they actually\n>> provide a benefit. These don't though, so it's dubious whether we should\n>> have them.\n\nMy thoughts exactly; see below.\n\n>> Also, shouldn't these functions call `prepare_repo_settings()`?\n>> Otherwise we cannot guarantee that those settings have already been\n>> parsed at all. And for the setter it could happen that the settings get\n>> overwritten by the next caller of `prepare_repo_settings()`.\n> \n> Oh, yeah, you're right. So, if we use `prepare_repo_settings()` in\n> them, wouldn't\n> it be better to use getter and setter functions? Otherwise, I'd have to call\n> `prepare_repo_settings()` everywhere I'm using the setting.\n\nAren’t most of the consumers builtins? And from a recent look, don’t they (all?) initialize the repo settings? I agree it is relatively painful to require developers to make sure that prepare_repo_settings has been called on each (new) code path that reads this variable, but OTOH I would expect that to be a straightforward audit during this change and then (see following) relatively easy to catch going forward. Is already a code convention that reading things in repo->settings depends on having prepared them?"},{"id":"519632","messageId":"aD_1tD-H74SOh1Xx@pks.im","threadId":"63571","inReplyTo":"4F074544-4E25-472D-A42C-C50A1E1CAC69@gmail.com","subject":"Re: [GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-06-04T07:28:52Z","receivedAt":"2025-06-04T07:28:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Jun 03, 2025 at 10:20:38PM -0400, Ben Knoble wrote:\n> > Le 3 juin 2025 à 12:21, Ayush Chandekar <ayu.chandekar@gmail.com> a écrit :\n> >>> +{\n> >>> +     return repo->settings.core_apply_sparse_checkout;\n> >>> +}\n> >>> +\n> >>> +void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n> >>> +{\n> >>> +     repo->settings.core_apply_sparse_checkout = value;\n> >>> +}\n> >> Getters and setters only really help in the case where they actually\n> >> provide a benefit. These don't though, so it's dubious whether we should\n> >> have them.\n> \n> My thoughts exactly; see below.\n> \n> >> Also, shouldn't these functions call `prepare_repo_settings()`?\n> >> Otherwise we cannot guarantee that those settings have already been\n> >> parsed at all. And for the setter it could happen that the settings get\n> >> overwritten by the next caller of `prepare_repo_settings()`.\n> > \n> > Oh, yeah, you're right. So, if we use `prepare_repo_settings()` in\n> > them, wouldn't\n> > it be better to use getter and setter functions? Otherwise, I'd have to call\n> > `prepare_repo_settings()` everywhere I'm using the setting.\n> \n> Aren’t most of the consumers builtins? And from a recent look, don’t\n> they (all?) initialize the repo settings? I agree it is relatively\n> painful to require developers to make sure that prepare_repo_settings\n> has been called on each (new) code path that reads this variable, but\n> OTOH I would expect that to be a straightforward audit during this\n> change and then (see following) relatively easy to catch going\n> forward. Is already a code convention that reading things in\n> repo->settings depends on having prepared them?\n\nYes, it is a code convention. We have two patterns though:\n\n  - Those that access the repo settings fields directly _always_ call\n    `prepare_repo_settings()` manually beforehand.\n\n  - Those that use a getter/setter rely on those to call\n    `prepare_repo_settings()`.\n\nSo if you add the call to `prepare_repo_settings()` the getter and\nsetter do provide additional value. So in that case it may be sensible\nto retain them indeed.\n\nPatrick\n"},{"id":"519704","messageId":"CAE7as+bH5nDTPqQkE6ZFzTrQ7+CZndsni9Zy6tzuTbq5BZSFYA@mail.gmail.com","threadId":"63571","inReplyTo":"4F074544-4E25-472D-A42C-C50A1E1CAC69@gmail.com","subject":"Re: [GSOC PATCH] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-04T23:48:15Z","receivedAt":"2025-06-04T23:48:27Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Wed, Jun 4, 2025 at 7:50 AM Ben Knoble <ben.knoble@gmail.com> wrote:\n>\n>\n> > Le 3 juin 2025 à 12:21, Ayush Chandekar <ayu.chandekar@gmail.com> a écrit :\n> >\n> > ﻿\n> >> The config is called \"core.sparseCheckout\", so why is the variable\n> >> called `core_apply_sparse_checkout`? `core_sparse_checkout` I would've\n> >> understood, but where does \"apply\" come from? Also, for brevity I think\n> >> we could just call it `settings.sparse_checkout`.\n> > Yes, I had this thought as well that adding \"apply\" doesn't make a lot of sense.\n> > But I thought since the global variable has this name for a long time, there\n> > must have been some reason. I can change the name if the \"apply\" doesn't hold\n> > any value.\n>\n> Perhaps \"git log -S core_apply_sparse_checkout config.c\" or similar will reveal a reason? Or point us at a patch series that has some discussion?\n>\nI ran the command to see previous commits and also went through the\npatch that introduced that variable, but there was no reasoning for\nwhy it was named that way.\nThere was no comment as well for the patch that introduced it. I think\nwe can also get rid of the \"core\" (so it just becomes\n\"sparse_checkout\") as there exist other core settings which don't have\n\"core\" in their variable names and since we are changing the name\nanyways.\n\n> >\n> >>> +{\n> >>> +     return repo->settings.core_apply_sparse_checkout;\n> >>> +}\n> >>> +\n> >>> +void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n> >>> +{\n> >>> +     repo->settings.core_apply_sparse_checkout = value;\n> >>> +}\n> >> Getters and setters only really help in the case where they actually\n> >> provide a benefit. These don't though, so it's dubious whether we should\n> >> have them.\n>\n> My thoughts exactly; see below.\n>\n> >> Also, shouldn't these functions call `prepare_repo_settings()`?\n> >> Otherwise we cannot guarantee that those settings have already been\n> >> parsed at all. And for the setter it could happen that the settings get\n> >> overwritten by the next caller of `prepare_repo_settings()`.\n> >\n> > Oh, yeah, you're right. So, if we use `prepare_repo_settings()` in\n> > them, wouldn't\n> > it be better to use getter and setter functions? Otherwise, I'd have to call\n> > `prepare_repo_settings()` everywhere I'm using the setting.\n>\n> Aren’t most of the consumers builtins? And from a recent look, don’t they (all?) initialize the repo settings? I agree it is relatively painful to require developers to make sure that prepare_repo_settings has been called on each (new) code path that reads this variable, but OTOH I would expect that to be a straightforward audit during this change and then (see following) relatively easy to catch going forward. Is already a code convention that reading things in repo->settings depends on having prepared them?\n\nYeah, as Patrick said, we have to call the `prepare_repo_settings()`\nbefore we access these settings.\nSo, either we manually call the function or use it inside a\ngetter/setter function.\n\nThanks\n"},{"id":"519898","messageId":"20250608003134.7488-1-ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"[GSOC PATCH v2] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-08T00:31:34Z","receivedAt":"2025-06-08T00:32:12Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout` in the struct\n`repo_settings`. Also, create functions to set and get the value of the\nsetting and update all the occurrences.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/backfill.c        |  5 +----\n builtin/clone.c           |  2 +-\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 20 ++++++++++----------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           | 13 +++++++++++++\n repo-settings.h           |  5 +++++\n sparse-index.c            |  4 ++--\n unpack-trees.c            |  2 +-\n wt-status.c               |  2 +-\n 15 files changed, 38 insertions(+), 30 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex fa82ad2f6f..e16d116e98 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -139,7 +136,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \trepo_config(repo, git_default_config, NULL);\n \n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo_settings_get_sparse_checkout(repo);\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 91b9cd0d16..ba25e58258 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -621,7 +621,7 @@ static int git_sparse_checkout_init(const char *repo)\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 3ce574a605..63342f5e36 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -481,7 +481,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n \t *\tof these submodules are expanded unexpectedly.\n \t *\n-\t * 2. \"core_apply_sparse_checkout\"\n+\t * 2. \"sparse_checkout\"\n \t *\tWhen running `grep` in the superproject, this setting is\n \t *\tpopulated using the superproject's configs. However, once\n \t *\tinitialized, this config is globally accessible and is read by\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..95d24843d9 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -572,7 +572,7 @@ int cmd_mv(int argc,\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n \n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    repo_settings_get_sparse_checkout(the_repository) &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..662858b0a8 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && repo_settings_get_sparse_checkout(the_repository))\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !repo_settings_get_sparse_checkout(the_repository);\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!repo_settings_get_sparse_checkout(the_repository)) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\trepo_settings_set_sparse_checkout(the_repository, 1);\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -935,7 +935,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \tstruct pattern_list pl;\n \n \t/*\n-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n+\t * We do not exit early if !sparse_checkout; due to the\n \t * ability for users to manually muck things up between\n \t *   direct editing of .git/info/sparse-checkout\n \t *   running read-tree -m u HEAD or update-index --skip-worktree\n@@ -961,7 +961,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 88a36ea9f8..590bec334f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (repo_settings_get_sparse_checkout(the_repository))\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex b18b5617fc..8fd4dd8c81 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex a374972b62..323017e7a5 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1503,7 +1503,7 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex c61d773e7e..a379a9149e 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d98461a06..6a30512f3c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 4129f8fb2b..e11201e25b 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n@@ -227,3 +228,15 @@ void repo_settings_reset_shared_repository(struct repository *repo)\n {\n \trepo->settings.shared_repository_initialized = 0;\n }\n+\n+int repo_settings_get_sparse_checkout(struct repository *repo)\n+{\n+\tprepare_repo_settings(repo);\n+\treturn repo->settings.sparse_checkout;\n+}\n+\n+void repo_settings_set_sparse_checkout(struct repository *repo, int value)\n+{\n+\tprepare_repo_settings(repo);\n+\trepo->settings.sparse_checkout = value;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 2bf24b2597..0d181e3f21 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\n@@ -98,4 +99,8 @@ int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\n void repo_settings_reset_shared_repository(struct repository *repo);\n \n+/* Read or set the value for \"core.sparseCheckout\". */\n+int repo_settings_get_sparse_checkout(struct repository *repo);\n+void repo_settings_set_sparse_checkout(struct repository *repo, int value);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..1bedb35001 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!repo_settings_get_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!repo_settings_get_sparse_checkout(istate->repo) ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 471837f032..c8eba27e5f 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo_settings_get_sparse_checkout(repo) || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..004f2945b7 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tif (!repo_settings_get_sparse_checkout(r) || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n-- \n2.49.0\n\n"},{"id":"519910","messageId":"CAP8UFD2z4AhtArDn31jY8HkAXrNU-rkQwRE9=M-ntEdsQ3e40w@mail.gmail.com","threadId":"63571","inReplyTo":"20250608003134.7488-1-ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v2] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2025-06-08T06:39:00Z","receivedAt":"2025-06-08T06:39:14Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Sun, Jun 8, 2025 at 2:32 AM Ayush Chandekar <ayu.chandekar@gmail.com> wrote:\n>\n> The setting \"core.sparsecheckout\" is stored in the global\n> `core_apply_sparse_checkout` and is populated in config.c. Refactor the\n> code to store it in the variable `sparse_checkout` in the struct\n> `repo_settings`. Also, create functions to set and get the value of the\n> setting and update all the occurrences.\n>\n> This also allows us to remove the definition `#define\n> USE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n>\n> This change is part of an ongoing effort to eliminate global variables,\n> improve modularity and help libify the codebase.\n>\n> Signed-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n> ---\n\nWhen sending a v2 like this one, it's nice if you can describe what\nchanged since v1 here, after the line starting with 3 dashes \"---\".\nProviding a range-diff here, when it makes sense, could be a good idea\nand help reviewers too. Speaking of reviewers, thanking or just\nmentioning them is nice too while at it.\n\n>  builtin/backfill.c        |  5 +----\n>  builtin/clone.c           |  2 +-\n>  builtin/grep.c            |  2 +-\n>  builtin/mv.c              |  2 +-\n>  builtin/sparse-checkout.c | 20 ++++++++++----------\n>  builtin/worktree.c        |  2 +-\n>  config.c                  |  5 -----\n>  dir.c                     |  2 +-\n>  environment.c             |  1 -\n>  environment.h             |  1 -\n>  repo-settings.c           | 13 +++++++++++++\n>  repo-settings.h           |  5 +++++\n>  sparse-index.c            |  4 ++--\n>  unpack-trees.c            |  2 +-\n>  wt-status.c               |  2 +-\n>  15 files changed, 38 insertions(+), 30 deletions(-)\n"},{"id":"520118","messageId":"20250611173433.74393-1-ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"[PATCH v3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-11T17:34:33Z","receivedAt":"2025-06-11T17:35:30Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout` in the struct\n`repo_settings`. Also, create functions to set and get the value of the\nsetting and update all the occurrences.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n\nNote that this patch is the same as v2, the v3 just contains the range-diff \nof v2/v3 vs v1, and the 'Mentored-by' trailers.\n\nI thank my mentors Christian and Ghanshyam, as well as Patrick and Ben, \nfor reviewing my patch and suggesting changes.\n\nSummary of the range-diff:\n* Change the variable name from 'core_apply_sparse_checkout' to 'sparse_checkout'.\n* Update the getter and setter function names to use 'sparse_checkout' instead of 'apply_sparse_checkout'.\n* Call the function 'prepare_repo_settings()' in the getter/setter functions of the variable.\n\nRange-diff:\n1:  a385fc1dbe ! 1:  c49dcde03b environment: move access to \"core.sparsecheckout\" into repo_settings\n    @@ Commit message\n     \n         The setting \"core.sparsecheckout\" is stored in the global\n         `core_apply_sparse_checkout` and is populated in config.c. Refactor the\n    -    code to store it inside the struct `repo_settings`. Also, create\n    -    functions to set and get the value of the setting and update all the\n    -    occurrences.\n    +    code to store it in the variable `sparse_checkout` in the struct\n    +    `repo_settings`. Also, create functions to set and get the value of the\n    +    setting and update all the occurrences.\n     \n         This also allows us to remove the definition `#define\n         USE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n    @@ Commit message\n         This change is part of an ongoing effort to eliminate global variables,\n         improve modularity and help libify the codebase.\n     \n    +    Mentored-by: Christian Couder <christian.couder@gmail.com>\n    +    Mentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\n         Signed-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n     \n      ## builtin/backfill.c ##\n    @@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *pr\n      \n      \tif (ctx.sparse < 0)\n     -\t\tctx.sparse = core_apply_sparse_checkout;\n    -+\t\tctx.sparse = repo_settings_get_apply_sparse_checkout(repo);\n    ++\t\tctx.sparse = repo_settings_get_sparse_checkout(repo);\n      \n      \tresult = do_backfill(&ctx);\n      \tbackfill_context_clear(&ctx);\n    @@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)\n      \t * for the later checkout to use the sparse-checkout file.\n      \t */\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n    ++\trepo_settings_set_sparse_checkout(the_repository, 1);\n      \n      \tcmd.git_cmd = 1;\n      \tif (run_command(&cmd)) {\n     \n    + ## builtin/grep.c ##\n    +@@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,\n    + \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n    + \t *\tof these submodules are expanded unexpectedly.\n    + \t *\n    +-\t * 2. \"core_apply_sparse_checkout\"\n    ++\t * 2. \"sparse_checkout\"\n    + \t *\tWhen running `grep` in the superproject, this setting is\n    + \t *\tpopulated using the superproject's configs. However, once\n    + \t *\tinitialized, this config is globally accessible and is read by\n    +\n      ## builtin/mv.c ##\n     @@ builtin/mv.c: int cmd_mv(int argc,\n      \t\trename_index_entry_at(the_repository->index, pos, dst);\n      \n      \t\tif (ignore_sparse &&\n     -\t\t    core_apply_sparse_checkout &&\n    -+\t\t    repo_settings_get_apply_sparse_checkout(the_repository) &&\n    ++\t\t    repo_settings_get_sparse_checkout(the_repository) &&\n      \t\t    core_sparse_checkout_cone) {\n      \t\t\t/*\n      \t\t\t * NEEDSWORK: we are *not* paying attention to\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (!repo_settings_get_sparse_checkout(the_repository))\n      \t\tdie(_(\"this worktree is not sparse\"));\n      \n      \targc = parse_options(argc, argv, prefix,\n    @@ builtin/sparse-checkout.c: static int set_config(enum sparse_checkout_mode mode)\n      static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n      \t/* If not specified, use previous definition of cone mode */\n     -\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n    -+\tif (*cone_mode == -1 && repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (*cone_mode == -1 && repo_settings_get_sparse_checkout(the_repository))\n      \t\t*cone_mode = core_sparse_checkout_cone;\n      \n      \t/* Set cone/non-cone mode appropriately */\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n    ++\trepo_settings_set_sparse_checkout(the_repository, 1);\n      \tif (*cone_mode == 1 || *cone_mode == -1) {\n      \t\tcore_sparse_checkout_cone = 1;\n      \t\treturn MODE_CONE_PATTERNS;\n    @@ builtin/sparse-checkout.c: static int update_modes(int *cone_mode, int *sparse_i\n      \n      \t/* Determine if we need to record the mode; ensure sparse checkout on */\n     -\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n    -+\trecord_mode = (*cone_mode != -1) || !repo_settings_get_apply_sparse_checkout(the_repository);\n    ++\trecord_mode = (*cone_mode != -1) || !repo_settings_get_sparse_checkout(the_repository);\n      \n      \tmode = update_cone_mode(cone_mode);\n      \tif (record_mode && set_config(mode))\n    @@ builtin/sparse-checkout.c: static int modify_pattern_list(struct strvec *args, i\n      \t}\n      \n     -\tif (!core_apply_sparse_checkout) {\n    -+\tif (!repo_settings_get_apply_sparse_checkout(the_repository)) {\n    ++\tif (!repo_settings_get_sparse_checkout(the_repository)) {\n      \t\tset_config(MODE_ALL_PATTERNS);\n     -\t\tcore_apply_sparse_checkout = 1;\n    -+\t\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n    ++\t\trepo_settings_set_sparse_checkout(the_repository, 1);\n      \t\tchanged_config = 1;\n      \t}\n      \n    @@ builtin/sparse-checkout.c: static int sparse_checkout_add(int argc, const char *\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (!repo_settings_get_sparse_checkout(the_repository))\n      \t\tdie(_(\"no sparse-checkout to add to\"));\n      \n      \trepo_read_index(the_repository);\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_reapply(int argc, const ch\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (!repo_settings_get_sparse_checkout(the_repository))\n      \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n      \n      \treapply_opts.cone_mode = -1;\n    +@@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const char **argv,\n    + \tstruct pattern_list pl;\n    + \n    + \t/*\n    +-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n    ++\t * We do not exit early if !sparse_checkout; due to the\n    + \t * ability for users to manually muck things up between\n    + \t *   direct editing of .git/info/sparse-checkout\n    + \t *   running read-tree -m u HEAD or update-index --skip-worktree\n     @@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const char **argv,\n      \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n      \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n      \tpl.use_cone_patterns = 0;\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_apply_sparse_checkout(the_repository, 1);\n    ++\trepo_settings_set_sparse_checkout(the_repository, 1);\n      \n      \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n      \n    @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam\n      \t * the sparse-checkout patterns from the current worktree.\n      \t */\n     -\tif (core_apply_sparse_checkout)\n    -+\tif (repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (repo_settings_get_sparse_checkout(the_repository))\n      \t\tcopy_sparse_checkout(sb_repo.buf);\n      \n      \t/*\n    @@ dir.c: enum pattern_match_result path_matches_pattern_list(\n      int init_sparse_checkout_patterns(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(the_repository))\n    ++\tif (!repo_settings_get_sparse_checkout(the_repository))\n      \t\treturn 1;\n      \tif (istate->sparse_checkout_patterns)\n      \t\treturn 0;\n    @@ repo-settings.c: void prepare_repo_settings(struct repository *r)\n      \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n      \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n      \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n    -+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.core_apply_sparse_checkout, 0);\n    ++\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n      \n      \t/*\n      \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n    @@ repo-settings.c: void repo_settings_reset_shared_repository(struct repository *r\n      \trepo->settings.shared_repository_initialized = 0;\n      }\n     +\n    -+int repo_settings_get_apply_sparse_checkout(struct repository *repo)\n    ++int repo_settings_get_sparse_checkout(struct repository *repo)\n     +{\n    -+\treturn repo->settings.core_apply_sparse_checkout;\n    ++\tprepare_repo_settings(repo);\n    ++\treturn repo->settings.sparse_checkout;\n     +}\n     +\n    -+void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value)\n    ++void repo_settings_set_sparse_checkout(struct repository *repo, int value)\n     +{\n    -+\trepo->settings.core_apply_sparse_checkout = value;\n    ++\tprepare_repo_settings(repo);\n    ++\trepo->settings.sparse_checkout = value;\n     +}\n     \n      ## repo-settings.h ##\n    @@ repo-settings.h: struct repo_settings {\n      \tunsigned long big_file_threshold;\n      \n      \tchar *hooks_path;\n    -+\tint core_apply_sparse_checkout;\n    ++\tint sparse_checkout;\n      };\n      #define REPO_SETTINGS_INIT { \\\n      \t.shared_repository = -1, \\\n    @@ repo-settings.h: int repo_settings_get_shared_repository(struct repository *repo\n      void repo_settings_set_shared_repository(struct repository *repo, int value);\n      void repo_settings_reset_shared_repository(struct repository *repo);\n      \n    -+/* Read, set or reset the value for \"core.sparsecheckout\". */\n    -+int repo_settings_get_apply_sparse_checkout(struct repository *repo);\n    -+void repo_settings_set_apply_sparse_checkout(struct repository *repo, int value);\n    ++/* Read or set the value for \"core.sparseCheckout\". */\n    ++int repo_settings_get_sparse_checkout(struct repository *repo);\n    ++void repo_settings_set_sparse_checkout(struct repository *repo, int value);\n     +\n      #endif /* REPO_SETTINGS_H */\n     \n    @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate\n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n     -\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n    ++\tif (!repo_settings_get_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n      \t\treturn 0;\n      \n      \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n    @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct i\n      void clear_skip_worktree_from_present_files(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout ||\n    -+\tif (!repo_settings_get_apply_sparse_checkout(istate->repo) ||\n    ++\tif (!repo_settings_get_sparse_checkout(istate->repo) ||\n      \t    sparse_expect_files_outside_of_patterns)\n      \t\treturn;\n      \n    @@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpac\n      \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n      \n     -\tif (!core_apply_sparse_checkout || !o->update)\n    -+\tif (!repo_settings_get_apply_sparse_checkout(repo) || !o->update)\n    ++\tif (!repo_settings_get_sparse_checkout(repo) || !o->update)\n      \t\to->skip_sparse_checkout = 1;\n      \tif (!o->skip_sparse_checkout) {\n      \t\tmemset(&pl, 0, sizeof(pl));\n    @@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r,\n      \tint i;\n      \n     -\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n    -+\tif (!repo_settings_get_apply_sparse_checkout(r) || r->index->cache_nr == 0) {\n    ++\tif (!repo_settings_get_sparse_checkout(r) || r->index->cache_nr == 0) {\n      \t\t/*\n      \t\t * Don't compute percentage of checked out files if we\n      \t\t * aren't in a sparse checkout or would get division by 0.\n\n builtin/backfill.c        |  5 +----\n builtin/clone.c           |  2 +-\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 20 ++++++++++----------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           | 13 +++++++++++++\n repo-settings.h           |  5 +++++\n sparse-index.c            |  4 ++--\n unpack-trees.c            |  2 +-\n wt-status.c               |  2 +-\n 15 files changed, 38 insertions(+), 30 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex fa82ad2f6f..e16d116e98 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -139,7 +136,7 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \trepo_config(repo, git_default_config, NULL);\n \n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo_settings_get_sparse_checkout(repo);\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 91b9cd0d16..ba25e58258 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -621,7 +621,7 @@ static int git_sparse_checkout_init(const char *repo)\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 3ce574a605..63342f5e36 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -481,7 +481,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n \t *\tof these submodules are expanded unexpectedly.\n \t *\n-\t * 2. \"core_apply_sparse_checkout\"\n+\t * 2. \"sparse_checkout\"\n \t *\tWhen running `grep` in the superproject, this setting is\n \t *\tpopulated using the superproject's configs. However, once\n \t *\tinitialized, this config is globally accessible and is read by\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..95d24843d9 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -572,7 +572,7 @@ int cmd_mv(int argc,\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n \n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    repo_settings_get_sparse_checkout(the_repository) &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..662858b0a8 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && repo_settings_get_sparse_checkout(the_repository))\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !repo_settings_get_sparse_checkout(the_repository);\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!repo_settings_get_sparse_checkout(the_repository)) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\trepo_settings_set_sparse_checkout(the_repository, 1);\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -935,7 +935,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \tstruct pattern_list pl;\n \n \t/*\n-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n+\t * We do not exit early if !sparse_checkout; due to the\n \t * ability for users to manually muck things up between\n \t *   direct editing of .git/info/sparse-checkout\n \t *   running read-tree -m u HEAD or update-index --skip-worktree\n@@ -961,7 +961,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\trepo_settings_set_sparse_checkout(the_repository, 1);\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 88a36ea9f8..590bec334f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (repo_settings_get_sparse_checkout(the_repository))\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex b18b5617fc..8fd4dd8c81 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex a374972b62..323017e7a5 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1503,7 +1503,7 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tif (!repo_settings_get_sparse_checkout(the_repository))\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex c61d773e7e..a379a9149e 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d98461a06..6a30512f3c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 4129f8fb2b..e11201e25b 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n@@ -227,3 +228,15 @@ void repo_settings_reset_shared_repository(struct repository *repo)\n {\n \trepo->settings.shared_repository_initialized = 0;\n }\n+\n+int repo_settings_get_sparse_checkout(struct repository *repo)\n+{\n+\tprepare_repo_settings(repo);\n+\treturn repo->settings.sparse_checkout;\n+}\n+\n+void repo_settings_set_sparse_checkout(struct repository *repo, int value)\n+{\n+\tprepare_repo_settings(repo);\n+\trepo->settings.sparse_checkout = value;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 2bf24b2597..0d181e3f21 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\n@@ -98,4 +99,8 @@ int repo_settings_get_shared_repository(struct repository *repo);\n void repo_settings_set_shared_repository(struct repository *repo, int value);\n void repo_settings_reset_shared_repository(struct repository *repo);\n \n+/* Read or set the value for \"core.sparseCheckout\". */\n+int repo_settings_get_sparse_checkout(struct repository *repo);\n+void repo_settings_set_sparse_checkout(struct repository *repo, int value);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..1bedb35001 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!repo_settings_get_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!repo_settings_get_sparse_checkout(istate->repo) ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 471837f032..c8eba27e5f 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo_settings_get_sparse_checkout(repo) || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..004f2945b7 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tif (!repo_settings_get_sparse_checkout(r) || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n\n-- \n2.49.0\n\n"},{"id":"520122","messageId":"xmqqmsaegf91.fsf@gitster.g","threadId":"63571","inReplyTo":"20250611173433.74393-1-ayu.chandekar@gmail.com","subject":"Re: [PATCH v3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-11T21:06:18Z","receivedAt":"2025-06-11T21:06:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> The setting \"core.sparsecheckout\" is stored in the global\n> `core_apply_sparse_checkout` and is populated in config.c. Refactor the\n> code to store it in the variable `sparse_checkout` in the struct\n> `repo_settings`. Also, create functions to set and get the value of the\n> setting and update all the occurrences.\n>\n> This also allows us to remove the definition `#define\n> USE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n>\n> This change is part of an ongoing effort to eliminate global variables,\n> improve modularity and help libify the codebase.\n>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\n> Signed-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n> ---\n\nIt may make sense to move the sparse-checkout bit from the\nprocess-wide global to per-repository settings.  One advantage of\nhaving it at the global level is that the code that does not require\nto be in a repository can refer to it, but the nature of this variable\nrequires a repository to make sense anyway, so that advantage does\nnot apply to it.\n\nBut looking at members of repo.settings, among 25+ of them, there\nare only a handful of variables with getter-setter pair, and this\npatch seems to add yet another for a simple boolean.  Among existing\nsetters and getters, prevailing pattern seem to be\n\n\t/* getter */\n\tif (!repo->settings.foo)\n\t\trepo_cfg_ulong(repo, \"core.foo\", &repo->settings.foo, FOO_DEFAULT);\n\treturn repo->settings.foo;\n\n\t/* setter */\n\trepo->settings.foo = value;\n\nbut there are more involved ones.\n\nThis new one adopts the most expensive pattern from\nget_warn_ambiguous_refs() where prepare_repo_settings() is used, as\nif it fears to be fed a repo instance that hasn't been prepared yet,\nand it even does so for its setter, which I think is probably a\nmistake.\n\nAnd there are tons of members in repo-settings that are initialized\nin prepare_repo_settings() (perhaps reading from the configuration\nfile or assigned their default values) and without having an\nexplicit setter/getter pair.  If the code paths that depends on the\nvalue of these members are functioning correctly (and they should,\ngiven how widely Git is used these days and not having heard about\nbugs coming from these variables), would not it mean that in the\nprogram start up sequence, prepare_repo_settings() is called early\nenough so that all the code paths that care about these repository\nsettings values do not have to worry about having a getter setter\npair at all?\n\nWhat is it so special about sparse-checkout bit that cannot be using\nthe same \"initialize in prepare_repo_settings() and access it\ndirectly thereafter\" model, or \"ah, do you need to know about this\nbit?  Let me see if I already have figured it out, and otherwise let\nme read from the configuration, and give it back to you\" model?\n\nMy gut feeling, if I have to choose between \"lazy loading\" and\n\"popluate in prepare_repo_settings() and then access the member\ndirectly thereafter\" for this variable, I may pick the latter for\nthis particular variable.\n\n\n"},{"id":"520124","messageId":"xmqqbjquge0c.fsf@gitster.g","threadId":"63571","inReplyTo":"xmqqmsaegf91.fsf@gitster.g","subject":"Re: [PATCH v3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-11T21:33:07Z","receivedAt":"2025-06-11T21:33:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> My gut feeling, if I have to choose between \"lazy loading\" and\n> \"popluate in prepare_repo_settings() and then access the member\n> directly thereafter\" for this variable, I may pick the latter for\n> this particular variable.\n\nI left the reason behind this choice unsaid, but let's spell it out.\n\nOriginally, this was read in git_config(git_default_config) into a\nglobal, and that is probably because almost everybody that touches\nthe working tree files needs to know about it.  So populating it in\nprepare_repo_settings() for everybody, even though the calling code\npath does not even need it, would be OK---they were paying the cost\nto read it when they read the default configuration variables.\n\nIt seems Patrick earlier made a confused comment on the two models\nthat may need a bit clarifying.\n\nHere are the rules to follow.\n\n - \"lazy loading\" is not wrong. Initialize the member to an\n   \"uninitialized\" state, never touch the member in\n   prepare_repo_settings(), and have its getter check for the\n   \"uninitialized\" state to lazily load it, or have its setter do\n   its thing.  prepare_repo_settings() should not even be aware of\n   the member, if we are going to give the member a getter/setter\n   pair.\n\n - \"Without getter/setter\" is not wrong, either.  Load the member in\n   prepare_repo_settings(), which will turn into a no-op once it is\n   called to a repo instance.  Use the member directly afterwards.\n\nYou cannot mix and match.  If the variable is rarely used, you'd\nwant to catch the initial access and lazily load it, hence you are\nrequired to have a getter/setter pair and lazily populate the member\nin your getter.  If your variable is very commonly used, load it\nonce in prepare_repo_settings(), and because you are not going to do\nanything special upon the first access, there is no need to have a\ngetter/setter pair.\n\n\n"},{"id":"520207","messageId":"CAE7as+aMtOvniTpNhTN083_7fMY=b-HR9R4HsqWSCBtv+w_+7w@mail.gmail.com","threadId":"63571","inReplyTo":"xmqqbjquge0c.fsf@gitster.g","subject":"Re: [PATCH v3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-13T06:57:22Z","receivedAt":"2025-06-13T06:57:34Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Thu, Jun 12, 2025 at 3:03 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > My gut feeling, if I have to choose between \"lazy loading\" and\n> > \"popluate in prepare_repo_settings() and then access the member\n> > directly thereafter\" for this variable, I may pick the latter for\n> > this particular variable.\n>\n> I left the reason behind this choice unsaid, but let's spell it out.\n>\n> Originally, this was read in git_config(git_default_config) into a\n> global, and that is probably because almost everybody that touches\n> the working tree files needs to know about it.  So populating it in\n> prepare_repo_settings() for everybody, even though the calling code\n> path does not even need it, would be OK---they were paying the cost\n> to read it when they read the default configuration variables.\n>\n> It seems Patrick earlier made a confused comment on the two models\n> that may need a bit clarifying.\n>\n> Here are the rules to follow.\n>\n>  - \"lazy loading\" is not wrong. Initialize the member to an\n>    \"uninitialized\" state, never touch the member in\n>    prepare_repo_settings(), and have its getter check for the\n>    \"uninitialized\" state to lazily load it, or have its setter do\n>    its thing.  prepare_repo_settings() should not even be aware of\n>    the member, if we are going to give the member a getter/setter\n>    pair.\n>\n>  - \"Without getter/setter\" is not wrong, either.  Load the member in\n>    prepare_repo_settings(), which will turn into a no-op once it is\n>    called to a repo instance.  Use the member directly afterwards.\n>\n> You cannot mix and match.  If the variable is rarely used, you'd\n> want to catch the initial access and lazily load it, hence you are\n> required to have a getter/setter pair and lazily populate the member\n> in your getter.  If your variable is very commonly used, load it\n> once in prepare_repo_settings(), and because you are not going to do\n> anything special upon the first access, there is no need to have a\n> getter/setter pair.\n>\n>\n\nOh, now I understand it. I will keep this in mind when working on\nthese settings.\nI will send a new version of this patch soon.\n\nThanks a lot, this helped clarify things.\n"},{"id":"520313","messageId":"cover.1750157825.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"[GSOC PATCH v4 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-17T12:06:33Z","receivedAt":"2025-06-17T12:07:39Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"This patch series aims to remove global variables related to sparse-checkout from the global scope and to remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n\nIt contains three patches:\n\n1 - Remove the global variable 'core_apply_sparse_checkout' and move its setting to the 'struct repo_settings'. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"builtin/backfill.c\".\n\n2 - Remove the global variable 'core_sparse_checkout_cone' and move its setting to the 'struct repo_settings'.\n\n3 - Remove the global variable 'sparse_expect_files_outside_of_patterns` and localize it in the function which calls it. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"sparse-index.c\"\n\nAs Junio suggested while reviewing v3 patch, I removed the getter and setter functions for the 'core.sparsecheckout' settings. After making this change, I realized the other sparse-checkout-related global variables could be cleaned up as well, leading to the addition of two new patches in this series.\n\nAyush Chandekar (3):\n  environment: move access to \"core.sparsecheckout\" into\n    repo_settings\n  environment: move access to \"core.sparsecheckoutcone\" into\n    repo_settings\n  environment: remove the global variable\n    'sparse_expect_files_outside_of_patterns'\n\n builtin/backfill.c        |  7 ++----\n builtin/clone.c           |  2 +-\n builtin/grep.c            |  4 ++--\n builtin/mv.c              |  4 ++--\n builtin/sparse-checkout.c | 48 +++++++++++++++++++--------------------\n builtin/worktree.c        |  2 +-\n config.c                  | 24 --------------------\n dir.c                     |  4 ++--\n environment.c             |  3 ---\n environment.h             |  4 ----\n repo-settings.c           |  2 ++\n repo-settings.h           |  3 +++\n sparse-index.c            |  8 ++++---\n unpack-trees.c            |  2 +-\n wt-status.c               |  2 +-\n 15 files changed, 46 insertions(+), 73 deletions(-)\n\n-- \n\nSummary of the range-diff:\n* Removed the getter and setter functions for the core.sparseCheckout setting. Instead, it is now initialized once in 'prepare_repo_settings()' and accessed directly, since it is commonly used.\n* Added two new commits to eliminate the global variables 'core_sparse_checkout_cone' and 'sparse_expect_files_outside_of_patterns'.\n\nRange-diff vs v3:\n 1:  c49dcde03b ! 30:  e221c68ab5 environment: move access to \"core.sparsecheckout\" into repo_settings\n    @@ Commit message\n         The setting \"core.sparsecheckout\" is stored in the global\n         `core_apply_sparse_checkout` and is populated in config.c. Refactor the\n         code to store it in the variable `sparse_checkout` in the struct\n    -    `repo_settings`. Also, create functions to set and get the value of the\n    -    setting and update all the occurrences.\n    +    `repo_settings`.\n    +    It's fine not to lazily load it from the config, as the variable\n    +    is used quite commonly.\n     \n         This also allows us to remove the definition `#define\n         USE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n    @@ builtin/backfill.c\n      #include \"git-compat-util.h\"\n      #include \"config.h\"\n     @@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n    - \trepo_config(repo, git_default_config, NULL);\n    + \t\t\t     0);\n      \n    + \trepo_config(repo, git_default_config, NULL);\n    +-\n    ++\tprepare_repo_settings(repo);\n      \tif (ctx.sparse < 0)\n     -\t\tctx.sparse = core_apply_sparse_checkout;\n    -+\t\tctx.sparse = repo_settings_get_sparse_checkout(repo);\n    ++\t\tctx.sparse = repo->settings.sparse_checkout;\n      \n      \tresult = do_backfill(&ctx);\n      \tbackfill_context_clear(&ctx);\n    @@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)\n      \t * for the later checkout to use the sparse-checkout file.\n      \t */\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_sparse_checkout(the_repository, 1);\n    ++\tthe_repository->settings.sparse_checkout = 1;\n      \n      \tcmd.git_cmd = 1;\n      \tif (run_command(&cmd)) {\n    @@ builtin/mv.c: int cmd_mv(int argc,\n      \n      \t\tif (ignore_sparse &&\n     -\t\t    core_apply_sparse_checkout &&\n    -+\t\t    repo_settings_get_sparse_checkout(the_repository) &&\n    ++\t\t    the_repository->settings.sparse_checkout &&\n      \t\t    core_sparse_checkout_cone) {\n      \t\t\t/*\n      \t\t\t * NEEDSWORK: we are *not* paying attention to\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_list(int argc, const char\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (!the_repository->settings.sparse_checkout)\n      \t\tdie(_(\"this worktree is not sparse\"));\n      \n      \targc = parse_options(argc, argv, prefix,\n    @@ builtin/sparse-checkout.c: static int set_config(enum sparse_checkout_mode mode)\n      static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n      \t/* If not specified, use previous definition of cone mode */\n     -\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n    -+\tif (*cone_mode == -1 && repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n      \t\t*cone_mode = core_sparse_checkout_cone;\n      \n      \t/* Set cone/non-cone mode appropriately */\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_sparse_checkout(the_repository, 1);\n    ++\tthe_repository->settings.sparse_checkout = 1;\n      \tif (*cone_mode == 1 || *cone_mode == -1) {\n      \t\tcore_sparse_checkout_cone = 1;\n      \t\treturn MODE_CONE_PATTERNS;\n    @@ builtin/sparse-checkout.c: static int update_modes(int *cone_mode, int *sparse_i\n      \n      \t/* Determine if we need to record the mode; ensure sparse checkout on */\n     -\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n    -+\trecord_mode = (*cone_mode != -1) || !repo_settings_get_sparse_checkout(the_repository);\n    ++\trecord_mode = (*cone_mode != -1) || !the_repository->settings.sparse_checkout;\n      \n      \tmode = update_cone_mode(cone_mode);\n      \tif (record_mode && set_config(mode))\n    @@ builtin/sparse-checkout.c: static int modify_pattern_list(struct strvec *args, i\n      \t}\n      \n     -\tif (!core_apply_sparse_checkout) {\n    -+\tif (!repo_settings_get_sparse_checkout(the_repository)) {\n    ++\tif (!the_repository->settings.sparse_checkout) {\n      \t\tset_config(MODE_ALL_PATTERNS);\n     -\t\tcore_apply_sparse_checkout = 1;\n    -+\t\trepo_settings_set_sparse_checkout(the_repository, 1);\n    ++\t\tthe_repository->settings.sparse_checkout = 1;\n      \t\tchanged_config = 1;\n      \t}\n      \n    @@ builtin/sparse-checkout.c: static int sparse_checkout_add(int argc, const char *\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (!the_repository->settings.sparse_checkout)\n      \t\tdie(_(\"no sparse-checkout to add to\"));\n      \n      \trepo_read_index(the_repository);\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_reapply(int argc, const ch\n      \n      \tsetup_work_tree();\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (!the_repository->settings.sparse_checkout)\n      \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n      \n      \treapply_opts.cone_mode = -1;\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch\n      \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n      \tpl.use_cone_patterns = 0;\n     -\tcore_apply_sparse_checkout = 1;\n    -+\trepo_settings_set_sparse_checkout(the_repository, 1);\n    ++\tthe_repository->settings.sparse_checkout = 1;\n      \n      \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n      \n    @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam\n      \t * the sparse-checkout patterns from the current worktree.\n      \t */\n     -\tif (core_apply_sparse_checkout)\n    -+\tif (repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (the_repository->settings.sparse_checkout)\n      \t\tcopy_sparse_checkout(sb_repo.buf);\n      \n      \t/*\n    @@ dir.c: enum pattern_match_result path_matches_pattern_list(\n      int init_sparse_checkout_patterns(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout)\n    -+\tif (!repo_settings_get_sparse_checkout(the_repository))\n    ++\tif (!istate->repo->settings.sparse_checkout)\n      \t\treturn 1;\n      \tif (istate->sparse_checkout_patterns)\n      \t\treturn 0;\n    @@ repo-settings.c: void prepare_repo_settings(struct repository *r)\n      \n      \t/*\n      \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n    -@@ repo-settings.c: void repo_settings_reset_shared_repository(struct repository *repo)\n    - {\n    - \trepo->settings.shared_repository_initialized = 0;\n    - }\n    -+\n    -+int repo_settings_get_sparse_checkout(struct repository *repo)\n    -+{\n    -+\tprepare_repo_settings(repo);\n    -+\treturn repo->settings.sparse_checkout;\n    -+}\n    -+\n    -+void repo_settings_set_sparse_checkout(struct repository *repo, int value)\n    -+{\n    -+\tprepare_repo_settings(repo);\n    -+\trepo->settings.sparse_checkout = value;\n    -+}\n     \n      ## repo-settings.h ##\n     @@ repo-settings.h: struct repo_settings {\n    @@ repo-settings.h: struct repo_settings {\n      };\n      #define REPO_SETTINGS_INIT { \\\n      \t.shared_repository = -1, \\\n    -@@ repo-settings.h: int repo_settings_get_shared_repository(struct repository *repo);\n    - void repo_settings_set_shared_repository(struct repository *repo, int value);\n    - void repo_settings_reset_shared_repository(struct repository *repo);\n    - \n    -+/* Read or set the value for \"core.sparseCheckout\". */\n    -+int repo_settings_get_sparse_checkout(struct repository *repo);\n    -+void repo_settings_set_sparse_checkout(struct repository *repo, int value);\n    -+\n    - #endif /* REPO_SETTINGS_H */\n     \n      ## sparse-index.c ##\n     @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate)\n    @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate\n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n     -\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n    -+\tif (!repo_settings_get_sparse_checkout(istate->repo) || !core_sparse_checkout_cone)\n    ++\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n      \t\treturn 0;\n      \n      \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n    @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct i\n      void clear_skip_worktree_from_present_files(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout ||\n    -+\tif (!repo_settings_get_sparse_checkout(istate->repo) ||\n    ++\tif (!istate->repo->settings.sparse_checkout ||\n      \t    sparse_expect_files_outside_of_patterns)\n      \t\treturn;\n      \n    @@ unpack-trees.c: int unpack_trees(unsigned len, struct tree_desc *t, struct unpac\n      \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n      \n     -\tif (!core_apply_sparse_checkout || !o->update)\n    -+\tif (!repo_settings_get_sparse_checkout(repo) || !o->update)\n    ++\tif (!repo->settings.sparse_checkout || !o->update)\n      \t\to->skip_sparse_checkout = 1;\n      \tif (!o->skip_sparse_checkout) {\n      \t\tmemset(&pl, 0, sizeof(pl));\n    @@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r,\n      \tint i;\n      \n     -\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n    -+\tif (!repo_settings_get_sparse_checkout(r) || r->index->cache_nr == 0) {\n    ++\tif (!r->settings.sparse_checkout || r->index->cache_nr == 0) {\n      \t\t/*\n      \t\t * Don't compute percentage of checked out files if we\n      \t\t * aren't in a sparse checkout or would get division by 0.\n -:  ---------- > 31:  9a63884341 environment: move access to \"core.sparsecheckoutcone\" into repo_settings\n -:  ---------- > 32:  a9e1e23685 environment: remove the global variable 'sparse_expect_files_outside_of_patterns'\n\n\n2.49.0\n\n"},{"id":"520314","messageId":"e221c68ab52e995adbb175dc4a09f6c3dfeaf7c8.1750157825.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1750157825.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v4 1/3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-17T12:06:34Z","receivedAt":"2025-06-17T12:07:50Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout` in the struct\n`repo_settings`.\nIt's fine not to lazily load it from the config, as the variable\nis used quite commonly.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/backfill.c        |  7 ++-----\n builtin/clone.c           |  2 +-\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 20 ++++++++++----------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  1 +\n sparse-index.c            |  4 ++--\n unpack-trees.c            |  2 +-\n wt-status.c               |  2 +-\n 15 files changed, 23 insertions(+), 31 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex fa82ad2f6f..bf9e56bff3 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -137,9 +134,9 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \t\t\t     0);\n \n \trepo_config(repo, git_default_config, NULL);\n-\n+\tprepare_repo_settings(repo);\n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo->settings.sparse_checkout;\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 91b9cd0d16..1bc9c1bada 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -621,7 +621,7 @@ static int git_sparse_checkout_init(const char *repo)\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 3ce574a605..63342f5e36 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -481,7 +481,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n \t *\tof these submodules are expanded unexpectedly.\n \t *\n-\t * 2. \"core_apply_sparse_checkout\"\n+\t * 2. \"sparse_checkout\"\n \t *\tWhen running `grep` in the superproject, this setting is\n \t *\tpopulated using the superproject's configs. However, once\n \t *\tinitialized, this config is globally accessible and is read by\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..1e9f4d3eba 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -572,7 +572,7 @@ int cmd_mv(int argc,\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n \n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    the_repository->settings.sparse_checkout &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..869d574a03 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !the_repository->settings.sparse_checkout;\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!the_repository->settings.sparse_checkout) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\tthe_repository->settings.sparse_checkout = 1;\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -935,7 +935,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \tstruct pattern_list pl;\n \n \t/*\n-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n+\t * We do not exit early if !sparse_checkout; due to the\n \t * ability for users to manually muck things up between\n \t *   direct editing of .git/info/sparse-checkout\n \t *   running read-tree -m u HEAD or update-index --skip-worktree\n@@ -961,7 +961,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 88a36ea9f8..92e1c92afc 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (the_repository->settings.sparse_checkout)\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex b18b5617fc..8fd4dd8c81 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex a374972b62..8f0f7ca8a4 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1503,7 +1503,7 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tif (!istate->repo->settings.sparse_checkout)\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex c61d773e7e..a379a9149e 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d98461a06..6a30512f3c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 4129f8fb2b..9270cca561 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 2bf24b2597..9caa7c57a3 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..2428b20634 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!istate->repo->settings.sparse_checkout ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 471837f032..02e32c4ba1 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo->settings.sparse_checkout || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..ec2be98194 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,7 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tif (!r->settings.sparse_checkout || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n-- \n2.49.0\n\n"},{"id":"520315","messageId":"9a638843411d0542e240ea0dd9537f388523fb3c.1750157825.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1750157825.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v4 2/3] environment: move access to \"core.sparsecheckoutcone\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-17T12:06:35Z","receivedAt":"2025-06-17T12:08:00Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckoutcone\" is stored in the global\n`core_sparse_checkout_cone` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout_cone` in the struct\n`repo_settings`.\nIt's fine not to lazily load it from the config, as the variable\nis used quite commonly.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 28 ++++++++++++++--------------\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  2 ++\n sparse-index.c            |  2 +-\n 10 files changed, 21 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 63342f5e36..94d6245b85 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -491,7 +491,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\tdictate the behavior for the submodule, making it \"forget\" its\n \t *\tsparse-checkout state.\n \t *\n-\t * 3. \"core_sparse_checkout_cone\"\n+\t * 3. \"sparse_checkout_cone\"\n \t *\tditto.\n \t *\n \t * Note that this list is not exhaustive.\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 1e9f4d3eba..833fa761dd 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -573,7 +573,7 @@ int cmd_mv(int argc,\n \n \t\tif (ignore_sparse &&\n \t\t    the_repository->settings.sparse_checkout &&\n-\t\t    core_sparse_checkout_cone) {\n+\t\t    the_repository->settings.sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\n \t\t\t * \"out-to-out\" move (<source> is out-of-cone and\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 869d574a03..e65a62f250 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -71,7 +71,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \n \tmemset(&pl, 0, sizeof(pl));\n \n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tsparse_filename = get_sparse_checkout_filename();\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, &pl, NULL, 0);\n@@ -352,7 +352,7 @@ static int write_patterns_and_update(struct pattern_list *pl)\n \tif (!fp)\n \t\tdie_errno(_(\"unable to fdopen %s\"), get_lock_file_path(&lk));\n \n-\tif (core_sparse_checkout_cone)\n+\tif (the_repository->settings.sparse_checkout_cone)\n \t\twrite_cone_to_file(fp, pl);\n \telse\n \t\twrite_patterns_to_file(fp, pl);\n@@ -398,15 +398,15 @@ static int set_config(enum sparse_checkout_mode mode)\n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n \tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n-\t\t*cone_mode = core_sparse_checkout_cone;\n+\t\t*cone_mode = the_repository->settings.sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n \tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n-\t\tcore_sparse_checkout_cone = 1;\n+\t\tthe_repository->settings.sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n \t}\n-\tcore_sparse_checkout_cone = 0;\n+\tthe_repository->settings.sparse_checkout_cone = 0;\n \treturn MODE_ALL_PATTERNS;\n }\n \n@@ -572,7 +572,7 @@ static void add_patterns_from_input(struct pattern_list *pl,\n \t\t\t\t    FILE *file)\n {\n \tint i;\n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tstruct strbuf line = STRBUF_INIT;\n \n \t\thashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n@@ -637,7 +637,7 @@ static void add_patterns_cone_mode(int argc, const char **argv,\n \t\t\t\tuse_stdin ? stdin : NULL);\n \n \tmemset(&existing, 0, sizeof(existing));\n-\texisting.use_cone_patterns = core_sparse_checkout_cone;\n+\texisting.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tif (add_patterns_from_file_to_list(sparse_filename, \"\", 0,\n \t\t\t\t\t   &existing, NULL, 0))\n@@ -683,7 +683,7 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \n \tswitch (m) {\n \tcase ADD:\n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tadd_patterns_cone_mode(args->nr, args->v, pl, use_stdin);\n \t\telse\n \t\t\tadd_patterns_literal(args->nr, args->v, pl, use_stdin);\n@@ -719,7 +719,7 @@ static void sanitize_paths(struct strvec *args,\n \tif (!args->nr)\n \t\treturn;\n \n-\tif (prefix && *prefix && core_sparse_checkout_cone) {\n+\tif (prefix && *prefix && the_repository->settings.sparse_checkout_cone) {\n \t\t/*\n \t\t * The args are not pathspecs, so unfortunately we\n \t\t * cannot imitate how cmd_add() uses parse_pathspec().\n@@ -736,10 +736,10 @@ static void sanitize_paths(struct strvec *args,\n \tif (skip_checks)\n \t\treturn;\n \n-\tif (prefix && *prefix && !core_sparse_checkout_cone)\n+\tif (prefix && *prefix && !the_repository->settings.sparse_checkout_cone)\n \t\tdie(_(\"please run from the toplevel directory in non-cone mode\"));\n \n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tfor (i = 0; i < args->nr; i++) {\n \t\t\tif (args->v[i][0] == '/')\n \t\t\t\tdie(_(\"specify directories rather than patterns (no leading slash)\"));\n@@ -761,7 +761,7 @@ static void sanitize_paths(struct strvec *args,\n \t\tif (S_ISSPARSEDIR(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tdie(_(\"'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks\"), args->v[i]);\n \t\telse\n \t\t\twarning(_(\"pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual).\"), args->v[i]);\n@@ -864,7 +864,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,\n \t * non-cone mode, if nothing is specified, manually select just the\n \t * top-level directory (much as 'init' would do).\n \t */\n-\tif (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n+\tif (!the_repository->settings.sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n \t\tfor (int i = 0; i < default_patterns_nr; i++)\n \t\t\tstrvec_push(&patterns, default_patterns[i]);\n \t} else {\n@@ -1042,7 +1042,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *\n \t\tcheck_rules_opts.cone_mode = 1;\n \n \tupdate_cone_mode(&check_rules_opts.cone_mode);\n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tif (check_rules_opts.rules_file) {\n \t\tfp = xfopen(check_rules_opts.rules_file, \"r\");\n \t\tadd_patterns_from_input(&pl, argc, argv, fp);\ndiff --git a/config.c b/config.c\nindex 8fd4dd8c81..707fe0707a 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n-\t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.precomposeunicode\")) {\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex 8f0f7ca8a4..8378996b72 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3459,7 +3459,7 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)\n \tint res;\n \tchar *sparse_filename = get_sparse_checkout_filename();\n \n-\tpl->use_cone_patterns = core_sparse_checkout_cone;\n+\tpl->use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, pl, NULL, 0);\n \n \tfree(sparse_filename);\ndiff --git a/environment.c b/environment.c\nindex a379a9149e..7d46b80711 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\ndiff --git a/environment.h b/environment.h\nindex 6a30512f3c..00a5b332a0 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n enum rebase_setup_type {\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 9270cca561..eebc1f941d 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -82,6 +82,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n \trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n+\trepo_cfg_bool(r, \"core.sparsecheckoutcone\", &r->settings.sparse_checkout_cone, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 9caa7c57a3..443e1399da 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,7 +67,9 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\n \tint sparse_checkout;\n+\tint sparse_checkout_cone;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 2428b20634..444da8a753 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!istate->repo->settings.sparse_checkout || !istate->repo->settings.sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n-- \n2.49.0\n\n"},{"id":"520316","messageId":"a9e1e23685c476b106b3bdb0d37b4ac5dd98ee3a.1750157825.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1750157825.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v4 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-17T12:06:36Z","receivedAt":"2025-06-17T12:08:04Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The global variable 'sparse_expect_files_outside_of_patterns' is used in\na single function named 'clear_skip_worktree_from_present_files()' in\nsparse-index.c. Move its declaration inside that function, removing\nunnecessary global state.\n\nThis also allows us to remove the definition '#define\nUSE_THE_REPOSITORY_VARIABLE' from the file 'sparse-index.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n config.c       | 14 --------------\n environment.c  |  1 -\n environment.h  |  2 --\n sparse-index.c |  4 +++-\n 4 files changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 707fe0707a..d212329799 100644\n--- a/config.c\n+++ b/config.c\n@@ -1636,17 +1636,6 @@ static int git_default_core_config(const char *var, const char *value,\n \treturn platform_core_config(var, value, ctx, cb);\n }\n \n-static int git_default_sparse_config(const char *var, const char *value)\n-{\n-\tif (!strcmp(var, \"sparse.expectfilesoutsideofpatterns\")) {\n-\t\tsparse_expect_files_outside_of_patterns = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n-\t/* Add other config variables here and to Documentation/config/sparse.adoc. */\n-\treturn 0;\n-}\n-\n static int git_default_i18n_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"i18n.commitencoding\")) {\n@@ -1808,9 +1797,6 @@ int git_default_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (starts_with(var, \"sparse.\"))\n-\t\treturn git_default_sparse_config(var, value);\n-\n \t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 7d46b80711..d51e0a14aa 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\ndiff --git a/environment.h b/environment.h\nindex 00a5b332a0..5121a28d3f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,8 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int sparse_expect_files_outside_of_patterns;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 444da8a753..5d87fc65c0 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -668,6 +667,9 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n+\tint sparse_expect_files_outside_of_patterns = 0;\n+\trepo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\", \n+\t\t&sparse_expect_files_outside_of_patterns);\n \tif (!istate->repo->settings.sparse_checkout ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n-- \n2.49.0\n\n"},{"id":"520321","messageId":"xmqqzfe6uyyh.fsf@gitster.g","threadId":"63571","inReplyTo":"e221c68ab52e995adbb175dc4a09f6c3dfeaf7c8.1750157825.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v4 1/3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-17T16:15:02Z","receivedAt":"2025-06-17T16:15:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> diff --git a/builtin/backfill.c b/builtin/backfill.c\n> index fa82ad2f6f..bf9e56bff3 100644\n> --- a/builtin/backfill.c\n> +++ b/builtin/backfill.c\n> @@ -1,6 +1,3 @@\n> -/* We need this macro to access core_apply_sparse_checkout */\n> -#define USE_THE_REPOSITORY_VARIABLE\n> -\n>  #include \"builtin.h\"\n>  #include \"git-compat-util.h\"\n>  #include \"config.h\"\n> @@ -137,9 +134,9 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n>  \t\t\t     0);\n>  \n>  \trepo_config(repo, git_default_config, NULL);\n> -\n> +\tprepare_repo_settings(repo);\n\nAt this point, because show_usage_with_options_if_asked() has\nalready been called and returned, we know repo is not NULL, since\nthe only time git.c:run_builtin() calls us with repo==NULL is when\nthere is \"-h\" with nothing else on the command line and that causes\nshow_usage_with_options_if_asked() to emit usage and exit.\n\nOK.\n\n>  \tif (ctx.sparse < 0)\n> -\t\tctx.sparse = core_apply_sparse_checkout;\n> +\t\tctx.sparse = repo->settings.sparse_checkout;\n\nThis is safe for the same reason.\n\n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index 91b9cd0d16..1bc9c1bada 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -621,7 +621,7 @@ static int git_sparse_checkout_init(const char *repo)\n>  \t * We must apply the setting in the current process\n>  \t * for the later checkout to use the sparse-checkout file.\n>  \t */\n> -\tcore_apply_sparse_checkout = 1;\n> +\tthe_repository->settings.sparse_checkout = 1;\n\nHave anybody called prepare_repo_settings() on the repository yet?\nWhat will prevent another call to the function from overwriting this\nvalue later?\n\n> diff --git a/builtin/mv.c b/builtin/mv.c\n> index 07548fe96a..1e9f4d3eba 100644\n> --- a/builtin/mv.c\n> +++ b/builtin/mv.c\n> @@ -572,7 +572,7 @@ int cmd_mv(int argc,\n>  \t\trename_index_entry_at(the_repository->index, pos, dst);\n>  \n>  \t\tif (ignore_sparse &&\n> -\t\t    core_apply_sparse_checkout &&\n> +\t\t    the_repository->settings.sparse_checkout &&\n>  \t\t    core_sparse_checkout_cone) {\n\nHave anybody called prepare_repo_settings() on the repository yet\nbefore the control comes here?\n\nThe guarantee of the original code being correct relied on the fact\nthat git_default_core_config() was called way before these places so\nthe global variable has been already initialized correctly.\n\nThe .sparse_checkout member is read in prepare_repo_settings() in\nyour new code; in order to give the correctness guarantee, there\nneeds to be some way to make sure prepare_repo_settings() has\nalready been called on the_repository before these places.\n\nThe same comment applies to all the code paths that access\nthe_repository->settings.sparse_checkout member instead of the\nglobal.  As the source of their correctness guarantee is quite\ndifferent, a mechanical replacement from global to a struct member\nis not sufficient.\n\n"},{"id":"520323","messageId":"xmqqplf2uy9w.fsf@gitster.g","threadId":"63571","inReplyTo":"9a638843411d0542e240ea0dd9537f388523fb3c.1750157825.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v4 2/3] environment: move access to \"core.sparsecheckoutcone\" into repo_settings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-17T16:29:47Z","receivedAt":"2025-06-17T16:29:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> The setting \"core.sparsecheckoutcone\" is stored in the global\n> `core_sparse_checkout_cone` and is populated in config.c. Refactor the\n> code to store it in the variable `sparse_checkout_cone` in the struct\n> `repo_settings`.\n> It's fine not to lazily load it from the config, as the variable\n> is used quite commonly.\n>\n> This change is part of an ongoing effort to eliminate global variables,\n> improve modularity and help libify the codebase.\n>\n> Mentored-by: Christian Couder <christian.couder@gmail.com>\n> Mentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\n> Signed-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n> ---\n\nI think \"the correctness guarantee comes from a different place now.\nHow are we making sure that these accesses are correct?\" comment\napplies equally here.\n\n>  builtin/grep.c            |  2 +-\n>  builtin/mv.c              |  2 +-\n\nLooking at the output from\n\n    $ git grep -n -e prepare_repo_settings \\*.c\n\nthere are many builtin/*.c that makes a call to the function on\nthe_repository fairly early in its start-up sequence.  Unlike many\nothers these two do not seem to have any.\n\n>  builtin/sparse-checkout.c | 28 ++++++++++++++--------------\n\nThis one does, immediately after calling git_config(), so it should\nbe fairly safe.\n\n>  dir.c                     |  2 +-\n>  sparse-index.c            |  2 +-\n\nThese two also need correctness guarantee.\n\nYou'd need to make sure any potential caller of the helper functions\nhave called prepare_repo_settings().  Those who wrote an access to\nthe global variable in the original would already have made sure\nthat the callers would have already read the configuration file, but\nwith the new code, that is no longer a guarantee for correctness.\n\n"},{"id":"520324","messageId":"xmqqldpquy8g.fsf@gitster.g","threadId":"63571","inReplyTo":"a9e1e23685c476b106b3bdb0d37b4ac5dd98ee3a.1750157825.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v4 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-17T16:30:39Z","receivedAt":"2025-06-17T16:30:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> diff --git a/sparse-index.c b/sparse-index.c\n> index 444da8a753..5d87fc65c0 100644\n> --- a/sparse-index.c\n> +++ b/sparse-index.c\n> @@ -1,4 +1,3 @@\n> -#define USE_THE_REPOSITORY_VARIABLE\n>  #define DISABLE_SIGN_COMPARE_WARNINGS\n>  \n>  #include \"git-compat-util.h\"\n> @@ -668,6 +667,9 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n>  \n>  void clear_skip_worktree_from_present_files(struct index_state *istate)\n>  {\n> +\tint sparse_expect_files_outside_of_patterns = 0;\n> +\trepo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\", \n\nThere is a trailing whitespace here.\n\n> +\t\t&sparse_expect_files_outside_of_patterns);\n\n"},{"id":"520965","messageId":"cover.1751309770.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"[GSOC PATCH v5 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-30T19:27:45Z","receivedAt":"2025-06-30T19:28:51Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"This patch series aims to remove global variables related to sparse-checkout from the global scope and to remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n\nIt contains three patches:\n\n1 - Remove the global variable 'core_apply_sparse_checkout' and move its setting to the 'struct repo_settings'. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"builtin/backfill.c\". \n\n2 - Remove the global variable 'core_sparse_checkout_cone' and move its setting to the 'struct repo_settings'.\n\n3 - Remove the global variable 'sparse_expect_files_outside_of_patterns` and localize it in the function which calls it. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"sparse-index.c\"\n\nThanks a lot to Christian for mentoring, and to Junio, Patrick and Ben for reviewing.\n\nAyush Chandekar (2):\n  environment: move access to \"core.sparsecheckoutcone\" into\n    repo_settings\n  environment: remove the global variable\n    'sparse_expect_files_outside_of_patterns'\n  environment: move access to \"core.sparsecheckout\" into repo_settings\n\n builtin/backfill.c        |  7 ++----\n builtin/clone.c           |  3 ++-\n builtin/grep.c            |  4 ++--\n builtin/mv.c              |  6 ++---\n builtin/sparse-checkout.c | 49 +++++++++++++++++++--------------------\n builtin/worktree.c        |  2 +-\n config.c                  | 24 -------------------\n dir.c                     |  5 ++--\n environment.c             |  3 ---\n environment.h             |  4 ----\n repo-settings.c           |  2 ++\n repo-settings.h           |  3 +++\n sparse-index.c            | 10 ++++----\n unpack-trees.c            |  3 ++-\n wt-status.c               |  3 ++-\n 15 files changed, 52 insertions(+), 76 deletions(-)\n\n-- \n\nSummary of range-diff:\n* Ensure that `prepare_repo_settings()` is called in all code paths before accessing `settings.sparse_checkout` and `settings.sparse_checkout_cone`.\n\nRange-diff with v4:\n1:  e221c68ab5 ! 1:  ba9929d128 environment: move access to \"core.sparsecheckout\" into repo_settings\n    @@ Commit message\n         `core_apply_sparse_checkout` and is populated in config.c. Refactor the\n         code to store it in the variable `sparse_checkout` in the struct\n         `repo_settings`.\n    -    It's fine not to lazily load it from the config, as the variable\n    -    is used quite commonly.\n    +\n    +    Call `prepare_repo_settings()` where necessary to ensure the `struct\n    +    repo_settings` is initialized before use:\n    +    - In \"builtin/backfill.c\", \"builtin/mv.c\" and \"builtin/clone.c\" call\n    +      `prepare_repo_settings()` since their respective `cmd_*()` functions\n    +      did not call it earlier.\n    +    - In \"dir.c\", the function using 'settings.sparse_checkout' is invoked\n    +      in multiple files that do not call `prepare_repo_settings()`, hence\n    +      add a call directly to that function.\n    +    - In \"sparse-checkout.c\", add a call to `prepare_repo_settings()` inside\n    +      `is_sparse_index_allowed()`, as it is used widely and relies on the\n    +      setting.\n    +    - In \"wt-status.c\", call `prepare_repo_settings()` before accessing\n    +      the setting because the function using it is commonly used.\n    +\n    +    Avoid reduntant calls to `prepare_repo_settings()` where it is already\n    +    present:\n    +    - In \"builtin/worktree.c\", it is already invoked in `cmd_worktree()`\n    +      before the setting is accessed.\n    +    - In \"unpack-tress.c\", the function accessing the setting already calls\n    +      it.\n     \n         This also allows us to remove the definition `#define\n         USE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n    @@ builtin/backfill.c: int cmd_backfill(int argc, const char **argv, const char *pr\n     \n      ## builtin/clone.c ##\n     @@ builtin/clone.c: static int git_sparse_checkout_init(const char *repo)\n    + \tint result = 0;\n    + \tstrvec_pushl(&cmd.args, \"-C\", repo, \"sparse-checkout\", \"set\", NULL);\n    + \n    ++\tprepare_repo_settings(the_repository);\n    + \t/*\n      \t * We must apply the setting in the current process\n      \t * for the later checkout to use the sparse-checkout file.\n      \t */\n    @@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,\n      \t *\tof these submodules are expanded unexpectedly.\n      \t *\n     -\t * 2. \"core_apply_sparse_checkout\"\n    -+\t * 2. \"sparse_checkout\"\n    ++\t * 2. \"settings.sparse_checkout\"\n      \t *\tWhen running `grep` in the superproject, this setting is\n      \t *\tpopulated using the superproject's configs. However, once\n      \t *\tinitialized, this config is globally accessible and is read by\n     \n      ## builtin/mv.c ##\n     @@ builtin/mv.c: int cmd_mv(int argc,\n    + \t\t\t\t\t\t       &st,\n    + \t\t\t\t\t\t       0);\n      \t\trename_index_entry_at(the_repository->index, pos, dst);\n    - \n    +-\n    ++\t\tprepare_repo_settings(the_repository);\n      \t\tif (ignore_sparse &&\n     -\t\t    core_apply_sparse_checkout &&\n     +\t\t    the_repository->settings.sparse_checkout &&\n    @@ builtin/sparse-checkout.c: static int sparse_checkout_disable(int argc, const ch\n      \n      \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n      \n    +-\tprepare_repo_settings(the_repository);\n    + \tthe_repository->settings.sparse_index = 0;\n    + \n    + \tif (update_working_directory(&pl))\n     \n      ## builtin/worktree.c ##\n     @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refname,\n    @@ dir.c: enum pattern_match_result path_matches_pattern_list(\n      int init_sparse_checkout_patterns(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout)\n    ++\tprepare_repo_settings(istate->repo);\n     +\tif (!istate->repo->settings.sparse_checkout)\n      \t\treturn 1;\n      \tif (istate->sparse_checkout_patterns)\n    @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate\n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n     -\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n    ++\tprepare_repo_settings(istate->repo);\n     +\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n      \t\treturn 0;\n      \n      \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n    +@@ sparse-index.c: int is_sparse_index_allowed(struct index_state *istate, int flags)\n    + \t\t/*\n    + \t\t * Only convert to sparse if index.sparse is set.\n    + \t\t */\n    +-\t\tprepare_repo_settings(istate->repo);\n    + \t\tif (!istate->repo->settings.sparse_index)\n    + \t\t\treturn 0;\n    + \t}\n     @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n      \n      void clear_skip_worktree_from_present_files(struct index_state *istate)\n    @@ wt-status.c: static void wt_status_check_sparse_checkout(struct repository *r,\n      \tint i;\n      \n     -\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n    ++\tprepare_repo_settings(r);\n     +\tif (!r->settings.sparse_checkout || r->index->cache_nr == 0) {\n      \t\t/*\n      \t\t * Don't compute percentage of checked out files if we\n2:  9a63884341 ! 2:  5a2f61443b environment: move access to \"core.sparsecheckoutcone\" into repo_settings\n    @@ Commit message\n         `core_sparse_checkout_cone` and is populated in config.c. Refactor the\n         code to store it in the variable `sparse_checkout_cone` in the struct\n         `repo_settings`.\n    -    It's fine not to lazily load it from the config, as the variable\n    -    is used quite commonly.\n    +\n    +    Call `prepare_repo_settings()` where necessary to ensure the `struct\n    +    repo_settings` is initialized before use:\n    +    - In \"dir.c\", the function accessing the setting is usually called after\n    +      `prepare_repo_settings()`, except for one code path in\n    +      \"unpack-trees.c\", so add a call there.\n    +\n    +    Avoid redundant calls to `prepare_repo_settings()` where it is already\n    +    present:\n    +    - In \"builtin/mv.c\" and \"builtin/sparse-checkout.c\", it is already\n    +      invoked in their respective `cmd_*()` functions.\n    +    - In \"sparse-index.c\", `prepare_repo_settings` is already called before\n    +      the setting is accessed.\n     \n         This change is part of an ongoing effort to eliminate global variables,\n         improve modularity and help libify the codebase.\n    @@ builtin/grep.c: static int grep_submodule(struct grep_opt *opt,\n      \t *\tsparse-checkout state.\n      \t *\n     -\t * 3. \"core_sparse_checkout_cone\"\n    -+\t * 3. \"sparse_checkout_cone\"\n    ++\t * 3. \"settings.sparse_checkout_cone\"\n      \t *\tditto.\n      \t *\n      \t * Note that this list is not exhaustive.\n     \n      ## builtin/mv.c ##\n     @@ builtin/mv.c: int cmd_mv(int argc,\n    - \n    + \t\tprepare_repo_settings(the_repository);\n      \t\tif (ignore_sparse &&\n      \t\t    the_repository->settings.sparse_checkout &&\n     -\t\t    core_sparse_checkout_cone) {\n    @@ repo-settings.h: struct repo_settings {\n     \n      ## sparse-index.c ##\n     @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate)\n    - \n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n    + \tprepare_repo_settings(istate->repo);\n     -\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n     +\tif (!istate->repo->settings.sparse_checkout || !istate->repo->settings.sparse_checkout_cone)\n      \t\treturn 0;\n      \n      \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n    +\n    + ## unpack-trees.c ##\n    +@@ unpack-trees.c: enum update_sparsity_result update_sparsity(struct unpack_trees_options *o,\n    + \t\tBUG(\"update_sparsity() called wrong\");\n    + \n    + \ttrace_performance_enter();\n    ++\tprepare_repo_settings(the_repository);\n    + \n    + \t/* If we weren't given patterns, use the recorded ones */\n    + \tif (!pl) {\n3:  578c087188 = 3:  45c84a6615 environment: remove the global variable 'sparse_expect_files_outside_of_patterns'\n\n\n2.49.0\n\n"},{"id":"520966","messageId":"ba9929d128c07993c8a83229b3721d12b7455dc6.1751309770.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1751309770.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v5 1/3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-30T19:27:46Z","receivedAt":"2025-06-30T19:28:58Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout` in the struct\n`repo_settings`.\n\nCall `prepare_repo_settings()` where necessary to ensure the `struct\nrepo_settings` is initialized before use:\n- In \"builtin/backfill.c\", \"builtin/mv.c\" and \"builtin/clone.c\" call\n  `prepare_repo_settings()` since their respective `cmd_*()` functions\n  did not call it earlier.\n- In \"dir.c\", the function using 'settings.sparse_checkout' is invoked\n  in multiple files that do not call `prepare_repo_settings()`, hence\n  add a call directly to that function.\n- In \"sparse-checkout.c\", add a call to `prepare_repo_settings()` inside\n  `is_sparse_index_allowed()`, as it is used widely and relies on the\n  setting.\n- In \"wt-status.c\", call `prepare_repo_settings()` before accessing\n  the setting because the function using it is commonly used.\n\nAvoid reduntant calls to `prepare_repo_settings()` where it is already\npresent:\n- In \"builtin/worktree.c\", it is already invoked in `cmd_worktree()`\n  before the setting is accessed.\n- In \"unpack-tress.c\", the function accessing the setting already calls\n  it.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/backfill.c        |  7 ++-----\n builtin/clone.c           |  3 ++-\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  4 ++--\n builtin/sparse-checkout.c | 21 ++++++++++-----------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  3 ++-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  1 +\n sparse-index.c            |  6 +++---\n unpack-trees.c            |  2 +-\n wt-status.c               |  3 ++-\n 15 files changed, 28 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex fa82ad2f6f..bf9e56bff3 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -137,9 +134,9 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \t\t\t     0);\n \n \trepo_config(repo, git_default_config, NULL);\n-\n+\tprepare_repo_settings(repo);\n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo->settings.sparse_checkout;\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 91b9cd0d16..6d70986f3e 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -617,11 +617,12 @@ static int git_sparse_checkout_init(const char *repo)\n \tint result = 0;\n \tstrvec_pushl(&cmd.args, \"-C\", repo, \"sparse-checkout\", \"set\", NULL);\n \n+\tprepare_repo_settings(the_repository);\n \t/*\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 3ce574a605..6111fee60b 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -481,7 +481,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n \t *\tof these submodules are expanded unexpectedly.\n \t *\n-\t * 2. \"core_apply_sparse_checkout\"\n+\t * 2. \"settings.sparse_checkout\"\n \t *\tWhen running `grep` in the superproject, this setting is\n \t *\tpopulated using the superproject's configs. However, once\n \t *\tinitialized, this config is globally accessible and is read by\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..43ed2e3d0a 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -570,9 +570,9 @@ int cmd_mv(int argc,\n \t\t\t\t\t\t       &st,\n \t\t\t\t\t\t       0);\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n-\n+\t\tprepare_repo_settings(the_repository);\n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    the_repository->settings.sparse_checkout &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..8329d29a27 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !the_repository->settings.sparse_checkout;\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!the_repository->settings.sparse_checkout) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\tthe_repository->settings.sparse_checkout = 1;\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -935,7 +935,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \tstruct pattern_list pl;\n \n \t/*\n-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n+\t * We do not exit early if !sparse_checkout; due to the\n \t * ability for users to manually muck things up between\n \t *   direct editing of .git/info/sparse-checkout\n \t *   running read-tree -m u HEAD or update-index --skip-worktree\n@@ -961,11 +961,10 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \n-\tprepare_repo_settings(the_repository);\n \tthe_repository->settings.sparse_index = 0;\n \n \tif (update_working_directory(&pl))\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 88a36ea9f8..92e1c92afc 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (the_repository->settings.sparse_checkout)\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex b18b5617fc..8fd4dd8c81 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex a374972b62..5d1cb7a067 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1503,7 +1503,8 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tprepare_repo_settings(istate->repo);\n+\tif (!istate->repo->settings.sparse_checkout)\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex c61d773e7e..a379a9149e 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d98461a06..6a30512f3c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 4129f8fb2b..9270cca561 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -81,6 +81,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 2bf24b2597..9caa7c57a3 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,6 +67,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..8132c0f2fb 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,8 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tprepare_repo_settings(istate->repo);\n+\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -172,7 +173,6 @@ int is_sparse_index_allowed(struct index_state *istate, int flags)\n \t\t/*\n \t\t * Only convert to sparse if index.sparse is set.\n \t\t */\n-\t\tprepare_repo_settings(istate->repo);\n \t\tif (!istate->repo->settings.sparse_index)\n \t\t\treturn 0;\n \t}\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!istate->repo->settings.sparse_checkout ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 471837f032..02e32c4ba1 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo->settings.sparse_checkout || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..8651134bcb 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,8 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tprepare_repo_settings(r);\n+\tif (!r->settings.sparse_checkout || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n-- \n2.49.0\n\n"},{"id":"520967","messageId":"5a2f61443bda079a2d85190b904473d6fab3fec4.1751309770.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1751309770.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v5 2/3] environment: move access to \"core.sparsecheckoutcone\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-30T19:27:47Z","receivedAt":"2025-06-30T19:29:02Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckoutcone\" is stored in the global\n`core_sparse_checkout_cone` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout_cone` in the struct\n`repo_settings`.\n\nCall `prepare_repo_settings()` where necessary to ensure the `struct\nrepo_settings` is initialized before use:\n- In \"dir.c\", the function accessing the setting is usually called after\n  `prepare_repo_settings()`, except for one code path in\n  \"unpack-trees.c\", so add a call there.\n\nAvoid redundant calls to `prepare_repo_settings()` where it is already\npresent:\n- In \"builtin/mv.c\" and \"builtin/sparse-checkout.c\", it is already\n  invoked in their respective `cmd_*()` functions.\n- In \"sparse-index.c\", `prepare_repo_settings` is already called before\n  the setting is accessed.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 28 ++++++++++++++--------------\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  2 ++\n sparse-index.c            |  2 +-\n unpack-trees.c            |  1 +\n 11 files changed, 22 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 6111fee60b..8971a15ef4 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -491,7 +491,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\tdictate the behavior for the submodule, making it \"forget\" its\n \t *\tsparse-checkout state.\n \t *\n-\t * 3. \"core_sparse_checkout_cone\"\n+\t * 3. \"settings.sparse_checkout_cone\"\n \t *\tditto.\n \t *\n \t * Note that this list is not exhaustive.\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 43ed2e3d0a..2d1326a18f 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -573,7 +573,7 @@ int cmd_mv(int argc,\n \t\tprepare_repo_settings(the_repository);\n \t\tif (ignore_sparse &&\n \t\t    the_repository->settings.sparse_checkout &&\n-\t\t    core_sparse_checkout_cone) {\n+\t\t    the_repository->settings.sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\n \t\t\t * \"out-to-out\" move (<source> is out-of-cone and\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 8329d29a27..8a0ffba9d4 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -71,7 +71,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \n \tmemset(&pl, 0, sizeof(pl));\n \n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tsparse_filename = get_sparse_checkout_filename();\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, &pl, NULL, 0);\n@@ -352,7 +352,7 @@ static int write_patterns_and_update(struct pattern_list *pl)\n \tif (!fp)\n \t\tdie_errno(_(\"unable to fdopen %s\"), get_lock_file_path(&lk));\n \n-\tif (core_sparse_checkout_cone)\n+\tif (the_repository->settings.sparse_checkout_cone)\n \t\twrite_cone_to_file(fp, pl);\n \telse\n \t\twrite_patterns_to_file(fp, pl);\n@@ -398,15 +398,15 @@ static int set_config(enum sparse_checkout_mode mode)\n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n \tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n-\t\t*cone_mode = core_sparse_checkout_cone;\n+\t\t*cone_mode = the_repository->settings.sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n \tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n-\t\tcore_sparse_checkout_cone = 1;\n+\t\tthe_repository->settings.sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n \t}\n-\tcore_sparse_checkout_cone = 0;\n+\tthe_repository->settings.sparse_checkout_cone = 0;\n \treturn MODE_ALL_PATTERNS;\n }\n \n@@ -572,7 +572,7 @@ static void add_patterns_from_input(struct pattern_list *pl,\n \t\t\t\t    FILE *file)\n {\n \tint i;\n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tstruct strbuf line = STRBUF_INIT;\n \n \t\thashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n@@ -637,7 +637,7 @@ static void add_patterns_cone_mode(int argc, const char **argv,\n \t\t\t\tuse_stdin ? stdin : NULL);\n \n \tmemset(&existing, 0, sizeof(existing));\n-\texisting.use_cone_patterns = core_sparse_checkout_cone;\n+\texisting.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tif (add_patterns_from_file_to_list(sparse_filename, \"\", 0,\n \t\t\t\t\t   &existing, NULL, 0))\n@@ -683,7 +683,7 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \n \tswitch (m) {\n \tcase ADD:\n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tadd_patterns_cone_mode(args->nr, args->v, pl, use_stdin);\n \t\telse\n \t\t\tadd_patterns_literal(args->nr, args->v, pl, use_stdin);\n@@ -719,7 +719,7 @@ static void sanitize_paths(struct strvec *args,\n \tif (!args->nr)\n \t\treturn;\n \n-\tif (prefix && *prefix && core_sparse_checkout_cone) {\n+\tif (prefix && *prefix && the_repository->settings.sparse_checkout_cone) {\n \t\t/*\n \t\t * The args are not pathspecs, so unfortunately we\n \t\t * cannot imitate how cmd_add() uses parse_pathspec().\n@@ -736,10 +736,10 @@ static void sanitize_paths(struct strvec *args,\n \tif (skip_checks)\n \t\treturn;\n \n-\tif (prefix && *prefix && !core_sparse_checkout_cone)\n+\tif (prefix && *prefix && !the_repository->settings.sparse_checkout_cone)\n \t\tdie(_(\"please run from the toplevel directory in non-cone mode\"));\n \n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tfor (i = 0; i < args->nr; i++) {\n \t\t\tif (args->v[i][0] == '/')\n \t\t\t\tdie(_(\"specify directories rather than patterns (no leading slash)\"));\n@@ -761,7 +761,7 @@ static void sanitize_paths(struct strvec *args,\n \t\tif (S_ISSPARSEDIR(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tdie(_(\"'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks\"), args->v[i]);\n \t\telse\n \t\t\twarning(_(\"pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual).\"), args->v[i]);\n@@ -864,7 +864,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,\n \t * non-cone mode, if nothing is specified, manually select just the\n \t * top-level directory (much as 'init' would do).\n \t */\n-\tif (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n+\tif (!the_repository->settings.sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n \t\tfor (int i = 0; i < default_patterns_nr; i++)\n \t\t\tstrvec_push(&patterns, default_patterns[i]);\n \t} else {\n@@ -1041,7 +1041,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *\n \t\tcheck_rules_opts.cone_mode = 1;\n \n \tupdate_cone_mode(&check_rules_opts.cone_mode);\n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tif (check_rules_opts.rules_file) {\n \t\tfp = xfopen(check_rules_opts.rules_file, \"r\");\n \t\tadd_patterns_from_input(&pl, argc, argv, fp);\ndiff --git a/config.c b/config.c\nindex 8fd4dd8c81..707fe0707a 100644\n--- a/config.c\n+++ b/config.c\n@@ -1612,11 +1612,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n-\t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.precomposeunicode\")) {\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex 5d1cb7a067..d2b0a5aef6 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3460,7 +3460,7 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)\n \tint res;\n \tchar *sparse_filename = get_sparse_checkout_filename();\n \n-\tpl->use_cone_patterns = core_sparse_checkout_cone;\n+\tpl->use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, pl, NULL, 0);\n \n \tfree(sparse_filename);\ndiff --git a/environment.c b/environment.c\nindex a379a9149e..7d46b80711 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\ndiff --git a/environment.h b/environment.h\nindex 6a30512f3c..00a5b332a0 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,7 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n enum rebase_setup_type {\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 9270cca561..eebc1f941d 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -82,6 +82,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n \trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n+\trepo_cfg_bool(r, \"core.sparsecheckoutcone\", &r->settings.sparse_checkout_cone, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 9caa7c57a3..443e1399da 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -67,7 +67,9 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\n \tint sparse_checkout;\n+\tint sparse_checkout_cone;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 8132c0f2fb..6fd782a8fc 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -151,7 +151,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n \tprepare_repo_settings(istate->repo);\n-\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!istate->repo->settings.sparse_checkout || !istate->repo->settings.sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 02e32c4ba1..0e9813bddf 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -2144,6 +2144,7 @@ enum update_sparsity_result update_sparsity(struct unpack_trees_options *o,\n \t\tBUG(\"update_sparsity() called wrong\");\n \n \ttrace_performance_enter();\n+\tprepare_repo_settings(the_repository);\n \n \t/* If we weren't given patterns, use the recorded ones */\n \tif (!pl) {\n-- \n2.49.0\n\n"},{"id":"520968","messageId":"45c84a6615aa15f19b34b7f3d73a6e418c178427.1751309770.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1751309770.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-06-30T19:27:48Z","receivedAt":"2025-06-30T19:29:08Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The global variable 'sparse_expect_files_outside_of_patterns' is used in\na single function named 'clear_skip_worktree_from_present_files()' in\nsparse-index.c. Move its declaration inside that function, removing\nunnecessary global state.\n\nThis also allows us to remove the definition '#define\nUSE_THE_REPOSITORY_VARIABLE' from the file 'sparse-index.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n config.c       | 14 --------------\n environment.c  |  1 -\n environment.h  |  2 --\n sparse-index.c |  4 +++-\n 4 files changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 707fe0707a..d212329799 100644\n--- a/config.c\n+++ b/config.c\n@@ -1636,17 +1636,6 @@ static int git_default_core_config(const char *var, const char *value,\n \treturn platform_core_config(var, value, ctx, cb);\n }\n \n-static int git_default_sparse_config(const char *var, const char *value)\n-{\n-\tif (!strcmp(var, \"sparse.expectfilesoutsideofpatterns\")) {\n-\t\tsparse_expect_files_outside_of_patterns = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n-\t/* Add other config variables here and to Documentation/config/sparse.adoc. */\n-\treturn 0;\n-}\n-\n static int git_default_i18n_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"i18n.commitencoding\")) {\n@@ -1808,9 +1797,6 @@ int git_default_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (starts_with(var, \"sparse.\"))\n-\t\treturn git_default_sparse_config(var, value);\n-\n \t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 7d46b80711..d51e0a14aa 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -64,7 +64,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\ndiff --git a/environment.h b/environment.h\nindex 00a5b332a0..5121a28d3f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -160,8 +160,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int sparse_expect_files_outside_of_patterns;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 6fd782a8fc..ff33b8516b 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -668,6 +667,9 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n+\tint sparse_expect_files_outside_of_patterns = 0;\n+\trepo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n+\t\t&sparse_expect_files_outside_of_patterns);\n \tif (!istate->repo->settings.sparse_checkout ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n-- \n2.49.0\n\n"},{"id":"520972","messageId":"xmqq5xgdlyxy.fsf@gitster.g","threadId":"63571","inReplyTo":"cover.1751309770.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v5 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-30T21:08:41Z","receivedAt":"2025-06-30T21:08:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> This patch series aims to remove global variables related to\n> sparse-checkout from the global scope and to remove the definition\n> '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n>\n> It contains three patches:\n>\n> 1 - Remove the global variable 'core_apply_sparse_checkout' and\n> move its setting to the 'struct repo_settings'. Also remove the\n> definition '#define USE_THE_REPOSITORY_VARIABLE' from\n> \"builtin/backfill.c\".\n>\n> 2 - Remove the global variable 'core_sparse_checkout_cone' and\n> move its setting to the 'struct repo_settings'.\n>\n> 3 - Remove the global variable\n> 'sparse_expect_files_outside_of_patterns` and localize it in the\n> function which calls it. Also remove the definition '#define\n> USE_THE_REPOSITORY_VARIABLE' from \"sparse-index.c\"\n\nA call to prepare_repo_settings() function is not free even though\nthe .settings.initialized member makes second and subsequent calls\nto it as cheap as possible.  It makes me a bit worried to see\npatches that add new calls to it to places that are fairly deep in\nthe callchain (as opposed to in cmd_foo() for various built-in\ncommands).  As long as the control passes these places only once\nbefore we do the heavy lifting and then after the heavy lifting,\nthe only thing left for us is to exit, we would be fine, but I do\nnot know if all new calls added in these patches are that kind.\n\nThanks.\n"},{"id":"521045","messageId":"17b7f51c-0c3d-4d63-a501-47ce829f7345@gmail.com","threadId":"63571","inReplyTo":"45c84a6615aa15f19b34b7f3d73a6e418c178427.1751309770.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-07-01T13:18:04Z","receivedAt":"2025-07-01T13:18:07Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Ayush\n\nOn 30/06/2025 20:27, Ayush Chandekar wrote:\n> \n>   void clear_skip_worktree_from_present_files(struct index_state *istate)\n>   {\n> +\tint sparse_expect_files_outside_of_patterns = 0;\n> +\trepo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n> +\t\t&sparse_expect_files_outside_of_patterns);\n\nThis changes the user facing behavior if \nsparse.expectfilesoutsideofpatterns is not a valid boolean value. \nCurrently git will error out when it first starts because that config \nvalue is parsed by git_default_config() which is called by almost all \ngit commands. This means that if someone sets an invalid value they get \ntimely feedback that the value is invalid and git dies before doing \nanything. Now, if the value is invalid, git will only die if this \nfunction is called and it is likely to die in the middle of a command.\n\nThanks\n\nPhillip\n\n"},{"id":"521129","messageId":"CAE7as+YeTuQh_BzZSLuVTimrddp5-OBtpMa81KFhd+3zDqDiMg@mail.gmail.com","threadId":"63571","inReplyTo":"17b7f51c-0c3d-4d63-a501-47ce829f7345@gmail.com","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-01T23:53:12Z","receivedAt":"2025-07-01T23:53:24Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Tue, Jul 1, 2025 at 6:48 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> Hi Ayush\n\nHi Phillip,\n\n>\n> On 30/06/2025 20:27, Ayush Chandekar wrote:\n> >\n> >   void clear_skip_worktree_from_present_files(struct index_state *istate)\n> >   {\n> > +     int sparse_expect_files_outside_of_patterns = 0;\n> > +     repo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n> > +             &sparse_expect_files_outside_of_patterns);\n>\n> This changes the user facing behavior if\n> sparse.expectfilesoutsideofpatterns is not a valid boolean value.\n> Currently git will error out when it first starts because that config\n> value is parsed by git_default_config() which is called by almost all\n> git commands. This means that if someone sets an invalid value they get\n> timely feedback that the value is invalid and git dies before doing\n> anything. Now, if the value is invalid, git will only die if this\n> function is called and it is likely to die in the middle of a command.\n>\n> Thanks\n>\n> Phillip\n>\n\nYes, I get your point. However, if we look at settings which are\nshifted to `struct repo_settings`, the behaviour is to set a\nfallback/default value in case of an invalid input, instead of\nthrowing an error. This is done inside the `prepare_repo_settings()`\nfunction, which is often called in the middle of a process.\n\nThanks\n\nAyush:)\n"},{"id":"521151","messageId":"70a10ec5-9fb7-4b7e-b4e3-3d04fb44c23e@gmail.com","threadId":"63571","inReplyTo":"CAE7as+YeTuQh_BzZSLuVTimrddp5-OBtpMa81KFhd+3zDqDiMg@mail.gmail.com","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-07-02T09:01:31Z","receivedAt":"2025-07-02T09:01:35Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Ayush\n\nOn 02/07/2025 00:53, Ayush Chandekar wrote:\n> On Tue, Jul 1, 2025 at 6:48 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>> On 30/06/2025 20:27, Ayush Chandekar wrote:\n>>>\n>>>    void clear_skip_worktree_from_present_files(struct index_state *istate)\n>>>    {\n>>> +     int sparse_expect_files_outside_of_patterns = 0;\n>>> +     repo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n>>> +             &sparse_expect_files_outside_of_patterns);\n>>\n>> This changes the user facing behavior if\n>> sparse.expectfilesoutsideofpatterns is not a valid boolean value.\n>> Currently git will error out when it first starts because that config\n>> value is parsed by git_default_config() which is called by almost all\n>> git commands. This means that if someone sets an invalid value they get\n>> timely feedback that the value is invalid and git dies before doing\n>> anything. Now, if the value is invalid, git will only die if this\n>> function is called and it is likely to die in the middle of a command.\n> \n> Yes, I get your point. However, if we look at settings which are\n> shifted to `struct repo_settings`, the behaviour is to set a\n> fallback/default value in case of an invalid input, instead of\n> throwing an error. This is done inside the `prepare_repo_settings()`\n> function, which is often called in the middle of a process.\n\nI'm a bit confused by this and I'm not quite sure what you're saying for \na couple of reasons. Firstly this patch is not adding a new member to \nstruct repo_settings, it is parsing the config directly and will die() \nin git_config_bool() if the config value is invalid. Secondly \nprepare_repo_settings() ends up calling git_config_bool() and so will \nalso die if the config value is invalid rather than setting a default \nvalue. In the case of prepare_repo_settings() commands that do not want \nto die in the middle of an operation can call that function early on \nbefore they start doing any real work. Looking at the output of \"git \ngrep prepare_repo_settings()\" many do exactly that. Here there is no \noption for a command to die() early on invalid config values if it wants to.\n\nThanks\n\nPhillip\n\n"},{"id":"521153","messageId":"xmqqecuzeynr.fsf@gitster.g","threadId":"63571","inReplyTo":"CAE7as+YeTuQh_BzZSLuVTimrddp5-OBtpMa81KFhd+3zDqDiMg@mail.gmail.com","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-02T09:21:12Z","receivedAt":"2025-07-02T09:21:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> Yes, I get your point. However, if we look at settings which are\n> shifted to `struct repo_settings`, the behaviour is to set a\n> fallback/default value in case of an invalid input, instead of\n> throwing an error.\n\nSo the user will not be told about misconfiguration like they used\nto?  Is that an acceptable way forward, I have to wonder...\n\n"},{"id":"521596","messageId":"xmqqbjpuqkrj.fsf@gitster.g","threadId":"63571","inReplyTo":"cover.1751309770.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v5 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-09T00:18:40Z","receivedAt":"2025-07-09T00:18:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> This patch series aims to remove global variables related to\n> sparse-checkout from the global scope and to remove the definition\n> '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n\nFor this topic, it seems that the ball is in the author's court\nafter a few review comments.  What's the status of it?\n\nIf it is back-burnered for now, then we may eject the topic out of\n'seen' to make room for a new topic that touches the same area with\noverlapping changes.\n\nThanks.\n\n"},{"id":"521603","messageId":"CAE7as+aTBTx8rZ467uv9QV5Wiqnyed5ndY-+smJ1ayYVx6qmRw@mail.gmail.com","threadId":"63571","inReplyTo":"xmqqbjpuqkrj.fsf@gitster.g","subject":"Re: [GSOC PATCH v5 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-09T01:39:29Z","receivedAt":"2025-07-09T01:39:41Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"Hi Junio,\n\nOn Wed, Jul 9, 2025 at 5:48 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n>\n> > This patch series aims to remove global variables related to\n> > sparse-checkout from the global scope and to remove the definition\n> > '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n>\n> For this topic, it seems that the ball is in the author's court\n> after a few review comments.  What's the status of it?\n>\n> If it is back-burnered for now, then we may eject the topic out of\n> 'seen' to make room for a new topic that touches the same area with\n> overlapping changes.\n>\n> Thanks.\n>\n\nApologies for not keeping you updated. I had actually drafted a\nresponse explaining that in 1/3, I only added two new calls to\n`prepare_repo_settings()`. Some other calls were made in cmd_foo()\nfunctions, and a few others were rearranged and removed as well. (I\nshould've made it clearer in the commit message). In fact, the commit\nmessage mistaknely suggests that one extra call was added which wasn't\nthe case. For 2/3, only one new call was added. As for 3/3, I can move\nthe setting into the repo_settings struct, since\n`prepare_repo_settings()` is already being called before the variable\nis accessed.\n\nAt the time, I felt my draft wasn't convincinv enough, and then got\ncaught up with responses on other patch series and also was working on\nanother one.\n\nYou can eject this topic if you think another one is more important or\nif this one still needs work.\n\nAgain, Sorry for not updating earlied, will do better next time.\n\nThanks,\nAyush\n"},{"id":"521843","messageId":"CAE7as+YFRk_ZsOUQrnMivHhaG9s55Mmh4qGrJ6B0sOLWZQh-9w@mail.gmail.com","threadId":"63571","inReplyTo":"70a10ec5-9fb7-4b7e-b4e3-3d04fb44c23e@gmail.com","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-11T19:24:08Z","receivedAt":"2025-07-11T19:24:21Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"Hi Phillip,\n\nOn Wed, Jul 2, 2025 at 2:31 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> Hi Ayush\n>\n> On 02/07/2025 00:53, Ayush Chandekar wrote:\n> > On Tue, Jul 1, 2025 at 6:48 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n> >> On 30/06/2025 20:27, Ayush Chandekar wrote:\n> >>>\n> >>>    void clear_skip_worktree_from_present_files(struct index_state *istate)\n> >>>    {\n> >>> +     int sparse_expect_files_outside_of_patterns = 0;\n> >>> +     repo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n> >>> +             &sparse_expect_files_outside_of_patterns);\n> >>\n> >> This changes the user facing behavior if\n> >> sparse.expectfilesoutsideofpatterns is not a valid boolean value.\n> >> Currently git will error out when it first starts because that config\n> >> value is parsed by git_default_config() which is called by almost all\n> >> git commands. This means that if someone sets an invalid value they get\n> >> timely feedback that the value is invalid and git dies before doing\n> >> anything. Now, if the value is invalid, git will only die if this\n> >> function is called and it is likely to die in the middle of a command.\n> >\n> > Yes, I get your point. However, if we look at settings which are\n> > shifted to `struct repo_settings`, the behaviour is to set a\n> > fallback/default value in case of an invalid input, instead of\n> > throwing an error. This is done inside the `prepare_repo_settings()`\n> > function, which is often called in the middle of a process.\n>\n> I'm a bit confused by this and I'm not quite sure what you're saying for\n> a couple of reasons. Firstly this patch is not adding a new member to\n> struct repo_settings, it is parsing the config directly and will die()\n> in git_config_bool() if the config value is invalid. Secondly\n> prepare_repo_settings() ends up calling git_config_bool() and so will\n> also die if the config value is invalid rather than setting a default\n> value. In the case of prepare_repo_settings() commands that do not want\n> to die in the middle of an operation can call that function early on\n> before they start doing any real work. Looking at the output of \"git\n> grep prepare_repo_settings()\" many do exactly that. Here there is no\n> option for a command to die() early on invalid config values if it wants to.\n>\n> Thanks\n>\n> Phillip\n>\n\nYeah, you're right about the `prepare_repo_settings()` which throws\nerror and since they're called early on, we are notified about it\nbefore any heavy operation takes place. I had it confused as it also\nstores a default value if there isn't a config setting set. I can move\nthis setting into `struct repo_settings`, and since\n`prepare_repo_settings()` is already called just before the function\nthat uses this variable, I don't have to add any extra call to it.\n\nThanks!\nAyush\n"},{"id":"521844","messageId":"CAE7as+Z5ihQThZ5cXax44XNHoRzqdnZpRTrDdKKGz86cM_BgYw@mail.gmail.com","threadId":"63571","inReplyTo":"xmqqecuzeynr.fsf@gitster.g","subject":"Re: [GSOC PATCH v5 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-11T19:35:26Z","receivedAt":"2025-07-11T19:35:38Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Wed, Jul 2, 2025 at 2:51 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n>\n> > Yes, I get your point. However, if we look at settings which are\n> > shifted to `struct repo_settings`, the behaviour is to set a\n> > fallback/default value in case of an invalid input, instead of\n> > throwing an error.\n>\n> So the user will not be told about misconfiguration like they used\n> to?  Is that an acceptable way forward, I have to wonder...\n>\n\nI was actually mistaken that `prepare_repo_settings()` does not throw\nany error due to the fact that it sets default value when a config\nsetting is not set. So I thought, if there's invalid value in the\nconfig, it would just set the default value, but I was wrong.\n\nThanks,\nAyush\n"},{"id":"522298","messageId":"cover.1752882401.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"20250603131806.14915-1-ayu.chandekar@gmail.com","subject":"[GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-19T00:11:25Z","receivedAt":"2025-07-19T00:11:53Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"This patch series aims to remove global variables related to sparse-checkout from the global scope and to remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n\nIt contains three patches:\n\n1 - Remove the global variable 'core_apply_sparse_checkout' and move its setting to the 'struct repo_settings'. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"builtin/backfill.c\". \n\n2 - Remove the global variable 'core_sparse_checkout_cone' and move its setting to the 'struct repo_settings'.\n\n3 - Remove the global variable 'sparse_expect_files_outside_of_patterns` and move its setting to 'struct repo_settings'. Also remove the definition '#define USE_THE_REPOSITORY_VARIABLE' from \"sparse-index.c\"\n\nThanks a lot to Christian for mentoring, and to Junio, Patrick, Phillip and Ben for reviewing\n\nAyush Chandekar (3):\n  environment: move access to \"core.sparsecheckout\" into repo_settings\n  environment: move access to \"core.sparsecheckoutcone\" into\n    repo_settings\n  environment: remove the global variable\n    'sparse_expect_files_outside_of_patterns'\n\n builtin/backfill.c        |  7 ++----\n builtin/clone.c           |  3 ++-\n builtin/grep.c            |  4 ++--\n builtin/mv.c              |  6 ++---\n builtin/sparse-checkout.c | 49 +++++++++++++++++++--------------------\n builtin/worktree.c        |  2 +-\n config.c                  | 24 -------------------\n dir.c                     |  5 ++--\n environment.c             |  3 ---\n environment.h             |  4 ----\n repo-settings.c           |  3 +++\n repo-settings.h           |  4 ++++\n sparse-index.c            |  9 ++++---\n unpack-trees.c            |  2 +-\n wt-status.c               |  3 ++-\n 15 files changed, 51 insertions(+), 77 deletions(-)\n\n-- \n\nDiscussions since v5:\n* For 1/3 and 2/3, Junio told me that it was concerning to put so many calls to `prepare_repo_settings()` so I tried to minimize the calls and made sure that there's no useless calling.\n* For 3/3, Phillip told me that it broke user-facing as it will be parsed quite late in the callchain and might throw an error mid operation which we do not want.\n\nMain problem I was dealing with was `prepare_repo_settings()`. I think we can try to get useless calls to `prepare_repo_settings()`. Other than that, I agree with the approach that came up in the discussion here:\nhttps://lore.kernel.org/git/32fceddc-c867-4a47-bde8-c873279edbc1@gmail.com/\nwhich was adding a call to `prepare_repo_settings()` in `repo_config()`.\n\nSummary of range-diff:\n* Changed some calls to `prepare_repo_settings()` to make sure that it is added in code paths only where it has no been called before. \n  Also changed a mistake in commit message: s/sparse-checkout.c/sparse-index.c  and have explained it more.\n* Shifted the global variable to `struct repo_settings`(the previous version just localized it leading to user experience issues) and changed the commit message\n\nRange-diff with v5:\n1:  54ea376768 ! 1:  d0e2042b30 environment: move access to \"core.sparsecheckout\" into repo_settings\n    @@ Commit message\n         - In \"dir.c\", the function using 'settings.sparse_checkout' is invoked\n           in multiple files that do not call `prepare_repo_settings()`, hence\n           add a call directly to that function.\n    -    - In \"sparse-checkout.c\", add a call to `prepare_repo_settings()` inside\n    -      `is_sparse_index_allowed()`, as it is used widely and relies on the\n    -      setting.\n    +    - In \"sparse-index.c\", remove a call to `prepare_repo_settings()`\n    +      from the function `is_sparse_index_allowed()` as it is called\n    +      everytime before the function is called, and add a call to\n    +      `prepare_repo_settings()` inside `convert_to_sparse()`, as it is\n    +      used widely without having a call to `prepare_repo_settings()`\n    +      before and relies on the setting.\n         - In \"wt-status.c\", call `prepare_repo_settings()` before accessing\n           the setting because the function using it is commonly used.\n     \n    @@ dir.c: enum pattern_match_result path_matches_pattern_list(\n      int init_sparse_checkout_patterns(struct index_state *istate)\n      {\n     -\tif (!core_apply_sparse_checkout)\n    -+\tprepare_repo_settings(istate->repo);\n     +\tif (!istate->repo->settings.sparse_checkout)\n      \t\treturn 1;\n      \tif (istate->sparse_checkout_patterns)\n      \t\treturn 0;\n    +@@ dir.c: static int path_in_sparse_checkout_1(const char *path,\n    + \tenum pattern_match_result match = UNDECIDED;\n    + \tconst char *end, *slash;\n    + \n    ++\tprepare_repo_settings(istate->repo);\n    + \t/*\n    + \t * We default to accepting a path if the path is empty, there are no\n    + \t * patterns, or the patterns are of the wrong type.\n     \n      ## environment.c ##\n     @@ environment.c: enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n    @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate\n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n     -\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n    -+\tprepare_repo_settings(istate->repo);\n     +\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n      \t\treturn 0;\n      \n    @@ sparse-index.c: int is_sparse_index_allowed(struct index_state *istate, int flag\n      \t\tif (!istate->repo->settings.sparse_index)\n      \t\t\treturn 0;\n      \t}\n    +@@ sparse-index.c: int is_sparse_index_allowed(struct index_state *istate, int flags)\n    + \n    + int convert_to_sparse(struct index_state *istate, int flags)\n    + {\n    ++\tprepare_repo_settings(istate->repo);\n    + \t/*\n    + \t * If the index is already sparse, empty, or otherwise\n    + \t * cannot be converted to sparse, do not convert.\n     @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n      \n      void clear_skip_worktree_from_present_files(struct index_state *istate)\n2:  c4d37dc7c5 ! 2:  d799faca3f environment: move access to \"core.sparsecheckoutcone\" into repo_settings\n    @@ Commit message\n         code to store it in the variable `sparse_checkout_cone` in the struct\n         `repo_settings`.\n     \n    -    Call `prepare_repo_settings()` where necessary to ensure the `struct\n    -    repo_settings` is initialized before use:\n    -    - In \"dir.c\", the function accessing the setting is usually called after\n    -      `prepare_repo_settings()`, except for one code path in\n    -      \"unpack-trees.c\", so add a call there.\n    -\n         Avoid redundant calls to `prepare_repo_settings()` where it is already\n         present:\n         - In \"builtin/mv.c\" and \"builtin/sparse-checkout.c\", it is already\n           invoked in their respective `cmd_*()` functions.\n    -    - In \"sparse-index.c\", `prepare_repo_settings` is already called before\n    -      the setting is accessed.\n    +    - In \"sparse-index.c\", `prepare_repo_settings()` is already called\n    +      before the setting is accessed.\n    +    - In \"dir.c\", `prepare_repo_settings()` is already called in all code\n    +      paths before the setting is accessed.\n     \n         This change is part of an ongoing effort to eliminate global variables,\n         improve modularity and help libify the codebase.\n    @@ repo-settings.h: struct repo_settings {\n     \n      ## sparse-index.c ##\n     @@ sparse-index.c: static int index_has_unmerged_entries(struct index_state *istate)\n    + \n      int is_sparse_index_allowed(struct index_state *istate, int flags)\n      {\n    - \tprepare_repo_settings(istate->repo);\n     -\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n     +\tif (!istate->repo->settings.sparse_checkout || !istate->repo->settings.sparse_checkout_cone)\n      \t\treturn 0;\n      \n      \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n    -\n    - ## unpack-trees.c ##\n    -@@ unpack-trees.c: enum update_sparsity_result update_sparsity(struct unpack_trees_options *o,\n    - \t\tBUG(\"update_sparsity() called wrong\");\n    - \n    - \ttrace_performance_enter();\n    -+\tprepare_repo_settings(the_repository);\n    - \n    - \t/* If we weren't given patterns, use the recorded ones */\n    - \tif (!pl) {\n3:  84cb67469e ! 3:  35137b6814 environment: remove the global variable 'sparse_expect_files_outside_of_patterns'\n    @@ Metadata\n      ## Commit message ##\n         environment: remove the global variable 'sparse_expect_files_outside_of_patterns'\n     \n    -    The global variable 'sparse_expect_files_outside_of_patterns' is used in\n    -    a single function named 'clear_skip_worktree_from_present_files()' in\n    -    sparse-index.c. Move its declaration inside that function, removing\n    -    unnecessary global state.\n    +    The setting \"sparse.expectFilesOutsideOfPatterns\" is stored in the\n    +    global variable 'sparse_expect_files_outside_of_patterns' and allows\n    +    files marked with the `SKIP_WORKTREE` bit to be present in the worktree.\n    +\n    +    As this setting is closely related to repository, remove the global\n    +    variable and store the setting in the `struct repo_settings` along\n    +    with other sparse checkout related settings.\n     \n         This also allows us to remove the definition '#define\n         USE_THE_REPOSITORY_VARIABLE' from the file 'sparse-index.c'.\n    @@ environment.h: extern int precomposed_unicode;\n      \tAUTOREBASE_NEVER = 0,\n      \tAUTOREBASE_LOCAL,\n     \n    + ## repo-settings.c ##\n    +@@ repo-settings.c: void prepare_repo_settings(struct repository *r)\n    + \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n    + \trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n    + \trepo_cfg_bool(r, \"core.sparsecheckoutcone\", &r->settings.sparse_checkout_cone, 0);\n    ++\trepo_cfg_bool(r, \"sparse.expectfilesoutsideofpatterns\", &r->settings.sparse_expect_files_outside_of_patterns, 0);\n    + \n    + \t/*\n    + \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\n    +\n    + ## repo-settings.h ##\n    +@@ repo-settings.h: struct repo_settings {\n    + \n    + \tint sparse_checkout;\n    + \tint sparse_checkout_cone;\n    ++\tint sparse_expect_files_outside_of_patterns;\n    + };\n    + #define REPO_SETTINGS_INIT { \\\n    + \t.shared_repository = -1, \\\n    +\n      ## sparse-index.c ##\n     @@\n     -#define USE_THE_REPOSITORY_VARIABLE\n    @@ sparse-index.c\n      \n      #include \"git-compat-util.h\"\n     @@ sparse-index.c: static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n    - \n      void clear_skip_worktree_from_present_files(struct index_state *istate)\n      {\n    -+\tint sparse_expect_files_outside_of_patterns = 0;\n    -+\trepo_config_get_bool(istate->repo, \"sparse.expectfilesoutsideofpatterns\",\n    -+\t\t&sparse_expect_files_outside_of_patterns);\n      \tif (!istate->repo->settings.sparse_checkout ||\n    - \t    sparse_expect_files_outside_of_patterns)\n    +-\t    sparse_expect_files_outside_of_patterns)\n    ++\t    istate->repo->settings.sparse_expect_files_outside_of_patterns)\n      \t\treturn;\n    + \n    + \tif (clear_skip_worktree_from_present_files_sparse(istate)) {\n\n2.49.0\n\n"},{"id":"522299","messageId":"d0e2042b3061320fac8a8fdf9043c6ab4dbed5a2.1752882401.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1752882401.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v6 1/3] environment: move access to \"core.sparsecheckout\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-19T00:11:26Z","receivedAt":"2025-07-19T00:11:59Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckout\" is stored in the global\n`core_apply_sparse_checkout` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout` in the struct\n`repo_settings`.\n\nCall `prepare_repo_settings()` where necessary to ensure the `struct\nrepo_settings` is initialized before use:\n- In \"builtin/backfill.c\", \"builtin/mv.c\" and \"builtin/clone.c\" call\n  `prepare_repo_settings()` since their respective `cmd_*()` functions\n  did not call it earlier.\n- In \"dir.c\", the function using 'settings.sparse_checkout' is invoked\n  in multiple files that do not call `prepare_repo_settings()`, hence\n  add a call directly to that function.\n- In \"sparse-index.c\", remove a call to `prepare_repo_settings()`\n  from the function `is_sparse_index_allowed()` as it is called\n  everytime before the function is called, and add a call to\n  `prepare_repo_settings()` inside `convert_to_sparse()`, as it is\n  used widely without having a call to `prepare_repo_settings()`\n  before and relies on the setting.\n- In \"wt-status.c\", call `prepare_repo_settings()` before accessing\n  the setting because the function using it is commonly used.\n\nAvoid reduntant calls to `prepare_repo_settings()` where it is already\npresent:\n- In \"builtin/worktree.c\", it is already invoked in `cmd_worktree()`\n  before the setting is accessed.\n- In \"unpack-tress.c\", the function accessing the setting already calls\n  it.\n\nThis also allows us to remove the definition `#define\nUSE_THE_REPOSITORY_VARIABLE` from the file 'builtin/backfill.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/backfill.c        |  7 ++-----\n builtin/clone.c           |  3 ++-\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  4 ++--\n builtin/sparse-checkout.c | 21 ++++++++++-----------\n builtin/worktree.c        |  2 +-\n config.c                  |  5 -----\n dir.c                     |  3 ++-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  1 +\n sparse-index.c            |  6 +++---\n unpack-trees.c            |  2 +-\n wt-status.c               |  3 ++-\n 15 files changed, 28 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/backfill.c b/builtin/backfill.c\nindex 80056abe47..48b2518743 100644\n--- a/builtin/backfill.c\n+++ b/builtin/backfill.c\n@@ -1,6 +1,3 @@\n-/* We need this macro to access core_apply_sparse_checkout */\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"builtin.h\"\n #include \"git-compat-util.h\"\n #include \"config.h\"\n@@ -137,9 +134,9 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit\n \t\t\t     0);\n \n \trepo_config(repo, git_default_config, NULL);\n-\n+\tprepare_repo_settings(repo);\n \tif (ctx.sparse < 0)\n-\t\tctx.sparse = core_apply_sparse_checkout;\n+\t\tctx.sparse = repo->settings.sparse_checkout;\n \n \tresult = do_backfill(&ctx);\n \tbackfill_context_clear(&ctx);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 6d08abed37..6b6d429fd8 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -619,11 +619,12 @@ static int git_sparse_checkout_init(const char *repo)\n \tint result = 0;\n \tstrvec_pushl(&cmd.args, \"-C\", repo, \"sparse-checkout\", \"set\", NULL);\n \n+\tprepare_repo_settings(the_repository);\n \t/*\n \t * We must apply the setting in the current process\n \t * for the later checkout to use the sparse-checkout file.\n \t */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tcmd.git_cmd = 1;\n \tif (run_command(&cmd)) {\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 39273d9c0f..fbad1a72a2 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -481,7 +481,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\t\"forget\" the sparse-index feature switch. As a result, the index\n \t *\tof these submodules are expanded unexpectedly.\n \t *\n-\t * 2. \"core_apply_sparse_checkout\"\n+\t * 2. \"settings.sparse_checkout\"\n \t *\tWhen running `grep` in the superproject, this setting is\n \t *\tpopulated using the superproject's configs. However, once\n \t *\tinitialized, this config is globally accessible and is read by\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 07548fe96a..43ed2e3d0a 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -570,9 +570,9 @@ int cmd_mv(int argc,\n \t\t\t\t\t\t       &st,\n \t\t\t\t\t\t       0);\n \t\trename_index_entry_at(the_repository->index, pos, dst);\n-\n+\t\tprepare_repo_settings(the_repository);\n \t\tif (ignore_sparse &&\n-\t\t    core_apply_sparse_checkout &&\n+\t\t    the_repository->settings.sparse_checkout &&\n \t\t    core_sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 1bf01591b2..8329d29a27 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -62,7 +62,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \tint res;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"this worktree is not sparse\"));\n \n \targc = parse_options(argc, argv, prefix,\n@@ -397,11 +397,11 @@ static int set_config(enum sparse_checkout_mode mode)\n \n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n-\tif (*cone_mode == -1 && core_apply_sparse_checkout)\n+\tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n \t\t*cone_mode = core_sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n \t\tcore_sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n@@ -415,7 +415,7 @@ static int update_modes(int *cone_mode, int *sparse_index)\n \tint mode, record_mode;\n \n \t/* Determine if we need to record the mode; ensure sparse checkout on */\n-\trecord_mode = (*cone_mode != -1) || !core_apply_sparse_checkout;\n+\trecord_mode = (*cone_mode != -1) || !the_repository->settings.sparse_checkout;\n \n \tmode = update_cone_mode(cone_mode);\n \tif (record_mode && set_config(mode))\n@@ -695,9 +695,9 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \t\tbreak;\n \t}\n \n-\tif (!core_apply_sparse_checkout) {\n+\tif (!the_repository->settings.sparse_checkout) {\n \t\tset_config(MODE_ALL_PATTERNS);\n-\t\tcore_apply_sparse_checkout = 1;\n+\t\tthe_repository->settings.sparse_checkout = 1;\n \t\tchanged_config = 1;\n \t}\n \n@@ -793,7 +793,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,\n \tint ret;\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"no sparse-checkout to add to\"));\n \n \trepo_read_index(the_repository);\n@@ -902,7 +902,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,\n \t};\n \n \tsetup_work_tree();\n-\tif (!core_apply_sparse_checkout)\n+\tif (!the_repository->settings.sparse_checkout)\n \t\tdie(_(\"must be in a sparse-checkout to reapply sparsity patterns\"));\n \n \treapply_opts.cone_mode = -1;\n@@ -935,7 +935,7 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \tstruct pattern_list pl;\n \n \t/*\n-\t * We do not exit early if !core_apply_sparse_checkout; due to the\n+\t * We do not exit early if !sparse_checkout; due to the\n \t * ability for users to manually muck things up between\n \t *   direct editing of .git/info/sparse-checkout\n \t *   running read-tree -m u HEAD or update-index --skip-worktree\n@@ -961,11 +961,10 @@ static int sparse_checkout_disable(int argc, const char **argv,\n \thashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n \thashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);\n \tpl.use_cone_patterns = 0;\n-\tcore_apply_sparse_checkout = 1;\n+\tthe_repository->settings.sparse_checkout = 1;\n \n \tadd_pattern(\"/*\", empty_base, 0, &pl, 0);\n \n-\tprepare_repo_settings(the_repository);\n \tthe_repository->settings.sparse_index = 0;\n \n \tif (update_working_directory(&pl))\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 2dceeeed8b..a3a1bb00e3 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -536,7 +536,7 @@ static int add_worktree(const char *path, const char *refname,\n \t * If the current worktree has sparse-checkout enabled, then copy\n \t * the sparse-checkout patterns from the current worktree.\n \t */\n-\tif (core_apply_sparse_checkout)\n+\tif (the_repository->settings.sparse_checkout)\n \t\tcopy_sparse_checkout(sb_repo.buf);\n \n \t/*\ndiff --git a/config.c b/config.c\nindex 095a17bd42..da76bf4fde 100644\n--- a/config.c\n+++ b/config.c\n@@ -1607,11 +1607,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckout\")) {\n-\t\tcore_apply_sparse_checkout = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n \t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex 02873f59ea..01d7574c09 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1516,7 +1516,7 @@ enum pattern_match_result path_matches_pattern_list(\n \n int init_sparse_checkout_patterns(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout)\n+\tif (!istate->repo->settings.sparse_checkout)\n \t\treturn 1;\n \tif (istate->sparse_checkout_patterns)\n \t\treturn 0;\n@@ -1539,6 +1539,7 @@ static int path_in_sparse_checkout_1(const char *path,\n \tenum pattern_match_result match = UNDECIDED;\n \tconst char *end, *slash;\n \n+\tprepare_repo_settings(istate->repo);\n \t/*\n \t * We default to accepting a path if the path is empty, there are no\n \t * patterns, or the patterns are of the wrong type.\ndiff --git a/environment.c b/environment.c\nindex 7c2480b22e..3a21629f86 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -63,7 +63,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\ndiff --git a/environment.h b/environment.h\nindex 3d806ced6e..1e1e83fff1 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -159,7 +159,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 195c24e9c0..c3aa92c065 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -84,6 +84,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      &r->settings.pack_use_bitmap_boundary_traversal,\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n+\trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex d477885561..95900784f1 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -68,6 +68,7 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\tint sparse_checkout;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 5634abafaa..c9e5a5efe1 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!core_apply_sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n@@ -172,7 +172,6 @@ int is_sparse_index_allowed(struct index_state *istate, int flags)\n \t\t/*\n \t\t * Only convert to sparse if index.sparse is set.\n \t\t */\n-\t\tprepare_repo_settings(istate->repo);\n \t\tif (!istate->repo->settings.sparse_index)\n \t\t\treturn 0;\n \t}\n@@ -196,6 +195,7 @@ int is_sparse_index_allowed(struct index_state *istate, int flags)\n \n int convert_to_sparse(struct index_state *istate, int flags)\n {\n+\tprepare_repo_settings(istate->repo);\n \t/*\n \t * If the index is already sparse, empty, or otherwise\n \t * cannot be converted to sparse, do not convert.\n@@ -668,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n \n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n-\tif (!core_apply_sparse_checkout ||\n+\tif (!istate->repo->settings.sparse_checkout ||\n \t    sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex f38c761ab9..2e6d3f98f7 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1924,7 +1924,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \tif (o->prefix)\n \t\tupdate_sparsity_for_prefix(o->prefix, o->src_index);\n \n-\tif (!core_apply_sparse_checkout || !o->update)\n+\tif (!repo->settings.sparse_checkout || !o->update)\n \t\to->skip_sparse_checkout = 1;\n \tif (!o->skip_sparse_checkout) {\n \t\tmemset(&pl, 0, sizeof(pl));\ndiff --git a/wt-status.c b/wt-status.c\nindex 454601afa1..8651134bcb 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1773,7 +1773,8 @@ static void wt_status_check_sparse_checkout(struct repository *r,\n \tint skip_worktree = 0;\n \tint i;\n \n-\tif (!core_apply_sparse_checkout || r->index->cache_nr == 0) {\n+\tprepare_repo_settings(r);\n+\tif (!r->settings.sparse_checkout || r->index->cache_nr == 0) {\n \t\t/*\n \t\t * Don't compute percentage of checked out files if we\n \t\t * aren't in a sparse checkout or would get division by 0.\n-- \n2.49.0\n\n"},{"id":"522300","messageId":"d799faca3fa93b0e5ac906bfd9839f143d299e5b.1752882401.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1752882401.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v6 2/3] environment: move access to \"core.sparsecheckoutcone\" into repo_settings","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-19T00:11:27Z","receivedAt":"2025-07-19T00:12:04Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"core.sparsecheckoutcone\" is stored in the global\n`core_sparse_checkout_cone` and is populated in config.c. Refactor the\ncode to store it in the variable `sparse_checkout_cone` in the struct\n`repo_settings`.\n\nAvoid redundant calls to `prepare_repo_settings()` where it is already\npresent:\n- In \"builtin/mv.c\" and \"builtin/sparse-checkout.c\", it is already\n  invoked in their respective `cmd_*()` functions.\n- In \"sparse-index.c\", `prepare_repo_settings()` is already called\n  before the setting is accessed.\n- In \"dir.c\", `prepare_repo_settings()` is already called in all code\n  paths before the setting is accessed.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n builtin/grep.c            |  2 +-\n builtin/mv.c              |  2 +-\n builtin/sparse-checkout.c | 28 ++++++++++++++--------------\n config.c                  |  5 -----\n dir.c                     |  2 +-\n environment.c             |  1 -\n environment.h             |  1 -\n repo-settings.c           |  1 +\n repo-settings.h           |  2 ++\n sparse-index.c            |  2 +-\n 10 files changed, 21 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex fbad1a72a2..bd5481cc44 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -491,7 +491,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t *\tdictate the behavior for the submodule, making it \"forget\" its\n \t *\tsparse-checkout state.\n \t *\n-\t * 3. \"core_sparse_checkout_cone\"\n+\t * 3. \"settings.sparse_checkout_cone\"\n \t *\tditto.\n \t *\n \t * Note that this list is not exhaustive.\ndiff --git a/builtin/mv.c b/builtin/mv.c\nindex 43ed2e3d0a..2d1326a18f 100644\n--- a/builtin/mv.c\n+++ b/builtin/mv.c\n@@ -573,7 +573,7 @@ int cmd_mv(int argc,\n \t\tprepare_repo_settings(the_repository);\n \t\tif (ignore_sparse &&\n \t\t    the_repository->settings.sparse_checkout &&\n-\t\t    core_sparse_checkout_cone) {\n+\t\t    the_repository->settings.sparse_checkout_cone) {\n \t\t\t/*\n \t\t\t * NEEDSWORK: we are *not* paying attention to\n \t\t\t * \"out-to-out\" move (<source> is out-of-cone and\ndiff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c\nindex 8329d29a27..8a0ffba9d4 100644\n--- a/builtin/sparse-checkout.c\n+++ b/builtin/sparse-checkout.c\n@@ -71,7 +71,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,\n \n \tmemset(&pl, 0, sizeof(pl));\n \n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tsparse_filename = get_sparse_checkout_filename();\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, &pl, NULL, 0);\n@@ -352,7 +352,7 @@ static int write_patterns_and_update(struct pattern_list *pl)\n \tif (!fp)\n \t\tdie_errno(_(\"unable to fdopen %s\"), get_lock_file_path(&lk));\n \n-\tif (core_sparse_checkout_cone)\n+\tif (the_repository->settings.sparse_checkout_cone)\n \t\twrite_cone_to_file(fp, pl);\n \telse\n \t\twrite_patterns_to_file(fp, pl);\n@@ -398,15 +398,15 @@ static int set_config(enum sparse_checkout_mode mode)\n static enum sparse_checkout_mode update_cone_mode(int *cone_mode) {\n \t/* If not specified, use previous definition of cone mode */\n \tif (*cone_mode == -1 && the_repository->settings.sparse_checkout)\n-\t\t*cone_mode = core_sparse_checkout_cone;\n+\t\t*cone_mode = the_repository->settings.sparse_checkout_cone;\n \n \t/* Set cone/non-cone mode appropriately */\n \tthe_repository->settings.sparse_checkout = 1;\n \tif (*cone_mode == 1 || *cone_mode == -1) {\n-\t\tcore_sparse_checkout_cone = 1;\n+\t\tthe_repository->settings.sparse_checkout_cone = 1;\n \t\treturn MODE_CONE_PATTERNS;\n \t}\n-\tcore_sparse_checkout_cone = 0;\n+\tthe_repository->settings.sparse_checkout_cone = 0;\n \treturn MODE_ALL_PATTERNS;\n }\n \n@@ -572,7 +572,7 @@ static void add_patterns_from_input(struct pattern_list *pl,\n \t\t\t\t    FILE *file)\n {\n \tint i;\n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tstruct strbuf line = STRBUF_INIT;\n \n \t\thashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);\n@@ -637,7 +637,7 @@ static void add_patterns_cone_mode(int argc, const char **argv,\n \t\t\t\tuse_stdin ? stdin : NULL);\n \n \tmemset(&existing, 0, sizeof(existing));\n-\texisting.use_cone_patterns = core_sparse_checkout_cone;\n+\texisting.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \n \tif (add_patterns_from_file_to_list(sparse_filename, \"\", 0,\n \t\t\t\t\t   &existing, NULL, 0))\n@@ -683,7 +683,7 @@ static int modify_pattern_list(struct strvec *args, int use_stdin,\n \n \tswitch (m) {\n \tcase ADD:\n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tadd_patterns_cone_mode(args->nr, args->v, pl, use_stdin);\n \t\telse\n \t\t\tadd_patterns_literal(args->nr, args->v, pl, use_stdin);\n@@ -719,7 +719,7 @@ static void sanitize_paths(struct strvec *args,\n \tif (!args->nr)\n \t\treturn;\n \n-\tif (prefix && *prefix && core_sparse_checkout_cone) {\n+\tif (prefix && *prefix && the_repository->settings.sparse_checkout_cone) {\n \t\t/*\n \t\t * The args are not pathspecs, so unfortunately we\n \t\t * cannot imitate how cmd_add() uses parse_pathspec().\n@@ -736,10 +736,10 @@ static void sanitize_paths(struct strvec *args,\n \tif (skip_checks)\n \t\treturn;\n \n-\tif (prefix && *prefix && !core_sparse_checkout_cone)\n+\tif (prefix && *prefix && !the_repository->settings.sparse_checkout_cone)\n \t\tdie(_(\"please run from the toplevel directory in non-cone mode\"));\n \n-\tif (core_sparse_checkout_cone) {\n+\tif (the_repository->settings.sparse_checkout_cone) {\n \t\tfor (i = 0; i < args->nr; i++) {\n \t\t\tif (args->v[i][0] == '/')\n \t\t\t\tdie(_(\"specify directories rather than patterns (no leading slash)\"));\n@@ -761,7 +761,7 @@ static void sanitize_paths(struct strvec *args,\n \t\tif (S_ISSPARSEDIR(ce->ce_mode))\n \t\t\tcontinue;\n \n-\t\tif (core_sparse_checkout_cone)\n+\t\tif (the_repository->settings.sparse_checkout_cone)\n \t\t\tdie(_(\"'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks\"), args->v[i]);\n \t\telse\n \t\t\twarning(_(\"pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual).\"), args->v[i]);\n@@ -864,7 +864,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,\n \t * non-cone mode, if nothing is specified, manually select just the\n \t * top-level directory (much as 'init' would do).\n \t */\n-\tif (!core_sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n+\tif (!the_repository->settings.sparse_checkout_cone && !set_opts.use_stdin && argc == 0) {\n \t\tfor (int i = 0; i < default_patterns_nr; i++)\n \t\t\tstrvec_push(&patterns, default_patterns[i]);\n \t} else {\n@@ -1041,7 +1041,7 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *\n \t\tcheck_rules_opts.cone_mode = 1;\n \n \tupdate_cone_mode(&check_rules_opts.cone_mode);\n-\tpl.use_cone_patterns = core_sparse_checkout_cone;\n+\tpl.use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tif (check_rules_opts.rules_file) {\n \t\tfp = xfopen(check_rules_opts.rules_file, \"r\");\n \t\tadd_patterns_from_input(&pl, argc, argv, fp);\ndiff --git a/config.c b/config.c\nindex da76bf4fde..e13f7d8fe8 100644\n--- a/config.c\n+++ b/config.c\n@@ -1607,11 +1607,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.sparsecheckoutcone\")) {\n-\t\tcore_sparse_checkout_cone = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.precomposeunicode\")) {\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/dir.c b/dir.c\nindex 01d7574c09..5bed22a479 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3473,7 +3473,7 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)\n \tint res;\n \tchar *sparse_filename = get_sparse_checkout_filename();\n \n-\tpl->use_cone_patterns = core_sparse_checkout_cone;\n+\tpl->use_cone_patterns = the_repository->settings.sparse_checkout_cone;\n \tres = add_patterns_from_file_to_list(sparse_filename, \"\", 0, pl, NULL, 0);\n \n \tfree(sparse_filename);\ndiff --git a/environment.c b/environment.c\nindex 3a21629f86..cd5ec5c736 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -63,7 +63,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int core_sparse_checkout_cone;\n int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\ndiff --git a/environment.h b/environment.h\nindex 1e1e83fff1..5642156d3d 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -159,7 +159,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n enum rebase_setup_type {\ndiff --git a/repo-settings.c b/repo-settings.c\nindex c3aa92c065..505e402276 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -85,6 +85,7 @@ void prepare_repo_settings(struct repository *r)\n \t\t      r->settings.pack_use_bitmap_boundary_traversal);\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n \trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n+\trepo_cfg_bool(r, \"core.sparsecheckoutcone\", &r->settings.sparse_checkout_cone, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 95900784f1..1b43c4029c 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -68,7 +68,9 @@ struct repo_settings {\n \tunsigned long big_file_threshold;\n \n \tchar *hooks_path;\n+\n \tint sparse_checkout;\n+\tint sparse_checkout_cone;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex c9e5a5efe1..3b51ea46e3 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -150,7 +150,7 @@ static int index_has_unmerged_entries(struct index_state *istate)\n \n int is_sparse_index_allowed(struct index_state *istate, int flags)\n {\n-\tif (!istate->repo->settings.sparse_checkout || !core_sparse_checkout_cone)\n+\tif (!istate->repo->settings.sparse_checkout || !istate->repo->settings.sparse_checkout_cone)\n \t\treturn 0;\n \n \tif (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {\n-- \n2.49.0\n\n"},{"id":"522301","messageId":"35137b6814818eb5f13d6c54b8532d551bf33cec.1752882401.git.ayu.chandekar@gmail.com","threadId":"63571","inReplyTo":"cover.1752882401.git.ayu.chandekar@gmail.com","subject":"[GSOC PATCH v6 3/3] environment: remove the global variable 'sparse_expect_files_outside_of_patterns'","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-19T00:11:28Z","receivedAt":"2025-07-19T00:12:09Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"The setting \"sparse.expectFilesOutsideOfPatterns\" is stored in the\nglobal variable 'sparse_expect_files_outside_of_patterns' and allows\nfiles marked with the `SKIP_WORKTREE` bit to be present in the worktree.\n\nAs this setting is closely related to repository, remove the global\nvariable and store the setting in the `struct repo_settings` along\nwith other sparse checkout related settings.\n\nThis also allows us to remove the definition '#define\nUSE_THE_REPOSITORY_VARIABLE' from the file 'sparse-index.c'.\n\nThis change is part of an ongoing effort to eliminate global variables,\nimprove modularity and help libify the codebase.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>\nSigned-off-by: Ayush Chandekar <ayu.chandekar@gmail.com>\n---\n config.c        | 14 --------------\n environment.c   |  1 -\n environment.h   |  2 --\n repo-settings.c |  1 +\n repo-settings.h |  1 +\n sparse-index.c  |  3 +--\n 6 files changed, 3 insertions(+), 19 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex e13f7d8fe8..ea6de843f7 100644\n--- a/config.c\n+++ b/config.c\n@@ -1631,17 +1631,6 @@ static int git_default_core_config(const char *var, const char *value,\n \treturn platform_core_config(var, value, ctx, cb);\n }\n \n-static int git_default_sparse_config(const char *var, const char *value)\n-{\n-\tif (!strcmp(var, \"sparse.expectfilesoutsideofpatterns\")) {\n-\t\tsparse_expect_files_outside_of_patterns = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n-\t/* Add other config variables here and to Documentation/config/sparse.adoc. */\n-\treturn 0;\n-}\n-\n static int git_default_i18n_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"i18n.commitencoding\")) {\n@@ -1803,9 +1792,6 @@ int git_default_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (starts_with(var, \"sparse.\"))\n-\t\treturn git_default_sparse_config(var, value);\n-\n \t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex cd5ec5c736..cf52fa9617 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -63,7 +63,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n int grafts_keep_true_parents;\n-int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\ndiff --git a/environment.h b/environment.h\nindex 5642156d3d..aaa3025df3 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -159,8 +159,6 @@ extern int precomposed_unicode;\n extern int protect_hfs;\n extern int protect_ntfs;\n \n-extern int sparse_expect_files_outside_of_patterns;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 505e402276..5e0ba4ae23 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -86,6 +86,7 @@ void prepare_repo_settings(struct repository *r)\n \trepo_cfg_bool(r, \"core.usereplacerefs\", &r->settings.read_replace_refs, 1);\n \trepo_cfg_bool(r, \"core.sparsecheckout\", &r->settings.sparse_checkout, 0);\n \trepo_cfg_bool(r, \"core.sparsecheckoutcone\", &r->settings.sparse_checkout_cone, 0);\n+\trepo_cfg_bool(r, \"sparse.expectfilesoutsideofpatterns\", &r->settings.sparse_expect_files_outside_of_patterns, 0);\n \n \t/*\n \t * The GIT_TEST_MULTI_PACK_INDEX variable is special in that\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 1b43c4029c..695c0fd0ce 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -71,6 +71,7 @@ struct repo_settings {\n \n \tint sparse_checkout;\n \tint sparse_checkout_cone;\n+\tint sparse_expect_files_outside_of_patterns;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 3b51ea46e3..552d26adc1 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,4 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n #define DISABLE_SIGN_COMPARE_WARNINGS\n \n #include \"git-compat-util.h\"\n@@ -669,7 +668,7 @@ static void clear_skip_worktree_from_present_files_full(struct index_state *ista\n void clear_skip_worktree_from_present_files(struct index_state *istate)\n {\n \tif (!istate->repo->settings.sparse_checkout ||\n-\t    sparse_expect_files_outside_of_patterns)\n+\t    istate->repo->settings.sparse_expect_files_outside_of_patterns)\n \t\treturn;\n \n \tif (clear_skip_worktree_from_present_files_sparse(istate)) {\n-- \n2.49.0\n\n"},{"id":"522611","messageId":"xmqqcy9qlfm8.fsf@gitster.g","threadId":"63571","inReplyTo":"cover.1752882401.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-23T22:14:07Z","receivedAt":"2025-07-23T22:14:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n> This patch series aims to remove global variables related to\n> sparse-checkout from the global scope and to remove the definition\n> '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n>\n> It contains three patches:\n>\n> 1 - Remove the global variable 'core_apply_sparse_checkout' and\n> move its setting to the 'struct repo_settings'. Also remove the\n> definition '#define USE_THE_REPOSITORY_VARIABLE' from\n> \"builtin/backfill.c\".\n>\n> 2 - Remove the global variable 'core_sparse_checkout_cone' and\n> move its setting to the 'struct repo_settings'.\n>\n> 3 - Remove the global variable\n> 'sparse_expect_files_outside_of_patterns` and move its setting to\n> 'struct repo_settings'. Also remove the definition '#define\n> USE_THE_REPOSITORY_VARIABLE' from \"sparse-index.c\"\n> --\n> Discussions since v5:\n>\n> * For 1/3 and 2/3, Junio told me that it was concerning to put so\n>   many calls to `prepare_repo_settings()` so I tried to minimize the\n>   calls and made sure that there's no useless calling.\n\nI didn't mean that the number of places is the problem.  What I\nfound troubling was that this is not done in any central place, so\nit is hard to notice even if some random cmd_foo() failed to call\nthe function before doing its real work.  For example, shouldn't we\nbe able to, at least for built-in commands that have RUN_SETUP bit\nset, centrally call prepare_repo_settings() somewhere late in\ngit.c:run_builtin() after we figure out what should be in\nthe_repository?  Now historically, setting up a repository may never\nhave involved opening and parsing tons of configuration files, so\nsuch a change may be incurring extra overhead we did not have to\npay, so it needs a lot more thought than just trying to minimize the\nnumber of calls, but some performance measurement.\n\n> * For 3/3, Phillip told me that it broke user-facing as it will be\n>   parsed quite late in the callchain and might throw an error mid\n>   operation which we do not want.\n\nSo has the behaviour change caused by 3/3 been resolved?\n\nA meta-level comment and a half.\n\n * Please do not use \"-- \" (that is a line that has dash dash and a\n   single space and nothing else on it) lightly.  It is called\n   signature line and often MUA pays attention to it when responding\n   to a message with such a line by omitting everything after it\n   (which is supposed to be your \"who I am\" advertisement) when\n   quoting the original.  Since you had one before the \"discussions\n   since v5\" section and the range-diff, I had to manually resurrect\n   the part after the signature line while composing this message.\n\n * This throws everything in repo_settings, but these settings are\n   inherently per repository and they are meaningful only when you\n   are working with a repository.  What makes us choose to make them\n   new members in the repo_settings structure, not direct members in\n   the repository structure?\n\n   Not an objection and not a suggestion to move them out of the\n   repo_settings and to the repository proper.  Just wanted to hear\n   the reasoning behind it (and have the rationale clearly\n   documented, preferrably in the proposed log messages).\n"},{"id":"522660","messageId":"43aaec10-2696-44c9-8728-2045b83dc5d3@gmail.com","threadId":"63571","inReplyTo":"xmqqcy9qlfm8.fsf@gitster.g","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-07-24T13:25:34Z","receivedAt":"2025-07-24T13:25:37Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/23/25 6:14 PM, Junio C Hamano wrote:\n> Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n> \n>> This patch series aims to remove global variables related to\n>> sparse-checkout from the global scope and to remove the definition\n>> '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n\nSorry that I missed early versions of this thread. It's an\ninteresting topic to me, but I've been distracted.\n\n>> Discussions since v5:\n>>\n>> * For 1/3 and 2/3, Junio told me that it was concerning to put so\n>>    many calls to `prepare_repo_settings()` so I tried to minimize the\n>>    calls and made sure that there's no useless calling.\n> \n> I didn't mean that the number of places is the problem.  What I\n> found troubling was that this is not done in any central place, so\n> it is hard to notice even if some random cmd_foo() failed to call\n> the function before doing its real work.  For example, shouldn't we\n> be able to, at least for built-in commands that have RUN_SETUP bit\n> set, centrally call prepare_repo_settings() somewhere late in\n> git.c:run_builtin() after we figure out what should be in\n> the_repository?  Now historically, setting up a repository may never\n> have involved opening and parsing tons of configuration files, so\n> such a change may be incurring extra overhead we did not have to\n> pay, so it needs a lot more thought than just trying to minimize the\n> number of calls, but some performance measurement.\n\nI think that the core issue here (and probably causing the issues\nthat were seen in the user-facing issues) is that the repo settings\nstruct was intended as a place to fill config for some one-off\n\"feature flags\" and not to replace core functionality for a repo.\n\nThere are two ways to change the approach here to fix the problem\nof needing prepare_repo_settings() everyhwere:\n\n  1. With the idea that these sparse-checkout variables are\n     critical to the functionality of the repo, they should move\n     into the repository struct itself and be initialized along\n     with all other values there. This changes the patches (and my\n     follow-up series) significantly, but mechanically.\n\n  2. If we are going to change the intention of the repo settings\n     struct to move from \"optional one-off feature flags\" to\n     \"important information about the core behavior of a repo\"\n     then we should prepare_repo_settings() when initializing the\n     repository struct.\n\nMy preference is (1). The only argument for (2) that I can think\nof is that it is sometimes helpful to share only the settings for\na repo without sharing the whole repo. But that seems like a weak\nreason right now.\n\n>> * For 3/3, Phillip told me that it broke user-facing as it will be\n>>    parsed quite late in the callchain and might throw an error mid\n>>    operation which we do not want.\n> \n> So has the behaviour change caused by 3/3 been resolved?\n\n>   * This throws everything in repo_settings, but these settings are\n>     inherently per repository and they are meaningful only when you\n>     are working with a repository.  What makes us choose to make them\n>     new members in the repo_settings structure, not direct members in\n>     the repository structure?\n\n(This is the same thought I expressed earlier in this message.)\n\nThanks,\n-Stolee\n\n"},{"id":"522698","messageId":"xmqq7bzxh1j6.fsf@gitster.g","threadId":"63571","inReplyTo":"43aaec10-2696-44c9-8728-2045b83dc5d3@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-24T18:44:13Z","receivedAt":"2025-07-24T18:44:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n> There are two ways to change the approach here to fix the problem\n> of needing prepare_repo_settings() everyhwere:\n>\n>  1. With the idea that these sparse-checkout variables are\n>     critical to the functionality of the repo, they should move\n>     into the repository struct itself and be initialized along\n>     with all other values there. This changes the patches (and my\n>     follow-up series) significantly, but mechanically.\n>\n>  2. If we are going to change the intention of the repo settings\n>     struct to move from \"optional one-off feature flags\" to\n>     \"important information about the core behavior of a repo\"\n>     then we should prepare_repo_settings() when initializing the\n>     repository struct.\n>\n> My preference is (1). The only argument for (2) that I can think\n> of is that it is sometimes helpful to share only the settings for\n> a repo without sharing the whole repo. But that seems like a weak\n> reason right now.\n\nI do agree with the sentiment that being able to pass &repo.settings\nto helper function makes us feel safer, but I agree that it is a\nweak argument.  If we reexamine other things in repo_settings, it\nmay turn out that the same reasoning applies to them and we may be\nbetter off to roll repo_settings into the repository itself (after\nall, it is an embedded structure, not even a pointer in the main\nstructure that points at an indenendent repo_settings structure),\nbut that is totally outside the scope of this discussion.\n\nThanks.\n"},{"id":"522817","messageId":"CAE7as+b2rSiXziZE0a3BdvPZ5h2961vOUX=zgvnjgvwPKbCHyg@mail.gmail.com","threadId":"63571","inReplyTo":"xmqqcy9qlfm8.fsf@gitster.g","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-26T23:55:29Z","receivedAt":"2025-07-26T23:55:41Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Thu, Jul 24, 2025 at 3:44 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n>\n> >\n> > * For 1/3 and 2/3, Junio told me that it was concerning to put so\n> >   many calls to `prepare_repo_settings()` so I tried to minimize the\n> >   calls and made sure that there's no useless calling.\n>\n> I didn't mean that the number of places is the problem.  What I\n> found troubling was that this is not done in any central place, so\n> it is hard to notice even if some random cmd_foo() failed to call\n> the function before doing its real work.  For example, shouldn't we\n> be able to, at least for built-in commands that have RUN_SETUP bit\n> set, centrally call prepare_repo_settings() somewhere late in\n> git.c:run_builtin() after we figure out what should be in\n> the_repository?  Now historically, setting up a repository may never\n> have involved opening and parsing tons of configuration files, so\n> such a change may be incurring extra overhead we did not have to\n> pay, so it needs a lot more thought than just trying to minimize the\n> number of calls, but some performance measurement.\n>\n\nI was quite stumped as I don't know what the perfect solution for this\nwould be. I get your point that we have calls to the function all over\nthe place and would take some toll on the performance as well. As you\nsaid that we can probably call the function in git.c:run_builtin() or\nwe can have a call to it in config.c:repo_config() so that just as the\nother settings, we will have our repo_settings parsed, which were once\nparsed through the same function(repo_config() or git_config()) and\nsince all the cmd_*() functions have a call to this, we will also be\nable to call prepare_repo_settings() there itself.\n\n> > * For 3/3, Phillip told me that it broke user-facing as it will be\n> >   parsed quite late in the callchain and might throw an error mid\n> >   operation which we do not want.\n>\n> So has the behaviour change caused by 3/3 been resolved?\n\nWell, I am not parsing it at that place. But, I am relying on an\nalready existing call to prepre_repo_settings() before the function\nusing the setting is called repository.c:repo_read_index(). I tried to\nnarrow down to a cmd_foo() function so that I can shift a call to the\nprepare_repo_settings() from repo_read_index() to it, but this\nfunction is widely called and cannot be narrowed down so I had to\nsettle with it. I'm afraid the issue still isn't completely resolved\n\n>\n> A meta-level comment and a half.\n>\n>  * Please do not use \"-- \" (that is a line that has dash dash and a\n>    single space and nothing else on it) lightly.  It is called\n>    signature line and often MUA pays attention to it when responding\n>    to a message with such a line by omitting everything after it\n>    (which is supposed to be your \"who I am\" advertisement) when\n>    quoting the original.  Since you had one before the \"discussions\n>    since v5\" section and the range-diff, I had to manually resurrect\n>    the part after the signature line while composing this message.\n>\n\nI am sorry for that. I will keep that in mind from next time.\n\n>  * This throws everything in repo_settings, but these settings are\n>    inherently per repository and they are meaningful only when you\n>    are working with a repository.  What makes us choose to make them\n>    new members in the repo_settings structure, not direct members in\n>    the repository structure?\n>\n>    Not an objection and not a suggestion to move them out of the\n>    repo_settings and to the repository proper.  Just wanted to hear\n>    the reasoning behind it (and have the rationale clearly\n>    documented, preferrably in the proposed log messages).\n\nYeah, so what I thought was that if it is a \"core.foo\" setting, I\nwould club it with other core.* settings in the struct repo_settings.\nBut other config settings like in the previous patch series,\n\"extensions.preciousObjects\" or also in this series, the\n\"sparse.expectfilesoutsideofpatterns\", I would put them in some local\ncontext or if they're tied to a repository, I would store them in the\nrepository struct itself. But, as other \"core.sparse_*\" variables are\nstored in the repo_settings, I thought it was better to store the\n\"sparse.expectfilesoutsideofpatterns\" along with them rather than\nstoring it in the repository.\n\nThanks\nAyush\n"},{"id":"522948","messageId":"CAE7as+bnG6KgA8X_n36pqP15bmyM6re+xEb1MOXKvZSUdJ8Arg@mail.gmail.com","threadId":"63571","inReplyTo":"43aaec10-2696-44c9-8728-2045b83dc5d3@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-29T11:36:39Z","receivedAt":"2025-07-29T11:36:54Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"Hey Derrick,\n\nOn Thu, Jul 24, 2025 at 6:55 PM Derrick Stolee <stolee@gmail.com> wrote:\n>\n> On 7/23/25 6:14 PM, Junio C Hamano wrote:\n> > Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n> >\n> >> This patch series aims to remove global variables related to\n> >> sparse-checkout from the global scope and to remove the definition\n> >> '#define USE_THE_REPOSITORY_VARIABLE' from a few files.\n>\n> Sorry that I missed early versions of this thread. It's an\n> interesting topic to me, but I've been distracted.\n>\n\nThanks for joining the discussion!\n\n> >> Discussions since v5:\n> >>\n> >> * For 1/3 and 2/3, Junio told me that it was concerning to put so\n> >>    many calls to `prepare_repo_settings()` so I tried to minimize the\n> >>    calls and made sure that there's no useless calling.\n> >\n> > I didn't mean that the number of places is the problem.  What I\n> > found troubling was that this is not done in any central place, so\n> > it is hard to notice even if some random cmd_foo() failed to call\n> > the function before doing its real work.  For example, shouldn't we\n> > be able to, at least for built-in commands that have RUN_SETUP bit\n> > set, centrally call prepare_repo_settings() somewhere late in\n> > git.c:run_builtin() after we figure out what should be in\n> > the_repository?  Now historically, setting up a repository may never\n> > have involved opening and parsing tons of configuration files, so\n> > such a change may be incurring extra overhead we did not have to\n> > pay, so it needs a lot more thought than just trying to minimize the\n> > number of calls, but some performance measurement.\n>\n> I think that the core issue here (and probably causing the issues\n> that were seen in the user-facing issues) is that the repo settings\n> struct was intended as a place to fill config for some one-off\n> \"feature flags\" and not to replace core functionality for a repo.\n>\n\nOh, that is the complete opposite of what I had understood. I assumed\nthat repo_settings is used to hold some core repository-related config\nsettings, especially since there are already quite a few stored there,\nand shifting these to the struct repository would probably clutter it.\nGiven that the existing configs in the struct repository are mostly\n'repository_format_*' and having Patrick address that we embed the\nrepository_format in the repository as they were increasing[1], it let\nme to think that we should try not to use the repository to store\nthese configs.\n\n> There are two ways to change the approach here to fix the problem\n> of needing prepare_repo_settings() everyhwere:\n>\n>   1. With the idea that these sparse-checkout variables are\n>      critical to the functionality of the repo, they should move\n>      into the repository struct itself and be initialized along\n>      with all other values there. This changes the patches (and my\n>      follow-up series) significantly, but mechanically.\n>\n>   2. If we are going to change the intention of the repo settings\n>      struct to move from \"optional one-off feature flags\" to\n>      \"important information about the core behavior of a repo\"\n>      then we should prepare_repo_settings() when initializing the\n>      repository struct.\n>\n> My preference is (1). The only argument for (2) that I can think\n> of is that it is sometimes helpful to share only the settings for\n> a repo without sharing the whole repo. But that seems like a weak\n> reason right now.\n>\n\nOkay, I agree with your points. I can maybe send a new version to address this.\n\nDo we also shift settings like index.sparse to the repository then?\n\n> >> * For 3/3, Phillip told me that it broke user-facing as it will be\n> >>    parsed quite late in the callchain and might throw an error mid\n> >>    operation which we do not want.\n> >\n> > So has the behaviour change caused by 3/3 been resolved?\n>\n> >   * This throws everything in repo_settings, but these settings are\n> >     inherently per repository and they are meaningful only when you\n> >     are working with a repository.  What makes us choose to make them\n> >     new members in the repo_settings structure, not direct members in\n> >     the repository structure?\n>\n> (This is the same thought I expressed earlier in this message.)\n>\n> Thanks,\n> -Stolee\n>\n\nThanks\nAyush\n"},{"id":"522949","messageId":"a78f4d66-f48c-4ec8-a9e2-cc8443b1d247@gmail.com","threadId":"63571","inReplyTo":"CAE7as+bnG6KgA8X_n36pqP15bmyM6re+xEb1MOXKvZSUdJ8Arg@mail.gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-07-29T12:19:43Z","receivedAt":"2025-07-29T12:19:45Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/29/25 7:36 AM, Ayush Chandekar wrote:\n> Hey Derrick,\n> \n> On Thu, Jul 24, 2025 at 6:55 PM Derrick Stolee <stolee@gmail.com> wrote:\n>>\n>> There are two ways to change the approach here to fix the problem\n>> of needing prepare_repo_settings() everyhwere:\n>>\n>>    1. With the idea that these sparse-checkout variables are\n>>       critical to the functionality of the repo, they should move\n>>       into the repository struct itself and be initialized along\n>>       with all other values there. This changes the patches (and my\n>>       follow-up series) significantly, but mechanically.\n>>\n>>    2. If we are going to change the intention of the repo settings\n>>       struct to move from \"optional one-off feature flags\" to\n>>       \"important information about the core behavior of a repo\"\n>>       then we should prepare_repo_settings() when initializing the\n>>       repository struct.\n>>\n>> My preference is (1). The only argument for (2) that I can think\n>> of is that it is sometimes helpful to share only the settings for\n>> a repo without sharing the whole repo. But that seems like a weak\n>> reason right now.\n>>\n> \n> Okay, I agree with your points. I can maybe send a new version to address this.\n> \n> Do we also shift settings like index.sparse to the repository then?\n\nFor now, it's important to focus this series on the globals being\nconverted. We can come back around to the ideas around removing\nthe settings struct and the prepare_repo_settings() method as a\nseparate series.\n\nThe index.sparse setting is something that is colocated in the\nsettings partly because of its interaction with feature.experimental\nbeing handled in prepare_repo_settings() but also its very isolated\nuse. The sparse checkout globals are much more spread out across the\ncodebase.\n\nThanks,\n-Stolee\n\n"},{"id":"522951","messageId":"CAE7as+Z7mxaMSWb8jrsFP12KU9NPxFu1W-8YhCF-TWE4rZ+LAg@mail.gmail.com","threadId":"63571","inReplyTo":"CAE7as+bnG6KgA8X_n36pqP15bmyM6re+xEb1MOXKvZSUdJ8Arg@mail.gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-07-29T12:53:14Z","receivedAt":"2025-07-29T12:53:26Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Tue, Jul 29, 2025 at 5:06 PM Ayush Chandekar <ayu.chandekar@gmail.com> wrote:\n>\n[snip]\n>\n> Oh, that is the complete opposite of what I had understood. I assumed\n> that repo_settings is used to hold some core repository-related config\n> settings, especially since there are already quite a few stored there,\n> and shifting these to the struct repository would probably clutter it.\n> Given that the existing configs in the struct repository are mostly\n> 'repository_format_*' and having Patrick address that we embed the\n> repository_format in the repository as they were increasing[1], it let\n> me to think that we should try not to use the repository to store\n> these configs.\n>\n\nIt seems that I missed out on adding the reference for [1]\n[1]: https://lore.kernel.org/git/aGPcJMfBCJuQLdtu@pks.im/\n"},{"id":"523001","messageId":"d61c966b-61ae-4ba9-b983-c8dab6e2c292@gmail.com","threadId":"63571","inReplyTo":"43aaec10-2696-44c9-8728-2045b83dc5d3@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-07-30T08:53:21Z","receivedAt":"2025-07-30T08:53:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 24/07/2025 14:25, Derrick Stolee wrote:\n> \n> I think that the core issue here (and probably causing the issues\n> that were seen in the user-facing issues) is that the repo settings\n> struct was intended as a place to fill config for some one-off\n> \"feature flags\" and not to replace core functionality for a repo.\n> \n> There are two ways to change the approach here to fix the problem\n> of needing prepare_repo_settings() everyhwere:\n> \n>   1. With the idea that these sparse-checkout variables are\n>      critical to the functionality of the repo, they should move\n>      into the repository struct itself and be initialized along\n>      with all other values there. This changes the patches (and my\n>      follow-up series) significantly, but mechanically.\n\nPatrick and I had a discussion about calling prepare_repo_settings() \nfrom repo_read_config() recently [1]. It turned out that does not work \nbut I wonder if instead we could change git_default_config() to expect a \nrepository pointer as the callback data and use that to initialize \nthings. That would mean that we would not need to move code out of \ngit_default_config() to remove global variables and we would retain the \n\"last one wins\" behavior when two or more config keys such are \n\"merge.log\" and \"merge.summary\" set the same variable. It would be \nfairly invasive though as we'd need to pass the repository pointer down \nthrough all the other callbacks that end up calling git_default_config().\n\nThanks\n\nPhillip\n\n[1] \nhttps://lore.kernel.org/git/f6479d6a-32a4-4a49-a75c-589978cb9a57@gmail.com/\n\n>   2. If we are going to change the intention of the repo settings\n>      struct to move from \"optional one-off feature flags\" to\n>      \"important information about the core behavior of a repo\"\n>      then we should prepare_repo_settings() when initializing the\n>      repository struct.\n> \n> My preference is (1). The only argument for (2) that I can think\n> of is that it is sometimes helpful to share only the settings for\n> a repo without sharing the whole repo. But that seems like a weak\n> reason right now.\n> \n>>> * For 3/3, Phillip told me that it broke user-facing as it will be\n>>>    parsed quite late in the callchain and might throw an error mid\n>>>    operation which we do not want.\n>>\n>> So has the behaviour change caused by 3/3 been resolved?\n> \n>>   * This throws everything in repo_settings, but these settings are\n>>     inherently per repository and they are meaningful only when you\n>>     are working with a repository.  What makes us choose to make them\n>>     new members in the repo_settings structure, not direct members in\n>>     the repository structure?\n> \n> (This is the same thought I expressed earlier in this message.)\n> \n> Thanks,\n> -Stolee\n> \n> \n\n"},{"id":"523013","messageId":"xmqq1ppxn0al.fsf@gitster.g","threadId":"63571","inReplyTo":"d61c966b-61ae-4ba9-b983-c8dab6e2c292@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-07-30T15:52:34Z","receivedAt":"2025-07-30T15:52:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> ... I wonder if instead we could change git_default_config() to expect\n> a repository pointer as the callback data and use that to initialize\n> things. That would mean that we would not need to move code out of\n> git_default_config() to remove global variables and we would retain\n> the \"last one wins\" behavior when two or more config keys such are\n> \"merge.log\" and \"merge.summary\" set the same variable. It would be\n> fairly invasive though as we'd need to pass the repository pointer\n> down through all the other callbacks that end up calling\n> git_default_config().\n\nSounds very painful, but it does sound like something worthwhile to\ndo.\n\nThanks.\n"},{"id":"523887","messageId":"CAE7as+b2QKcPVnyEupriK54bMSSxdRAmSrMZqTvfq_KabaU-Ug@mail.gmail.com","threadId":"63571","inReplyTo":"cover.1752882401.git.ayu.chandekar@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-08-10T15:36:21Z","receivedAt":"2025-08-10T15:36:32Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"Just an update, I'm still working on this patch series.\n\nThanks,\nAyush\n"},{"id":"524939","messageId":"47d09c43-6d27-40ff-8dbc-22cc4a5949ed@gmail.com","threadId":"63571","inReplyTo":"CAE7as+b2QKcPVnyEupriK54bMSSxdRAmSrMZqTvfq_KabaU-Ug@mail.gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-08-26T12:20:37Z","receivedAt":"2025-08-26T12:20:39Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/10/25 11:36 AM, Ayush Chandekar wrote:\n> Just an update, I'm still working on this patch series.\n\nHi Ayush. Do you have an update on your progress? Perhaps there\nis something you're stuck on and could use some help?\n\nA few weeks ago, I played around with the ideas around updating\nthe location of these globals into the repository struct and\nmade this critical observation:\n\n   It's \"easy\" to move the global into the_repository, but it\n   becomes harder (and changes behavior) if we start referring\n   to the data in each repository struct.\n\nIt may be good to separate the two things into different steps:\n\n  1. Move the globals into the repository struct, but only set\n     or read from the_repository->sparse_checkout[_cone].\n\n  2. Replace the use of the_repository and instead refer to a\n     specific repo. This may change behavior of the feature in\n     the presence of submodules with different config than the\n     root repo (tests before and after will be necessary).\n     We'll also need to update the_repository during the very\n     early config parsing but then update other repos during\n     repo initialization.\n\nDoes this make sense based on your progress in this space?\n\nThanks,\n-Stolee\n\n"},{"id":"525080","messageId":"CAE7as+ZpEwiNsDAozoZXqHRLOF3+hT++uo=mzZqEvTPovQN9uw@mail.gmail.com","threadId":"63571","inReplyTo":"47d09c43-6d27-40ff-8dbc-22cc4a5949ed@gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Ayush Chandekar","fromEmail":"ayu.chandekar@gmail.com","sentAt":"2025-08-27T21:31:45Z","receivedAt":"2025-08-27T21:31:58Z","isPatch":true,"sender":{"key":"ayu.chandekar@gmail.com","avatar":"https://avatars.githubusercontent.com/u/137001939?v=4"},"body":"On Tue, Aug 26, 2025 at 5:50 PM Derrick Stolee <stolee@gmail.com> wrote:\n>\n> On 8/10/25 11:36 AM, Ayush Chandekar wrote:\n> > Just an update, I'm still working on this patch series.\n>\n> Hi Ayush. Do you have an update on your progress? Perhaps there\n> is something you're stuck on and could use some help?\n>\n\nHi Derrick, thanks for checking in!\nI have made a few branches by trying out different ways: [1],[2] & [3]\nI am quite close to sending the patch series now.\n\n> A few weeks ago, I played around with the ideas around updating\n> the location of these globals into the repository struct and\n> made this critical observation:\n>\n>    It's \"easy\" to move the global into the_repository, but it\n>    becomes harder (and changes behavior) if we start referring\n>    to the data in each repository struct.\n>\n> It may be good to separate the two things into different steps:\n>\n>   1. Move the globals into the repository struct, but only set\n>      or read from the_repository->sparse_checkout[_cone].\n>\n>   2. Replace the use of the_repository and instead refer to a\n>      specific repo. This may change behavior of the feature in\n>      the presence of submodules with different config than the\n>      root repo (tests before and after will be necessary).\n>      We'll also need to update the_repository during the very\n>      early config parsing but then update other repos during\n>      repo initialization.\n>\n> Does this make sense based on your progress in this space?\n>\n\nYes, I was able to do the first step, the second step means that I\nhave to pass the repo struct to quite a few functions.\n\n> Thanks,\n> -Stolee\n>\n\nThanks!\nAyush:)\n\n[1]: https://github.com/ayu-ch/git/commits/sparse-checkout-6 (Stored\nthe variables in the 'struct repository' as int, and made a function\nto read their values from the config)\n\n[2]: https://github.com/ayu-ch/git/commits/sparse-checkout-7\n(Christian suggested me that I can also store them as booleans so I\ntried it.)\n\n[3]: https://github.com/ayu-ch/git/commits/sparse-checkout-8 (Similar\nto [1] but set their value as -1 when uninitialized. Tests seem to\nfail though when I make this change.)\n"},{"id":"525637","messageId":"xmqqv7lx56kn.fsf@gitster.g","threadId":"63571","inReplyTo":"CAE7as+ZpEwiNsDAozoZXqHRLOF3+hT++uo=mzZqEvTPovQN9uw@mail.gmail.com","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-05T14:15:20Z","receivedAt":"2025-09-05T14:15:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ayush Chandekar <ayu.chandekar@gmail.com> writes:\n\n>> It may be good to separate the two things into different steps:\n>>\n>>   1. Move the globals into the repository struct, but only set\n>>      or read from the_repository->sparse_checkout[_cone].\n>>\n>>   2. Replace the use of the_repository and instead refer to a\n>>      specific repo. This may change behavior of the feature in\n>>      the presence of submodules with different config than the\n>>      root repo (tests before and after will be necessary).\n>>      We'll also need to update the_repository during the very\n>>      early config parsing but then update other repos during\n>>      repo initialization.\n>>\n>> Does this make sense based on your progress in this space?\n>\n> Yes, I was able to do the first step, the second step means that I\n> have to pass the repo struct to quite a few functions.\n\nAyush, what's the status of this effort?\n\nCurrently a topic by Derrick is built on top of this one, which\nmeans it is stuck waiting for this topic to stabilize.  Should we\nask Derrick to rebuild his topic independent from this topic and let\nit graduate sooner, and when you reroll this series, you'd base\nyours on top of whatever the Git codebase looks like when it\nhappens?\n\nThanks.\n"},{"id":"525650","messageId":"xmqqldms3jwr.fsf@gitster.g","threadId":"63571","inReplyTo":"xmqqv7lx56kn.fsf@gitster.g","subject":"Re: [GSOC PATCH v6 0/3] environment: remove sparse-checkout related global variables","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-05T17:10:12Z","receivedAt":"2025-09-05T17:10:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Ayush, what's the status of this effort?\n>\n> Currently a topic by Derrick is built on top of this one, which\n> means it is stuck waiting for this topic to stabilize.  Should we\n> ask Derrick to rebuild his topic independent from this topic and let\n> it graduate sooner, and when you reroll this series, you'd base\n> yours on top of whatever the Git codebase looks like when it\n> happens?\n\nI tried to (re)adjust Derrick's ds/sparse-checkout-clean topic to\nbuild directly on top of 'master', which involved removing its first\nstep to make it depend on the global core_apply_sparse_checkout and\ncore_sparse_checkout_cone variables, which was not too bad.\n\nThe result is queued on 'seen' I just pushed out.  Derrick, could\nyou take a look to see if I screwed up any?  At least it seems to\npass the tests locally.\n\nI've ejected the ac/deglobal-sparse-variables topic from 'seen' for\nnow, but perhaps it may want to be rebased on Derrick's series when\nit is rerolled.  We'll see how fast the sparse-checkout-clean topic\ncan enter 'next' and graduate, hopefully soon enough.\n\nThanks.\n"}]}