{"thread":{"id":"55966","subject":"[PATCH v3 1/2] config: rename \"submodule\" scope to \"gitmodules\"","startedAt":"2021-06-19T00:32:32Z","lastAt":"2021-06-19T00:32:32Z","messageCount":3,"participants":["Emily Shaffer"],"isPatch":true,"patchVersion":3,"patchTotal":2},"messages":[{"id":"427925","messageId":"20210619003118.1352300-2-emilyshaffer@google.com","threadId":"55966","inReplyTo":"20210619003118.1352300-1-emilyshaffer@google.com","subject":"[PATCH v3 1/2] config: rename \"submodule\" scope to \"gitmodules\"","fromName":"Emily Shaffer","fromEmail":"emilyshaffer@google.com","sentAt":"2021-06-19T00:31:16Z","receivedAt":"2021-06-19T00:32:32Z","isPatch":true,"sender":{"key":"nasamuffin@google.com","avatar":"https://avatars.githubusercontent.com/u/1606826?v=4"},"body":"To prepare for the addition of a new config scope which only applies to\nsubmodule projects, disambiguate \"CONFIG_SCOPE_SUBMODULES\". This scope\nrefers to configs gathered from the .gitmodules file in the\nsuperproject, so just call it \"gitmodules.\"\n\nSigned-off-by: Emily Shaffer <emilyshaffer@google.com>\n---\n config.c           | 4 ++--\n config.h           | 2 +-\n submodule-config.c | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex f9c400ad30..a5fc4cacd5 100644\n--- a/config.c\n+++ b/config.c\n@@ -3516,8 +3516,8 @@ const char *config_scope_name(enum config_scope scope)\n \t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_COMMAND:\n \t\treturn \"command\";\n-\tcase CONFIG_SCOPE_SUBMODULE:\n-\t\treturn \"submodule\";\n+\tcase CONFIG_SCOPE_GITMODULES:\n+\t\treturn \"gitmodules\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/config.h b/config.h\nindex 9038538ffd..5faa72f3f5 100644\n--- a/config.h\n+++ b/config.h\n@@ -42,7 +42,7 @@ enum config_scope {\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_COMMAND,\n-\tCONFIG_SCOPE_SUBMODULE,\n+\tCONFIG_SCOPE_GITMODULES,\n };\n const char *config_scope_name(enum config_scope scope);\n \ndiff --git a/submodule-config.c b/submodule-config.c\nindex 2026120fb3..ed8e671d17 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -637,7 +637,7 @@ static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void\n {\n \tif (repo->worktree) {\n \t\tstruct git_config_source config_source = {\n-\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t\t0, .scope = CONFIG_SCOPE_GITMODULES\n \t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n-- \n2.32.0.288.g62a8d224e6-goog\n\n"},{"id":"427926","messageId":"20210619003118.1352300-1-emilyshaffer@google.com","threadId":"55966","inReplyTo":"20210423001539.4059524-1-emilyshaffer@google.com","subject":"[PATCH v3 0/2] share a config between submodule and superproject","fromName":"Emily Shaffer","fromEmail":"emilyshaffer@google.com","sentAt":"2021-06-19T00:31:15Z","receivedAt":"2021-06-19T00:32:32Z","isPatch":true,"sender":{"key":"nasamuffin@google.com","avatar":"https://avatars.githubusercontent.com/u/1606826?v=4"},"body":"Now based on es/superproject-aware-submodules.\n\nBy using the cached path to the superproject, I was able to drop the\nextra subprocess(es) to find out the superproject's gitdir. That means\nthis change should now be relatively low overhead, and we can discuss\nthings like naming, recursion, etc. to our hearts' content.\n\nSince v2 of this series, I have rebased the series onto\nes/superproject-aware-submodules and made appropriate changes, including\ndropping v2 patches 2 and 3. However, I think this solution answers a\nhandful of the comments on v2:\n\n - dscho asked about submodules who live outside of the superproject's\n   tree; assuming the submodule was created in one of the ways covered\n   by superproject-aware-submodules, it should be a nonissue now.\n - Phillip had comments on patches 2 and 3; they're not necessary to\n   make the tests pass anymore, because there is no longer an additional\n   process cluttering up the traces as a result of this series.\n\nI did not address Phillip's comment about breaking scripts by changing\nthe config scope name, but I think it's probably valid, so maybe patch 1\nalso should go (or be replaced by a robust comment).\n\nI'm hoping this can also serve as a nice example of what\nhttps://lore.kernel.org/git/20210616004508.87186-1-emilyshaffer@google.com\ncan enable.\n\nHappy CI: https://github.com/nasamuffin/git/actions/runs/951382014\n\nThanks,\n - Emily\n\nEmily Shaffer (2):\n  config: rename \"submodule\" scope to \"gitmodules\"\n  config: add 'config.superproject' file\n\n Documentation/git-config.txt   |  21 +++++-\n builtin/config.c               |   9 ++-\n config.c                       |  32 ++++++++-\n config.h                       |   5 +-\n submodule-config.c             |   2 +-\n t/t1311-superproject-config.sh | 116 +++++++++++++++++++++++++++++++++\n 6 files changed, 178 insertions(+), 7 deletions(-)\n create mode 100755 t/t1311-superproject-config.sh\n\nRange-diff against v2:\n1:  785f961f4c = 1:  cddd53e33a config: rename \"submodule\" scope to \"gitmodules\"\n2:  b4d853e261 ! 2:  3eaca59b65 config: add 'config.superproject' file\n    @@ builtin/config.c: static struct option builtin_config_options[] = {\n      \tOPT_STRING('f', \"file\", &given_config_source.file, N_(\"file\"), N_(\"use given config file\")),\n     @@ builtin/config.c: int cmd_config(int argc, const char **argv, const char *prefix)\n      \telse if (use_system_config) {\n    - \t\tgiven_config_source.file = git_etc_gitconfig();\n    + \t\tgiven_config_source.file = git_system_config();\n      \t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n     +\t} else if (use_superproject_config) {\n     +\t\tstruct strbuf superproject_cfg = STRBUF_INIT;\n    @@ config.c\n      \n      struct config_source {\n      \tstruct config_source *prev;\n    -@@ config.c: const char *git_etc_gitconfig(void)\n    - \treturn system_wide;\n    +@@ config.c: void git_global_config(char **user_out, char **xdg_out)\n    + \t*xdg_out = xdg_config;\n      }\n      \n     +void git_config_superproject(struct strbuf *sb, const char *gitdir)\n     +{\n    -+\tif (!get_superproject_gitdir(sb))\n    -+\t\t/* not a submodule */\n    ++\tconst char *sp_gitdir;\n    ++\tif (git_config_get_string_tmp(\"submodule.superprojectGitDir\", &sp_gitdir))\n    ++\t\t/* probably not a submodule */\n     +\t\tstrbuf_addstr(sb, gitdir);\n    ++\telse\n    ++\t\t/* definitely a submodule */\n    ++\t\tstrbuf_addstr(sb, sp_gitdir);\n     +\n     +\tstrbuf_addstr(sb, \"/config.superproject\");\n     +}\n    @@ config.h: typedef int (*config_parser_event_fn_t)(enum config_event_t type,\n      \tunsigned int ignore_worktree : 1;\n      \tunsigned int ignore_cmdline : 1;\n      \tunsigned int system_gently : 1;\n    -@@ config.h: int git_config_rename_section_in_file(const char *, const char *, const char *);\n    +@@ config.h: int git_config_rename_section(const char *, const char *);\n    + int git_config_rename_section_in_file(const char *, const char *, const char *);\n      int git_config_copy_section(const char *, const char *);\n      int git_config_copy_section_in_file(const char *, const char *, const char *);\n    - const char *git_etc_gitconfig(void);\n     +void git_config_superproject(struct strbuf *, const char *);\n      int git_env_bool(const char *, int);\n      unsigned long git_env_ulong(const char *, unsigned long);\n      int git_config_system(void);\n     \n    - ## submodule.c ##\n    -@@ submodule.c: void absorb_git_dir_into_superproject(const char *path,\n    - \t}\n    - }\n    - \n    -+int get_superproject_gitdir(struct strbuf *buf)\n    -+{\n    -+\tstruct strbuf sb = STRBUF_INIT;\n    -+\tstruct child_process cp = CHILD_PROCESS_INIT;\n    -+\tint rc = 0;\n    -+\n    -+\t/* NEEDSWORK: this call also calls out to a subprocess! */\n    -+\trc = get_superproject_working_tree(&sb);\n    -+\tstrbuf_release(&sb);\n    -+\n    -+\tif (!rc)\n    -+\t\treturn rc;\n    -+\n    -+\tprepare_submodule_repo_env_no_git_dir(&cp.env_array);\n    -+\n    -+\tstrvec_pushl(&cp.args, \"-C\", \"..\", \"rev-parse\", \"--absolute-git-dir\", NULL);\n    -+\tcp.git_cmd = 1;\n    -+\n    -+\trc = capture_command(&cp, buf, 0);\n    -+\tstrbuf_trim_trailing_newline(buf);\n    -+\n    -+\t/* leave buf empty if we didn't have a superproject gitdir */\n    -+\tif (rc)\n    -+\t\tstrbuf_reset(buf);\n    -+\n    -+\t/* rc reflects the exit code of the rev-parse; invert into a bool */\n    -+\treturn !rc;\n    -+}\n    -+\n    - int get_superproject_working_tree(struct strbuf *buf)\n    - {\n    - \tstruct child_process cp = CHILD_PROCESS_INIT;\n    -\n    - ## submodule.h ##\n    -@@ submodule.h: void prepare_submodule_repo_env(struct strvec *out);\n    - void absorb_git_dir_into_superproject(const char *path,\n    - \t\t\t\t      unsigned flags);\n    - \n    -+/*\n    -+ * Return the gitdir of the superproject, which this project is a submodule of.\n    -+ * If this repository is a submodule, return 1 and fill buf with the absolute\n    -+ * path to the superproject's gitdir. If this repository is not a submodule of\n    -+ * another repository, return 0 and leave buf untouched.\n    -+ */\n    -+int get_superproject_gitdir(struct strbuf *buf);\n    -+\n    - /*\n    -  * Return the absolute path of the working tree of the superproject, which this\n    -  * project is a submodule of. If this repository is not a submodule of\n    -\n      ## t/t1311-superproject-config.sh (new) ##\n     @@\n     +#!/bin/sh\n-- \n2.32.0.288.g62a8d224e6-goog\n\n"},{"id":"427927","messageId":"20210619003118.1352300-3-emilyshaffer@google.com","threadId":"55966","inReplyTo":"20210619003118.1352300-1-emilyshaffer@google.com","subject":"[PATCH v3 2/2] config: add 'config.superproject' file","fromName":"Emily Shaffer","fromEmail":"emilyshaffer@google.com","sentAt":"2021-06-19T00:31:17Z","receivedAt":"2021-06-19T00:32:32Z","isPatch":true,"sender":{"key":"nasamuffin@google.com","avatar":"https://avatars.githubusercontent.com/u/1606826?v=4"},"body":"Some configs, such as wrapper directives like gerrit.createChangeId, or\nforthcoming hook configs, should apply to a superproject as well as all\nits submodules. It may not be appropriate to apply them globally - for\nexample, if the user also contributes to many projects which do not use\nthe configs necessary for one project-with-submodules - and it may be\nburdensome to apply them locally to the superproject and each of its\nsubmodules. Even if the user runs 'git submodule foreach \"git config\n--local foo.bar', if a new submodule is added later on, that config is\nnot applied to the new submodule.\n\nIt is also inappropriate to share the entire superproject config, since\nsome items - like remote URLs or partial-clone filters - would not apply\nto a submodule.\n\nTo make life easier for projects with many submodules, then, create a\nnew \"config.superproject\" config scope, which is included in the config\nparse for the superproject as well as for all the submodules of that\nsuperproject.\n\nFor the superproject, this new config file is equally local to the local\nconfig; for the submodule, the new config file is less local than the\nlocal config. So let's include it directly before the local config\nduring the config parse.\n\nSigned-off-by: Emily Shaffer <emilyshaffer@google.com>\n---\n\nNotes:\n    Since v1:\n    \n    - Used test_when_finished liberally in tests instead of bare cleanup steps\n    - Fixed some nits regarding xstrdup instead of strbuf_detach.\n    \n    One thing that I thought about but did not implement: rather than finding the\n    path to the superproject's gitdir, you could imagine gathering the config by\n    making a call out to 'git -C ../ config' - but on second thought, it seems like\n    that will make it harder to edit. However, if we don't want to be able to edit\n    superproject config from a submodule, that might be okay... (This approach could\n    make 'git config --show-origin' harder to implement, though, I think.) So I did\n    not make any changes about that.\n\n Documentation/git-config.txt   |  21 +++++-\n builtin/config.c               |   9 ++-\n config.c                       |  28 ++++++++\n config.h                       |   3 +\n t/t1311-superproject-config.sh | 116 +++++++++++++++++++++++++++++++++\n 5 files changed, 174 insertions(+), 3 deletions(-)\n create mode 100755 t/t1311-superproject-config.sh\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 5cddadafd2..312deea21d 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -48,7 +48,7 @@ unset an existing `--type` specifier with `--no-type`.\n \n When reading, the values are read from the system, global and\n repository local configuration files by default, and options\n-`--system`, `--global`, `--local`, `--worktree` and\n+`--system`, `--global`, `--superproject`, `--local`, `--worktree` and\n `--file <filename>` can be used to tell the command to read from only\n that location (see <<FILES>>).\n \n@@ -127,6 +127,17 @@ rather than from all available files.\n +\n See also <<FILES>>.\n \n+--superproject::\n+\tFor writing options: write to the superproject's\n+\t`.git/config.superproject` file, even if run from a submodule of that\n+\tsuperproject.\n++\n+For reading options: read only from the superproject's\n+`.git/config.superproject` file, even if run from a submodule of that\n+superproject, rather than from all available files.\n++\n+See also <<FILES>>.\n+\n --local::\n \tFor writing options: write to the repository `.git/config` file.\n \tThis is the default behavior.\n@@ -283,7 +294,7 @@ The default is to use a pager.\n FILES\n -----\n \n-If not set explicitly with `--file`, there are four files where\n+If not set explicitly with `--file`, there are five files where\n 'git config' will search for configuration options:\n \n $(prefix)/etc/gitconfig::\n@@ -301,6 +312,12 @@ $XDG_CONFIG_HOME/git/config::\n \tUser-specific configuration file. Also called \"global\"\n \tconfiguration file.\n \n+$GIT_DIR/config.superproject::\n+\tWhen `git config` is run from a project which is a submodule of another\n+\tproject, that superproject's $GIT_DIR will be used. Use this config file\n+\tto set configurations which need to be the same across a superproject\n+\tand all its submodules.\n+\n $GIT_DIR/config::\n \tRepository specific configuration file.\n \ndiff --git a/builtin/config.c b/builtin/config.c\nindex 865fddd6ce..83376e0916 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -26,7 +26,7 @@ static char key_delim = ' ';\n static char term = '\\n';\n \n static int use_global_config, use_system_config, use_local_config;\n-static int use_worktree_config;\n+static int use_worktree_config, use_superproject_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n@@ -130,6 +130,8 @@ static struct option builtin_config_options[] = {\n \tOPT_GROUP(N_(\"Config file location\")),\n \tOPT_BOOL(0, \"global\", &use_global_config, N_(\"use global config file\")),\n \tOPT_BOOL(0, \"system\", &use_system_config, N_(\"use system config file\")),\n+\tOPT_BOOL(0, \"superproject\",\n+\t\t &use_superproject_config, N_(\"use superproject config file\")),\n \tOPT_BOOL(0, \"local\", &use_local_config, N_(\"use repository config file\")),\n \tOPT_BOOL(0, \"worktree\", &use_worktree_config, N_(\"use per-worktree config file\")),\n \tOPT_STRING('f', \"file\", &given_config_source.file, N_(\"file\"), N_(\"use given config file\")),\n@@ -697,6 +699,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \telse if (use_system_config) {\n \t\tgiven_config_source.file = git_system_config();\n \t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_superproject_config) {\n+\t\tstruct strbuf superproject_cfg = STRBUF_INIT;\n+\t\tgit_config_superproject(&superproject_cfg, get_git_dir());\n+\t\tgiven_config_source.file = strbuf_detach(&superproject_cfg, NULL);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SUPERPROJECT;\n \t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n \t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\ndiff --git a/config.c b/config.c\nindex a5fc4cacd5..97d63a825c 100644\n--- a/config.c\n+++ b/config.c\n@@ -21,6 +21,7 @@\n #include \"dir.h\"\n #include \"color.h\"\n #include \"refs.h\"\n+#include \"submodule.h\"\n \n struct config_source {\n \tstruct config_source *prev;\n@@ -1852,6 +1853,19 @@ void git_global_config(char **user_out, char **xdg_out)\n \t*xdg_out = xdg_config;\n }\n \n+void git_config_superproject(struct strbuf *sb, const char *gitdir)\n+{\n+\tconst char *sp_gitdir;\n+\tif (git_config_get_string_tmp(\"submodule.superprojectGitDir\", &sp_gitdir))\n+\t\t/* probably not a submodule */\n+\t\tstrbuf_addstr(sb, gitdir);\n+\telse\n+\t\t/* definitely a submodule */\n+\t\tstrbuf_addstr(sb, sp_gitdir);\n+\n+\tstrbuf_addstr(sb, \"/config.superproject\");\n+}\n+\n /*\n  * Parse environment variable 'k' as a boolean (in various\n  * possible spellings); if missing, use the default value 'def'.\n@@ -1911,6 +1925,17 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n+\tcurrent_parsing_scope = CONFIG_SCOPE_SUPERPROJECT;\n+\tif (opts->git_dir && !opts->ignore_superproject) {\n+\n+\t\tstruct strbuf superproject_gitdir = STRBUF_INIT;\n+\t\tgit_config_superproject(&superproject_gitdir, opts->git_dir);\n+\t\tif (!access_or_die(superproject_gitdir.buf, R_OK, 0))\n+\t\t\tret += git_config_from_file(fn, superproject_gitdir.buf, data);\n+\n+\t\tstrbuf_release(&superproject_gitdir);\n+\t}\n+\n \tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n@@ -2030,6 +2055,7 @@ void read_very_early_config(config_fn_t cb, void *data)\n \n \topts.respect_includes = 1;\n \topts.ignore_repo = 1;\n+\topts.ignore_superproject = 1;\n \topts.ignore_worktree = 1;\n \topts.ignore_cmdline = 1;\n \topts.system_gently = 1;\n@@ -3518,6 +3544,8 @@ const char *config_scope_name(enum config_scope scope)\n \t\treturn \"command\";\n \tcase CONFIG_SCOPE_GITMODULES:\n \t\treturn \"gitmodules\";\n+\tcase CONFIG_SCOPE_SUPERPROJECT:\n+\t\treturn \"superproject\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/config.h b/config.h\nindex 5faa72f3f5..69d7e4cb72 100644\n--- a/config.h\n+++ b/config.h\n@@ -43,6 +43,7 @@ enum config_scope {\n \tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_COMMAND,\n \tCONFIG_SCOPE_GITMODULES,\n+\tCONFIG_SCOPE_SUPERPROJECT,\n };\n const char *config_scope_name(enum config_scope scope);\n \n@@ -84,6 +85,7 @@ typedef int (*config_parser_event_fn_t)(enum config_event_t type,\n struct config_options {\n \tunsigned int respect_includes : 1;\n \tunsigned int ignore_repo : 1;\n+\tunsigned int ignore_superproject : 1;\n \tunsigned int ignore_worktree : 1;\n \tunsigned int ignore_cmdline : 1;\n \tunsigned int system_gently : 1;\n@@ -318,6 +320,7 @@ int git_config_rename_section(const char *, const char *);\n int git_config_rename_section_in_file(const char *, const char *, const char *);\n int git_config_copy_section(const char *, const char *);\n int git_config_copy_section_in_file(const char *, const char *, const char *);\n+void git_config_superproject(struct strbuf *, const char *);\n int git_env_bool(const char *, int);\n unsigned long git_env_ulong(const char *, unsigned long);\n int git_config_system(void);\ndiff --git a/t/t1311-superproject-config.sh b/t/t1311-superproject-config.sh\nnew file mode 100755\nindex 0000000000..74b6ca2cac\n--- /dev/null\n+++ b/t/t1311-superproject-config.sh\n@@ -0,0 +1,116 @@\n+#!/bin/sh\n+\n+test_description='Test git config --superproject in different settings'\n+\n+. ./test-lib.sh\n+\n+# follow t7400's example and use the trash dir repo as a submodule to add\n+submodurl=$(pwd -P)\n+\n+# since only the configs are modified, set up the repo structure only once\n+test_expect_success 'setup repo structure' '\n+\ttest_commit \"base\" &&\n+\tgit submodule add \"${submodurl}\" sub/ &&\n+\tgit commit -m \"add a submodule\"\n+'\n+\n+test_expect_success 'superproject config applies to super and submodule' '\n+\tcat >.git/config.superproject <<-EOF &&\n+\t[foo]\n+\t\tbar = baz\n+\tEOF\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --get foo.bar &&\n+\tgit -C sub config --get foo.bar\n+\n+'\n+\n+test_expect_success 'can add from super or sub' '\n+\tgit config --superproject apple.species honeycrisp &&\n+\tgit -C sub config --superproject banana.species cavendish &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tcat >expect <<-EOF &&\n+\tapple.species=honeycrisp\n+\tbanana.species=cavendish\n+\tEOF\n+\n+\tgit config --list >actual &&\n+\tgrep -Ff expect actual &&\n+\n+\tgit -C sub config --list >actual &&\n+\tgrep -Ff expect actual\n+'\n+\n+test_expect_success 'can --unset from super or sub' '\n+\tgit config --superproject apple.species honeycrisp &&\n+\tgit -C sub config --superproject banana.species cavendish &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --unset --superproject banana.species &&\n+\tgit -C sub config --unset --superproject apple.species\n+'\n+\n+test_expect_success 'can --edit superproject config' '\n+\ttest_config core.editor \"echo [foo]bar=baz >\" &&\n+\tgit config --edit --superproject &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --get foo.bar\n+'\n+\n+test_expect_success 'can --show-origin the superproject config' '\n+\tgit config --superproject --add foo.bar baz &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --list --show-origin >actual &&\n+\tgrep -F \"config.superproject\" actual\n+'\n+\n+test_expect_success 'can --show-scope the superproject config' '\n+\tgit config --superproject --add foo.bar baz &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --list --show-scope >actual &&\n+\tgrep \"superproject\" actual\n+'\n+\n+test_expect_success 'pre-existing config applies to new submodule' '\n+\tgit config --superproject --add foo.bar baz &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit submodule add \"${submodurl}\" sub2/ &&\n+\ttest_when_finished rm -fr sub2 &&\n+\tgit commit -m \"add a second submodule\" &&\n+\ttest_when_finished git reset HEAD^ &&\n+\n+\tgit -C sub2 config --get foo.bar\n+'\n+\n+# NEEDSWORK: submodule.c:get_superproject_working_tree doesn't support worktree\n+test_expect_failure 'worktrees can still access config.superproject' '\n+\tgit config --superproject --add foo.bar baz &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit worktree add wt &&\n+\ttest_when_finished git worktree remove wt &&\n+\t(\n+\t\tcd wt &&\n+\t\tgit config --get foo.bar\n+\t)\n+'\n+\n+# This test deletes the submodule! Keep it at the end of the test suite.\n+test_expect_success 'config.superproject works even with no submodules' '\n+\t# get rid of the submodule\n+\tgit reset HEAD^ &&\n+\trm -fr sub &&\n+\n+\tgit config --superproject --add foo.bar baz &&\n+\ttest_when_finished rm .git/config.superproject &&\n+\n+\tgit config --get foo.bar\n+'\n+\n+test_done\n-- \n2.32.0.288.g62a8d224e6-goog\n\n"}]}