{"thread":{"id":"45207","subject":"[PATCH 06/10] submodule add: respect submodule.active","startedAt":"2017-02-23T23:49:03Z","lastAt":"2017-03-18T17:01:00Z","messageCount":123,"participants":["Brandon Williams","Stefan Beller","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"312472","messageId":"20170223234728.164111-7-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 06/10] submodule add: respect submodule.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:24Z","receivedAt":"2017-02-23T23:49:03Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"When submodule.active is configured, in addition to adding\nsubmodule.\"<name>\".url to the config, add the path of the added\nsubmodule if it isn't already covered by the current config values.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh               | 11 +++++++++++\n t/t7413-submodule-is-active.sh | 22 ++++++++++++++++++++++\n 2 files changed, 33 insertions(+)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex e5b9a8920..4633a4336 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -271,6 +271,17 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n+\n+\tif git config --get submodule.active >/dev/null\n+\tthen\n+\t\t# If the submodule being adding isn't already covered by the\n+\t\t# current configured pathspec, add the submodule's path to\n+\t\t# 'submodule.active'\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tgit config --add submodule.active \"$sm_path\"\n+\t\tfi\n+\tfi\n }\n \n #\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex 683487020..8a519163b 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -60,4 +60,26 @@ test_expect_success 'is-active works with exclusions in submodule.active config'\n \tgit -C super config --unset-all submodule.active\n '\n \n+test_expect_success 'is-active and submodule add' '\n+\ttest_when_finished \"rm -rf super2\" &&\n+\tgit init super2 &&\n+\ttest_commit -C super2 initial &&\n+\tgit -C super2 config --add submodule.active \"sub*\" &&\n+\n+\tcat >expect <<-\\EOF &&\n+\tsub*\n+\tEOF\n+\tgit -C super2 submodule add ../sub sub1 &&\n+\tgit -C super2 config --get-all submodule.active >actual &&\n+\ttest_cmp actual expect &&\n+\n+\tcat >expect <<-\\EOF &&\n+\tsub*\n+\tmod\n+\tEOF\n+\tgit -C super2 submodule add ../sub mod &&\n+\tgit -C super2 config --get-all submodule.active >actual &&\n+\ttest_cmp actual expect\n+'\n+\n test_done\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312473","messageId":"20170223234728.164111-1-bmwill@google.com","threadId":"45207","inReplyTo":null,"subject":"[PATCH 00/10] decoupling a submodule's existence and its url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:18Z","receivedAt":"2017-02-23T23:49:05Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"There are two motivations for decoupling a submodule's existence from the url\nthat is stored in .git/config.\n\n1. Worktrees can't really be used with submodules since the existence is\n   checked based on the shared .git/config.  This means that two different\n   worktress have to have the same initialized submodules.  By decoupling a\n   submodule's existence from the url, two different work trees can be\n   configured to have different submodules checked out.\n2. Easily configure gorups of submodules that a user is interested in.  In a\n   repository with hundreds of submodules it would be difficult to easily tell git\n   which modules to worry about without having to individually init all of\n   them.  Instead, a pathspec can be used to more easily select or deselect\n   groups of submodules.\n\nThis patch series works to do this decoupling and instead allows a user to\nconfigure submodule.active with a pathspec to use to check if a submodule is\ninitialized.\n\nBrandon Williams (10):\n  submodule: decouple url and submodule existence\n  submodule update: add `--init-active` switch\n  clone: add --submodule-spec=<pathspec> switch\n  completion: clone can initialize specific submodules\n  submodule--helper: add is_active command\n  submodule add: respect submodule.active\n  submodule status: use submodule--helper is-active\n  submodule deinit: use most reliable url\n  submodule sync: use submodule--helper is-active\n  submodule--helper clone: check for configured submodules using helper\n\n Documentation/git-clone.txt            |  23 ++++---\n Documentation/git-submodule.txt        |  11 +++-\n builtin/clone.c                        |  36 ++++++++++-\n builtin/submodule--helper.c            |  22 ++++---\n contrib/completion/git-completion.bash |   1 +\n git-submodule.sh                       |  39 +++++++++---\n submodule.c                            |  25 +++++++-\n t/t7400-submodule-basic.sh             | 109 +++++++++++++++++++++++++++++++++\n t/t7413-submodule-is-active.sh         |  85 +++++++++++++++++++++++++\n 9 files changed, 323 insertions(+), 28 deletions(-)\n create mode 100755 t/t7413-submodule-is-active.sh\n\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312474","messageId":"20170223234728.164111-10-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 09/10] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:27Z","receivedAt":"2017-02-23T23:49:10Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 02b85dceb..f35345775 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1127,7 +1127,7 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tif git submodule--helper is-active \"$sm_path\"\n \t\tthen\n \t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312475","messageId":"20170223234728.164111-5-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 04/10] completion: clone can initialize specific submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:22Z","receivedAt":"2017-02-23T23:49:11Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n contrib/completion/git-completion.bash | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6721ff80f..4e473aa90 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1138,6 +1138,7 @@ _git_clone ()\n \t\t\t--single-branch\n \t\t\t--branch\n \t\t\t--recurse-submodules\n+\t\t\t--submodule-spec\n \t\t\t\"\n \t\treturn\n \t\t;;\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312476","messageId":"20170223234728.164111-2-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:19Z","receivedAt":"2017-02-23T23:49:13Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Currently the submodule.<name>.url config option is used to determine\nif a given submodule exists and is interesting to the user.  This\nhowever doesn't work very well because the URL is a config option for\nthe scope of a repository, whereas the existence of a submodule is an\noption scoped to the working tree.\n\nIn a future with worktree support for submodules, there will be multiple\nworking trees, each of which may only need a subset of the submodules\nchecked out.  The URL (which is where the submodule repository can be\nobtained) should not differ between different working trees.\n\nIt may also be convenient for users to more easily specify groups of\nsubmodules they are interested in as apposed to running \"git submodule\ninit <path>\" on each submodule they want checked out in their working\ntree.\n\nTo this end, the config option submodule.active is introduced which\nholds a pathspec that specifies which submodules should exist in the\nworking tree.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n submodule.c | 25 ++++++++++++++++++++++---\n 1 file changed, 22 insertions(+), 3 deletions(-)\n\ndiff --git a/submodule.c b/submodule.c\nindex 4c4f033e8..991066ddf 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -217,11 +217,16 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tconst struct submodule *module = NULL;\n+\tconst struct string_list *sl;\n+\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n-\tmodule = submodule_from_path(null_sha1, path);\n+\t/* early return if there isn't a path->module mapping */\n+\tif (!module)\n+\t\treturn 0;\n+\n+\tsl = git_config_get_value_multi(\"submodule.active\");\n \n-\tif (module) {\n+\tif (!sl) {\n \t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n \t\tchar *value = NULL;\n \n@@ -229,6 +234,20 @@ int is_submodule_initialized(const char *path)\n \n \t\tfree(value);\n \t\tfree(key);\n+\t} else {\n+\t\tstruct pathspec ps;\n+\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n+\t\tconst struct string_list_item *item;\n+\n+\t\tfor_each_string_list_item(item, sl) {\n+\t\t\targv_array_push(&args, item->string);\n+\t\t}\n+\n+\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n+\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n+\n+\t\targv_array_clear(&args);\n+\t\tclear_pathspec(&ps);\n \t}\n \n \treturn ret;\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312477","messageId":"20170223234728.164111-4-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 03/10] clone: add --submodule-spec=<pathspec> switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:21Z","receivedAt":"2017-02-23T23:49:14Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch passes the pathspec to `git submodule update\n--init-active` which is called after the actual clone is done.\n\nAdditionally this configures the submodule.active option to\nbe the given pathspec, such that any future invocation of\n`git submodule update --init-active` will keep up\nwith the pathspec.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-clone.txt | 23 ++++++++++-----\n builtin/clone.c             | 36 +++++++++++++++++++++--\n t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 120 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 35cc34b2f..9692eab30 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -15,7 +15,8 @@ SYNOPSIS\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n \t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n-\t  [--jobs <n>] [--] <repository> [<directory>]\n+\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n+\t  <repository> [<directory>]\n \n DESCRIPTION\n -----------\n@@ -217,12 +218,20 @@ objects from the source repository into a pack in the cloned repository.\n \n --recursive::\n --recurse-submodules::\n-\tAfter the clone is created, initialize all submodules within,\n-\tusing their default settings. This is equivalent to running\n-\t`git submodule update --init --recursive` immediately after\n-\tthe clone is finished. This option is ignored if the cloned\n-\trepository does not have a worktree/checkout (i.e. if any of\n-\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\tAfter the clone is created, initialize and clone all submodules\n+\twithin, using their default settings. This is equivalent to\n+\trunning `git submodule update --recursive --init` immediately\n+\tafter the clone is finished. This option is ignored if the\n+\tcloned repository does not have a worktree/checkout (i.e.  if\n+\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\n+--submodule-spec::\n+\tAfter the clone is created, initialize and clone specified\n+\tsubmodules within, using their default settings. It is possible\n+\tto give multiple specifications by giving this argument multiple\n+\ttimes. This is equivalent to configuring `submodule.active`\n+\tand then running `git submodule update --init-active`\n+\timmediately after the clone is finished.\n \n --[no-]shallow-submodules::\n \tAll submodules which are cloned will be shallow with a depth of 1.\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 5ef81927a..15a8d3ef0 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -56,6 +56,16 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list submodule_spec;\n+\n+static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\treturn -1;\n+\n+\tstring_list_append((struct string_list *)opt->value, arg);\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -112,6 +122,9 @@ static struct option builtin_clone_options[] = {\n \t\t\tTRANSPORT_FAMILY_IPV4),\n \tOPT_SET_INT('6', \"ipv6\", &family, N_(\"use IPv6 addresses only\"),\n \t\t\tTRANSPORT_FAMILY_IPV6),\n+\tOPT_CALLBACK(0, \"submodule-spec\", &submodule_spec, N_(\"<pathspec>\"),\n+\t\t\tN_(\"clone specific submodules. Pass multiple times for complex pathspecs\"),\n+\t\t\tsubmodule_spec_cb),\n \tOPT_END()\n };\n \n@@ -733,13 +746,21 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && option_recursive) {\n+\tif (!err && (option_recursive || submodule_spec.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n-\t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n+\t\targv_array_pushl(&args, \"submodule\", \"update\", NULL);\n+\n+\t\tif (submodule_spec.nr > 0)\n+\t\t\targv_array_pushf(&args, \"--init-active\");\n+\t\telse\n+\t\t\targv_array_pushf(&args, \"--init\");\n \n \t\tif (option_shallow_submodules == 1)\n \t\t\targv_array_push(&args, \"--depth=1\");\n \n+\t\tif (option_recursive)\n+\t\t\targv_array_pushf(&args, \"--recursive\");\n+\n \t\tif (max_jobs != -1)\n \t\t\targv_array_pushf(&args, \"--jobs=%d\", max_jobs);\n \n@@ -887,6 +908,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\toption_no_checkout = 1;\n \t}\n \n+\tif (submodule_spec.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tfor_each_string_list_item(item, &submodule_spec) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\t}\n+\n \tif (!option_origin)\n \t\toption_origin = \"origin\";\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex f5df0a5b4..39364ef68 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1156,4 +1156,74 @@ test_expect_success 'submodule update --init-active' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'clone --submodule-spec works' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expected <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t-sub2\n+\t-sub3\n+\tEOF\n+\n+\tgit clone --recurse-submodules --submodule-spec=\"sub0\" multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'clone with multiple --submodule-spec options' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expect <<-\\EOF &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat <<-\\EOF >expect &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tcat <<-\\EOF >expect2 &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\t-sub4\n+\t sub5 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  --submodule-spec \":(exclude)sub4\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit -C multisuper submodule add ../sub1 sub4 &&\n+\tgit -C multisuper submodule add ../sub1 sub5 &&\n+\tgit -C multisuper commit -m \"add more submodules\" &&\n+\t# obtain the new superproject\n+\tgit -C multisuper_clone pull &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect2 actual\n+'\n+\n test_done\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312478","messageId":"20170223234728.164111-8-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 07/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:25Z","receivedAt":"2017-02-23T23:49:15Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 4633a4336..f8adfb179 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1026,14 +1026,13 @@ cmd_status()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n \t\t\tcontinue\n \t\tfi\n-\t\tif test -z \"$url\" ||\n+\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n \t\t{\n \t\t\t! test -d \"$sm_path\"/.git &&\n \t\t\t! test -f \"$sm_path\"/.git\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312479","messageId":"20170223234728.164111-9-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 08/10] submodule deinit: use most reliable url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:26Z","receivedAt":"2017-02-23T23:49:22Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The user could have configured the submodule to have a different URL\nfrom the one in the superproject's config.  To account for this read\nwhat the submodule has configured for remote.origin.url and use that\ninstead.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex f8adfb179..02b85dceb 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -466,7 +466,7 @@ Submodule work tree '\\$displaypath' contains a .git directory\n \t\tthen\n \t\t\t# Remove the whole section so we have a clean state when\n \t\t\t# the user later decides to init this submodule again\n-\t\t\turl=$(git config submodule.\"$name\".url)\n+\t\t\turl=$(GIT_DIR=\"$(git rev-parse --git-path modules/$name)\" git config remote.origin.url)\n \t\t\tgit config --remove-section submodule.\"$name\" 2>/dev/null &&\n \t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n \t\tfi\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312480","messageId":"20170223234728.164111-11-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 10/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:28Z","receivedAt":"2017-02-23T23:49:23Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Use the 'is_submodule_initialized()' helper to check for configured\nsubmodules instead of manually checking for the submodule's URL in the\nconfig.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 11 +++--------\n 1 file changed, 3 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex dac02604d..68d21b600 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -760,7 +760,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstruct strbuf displaypath_sb = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *displaypath = NULL;\n-\tchar *url = NULL;\n \tint needs_cloning = 0;\n \n \tif (ce_stage(ce)) {\n@@ -795,14 +794,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t}\n \n \t/*\n-\t * Looking up the url in .git/config.\n+\t * Check if the submodule has been initialized.\n \t * We must not fall back to .gitmodules as we only want\n \t * to process configured submodules.\n \t */\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n-\tgit_config_get_string(sb.buf, &url);\n-\tif (!url) {\n+\tif (!is_submodule_initialized(ce->name)) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n \t\tgoto cleanup;\n \t}\n@@ -836,7 +832,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, \"--depth=1\");\n \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n-\targv_array_pushl(&child->args, \"--url\", url, NULL);\n+\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n \tif (suc->references.nr) {\n \t\tstruct string_list_item *item;\n \t\tfor_each_string_list_item(item, &suc->references)\n@@ -846,7 +842,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, suc->depth);\n \n cleanup:\n-\tfree(url);\n \tstrbuf_reset(&displaypath_sb);\n \tstrbuf_reset(&sb);\n \n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312481","messageId":"20170223234728.164111-3-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 02/10] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:20Z","receivedAt":"2017-02-23T23:49:26Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch `--init-active` initializes the submodules which are\nconfigured in `submodule.active` instead of those given as\ncommand line arguments before updating. In the first implementation this\nis made incompatible with further command line arguments as it is\nunclear what the user means by\n\n    git submodule update --init --init-active <paths>\n\nThis new switch allows users to record more complex patterns as it saves\nretyping them whenever you invoke update.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-submodule.txt | 11 ++++++++++-\n git-submodule.sh                | 21 ++++++++++++++++++---\n t/t7400-submodule-basic.sh      | 39 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 67 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 918bd1d1b..626b9760a 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,7 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n-'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]\n+'git submodule' [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch]\n \t      [--[no-]recommend-shallow] [-f|--force] [--rebase|--merge]\n \t      [--reference <repository>] [--depth <depth>] [--recursive]\n \t      [--jobs <n>] [--] [<path>...]\n@@ -195,6 +195,10 @@ If the submodule is not yet initialized, and you just want to use the\n setting as stored in .gitmodules, you can automatically initialize the\n submodule with the `--init` option.\n \n+You can configure a set of submodules using pathspec syntax in\n+submodule.active you can use `--init-active` to initialize\n+those before updating.\n+\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n@@ -378,6 +382,11 @@ the submodule itself.\n \tInitialize all submodules for which \"git submodule init\" has not been\n \tcalled so far before updating.\n \n+--init-active::\n+\tThis option is only valid for the update command.\n+\tInitialize all submodules configured in \"`submodule.active`\"\n+\tthat have not been updated before.\n+\n --name::\n \tThis option is only valid for the add command. It sets the submodule's\n \tname to the given string instead of defaulting to its path. The name\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 554bd1c49..e5b9a8920 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -9,7 +9,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n-   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\"\n@@ -499,7 +499,12 @@ cmd_update()\n \t\t\tprogress=\"--progress\"\n \t\t\t;;\n \t\t-i|--init)\n-\t\t\tinit=1\n+\t\t\ttest -z $init || test $init = by_args || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_args\n+\t\t\t;;\n+\t\t--init-active)\n+\t\t\ttest -z $init || test $init = by_config || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_config\n \t\t\t;;\n \t\t--remote)\n \t\t\tremote=1\n@@ -568,7 +573,17 @@ cmd_update()\n \n \tif test -n \"$init\"\n \tthen\n-\t\tcmd_init \"--\" \"$@\" || return\n+\t\tif test \"$init\" = \"by_config\"\n+\t\tthen\n+\t\t\tif test $# -gt 0\n+\t\t\tthen\n+\t\t\t\tdie \"$(gettext \"path arguments are incompatible with --init-active\")\"\n+\t\t\tfi\n+\t\t\tcmd_init \"--\" $(git config --get-all submodule.active) || return\n+\t\telse\n+\t\t\tcmd_init \"--\" \"$@\" || return\n+\t\tfi\n+\n \tfi\n \n \t{\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex b77cce8e4..f5df0a5b4 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1116,5 +1116,44 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'setup superproject with submodules' '\n+\tgit init sub1 &&\n+\ttest_commit -C sub1 test &&\n+\ttest_commit -C sub1 test2 &&\n+\tgit init multisuper &&\n+\tgit -C multisuper submodule add ../sub1 sub0 &&\n+\tgit -C multisuper submodule add ../sub1 sub1 &&\n+\tgit -C multisuper submodule add ../sub1 sub2 &&\n+\tgit -C multisuper submodule add ../sub1 sub3 &&\n+\tgit -C multisuper commit -m \"add some submodules\"\n+'\n+\n+cat >expect <<-EOF\n+-sub0\n+ sub1 (test2)\n+ sub2 (test2)\n+ sub3 (test2)\n+EOF\n+\n+test_expect_success 'submodule update --init with a specification' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule update --init . \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update --init-active' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config submodule.active \".\" &&\n+\tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_must_fail git -C multisuper_clone submodule update --init-active sub0 &&\n+\ttest_cmp expect actual\n+'\n \n test_done\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312482","messageId":"20170223234728.164111-6-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH 05/10] submodule--helper: add is_active command","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-23T23:47:23Z","receivedAt":"2017-02-23T23:49:28Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"There are a lot of places where an explicit check for\nsubmodule.\"<name>\".url is done to see if a submodule exists.  In order\nto more easily facilitate the use of the submodule.active config option\nto indicate active submodules, add a helper which can be used to query\nif a submodule is active or not.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c    | 11 ++++++++\n t/t7413-submodule-is-active.sh | 63 ++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 74 insertions(+)\n create mode 100755 t/t7413-submodule-is-active.sh\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex df0d9c166..dac02604d 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1128,6 +1128,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int is_active(int argc, const char **argv, const char *prefix)\n+{\n+\tif (argc != 2)\n+\t\tdie(\"submodule--helper is-active takes exactly 1 arguments\");\n+\n+\tgitmodules_config();\n+\n+\treturn !is_submodule_initialized(argv[1]);\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -1147,6 +1157,7 @@ static struct cmd_struct commands[] = {\n \t{\"init\", module_init, 0},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n+\t{\"is-active\", is_active, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nnew file mode 100755\nindex 000000000..683487020\n--- /dev/null\n+++ b/t/t7413-submodule-is-active.sh\n@@ -0,0 +1,63 @@\n+#!/bin/sh\n+\n+test_description='Test submodule--helper is-active\n+\n+This test verifies that `git submodue--helper is-active` correclty identifies\n+submodules which are \"active\" and interesting to the user.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tgit init sub &&\n+\ttest_commit -C sub initial &&\n+\tgit init super &&\n+\ttest_commit -C super initial &&\n+\tgit -C super submodule add ../sub sub1 &&\n+\tgit -C super submodule add ../sub sub2 &&\n+\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n+'\n+\n+test_expect_success 'is-active works with urls' '\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_expect_success 'is-active works with basic submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\tgit -C super config --unset submodule.sub2.URL &&\n+\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super config submodule.sub2.URL ../sub &&\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active correctly works with paths that are not submodules' '\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_done\n-- \n2.11.0.483.g087da7b7c-goog\n\n"},{"id":"312484","messageId":"CAGZ79kbf6tWjgV6V96gBzjPABHrEAdL0zhmrRqdNw9ZQQ-2QXw@mail.gmail.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"Re: [PATCH 00/10] decoupling a submodule's existence and its url","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-02-23T23:58:05Z","receivedAt":"2017-02-23T23:58:11Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:\n> There are two motivations for decoupling a submodule's existence from the url\n> that is stored in .git/config.\n>\n> 1. Worktrees can't really be used with submodules since the existence is\n>    checked based on the shared .git/config.  This means that two different\n>    worktress have to have the same initialized submodules.  By decoupling a\n>    submodule's existence from the url, two different work trees can be\n>    configured to have different submodules checked out.\n\ncc Duy for this one:\n\nWell once we have the per-worktree configuration, e.g. [1] we can *technically*\nhave different submodules in different worktrees by saying\n\n  workingtree0: submodule.<name>.url = git://example.org/real-submodule\n  workingtree1: submodule.<name>.url = bogus\n  workingtree2: submodule.<name>.url = more bogus\n\nand once we used the URL in the first workingtree all urls are\ndegraded to a boolean flag,\nso the different (possible bogus) content does not do harm, only user-confusion,\nbecause the model of the URL being the flag indicating existence doesn't quite\nfit multiple working trees.\n\n[1] https://public-inbox.org/git/20170110112524.12870-3-pclouds@gmail.com/\n\n> 2. Easily configure gorups of submodules that a user is interested in.  In a\n>    repository with hundreds of submodules it would be difficult to easily tell git\n>    which modules to worry about without having to individually init all of\n>    them.  Instead, a pathspec can be used to more easily select or deselect\n>    groups of submodules.\n>\n> This patch series works to do this decoupling and instead allows a user to\n> configure submodule.active with a pathspec to use to check if a submodule is\n> initialized.\n\nThanks for stating both intentions!\nStefan\n"},{"id":"312493","messageId":"CAGZ79kYmmeVOYSPTvAbGpRQn1YL9yjPOkT5xCoSDmtNzQ1t2fw@mail.gmail.com","threadId":"45207","inReplyTo":"20170223234728.164111-11-bmwill@google.com","subject":"Re: [PATCH 10/10] submodule--helper clone: check for configured submodules using helper","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-02-24T00:58:55Z","receivedAt":"2017-02-24T01:00:28Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:\n\n> @@ -795,14 +794,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>         }\n>\n>         /*\n> -        * Looking up the url in .git/config.\n> +        * Check if the submodule has been initialized.\n>          * We must not fall back to .gitmodules as we only want\n>          * to process configured submodules.\n\nThis sentence \"we must not ...\" is also no longer accurate,\nas we do exactly that when using sub->url instead of just url\nbelow.\n"},{"id":"312495","messageId":"CAGZ79kZKH_e2NLd=A=og452f-1bfFcSoi5=SM5oetu87TT766Q@mail.gmail.com","threadId":"45207","inReplyTo":"20170223234728.164111-6-bmwill@google.com","subject":"Re: [PATCH 05/10] submodule--helper: add is_active command","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-02-24T01:15:34Z","receivedAt":"2017-02-24T01:16:51Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:\n> There are a lot of places where an explicit check for\n> submodule.\"<name>\".url is done to see if a submodule exists.  In order\n> to more easily facilitate the use of the submodule.active config option\n> to indicate active submodules, add a helper which can be used to query\n> if a submodule is active or not.\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  builtin/submodule--helper.c    | 11 ++++++++\n>  t/t7413-submodule-is-active.sh | 63 ++++++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 74 insertions(+)\n>  create mode 100755 t/t7413-submodule-is-active.sh\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index df0d9c166..dac02604d 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -1128,6 +1128,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n>         return 0;\n>  }\n>\n> +static int is_active(int argc, const char **argv, const char *prefix)\n> +{\n> +       if (argc != 2)\n> +               die(\"submodule--helper is-active takes exactly 1 arguments\");\n> +\n> +       gitmodules_config();\n> +\n> +       return !is_submodule_initialized(argv[1]);\n> +}\n> +\n>  #define SUPPORT_SUPER_PREFIX (1<<0)\n>\n>  struct cmd_struct {\n> @@ -1147,6 +1157,7 @@ static struct cmd_struct commands[] = {\n>         {\"init\", module_init, 0},\n>         {\"remote-branch\", resolve_remote_submodule_branch, 0},\n>         {\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n> +       {\"is-active\", is_active, 0},\n>  };\n>\n>  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\n> diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> new file mode 100755\n> index 000000000..683487020\n> --- /dev/null\n> +++ b/t/t7413-submodule-is-active.sh\n> @@ -0,0 +1,63 @@\n> +#!/bin/sh\n> +\n> +test_description='Test submodule--helper is-active\n> +\n> +This test verifies that `git submodue--helper is-active` correclty identifies\n> +submodules which are \"active\" and interesting to the user.\n> +'\n> +\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'setup' '\n> +       git init sub &&\n> +       test_commit -C sub initial &&\n> +       git init super &&\n> +       test_commit -C super initial &&\n> +       git -C super submodule add ../sub sub1 &&\n> +       git -C super submodule add ../sub sub2 &&\n> +       git -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n> +'\n> +\n> +test_expect_success 'is-active works with urls' '\n> +       git -C super submodule--helper is-active sub1 &&\n> +       git -C super submodule--helper is-active sub2 &&\n> +\n> +       git -C super config --unset submodule.sub1.URL &&\n> +       test_must_fail git -C super submodule--helper is-active sub1 &&\n> +       git -C super config submodule.sub1.URL ../sub &&\n> +       git -C super submodule--helper is-active sub1\n> +'\n> +\n> +test_expect_success 'is-active works with basic submodule.active config' '\n> +       git -C super config --add submodule.active \".\" &&\n> +       git -C super config --unset submodule.sub1.URL &&\n> +       git -C super config --unset submodule.sub2.URL &&\n\nI think we'd want to unset only one of them here\n\n> +\n> +       git -C super submodule--helper is-active sub1 &&\n> +       git -C super submodule--helper is-active sub2 &&\n\nto test 2 different cases of one being active by config setting only and\nthe other having both.\n\nI could not spot test for having the URL set but the config setting set, not\nincluding the submodule, e.g.\n\n    git -C super config  submodule.sub1.URL ../sub &&\n    git -C super submodule.active  \":(exclude)sub1\" &&\n\nwhich would be expected to not be active, as once the configuration\nis there it takes precedence over any (no)URL setting?\n"},{"id":"312560","messageId":"xmqq8tov1ev7.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170223234728.164111-2-bmwill@google.com","subject":"Re: [PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-02-24T21:02:52Z","receivedAt":"2017-02-24T21:03:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> Currently the submodule.<name>.url config option is used to determine\n> if a given submodule exists and is interesting to the user.  This\n> however doesn't work very well because the URL is a config option for\n> the scope of a repository, whereas the existence of a submodule is an\n> option scoped to the working tree.\n>\n> In a future with worktree support for submodules, there will be multiple\n> working trees, each of which may only need a subset of the submodules\n> checked out.  The URL (which is where the submodule repository can be\n> obtained) should not differ between different working trees.\n>\n> It may also be convenient for users to more easily specify groups of\n> submodules they are interested in as apposed to running \"git submodule\n> init <path>\" on each submodule they want checked out in their working\n> tree.\n>\n> To this end, the config option submodule.active is introduced which\n> holds a pathspec that specifies which submodules should exist in the\n> working tree.\n\nHmph.  submodule.active in .git/config would be shared the same way\nsubmodule.<name>.url in .git/config is shared across the worktrees\nthat stems from the same primary repository, no?\n\nPerhaps there are some other uses of this submodule.active idea, but\nI do not see how it is relevant to solving \"multiple worktrees\"\nissue.  Per-worktree config would solve it with the current\nsubmodule.<name>.url without submodule.active list, I would think [*1*].\n\nAlso as a grouping measure, submodule.active that lists submodule\npaths feels hard to use.  When switching between two branches in the\nsuperproject that have the same submodule bound at two different\npaths, who is responsible for updating submodule.active in\nsuperproject's config?  If it were a list of submodule names, this\nobjection does not apply, though.\n\n\n\n[Footnote]\n\n*1* At the conceptual level, I agree that .url that also means \"we\n    are interested in this one\" feels like somewhat an unclean\n    design, but that is not what you are \"fixing\", is it?\n\n"},{"id":"312751","messageId":"20170227183815.GE153455@google.com","threadId":"45207","inReplyTo":"CAGZ79kYmmeVOYSPTvAbGpRQn1YL9yjPOkT5xCoSDmtNzQ1t2fw@mail.gmail.com","subject":"Re: [PATCH 10/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-27T18:38:15Z","receivedAt":"2017-02-27T18:40:24Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 02/23, Stefan Beller wrote:\n> On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:\n> \n> > @@ -795,14 +794,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n> >         }\n> >\n> >         /*\n> > -        * Looking up the url in .git/config.\n> > +        * Check if the submodule has been initialized.\n> >          * We must not fall back to .gitmodules as we only want\n> >          * to process configured submodules.\n> \n> This sentence \"we must not ...\" is also no longer accurate,\n> as we do exactly that when using sub->url instead of just url\n> below.\n\nYou're right, I'll fix that.\n\n-- \nBrandon Williams\n"},{"id":"312794","messageId":"20170227183536.GD153455@google.com","threadId":"45207","inReplyTo":"CAGZ79kZKH_e2NLd=A=og452f-1bfFcSoi5=SM5oetu87TT766Q@mail.gmail.com","subject":"Re: [PATCH 05/10] submodule--helper: add is_active command","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-02-27T18:35:36Z","receivedAt":"2017-02-27T22:35:47Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 02/23, Stefan Beller wrote:\n> On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:\n> > There are a lot of places where an explicit check for\n> > submodule.\"<name>\".url is done to see if a submodule exists.  In order\n> > to more easily facilitate the use of the submodule.active config option\n> > to indicate active submodules, add a helper which can be used to query\n> > if a submodule is active or not.\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  builtin/submodule--helper.c    | 11 ++++++++\n> >  t/t7413-submodule-is-active.sh | 63 ++++++++++++++++++++++++++++++++++++++++++\n> >  2 files changed, 74 insertions(+)\n> >  create mode 100755 t/t7413-submodule-is-active.sh\n> >\n> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> > index df0d9c166..dac02604d 100644\n> > --- a/builtin/submodule--helper.c\n> > +++ b/builtin/submodule--helper.c\n> > @@ -1128,6 +1128,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n> >         return 0;\n> >  }\n> >\n> > +static int is_active(int argc, const char **argv, const char *prefix)\n> > +{\n> > +       if (argc != 2)\n> > +               die(\"submodule--helper is-active takes exactly 1 arguments\");\n> > +\n> > +       gitmodules_config();\n> > +\n> > +       return !is_submodule_initialized(argv[1]);\n> > +}\n> > +\n> >  #define SUPPORT_SUPER_PREFIX (1<<0)\n> >\n> >  struct cmd_struct {\n> > @@ -1147,6 +1157,7 @@ static struct cmd_struct commands[] = {\n> >         {\"init\", module_init, 0},\n> >         {\"remote-branch\", resolve_remote_submodule_branch, 0},\n> >         {\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n> > +       {\"is-active\", is_active, 0},\n> >  };\n> >\n> >  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\n> > diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> > new file mode 100755\n> > index 000000000..683487020\n> > --- /dev/null\n> > +++ b/t/t7413-submodule-is-active.sh\n> > @@ -0,0 +1,63 @@\n> > +#!/bin/sh\n> > +\n> > +test_description='Test submodule--helper is-active\n> > +\n> > +This test verifies that `git submodue--helper is-active` correclty identifies\n> > +submodules which are \"active\" and interesting to the user.\n> > +'\n> > +\n> > +. ./test-lib.sh\n> > +\n> > +test_expect_success 'setup' '\n> > +       git init sub &&\n> > +       test_commit -C sub initial &&\n> > +       git init super &&\n> > +       test_commit -C super initial &&\n> > +       git -C super submodule add ../sub sub1 &&\n> > +       git -C super submodule add ../sub sub2 &&\n> > +       git -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n> > +'\n> > +\n> > +test_expect_success 'is-active works with urls' '\n> > +       git -C super submodule--helper is-active sub1 &&\n> > +       git -C super submodule--helper is-active sub2 &&\n> > +\n> > +       git -C super config --unset submodule.sub1.URL &&\n> > +       test_must_fail git -C super submodule--helper is-active sub1 &&\n> > +       git -C super config submodule.sub1.URL ../sub &&\n> > +       git -C super submodule--helper is-active sub1\n> > +'\n> > +\n> > +test_expect_success 'is-active works with basic submodule.active config' '\n> > +       git -C super config --add submodule.active \".\" &&\n> > +       git -C super config --unset submodule.sub1.URL &&\n> > +       git -C super config --unset submodule.sub2.URL &&\n> \n> I think we'd want to unset only one of them here\n> \n> > +\n> > +       git -C super submodule--helper is-active sub1 &&\n> > +       git -C super submodule--helper is-active sub2 &&\n> \n> to test 2 different cases of one being active by config setting only and\n> the other having both.\n\nWill do.\n\n> \n> I could not spot test for having the URL set but the config setting set, not\n> including the submodule, e.g.\n> \n>     git -C super config  submodule.sub1.URL ../sub &&\n>     git -C super submodule.active  \":(exclude)sub1\" &&\n> \n> which would be expected to not be active, as once the configuration\n> is there it takes precedence over any (no)URL setting?\n\nThe last test, tests this functionality as the URL settings for both\nsub1 and sub2 are in the config.  You'll notice in the tests where I\nunset the URL config, that they get added back at the end of the test so\nthat future tests have a clean state to work with.\n\n-- \nBrandon Williams\n"},{"id":"312973","messageId":"20170301200230.GA30622@google.com","threadId":"45207","inReplyTo":"xmqq8tov1ev7.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-01T20:02:30Z","receivedAt":"2017-03-01T20:11:17Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 02/24, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > Currently the submodule.<name>.url config option is used to determine\n> > if a given submodule exists and is interesting to the user.  This\n> > however doesn't work very well because the URL is a config option for\n> > the scope of a repository, whereas the existence of a submodule is an\n> > option scoped to the working tree.\n> >\n> > In a future with worktree support for submodules, there will be multiple\n> > working trees, each of which may only need a subset of the submodules\n> > checked out.  The URL (which is where the submodule repository can be\n> > obtained) should not differ between different working trees.\n> >\n> > It may also be convenient for users to more easily specify groups of\n> > submodules they are interested in as apposed to running \"git submodule\n> > init <path>\" on each submodule they want checked out in their working\n> > tree.\n> >\n> > To this end, the config option submodule.active is introduced which\n> > holds a pathspec that specifies which submodules should exist in the\n> > working tree.\n> \n> Hmph.  submodule.active in .git/config would be shared the same way\n> submodule.<name>.url in .git/config is shared across the worktrees\n> that stems from the same primary repository, no?\n> \n> Perhaps there are some other uses of this submodule.active idea, but\n> I do not see how it is relevant to solving \"multiple worktrees\"\n> issue.  Per-worktree config would solve it with the current\n> submodule.<name>.url without submodule.active list, I would think [*1*].\n\nCorrect, I should update the language to indicate this allows the URL to\nbe shared between worktrees, but a per-worktree config must exist before\nsubmodule.active can actually be used to select different groups of\nsubmodules per-worktree.  The idea is that if submodule.active is set\nthen you no longer look at the URLs to see what is interesting but\nrather at the paths.\n\n> Also as a grouping measure, submodule.active that lists submodule\n> paths feels hard to use.  When switching between two branches in the\n> superproject that have the same submodule bound at two different\n> paths, who is responsible for updating submodule.active in\n> superproject's config?  If it were a list of submodule names, this\n> objection does not apply, though.\n\nI agree that if you are listing every submodule path by hand then this\nmay not be the best approach and would be difficult to use.  The idea is\nthat this would allow a user to set a general pathspec to identify a\ngroup of modules they are interested in.  Perhaps once attributes can be\nused in pathspecs a user could group submodules by setting a particular\nattribute and then submodule.active would have a value like\n\":(attr:foo)\" to indicate I'm interested in all submodules with the\n\"foo\" attribute.\n\n> \n> \n> \n> [Footnote]\n> \n> *1* At the conceptual level, I agree that .url that also means \"we\n>     are interested in this one\" feels like somewhat an unclean\n>     design, but that is not what you are \"fixing\", is it?\n> \n\n-- \nBrandon Williams\n"},{"id":"312992","messageId":"CAGZ79kb9Fhb0z5AbygBx9wNyLr-ovb-74xeaD8p+C5Xz9Dekcw@mail.gmail.com","threadId":"45207","inReplyTo":"20170301200230.GA30622@google.com","subject":"Re: [PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-01T21:53:18Z","receivedAt":"2017-03-01T22:53:19Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"IIRC most of the series is actually refactoring, i.e.\nproviding a central function that answers\n\"is this submodule active/initialized?\" and then making use of this\nfunction.\n\nMaybe it would be easier to reroll these refactorings first without adding\nin the change of behavior.\n\nOff the list we talked about different models how to indicate that\na submodule is active.\n\nCurrent situation:\nsubmodule.<name>.URL is used as a boolean flag\n\nPossible future A:\n1) If submodule.active exists use that\n2) otherwise go be individual .URL configs\n\nsubmodule.active is a config that contains a pathspec,\ni.e. specifies the group of submodules instead of marking\neach submodule individually.\n\nHow to get to future A:\n* apply this patch series\n\nPossible future B:\n1) the boolean submodule.<name>.exists is used\n    if existent\n2) If that boolean is missing we'd respect a grouping\n   feature such as submodule.active\n3) fallback to the .URL as a boolean indicator.\n\nHow to get to future B:\n1) possibly take the refactoring part from this series\n2) implement the .exists flag (that can solve the worktree\n  problem, as then we don't have to abuse the .URL\n  as a boolean indicator any more.)\n3) implement the grouping feature that takes precedence\n  over .URL, but yields precedence to the .exists flag.\n  (This would solve the grouping problem)\n\nBy having two different series (2) and (3) we'd solve\njust one thing at a time with each series, such that\nthis seems easier to understand and review.\n\nThe question is if this future B is also easier to use for\nusers and I think it would be, despite being technically more\ncomplex.\n\nMost users only have a few submodules. Also the assumption\nis to have either interest in very few specific submodules\nor all of them. For both of these cases the .exists is a good idea\nas it is very explicit, but verbose.\n\nThe grouping feature would help in the case of lots of\nsubmodules, e.g. to select all of them you would just give\nan easy pathspec \".\" and that would help going forward\nas by such a submodule spec all new submodules would\nbe \"auto-on\".\n\nPossible future C:\nSimilar to B, but with branch specific configuration.\nsubmodule.<branchname>.active would work as a\ngrouping feature. I wonder how it would work with\nthe .exists flag.\n\nStefan\n"},{"id":"313037","messageId":"xmqqwpc8cjxj.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170301200230.GA30622@google.com","subject":"Re: [PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-02T05:43:52Z","receivedAt":"2017-03-02T05:45:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> On 02/24, Junio C Hamano wrote:\n>\n>> Also as a grouping measure, submodule.active that lists submodule\n>> paths feels hard to use.  When switching between two branches in the\n>> superproject that have the same submodule bound at two different\n>> paths, who is responsible for updating submodule.active in\n>> superproject's config?  If it were a list of submodule names, this\n>> objection does not apply, though.\n>\n> I agree that if you are listing every submodule path by hand then this\n> may not be the best approach and would be difficult to use.  The idea is\n> that this would allow a user to set a general pathspec to identify a\n> group of modules they are interested in.  Perhaps once attributes can be\n> used in pathspecs a user could group submodules by setting a particular\n> attribute and then submodule.active would have a value like\n> \":(attr:foo)\" to indicate I'm interested in all submodules with the\n> \"foo\" attribute.\n\nOK.  As .gitattributes is tracked just like .gitmodules in tree, the\nproject can adjust the path pattern that matches a renamed submodule\nand gives it an attribute in .gitattributes in the same commit in\nthe superproject that moves the directory to which the submodule is\nbound, just like it updates .gitmodules to adjust the name<->path\nmapping.  So that plan solves my specific worry about using \"path\"\nfor grouping and not \"name\".\n\nThanks.\n"},{"id":"313348","messageId":"20170306185048.GC183239@google.com","threadId":"45207","inReplyTo":"CAGZ79kb9Fhb0z5AbygBx9wNyLr-ovb-74xeaD8p+C5Xz9Dekcw@mail.gmail.com","subject":"Re: [PATCH 01/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-06T18:50:48Z","receivedAt":"2017-03-06T18:51:46Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/01, Stefan Beller wrote:\n\nSorry I've been slow at rerolling this.  I'll send out a reroll today.\n\n> IIRC most of the series is actually refactoring, i.e.\n> providing a central function that answers\n> \"is this submodule active/initialized?\" and then making use of this\n> function.\n> \n> Maybe it would be easier to reroll these refactorings first without adding\n> in the change of behavior.\n\nI agree, when I resend out the series I can drop the first patch so that\nthe series as a whole just moves to using a standardized function to\ncheck that a submodule is active.  I can then resend out the first patch\nin the series on its own so that we can more easily discuss the best\nroute to take.\n\n> \n> Off the list we talked about different models how to indicate that\n> a submodule is active.\n> \n> Current situation:\n> submodule.<name>.URL is used as a boolean flag\n> \n> Possible future A:\n> 1) If submodule.active exists use that\n> 2) otherwise go be individual .URL configs\n> \n> submodule.active is a config that contains a pathspec,\n> i.e. specifies the group of submodules instead of marking\n> each submodule individually.\n> \n> How to get to future A:\n> * apply this patch series\n> \n> Possible future B:\n> 1) the boolean submodule.<name>.exists is used\n>     if existent\n> 2) If that boolean is missing we'd respect a grouping\n>    feature such as submodule.active\n> 3) fallback to the .URL as a boolean indicator.\n\nThinking on this, and to maintain simplicity and uniformity, we could\nhave the per-submodule boolean flag to be \"submodule.<name>.active\"\nwhile the general pathspec based config option would be\n\"submodule.active\".\n\n> \n> How to get to future B:\n> 1) possibly take the refactoring part from this series\n> 2) implement the .exists flag (that can solve the worktree\n>   problem, as then we don't have to abuse the .URL\n>   as a boolean indicator any more.)\n> 3) implement the grouping feature that takes precedence\n>   over .URL, but yields precedence to the .exists flag.\n>   (This would solve the grouping problem)\n> \n> By having two different series (2) and (3) we'd solve\n> just one thing at a time with each series, such that\n> this seems easier to understand and review.\n> \n> The question is if this future B is also easier to use for\n> users and I think it would be, despite being technically more\n> complex.\n> \n> Most users only have a few submodules. Also the assumption\n> is to have either interest in very few specific submodules\n> or all of them. For both of these cases the .exists is a good idea\n> as it is very explicit, but verbose.\n> \n> The grouping feature would help in the case of lots of\n> submodules, e.g. to select all of them you would just give\n> an easy pathspec \".\" and that would help going forward\n> as by such a submodule spec all new submodules would\n> be \"auto-on\".\n\nAnd if you wanted all but one you could have submodule.active=\".\" while\nsubmodule.dontwant.active=false instead of having a multi value\nsubmodule.active with an exclusion pathspec.  Both work but one may be\neasier for a user to understand.\n\n> \n> Possible future C:\n> Similar to B, but with branch specific configuration.\n> submodule.<branchname>.active would work as a\n> grouping feature. I wonder how it would work with\n> the .exists flag.\n> \n> Stefan\n\n-- \nBrandon Williams\n"},{"id":"313593","messageId":"20170309012345.180702-6-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 05/11] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:39Z","receivedAt":"2017-03-09T01:31:01Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Use the 'is_submodule_initialized()' helper to check for configured\nsubmodules instead of manually checking for the submodule's URL in the\nconfig.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 15 +++------------\n 1 file changed, 3 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex dac02604d..bceb62a20 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -760,7 +760,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstruct strbuf displaypath_sb = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *displaypath = NULL;\n-\tchar *url = NULL;\n \tint needs_cloning = 0;\n \n \tif (ce_stage(ce)) {\n@@ -794,15 +793,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\t/*\n-\t * Looking up the url in .git/config.\n-\t * We must not fall back to .gitmodules as we only want\n-\t * to process configured submodules.\n-\t */\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n-\tgit_config_get_string(sb.buf, &url);\n-\tif (!url) {\n+\t/* Check if the submodule has been initialized. */\n+\tif (!is_submodule_initialized(ce->name)) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n \t\tgoto cleanup;\n \t}\n@@ -836,7 +828,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, \"--depth=1\");\n \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n-\targv_array_pushl(&child->args, \"--url\", url, NULL);\n+\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n \tif (suc->references.nr) {\n \t\tstruct string_list_item *item;\n \t\tfor_each_string_list_item(item, &suc->references)\n@@ -846,7 +838,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, suc->depth);\n \n cleanup:\n-\tfree(url);\n \tstrbuf_reset(&displaypath_sb);\n \tstrbuf_reset(&sb);\n \n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313594","messageId":"20170309012345.180702-3-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 02/11] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:36Z","receivedAt":"2017-03-09T01:31:03Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 554bd1c49..19660b9c0 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1000,14 +1000,13 @@ cmd_status()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n \t\t\tcontinue\n \t\tfi\n-\t\tif test -z \"$url\" ||\n+\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n \t\t{\n \t\t\t! test -d \"$sm_path\"/.git &&\n \t\t\t! test -f \"$sm_path\"/.git\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313595","messageId":"20170309012345.180702-5-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 04/11] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:38Z","receivedAt":"2017-03-09T01:32:43Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 1c2064cc1..7ed1aaba3 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1101,7 +1101,7 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tif git submodule--helper is-active \"$sm_path\"\n \t\tthen\n \t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313596","messageId":"20170309012345.180702-1-bmwill@google.com","threadId":"45207","inReplyTo":"20170223234728.164111-1-bmwill@google.com","subject":"[PATCH v2 00/11] decoupling a submodule's existence and its url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:34Z","receivedAt":"2017-03-09T01:32:51Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Differences from v1:\n* Reordered some of the patches\n* added submodule.<name>.active boolean config option which can be used to do\n  more fine grain selection of submodules while still decoupling the existence\n  from the URL.\n* submodule.<name>.active has precedence over the pathspec stored in\n  submodule.active\n\nBrandon Williams (11):\n  submodule--helper: add is_active command\n  submodule status: use submodule--helper is-active\n  submodule deinit: use most reliable url\n  submodule sync: use submodule--helper is-active\n  submodule--helper clone: check for configured submodules using helper\n  submodule: decouple url and submodule existence\n  submodule update: add `--init-active` switch\n  clone: add --submodule-spec=<pathspec> switch\n  completion: clone can initialize specific submodules\n  submodule--helper init: set submodule.<name>.active\n  submodule add: respect submodule.active and submodule.<name>.active\n\n Documentation/config.txt               |  15 ++++-\n Documentation/git-clone.txt            |  23 ++++---\n Documentation/git-submodule.txt        |  11 +++-\n builtin/clone.c                        |  36 ++++++++++-\n builtin/submodule--helper.c            |  33 ++++++----\n contrib/completion/git-completion.bash |   1 +\n git-submodule.sh                       |  40 +++++++++---\n submodule.c                            |  36 +++++++++--\n t/t7400-submodule-basic.sh             | 109 +++++++++++++++++++++++++++++++++\n t/t7413-submodule-is-active.sh         | 107 ++++++++++++++++++++++++++++++++\n 10 files changed, 376 insertions(+), 35 deletions(-)\n create mode 100755 t/t7413-submodule-is-active.sh\n\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313597","messageId":"20170309012345.180702-2-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 01/11] submodule--helper: add is_active command","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:35Z","receivedAt":"2017-03-09T01:33:12Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"There are a lot of places where an explicit check for\nsubmodule.\"<name>\".url is done to see if a submodule exists.  In order\nto centralize this check introduce a helper which can be used to query\nif a submodule is active or not.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c    | 11 +++++++++++\n t/t7413-submodule-is-active.sh | 31 +++++++++++++++++++++++++++++++\n 2 files changed, 42 insertions(+)\n create mode 100755 t/t7413-submodule-is-active.sh\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex df0d9c166..dac02604d 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1128,6 +1128,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int is_active(int argc, const char **argv, const char *prefix)\n+{\n+\tif (argc != 2)\n+\t\tdie(\"submodule--helper is-active takes exactly 1 arguments\");\n+\n+\tgitmodules_config();\n+\n+\treturn !is_submodule_initialized(argv[1]);\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -1147,6 +1157,7 @@ static struct cmd_struct commands[] = {\n \t{\"init\", module_init, 0},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n+\t{\"is-active\", is_active, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nnew file mode 100755\nindex 000000000..f18e0c925\n--- /dev/null\n+++ b/t/t7413-submodule-is-active.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+\n+test_description='Test submodule--helper is-active\n+\n+This test verifies that `git submodue--helper is-active` correclty identifies\n+submodules which are \"active\" and interesting to the user.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tgit init sub &&\n+\ttest_commit -C sub initial &&\n+\tgit init super &&\n+\ttest_commit -C super initial &&\n+\tgit -C super submodule add ../sub sub1 &&\n+\tgit -C super submodule add ../sub sub2 &&\n+\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n+'\n+\n+test_expect_success 'is-active works with urls' '\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313598","messageId":"20170309012345.180702-12-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 11/11] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:45Z","receivedAt":"2017-03-09T01:33:19Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"In addition to adding submodule.<name>.url to the config, set\nsubmodule.<name>.active to true unless submodule.active is configured\nand the submodule's path matches the configured pathspec.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh               | 12 ++++++++++++\n t/t7413-submodule-is-active.sh | 21 +++++++++++++++++++++\n 2 files changed, 33 insertions(+)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 43a393d7e..d90fde655 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -271,6 +271,18 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n+\n+\tif git config --get submodule.active >/dev/null\n+\tthen\n+\t\t# If the submodule being adding isn't already covered by the\n+\t\t# current configured pathspec, set the submodule's active flag\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\t\tfi\n+\telse\n+\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\tfi\n }\n \n #\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex c41b899ab..865931978 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -15,6 +15,12 @@ test_expect_success 'setup' '\n \ttest_commit -C super initial &&\n \tgit -C super submodule add ../sub sub1 &&\n \tgit -C super submodule add ../sub sub2 &&\n+\n+\t# Remove submodule.<name>.active entries in order to test in an\n+\t# environment where only URLs are present in the conifg\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active &&\n+\n \tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n '\n \n@@ -83,4 +89,19 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active\n \tgit -C super config --unset submodule.sub2.active\n '\n \n+test_expect_success 'is-active, submodule.active and submodule add' '\n+\ttest_when_finished \"rm -rf super2\" &&\n+\tgit init super2 &&\n+\ttest_commit -C super2 initial &&\n+\tgit -C super2 config --add submodule.active \"sub*\" &&\n+\n+\t# submodule add should only add submodule.<name>.active\n+\t# to the config if not matched by the pathspec\n+\tgit -C super2 submodule add ../sub sub1 &&\n+\ttest_must_fail git -C super2 config --get submodule.sub1.active &&\n+\n+\tgit -C super2 submodule add ../sub mod &&\n+\tgit -C super2 config --get submodule.mod.active\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313599","messageId":"20170309012345.180702-7-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 06/11] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:40Z","receivedAt":"2017-03-09T01:33:23Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Currently the submodule.<name>.url config option is used to determine\nif a given submodule exists and is interesting to the user.  This\nhowever doesn't work very well because the URL is a config option for\nthe scope of a repository, whereas the existence of a submodule is an\noption scoped to the working tree.\n\nIn a future with worktree support for submodules, there will be multiple\nworking trees, each of which may only need a subset of the submodules\nchecked out.  The URL (which is where the submodule repository can be\nobtained) should not differ between different working trees.\n\nIt may also be convenient for users to more easily specify groups of\nsubmodules they are interested in as apposed to running \"git submodule\ninit <path>\" on each submodule they want checked out in their working\ntree.\n\nTo this end two config options are introduced, submodule.active and\nsubmodule.<name>.active.  The submodule.active config holds a pathspec\nthat specifies which submodules should exist in the working tree.  The\nsubmodule.<name>.active config is a boolean flag used to indicate if\nthat particular submodule should exist in the working tree.\n\nGiven these multiple ways to check for a submodule's existence the more\nfine-grained submodule.<name>.active option has the highest order of\nprecedence followed by the pathspec check against submodule.active. To\nensure backwards compatibility, if neither of these options are set git\nfalls back to checking the submodule.<name>.url option to determine a\nsubmodule's existence.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/config.txt       | 15 ++++++++++--\n submodule.c                    | 36 ++++++++++++++++++++++++---\n t/t7413-submodule-is-active.sh | 55 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 100 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 506431267..21037e8c5 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -2888,8 +2888,9 @@ submodule.<name>.url::\n \tThe URL for a submodule. This variable is copied from the .gitmodules\n \tfile to the git config via 'git submodule init'. The user can change\n \tthe configured URL before obtaining the submodule via 'git submodule\n-\tupdate'. After obtaining the submodule, the presence of this variable\n-\tis used as a sign whether the submodule is of interest to git commands.\n+\tupdate'. If neither submodule.<name>.active or submodule.active are\n+\tset, the presence of this variable is used as a fallback to indicate\n+\twhether the submodule is of interest to git commands.\n \tSee linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.\n \n submodule.<name>.update::\n@@ -2927,6 +2928,16 @@ submodule.<name>.ignore::\n \t\"--ignore-submodules\" option. The 'git submodule' commands are not\n \taffected by this setting.\n \n+submodule.<name>.active::\n+\tBoolean value indicating if the submodule is of interest to git\n+\tcommands.  This config option takes precedence over the\n+\tsubmodule.active config option.\n+\n+submodule.active::\n+\tA repeated field which contains a pathspec used to match against a\n+\tsubmodule's path to determine if the submodule is of interest to git\n+\tcommands.\n+\n submodule.fetchJobs::\n \tSpecifies how many submodules are fetched/cloned at the same time.\n \tA positive integer allows up to that number of submodules fetched\ndiff --git a/submodule.c b/submodule.c\nindex 4c4f033e8..6125736fc 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -217,13 +217,41 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tconst struct submodule *module = NULL;\n+\tchar *key;\n+\tconst struct string_list *sl;\n+\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n-\tmodule = submodule_from_path(null_sha1, path);\n+\t/* early return if there isn't a path->module mapping */\n+\tif (!module)\n+\t\treturn 0;\n+\n+\t/* submodule.<name>.active is set */\n+\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n+\tif (!git_config_get_bool(key, &ret)) {\n+\t\tfree(key);\n+\t\treturn ret;\n+\t}\n+\tfree(key);\n+\n+\tsl = git_config_get_value_multi(\"submodule.active\");\n \n-\tif (module) {\n-\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n+\tif (sl) {\n+\t\tstruct pathspec ps;\n+\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n+\t\tconst struct string_list_item *item;\n+\n+\t\tfor_each_string_list_item(item, sl) {\n+\t\t\targv_array_push(&args, item->string);\n+\t\t}\n+\n+\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n+\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n+\n+\t\targv_array_clear(&args);\n+\t\tclear_pathspec(&ps);\n+\t} else {\n \t\tchar *value = NULL;\n+\t\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n \n \t\tret = !git_config_get_string(key, &value);\n \ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex f18e0c925..c41b899ab 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n \tgit -C super submodule--helper is-active sub1\n '\n \n+test_expect_success 'is-active works with submodule.<name>.active config' '\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"true\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\tgit -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super config --unset submodule.sub1.active\n+'\n+\n+test_expect_success 'is-active works with basic submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active correctly works with paths that are not submodules' '\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n+\tgit -C super config --add submodule.active \"sub1\" &&\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\tgit -C super config --bool submodule.sub2.active \"true\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset-all submodule.active &&\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313600","messageId":"20170309012345.180702-10-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 09/11] completion: clone can initialize specific submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:43Z","receivedAt":"2017-03-09T01:33:24Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n contrib/completion/git-completion.bash | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6721ff80f..4e473aa90 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1138,6 +1138,7 @@ _git_clone ()\n \t\t\t--single-branch\n \t\t\t--branch\n \t\t\t--recurse-submodules\n+\t\t\t--submodule-spec\n \t\t\t\"\n \t\treturn\n \t\t;;\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313601","messageId":"20170309012345.180702-8-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 07/11] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:41Z","receivedAt":"2017-03-09T01:33:29Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch `--init-active` initializes the submodules which are\nconfigured in `submodule.active` instead of those given as\ncommand line arguments before updating. In the first implementation this\nis made incompatible with further command line arguments as it is\nunclear what the user means by\n\n    git submodule update --init --init-active <paths>\n\nThis new switch allows users to record more complex patterns as it saves\nretyping them whenever you invoke update.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-submodule.txt | 11 ++++++++++-\n git-submodule.sh                | 21 ++++++++++++++++++---\n t/t7400-submodule-basic.sh      | 39 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 67 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 918bd1d1b..626b9760a 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,7 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n-'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]\n+'git submodule' [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch]\n \t      [--[no-]recommend-shallow] [-f|--force] [--rebase|--merge]\n \t      [--reference <repository>] [--depth <depth>] [--recursive]\n \t      [--jobs <n>] [--] [<path>...]\n@@ -195,6 +195,10 @@ If the submodule is not yet initialized, and you just want to use the\n setting as stored in .gitmodules, you can automatically initialize the\n submodule with the `--init` option.\n \n+You can configure a set of submodules using pathspec syntax in\n+submodule.active you can use `--init-active` to initialize\n+those before updating.\n+\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n@@ -378,6 +382,11 @@ the submodule itself.\n \tInitialize all submodules for which \"git submodule init\" has not been\n \tcalled so far before updating.\n \n+--init-active::\n+\tThis option is only valid for the update command.\n+\tInitialize all submodules configured in \"`submodule.active`\"\n+\tthat have not been updated before.\n+\n --name::\n \tThis option is only valid for the add command. It sets the submodule's\n \tname to the given string instead of defaulting to its path. The name\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 7ed1aaba3..43a393d7e 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -9,7 +9,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n-   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\"\n@@ -499,7 +499,12 @@ cmd_update()\n \t\t\tprogress=\"--progress\"\n \t\t\t;;\n \t\t-i|--init)\n-\t\t\tinit=1\n+\t\t\ttest -z $init || test $init = by_args || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_args\n+\t\t\t;;\n+\t\t--init-active)\n+\t\t\ttest -z $init || test $init = by_config || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_config\n \t\t\t;;\n \t\t--remote)\n \t\t\tremote=1\n@@ -568,7 +573,17 @@ cmd_update()\n \n \tif test -n \"$init\"\n \tthen\n-\t\tcmd_init \"--\" \"$@\" || return\n+\t\tif test \"$init\" = \"by_config\"\n+\t\tthen\n+\t\t\tif test $# -gt 0\n+\t\t\tthen\n+\t\t\t\tdie \"$(gettext \"path arguments are incompatible with --init-active\")\"\n+\t\t\tfi\n+\t\t\tcmd_init \"--\" $(git config --get-all submodule.active) || return\n+\t\telse\n+\t\t\tcmd_init \"--\" \"$@\" || return\n+\t\tfi\n+\n \tfi\n \n \t{\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex b77cce8e4..f5df0a5b4 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1116,5 +1116,44 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'setup superproject with submodules' '\n+\tgit init sub1 &&\n+\ttest_commit -C sub1 test &&\n+\ttest_commit -C sub1 test2 &&\n+\tgit init multisuper &&\n+\tgit -C multisuper submodule add ../sub1 sub0 &&\n+\tgit -C multisuper submodule add ../sub1 sub1 &&\n+\tgit -C multisuper submodule add ../sub1 sub2 &&\n+\tgit -C multisuper submodule add ../sub1 sub3 &&\n+\tgit -C multisuper commit -m \"add some submodules\"\n+'\n+\n+cat >expect <<-EOF\n+-sub0\n+ sub1 (test2)\n+ sub2 (test2)\n+ sub3 (test2)\n+EOF\n+\n+test_expect_success 'submodule update --init with a specification' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule update --init . \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update --init-active' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config submodule.active \".\" &&\n+\tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_must_fail git -C multisuper_clone submodule update --init-active sub0 &&\n+\ttest_cmp expect actual\n+'\n \n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313602","messageId":"20170309012345.180702-9-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 08/11] clone: add --submodule-spec=<pathspec> switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:42Z","receivedAt":"2017-03-09T01:33:51Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch passes the pathspec to `git submodule update\n--init-active` which is called after the actual clone is done.\n\nAdditionally this configures the submodule.active option to\nbe the given pathspec, such that any future invocation of\n`git submodule update --init-active` will keep up\nwith the pathspec.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-clone.txt | 23 ++++++++++-----\n builtin/clone.c             | 36 +++++++++++++++++++++--\n t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 120 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 35cc34b2f..9692eab30 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -15,7 +15,8 @@ SYNOPSIS\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n \t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n-\t  [--jobs <n>] [--] <repository> [<directory>]\n+\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n+\t  <repository> [<directory>]\n \n DESCRIPTION\n -----------\n@@ -217,12 +218,20 @@ objects from the source repository into a pack in the cloned repository.\n \n --recursive::\n --recurse-submodules::\n-\tAfter the clone is created, initialize all submodules within,\n-\tusing their default settings. This is equivalent to running\n-\t`git submodule update --init --recursive` immediately after\n-\tthe clone is finished. This option is ignored if the cloned\n-\trepository does not have a worktree/checkout (i.e. if any of\n-\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\tAfter the clone is created, initialize and clone all submodules\n+\twithin, using their default settings. This is equivalent to\n+\trunning `git submodule update --recursive --init` immediately\n+\tafter the clone is finished. This option is ignored if the\n+\tcloned repository does not have a worktree/checkout (i.e.  if\n+\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\n+--submodule-spec::\n+\tAfter the clone is created, initialize and clone specified\n+\tsubmodules within, using their default settings. It is possible\n+\tto give multiple specifications by giving this argument multiple\n+\ttimes. This is equivalent to configuring `submodule.active`\n+\tand then running `git submodule update --init-active`\n+\timmediately after the clone is finished.\n \n --[no-]shallow-submodules::\n \tAll submodules which are cloned will be shallow with a depth of 1.\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 5ef81927a..15a8d3ef0 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -56,6 +56,16 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list submodule_spec;\n+\n+static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\treturn -1;\n+\n+\tstring_list_append((struct string_list *)opt->value, arg);\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -112,6 +122,9 @@ static struct option builtin_clone_options[] = {\n \t\t\tTRANSPORT_FAMILY_IPV4),\n \tOPT_SET_INT('6', \"ipv6\", &family, N_(\"use IPv6 addresses only\"),\n \t\t\tTRANSPORT_FAMILY_IPV6),\n+\tOPT_CALLBACK(0, \"submodule-spec\", &submodule_spec, N_(\"<pathspec>\"),\n+\t\t\tN_(\"clone specific submodules. Pass multiple times for complex pathspecs\"),\n+\t\t\tsubmodule_spec_cb),\n \tOPT_END()\n };\n \n@@ -733,13 +746,21 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && option_recursive) {\n+\tif (!err && (option_recursive || submodule_spec.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n-\t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n+\t\targv_array_pushl(&args, \"submodule\", \"update\", NULL);\n+\n+\t\tif (submodule_spec.nr > 0)\n+\t\t\targv_array_pushf(&args, \"--init-active\");\n+\t\telse\n+\t\t\targv_array_pushf(&args, \"--init\");\n \n \t\tif (option_shallow_submodules == 1)\n \t\t\targv_array_push(&args, \"--depth=1\");\n \n+\t\tif (option_recursive)\n+\t\t\targv_array_pushf(&args, \"--recursive\");\n+\n \t\tif (max_jobs != -1)\n \t\t\targv_array_pushf(&args, \"--jobs=%d\", max_jobs);\n \n@@ -887,6 +908,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\toption_no_checkout = 1;\n \t}\n \n+\tif (submodule_spec.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tfor_each_string_list_item(item, &submodule_spec) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\t}\n+\n \tif (!option_origin)\n \t\toption_origin = \"origin\";\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex f5df0a5b4..39364ef68 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1156,4 +1156,74 @@ test_expect_success 'submodule update --init-active' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'clone --submodule-spec works' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expected <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t-sub2\n+\t-sub3\n+\tEOF\n+\n+\tgit clone --recurse-submodules --submodule-spec=\"sub0\" multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'clone with multiple --submodule-spec options' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expect <<-\\EOF &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat <<-\\EOF >expect &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tcat <<-\\EOF >expect2 &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\t-sub4\n+\t sub5 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  --submodule-spec \":(exclude)sub4\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit -C multisuper submodule add ../sub1 sub4 &&\n+\tgit -C multisuper submodule add ../sub1 sub5 &&\n+\tgit -C multisuper commit -m \"add more submodules\" &&\n+\t# obtain the new superproject\n+\tgit -C multisuper_clone pull &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect2 actual\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313603","messageId":"20170309012345.180702-11-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 10/11] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:44Z","receivedAt":"2017-03-09T01:33:52Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"When initializing a submodule set the submodule.<name>.active config to\ntrue to indicate that the submodule is active.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex bceb62a20..44f2c02ba 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -329,6 +329,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n \t\t\tdisplaypath);\n \n+\t/* Set active flag for the submodule being initialized */\n+\tif (!is_submodule_initialized(path)) {\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n+\t\tgit_config_set_gently(sb.buf, \"true\");\n+\t}\n+\n \t/*\n \t * Copy url setting when it is not set yet.\n \t * To look up the url in .git/config, we must not fall back to\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313605","messageId":"CAGZ79kZG+Y+AtYYxeE5hmsNxfwmNp1h7aKAem=JD3yiKB6STPw@mail.gmail.com","threadId":"45207","inReplyTo":"20170309012345.180702-4-bmwill@google.com","subject":"Re: [PATCH v2 03/11] submodule deinit: use most reliable url","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-09T01:56:11Z","receivedAt":"2017-03-09T02:06:53Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> The user could have configured the submodule to have a different URL\n> from the one in the superproject's config.  To account for this read\n> what the submodule has configured for remote.origin.url and use that\n> instead.\n\nWhen reading this commit message, I first thought this is an unrelated\nbug fix. However it is not unrelated. In a later patch you introduce a mode\nwhere submodule.<name>.url may not exist in .git/config any more,\n(there may be a .existence flag instead?) such that url=\"\", which is\nobviously a bad UI:\n\n    Submodule '$name' (<empty string>) unregistered for path '$displaypath'\"\n\nLike the first patch of this series, we could have a helper function\n\"git submodule--helper url <name>\" that figures out how to get the URL:\n1) Look into that GIT_DIR\n2) if non-existent check .git/config for the URL or\n3) fall back to .gitmodules?\n\nInstead of having such a helper, we directly look into that first option\nhoping it exists, however it doesn't have to:\n\n  git submodule init <ps>\n  # no command in between\n  git submodule deinit <ps>\n  # submodule was not cloned yet, but we still test positive for\n    > # Remove the .git/config entries (unless the user already did it)\n    > if test -n \"$(git config --get-regexp submodule.\"$name\\.\")\"\n\nI am not sure if there is an easy way out here.\n\nThinking about the name for such a url helper lookup, I wonder if\nwe want to have\n\n    git submodule--helper show-url <name>\n\nas potentially we end up having this issue for a lot\nof different things (e.g. submodule.<name>.shallow = (true,false),\nor in case the submodule is cloned you can give the actual depth\nas an integral number), so maybe we'd want to introduce one\nlayer of indirection\n\n    git submodule--helper ask-property \\\n       (is-active/URL/depth/size/..) <name>\n\nSo with that said, I wonder if we also want to ease up:\n\n    GIT_DIR=\"$(git rev-parse --git-path modules/$name\n\nto be\n\n    GIT_DIR=$(git submodule--helper show-git-dir $name)\n\n>                 then\n>                         # Remove the whole section so we have a clean state when\n>                         # the user later decides to init this submodule again\n> -                       url=$(git config submodule.\"$name\".url)\n> +                       url=$(GIT_DIR=\"$(git rev-parse --git-path modules/$name)\" git config remote.origin.url)\n\nIn the submodule helper we have get_default_remote(), which we do not\nhave in shell\n(which we seemed to have in shell?), so maybe it's worth not using origin here,\nalthough I guess it is rare that the original remote is named other than origin.\n\n>                         git config --remove-section submodule.\"$name\" 2>/dev/null &&\n>                         say \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n>                 fi\n> --\n> 2.12.0.246.ga2ecc84866-goog\n>\n\nThanks,\nStefan\n"},{"id":"313606","messageId":"CAGZ79kbyyJCZ7iP6c7RBgrv8NNSMjb9fov3eFazpOb2QL5aAcg@mail.gmail.com","threadId":"45207","inReplyTo":"20170309012345.180702-8-bmwill@google.com","subject":"Re: [PATCH v2 07/11] submodule update: add `--init-active` switch","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-09T02:16:23Z","receivedAt":"2017-03-09T02:17:54Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> The new switch `--init-active` initializes the submodules which are\n> configured in `submodule.active` instead of those given as\n> command line arguments before updating. In the first implementation this\n> is made incompatible with further command line arguments as it is\n> unclear what the user means by\n>\n>     git submodule update --init --init-active <paths>\n>\n> This new switch allows users to record more complex patterns as it saves\n> retyping them whenever you invoke update.\n>\n> Based on a patch by Stefan Beller <sbeller@google.com>\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n\n\n\n> @@ -568,7 +573,17 @@ cmd_update()\n>\n>         if test -n \"$init\"\n>         then\n> -               cmd_init \"--\" \"$@\" || return\n> +               if test \"$init\" = \"by_config\"\n> +               then\n> +                       if test $# -gt 0\n> +                       then\n> +                               die \"$(gettext \"path arguments are incompatible with --init-active\")\"\n> +                       fi\n> +                       cmd_init \"--\" $(git config --get-all submodule.active) || return\n\nWhat happens with submodule.<name>.actives here?\n"},{"id":"313607","messageId":"CAGZ79kYspNw4=dSnDtyWp7bEhggAM-gRo3g9GJ78jZ8HW7pUFQ@mail.gmail.com","threadId":"45207","inReplyTo":"20170309012345.180702-11-bmwill@google.com","subject":"Re: [PATCH v2 10/11] submodule--helper init: set submodule.<name>.active","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-09T02:28:35Z","receivedAt":"2017-03-09T02:29:19Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> When initializing a submodule set the submodule.<name>.active config to\n> true to indicate that the submodule is active.\n\nSo by this patch an init of a submodule performs both\na \"regular init\" (copy URL and the update setting)\nas well as setting the new submodule.<name>.active.\n\nAnd both happens in the same config file (i.e. no worktree\nsupport here)\n\nLater on we *could* remove the URL as the .active is the new\nflag of existence.\n\nBut enough of my speculation, I am left wondering what this\npatch accomplishes, as this states no agenda as why it is useful\non its own.\n\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  builtin/submodule--helper.c | 7 +++++++\n>  1 file changed, 7 insertions(+)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index bceb62a20..44f2c02ba 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -329,6 +329,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>                 die(_(\"No url found for submodule path '%s' in .gitmodules\"),\n>                         displaypath);\n>\n> +       /* Set active flag for the submodule being initialized */\n> +       if (!is_submodule_initialized(path)) {\n> +               strbuf_reset(&sb);\n> +               strbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n> +               git_config_set_gently(sb.buf, \"true\");\n> +       }\n> +\n>         /*\n>          * Copy url setting when it is not set yet.\n>          * To look up the url in .git/config, we must not fall back to\n> --\n> 2.12.0.246.ga2ecc84866-goog\n>\n"},{"id":"313611","messageId":"20170309012345.180702-4-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v2 03/11] submodule deinit: use most reliable url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T01:23:37Z","receivedAt":"2017-03-09T04:17:52Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The user could have configured the submodule to have a different URL\nfrom the one in the superproject's config.  To account for this read\nwhat the submodule has configured for remote.origin.url and use that\ninstead.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 19660b9c0..1c2064cc1 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -455,7 +455,7 @@ Submodule work tree '\\$displaypath' contains a .git directory\n \t\tthen\n \t\t\t# Remove the whole section so we have a clean state when\n \t\t\t# the user later decides to init this submodule again\n-\t\t\turl=$(git config submodule.\"$name\".url)\n+\t\t\turl=$(GIT_DIR=\"$(git rev-parse --git-path modules/$name)\" git config remote.origin.url)\n \t\t\tgit config --remove-section submodule.\"$name\" 2>/dev/null &&\n \t\t\tsay \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n \t\tfi\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313654","messageId":"20170309175621.GC153031@google.com","threadId":"45207","inReplyTo":"CAGZ79kYspNw4=dSnDtyWp7bEhggAM-gRo3g9GJ78jZ8HW7pUFQ@mail.gmail.com","subject":"Re: [PATCH v2 10/11] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T17:56:21Z","receivedAt":"2017-03-09T17:57:15Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/08, Stefan Beller wrote:\n> On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> > When initializing a submodule set the submodule.<name>.active config to\n> > true to indicate that the submodule is active.\n> \n> So by this patch an init of a submodule performs both\n> a \"regular init\" (copy URL and the update setting)\n> as well as setting the new submodule.<name>.active.\n> \n> And both happens in the same config file (i.e. no worktree\n> support here)\n\nWell there isn't any per-worktree config yet (unless that series managed\nto land and I didn't notice that).  So once their are per-worktree\nconfigs we would need to push this to there.\n\n> \n> Later on we *could* remove the URL as the .active is the new\n> flag of existence.\n> \n> But enough of my speculation, I am left wondering what this\n> patch accomplishes, as this states no agenda as why it is useful\n> on its own.\n> \n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  builtin/submodule--helper.c | 7 +++++++\n> >  1 file changed, 7 insertions(+)\n> >\n> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> > index bceb62a20..44f2c02ba 100644\n> > --- a/builtin/submodule--helper.c\n> > +++ b/builtin/submodule--helper.c\n> > @@ -329,6 +329,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n> >                 die(_(\"No url found for submodule path '%s' in .gitmodules\"),\n> >                         displaypath);\n> >\n> > +       /* Set active flag for the submodule being initialized */\n> > +       if (!is_submodule_initialized(path)) {\n> > +               strbuf_reset(&sb);\n> > +               strbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n> > +               git_config_set_gently(sb.buf, \"true\");\n> > +       }\n> > +\n> >         /*\n> >          * Copy url setting when it is not set yet.\n> >          * To look up the url in .git/config, we must not fall back to\n> > --\n> > 2.12.0.246.ga2ecc84866-goog\n> >\n\n-- \nBrandon Williams\n"},{"id":"313655","messageId":"20170309180812.GD153031@google.com","threadId":"45207","inReplyTo":"CAGZ79kbyyJCZ7iP6c7RBgrv8NNSMjb9fov3eFazpOb2QL5aAcg@mail.gmail.com","subject":"Re: [PATCH v2 07/11] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T18:08:12Z","receivedAt":"2017-03-09T18:08:42Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/08, Stefan Beller wrote:\n> On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> > The new switch `--init-active` initializes the submodules which are\n> > configured in `submodule.active` instead of those given as\n> > command line arguments before updating. In the first implementation this\n> > is made incompatible with further command line arguments as it is\n> > unclear what the user means by\n> >\n> >     git submodule update --init --init-active <paths>\n> >\n> > This new switch allows users to record more complex patterns as it saves\n> > retyping them whenever you invoke update.\n> >\n> > Based on a patch by Stefan Beller <sbeller@google.com>\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> \n> \n> \n> > @@ -568,7 +573,17 @@ cmd_update()\n> >\n> >         if test -n \"$init\"\n> >         then\n> > -               cmd_init \"--\" \"$@\" || return\n> > +               if test \"$init\" = \"by_config\"\n> > +               then\n> > +                       if test $# -gt 0\n> > +                       then\n> > +                               die \"$(gettext \"path arguments are incompatible with --init-active\")\"\n> > +                       fi\n> > +                       cmd_init \"--\" $(git config --get-all submodule.active) || return\n> \n> What happens with submodule.<name>.actives here?\n\nNothing?  I am still not 100% certain that we really need the\nsubmodule.<name>.active config but it seemed like what we decided upon\nlast we discussed this.\n\nMaybe we don't even need this as an option?  Maybe update should be able\nto just 'update' all active submodules without having to make an\nexplicit call to cmd_init?\n\n-- \nBrandon Williams\n"},{"id":"313661","messageId":"20170309181545.GE153031@google.com","threadId":"45207","inReplyTo":"CAGZ79kZG+Y+AtYYxeE5hmsNxfwmNp1h7aKAem=JD3yiKB6STPw@mail.gmail.com","subject":"Re: [PATCH v2 03/11] submodule deinit: use most reliable url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-09T18:15:45Z","receivedAt":"2017-03-09T18:23:50Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/08, Stefan Beller wrote:\n> On Wed, Mar 8, 2017 at 5:23 PM, Brandon Williams <bmwill@google.com> wrote:\n> > The user could have configured the submodule to have a different URL\n> > from the one in the superproject's config.  To account for this read\n> > what the submodule has configured for remote.origin.url and use that\n> > instead.\n> \n> When reading this commit message, I first thought this is an unrelated\n> bug fix. However it is not unrelated. In a later patch you introduce a mode\n> where submodule.<name>.url may not exist in .git/config any more,\n> (there may be a .existence flag instead?) such that url=\"\", which is\n> obviously a bad UI:\n\nSo the later patch doesn't actually omit submodule.<name>.url but we\ncould end up with this if you init and then deinit without actually\ncloning the submodule.  So maybe the best bet is to drop this patch from\nthe series and we can include one like it in a follow up which uses a\nhelper function that you suggest.\n\n> \n>     Submodule '$name' (<empty string>) unregistered for path '$displaypath'\"\n> \n> Like the first patch of this series, we could have a helper function\n> \"git submodule--helper url <name>\" that figures out how to get the URL:\n> 1) Look into that GIT_DIR\n> 2) if non-existent check .git/config for the URL or\n> 3) fall back to .gitmodules?\n> \n> Instead of having such a helper, we directly look into that first option\n> hoping it exists, however it doesn't have to:\n> \n>   git submodule init <ps>\n>   # no command in between\n>   git submodule deinit <ps>\n>   # submodule was not cloned yet, but we still test positive for\n>     > # Remove the .git/config entries (unless the user already did it)\n>     > if test -n \"$(git config --get-regexp submodule.\"$name\\.\")\"\n> \n> I am not sure if there is an easy way out here.\n> \n> Thinking about the name for such a url helper lookup, I wonder if\n> we want to have\n> \n>     git submodule--helper show-url <name>\n> \n> as potentially we end up having this issue for a lot\n> of different things (e.g. submodule.<name>.shallow = (true,false),\n> or in case the submodule is cloned you can give the actual depth\n> as an integral number), so maybe we'd want to introduce one\n> layer of indirection\n> \n>     git submodule--helper ask-property \\\n>        (is-active/URL/depth/size/..) <name>\n> \n> So with that said, I wonder if we also want to ease up:\n> \n>     GIT_DIR=\"$(git rev-parse --git-path modules/$name\n> \n> to be\n> \n>     GIT_DIR=$(git submodule--helper show-git-dir $name)\n> \n> >                 then\n> >                         # Remove the whole section so we have a clean state when\n> >                         # the user later decides to init this submodule again\n> > -                       url=$(git config submodule.\"$name\".url)\n> > +                       url=$(GIT_DIR=\"$(git rev-parse --git-path modules/$name)\" git config remote.origin.url)\n> \n> In the submodule helper we have get_default_remote(), which we do not\n> have in shell\n> (which we seemed to have in shell?), so maybe it's worth not using origin here,\n> although I guess it is rare that the original remote is named other than origin.\n> \n> >                         git config --remove-section submodule.\"$name\" 2>/dev/null &&\n> >                         say \"$(eval_gettext \"Submodule '\\$name' (\\$url) unregistered for path '\\$displaypath'\")\"\n> >                 fi\n> > --\n> > 2.12.0.246.ga2ecc84866-goog\n> >\n> \n> Thanks,\n> Stefan\n\n-- \nBrandon Williams\n"},{"id":"313978","messageId":"20170313214341.172676-1-bmwill@google.com","threadId":"45207","inReplyTo":"20170309012345.180702-1-bmwill@google.com","subject":"[PATCH v3 00/10] decoupling a submodule's existence and its url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:31Z","receivedAt":"2017-03-13T21:43:51Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"changes in v3:\n\n* Droped a patch which tried to use a more accurate URL for deinit.  It didn't\n  really fit inside the scope of this series.  It may be something we want to\n  revisit later though.\n\n* The --init-active flag now ensure that all submodules which are configured to\n  be 'active' (either via 'submodule.active' or 'submodule.<name>.active') go\n  through the initialization phase and have their relevent info copied over to\n  the config.\n\n\nBrandon Williams (10):\n  submodule--helper: add is_active command\n  submodule status: use submodule--helper is-active\n  submodule sync: use submodule--helper is-active\n  submodule--helper clone: check for configured submodules using helper\n  submodule: decouple url and submodule existence\n  submodule update: add `--init-active` switch\n  clone: add --submodule-spec=<pathspec> switch\n  completion: clone can initialize specific submodules\n  submodule--helper init: set submodule.<name>.active\n  submodule add: respect submodule.active and submodule.<name>.active\n\n Documentation/config.txt               |  15 +++-\n Documentation/git-clone.txt            |  23 ++++--\n Documentation/git-submodule.txt        |   9 +++\n builtin/clone.c                        |  36 +++++++++-\n builtin/submodule--helper.c            |  68 ++++++++++++++----\n contrib/completion/git-completion.bash |   1 +\n git-submodule.sh                       |  43 +++++++++--\n submodule.c                            |  36 ++++++++--\n t/t7400-submodule-basic.sh             | 128 +++++++++++++++++++++++++++++++++\n t/t7413-submodule-is-active.sh         | 107 +++++++++++++++++++++++++++\n 10 files changed, 431 insertions(+), 35 deletions(-)\n create mode 100755 t/t7413-submodule-is-active.sh\n\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313979","messageId":"20170313214341.172676-2-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 01/10] submodule--helper: add is_active command","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:32Z","receivedAt":"2017-03-13T21:43:53Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"There are a lot of places where an explicit check for\nsubmodule.\"<name>\".url is done to see if a submodule exists.  In order\nto centralize this check introduce a helper which can be used to query\nif a submodule is active or not.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c    | 11 +++++++++++\n t/t7413-submodule-is-active.sh | 31 +++++++++++++++++++++++++++++++\n 2 files changed, 42 insertions(+)\n create mode 100755 t/t7413-submodule-is-active.sh\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 15a5430c0..5fe7e23b1 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1127,6 +1127,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int is_active(int argc, const char **argv, const char *prefix)\n+{\n+\tif (argc != 2)\n+\t\tdie(\"submodule--helper is-active takes exactly 1 arguments\");\n+\n+\tgitmodules_config();\n+\n+\treturn !is_submodule_initialized(argv[1]);\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -1146,6 +1156,7 @@ static struct cmd_struct commands[] = {\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n+\t{\"is-active\", is_active, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nnew file mode 100755\nindex 000000000..f18e0c925\n--- /dev/null\n+++ b/t/t7413-submodule-is-active.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+\n+test_description='Test submodule--helper is-active\n+\n+This test verifies that `git submodue--helper is-active` correclty identifies\n+submodules which are \"active\" and interesting to the user.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tgit init sub &&\n+\ttest_commit -C sub initial &&\n+\tgit init super &&\n+\ttest_commit -C super initial &&\n+\tgit -C super submodule add ../sub sub1 &&\n+\tgit -C super submodule add ../sub sub2 &&\n+\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n+'\n+\n+test_expect_success 'is-active works with urls' '\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313980","messageId":"20170313214341.172676-3-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:33Z","receivedAt":"2017-03-13T21:43:56Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 136e26a2c..ab233712d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1010,14 +1010,13 @@ cmd_status()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n \t\t\tcontinue\n \t\tfi\n-\t\tif test -z \"$url\" ||\n+\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n \t\t{\n \t\t\t! test -d \"$sm_path\"/.git &&\n \t\t\t! test -f \"$sm_path\"/.git\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313981","messageId":"20170313214341.172676-4-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 03/10] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:34Z","receivedAt":"2017-03-13T21:43:58Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ab233712d..e2d08595f 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1111,7 +1111,7 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tif git submodule--helper is-active \"$sm_path\"\n \t\tthen\n \t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313982","messageId":"20170313214341.172676-6-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:36Z","receivedAt":"2017-03-13T21:44:02Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Currently the submodule.<name>.url config option is used to determine\nif a given submodule exists and is interesting to the user.  This\nhowever doesn't work very well because the URL is a config option for\nthe scope of a repository, whereas the existence of a submodule is an\noption scoped to the working tree.\n\nIn a future with worktree support for submodules, there will be multiple\nworking trees, each of which may only need a subset of the submodules\nchecked out.  The URL (which is where the submodule repository can be\nobtained) should not differ between different working trees.\n\nIt may also be convenient for users to more easily specify groups of\nsubmodules they are interested in as apposed to running \"git submodule\ninit <path>\" on each submodule they want checked out in their working\ntree.\n\nTo this end two config options are introduced, submodule.active and\nsubmodule.<name>.active.  The submodule.active config holds a pathspec\nthat specifies which submodules should exist in the working tree.  The\nsubmodule.<name>.active config is a boolean flag used to indicate if\nthat particular submodule should exist in the working tree.\n\nGiven these multiple ways to check for a submodule's existence the more\nfine-grained submodule.<name>.active option has the highest order of\nprecedence followed by the pathspec check against submodule.active. To\nensure backwards compatibility, if neither of these options are set git\nfalls back to checking the submodule.<name>.url option to determine a\nsubmodule's existence.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/config.txt       | 15 ++++++++++--\n submodule.c                    | 36 ++++++++++++++++++++++++---\n t/t7413-submodule-is-active.sh | 55 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 100 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5e5c2ae5f..d2d79b9d4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -2920,8 +2920,9 @@ submodule.<name>.url::\n \tThe URL for a submodule. This variable is copied from the .gitmodules\n \tfile to the git config via 'git submodule init'. The user can change\n \tthe configured URL before obtaining the submodule via 'git submodule\n-\tupdate'. After obtaining the submodule, the presence of this variable\n-\tis used as a sign whether the submodule is of interest to git commands.\n+\tupdate'. If neither submodule.<name>.active or submodule.active are\n+\tset, the presence of this variable is used as a fallback to indicate\n+\twhether the submodule is of interest to git commands.\n \tSee linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.\n \n submodule.<name>.update::\n@@ -2959,6 +2960,16 @@ submodule.<name>.ignore::\n \t\"--ignore-submodules\" option. The 'git submodule' commands are not\n \taffected by this setting.\n \n+submodule.<name>.active::\n+\tBoolean value indicating if the submodule is of interest to git\n+\tcommands.  This config option takes precedence over the\n+\tsubmodule.active config option.\n+\n+submodule.active::\n+\tA repeated field which contains a pathspec used to match against a\n+\tsubmodule's path to determine if the submodule is of interest to git\n+\tcommands.\n+\n submodule.fetchJobs::\n \tSpecifies how many submodules are fetched/cloned at the same time.\n \tA positive integer allows up to that number of submodules fetched\ndiff --git a/submodule.c b/submodule.c\nindex 0a2831d84..2b33bd70f 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -217,13 +217,41 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tconst struct submodule *module = NULL;\n+\tchar *key;\n+\tconst struct string_list *sl;\n+\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n-\tmodule = submodule_from_path(null_sha1, path);\n+\t/* early return if there isn't a path->module mapping */\n+\tif (!module)\n+\t\treturn 0;\n+\n+\t/* submodule.<name>.active is set */\n+\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n+\tif (!git_config_get_bool(key, &ret)) {\n+\t\tfree(key);\n+\t\treturn ret;\n+\t}\n+\tfree(key);\n+\n+\tsl = git_config_get_value_multi(\"submodule.active\");\n \n-\tif (module) {\n-\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n+\tif (sl) {\n+\t\tstruct pathspec ps;\n+\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n+\t\tconst struct string_list_item *item;\n+\n+\t\tfor_each_string_list_item(item, sl) {\n+\t\t\targv_array_push(&args, item->string);\n+\t\t}\n+\n+\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n+\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n+\n+\t\targv_array_clear(&args);\n+\t\tclear_pathspec(&ps);\n+\t} else {\n \t\tchar *value = NULL;\n+\t\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n \n \t\tret = !git_config_get_string(key, &value);\n \ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex f18e0c925..c41b899ab 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n \tgit -C super submodule--helper is-active sub1\n '\n \n+test_expect_success 'is-active works with submodule.<name>.active config' '\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"true\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\tgit -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super config --unset submodule.sub1.active\n+'\n+\n+test_expect_success 'is-active works with basic submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active correctly works with paths that are not submodules' '\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset-all submodule.active\n+'\n+\n+test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n+\tgit -C super config --add submodule.active \"sub1\" &&\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\tgit -C super config --bool submodule.sub2.active \"true\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset-all submodule.active &&\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313983","messageId":"20170313214341.172676-8-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 07/10] clone: add --submodule-spec=<pathspec> switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:38Z","receivedAt":"2017-03-13T21:44:04Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch passes the pathspec to `git submodule update\n--init-active` which is called after the actual clone is done.\n\nAdditionally this configures the submodule.active option to\nbe the given pathspec, such that any future invocation of\n`git submodule update --init-active` will keep up\nwith the pathspec.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-clone.txt | 23 ++++++++++-----\n builtin/clone.c             | 36 +++++++++++++++++++++--\n t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 120 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 35cc34b2f..9692eab30 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -15,7 +15,8 @@ SYNOPSIS\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n \t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n-\t  [--jobs <n>] [--] <repository> [<directory>]\n+\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n+\t  <repository> [<directory>]\n \n DESCRIPTION\n -----------\n@@ -217,12 +218,20 @@ objects from the source repository into a pack in the cloned repository.\n \n --recursive::\n --recurse-submodules::\n-\tAfter the clone is created, initialize all submodules within,\n-\tusing their default settings. This is equivalent to running\n-\t`git submodule update --init --recursive` immediately after\n-\tthe clone is finished. This option is ignored if the cloned\n-\trepository does not have a worktree/checkout (i.e. if any of\n-\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\tAfter the clone is created, initialize and clone all submodules\n+\twithin, using their default settings. This is equivalent to\n+\trunning `git submodule update --recursive --init` immediately\n+\tafter the clone is finished. This option is ignored if the\n+\tcloned repository does not have a worktree/checkout (i.e.  if\n+\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n+\n+--submodule-spec::\n+\tAfter the clone is created, initialize and clone specified\n+\tsubmodules within, using their default settings. It is possible\n+\tto give multiple specifications by giving this argument multiple\n+\ttimes. This is equivalent to configuring `submodule.active`\n+\tand then running `git submodule update --init-active`\n+\timmediately after the clone is finished.\n \n --[no-]shallow-submodules::\n \tAll submodules which are cloned will be shallow with a depth of 1.\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 3f63edbbf..c6731379b 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -56,6 +56,16 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list submodule_spec;\n+\n+static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\treturn -1;\n+\n+\tstring_list_append((struct string_list *)opt->value, arg);\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -112,6 +122,9 @@ static struct option builtin_clone_options[] = {\n \t\t\tTRANSPORT_FAMILY_IPV4),\n \tOPT_SET_INT('6', \"ipv6\", &family, N_(\"use IPv6 addresses only\"),\n \t\t\tTRANSPORT_FAMILY_IPV6),\n+\tOPT_CALLBACK(0, \"submodule-spec\", &submodule_spec, N_(\"<pathspec>\"),\n+\t\t\tN_(\"clone specific submodules. Pass multiple times for complex pathspecs\"),\n+\t\t\tsubmodule_spec_cb),\n \tOPT_END()\n };\n \n@@ -733,13 +746,21 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && option_recursive) {\n+\tif (!err && (option_recursive || submodule_spec.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n-\t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n+\t\targv_array_pushl(&args, \"submodule\", \"update\", NULL);\n+\n+\t\tif (submodule_spec.nr > 0)\n+\t\t\targv_array_pushf(&args, \"--init-active\");\n+\t\telse\n+\t\t\targv_array_pushf(&args, \"--init\");\n \n \t\tif (option_shallow_submodules == 1)\n \t\t\targv_array_push(&args, \"--depth=1\");\n \n+\t\tif (option_recursive)\n+\t\t\targv_array_pushf(&args, \"--recursive\");\n+\n \t\tif (max_jobs != -1)\n \t\t\targv_array_pushf(&args, \"--jobs=%d\", max_jobs);\n \n@@ -887,6 +908,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\toption_no_checkout = 1;\n \t}\n \n+\tif (submodule_spec.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tfor_each_string_list_item(item, &submodule_spec) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\t}\n+\n \tif (!option_origin)\n \t\toption_origin = \"origin\";\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex cc348b807..c2e198a92 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1189,4 +1189,74 @@ test_expect_success 'submodule init --active and update' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'clone --submodule-spec works' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expected <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t-sub2\n+\t-sub3\n+\tEOF\n+\n+\tgit clone --recurse-submodules --submodule-spec=\"sub0\" multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'clone with multiple --submodule-spec options' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expect <<-\\EOF &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat <<-\\EOF >expect &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tcat <<-\\EOF >expect2 &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\t-sub4\n+\t sub5 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules \\\n+\t\t  --submodule-spec=\".\" \\\n+\t\t  --submodule-spec \":(exclude)sub0\" \\\n+\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\t\t  --submodule-spec \":(exclude)sub4\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit -C multisuper submodule add ../sub1 sub4 &&\n+\tgit -C multisuper submodule add ../sub1 sub5 &&\n+\tgit -C multisuper commit -m \"add more submodules\" &&\n+\t# obtain the new superproject\n+\tgit -C multisuper_clone pull &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect2 actual\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313984","messageId":"20170313214341.172676-9-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 08/10] completion: clone can initialize specific submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:39Z","receivedAt":"2017-03-13T21:44:07Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n contrib/completion/git-completion.bash | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex fc32286a4..eb13433d5 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1212,6 +1212,7 @@ _git_clone ()\n \t\t\t--recurse-submodules\n \t\t\t--no-single-branch\n \t\t\t--shallow-submodules\n+\t\t\t--submodule-spec\n \t\t\t\"\n \t\treturn\n \t\t;;\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313985","messageId":"20170313214341.172676-10-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:40Z","receivedAt":"2017-03-13T21:44:12Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"When initializing a submodule set the submodule.<name>.active config to\ntrue to indicate that the submodule is active.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex a3acc9e4c..b669ed031 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n \t\t\tdisplaypath);\n \n+\t/* Set active flag for the submodule being initialized */\n+\tif (!is_submodule_initialized(path)) {\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n+\t\tgit_config_set_gently(sb.buf, \"true\");\n+\t}\n+\n \t/*\n \t * Copy url setting when it is not set yet.\n \t * To look up the url in .git/config, we must not fall back to\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313986","messageId":"20170313214341.172676-5-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 04/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:35Z","receivedAt":"2017-03-13T21:44:19Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Use the 'is_submodule_initialized()' helper to check for configured\nsubmodules instead of manually checking for the submodule's URL in the\nconfig.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 15 +++------------\n 1 file changed, 3 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 5fe7e23b1..f38e332c5 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -759,7 +759,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstruct strbuf displaypath_sb = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *displaypath = NULL;\n-\tchar *url = NULL;\n \tint needs_cloning = 0;\n \n \tif (ce_stage(ce)) {\n@@ -793,15 +792,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\t/*\n-\t * Looking up the url in .git/config.\n-\t * We must not fall back to .gitmodules as we only want\n-\t * to process configured submodules.\n-\t */\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n-\tgit_config_get_string(sb.buf, &url);\n-\tif (!url) {\n+\t/* Check if the submodule has been initialized. */\n+\tif (!is_submodule_initialized(ce->name)) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n \t\tgoto cleanup;\n \t}\n@@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, \"--depth=1\");\n \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n-\targv_array_pushl(&child->args, \"--url\", url, NULL);\n+\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n \tif (suc->references.nr) {\n \t\tstruct string_list_item *item;\n \t\tfor_each_string_list_item(item, &suc->references)\n@@ -845,7 +837,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, suc->depth);\n \n cleanup:\n-\tfree(url);\n \tstrbuf_reset(&displaypath_sb);\n \tstrbuf_reset(&sb);\n \n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313989","messageId":"20170313214341.172676-11-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 10/10] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:41Z","receivedAt":"2017-03-13T21:44:35Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"In addition to adding submodule.<name>.url to the config, set\nsubmodule.<name>.active to true unless submodule.active is configured\nand the submodule's path matches the configured pathspec.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh               | 12 ++++++++++++\n t/t7413-submodule-is-active.sh | 21 +++++++++++++++++++++\n 2 files changed, 33 insertions(+)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 3c7da08aa..2c510038d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -278,6 +278,18 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n+\n+\tif git config --get submodule.active >/dev/null\n+\tthen\n+\t\t# If the submodule being adding isn't already covered by the\n+\t\t# current configured pathspec, set the submodule's active flag\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\t\tfi\n+\telse\n+\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\tfi\n }\n \n #\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex c41b899ab..865931978 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -15,6 +15,12 @@ test_expect_success 'setup' '\n \ttest_commit -C super initial &&\n \tgit -C super submodule add ../sub sub1 &&\n \tgit -C super submodule add ../sub sub2 &&\n+\n+\t# Remove submodule.<name>.active entries in order to test in an\n+\t# environment where only URLs are present in the conifg\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active &&\n+\n \tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n '\n \n@@ -83,4 +89,19 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active\n \tgit -C super config --unset submodule.sub2.active\n '\n \n+test_expect_success 'is-active, submodule.active and submodule add' '\n+\ttest_when_finished \"rm -rf super2\" &&\n+\tgit init super2 &&\n+\ttest_commit -C super2 initial &&\n+\tgit -C super2 config --add submodule.active \"sub*\" &&\n+\n+\t# submodule add should only add submodule.<name>.active\n+\t# to the config if not matched by the pathspec\n+\tgit -C super2 submodule add ../sub sub1 &&\n+\ttest_must_fail git -C super2 config --get submodule.sub1.active &&\n+\n+\tgit -C super2 submodule add ../sub mod &&\n+\tgit -C super2 config --get submodule.mod.active\n+'\n+\n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313990","messageId":"20170313214341.172676-7-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v3 06/10] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-13T21:43:37Z","receivedAt":"2017-03-13T21:44:37Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The new switch `--init-active` initializes the submodules which are\nconfigured in `submodule.active` and `submodule.<name>.active` instead\nof those given as command line arguments before updating. In the first\nimplementation this is made incompatible with further command line\narguments as it is unclear what the user means by\n\n    git submodule update --init --init-active <paths>\n\nThis new switch allows users to record more complex patterns as it saves\nretyping them whenever you invoke update.\n\nBased on a patch by Stefan Beller <sbeller@google.com>\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-submodule.txt |  9 +++++++\n builtin/submodule--helper.c     | 35 ++++++++++++++++++++++++-\n git-submodule.sh                | 26 +++++++++++++++---\n t/t7400-submodule-basic.sh      | 58 +++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 123 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex e05d0cdde..6b17cd707 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -198,6 +198,10 @@ If the submodule is not yet initialized, and you just want to use the\n setting as stored in .gitmodules, you can automatically initialize the\n submodule with the `--init` option.\n \n+You can configure a set of submodules using pathspec syntax in\n+submodule.active you can use `--init-active` to initialize\n+those before updating.\n+\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n@@ -384,6 +388,11 @@ the submodule itself.\n \tInitialize all submodules for which \"git submodule init\" has not been\n \tcalled so far before updating.\n \n+--init-active::\n+\tThis option is only valid for the update command.\n+\tInitialize all submodules configured in \"`submodule.active`\"\n+\tthat have not been updated before.\n+\n --name::\n \tThis option is only valid for the add command. It sets the submodule's\n \tname to the given string instead of defaulting to its path. The name\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f38e332c5..a3acc9e4c 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -270,6 +270,34 @@ static int module_list_compute(int argc, const char **argv,\n \treturn result;\n }\n \n+static void module_list_active(struct module_list *list)\n+{\n+\tint i;\n+\n+\tif (read_cache() < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tgitmodules_config();\n+\n+\tfor (i = 0; i < active_nr; i++) {\n+\t\tconst struct cache_entry *ce = active_cache[i];\n+\n+\t\tif (!S_ISGITLINK(ce->ce_mode) ||\n+\t\t    !is_submodule_initialized(ce->name))\n+\t\t\tcontinue;\n+\n+\t\tALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n+\t\tlist->entries[list->nr++] = ce;\n+\t\twhile (i + 1 < active_nr &&\n+\t\t       !strcmp(ce->name, active_cache[i + 1]->name))\n+\t\t\t/*\n+\t\t\t * Skip entries with the same name in different stages\n+\t\t\t * to make sure an entry is returned only once.\n+\t\t\t */\n+\t\t\ti++;\n+\t}\n+}\n+\n static int module_list(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -402,9 +430,12 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \tstruct pathspec pathspec;\n \tstruct module_list list = MODULE_LIST_INIT;\n \tint quiet = 0;\n+\tint active = 0;\n \tint i;\n \n \tstruct option module_init_options[] = {\n+\t\tOPT_BOOL(0, \"active\", &active,\n+\t\t\t N_(\"ensure all active submodules are properly initialized\")),\n \t\tOPT__QUIET(&quiet, N_(\"Suppress output for initializing a submodule\")),\n \t\tOPT_END()\n \t};\n@@ -417,7 +448,9 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, module_init_options,\n \t\t\t     git_submodule_helper_usage, 0);\n \n-\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\tif (active)\n+\t\tmodule_list_active(&list);\n+\telse if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n \t\treturn 1;\n \n \tfor (i = 0; i < list.nr; i++)\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex e2d08595f..3c7da08aa 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -9,7 +9,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n-   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -363,6 +363,9 @@ cmd_init()\n \t\t-q|--quiet)\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n+\t\t--active)\n+\t\t\tGIT_ACTIVE=1\n+\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -377,7 +380,7 @@ cmd_init()\n \t\tshift\n \tdone\n \n-\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper init ${GIT_QUIET:+--quiet}  \"$@\"\n+\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper init ${GIT_QUIET:+--quiet} ${GIT_ACTIVE:+--active} \"$@\"\n }\n \n #\n@@ -506,7 +509,12 @@ cmd_update()\n \t\t\tprogress=\"--progress\"\n \t\t\t;;\n \t\t-i|--init)\n-\t\t\tinit=1\n+\t\t\ttest -z $init || test $init = by_args || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_args\n+\t\t\t;;\n+\t\t--init-active)\n+\t\t\ttest -z $init || test $init = by_config || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n+\t\t\tinit=by_config\n \t\t\t;;\n \t\t--remote)\n \t\t\tremote=1\n@@ -575,7 +583,17 @@ cmd_update()\n \n \tif test -n \"$init\"\n \tthen\n-\t\tcmd_init \"--\" \"$@\" || return\n+\t\tif test \"$init\" = \"by_config\"\n+\t\tthen\n+\t\t\tif test $# -gt 0\n+\t\t\tthen\n+\t\t\t\tdie \"$(gettext \"path arguments are incompatible with --init-active\")\"\n+\t\t\tfi\n+\t\t\tcmd_init \"--active\" || return\n+\t\telse\n+\t\t\tcmd_init \"--\" \"$@\" || return\n+\t\tfi\n+\n \tfi\n \n \t{\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex c09ce0d4c..cc348b807 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1130,5 +1130,63 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'setup superproject with submodules' '\n+\tgit init sub1 &&\n+\ttest_commit -C sub1 test &&\n+\ttest_commit -C sub1 test2 &&\n+\tgit init multisuper &&\n+\tgit -C multisuper submodule add ../sub1 sub0 &&\n+\tgit -C multisuper submodule add ../sub1 sub1 &&\n+\tgit -C multisuper submodule add ../sub1 sub2 &&\n+\tgit -C multisuper submodule add ../sub1 sub3 &&\n+\tgit -C multisuper commit -m \"add some submodules\"\n+'\n+\n+cat >expect <<-EOF\n+-sub0\n+ sub1 (test2)\n+ sub2 (test2)\n+ sub3 (test2)\n+EOF\n+\n+test_expect_success 'submodule update --init with a specification' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule update --init . \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update --init-active' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config submodule.active \".\" &&\n+\tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_must_fail git -C multisuper_clone submodule update --init-active sub0 &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule init --active and update' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config --bool submodule.sub0.active \"true\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub1.active \"false\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub2.active \"true\" &&\n+\n+\tcat >expect <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t sub2 (test2)\n+\t-sub3\n+\tEOF\n+\tgit -C multisuper_clone submodule update &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n \n test_done\n-- \n2.12.0.246.ga2ecc84866-goog\n\n"},{"id":"313998","messageId":"CAGZ79kY_hPYT8hEbQ-S6ahitfU2d1GHwCz44UKVCHgCSRpHy0g@mail.gmail.com","threadId":"45207","inReplyTo":"20170313214341.172676-2-bmwill@google.com","subject":"Re: [PATCH v3 01/10] submodule--helper: add is_active command","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-13T22:36:54Z","receivedAt":"2017-03-13T22:37:00Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Mar 13, 2017 at 2:43 PM, Brandon Williams <bmwill@google.com> wrote:\n> There are a lot of places where an explicit check for\n> submodule.\"<name>\".url is done to see if a submodule exists.  In order\n> to centralize this check introduce a helper which can be used to query\n> if a submodule is active or not.\n\nWith this patch in mind, I need to take notes for rerolling\nhttp://public-inbox.org/git/20170209020855.23486-1-sbeller@google.com/\n\n>  #define SUPPORT_SUPER_PREFIX (1<<0)\n...\n> +       {\"is-active\", is_active, 0},\n\nI think you can even mark it as SUPPORT_SUPER_PREFIX.\nThe only messages produced are from die()ing in git_config_get_string\nin is_submodule_initialized.\n\nThis alone doesn't warrant a reroll though; just in case you do reroll, this\nmay be worth checking.\n"},{"id":"314002","messageId":"CAGZ79kaqNUV_Wa_9-PSTf=NU7EcKASHqk6NcmGZSX5r610Zdew@mail.gmail.com","threadId":"45207","inReplyTo":"20170313214341.172676-6-bmwill@google.com","subject":"Re: [PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-13T22:49:31Z","receivedAt":"2017-03-13T22:49:38Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"+ cc Jens, FYI.\n\nOnce upon a time I brought up different addressing/activating mechanism for\nsubmodules and I remember Jens having some uneasy thoughts about\nthat back in the day. This series addresses the user confusion and documentation\nbetter than what I had back then.\n\nOn Mon, Mar 13, 2017 at 2:43 PM, Brandon Williams <bmwill@google.com> wrote:\n> Currently the submodule.<name>.url config option is used to determine\n> if a given submodule exists and is interesting to the user.  This\n> however doesn't work very well because the URL is a config option for\n> the scope of a repository, whereas the existence of a submodule is an\n> option scoped to the working tree.\n>\n> In a future with worktree support for submodules, there will be multiple\n> working trees, each of which may only need a subset of the submodules\n> checked out.  The URL (which is where the submodule repository can be\n> obtained) should not differ between different working trees.\n>\n> It may also be convenient for users to more easily specify groups of\n> submodules they are interested in as apposed to running \"git submodule\n> init <path>\" on each submodule they want checked out in their working\n> tree.\n>\n> To this end two config options are introduced, submodule.active and\n> submodule.<name>.active.  The submodule.active config holds a pathspec\n> that specifies which submodules should exist in the working tree.  The\n> submodule.<name>.active config is a boolean flag used to indicate if\n> that particular submodule should exist in the working tree.\n>\n> Given these multiple ways to check for a submodule's existence the more\n> fine-grained submodule.<name>.active option has the highest order of\n> precedence followed by the pathspec check against submodule.active. To\n> ensure backwards compatibility, if neither of these options are set git\n> falls back to checking the submodule.<name>.url option to determine a\n> submodule's existence.\n>\n\n\n\n\n>\n> +submodule.<name>.active::\n> +       Boolean value indicating if the submodule is of interest to git\n> +       commands.  This config option takes precedence over the\n> +       submodule.active config option.\n\n... which itself takes precedence over the (deprecated) .URL\nWe conveniently do not talk about the URL here anymore.\nBut! We need to change submodule.<name>.URL now?\n"},{"id":"314003","messageId":"CAGZ79kZ8mRT8HfxNjJ+CG0Abyubs=uF=R4NWuK9Cyhx0_H3niA@mail.gmail.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"Re: [PATCH v3 00/10] decoupling a submodule's existence and its url","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-13T22:51:22Z","receivedAt":"2017-03-13T22:51:28Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Mar 13, 2017 at 2:43 PM, Brandon Williams <bmwill@google.com> wrote:\n> changes in v3:\n>\n> * Droped a patch which tried to use a more accurate URL for deinit.  It didn't\n>   really fit inside the scope of this series.  It may be something we want to\n>   revisit later though.\n>\n> * The --init-active flag now ensure that all submodules which are configured to\n>   be 'active' (either via 'submodule.active' or 'submodule.<name>.active') go\n>   through the initialization phase and have their relevent info copied over to\n>   the config.\n>\n\nThis round looks sensible to me.\n\nThanks,\nStefan\n"},{"id":"314039","messageId":"xmqqh92vkb8d.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-2-bmwill@google.com","subject":"Re: [PATCH v3 01/10] submodule--helper: add is_active command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T17:40:50Z","receivedAt":"2017-03-14T17:41:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> There are a lot of places where an explicit check for\n> submodule.\"<name>\".url is done to see if a submodule exists.  In order\n> to centralize this check introduce a helper which can be used to query\n> if a submodule is active or not.\n\n    \"Right now, is_submodule_initialized(), the underlying\n    implementation of \"submodule--helper is-active\", checks exactly\n    the same thing.  When submodule.<name>.url is set to a non-empty\n    string, then it is initialized.  We'd want to change this\n    definition in later steps of this series and having the checks\n    centralized is a necessary preparatory step.\"\n\nor something like that need to be tacked at the end to make it known\nthat 02-04/10 are meant as pure code clean-up without improvement in\nbehaviour.\n\n\"Tacking at the end\" will make the whole thing awkward to read, and\nthat is because the flow of logic is inverted.  The first sentence,\n\"there are a lot of places...\", is trying to state that there is a\nproblem worthy of fixing, but it does so without saying why it is a\nproblem in the first place.  After step 04/10 of this series, we\nwould still be able to say \"There are a log of places where an\nexplicit call to \"submodule--helper is-active\" is done to see if a\nsubmodule exists.\"  Is that still a problem?  The answer depends on\nwhat motivated this change, and it is better to make the motivation\nknown in advance.\n\nHere is my attempt to rewrite the whole thing.\n\n    The definition of which submodules are of interest by the user\n    is tied to the configuration submodule.<name>.url; when it is\n    set to a non-empty string, it is of interest.  We'd want to be\n    able to later change this definition, but there are many places\n    that explicitly check this condition in the scripted Porcelain.\n\n    Introduce the \"is-active\" subcommand to \"submodule--helper\", so\n    that the exact definition of what submodule is of interest can\n    be centrally defined (and changed in later steps).  In a few\n    patches that follow, this helper is used to replace the explicit\n    checks of the configuration variable in scripts.\n\nYou are adding the \"is-active\" subcommand, and the implementation\ndetail to do so is by using a new is_active() function, so the patch\ntitle needs a bit of tweaking, too.\n\n\tSubject: submodule--helper: add is-active subcommand\n\n> diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> new file mode 100755\n> index 000000000..f18e0c925\n> --- /dev/null\n> +++ b/t/t7413-submodule-is-active.sh\n> @@ -0,0 +1,31 @@\n> +#!/bin/sh\n> +\n> +test_description='Test submodule--helper is-active\n> +\n> +This test verifies that `git submodue--helper is-active` correclty identifies\n> +submodules which are \"active\" and interesting to the user.\n> +'\n> +\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'setup' '\n> +\tgit init sub &&\n> +\ttest_commit -C sub initial &&\n> +\tgit init super &&\n> +\ttest_commit -C super initial &&\n> +\tgit -C super submodule add ../sub sub1 &&\n> +\tgit -C super submodule add ../sub sub2 &&\n> +\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n> +'\n> +\n> +test_expect_success 'is-active works with urls' '\n> +\tgit -C super submodule--helper is-active sub1 &&\n> +\tgit -C super submodule--helper is-active sub2 &&\n> +\n> +\tgit -C super config --unset submodule.sub1.URL &&\n> +\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n> +\tgit -C super config submodule.sub1.URL ../sub &&\n> +\tgit -C super submodule--helper is-active sub1\n> +'\n\nLooks sensible.\n\nThanks.\n"},{"id":"314040","messageId":"xmqqd1djkay4.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-3-bmwill@google.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T17:46:59Z","receivedAt":"2017-03-14T17:47:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  git-submodule.sh | 3 +--\n>  1 file changed, 1 insertion(+), 2 deletions(-)\n>\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 136e26a2c..ab233712d 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -1010,14 +1010,13 @@ cmd_status()\n>  \tdo\n>  \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n>  \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n> -\t\turl=$(git config submodule.\"$name\".url)\n>  \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n>  \t\tif test \"$stage\" = U\n>  \t\tthen\n>  \t\t\tsay \"U$sha1 $displaypath\"\n>  \t\t\tcontinue\n>  \t\tfi\n> -\t\tif test -z \"$url\" ||\n> +\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n>  \t\t{\n>  \t\t\t! test -d \"$sm_path\"/.git &&\n>  \t\t\t! test -f \"$sm_path\"/.git\n\nThe $name is no longer used after this step in cmd_status function, \nas the sole purpose of learning the name from the path was so that\nwe can ask if the submodule has .URL defined and the query is done\nby name, not path.\n\nThis actually raises a question.  \n\nShouldn't \"submodule--helper is-active\" ask about submodule while\nidentifying the submodule in question by name?  Or do all (or most\nof) the callers start from path and ask is-active on them so that it\nis handier to let them ask by path?\n"},{"id":"314041","messageId":"xmqq8to7kamv.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-4-bmwill@google.com","subject":"Re: [PATCH v3 03/10] submodule sync: use submodule--helper is-active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T17:53:44Z","receivedAt":"2017-03-14T17:53:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  git-submodule.sh | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index ab233712d..e2d08595f 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -1111,7 +1111,7 @@ cmd_sync()\n>  \t\t\t;;\n>  \t\tesac\n>  \n> -\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> +\t\tif git submodule--helper is-active \"$sm_path\"\n>  \t\tthen\n>  \t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n>  \t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n\nThis is not a problem this patch introduces, but the loop this hunk\nis in seems a bit inefficient.  It maps the sm_path to its name and\nthen asks .gitmodules the URL the upstream suggests to clone it from,\nmunges it with a large case statement and discards all of that if\nthe module is not active.\n\nAdding this patch on top would be a way to remove the inefficiency\nand one level of nesting while at it, I think, but I may have missed\nsomething, so please double check, and if you agree that this is a\ngood way to go, please do so as a preparatory clean-up.\n\nThanks.\n\n git-submodule.sh | 19 +++++++++++--------\n 1 file changed, 11 insertions(+), 8 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex e2d08595f0..dcdd36fa64 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1089,6 +1089,12 @@ cmd_sync()\n \twhile read mode sha1 stage sm_path\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n+\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tcontinue\n+\t\tfi\n+\n \t\tname=$(git submodule--helper name \"$sm_path\")\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n@@ -1111,14 +1117,12 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git submodule--helper is-active \"$sm_path\"\n-\t\tthen\n-\t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-\t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n+\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n+\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n \n-\t\t\tif test -e \"$sm_path\"/.git\n-\t\t\tthen\n+\t\tif test -e \"$sm_path\"/.git\n+\t\tthen\n \t\t\t(\n \t\t\t\tsanitize_submodule_env\n \t\t\t\tcd \"$sm_path\"\n@@ -1131,7 +1135,6 @@ cmd_sync()\n \t\t\t\t\teval cmd_sync\n \t\t\t\tfi\n \t\t\t)\n-\t\t\tfi\n \t\tfi\n \tdone\n }\n"},{"id":"314044","messageId":"xmqq4lyvka1i.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-5-bmwill@google.com","subject":"Re: [PATCH v3 04/10] submodule--helper clone: check for configured submodules using helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T18:06:33Z","receivedAt":"2017-03-14T18:06:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> -\t/*\n> -\t * Looking up the url in .git/config.\n> -\t * We must not fall back to .gitmodules as we only want\n> -\t * to process configured submodules.\n> -\t */\n> -\tstrbuf_reset(&sb);\n> -\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n> -\tgit_config_get_string(sb.buf, &url);\n> -\tif (!url) {\n> +\t/* Check if the submodule has been initialized. */\n> +\tif (!is_submodule_initialized(ce->name)) {\n>  \t\tnext_submodule_warn_missing(suc, out, displaypath);\n>  \t\tgoto cleanup;\n>  \t}\n> @@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>  \t\targv_array_push(&child->args, \"--depth=1\");\n>  \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n>  \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n> -\targv_array_pushl(&child->args, \"--url\", url, NULL);\n> +\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n\nEven without this patch, we already had an instance of struct submodule\navailable in this function, so the query to .git/config this patch removed\nwas unnecessary?\n\nI am wondering what was meant by the comment \"We must not fall back to...\"\nthat is being removed---is that because sub->url can come from .gitmodules\nthat is in-tree, not from .git/config?  If that is the case, doesn't the\nchange in this hunk change behaviour from using the URL the user prefers\nto using the URL the upstream suggests, overriding user's configuration?\n\n> @@ -845,7 +837,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>  \t\targv_array_push(&child->args, suc->depth);\n>  \n>  cleanup:\n> -\tfree(url);\n>  \tstrbuf_reset(&displaypath_sb);\n>  \tstrbuf_reset(&sb);\n"},{"id":"314045","messageId":"CAGZ79kZ6noz7RGbmNwg=NhuWYH=KbNPYUWL7We9YjbHn6uf2Jg@mail.gmail.com","threadId":"45207","inReplyTo":"xmqqd1djkay4.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-14T18:16:29Z","receivedAt":"2017-03-14T18:16:35Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 14, 2017 at 10:46 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Brandon Williams <bmwill@google.com> writes:\n>\n>> Signed-off-by: Brandon Williams <bmwill@google.com>\n>> ---\n>>  git-submodule.sh | 3 +--\n>>  1 file changed, 1 insertion(+), 2 deletions(-)\n>>\n>> diff --git a/git-submodule.sh b/git-submodule.sh\n>> index 136e26a2c..ab233712d 100755\n>> --- a/git-submodule.sh\n>> +++ b/git-submodule.sh\n>> @@ -1010,14 +1010,13 @@ cmd_status()\n>>       do\n>>               die_if_unmatched \"$mode\" \"$sha1\"\n>>               name=$(git submodule--helper name \"$sm_path\") || exit\n>> -             url=$(git config submodule.\"$name\".url)\n>>               displaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n>>               if test \"$stage\" = U\n>>               then\n>>                       say \"U$sha1 $displaypath\"\n>>                       continue\n>>               fi\n>> -             if test -z \"$url\" ||\n>> +             if ! git submodule--helper is-active \"$sm_path\" ||\n>>               {\n>>                       ! test -d \"$sm_path\"/.git &&\n>>                       ! test -f \"$sm_path\"/.git\n>\n> The $name is no longer used after this step in cmd_status function,\n> as the sole purpose of learning the name from the path was so that\n> we can ask if the submodule has .URL defined and the query is done\n> by name, not path.\n>\n> This actually raises a question.\n>\n> Shouldn't \"submodule--helper is-active\" ask about submodule while\n> identifying the submodule in question by name?  Or do all (or most\n> of) the callers start from path and ask is-active on them so that it\n> is handier to let them ask by path?\n\nA similar observation can be made, when looking at\nsubmodule_from_name and submodule_from_path\n(both defined in submodule-config.h)\n\nsubmodule_from_name has only one real world use case in code,\nwhich I suspect is even a bug.\n\nThat line was last touched with 851e18c3859a (submodule: use new config\nAPI for worktree configurations). but the original mechanism comes\nfrom 7dce19d374 (fetch/pull: Add the --recurse-submodules option).\n\nThere we take the path as name and if a real name exists, the name\nis overwritten with the real name, i.e.\n\n    name = name_for_path(path) ? name_for_path(path) : path;\n\nwhich IMHO is overly accepting and we should just die in case of\n!name_for_path.\n\nSo to answer your original question, I think the codebase currently\nthinks by_path is handier, the name is a mere internal field in\n\"struct submodule\", useful for looking up its git dir.\n\nThanks,\nStefan\n"},{"id":"314047","messageId":"CAGZ79kZ20Jy_A8SPJte7U0iZZB97P0Sn_PqAMfwp40sAj6Y=RA@mail.gmail.com","threadId":"45207","inReplyTo":"xmqq4lyvka1i.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 04/10] submodule--helper clone: check for configured submodules using helper","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-14T18:40:15Z","receivedAt":"2017-03-14T18:40:26Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 14, 2017 at 11:06 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Brandon Williams <bmwill@google.com> writes:\n>\n>> -     /*\n>> -      * Looking up the url in .git/config.\n>> -      * We must not fall back to .gitmodules as we only want\n>> -      * to process configured submodules.\n>> -      */\n>> -     strbuf_reset(&sb);\n>> -     strbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n>> -     git_config_get_string(sb.buf, &url);\n>> -     if (!url) {\n>> +     /* Check if the submodule has been initialized. */\n>> +     if (!is_submodule_initialized(ce->name)) {\n>>               next_submodule_warn_missing(suc, out, displaypath);\n>>               goto cleanup;\n>>       }\n>> @@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>>               argv_array_push(&child->args, \"--depth=1\");\n>>       argv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n>>       argv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n>> -     argv_array_pushl(&child->args, \"--url\", url, NULL);\n>> +     argv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n>\n> Even without this patch, we already had an instance of struct submodule\n> available in this function, so the query to .git/config this patch removed\n> was unnecessary?\n>\n> I am wondering what was meant by the comment \"We must not fall back to...\"\n> that is being removed---is that because sub->url can come from .gitmodules\n> that is in-tree, not from .git/config?\n\nYes. We want to check for the submodule being \"initialized\", i.e.\nhaving a url in .git/config. (and the struct submodule reads in both .git/config\nand .gitmodules and overlays them with a given precedence order)\n\n>  If that is the case, doesn't the\n> change in this hunk change behaviour from using the URL the user prefers\n> to using the URL the upstream suggests, overriding user's configuration?\n\nThe mentioned precedence makes sure to have the right order:\n\n    /* Overlay the parsed .gitmodules file with .git/config */\n    gitmodules_config();\n    git_config(submodule_config, NULL);\n\nsuch that the sub->url is correct as a URL, but not correct as a boolean\nindicator if the submodule is \"initialized\".\n"},{"id":"314049","messageId":"xmqqzignittf.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-6-bmwill@google.com","subject":"Re: [PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T18:42:20Z","receivedAt":"2017-03-14T18:42:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> Currently the submodule.<name>.url config option is used to determine\n> if a given submodule exists and is interesting to the user.  This\n> however doesn't work very well because the URL is a config option for\n> the scope of a repository, whereas the existence of a submodule is an\n> option scoped to the working tree.\n\nA submodule exists if it is exists, whether the user is interested\nin it or not.  If it should be checked out in the working tree is a\ndifferent matter, but that should be a logical AND between \"is it of\ninterest?\" and \"is the superproject tree has a gitlink for it in its\nworking tree?\".  \n\nSo I do not agree with \"This however doesn't work\" at all.  I'd\nunderstand it if you said \"This is cumbersome if we want to do this\nand that, which are different from what we have done traditionally\"\nand explain what this and that are and how they are different.\n\n> In a future with worktree support for submodules, there will be multiple\n> working trees, each of which may only need a subset of the submodules\n> checked out.  The URL (which is where the submodule repository can be\n> obtained) should not differ between different working trees.\n\nAnd this makes the motivation a bit clearer.  When the user wants to\nhave multiple worktrees for the same superproject.  In such a\nsetting, the same submodule in two worktrees typically want to have\nthe same URL.  It may be different from what the upstream suggests\nin the .gitmodules file, but the difference, i.e. the site specific\ncustomization of the URL, should be the same between the two\nworktrees.  But one worktree may be and the other worktree may not be\ninterested in that submodule, and with shared .git/config file, you\ncannot have submodule.<name>.url set to one value and unset at the\nsame time.\n\nThis series does not solve the \"two worktrees cannot have private\nparts in the configuration namespace\" issue, but assuming it will be\nsolved by some other series, it anticipates that submodule.<name>.URL \nwould want to be shared between two worktrees most of time (note that\nthere will be users who want two separate .URL for the same submodule\nwhile sharing the object database via worktrees mechanism, and you'll\nneed to prepare for them, too), and another \"bit\" that tells if the\nsubmodule is of interest would want to be private to each worktree.\n\nThat is the motivation, the reason why you want .URL to stop serving\nthe dual purpose of overriding upstream-suggested URL and indicating\nthe submodule is interesting to the user.\n\n> It may also be convenient for users to more easily specify groups of\n> submodules they are interested in as apposed to running \"git submodule\n> init <path>\" on each submodule they want checked out in their working\n> tree.\n>\n> To this end two config options are introduced, submodule.active and\n> submodule.<name>.active.  The submodule.active config holds a pathspec\n> that specifies which submodules should exist in the working tree.  The\n> submodule.<name>.active config is a boolean flag used to indicate if\n> that particular submodule should exist in the working tree.\n\nAnd because two worktrees always share their .git/config, these new\nconfiguration variables are useless to help workflow with multiple\nworktrees with the current system, until \"per-worktree configuration\"\nis invented.  But we prepare for that future in this step.\n\nAlso submodule.active that takes pathspec and not name is an oddball\n(use of \"name\" not \"path\" is to prepare for a submodule whose\nlocation in the superproject changes depending on the commit in the\nsuperproject), and we need to justify with an explanation.  I think\nyou envision two cases.  1. we encourage projects to adopt a\nconvention that submodules are grouped with leading directory, so\nthat pathspec e.g. lib/, would cover _all_ library-ish modules to\nallow those who are interested in library-ish modules to set\n\".active = lib/\" just once to say any and all modules in lib/ are\ninteresting.  2. another convention the projects can adopt, when\npathspec-attribute feature is invented, is to label submodules with\nattribute to group them, so that a broad pathspec with attribute\nrequirement, e.g. .:(attr:lib), can be used to say any and all\nmodules with 'lib' attribute are interesting.\n\nThe above two points (justifications, intended uses and future\nplans) need to be clarified around here (and possibly in the\ndocumentation), I would think.\n\n> diff --git a/submodule.c b/submodule.c\n> index 0a2831d84..2b33bd70f 100644\n> --- a/submodule.c\n> +++ b/submodule.c\n> @@ -217,13 +217,41 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n>  int is_submodule_initialized(const char *path)\n>  {\n>  \tint ret = 0;\n> -\tconst struct submodule *module = NULL;\n> +\tchar *key;\n> +\tconst struct string_list *sl;\n> +\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n>  \n> -\tmodule = submodule_from_path(null_sha1, path);\n> +\t/* early return if there isn't a path->module mapping */\n> +\tif (!module)\n> +\t\treturn 0;\n> +\n> +\t/* submodule.<name>.active is set */\n> +\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n> +\tif (!git_config_get_bool(key, &ret)) {\n> +\t\tfree(key);\n> +\t\treturn ret;\n> +\t}\n> +\tfree(key);\n> +\n> +\tsl = git_config_get_value_multi(\"submodule.active\");\n>  \n> -\tif (module) {\n> -\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n> +\tif (sl) {\n> +\t\tstruct pathspec ps;\n> +\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n> +\t\tconst struct string_list_item *item;\n> +\n> +\t\tfor_each_string_list_item(item, sl) {\n> +\t\t\targv_array_push(&args, item->string);\n> +\t\t}\n> +\n> +\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n> +\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n> +\n> +\t\targv_array_clear(&args);\n> +\t\tclear_pathspec(&ps);\n> +\t} else {\n>  \t\tchar *value = NULL;\n> +\t\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n>  \n>  \t\tret = !git_config_get_string(key, &value);\n\nIt probably is easier to read if you had a final \"return ret\" in the\n\"if (sl) {...}\" part, just like you have one for the codepath that\ndeals with \"submodule.<name>.active\", and flatten the else clause.\nThat would make it clear that we have three ways with decreasing\nprecedence.\n\nAt this point, the answer from function is even less about \"is it\ninitialized?\"  but about \"is it of interest?\" (or \"is it to be\ninitialized?\").  We'd probably want a /* NEEDSWORK */ comment before\nthe function to remind us to come up with a better name after the\ndust settles.\n\n> diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> index f18e0c925..c41b899ab 100755\n> --- a/t/t7413-submodule-is-active.sh\n> +++ b/t/t7413-submodule-is-active.sh\n> @@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n>  \tgit -C super submodule--helper is-active sub1\n>  '\n>  \n> +test_expect_success 'is-active works with submodule.<name>.active config' '\n> +\tgit -C super config --bool submodule.sub1.active \"false\" &&\n> +\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n> +\n> +\tgit -C super config --bool submodule.sub1.active \"true\" &&\n> +\tgit -C super config --unset submodule.sub1.URL &&\n> +\tgit -C super submodule--helper is-active sub1 &&\n> +\n> +\tgit -C super config submodule.sub1.URL ../sub &&\n> +\tgit -C super config --unset submodule.sub1.active\n> +'\n\nThe last \"unset\" is done to clean the customization this test did,\nin order to give a predictable beginning state to the next test?  If\nso, use test_when_finished instead of &&-cascading it at the end.\n\n> + ...\n> +test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n> +\tgit -C super config --add submodule.active \"sub1\" &&\n> +\tgit -C super config --bool submodule.sub1.active \"false\" &&\n> +\tgit -C super config --bool submodule.sub2.active \"true\" &&\n> +\n> +\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n> +\tgit -C super submodule--helper is-active sub2 &&\n> +\n> +\tgit -C super config --unset-all submodule.active &&\n> +\tgit -C super config --unset submodule.sub1.active &&\n> +\tgit -C super config --unset submodule.sub2.active\n> +'\n\nLikewise for all the new tests in this patch.\n\nThanks.\n"},{"id":"314050","messageId":"xmqqvarbis4j.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-7-bmwill@google.com","subject":"Re: [PATCH v3 06/10] submodule update: add `--init-active` switch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T19:18:52Z","receivedAt":"2017-03-14T19:19:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> +--init-active::\n> +\tThis option is only valid for the update command.\n> +\tInitialize all submodules configured in \"`submodule.active`\"\n> +\tthat have not been updated before.\n\nYou mean s/not been updated/not been initialized/ here?\n\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index f38e332c5..a3acc9e4c 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -270,6 +270,34 @@ static int module_list_compute(int argc, const char **argv,\n>  \treturn result;\n>  }\n>  \n> +static void module_list_active(struct module_list *list)\n> +{\n> +\tint i;\n> +\n> +\tif (read_cache() < 0)\n> +\t\tdie(_(\"index file corrupt\"));\n> +\n> +\tgitmodules_config();\n\nTo this codepath, it probably would not make any difference, but in\ngeneral, calling gitmodules_config() after you did git_config()\nwould be a bug, right?  Otherwise, gitmodules_config() would\noverwrite submodule.* configuration you read with git_config().\n\nI have a feeling that we need to make this function hard to misuse;\nit is not a fault of _this_ patch, but still any and all additions\nto any of the submodule*.c files needs careful vetting.\n"},{"id":"314051","messageId":"xmqqr31ziroz.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-7-bmwill@google.com","subject":"Re: [PATCH v3 06/10] submodule update: add `--init-active` switch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T19:28:12Z","receivedAt":"2017-03-14T19:28:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> +static void module_list_active(struct module_list *list)\n> +{\n> +\tint i;\n> +\n> +\tif (read_cache() < 0)\n> +\t\tdie(_(\"index file corrupt\"));\n> +\n> +\tgitmodules_config();\n> +\n> +\tfor (i = 0; i < active_nr; i++) {\n> +\t\tconst struct cache_entry *ce = active_cache[i];\n> +\n> +\t\tif (!S_ISGITLINK(ce->ce_mode) ||\n> +\t\t    !is_submodule_initialized(ce->name))\n> +\t\t\tcontinue;\n\nThis, because \"is_submodule_initialized()\" is not \"is it\ninitialized?\" but \"is it interesting?\", will catch a submodule\nthat used to be uninteresting but has become interesting (e.g. a new\nsubmodule added to somewhere in \"lib/\" when submodule.active lists\n\"lib/\" as one of the pathspecs to match interesting submodules) and\nautomatically updates it.\n\nI anticipate that a corresponding \"please deinitialize ones that are\nno longer interesting\" coming in the series ;-)  Without it, the\ninterested set will only grow without shrinking.\n\n> +\t\tALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n> +\t\tlist->entries[list->nr++] = ce;\n> +\t\twhile (i + 1 < active_nr &&\n> +\t\t       !strcmp(ce->name, active_cache[i + 1]->name))\n> +\t\t\t/*\n> +\t\t\t * Skip entries with the same name in different stages\n> +\t\t\t * to make sure an entry is returned only once.\n> +\t\t\t */\n> +\t\t\ti++;\n> +\t}\n> +}\n"},{"id":"314052","messageId":"xmqqmvcnir8m.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-8-bmwill@google.com","subject":"Re: [PATCH v3 07/10] clone: add --submodule-spec=<pathspec> switch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T19:38:01Z","receivedAt":"2017-03-14T19:38:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> The new switch passes the pathspec to `git submodule update\n> --init-active` which is called after the actual clone is done.\n>\n> Additionally this configures the submodule.active option to\n> be the given pathspec, such that any future invocation of\n> `git submodule update --init-active` will keep up\n> with the pathspec.\n>\n> Based on a patch by Stefan Beller <sbeller@google.com>\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  Documentation/git-clone.txt | 23 ++++++++++-----\n>  builtin/clone.c             | 36 +++++++++++++++++++++--\n>  t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 120 insertions(+), 9 deletions(-)\n>\n> diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\n> index 35cc34b2f..9692eab30 100644\n> --- a/Documentation/git-clone.txt\n> +++ b/Documentation/git-clone.txt\n> @@ -15,7 +15,8 @@ SYNOPSIS\n>  \t  [--dissociate] [--separate-git-dir <git dir>]\n>  \t  [--depth <depth>] [--[no-]single-branch]\n>  \t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n> -\t  [--jobs <n>] [--] <repository> [<directory>]\n> +\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n> +\t  <repository> [<directory>]\n\nHmph.  Can we then make \"--recurse-submodules\" an obsolete way to\nspell \"--submodule-spec .\"?  I am not actively suggesting to\ndeprecate it; I am trying to see if there are semantic differences\nbetween the two.\n\nI am also wondering \"--recurse-submodules=<pathspec>\" would be a\nbetter UI, instead of introducing yet another option.\n\n> @@ -217,12 +218,20 @@ objects from the source repository into a pack in the cloned repository.\n>  \n>  --recursive::\n>  --recurse-submodules::\n> -\tAfter the clone is created, initialize all submodules within,\n> -\tusing their default settings. This is equivalent to running\n> -\t`git submodule update --init --recursive` immediately after\n> -\tthe clone is finished. This option is ignored if the cloned\n> -\trepository does not have a worktree/checkout (i.e. if any of\n> -\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n> +\tAfter the clone is created, initialize and clone all submodules\n> +\twithin, using their default settings. This is equivalent to\n> +\trunning `git submodule update --recursive --init` immediately\n> +\tafter the clone is finished. This option is ignored if the\n> +\tcloned repository does not have a worktree/checkout (i.e.  if\n> +\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n\nWith reflowing it is unnecessarily harder to spot what got changed.\n\"and clone\" is inserted, \"--init\" and \"--recursive\" were swapped.\nAny other changes?\n\n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index 3f63edbbf..c6731379b 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -56,6 +56,16 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n>  static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n>  static int option_dissociate;\n>  static int max_jobs = -1;\n> +static struct string_list submodule_spec;\n> +\n> +static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tif (unset)\n> +\t\treturn -1;\n> +\n> +\tstring_list_append((struct string_list *)opt->value, arg);\n> +\treturn 0;\n> +}\n\nHmph,  doesn't OPT_STRING_LIST work for this thing?\n\n> +\tif (submodule_spec.nr > 0) {\n> +\t\tstruct string_list_item *item;\n> +\t\tstruct strbuf sb = STRBUF_INIT;\n> +\t\tfor_each_string_list_item(item, &submodule_spec) {\n> +\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n> +\t\t\t\t    item->string);\n> +\t\t\tstring_list_append(&option_config,\n> +\t\t\t\t\t   strbuf_detach(&sb, NULL));\n> +\t\t}\n> +\t}\n\nOK.  Each pathspec becomes submodule.active in the newly created\nrepository.\n"},{"id":"314053","messageId":"xmqqinnbiqzs.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-10-bmwill@google.com","subject":"Re: [PATCH v3 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T19:43:19Z","receivedAt":"2017-03-14T19:43:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> When initializing a submodule set the submodule.<name>.active config to\n> true to indicate that the submodule is active.\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n\nHmph.  When you do\n\n\tgit clone --submodule-spec=lib/\n\nand resulting repository says \"submodule.active = lib/\", you are\nsaying that you are interested in anything in \"lib/\", now or in the\nfuture--that is the point of 08/10.\n\nIt is unclear what your desire would be for a submodule that was\nbound to somewhere in \"lib/\" in the superproject when you cloned\nwhen it later gets moved outside \"lib/\".  With changes up to 08/10,\nthat submodule will no longer be interesting, but with this 09/10,\nwhen recursing clone will activate it upon the initial clone, the\nsubmodule is explicitly marked as active by its name, so no matter\nwhere it gets moved later, it will remain to be interesting.\n\nI am not sure if that is a desired behaviour.\n\n>  builtin/submodule--helper.c | 7 +++++++\n>  1 file changed, 7 insertions(+)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index a3acc9e4c..b669ed031 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>  \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n>  \t\t\tdisplaypath);\n>  \n> +\t/* Set active flag for the submodule being initialized */\n> +\tif (!is_submodule_initialized(path)) {\n> +\t\tstrbuf_reset(&sb);\n> +\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n> +\t\tgit_config_set_gently(sb.buf, \"true\");\n> +\t}\n> +\n>  \t/*\n>  \t * Copy url setting when it is not set yet.\n>  \t * To look up the url in .git/config, we must not fall back to\n"},{"id":"314054","messageId":"xmqqefxziqrj.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-11-bmwill@google.com","subject":"Re: [PATCH v3 10/10] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T19:48:16Z","receivedAt":"2017-03-14T19:48:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> +\tif git config --get submodule.active >/dev/null\n> +\tthen\n> +\t\t# If the submodule being adding isn't already covered by the\n> +\t\t# current configured pathspec, set the submodule's active flag\n> +\t\tif ! git submodule--helper is-active \"$sm_path\"\n> +\t\tthen\n> +\t\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n> +\t\tfi\n> +\telse\n> +\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n> +\tfi\n\nWhy \"--add\"?  That's a way to add new entry for multi-valued\nconfiguration, but you do not care if the old value (if existed)\nwere false or true---you want to replace it to true here, no?\n\n"},{"id":"314056","messageId":"xmqqa88nip9z.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"CAGZ79kZ6noz7RGbmNwg=NhuWYH=KbNPYUWL7We9YjbHn6uf2Jg@mail.gmail.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T20:20:24Z","receivedAt":"2017-03-14T20:20:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> There we take the path as name and if a real name exists, the name\n> is overwritten with the real name, i.e.\n>\n>     name = name_for_path(path) ? name_for_path(path) : path;\n>\n> which IMHO is overly accepting and we should just die in case of\n> !name_for_path.\n\nYes, I agree that falling back (unless path is a submodule yet to be\nadded to .gitmodules) is bad.\n"},{"id":"314057","messageId":"xmqq60jbip23.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"CAGZ79kZ20Jy_A8SPJte7U0iZZB97P0Sn_PqAMfwp40sAj6Y=RA@mail.gmail.com","subject":"Re: [PATCH v3 04/10] submodule--helper clone: check for configured submodules using helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T20:25:08Z","receivedAt":"2017-03-14T20:25:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n>> I am wondering what was meant by the comment \"We must not fall back to...\"\n>> that is being removed---is that because sub->url can come from .gitmodules\n>> that is in-tree, not from .git/config?\n>\n> Yes. We want to check for the submodule being \"initialized\", i.e.\n> having a url in .git/config. (and the struct submodule reads in both .git/config\n> and .gitmodules and overlays them with a given precedence order)\n\nOK, thanks.\n\nI agree that the current code happens to be OK but the arrangement\nlooks rather brittle to me.  It seems the code liberally call\ngitmodules_config() without making sure it is early enough to do so\n(iow, git_config() for submodule-related stuff has not been done and\nwill be done before the values read there are the ones that are\nused).\n\n"},{"id":"314062","messageId":"xmqqpohjh7bc.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"CAGZ79kZ6noz7RGbmNwg=NhuWYH=KbNPYUWL7We9YjbHn6uf2Jg@mail.gmail.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T21:33:43Z","receivedAt":"2017-03-14T21:33:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> So to answer your original question, I think the codebase currently\n> thinks by_path is handier, the name is a mere internal field in\n> \"struct submodule\", useful for looking up its git dir.\n\nOK, that makes sense at the conceptual level, too.  When you have a\nspecific version of the superproject checked out, you would want to\nidentify which submodule to work on by the path to it inside that\nversion of the superproject.  The name is used only to keep track\nof attributes of the submodule that will not change across versions\nof the superproject, no matter where in its tree it binds the\nsubmodule at.\n\nThanks.\n"},{"id":"314063","messageId":"xmqqlgs7h737.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"xmqqzignittf.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T21:38:36Z","receivedAt":"2017-03-14T21:38:52Z","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> Also submodule.active that takes pathspec and not name is an oddball\n> (use of \"name\" not \"path\" is to prepare for a submodule whose\n> location in the superproject changes depending on the commit in the\n> superproject), and we need to justify with an explanation.  I think\n> you envision two cases.  1. we encourage projects to adopt a\n> convention that submodules are grouped with leading directory, so\n> that pathspec e.g. lib/, would cover _all_ library-ish modules to\n> allow those who are interested in library-ish modules to set\n> \".active = lib/\" just once to say any and all modules in lib/ are\n> interesting.  2. another convention the projects can adopt, when\n> pathspec-attribute feature is invented, is to label submodules with\n> attribute to group them, so that a broad pathspec with attribute\n> requirement, e.g. .:(attr:lib), can be used to say any and all\n> modules with 'lib' attribute are interesting.\n\nOne addition to the point 2. above is that because .gitattributes,\njust like .gitmodules, is tracked by the superproject, and when a\nsubmodule that moves in the superproject tree, the project can\nadjust which path gets the attribute in .gitattributes, just like it\ncan adjust which path has the submodule in .gitmodules.  That makes\na broad pathspec with attribute requirement just as a viable\nsolution to identify a submodule as having an unchanging \"name\" for\na submodule in the .gitmodules file.\n\n> The above two points (justifications, intended uses and future\n> plans) need to be clarified around here (and possibly in the\n> documentation), I would think.\n"},{"id":"314064","messageId":"xmqqh92vh70l.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"Re: [PATCH v3 00/10] decoupling a submodule's existence and its url","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-14T21:40:10Z","receivedAt":"2017-03-14T21:40:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> changes in v3:\n>\n> * Droped a patch which tried to use a more accurate URL for deinit.  It didn't\n>   really fit inside the scope of this series.  It may be something we want to\n>   revisit later though.\n>\n> * The --init-active flag now ensure that all submodules which are configured to\n>   be 'active' (either via 'submodule.active' or 'submodule.<name>.active') go\n>   through the initialization phase and have their relevent info copied over to\n>   the config.\n\nAside from comments I sent already to the individual patches, I\nthink overall this coherently adds a nicer way to keep track of\nwhich submodules are of interest (and which are not) than what we\ntraditionally had.  I'll queue it on 'pu', awaiting further\npolishing (if necessary).\n\nThanks.\n"},{"id":"314096","messageId":"20170314221702.GA168037@google.com","threadId":"45207","inReplyTo":"xmqqh92vh70l.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 00/10] decoupling a submodule's existence and its url","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-14T22:17:02Z","receivedAt":"2017-03-14T22:17:12Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > changes in v3:\n> >\n> > * Droped a patch which tried to use a more accurate URL for deinit.  It didn't\n> >   really fit inside the scope of this series.  It may be something we want to\n> >   revisit later though.\n> >\n> > * The --init-active flag now ensure that all submodules which are configured to\n> >   be 'active' (either via 'submodule.active' or 'submodule.<name>.active') go\n> >   through the initialization phase and have their relevent info copied over to\n> >   the config.\n> \n> Aside from comments I sent already to the individual patches, I\n> think overall this coherently adds a nicer way to keep track of\n> which submodules are of interest (and which are not) than what we\n> traditionally had.  I'll queue it on 'pu', awaiting further\n> polishing (if necessary).\n\nI've just started looking at your comments and I expect I'll do at least\none more round of polish.\n\nThanks for taking a look!\n\n-- \nBrandon Williams\n"},{"id":"314099","messageId":"20170314224407.GC168037@google.com","threadId":"45207","inReplyTo":"xmqqh92vkb8d.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 01/10] submodule--helper: add is_active command","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-14T22:44:07Z","receivedAt":"2017-03-14T22:44:16Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Here is my attempt to rewrite the whole thing.\n> \n>     The definition of which submodules are of interest by the user\n>     is tied to the configuration submodule.<name>.url; when it is\n>     set to a non-empty string, it is of interest.  We'd want to be\n>     able to later change this definition, but there are many places\n>     that explicitly check this condition in the scripted Porcelain.\n> \n>     Introduce the \"is-active\" subcommand to \"submodule--helper\", so\n>     that the exact definition of what submodule is of interest can\n>     be centrally defined (and changed in later steps).  In a few\n>     patches that follow, this helper is used to replace the explicit\n>     checks of the configuration variable in scripts.\n> \n> You are adding the \"is-active\" subcommand, and the implementation\n> detail to do so is by using a new is_active() function, so the patch\n> title needs a bit of tweaking, too.\n> \n> \tSubject: submodule--helper: add is-active subcommand\n\nThanks for helping wordsmith this.  Since starting to contribute I've\nrealized that writing a good commit message is probably the hardest\npart of the whole process.\n\n-- \nBrandon Williams\n"},{"id":"314101","messageId":"20170314225002.GD168037@google.com","threadId":"45207","inReplyTo":"xmqqd1djkay4.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-14T22:50:02Z","receivedAt":"2017-03-14T22:50:15Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  git-submodule.sh | 3 +--\n> >  1 file changed, 1 insertion(+), 2 deletions(-)\n> >\n> > diff --git a/git-submodule.sh b/git-submodule.sh\n> > index 136e26a2c..ab233712d 100755\n> > --- a/git-submodule.sh\n> > +++ b/git-submodule.sh\n> > @@ -1010,14 +1010,13 @@ cmd_status()\n> >  \tdo\n> >  \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n> >  \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n> > -\t\turl=$(git config submodule.\"$name\".url)\n> >  \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> >  \t\tif test \"$stage\" = U\n> >  \t\tthen\n> >  \t\t\tsay \"U$sha1 $displaypath\"\n> >  \t\t\tcontinue\n> >  \t\tfi\n> > -\t\tif test -z \"$url\" ||\n> > +\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n> >  \t\t{\n> >  \t\t\t! test -d \"$sm_path\"/.git &&\n> >  \t\t\t! test -f \"$sm_path\"/.git\n> \n> The $name is no longer used after this step in cmd_status function, \n> as the sole purpose of learning the name from the path was so that\n> we can ask if the submodule has .URL defined and the query is done\n> by name, not path.\n\nThanks, I'll remove computing the name.\n\n> \n> This actually raises a question.  \n> \n> Shouldn't \"submodule--helper is-active\" ask about submodule while\n> identifying the submodule in question by name?  Or do all (or most\n> of) the callers start from path and ask is-active on them so that it\n> is handier to let them ask by path?\n\nAs you can Stefan already discussed the path is a much easier handle to\nwork with simply because that is what is more readily available as the\nname is an internal detail.\n\n-- \nBrandon Williams\n"},{"id":"314107","messageId":"20170314233659.GE168037@google.com","threadId":"45207","inReplyTo":"20170314225002.GD168037@google.com","subject":"Re: [PATCH v3 02/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-14T23:36:59Z","receivedAt":"2017-03-14T23:37:07Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Brandon Williams wrote:\n> On 03/14, Junio C Hamano wrote:\n> > Brandon Williams <bmwill@google.com> writes:\n> > \n> > > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > > ---\n> > >  git-submodule.sh | 3 +--\n> > >  1 file changed, 1 insertion(+), 2 deletions(-)\n> > >\n> > > diff --git a/git-submodule.sh b/git-submodule.sh\n> > > index 136e26a2c..ab233712d 100755\n> > > --- a/git-submodule.sh\n> > > +++ b/git-submodule.sh\n> > > @@ -1010,14 +1010,13 @@ cmd_status()\n> > >  \tdo\n> > >  \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n> > >  \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n> > > -\t\turl=$(git config submodule.\"$name\".url)\n> > >  \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> > >  \t\tif test \"$stage\" = U\n> > >  \t\tthen\n> > >  \t\t\tsay \"U$sha1 $displaypath\"\n> > >  \t\t\tcontinue\n> > >  \t\tfi\n> > > -\t\tif test -z \"$url\" ||\n> > > +\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n> > >  \t\t{\n> > >  \t\t\t! test -d \"$sm_path\"/.git &&\n> > >  \t\t\t! test -f \"$sm_path\"/.git\n> > \n> > The $name is no longer used after this step in cmd_status function, \n> > as the sole purpose of learning the name from the path was so that\n> > we can ask if the submodule has .URL defined and the query is done\n> > by name, not path.\n> \n> Thanks, I'll remove computing the name.\n\nActually looks like it should stay in for now. It's used to exit if\nthere doesn't exist a path mapping in the users .gitmodules for a given\nsubmodule.\n\n> \n> > \n> > This actually raises a question.  \n> > \n> > Shouldn't \"submodule--helper is-active\" ask about submodule while\n> > identifying the submodule in question by name?  Or do all (or most\n> > of) the callers start from path and ask is-active on them so that it\n> > is handier to let them ask by path?\n> \n> As you can Stefan already discussed the path is a much easier handle to\n> work with simply because that is what is more readily available as the\n> name is an internal detail.\n> \n> -- \n> Brandon Williams\n\n-- \nBrandon Williams\n"},{"id":"314111","messageId":"20170314235036.GF168037@google.com","threadId":"45207","inReplyTo":"xmqq8to7kamv.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 03/10] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-14T23:50:36Z","receivedAt":"2017-03-14T23:50:46Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  git-submodule.sh | 2 +-\n> >  1 file changed, 1 insertion(+), 1 deletion(-)\n> >\n> > diff --git a/git-submodule.sh b/git-submodule.sh\n> > index ab233712d..e2d08595f 100755\n> > --- a/git-submodule.sh\n> > +++ b/git-submodule.sh\n> > @@ -1111,7 +1111,7 @@ cmd_sync()\n> >  \t\t\t;;\n> >  \t\tesac\n> >  \n> > -\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> > +\t\tif git submodule--helper is-active \"$sm_path\"\n> >  \t\tthen\n> >  \t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> >  \t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> \n> This is not a problem this patch introduces, but the loop this hunk\n> is in seems a bit inefficient.  It maps the sm_path to its name and\n> then asks .gitmodules the URL the upstream suggests to clone it from,\n> munges it with a large case statement and discards all of that if\n> the module is not active.\n> \n> Adding this patch on top would be a way to remove the inefficiency\n> and one level of nesting while at it, I think, but I may have missed\n> something, so please double check, and if you agree that this is a\n> good way to go, please do so as a preparatory clean-up.\n> \n> Thanks.\n\nYeah you're right, some of that work can be avoided.  I'll do the\ncode cleanup in a prep patch and then convert submodule sync to use the\nis-active subcommand.\n\n> \n>  git-submodule.sh | 19 +++++++++++--------\n>  1 file changed, 11 insertions(+), 8 deletions(-)\n> \n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index e2d08595f0..dcdd36fa64 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -1089,6 +1089,12 @@ cmd_sync()\n>  \twhile read mode sha1 stage sm_path\n>  \tdo\n>  \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n> +\n> +\t\tif ! git submodule--helper is-active \"$sm_path\"\n> +\t\tthen\n> +\t\t\tcontinue\n> +\t\tfi\n> +\n>  \t\tname=$(git submodule--helper name \"$sm_path\")\n>  \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n>  \n> @@ -1111,14 +1117,12 @@ cmd_sync()\n>  \t\t\t;;\n>  \t\tesac\n>  \n> -\t\tif git submodule--helper is-active \"$sm_path\"\n> -\t\tthen\n> -\t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> -\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> -\t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n> +\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> +\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> +\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n>  \n> -\t\t\tif test -e \"$sm_path\"/.git\n> -\t\t\tthen\n> +\t\tif test -e \"$sm_path\"/.git\n> +\t\tthen\n>  \t\t\t(\n>  \t\t\t\tsanitize_submodule_env\n>  \t\t\t\tcd \"$sm_path\"\n> @@ -1131,7 +1135,6 @@ cmd_sync()\n>  \t\t\t\t\teval cmd_sync\n>  \t\t\t\tfi\n>  \t\t\t)\n> -\t\t\tfi\n>  \t\tfi\n>  \tdone\n>  }\n\n-- \nBrandon Williams\n"},{"id":"314112","messageId":"20170315001006.GG168037@google.com","threadId":"45207","inReplyTo":"CAGZ79kZ20Jy_A8SPJte7U0iZZB97P0Sn_PqAMfwp40sAj6Y=RA@mail.gmail.com","subject":"Re: [PATCH v3 04/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T00:10:06Z","receivedAt":"2017-03-15T00:10:14Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Stefan Beller wrote:\n> On Tue, Mar 14, 2017 at 11:06 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> > Brandon Williams <bmwill@google.com> writes:\n> >\n> >> -     /*\n> >> -      * Looking up the url in .git/config.\n> >> -      * We must not fall back to .gitmodules as we only want\n> >> -      * to process configured submodules.\n> >> -      */\n> >> -     strbuf_reset(&sb);\n> >> -     strbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n> >> -     git_config_get_string(sb.buf, &url);\n> >> -     if (!url) {\n> >> +     /* Check if the submodule has been initialized. */\n> >> +     if (!is_submodule_initialized(ce->name)) {\n> >>               next_submodule_warn_missing(suc, out, displaypath);\n> >>               goto cleanup;\n> >>       }\n> >> @@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n> >>               argv_array_push(&child->args, \"--depth=1\");\n> >>       argv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n> >>       argv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n> >> -     argv_array_pushl(&child->args, \"--url\", url, NULL);\n> >> +     argv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n> >\n> > Even without this patch, we already had an instance of struct submodule\n> > available in this function, so the query to .git/config this patch removed\n> > was unnecessary?\n> >\n> > I am wondering what was meant by the comment \"We must not fall back to...\"\n> > that is being removed---is that because sub->url can come from .gitmodules\n> > that is in-tree, not from .git/config?\n> \n> Yes. We want to check for the submodule being \"initialized\", i.e.\n> having a url in .git/config. (and the struct submodule reads in both .git/config\n> and .gitmodules and overlays them with a given precedence order)\n> \n> >  If that is the case, doesn't the\n> > change in this hunk change behaviour from using the URL the user prefers\n> > to using the URL the upstream suggests, overriding user's configuration?\n> \n> The mentioned precedence makes sure to have the right order:\n> \n>     /* Overlay the parsed .gitmodules file with .git/config */\n>     gitmodules_config();\n>     git_config(submodule_config, NULL);\n> \n> such that the sub->url is correct as a URL, but not correct as a boolean\n> indicator if the submodule is \"initialized\".\n\nThanks for clarifying this.\n\n-- \nBrandon Williams\n"},{"id":"314150","messageId":"20170315173831.GB159137@google.com","threadId":"45207","inReplyTo":"CAGZ79kaqNUV_Wa_9-PSTf=NU7EcKASHqk6NcmGZSX5r610Zdew@mail.gmail.com","subject":"Re: [PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T17:38:31Z","receivedAt":"2017-03-15T17:46:03Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/13, Stefan Beller wrote:\n> + cc Jens, FYI.\n> \n> Once upon a time I brought up different addressing/activating mechanism for\n> submodules and I remember Jens having some uneasy thoughts about\n> that back in the day. This series addresses the user confusion and documentation\n> better than what I had back then.\n> \n> On Mon, Mar 13, 2017 at 2:43 PM, Brandon Williams <bmwill@google.com> wrote:\n> > Currently the submodule.<name>.url config option is used to determine\n> > if a given submodule exists and is interesting to the user.  This\n> > however doesn't work very well because the URL is a config option for\n> > the scope of a repository, whereas the existence of a submodule is an\n> > option scoped to the working tree.\n> >\n> > In a future with worktree support for submodules, there will be multiple\n> > working trees, each of which may only need a subset of the submodules\n> > checked out.  The URL (which is where the submodule repository can be\n> > obtained) should not differ between different working trees.\n> >\n> > It may also be convenient for users to more easily specify groups of\n> > submodules they are interested in as apposed to running \"git submodule\n> > init <path>\" on each submodule they want checked out in their working\n> > tree.\n> >\n> > To this end two config options are introduced, submodule.active and\n> > submodule.<name>.active.  The submodule.active config holds a pathspec\n> > that specifies which submodules should exist in the working tree.  The\n> > submodule.<name>.active config is a boolean flag used to indicate if\n> > that particular submodule should exist in the working tree.\n> >\n> > Given these multiple ways to check for a submodule's existence the more\n> > fine-grained submodule.<name>.active option has the highest order of\n> > precedence followed by the pathspec check against submodule.active. To\n> > ensure backwards compatibility, if neither of these options are set git\n> > falls back to checking the submodule.<name>.url option to determine a\n> > submodule's existence.\n> >\n> \n> \n> \n> \n> >\n> > +submodule.<name>.active::\n> > +       Boolean value indicating if the submodule is of interest to git\n> > +       commands.  This config option takes precedence over the\n> > +       submodule.active config option.\n> \n> ... which itself takes precedence over the (deprecated) .URL\n> We conveniently do not talk about the URL here anymore.\n> But! We need to change submodule.<name>.URL now?\n\nyeah this patch introduces a change to the documentation for URL to\nindicate the change.\n\n-- \nBrandon Williams\n"},{"id":"314185","messageId":"20170315213737.GC159137@google.com","threadId":"45207","inReplyTo":"xmqqzignittf.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 05/10] submodule: decouple url and submodule existence","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T21:37:37Z","receivedAt":"2017-03-15T21:37:45Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > Currently the submodule.<name>.url config option is used to determine\n> > if a given submodule exists and is interesting to the user.  This\n> > however doesn't work very well because the URL is a config option for\n> > the scope of a repository, whereas the existence of a submodule is an\n> > option scoped to the working tree.\n> \n> A submodule exists if it is exists, whether the user is interested\n> in it or not.  If it should be checked out in the working tree is a\n> different matter, but that should be a logical AND between \"is it of\n> interest?\" and \"is the superproject tree has a gitlink for it in its\n> working tree?\".  \n> \n> So I do not agree with \"This however doesn't work\" at all.  I'd\n> understand it if you said \"This is cumbersome if we want to do this\n> and that, which are different from what we have done traditionally\"\n> and explain what this and that are and how they are different.\n> \n> > In a future with worktree support for submodules, there will be multiple\n> > working trees, each of which may only need a subset of the submodules\n> > checked out.  The URL (which is where the submodule repository can be\n> > obtained) should not differ between different working trees.\n> \n> And this makes the motivation a bit clearer.  When the user wants to\n> have multiple worktrees for the same superproject.  In such a\n> setting, the same submodule in two worktrees typically want to have\n> the same URL.  It may be different from what the upstream suggests\n> in the .gitmodules file, but the difference, i.e. the site specific\n> customization of the URL, should be the same between the two\n> worktrees.  But one worktree may be and the other worktree may not be\n> interested in that submodule, and with shared .git/config file, you\n> cannot have submodule.<name>.url set to one value and unset at the\n> same time.\n> \n> This series does not solve the \"two worktrees cannot have private\n> parts in the configuration namespace\" issue, but assuming it will be\n> solved by some other series, it anticipates that submodule.<name>.URL \n> would want to be shared between two worktrees most of time (note that\n> there will be users who want two separate .URL for the same submodule\n> while sharing the object database via worktrees mechanism, and you'll\n> need to prepare for them, too), and another \"bit\" that tells if the\n> submodule is of interest would want to be private to each worktree.\n> \n> That is the motivation, the reason why you want .URL to stop serving\n> the dual purpose of overriding upstream-suggested URL and indicating\n> the submodule is interesting to the user.\n> \n> > It may also be convenient for users to more easily specify groups of\n> > submodules they are interested in as apposed to running \"git submodule\n> > init <path>\" on each submodule they want checked out in their working\n> > tree.\n> >\n> > To this end two config options are introduced, submodule.active and\n> > submodule.<name>.active.  The submodule.active config holds a pathspec\n> > that specifies which submodules should exist in the working tree.  The\n> > submodule.<name>.active config is a boolean flag used to indicate if\n> > that particular submodule should exist in the working tree.\n> \n> And because two worktrees always share their .git/config, these new\n> configuration variables are useless to help workflow with multiple\n> worktrees with the current system, until \"per-worktree configuration\"\n> is invented.  But we prepare for that future in this step.\n> \n> Also submodule.active that takes pathspec and not name is an oddball\n> (use of \"name\" not \"path\" is to prepare for a submodule whose\n> location in the superproject changes depending on the commit in the\n> superproject), and we need to justify with an explanation.  I think\n> you envision two cases.  1. we encourage projects to adopt a\n> convention that submodules are grouped with leading directory, so\n> that pathspec e.g. lib/, would cover _all_ library-ish modules to\n> allow those who are interested in library-ish modules to set\n> \".active = lib/\" just once to say any and all modules in lib/ are\n> interesting.  2. another convention the projects can adopt, when\n> pathspec-attribute feature is invented, is to label submodules with\n> attribute to group them, so that a broad pathspec with attribute\n> requirement, e.g. .:(attr:lib), can be used to say any and all\n> modules with 'lib' attribute are interesting.\n> \n> The above two points (justifications, intended uses and future\n> plans) need to be clarified around here (and possibly in the\n> documentation), I would think.\n\nI'll overhaul this to better explain the intentions behind the change.\nThanks for pointing out what needs a more detailed explanation.\n\n> \n> > diff --git a/submodule.c b/submodule.c\n> > index 0a2831d84..2b33bd70f 100644\n> > --- a/submodule.c\n> > +++ b/submodule.c\n> > @@ -217,13 +217,41 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n> >  int is_submodule_initialized(const char *path)\n> >  {\n> >  \tint ret = 0;\n> > -\tconst struct submodule *module = NULL;\n> > +\tchar *key;\n> > +\tconst struct string_list *sl;\n> > +\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n> >  \n> > -\tmodule = submodule_from_path(null_sha1, path);\n> > +\t/* early return if there isn't a path->module mapping */\n> > +\tif (!module)\n> > +\t\treturn 0;\n> > +\n> > +\t/* submodule.<name>.active is set */\n> > +\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n> > +\tif (!git_config_get_bool(key, &ret)) {\n> > +\t\tfree(key);\n> > +\t\treturn ret;\n> > +\t}\n> > +\tfree(key);\n> > +\n> > +\tsl = git_config_get_value_multi(\"submodule.active\");\n> >  \n> > -\tif (module) {\n> > -\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n> > +\tif (sl) {\n> > +\t\tstruct pathspec ps;\n> > +\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n> > +\t\tconst struct string_list_item *item;\n> > +\n> > +\t\tfor_each_string_list_item(item, sl) {\n> > +\t\t\targv_array_push(&args, item->string);\n> > +\t\t}\n> > +\n> > +\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n> > +\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n> > +\n> > +\t\targv_array_clear(&args);\n> > +\t\tclear_pathspec(&ps);\n> > +\t} else {\n> >  \t\tchar *value = NULL;\n> > +\t\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n> >  \n> >  \t\tret = !git_config_get_string(key, &value);\n> \n> It probably is easier to read if you had a final \"return ret\" in the\n> \"if (sl) {...}\" part, just like you have one for the codepath that\n> deals with \"submodule.<name>.active\", and flatten the else clause.\n> That would make it clear that we have three ways with decreasing\n> precedence.\n\nSounds like a good change.  I'm all for making the code more readable.\n\n> \n> At this point, the answer from function is even less about \"is it\n> initialized?\"  but about \"is it of interest?\" (or \"is it to be\n> initialized?\").  We'd probably want a /* NEEDSWORK */ comment before\n> the function to remind us to come up with a better name after the\n> dust settles.\n\nYeah I expect we should rename it to 'is_submodule_active' at some\npoint, or something along those lines.\n\n> \n> > diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> > index f18e0c925..c41b899ab 100755\n> > --- a/t/t7413-submodule-is-active.sh\n> > +++ b/t/t7413-submodule-is-active.sh\n> > @@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n> >  \tgit -C super submodule--helper is-active sub1\n> >  '\n> >  \n> > +test_expect_success 'is-active works with submodule.<name>.active config' '\n> > +\tgit -C super config --bool submodule.sub1.active \"false\" &&\n> > +\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n> > +\n> > +\tgit -C super config --bool submodule.sub1.active \"true\" &&\n> > +\tgit -C super config --unset submodule.sub1.URL &&\n> > +\tgit -C super submodule--helper is-active sub1 &&\n> > +\n> > +\tgit -C super config submodule.sub1.URL ../sub &&\n> > +\tgit -C super config --unset submodule.sub1.active\n> > +'\n> \n> The last \"unset\" is done to clean the customization this test did,\n> in order to give a predictable beginning state to the next test?  If\n> so, use test_when_finished instead of &&-cascading it at the end.\n\nWill do.\n\n> \n> > + ...\n> > +test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n> > +\tgit -C super config --add submodule.active \"sub1\" &&\n> > +\tgit -C super config --bool submodule.sub1.active \"false\" &&\n> > +\tgit -C super config --bool submodule.sub2.active \"true\" &&\n> > +\n> > +\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n> > +\tgit -C super submodule--helper is-active sub2 &&\n> > +\n> > +\tgit -C super config --unset-all submodule.active &&\n> > +\tgit -C super config --unset submodule.sub1.active &&\n> > +\tgit -C super config --unset submodule.sub2.active\n> > +'\n> \n> Likewise for all the new tests in this patch.\n> \n> Thanks.\n\n-- \nBrandon Williams\n"},{"id":"314187","messageId":"20170315214227.GD159137@google.com","threadId":"45207","inReplyTo":"xmqqr31ziroz.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 06/10] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T21:42:27Z","receivedAt":"2017-03-15T21:42:34Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > +static void module_list_active(struct module_list *list)\n> > +{\n> > +\tint i;\n> > +\n> > +\tif (read_cache() < 0)\n> > +\t\tdie(_(\"index file corrupt\"));\n> > +\n> > +\tgitmodules_config();\n> > +\n> > +\tfor (i = 0; i < active_nr; i++) {\n> > +\t\tconst struct cache_entry *ce = active_cache[i];\n> > +\n> > +\t\tif (!S_ISGITLINK(ce->ce_mode) ||\n> > +\t\t    !is_submodule_initialized(ce->name))\n> > +\t\t\tcontinue;\n> \n> This, because \"is_submodule_initialized()\" is not \"is it\n> initialized?\" but \"is it interesting?\", will catch a submodule\n> that used to be uninteresting but has become interesting (e.g. a new\n> submodule added to somewhere in \"lib/\" when submodule.active lists\n> \"lib/\" as one of the pathspecs to match interesting submodules) and\n> automatically updates it.\n\nYes, is_submodule_initialized should be renamed to something more\ndescriptive (is_submodule_active, or something) in a follow on series\nbecause it is doing a check to see which submodule's the user finds\ninteresting.\n\n-- \nBrandon Williams\n"},{"id":"314188","messageId":"20170315215205.GE159137@google.com","threadId":"45207","inReplyTo":"xmqqvarbis4j.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 06/10] submodule update: add `--init-active` switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T21:52:05Z","receivedAt":"2017-03-15T21:52:19Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > +--init-active::\n> > +\tThis option is only valid for the update command.\n> > +\tInitialize all submodules configured in \"`submodule.active`\"\n> > +\tthat have not been updated before.\n> \n> You mean s/not been updated/not been initialized/ here?\n\nYep you're right, the documentation is a little stale too so I'll update\nit.\n\n> \n> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> > index f38e332c5..a3acc9e4c 100644\n> > --- a/builtin/submodule--helper.c\n> > +++ b/builtin/submodule--helper.c\n> > @@ -270,6 +270,34 @@ static int module_list_compute(int argc, const char **argv,\n> >  \treturn result;\n> >  }\n> >  \n> > +static void module_list_active(struct module_list *list)\n> > +{\n> > +\tint i;\n> > +\n> > +\tif (read_cache() < 0)\n> > +\t\tdie(_(\"index file corrupt\"));\n> > +\n> > +\tgitmodules_config();\n> \n> To this codepath, it probably would not make any difference, but in\n> general, calling gitmodules_config() after you did git_config()\n> would be a bug, right?  Otherwise, gitmodules_config() would\n> overwrite submodule.* configuration you read with git_config().\n\ngitmodules_config() doesn't interact with the git config, unless you do\ngit_config(submodule_confi, NULL) to overlay the two.  But yes it\ndoesn't effect this codepath.\n\n> I have a feeling that we need to make this function hard to misuse;\n> it is not a fault of _this_ patch, but still any and all additions\n> to any of the submodule*.c files needs careful vetting.\n\n-- \nBrandon Williams\n"},{"id":"314189","messageId":"20170315215913.GF159137@google.com","threadId":"45207","inReplyTo":"xmqqefxziqrj.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 10/10] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T21:59:13Z","receivedAt":"2017-03-15T21:59:25Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > +\tif git config --get submodule.active >/dev/null\n> > +\tthen\n> > +\t\t# If the submodule being adding isn't already covered by the\n> > +\t\t# current configured pathspec, set the submodule's active flag\n> > +\t\tif ! git submodule--helper is-active \"$sm_path\"\n> > +\t\tthen\n> > +\t\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n> > +\t\tfi\n> > +\telse\n> > +\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n> > +\tfi\n> \n> Why \"--add\"?  That's a way to add new entry for multi-valued\n> configuration, but you do not care if the old value (if existed)\n> were false or true---you want to replace it to true here, no?\n\nCorrect, that was a leftover bit from a previous version of the patch.\nWill fix.\n\n-- \nBrandon Williams\n"},{"id":"314194","messageId":"20170315224604.GG159137@google.com","threadId":"45207","inReplyTo":"xmqqinnbiqzs.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T22:46:04Z","receivedAt":"2017-03-15T22:47:18Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > When initializing a submodule set the submodule.<name>.active config to\n> > true to indicate that the submodule is active.\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> \n> Hmph.  When you do\n> \n> \tgit clone --submodule-spec=lib/\n> \n> and resulting repository says \"submodule.active = lib/\", you are\n> saying that you are interested in anything in \"lib/\", now or in the\n> future--that is the point of 08/10.\n> \n> It is unclear what your desire would be for a submodule that was\n> bound to somewhere in \"lib/\" in the superproject when you cloned\n> when it later gets moved outside \"lib/\".  With changes up to 08/10,\n> that submodule will no longer be interesting, but with this 09/10,\n> when recursing clone will activate it upon the initial clone, the\n> submodule is explicitly marked as active by its name, so no matter\n> where it gets moved later, it will remain to be interesting.\n> \n> I am not sure if that is a desired behaviour.\n\nI'm going to blame my poor commit msg for this.\n\nEssentially it would be nice if when a user explicitly says \"I want to\ninit submodule b\" that we obey and do just that.  What this patch does\nis allow for a user to do that and the \"submodule.<name>.active\" config\noption will only be set to 'true' in the event that that the submodule\nisn't already marked as being active/interesting by some other means.\nSo if we did\n\n  git clone --submodule-spec=lib/\n\nthen each module under 'lib/' won't have their submodule.<name>.active\nconfig set since submodule.active=lib/ already encompasses them.\n\n\nBut if no submodule-spec was given then it would default to all\nsubmodules and set every submodule's submodule.<name>.active config to\ntrue.\n\nI'll add a few tests to illustrate this.\n\n> \n> >  builtin/submodule--helper.c | 7 +++++++\n> >  1 file changed, 7 insertions(+)\n> >\n> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> > index a3acc9e4c..b669ed031 100644\n> > --- a/builtin/submodule--helper.c\n> > +++ b/builtin/submodule--helper.c\n> > @@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n> >  \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n> >  \t\t\tdisplaypath);\n> >  \n> > +\t/* Set active flag for the submodule being initialized */\n> > +\tif (!is_submodule_initialized(path)) {\n> > +\t\tstrbuf_reset(&sb);\n> > +\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n> > +\t\tgit_config_set_gently(sb.buf, \"true\");\n> > +\t}\n> > +\n> >  \t/*\n> >  \t * Copy url setting when it is not set yet.\n> >  \t * To look up the url in .git/config, we must not fall back to\n\n-- \nBrandon Williams\n"},{"id":"314198","messageId":"20170315230834.GH159137@google.com","threadId":"45207","inReplyTo":"xmqqmvcnir8m.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 07/10] clone: add --submodule-spec=<pathspec> switch","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-15T23:08:34Z","receivedAt":"2017-03-15T23:10:17Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/14, Junio C Hamano wrote:\n> Brandon Williams <bmwill@google.com> writes:\n> \n> > The new switch passes the pathspec to `git submodule update\n> > --init-active` which is called after the actual clone is done.\n> >\n> > Additionally this configures the submodule.active option to\n> > be the given pathspec, such that any future invocation of\n> > `git submodule update --init-active` will keep up\n> > with the pathspec.\n> >\n> > Based on a patch by Stefan Beller <sbeller@google.com>\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  Documentation/git-clone.txt | 23 ++++++++++-----\n> >  builtin/clone.c             | 36 +++++++++++++++++++++--\n> >  t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n> >  3 files changed, 120 insertions(+), 9 deletions(-)\n> >\n> > diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\n> > index 35cc34b2f..9692eab30 100644\n> > --- a/Documentation/git-clone.txt\n> > +++ b/Documentation/git-clone.txt\n> > @@ -15,7 +15,8 @@ SYNOPSIS\n> >  \t  [--dissociate] [--separate-git-dir <git dir>]\n> >  \t  [--depth <depth>] [--[no-]single-branch]\n> >  \t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n> > -\t  [--jobs <n>] [--] <repository> [<directory>]\n> > +\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n> > +\t  <repository> [<directory>]\n> \n> Hmph.  Can we then make \"--recurse-submodules\" an obsolete way to\n> spell \"--submodule-spec .\"?  I am not actively suggesting to\n> deprecate it; I am trying to see if there are semantic differences\n> between the two.\n\nWe can if you think that would be better.  That way if at clone time you\nsay \"I want the submodules too\" that your default config tracks all\nsubmodules even new ones yet to be added.\n\n> \n> I am also wondering \"--recurse-submodules=<pathspec>\" would be a\n> better UI, instead of introducing yet another option.\n\nYeah we could do that, have --recurse-submodules be a repeated option\nand if you don't specify a value it defaults to \".\"\n\nAny thoughts on this Stefan?\n\n> \n> > @@ -217,12 +218,20 @@ objects from the source repository into a pack in the cloned repository.\n> >  \n> >  --recursive::\n> >  --recurse-submodules::\n> > -\tAfter the clone is created, initialize all submodules within,\n> > -\tusing their default settings. This is equivalent to running\n> > -\t`git submodule update --init --recursive` immediately after\n> > -\tthe clone is finished. This option is ignored if the cloned\n> > -\trepository does not have a worktree/checkout (i.e. if any of\n> > -\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n> > +\tAfter the clone is created, initialize and clone all submodules\n> > +\twithin, using their default settings. This is equivalent to\n> > +\trunning `git submodule update --recursive --init` immediately\n> > +\tafter the clone is finished. This option is ignored if the\n> > +\tcloned repository does not have a worktree/checkout (i.e.  if\n> > +\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n> \n> With reflowing it is unnecessarily harder to spot what got changed.\n> \"and clone\" is inserted, \"--init\" and \"--recursive\" were swapped.\n> Any other changes?\n\nNo other changes, it just reads a little bit clearer now IMO.\n\n> \n> > diff --git a/builtin/clone.c b/builtin/clone.c\n> > index 3f63edbbf..c6731379b 100644\n> > --- a/builtin/clone.c\n> > +++ b/builtin/clone.c\n> > @@ -56,6 +56,16 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n> >  static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n> >  static int option_dissociate;\n> >  static int max_jobs = -1;\n> > +static struct string_list submodule_spec;\n> > +\n> > +static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n> > +{\n> > +\tif (unset)\n> > +\t\treturn -1;\n> > +\n> > +\tstring_list_append((struct string_list *)opt->value, arg);\n> > +\treturn 0;\n> > +}\n> \n> Hmph,  doesn't OPT_STRING_LIST work for this thing?\n\nYou're right, I'll change to that.\n\n-- \nBrandon Williams\n"},{"id":"314199","messageId":"CAGZ79kbqcGe30-FO4jAzx1wmJBF1dg5O5zYAK5mOFOfQk3PULQ@mail.gmail.com","threadId":"45207","inReplyTo":"20170315230834.GH159137@google.com","subject":"Re: [PATCH v3 07/10] clone: add --submodule-spec=<pathspec> switch","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-15T23:25:54Z","receivedAt":"2017-03-15T23:27:27Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 15, 2017 at 4:08 PM, Brandon Williams <bmwill@google.com> wrote:\n> On 03/14, Junio C Hamano wrote:\n>> Brandon Williams <bmwill@google.com> writes:\n>>\n>> > The new switch passes the pathspec to `git submodule update\n>> > --init-active` which is called after the actual clone is done.\n>> >\n>> > Additionally this configures the submodule.active option to\n>> > be the given pathspec, such that any future invocation of\n>> > `git submodule update --init-active` will keep up\n>> > with the pathspec.\n>> >\n>> > Based on a patch by Stefan Beller <sbeller@google.com>\n>> >\n>> > Signed-off-by: Brandon Williams <bmwill@google.com>\n>> > ---\n>> >  Documentation/git-clone.txt | 23 ++++++++++-----\n>> >  builtin/clone.c             | 36 +++++++++++++++++++++--\n>> >  t/t7400-submodule-basic.sh  | 70 +++++++++++++++++++++++++++++++++++++++++++++\n>> >  3 files changed, 120 insertions(+), 9 deletions(-)\n>> >\n>> > diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\n>> > index 35cc34b2f..9692eab30 100644\n>> > --- a/Documentation/git-clone.txt\n>> > +++ b/Documentation/git-clone.txt\n>> > @@ -15,7 +15,8 @@ SYNOPSIS\n>> >       [--dissociate] [--separate-git-dir <git dir>]\n>> >       [--depth <depth>] [--[no-]single-branch]\n>> >       [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n>> > -     [--jobs <n>] [--] <repository> [<directory>]\n>> > +     [--submodule-spec <pathspec>] [--jobs <n>] [--]\n>> > +     <repository> [<directory>]\n>>\n>> Hmph.  Can we then make \"--recurse-submodules\" an obsolete way to\n>> spell \"--submodule-spec .\"?  I am not actively suggesting to\n>> deprecate it; I am trying to see if there are semantic differences\n>> between the two.\n>\n> We can if you think that would be better.  That way if at clone time you\n> say \"I want the submodules too\" that your default config tracks all\n> submodules even new ones yet to be added.\n>\n>>\n>> I am also wondering \"--recurse-submodules=<pathspec>\" would be a\n>> better UI, instead of introducing yet another option.\n>\n> Yeah we could do that, have --recurse-submodules be a repeated option\n> and if you don't specify a value it defaults to \".\"\n>\n> Any thoughts on this Stefan?\n\nI think when I first tried to tackle this problem, I realized that the recursing\nbeyond the first level is orthogonal to the selection of submodules in the\nfirst level.\n\nConsider the following submodules\n\n    /sub1\n    /sub1/nestedA\n    /sub2\n    /sub2/nestedB\n\nTo select sub1\n  git clone --submodule-spec=sub1\n\nTo select sub1 +nestedA\n  git clone --submodule-spec=sub1 --recurse-submodules\n\nTo select sub1+sub2\n  git clone --submodule-spec=. --no-recurse-submodules\n\nHow to select sub1+nestedA+sub2, but not nestedB\n  not possible in one command\n\nI wonder if we want to be able to differentiate these cases at all,\nI guess if you want sub1, you also care about nestedB ?\n\n(Or is there any way to recurse pathspecs,\nwhich could be gitattributes)\n\nThat said, I optimized for the complex case, which we might not have\nand a combination into one switch makes sense, such that\n  git clone --recurse-submodules=<pathspec>\nis sufficient and turns on recursion beyond the first level.\n\nThanks,\nStefan\n"},{"id":"314231","messageId":"xmqq4lytcgod.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170315224604.GG159137@google.com","subject":"Re: [PATCH v3 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-16T16:47:14Z","receivedAt":"2017-03-16T16:47:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> So if we did\n>\n>   git clone --submodule-spec=lib/\n>\n> then each module under 'lib/' won't have their submodule.<name>.active\n> config set since submodule.active=lib/ already encompasses them.\n\nAh, OK.  That removes my worries ;-)  Thanks for an explanation.\n\n"},{"id":"314271","messageId":"20170316222952.53801-7-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 06/10] submodule: decouple url and submodule interest","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:48Z","receivedAt":"2017-03-16T22:37:01Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Currently the submodule.<name>.url config option is used to determine if\na given submodule is of interest to the user.  This ends up being\ncumbersome in a world where we want to have different submodules checked\nout in different worktrees or a more generalized mechanism to select\nwhich submodules are of interest.\n\nIn a future with worktree support for submodules, there will be multiple\nworking trees, each of which may only need a subset of the submodules\nchecked out.  The URL (which is where the submodule repository can be\nobtained) should not differ between different working trees.\n\nIt may also be convenient for users to more easily specify groups of\nsubmodules they are interested in as apposed to running \"git submodule\ninit <path>\" on each submodule they want checked out in their working\ntree.\n\nTo this end two config options are introduced, submodule.active and\nsubmodule.<name>.active.  The submodule.active config holds a pathspec\nthat specifies which submodules should exist in the working tree.  The\nsubmodule.<name>.active config is a boolean flag used to indicate if\nthat particular submodule should exist in the working tree.\n\nIts important to note that submodule.active functions differently than\nthe other configuration options since it takes a pathspec.  This allows\nusers to adopt at least two new workflows:\n\n  1. Submodules can be grouped with a leading directory, such that a\n     pathspec e.g. 'lib/' would cover all library-ish modules to allow\n     those who are interested in library-ish modules to set\n     \"submodule.active = lib/\" just once to say any and all modules in\n     'lib/' are interesting.\n\n  2. Once the pathspec-attribute feature is invented, users can label\n     submodules with attributes to group them, so that a broad pathspec\n     with attribute requirements, e.g. ':(attr:lib)', can be used to say\n     any and all modules with the 'lib' attribute are interesting.\n     Since the .gitattributes file, just like the .gitmodules file, is\n     tracked by the superproject, when a submodule moves in the\n     superproject tree, the project can adjust which path gets the\n     attribute in .gitattributes, just like it can adjust which path has\n     the submodule in .gitmodules.\n\nNeither of these two additional configuration options solve the problem\nof wanting different submodules checked out in different worktrees\nbecause multiple worktrees share .git/config.  Only once per-worktree\nconfigurations become a reality can this be solved, but this is a\nnecessary preparatory step for that future.\n\nGiven these multiple ways to check if a submodule is of interest, the\nmore fine-grained submodule.<name>.active option has the highest order\nof precedence followed by the pathspec check against submodule.active.\nTo ensure backwards compatibility, if neither of these options are set,\ngit falls back to checking the submodule.<name>.url option to determine\nif a submodule is interesting.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/config.txt       | 15 ++++++++++--\n submodule.c                    | 50 ++++++++++++++++++++++++++++++++------\n t/t7413-submodule-is-active.sh | 55 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 110 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5e5c2ae5f..d2d79b9d4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -2920,8 +2920,9 @@ submodule.<name>.url::\n \tThe URL for a submodule. This variable is copied from the .gitmodules\n \tfile to the git config via 'git submodule init'. The user can change\n \tthe configured URL before obtaining the submodule via 'git submodule\n-\tupdate'. After obtaining the submodule, the presence of this variable\n-\tis used as a sign whether the submodule is of interest to git commands.\n+\tupdate'. If neither submodule.<name>.active or submodule.active are\n+\tset, the presence of this variable is used as a fallback to indicate\n+\twhether the submodule is of interest to git commands.\n \tSee linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.\n \n submodule.<name>.update::\n@@ -2959,6 +2960,16 @@ submodule.<name>.ignore::\n \t\"--ignore-submodules\" option. The 'git submodule' commands are not\n \taffected by this setting.\n \n+submodule.<name>.active::\n+\tBoolean value indicating if the submodule is of interest to git\n+\tcommands.  This config option takes precedence over the\n+\tsubmodule.active config option.\n+\n+submodule.active::\n+\tA repeated field which contains a pathspec used to match against a\n+\tsubmodule's path to determine if the submodule is of interest to git\n+\tcommands.\n+\n submodule.fetchJobs::\n \tSpecifies how many submodules are fetched/cloned at the same time.\n \tA positive integer allows up to that number of submodules fetched\ndiff --git a/submodule.c b/submodule.c\nindex 0a2831d84..ad2779ee7 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -212,25 +212,59 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n }\n \n /*\n+ * NEEDSWORK: With the addition of different configuration options to determine\n+ * if a submodule is of interests, the validity of this function's name comes\n+ * into question.  Once the dust has settled and more concrete terminology is\n+ * decided upon, come up with a more proper name for this function.  One\n+ * potential candidate could be 'is_submodule_active()'.\n+ *\n  * Determine if a submodule has been initialized at a given 'path'\n  */\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tconst struct submodule *module = NULL;\n+\tchar *key = NULL;\n+\tchar *value = NULL;\n+\tconst struct string_list *sl;\n+\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n-\tmodule = submodule_from_path(null_sha1, path);\n+\t/* early return if there isn't a path->module mapping */\n+\tif (!module)\n+\t\treturn 0;\n \n-\tif (module) {\n-\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n-\t\tchar *value = NULL;\n+\t/* submodule.<name>.active is set */\n+\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n+\tif (!git_config_get_bool(key, &ret)) {\n+\t\tfree(key);\n+\t\treturn ret;\n+\t}\n+\tfree(key);\n \n-\t\tret = !git_config_get_string(key, &value);\n+\t/* submodule.active is set */\n+\tsl = git_config_get_value_multi(\"submodule.active\");\n+\tif (sl) {\n+\t\tstruct pathspec ps;\n+\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n+\t\tconst struct string_list_item *item;\n \n-\t\tfree(value);\n-\t\tfree(key);\n+\t\tfor_each_string_list_item(item, sl) {\n+\t\t\targv_array_push(&args, item->string);\n+\t\t}\n+\n+\t\tparse_pathspec(&ps, 0, 0, NULL, args.argv);\n+\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n+\n+\t\targv_array_clear(&args);\n+\t\tclear_pathspec(&ps);\n+\t\treturn ret;\n \t}\n \n+\t/* fallback to checking if the URL is set */\n+\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n+\tret = !git_config_get_string(key, &value);\n+\n+\tfree(value);\n+\tfree(key);\n \treturn ret;\n }\n \ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex f18e0c925..ea1644b58 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n \tgit -C super submodule--helper is-active sub1\n '\n \n+test_expect_success 'is-active works with submodule.<name>.active config' '\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"true\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_expect_success 'is-active works with basic submodule.active config' '\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n+test_expect_success 'is-active correctly works with paths that are not submodules' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule\n+'\n+\n+test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n+test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub2.active\" &&\n+\n+\tgit -C super config --add submodule.active \"sub1\" &&\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\tgit -C super config --bool submodule.sub2.active \"true\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314272","messageId":"20170316222952.53801-4-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:45Z","receivedAt":"2017-03-16T22:37:03Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Sync does some work determining what URLs should be used for a submodule\nbut then throws this work away if the submodule isn't active.  Instead\nperform the activity check earlier and skip inactive submodule in order\nto avoid doing unnecessary work.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 38 +++++++++++++++++++++-----------------\n 1 file changed, 21 insertions(+), 17 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ab233712d..577136148 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1090,6 +1090,13 @@ cmd_sync()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\")\n+\n+\t\t# skip inactive submodules\n+\t\tif ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tthen\n+\t\t\tcontinue\n+\t\tfi\n+\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n \t\t# Possibly a url relative to parent\n@@ -1111,27 +1118,24 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n+\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n+\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\n+\t\tif test -e \"$sm_path\"/.git\n \t\tthen\n-\t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-\t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\t\t(\n+\t\t\tsanitize_submodule_env\n+\t\t\tcd \"$sm_path\"\n+\t\t\tremote=$(get_default_remote)\n+\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n \n-\t\t\tif test -e \"$sm_path\"/.git\n+\t\t\tif test -n \"$recursive\"\n \t\t\tthen\n-\t\t\t(\n-\t\t\t\tsanitize_submodule_env\n-\t\t\t\tcd \"$sm_path\"\n-\t\t\t\tremote=$(get_default_remote)\n-\t\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n-\n-\t\t\t\tif test -n \"$recursive\"\n-\t\t\t\tthen\n-\t\t\t\t\tprefix=\"$prefix$sm_path/\"\n-\t\t\t\t\teval cmd_sync\n-\t\t\t\tfi\n-\t\t\t)\n+\t\t\t\tprefix=\"$prefix$sm_path/\"\n+\t\t\t\teval cmd_sync\n \t\t\tfi\n+\t\t)\n \t\tfi\n \tdone\n }\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314273","messageId":"20170316222952.53801-6-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 05/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:47Z","receivedAt":"2017-03-16T22:37:19Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Use the 'is_submodule_initialized()' helper to check for configured\nsubmodules instead of manually checking for the submodule's URL in the\nconfig.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 15 +++------------\n 1 file changed, 3 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 5fe7e23b1..f38e332c5 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -759,7 +759,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstruct strbuf displaypath_sb = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *displaypath = NULL;\n-\tchar *url = NULL;\n \tint needs_cloning = 0;\n \n \tif (ce_stage(ce)) {\n@@ -793,15 +792,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\t/*\n-\t * Looking up the url in .git/config.\n-\t * We must not fall back to .gitmodules as we only want\n-\t * to process configured submodules.\n-\t */\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n-\tgit_config_get_string(sb.buf, &url);\n-\tif (!url) {\n+\t/* Check if the submodule has been initialized. */\n+\tif (!is_submodule_initialized(ce->name)) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n \t\tgoto cleanup;\n \t}\n@@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, \"--depth=1\");\n \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n-\targv_array_pushl(&child->args, \"--url\", url, NULL);\n+\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n \tif (suc->references.nr) {\n \t\tstruct string_list_item *item;\n \t\tfor_each_string_list_item(item, &suc->references)\n@@ -845,7 +837,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, suc->depth);\n \n cleanup:\n-\tfree(url);\n \tstrbuf_reset(&displaypath_sb);\n \tstrbuf_reset(&sb);\n \n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314274","messageId":"20170316222952.53801-1-bmwill@google.com","threadId":"45207","inReplyTo":"20170313214341.172676-1-bmwill@google.com","subject":"[PATCH v4 00/10] decoupling url and submodule interest","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:42Z","receivedAt":"2017-03-16T22:37:31Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Lots of changes in v4 to address comments by Junio, Ramsay, and Stefan.\n  * Overhaul a lot of the commit messages (thanks Junio for helping wordsmith)\n  * Change how submodule.active functions with `submodule init` and clone\n    --recurse-submodules.  This allowed me to not have to add additional\n    command line options resulting in what I think is less cluttered UI from\n    the last version.  See patch 7 and 8 for more detail.\n  * Fixed an incorrect parameter type in patch 6 (thanks Ramsay).\n\nBrandon Williams (10):\n  submodule--helper: add is-active subcommand\n  submodule status: use submodule--helper is-active\n  submodule sync: skip work for inactive submodules\n  submodule sync: use submodule--helper is-active\n  submodule--helper clone: check for configured submodules using helper\n  submodule: decouple url and submodule interest\n  submodule init: initialize active submodules\n  clone: teach --recurse-submodules to optionally take a pathspec\n  submodule--helper init: set submodule.<name>.active\n  submodule add: respect submodule.active and submodule.<name>.active\n\n Documentation/config.txt        |  15 ++++-\n Documentation/git-clone.txt     |  14 +++--\n Documentation/git-submodule.txt |   4 +-\n builtin/clone.c                 |  47 +++++++++++---\n builtin/submodule--helper.c     |  69 ++++++++++++++++----\n git-submodule.sh                |  53 ++++++++++------\n submodule.c                     |  50 ++++++++++++---\n t/t7400-submodule-basic.sh      | 136 ++++++++++++++++++++++++++++++++++++++++\n t/t7413-submodule-is-active.sh  | 107 +++++++++++++++++++++++++++++++\n 9 files changed, 440 insertions(+), 55 deletions(-)\n create mode 100755 t/t7413-submodule-is-active.sh\n\n---interdiff with 'origin/bw/submodule-is-active'\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 9692eab30..30052cce4 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -14,9 +14,8 @@ SYNOPSIS\n \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n-\t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n-\t  [--submodule-spec <pathspec>] [--jobs <n>] [--]\n-\t  <repository> [<directory>]\n+\t  [--recurse-submodules] [--[no-]shallow-submodules]\n+\t  [--jobs <n>] [--] <repository> [<directory>]\n \n DESCRIPTION\n -----------\n@@ -216,22 +215,18 @@ objects from the source repository into a pack in the cloned repository.\n \tbranch when `--single-branch` clone was made, no remote-tracking\n \tbranch is created.\n \n---recursive::\n---recurse-submodules::\n-\tAfter the clone is created, initialize and clone all submodules\n-\twithin, using their default settings. This is equivalent to\n-\trunning `git submodule update --recursive --init` immediately\n-\tafter the clone is finished. This option is ignored if the\n-\tcloned repository does not have a worktree/checkout (i.e.  if\n-\tany of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n-\n---submodule-spec::\n-\tAfter the clone is created, initialize and clone specified\n-\tsubmodules within, using their default settings. It is possible\n-\tto give multiple specifications by giving this argument multiple\n-\ttimes. This is equivalent to configuring `submodule.active`\n-\tand then running `git submodule update --init-active`\n-\timmediately after the clone is finished.\n+--recurse-submodules[=<pathspec]::\n+\tAfter the clone is created, initialize and clone submodules\n+\twithin based on the provided pathspec.  If no pathspec is\n+\tprovided, all submodules are initialized and cloned.\n+\tSubmodules are initialized and cloned using their default\n+\tsettings.  The resulting clone has `submodule.active` set to\n+\tthe provided pathspec, or \".\" (meaning all submodules) if no\n+\tpathspec is provided.  This is equivalent to running\n+\t`git submodule update --init --recursive` immediately after\n+\tthe clone is finished. This option is ignored if the cloned\n+\trepository does not have a worktree/checkout (i.e. if any of\n+\t`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)\n \n --[no-]shallow-submodules::\n \tAll submodules which are cloned will be shallow with a depth of 1.\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 6b17cd707..74bc6200d 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -129,7 +129,9 @@ init [--] [<path>...]::\n \trepository will be assumed to be upstream.\n +\n Optional <path> arguments limit which submodules will be initialized.\n-If no path is specified, all submodules are initialized.\n+If no path is specified and submodule.active has been configured, submodules\n+configured to be active will be initialized, otherwise all submodules are\n+initialized.\n +\n When present, it will also copy the value of `submodule.$name.update`.\n This command does not alter existing information in .git/config.\n@@ -198,10 +200,6 @@ If the submodule is not yet initialized, and you just want to use the\n setting as stored in .gitmodules, you can automatically initialize the\n submodule with the `--init` option.\n \n-You can configure a set of submodules using pathspec syntax in\n-submodule.active you can use `--init-active` to initialize\n-those before updating.\n-\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n@@ -388,11 +386,6 @@ the submodule itself.\n \tInitialize all submodules for which \"git submodule init\" has not been\n \tcalled so far before updating.\n \n---init-active::\n-\tThis option is only valid for the update command.\n-\tInitialize all submodules configured in \"`submodule.active`\"\n-\tthat have not been updated before.\n-\n --name::\n \tThis option is only valid for the add command. It sets the submodule's\n \tname to the given string instead of defaulting to its path. The name\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex c6731379b..3dc8faac5 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -39,7 +39,7 @@ static const char * const builtin_clone_usage[] = {\n };\n \n static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n-static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;\n+static int option_local = -1, option_no_hardlinks, option_shared;\n static int option_shallow_submodules;\n static int deepen;\n static char *option_template, *option_depth, *option_since;\n@@ -56,14 +56,20 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n-static struct string_list submodule_spec;\n+static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;\n \n-static int submodule_spec_cb(const struct option *opt, const char *arg, int unset)\n+static int recurse_submodules_cb(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n {\n \tif (unset)\n \t\treturn -1;\n \n-\tstring_list_append((struct string_list *)opt->value, arg);\n+\tif (arg)\n+\t\tstring_list_append((struct string_list *)opt->value, arg);\n+\telse\n+\t\tstring_list_append((struct string_list *)opt->value,\n+\t\t\t\t   (const char *)opt->defval);\n+\n \treturn 0;\n }\n \n@@ -84,10 +90,13 @@ static struct option builtin_clone_options[] = {\n \t\t    N_(\"don't use local hardlinks, always copy\")),\n \tOPT_BOOL('s', \"shared\", &option_shared,\n \t\t    N_(\"setup as shared repository\")),\n-\tOPT_BOOL(0, \"recursive\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n-\tOPT_BOOL(0, \"recurse-submodules\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n+\t{ OPTION_CALLBACK, 0, \"recursive\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,\n+\t  (intptr_t)\".\" },\n+\t{ OPTION_CALLBACK, 0, \"recurse-submodules\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)\".\" },\n \tOPT_INTEGER('j', \"jobs\", &max_jobs,\n \t\t    N_(\"number of submodules cloned in parallel\")),\n \tOPT_STRING(0, \"template\", &option_template, N_(\"template-directory\"),\n@@ -122,9 +131,6 @@ static struct option builtin_clone_options[] = {\n \t\t\tTRANSPORT_FAMILY_IPV4),\n \tOPT_SET_INT('6', \"ipv6\", &family, N_(\"use IPv6 addresses only\"),\n \t\t\tTRANSPORT_FAMILY_IPV6),\n-\tOPT_CALLBACK(0, \"submodule-spec\", &submodule_spec, N_(\"<pathspec>\"),\n-\t\t\tN_(\"clone specific submodules. Pass multiple times for complex pathspecs\"),\n-\t\t\tsubmodule_spec_cb),\n \tOPT_END()\n };\n \n@@ -746,21 +752,13 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && (option_recursive || submodule_spec.nr > 0)) {\n+\tif (!err && (option_recurse_submodules.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n-\t\targv_array_pushl(&args, \"submodule\", \"update\", NULL);\n-\n-\t\tif (submodule_spec.nr > 0)\n-\t\t\targv_array_pushf(&args, \"--init-active\");\n-\t\telse\n-\t\t\targv_array_pushf(&args, \"--init\");\n+\t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n \n \t\tif (option_shallow_submodules == 1)\n \t\t\targv_array_push(&args, \"--depth=1\");\n \n-\t\tif (option_recursive)\n-\t\t\targv_array_pushf(&args, \"--recursive\");\n-\n \t\tif (max_jobs != -1)\n \t\t\targv_array_pushf(&args, \"--jobs=%d\", max_jobs);\n \n@@ -908,17 +906,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\toption_no_checkout = 1;\n \t}\n \n-\tif (submodule_spec.nr > 0) {\n-\t\tstruct string_list_item *item;\n-\t\tstruct strbuf sb = STRBUF_INIT;\n-\t\tfor_each_string_list_item(item, &submodule_spec) {\n-\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n-\t\t\t\t    item->string);\n-\t\t\tstring_list_append(&option_config,\n-\t\t\t\t\t   strbuf_detach(&sb, NULL));\n-\t\t}\n-\t}\n-\n \tif (!option_origin)\n \t\toption_origin = \"origin\";\n \n@@ -989,7 +976,21 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\t\tfprintf(stderr, _(\"Cloning into '%s'...\\n\"), dir);\n \t}\n \n-\tif (option_recursive) {\n+\tif (option_recurse_submodules.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\n+\t\t/* remove duplicates */\n+\t\tstring_list_sort(&option_recurse_submodules);\n+\t\tstring_list_remove_duplicates(&option_recurse_submodules, 0);\n+\n+\t\tfor_each_string_list_item(item, &option_recurse_submodules) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\n \t\tif (option_required_reference.nr &&\n \t\t    option_optional_reference.nr)\n \t\t\tdie(_(\"clone --recursive is not compatible with \"\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex b669ed031..a574596cb 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -437,12 +437,9 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \tstruct pathspec pathspec;\n \tstruct module_list list = MODULE_LIST_INIT;\n \tint quiet = 0;\n-\tint active = 0;\n \tint i;\n \n \tstruct option module_init_options[] = {\n-\t\tOPT_BOOL(0, \"active\", &active,\n-\t\t\t N_(\"ensure all active submodules are properly initialized\")),\n \t\tOPT__QUIET(&quiet, N_(\"Suppress output for initializing a submodule\")),\n \t\tOPT_END()\n \t};\n@@ -455,7 +452,11 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, module_init_options,\n \t\t\t     git_submodule_helper_usage, 0);\n \n-\tif (active)\n+\t/*\n+\t * If there are no path args and submodule.active is set then,\n+\t * by default, only initialize 'active' modules.\n+\t */\n+\tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n \t\tmodule_list_active(&list);\n \telse if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n \t\treturn 1;\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex eb13433d5..fc32286a4 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1212,7 +1212,6 @@ _git_clone ()\n \t\t\t--recurse-submodules\n \t\t\t--no-single-branch\n \t\t\t--shallow-submodules\n-\t\t\t--submodule-spec\n \t\t\t\"\n \t\treturn\n \t\t;;\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 2c510038d..6eca93416 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -9,7 +9,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n-   or: $dashless [--quiet] update [--init[-active]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -285,10 +285,10 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \t\t# current configured pathspec, set the submodule's active flag\n \t\tif ! git submodule--helper is-active \"$sm_path\"\n \t\tthen\n-\t\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\t\t\tgit config submodule.\"$sm_name\".active \"true\"\n \t\tfi\n \telse\n-\t\tgit config --add submodule.\"$sm_name\".active \"true\"\n+\t\tgit config submodule.\"$sm_name\".active \"true\"\n \tfi\n }\n \n@@ -375,9 +375,6 @@ cmd_init()\n \t\t-q|--quiet)\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n-\t\t--active)\n-\t\t\tGIT_ACTIVE=1\n-\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -392,7 +389,7 @@ cmd_init()\n \t\tshift\n \tdone\n \n-\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper init ${GIT_QUIET:+--quiet} ${GIT_ACTIVE:+--active} \"$@\"\n+\tgit ${wt_prefix:+-C \"$wt_prefix\"} ${prefix:+--super-prefix \"$prefix\"} submodule--helper init ${GIT_QUIET:+--quiet}  \"$@\"\n }\n \n #\n@@ -521,12 +518,7 @@ cmd_update()\n \t\t\tprogress=\"--progress\"\n \t\t\t;;\n \t\t-i|--init)\n-\t\t\ttest -z $init || test $init = by_args || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n-\t\t\tinit=by_args\n-\t\t\t;;\n-\t\t--init-active)\n-\t\t\ttest -z $init || test $init = by_config || die \"$(gettext \"Only one of --init or --init-active may be used.\")\"\n-\t\t\tinit=by_config\n+\t\t\tinit=1\n \t\t\t;;\n \t\t--remote)\n \t\t\tremote=1\n@@ -595,17 +587,7 @@ cmd_update()\n \n \tif test -n \"$init\"\n \tthen\n-\t\tif test \"$init\" = \"by_config\"\n-\t\tthen\n-\t\t\tif test $# -gt 0\n-\t\t\tthen\n-\t\t\t\tdie \"$(gettext \"path arguments are incompatible with --init-active\")\"\n-\t\t\tfi\n-\t\t\tcmd_init \"--active\" || return\n-\t\telse\n-\t\t\tcmd_init \"--\" \"$@\" || return\n-\t\tfi\n-\n+\t\tcmd_init \"--\" \"$@\" || return\n \tfi\n \n \t{\n@@ -1119,6 +1101,13 @@ cmd_sync()\n \twhile read mode sha1 stage sm_path\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n+\n+\t\t# skip inactive submodules\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tcontinue\n+\t\tfi\n+\n \t\tname=$(git submodule--helper name \"$sm_path\")\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n@@ -1141,27 +1130,24 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git submodule--helper is-active \"$sm_path\"\n+\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n+\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n+\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\n+\t\tif test -e \"$sm_path\"/.git\n \t\tthen\n-\t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-\t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\t\t(\n+\t\t\tsanitize_submodule_env\n+\t\t\tcd \"$sm_path\"\n+\t\t\tremote=$(get_default_remote)\n+\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n \n-\t\t\tif test -e \"$sm_path\"/.git\n+\t\t\tif test -n \"$recursive\"\n \t\t\tthen\n-\t\t\t(\n-\t\t\t\tsanitize_submodule_env\n-\t\t\t\tcd \"$sm_path\"\n-\t\t\t\tremote=$(get_default_remote)\n-\t\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n-\n-\t\t\t\tif test -n \"$recursive\"\n-\t\t\t\tthen\n-\t\t\t\t\tprefix=\"$prefix$sm_path/\"\n-\t\t\t\t\teval cmd_sync\n-\t\t\t\tfi\n-\t\t\t)\n+\t\t\t\tprefix=\"$prefix$sm_path/\"\n+\t\t\t\teval cmd_sync\n \t\t\tfi\n+\t\t)\n \t\tfi\n \tdone\n }\ndiff --git a/submodule.c b/submodule.c\nindex 2b33bd70f..ad2779ee7 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -212,12 +212,19 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n }\n \n /*\n+ * NEEDSWORK: With the addition of different configuration options to determine\n+ * if a submodule is of interests, the validity of this function's name comes\n+ * into question.  Once the dust has settled and more concrete terminology is\n+ * decided upon, come up with a more proper name for this function.  One\n+ * potential candidate could be 'is_submodule_active()'.\n+ *\n  * Determine if a submodule has been initialized at a given 'path'\n  */\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tchar *key;\n+\tchar *key = NULL;\n+\tchar *value = NULL;\n \tconst struct string_list *sl;\n \tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n@@ -233,8 +240,8 @@ int is_submodule_initialized(const char *path)\n \t}\n \tfree(key);\n \n+\t/* submodule.active is set */\n \tsl = git_config_get_value_multi(\"submodule.active\");\n-\n \tif (sl) {\n \t\tstruct pathspec ps;\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n@@ -244,21 +251,20 @@ int is_submodule_initialized(const char *path)\n \t\t\targv_array_push(&args, item->string);\n \t\t}\n \n-\t\tparse_pathspec(&ps, 0, 0, 0, args.argv);\n+\t\tparse_pathspec(&ps, 0, 0, NULL, args.argv);\n \t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n \n \t\targv_array_clear(&args);\n \t\tclear_pathspec(&ps);\n-\t} else {\n-\t\tchar *value = NULL;\n-\t\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n-\n-\t\tret = !git_config_get_string(key, &value);\n-\n-\t\tfree(value);\n-\t\tfree(key);\n+\t\treturn ret;\n \t}\n \n+\t/* fallback to checking if the URL is set */\n+\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n+\tret = !git_config_get_string(key, &value);\n+\n+\tfree(value);\n+\tfree(key);\n \treturn ret;\n }\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex c2e198a92..cf77a3a35 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1158,19 +1158,18 @@ test_expect_success 'submodule update --init with a specification' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'submodule update --init-active' '\n+test_expect_success 'submodule update --init with submodule.active set' '\n \ttest_when_finished \"rm -rf multisuper_clone\" &&\n \tpwd=$(pwd) &&\n \tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n \tgit -C multisuper_clone config submodule.active \".\" &&\n \tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n-\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule update --init &&\n \tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n-\ttest_must_fail git -C multisuper_clone submodule update --init-active sub0 &&\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'submodule init --active and update' '\n+test_expect_success 'submodule update and setting submodule.<name>.active' '\n \ttest_when_finished \"rm -rf multisuper_clone\" &&\n \tpwd=$(pwd) &&\n \tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n@@ -1189,7 +1188,7 @@ test_expect_success 'submodule init --active and update' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'clone --submodule-spec works' '\n+test_expect_success 'clone --recurse-submodules with a pathspec works' '\n \ttest_when_finished \"rm -rf multisuper_clone\" &&\n \tcat >expected <<-\\EOF &&\n \t sub0 (test2)\n@@ -1198,12 +1197,12 @@ test_expect_success 'clone --submodule-spec works' '\n \t-sub3\n \tEOF\n \n-\tgit clone --recurse-submodules --submodule-spec=\"sub0\" multisuper multisuper_clone &&\n+\tgit clone --recurse-submodules=\"sub0\" multisuper multisuper_clone &&\n \tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n \ttest_cmp actual expected\n '\n \n-test_expect_success 'clone with multiple --submodule-spec options' '\n+test_expect_success 'clone with multiple --recurse-submodules options' '\n \ttest_when_finished \"rm -rf multisuper_clone\" &&\n \tcat >expect <<-\\EOF &&\n \t-sub0\n@@ -1212,10 +1211,9 @@ test_expect_success 'clone with multiple --submodule-spec options' '\n \t sub3 (test2)\n \tEOF\n \n-\tgit clone --recurse-submodules \\\n-\t\t  --submodule-spec=\".\" \\\n-\t\t  --submodule-spec \":(exclude)sub0\" \\\n-\t\t  --submodule-spec \":(exclude)sub2\" \\\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n \t\t  multisuper multisuper_clone &&\n \tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n \ttest_cmp expect actual\n@@ -1239,11 +1237,10 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm\n \t sub5 (test2)\n \tEOF\n \n-\tgit clone --recurse-submodules \\\n-\t\t  --submodule-spec=\".\" \\\n-\t\t  --submodule-spec \":(exclude)sub0\" \\\n-\t\t  --submodule-spec \":(exclude)sub2\" \\\n-\t\t  --submodule-spec \":(exclude)sub4\" \\\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub4\" \\\n \t\t  multisuper multisuper_clone &&\n \n \tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n@@ -1254,9 +1251,20 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm\n \tgit -C multisuper commit -m \"add more submodules\" &&\n \t# obtain the new superproject\n \tgit -C multisuper_clone pull &&\n-\tgit -C multisuper_clone submodule update --init-active &&\n+\tgit -C multisuper_clone submodule update --init &&\n \tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n \ttest_cmp expect2 actual\n '\n \n+test_expect_success 'init properly sets the config' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule init -- sub0 sub1 &&\n+\tgit -C multisuper_clone config --get submodule.sub0.active &&\n+\ttest_must_fail git -C multisuper_clone config --get submodule.sub1.active\n+'\n+\n test_done\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex 865931978..9c785b07e 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -35,58 +35,58 @@ test_expect_success 'is-active works with urls' '\n '\n \n test_expect_success 'is-active works with submodule.<name>.active config' '\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\n \tgit -C super config --bool submodule.sub1.active \"false\" &&\n \ttest_must_fail git -C super submodule--helper is-active sub1 &&\n \n \tgit -C super config --bool submodule.sub1.active \"true\" &&\n \tgit -C super config --unset submodule.sub1.URL &&\n-\tgit -C super submodule--helper is-active sub1 &&\n-\n-\tgit -C super config submodule.sub1.URL ../sub &&\n-\tgit -C super config --unset submodule.sub1.active\n+\tgit -C super submodule--helper is-active sub1\n '\n \n test_expect_success 'is-active works with basic submodule.active config' '\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n \tgit -C super config --add submodule.active \".\" &&\n \tgit -C super config --unset submodule.sub1.URL &&\n \n \tgit -C super submodule--helper is-active sub1 &&\n-\tgit -C super submodule--helper is-active sub2 &&\n-\n-\tgit -C super config submodule.sub1.URL ../sub &&\n-\tgit -C super config --unset-all submodule.active\n+\tgit -C super submodule--helper is-active sub2\n '\n \n test_expect_success 'is-active correctly works with paths that are not submodules' '\n-\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n \n-\tgit -C super config --add submodule.active \".\" &&\n \ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n \n-\tgit -C super config --unset-all submodule.active\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule\n '\n \n test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n \tgit -C super config --add submodule.active \".\" &&\n \tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n \n \ttest_must_fail git -C super submodule--helper is-active sub1 &&\n-\tgit -C super submodule--helper is-active sub2 &&\n-\n-\tgit -C super config --unset-all submodule.active\n+\tgit -C super submodule--helper is-active sub2\n '\n \n test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub2.active\" &&\n+\n \tgit -C super config --add submodule.active \"sub1\" &&\n \tgit -C super config --bool submodule.sub1.active \"false\" &&\n \tgit -C super config --bool submodule.sub2.active \"true\" &&\n \n \ttest_must_fail git -C super submodule--helper is-active sub1 &&\n-\tgit -C super submodule--helper is-active sub2 &&\n-\n-\tgit -C super config --unset-all submodule.active &&\n-\tgit -C super config --unset submodule.sub1.active &&\n-\tgit -C super config --unset submodule.sub2.active\n+\tgit -C super submodule--helper is-active sub2\n '\n \n test_expect_success 'is-active, submodule.active and submodule add' '\n\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314275","messageId":"20170316222952.53801-3-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 02/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:44Z","receivedAt":"2017-03-16T22:37:45Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 136e26a2c..ab233712d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1010,14 +1010,13 @@ cmd_status()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n \t\t\tcontinue\n \t\tfi\n-\t\tif test -z \"$url\" ||\n+\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n \t\t{\n \t\t\t! test -d \"$sm_path\"/.git &&\n \t\t\t! test -f \"$sm_path\"/.git\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314276","messageId":"20170316222952.53801-9-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 08/10] clone: teach --recurse-submodules to optionally take a pathspec","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:50Z","receivedAt":"2017-03-16T22:38:01Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Teach clone --recurse-submodules to optionally take a pathspec argument\nwhich describes which submodules should be recursively initialized and\ncloned.  If no pathspec is provided, --recurse-submodules will\nrecursively initialize and clone all submodules by using a default\npathspec of \".\".  In order to construct more complex pathspecs,\n--recurse-submodules can be given multiple times.\n\nAdditionally this configures the 'submodule.active' configuration option\nto be the given pathspec, such that any future invocation of `git\nsubmodule update` will keep up with the pathspec.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-clone.txt | 14 ++++++----\n builtin/clone.c             | 47 ++++++++++++++++++++++++++-----\n t/t7400-submodule-basic.sh  | 68 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 117 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 35cc34b2f..30052cce4 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -14,7 +14,7 @@ SYNOPSIS\n \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n-\t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n+\t  [--recurse-submodules] [--[no-]shallow-submodules]\n \t  [--jobs <n>] [--] <repository> [<directory>]\n \n DESCRIPTION\n@@ -215,10 +215,14 @@ objects from the source repository into a pack in the cloned repository.\n \tbranch when `--single-branch` clone was made, no remote-tracking\n \tbranch is created.\n \n---recursive::\n---recurse-submodules::\n-\tAfter the clone is created, initialize all submodules within,\n-\tusing their default settings. This is equivalent to running\n+--recurse-submodules[=<pathspec]::\n+\tAfter the clone is created, initialize and clone submodules\n+\twithin based on the provided pathspec.  If no pathspec is\n+\tprovided, all submodules are initialized and cloned.\n+\tSubmodules are initialized and cloned using their default\n+\tsettings.  The resulting clone has `submodule.active` set to\n+\tthe provided pathspec, or \".\" (meaning all submodules) if no\n+\tpathspec is provided.  This is equivalent to running\n \t`git submodule update --init --recursive` immediately after\n \tthe clone is finished. This option is ignored if the cloned\n \trepository does not have a worktree/checkout (i.e. if any of\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 3f63edbbf..3dc8faac5 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -39,7 +39,7 @@ static const char * const builtin_clone_usage[] = {\n };\n \n static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n-static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;\n+static int option_local = -1, option_no_hardlinks, option_shared;\n static int option_shallow_submodules;\n static int deepen;\n static char *option_template, *option_depth, *option_since;\n@@ -56,6 +56,22 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;\n+\n+static int recurse_submodules_cb(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\treturn -1;\n+\n+\tif (arg)\n+\t\tstring_list_append((struct string_list *)opt->value, arg);\n+\telse\n+\t\tstring_list_append((struct string_list *)opt->value,\n+\t\t\t\t   (const char *)opt->defval);\n+\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -74,10 +90,13 @@ static struct option builtin_clone_options[] = {\n \t\t    N_(\"don't use local hardlinks, always copy\")),\n \tOPT_BOOL('s', \"shared\", &option_shared,\n \t\t    N_(\"setup as shared repository\")),\n-\tOPT_BOOL(0, \"recursive\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n-\tOPT_BOOL(0, \"recurse-submodules\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n+\t{ OPTION_CALLBACK, 0, \"recursive\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,\n+\t  (intptr_t)\".\" },\n+\t{ OPTION_CALLBACK, 0, \"recurse-submodules\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)\".\" },\n \tOPT_INTEGER('j', \"jobs\", &max_jobs,\n \t\t    N_(\"number of submodules cloned in parallel\")),\n \tOPT_STRING(0, \"template\", &option_template, N_(\"template-directory\"),\n@@ -733,7 +752,7 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && option_recursive) {\n+\tif (!err && (option_recurse_submodules.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n \t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n \n@@ -957,7 +976,21 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\t\tfprintf(stderr, _(\"Cloning into '%s'...\\n\"), dir);\n \t}\n \n-\tif (option_recursive) {\n+\tif (option_recurse_submodules.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\n+\t\t/* remove duplicates */\n+\t\tstring_list_sort(&option_recurse_submodules);\n+\t\tstring_list_remove_duplicates(&option_recurse_submodules, 0);\n+\n+\t\tfor_each_string_list_item(item, &option_recurse_submodules) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\n \t\tif (option_required_reference.nr &&\n \t\t    option_optional_reference.nr)\n \t\t\tdie(_(\"clone --recursive is not compatible with \"\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex fbbe932d1..3af1c00ff 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1188,4 +1188,72 @@ test_expect_success 'submodule update and setting submodule.<name>.active' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'clone --recurse-submodules with a pathspec works' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expected <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t-sub2\n+\t-sub3\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\"sub0\" multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'clone with multiple --recurse-submodules options' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expect <<-\\EOF &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n+\t\t  multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat <<-\\EOF >expect &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tcat <<-\\EOF >expect2 &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\t-sub4\n+\t sub5 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub4\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit -C multisuper submodule add ../sub1 sub4 &&\n+\tgit -C multisuper submodule add ../sub1 sub5 &&\n+\tgit -C multisuper commit -m \"add more submodules\" &&\n+\t# obtain the new superproject\n+\tgit -C multisuper_clone pull &&\n+\tgit -C multisuper_clone submodule update --init &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect2 actual\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314277","messageId":"20170316222952.53801-5-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 04/10] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:46Z","receivedAt":"2017-03-16T22:38:22Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 577136148..db94dea3b 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1089,14 +1089,14 @@ cmd_sync()\n \twhile read mode sha1 stage sm_path\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n-\t\tname=$(git submodule--helper name \"$sm_path\")\n \n \t\t# skip inactive submodules\n-\t\tif ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n \t\tthen\n \t\t\tcontinue\n \t\tfi\n \n+\t\tname=$(git submodule--helper name \"$sm_path\")\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n \t\t# Possibly a url relative to parent\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314278","messageId":"20170316222952.53801-8-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 07/10] submodule init: initialize active submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:49Z","receivedAt":"2017-03-16T22:38:34Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Teach `submodule init` to initialize submodules which have been\nconfigured to be active by setting 'submodule.active' with a pathspec.\n\nNow if no path arguments are given and 'submodule.active' is configured,\n`init` will initialize all submodules which have been configured to be\nactive.  If no path arguments are given and 'submodule.active' is not\nconfigured, then `init` will retain the old behavior of initializing all\nsubmodules.\n\nThis allows users to record more complex patterns as it saves retyping\nthem whenever you invoke update.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-submodule.txt |  4 ++-\n builtin/submodule--helper.c     | 36 +++++++++++++++++++++++++-\n t/t7400-submodule-basic.sh      | 57 +++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 95 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex e05d0cdde..74bc6200d 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -129,7 +129,9 @@ init [--] [<path>...]::\n \trepository will be assumed to be upstream.\n +\n Optional <path> arguments limit which submodules will be initialized.\n-If no path is specified, all submodules are initialized.\n+If no path is specified and submodule.active has been configured, submodules\n+configured to be active will be initialized, otherwise all submodules are\n+initialized.\n +\n When present, it will also copy the value of `submodule.$name.update`.\n This command does not alter existing information in .git/config.\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f38e332c5..e95738b42 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -270,6 +270,34 @@ static int module_list_compute(int argc, const char **argv,\n \treturn result;\n }\n \n+static void module_list_active(struct module_list *list)\n+{\n+\tint i;\n+\n+\tif (read_cache() < 0)\n+\t\tdie(_(\"index file corrupt\"));\n+\n+\tgitmodules_config();\n+\n+\tfor (i = 0; i < active_nr; i++) {\n+\t\tconst struct cache_entry *ce = active_cache[i];\n+\n+\t\tif (!S_ISGITLINK(ce->ce_mode) ||\n+\t\t    !is_submodule_initialized(ce->name))\n+\t\t\tcontinue;\n+\n+\t\tALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n+\t\tlist->entries[list->nr++] = ce;\n+\t\twhile (i + 1 < active_nr &&\n+\t\t       !strcmp(ce->name, active_cache[i + 1]->name))\n+\t\t\t/*\n+\t\t\t * Skip entries with the same name in different stages\n+\t\t\t * to make sure an entry is returned only once.\n+\t\t\t */\n+\t\t\ti++;\n+\t}\n+}\n+\n static int module_list(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -417,7 +445,13 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, module_init_options,\n \t\t\t     git_submodule_helper_usage, 0);\n \n-\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\t/*\n+\t * If there are no path args and submodule.active is set then,\n+\t * by default, only initialize 'active' modules.\n+\t */\n+\tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n+\t\tmodule_list_active(&list);\n+\telse if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n \t\treturn 1;\n \n \tfor (i = 0; i < list.nr; i++)\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex c09ce0d4c..fbbe932d1 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1130,5 +1130,62 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'setup superproject with submodules' '\n+\tgit init sub1 &&\n+\ttest_commit -C sub1 test &&\n+\ttest_commit -C sub1 test2 &&\n+\tgit init multisuper &&\n+\tgit -C multisuper submodule add ../sub1 sub0 &&\n+\tgit -C multisuper submodule add ../sub1 sub1 &&\n+\tgit -C multisuper submodule add ../sub1 sub2 &&\n+\tgit -C multisuper submodule add ../sub1 sub3 &&\n+\tgit -C multisuper commit -m \"add some submodules\"\n+'\n+\n+cat >expect <<-EOF\n+-sub0\n+ sub1 (test2)\n+ sub2 (test2)\n+ sub3 (test2)\n+EOF\n+\n+test_expect_success 'submodule update --init with a specification' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule update --init . \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update --init with submodule.active set' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config submodule.active \".\" &&\n+\tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule update --init &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update and setting submodule.<name>.active' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config --bool submodule.sub0.active \"true\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub1.active \"false\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub2.active \"true\" &&\n+\n+\tcat >expect <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t sub2 (test2)\n+\t-sub3\n+\tEOF\n+\tgit -C multisuper_clone submodule update &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n \n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314279","messageId":"20170316222952.53801-2-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 01/10] submodule--helper: add is-active subcommand","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:43Z","receivedAt":"2017-03-16T22:38:42Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The definition of which submodules are of interest by the user\nis tied to the configuration submodule.<name>.url; when it is\nset to a non-empty string, it is of interest.  We'd want to be\nable to later change this definition, but there are many places\nthat explicitly check this condition in the scripted Porcelain.\n\nIntroduce the \"is-active\" subcommand to \"submodule--helper\", so\nthat the exact definition of what submodule is of interest can\nbe centrally defined (and changed in later steps).  In a few\npatches that follow, this helper is used to replace the explicit\nchecks of the configuration variable in scripts.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c    | 11 +++++++++++\n t/t7413-submodule-is-active.sh | 31 +++++++++++++++++++++++++++++++\n 2 files changed, 42 insertions(+)\n create mode 100755 t/t7413-submodule-is-active.sh\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 15a5430c0..5fe7e23b1 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1127,6 +1127,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int is_active(int argc, const char **argv, const char *prefix)\n+{\n+\tif (argc != 2)\n+\t\tdie(\"submodule--helper is-active takes exactly 1 arguments\");\n+\n+\tgitmodules_config();\n+\n+\treturn !is_submodule_initialized(argv[1]);\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -1146,6 +1156,7 @@ static struct cmd_struct commands[] = {\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n+\t{\"is-active\", is_active, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nnew file mode 100755\nindex 000000000..f18e0c925\n--- /dev/null\n+++ b/t/t7413-submodule-is-active.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+\n+test_description='Test submodule--helper is-active\n+\n+This test verifies that `git submodue--helper is-active` correclty identifies\n+submodules which are \"active\" and interesting to the user.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tgit init sub &&\n+\ttest_commit -C sub initial &&\n+\tgit init super &&\n+\ttest_commit -C super initial &&\n+\tgit -C super submodule add ../sub sub1 &&\n+\tgit -C super submodule add ../sub sub2 &&\n+\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n+'\n+\n+test_expect_success 'is-active works with urls' '\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314280","messageId":"20170316222952.53801-11-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 10/10] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:52Z","receivedAt":"2017-03-16T22:38:45Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"In addition to adding submodule.<name>.url to the config, set\nsubmodule.<name>.active to true unless submodule.active is configured\nand the submodule's path matches the configured pathspec.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh               | 12 ++++++++++++\n t/t7413-submodule-is-active.sh | 21 +++++++++++++++++++++\n 2 files changed, 33 insertions(+)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex db94dea3b..6eca93416 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -278,6 +278,18 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n+\n+\tif git config --get submodule.active >/dev/null\n+\tthen\n+\t\t# If the submodule being adding isn't already covered by the\n+\t\t# current configured pathspec, set the submodule's active flag\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tgit config submodule.\"$sm_name\".active \"true\"\n+\t\tfi\n+\telse\n+\t\tgit config submodule.\"$sm_name\".active \"true\"\n+\tfi\n }\n \n #\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex ea1644b58..9c785b07e 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -15,6 +15,12 @@ test_expect_success 'setup' '\n \ttest_commit -C super initial &&\n \tgit -C super submodule add ../sub sub1 &&\n \tgit -C super submodule add ../sub sub2 &&\n+\n+\t# Remove submodule.<name>.active entries in order to test in an\n+\t# environment where only URLs are present in the conifg\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active &&\n+\n \tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n '\n \n@@ -83,4 +89,19 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active\n \tgit -C super submodule--helper is-active sub2\n '\n \n+test_expect_success 'is-active, submodule.active and submodule add' '\n+\ttest_when_finished \"rm -rf super2\" &&\n+\tgit init super2 &&\n+\ttest_commit -C super2 initial &&\n+\tgit -C super2 config --add submodule.active \"sub*\" &&\n+\n+\t# submodule add should only add submodule.<name>.active\n+\t# to the config if not matched by the pathspec\n+\tgit -C super2 submodule add ../sub sub1 &&\n+\ttest_must_fail git -C super2 config --get submodule.sub1.active &&\n+\n+\tgit -C super2 submodule add ../sub mod &&\n+\tgit -C super2 config --get submodule.mod.active\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314281","messageId":"20170316222952.53801-10-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v4 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T22:29:51Z","receivedAt":"2017-03-16T22:38:56Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"When initializing a submodule set the submodule.<name>.active config to\ntrue if the module hasn't already been configured to be active by some\nother means (e.g. a pathspec set in submodule.active).\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c |  7 +++++++\n t/t7400-submodule-basic.sh  | 11 +++++++++++\n 2 files changed, 18 insertions(+)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex e95738b42..a574596cb 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n \t\t\tdisplaypath);\n \n+\t/* Set active flag for the submodule being initialized */\n+\tif (!is_submodule_initialized(path)) {\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n+\t\tgit_config_set_gently(sb.buf, \"true\");\n+\t}\n+\n \t/*\n \t * Copy url setting when it is not set yet.\n \t * To look up the url in .git/config, we must not fall back to\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 3af1c00ff..cf77a3a35 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1256,4 +1256,15 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm\n \ttest_cmp expect2 actual\n '\n \n+test_expect_success 'init properly sets the config' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule init -- sub0 sub1 &&\n+\tgit -C multisuper_clone config --get submodule.sub0.active &&\n+\ttest_must_fail git -C multisuper_clone config --get submodule.sub1.active\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314289","messageId":"CAGZ79kaP9ob+qvso=pV=PPaB5guaW18w297xA+bfDFASV0zibg@mail.gmail.com","threadId":"45207","inReplyTo":"20170316222952.53801-4-bmwill@google.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-16T23:24:55Z","receivedAt":"2017-03-16T23:25:36Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> Sync does some work determining what URLs should be used for a submodule\n> but then throws this work away if the submodule isn't active.  Instead\n> perform the activity check earlier and skip inactive submodule in order\n> to avoid doing unnecessary work.\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n\n> +               # skip inactive submodules\n> +               if ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n\nAs a stand alone patch, this would look good to me.\nBut with the goal of this patch series in mind (which is to add\nmore options to enable a submodules \"active\" state), this\nshould rather be \"submodule--helper is-active\" here?\n\n\n> +               then\n> +                       continue\n> +               fi\n> +\n\nThe changes below here are just de-dented, no behavioral change?\n\n>\n> -               if git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> +               displaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> +               say \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> +               git config submodule.\"$name\".url \"$super_config_url\"\n> +\n> +               if test -e \"$sm_path\"/.git\n>                 then\n> -                       displaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> -                       say \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> -                       git config submodule.\"$name\".url \"$super_config_url\"\n> +               (\n> +                       sanitize_submodule_env\n> +                       cd \"$sm_path\"\n> +                       remote=$(get_default_remote)\n> +                       git config remote.\"$remote\".url \"$sub_origin_url\"\n>\n> -                       if test -e \"$sm_path\"/.git\n> +                       if test -n \"$recursive\"\n>                         then\n> -                       (\n> -                               sanitize_submodule_env\n> -                               cd \"$sm_path\"\n> -                               remote=$(get_default_remote)\n> -                               git config remote.\"$remote\".url \"$sub_origin_url\"\n> -\n> -                               if test -n \"$recursive\"\n> -                               then\n> -                                       prefix=\"$prefix$sm_path/\"\n> -                                       eval cmd_sync\n> -                               fi\n> -                       )\n> +                               prefix=\"$prefix$sm_path/\"\n> +                               eval cmd_sync\n>                         fi\n> +               )\n"},{"id":"314290","messageId":"20170316232637.GB168812@google.com","threadId":"45207","inReplyTo":"CAGZ79kaP9ob+qvso=pV=PPaB5guaW18w297xA+bfDFASV0zibg@mail.gmail.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-16T23:26:37Z","receivedAt":"2017-03-16T23:27:23Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/16, Stefan Beller wrote:\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> > Sync does some work determining what URLs should be used for a submodule\n> > but then throws this work away if the submodule isn't active.  Instead\n> > perform the activity check earlier and skip inactive submodule in order\n> > to avoid doing unnecessary work.\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> \n> > +               # skip inactive submodules\n> > +               if ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> \n> As a stand alone patch, this would look good to me.\n> But with the goal of this patch series in mind (which is to add\n> more options to enable a submodules \"active\" state), this\n> should rather be \"submodule--helper is-active\" here?\n\nJunio mentioned do this as a preparatory step to make it easier to\nreview.  The next patch changes that to use 'is-active' instead of the\nURL.\n\n> \n> \n> > +               then\n> > +                       continue\n> > +               fi\n> > +\n> \n> The changes below here are just de-dented, no behavioral change?\n\nYeah no behavioral change, just short circuiting earlier.\n> \n> >\n> > -               if git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> > +               displaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> > +               say \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> > +               git config submodule.\"$name\".url \"$super_config_url\"\n> > +\n> > +               if test -e \"$sm_path\"/.git\n> >                 then\n> > -                       displaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n> > -                       say \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n> > -                       git config submodule.\"$name\".url \"$super_config_url\"\n> > +               (\n> > +                       sanitize_submodule_env\n> > +                       cd \"$sm_path\"\n> > +                       remote=$(get_default_remote)\n> > +                       git config remote.\"$remote\".url \"$sub_origin_url\"\n> >\n> > -                       if test -e \"$sm_path\"/.git\n> > +                       if test -n \"$recursive\"\n> >                         then\n> > -                       (\n> > -                               sanitize_submodule_env\n> > -                               cd \"$sm_path\"\n> > -                               remote=$(get_default_remote)\n> > -                               git config remote.\"$remote\".url \"$sub_origin_url\"\n> > -\n> > -                               if test -n \"$recursive\"\n> > -                               then\n> > -                                       prefix=\"$prefix$sm_path/\"\n> > -                                       eval cmd_sync\n> > -                               fi\n> > -                       )\n> > +                               prefix=\"$prefix$sm_path/\"\n> > +                               eval cmd_sync\n> >                         fi\n> > +               )\n\n-- \nBrandon Williams\n"},{"id":"314291","messageId":"CAGZ79kaqeR3aNT5qVh0Zz1MmCJ-+WpRMLZAt23DMxU53kpr_Ew@mail.gmail.com","threadId":"45207","inReplyTo":"CAGZ79kaP9ob+qvso=pV=PPaB5guaW18w297xA+bfDFASV0zibg@mail.gmail.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-16T23:25:41Z","receivedAt":"2017-03-16T23:27:40Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 4:24 PM, Stefan Beller <sbeller@google.com> wrote:\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n>> Sync does some work determining what URLs should be used for a submodule\n>> but then throws this work away if the submodule isn't active.  Instead\n>> perform the activity check earlier and skip inactive submodule in order\n>> to avoid doing unnecessary work.\n>>\n>> Signed-off-by: Brandon Williams <bmwill@google.com>\n>> ---\n>\n>> +               # skip inactive submodules\n>> +               if ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n>\n> As a stand alone patch, this would look good to me.\n> But with the goal of this patch series in mind (which is to add\n> more options to enable a submodules \"active\" state), this\n> should rather be \"submodule--helper is-active\" here?\n>\n\nI spoke too early. this happens in the next patch.\n\nok, thanks!\nStefan\n"},{"id":"314292","messageId":"CAGZ79kbMB3e8AXsK5EYjDBe=7+AccF56+kFDY5PQ9i9=R+2G0w@mail.gmail.com","threadId":"45207","inReplyTo":"20170316222952.53801-7-bmwill@google.com","subject":"Re: [PATCH v4 06/10] submodule: decouple url and submodule interest","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-16T23:45:41Z","receivedAt":"2017-03-16T23:45:51Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> Currently the submodule.<name>.url config option is used to determine if\n> a given submodule is of interest to the user.  This ends up being\n> cumbersome in a world where we want to have different submodules checked\n> out in different worktrees or a more generalized mechanism to select\n> which submodules are of interest.\n>\n> In a future with worktree support for submodules, there will be multiple\n> working trees, each of which may only need a subset of the submodules\n> checked out.  The URL (which is where the submodule repository can be\n> obtained) should not differ between different working trees.\n>\n> It may also be convenient for users to more easily specify groups of\n> submodules they are interested in as apposed to running \"git submodule\n\nDid you mean opposed?\n\n> init <path>\" on each submodule they want checked out in their working\n> tree.\n>\n> To this end two config options are introduced, submodule.active and\n> submodule.<name>.active.  The submodule.active config holds a pathspec\n> that specifies which submodules should exist in the working tree.  The\n> submodule.<name>.active config is a boolean flag used to indicate if\n> that particular submodule should exist in the working tree.\n>\n> Its important to note that submodule.active functions differently than\n> the other configuration options since it takes a pathspec.  This allows\n> users to adopt at least two new workflows:\n>\n>   1. Submodules can be grouped with a leading directory, such that a\n>      pathspec e.g. 'lib/' would cover all library-ish modules to allow\n>      those who are interested in library-ish modules to set\n>      \"submodule.active = lib/\" just once to say any and all modules in\n>      'lib/' are interesting.\n>\n>   2. Once the pathspec-attribute feature is invented, users can label\n>      submodules with attributes to group them, so that a broad pathspec\n>      with attribute requirements, e.g. ':(attr:lib)', can be used to say\n>      any and all modules with the 'lib' attribute are interesting.\n>      Since the .gitattributes file, just like the .gitmodules file, is\n>      tracked by the superproject, when a submodule moves in the\n>      superproject tree, the project can adjust which path gets the\n>      attribute in .gitattributes, just like it can adjust which path has\n>      the submodule in .gitmodules.\n>\n> Neither of these two additional configuration options solve the problem\n> of wanting different submodules checked out in different worktrees\n> because multiple worktrees share .git/config.  Only once per-worktree\n> configurations become a reality can this be solved, but this is a\n> necessary preparatory step for that future.\n>\n> Given these multiple ways to check if a submodule is of interest, the\n> more fine-grained submodule.<name>.active option has the highest order\n> of precedence followed by the pathspec check against submodule.active.\n> To ensure backwards compatibility, if neither of these options are set,\n> git falls back to checking the submodule.<name>.url option to determine\n> if a submodule is interesting.\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  Documentation/config.txt       | 15 ++++++++++--\n>  submodule.c                    | 50 ++++++++++++++++++++++++++++++++------\n>  t/t7413-submodule-is-active.sh | 55 ++++++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 110 insertions(+), 10 deletions(-)\n>\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 5e5c2ae5f..d2d79b9d4 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -2920,8 +2920,9 @@ submodule.<name>.url::\n>         The URL for a submodule. This variable is copied from the .gitmodules\n>         file to the git config via 'git submodule init'. The user can change\n>         the configured URL before obtaining the submodule via 'git submodule\n> -       update'. After obtaining the submodule, the presence of this variable\n> -       is used as a sign whether the submodule is of interest to git commands.\n> +       update'. If neither submodule.<name>.active or submodule.active are\n> +       set, the presence of this variable is used as a fallback to indicate\n> +       whether the submodule is of interest to git commands.\n>         See linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.\n>\n>  submodule.<name>.update::\n> @@ -2959,6 +2960,16 @@ submodule.<name>.ignore::\n>         \"--ignore-submodules\" option. The 'git submodule' commands are not\n>         affected by this setting.\n>\n> +submodule.<name>.active::\n> +       Boolean value indicating if the submodule is of interest to git\n> +       commands.  This config option takes precedence over the\n> +       submodule.active config option.\n> +\n> +submodule.active::\n> +       A repeated field which contains a pathspec used to match against a\n> +       submodule's path to determine if the submodule is of interest to git\n> +       commands.\n> +\n>  submodule.fetchJobs::\n>         Specifies how many submodules are fetched/cloned at the same time.\n>         A positive integer allows up to that number of submodules fetched\n> diff --git a/submodule.c b/submodule.c\n> index 0a2831d84..ad2779ee7 100644\n> --- a/submodule.c\n> +++ b/submodule.c\n> @@ -212,25 +212,59 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n>  }\n>\n>  /*\n> + * NEEDSWORK: With the addition of different configuration options to determine\n> + * if a submodule is of interests, the validity of this function's name comes\n> + * into question.  Once the dust has settled and more concrete terminology is\n> + * decided upon, come up with a more proper name for this function.  One\n> + * potential candidate could be 'is_submodule_active()'.\n> + *\n>   * Determine if a submodule has been initialized at a given 'path'\n>   */\n>  int is_submodule_initialized(const char *path)\n>  {\n>         int ret = 0;\n> -       const struct submodule *module = NULL;\n> +       char *key = NULL;\n> +       char *value = NULL;\n> +       const struct string_list *sl;\n> +       const struct submodule *module = submodule_from_path(null_sha1, path);\n>\n> -       module = submodule_from_path(null_sha1, path);\n> +       /* early return if there isn't a path->module mapping */\n> +       if (!module)\n> +               return 0;\n>\n> -       if (module) {\n> -               char *key = xstrfmt(\"submodule.%s.url\", module->name);\n> -               char *value = NULL;\n> +       /* submodule.<name>.active is set */\n> +       key = xstrfmt(\"submodule.%s.active\", module->name);\n> +       if (!git_config_get_bool(key, &ret)) {\n> +               free(key);\n> +               return ret;\n> +       }\n> +       free(key);\n>\n> -               ret = !git_config_get_string(key, &value);\n> +       /* submodule.active is set */\n> +       sl = git_config_get_value_multi(\"submodule.active\");\n> +       if (sl) {\n> +               struct pathspec ps;\n> +               struct argv_array args = ARGV_ARRAY_INIT;\n> +               const struct string_list_item *item;\n>\n> -               free(value);\n> -               free(key);\n> +               for_each_string_list_item(item, sl) {\n> +                       argv_array_push(&args, item->string);\n> +               }\n> +\n> +               parse_pathspec(&ps, 0, 0, NULL, args.argv);\n> +               ret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n> +\n> +               argv_array_clear(&args);\n> +               clear_pathspec(&ps);\n> +               return ret;\n>         }\n>\n> +       /* fallback to checking if the URL is set */\n> +       key = xstrfmt(\"submodule.%s.url\", module->name);\n> +       ret = !git_config_get_string(key, &value);\n> +\n> +       free(value);\n> +       free(key);\n>         return ret;\n>  }\n>\n> diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\n> index f18e0c925..ea1644b58 100755\n> --- a/t/t7413-submodule-is-active.sh\n> +++ b/t/t7413-submodule-is-active.sh\n> @@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n>         git -C super submodule--helper is-active sub1\n>  '\n>\n> +test_expect_success 'is-active works with submodule.<name>.active config' '\n> +       test_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n\nSorry for late notice: This can be solved more elegantly with\ntest_config[_global].\nIf this is the only nit, we can fix it later, though.\n\n> +       test_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n\nAll tests look like they are structured very similarly; we also want\nto test all combinations,\nso maybe it is easier to make a function\n\ntest_active_case()\n{\n    on_submodule=$1\n    expectation=$2\n    with_URL=$3\n    with_active_flag=$4\n    with_active_pathspec=$5\n    test_expect_success 'is_active for $1 $2 $3 $4 $5' '\n      # do the actual test\n    '\n}\n\n# here put all combinations for a submodule + the non-submodule case\n\nI am not sure though, it would be a more disciplined approach, but not\nnecessarily\nbe covering the corner cases just as nice, i.e. having multiple\npathspecs, including 'exclude's.\n\nJust food for thought.\n\nThanks,\nStefan\n"},{"id":"314307","messageId":"xmqq8to4a2xv.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"CAGZ79kaP9ob+qvso=pV=PPaB5guaW18w297xA+bfDFASV0zibg@mail.gmail.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-17T05:26:52Z","receivedAt":"2017-03-17T05:26:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n>> Sync does some work determining what URLs should be used for a submodule\n>> but then throws this work away if the submodule isn't active.  Instead\n>> perform the activity check earlier and skip inactive submodule in order\n>> to avoid doing unnecessary work.\n>>\n>> Signed-off-by: Brandon Williams <bmwill@google.com>\n>> ---\n>\n>> +               # skip inactive submodules\n>> +               if ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n\nJust a style thing, but \">/dev/null 2>&1\" is probably shorter and\nmore idiomatic.\n\n"},{"id":"314313","messageId":"20170317065823.GA101452@google.com","threadId":"45207","inReplyTo":"xmqq8to4a2xv.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T06:58:23Z","receivedAt":"2017-03-17T07:04:38Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/16, Junio C Hamano wrote:\n> Stefan Beller <sbeller@google.com> writes:\n> \n> > On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> >> Sync does some work determining what URLs should be used for a submodule\n> >> but then throws this work away if the submodule isn't active.  Instead\n> >> perform the activity check earlier and skip inactive submodule in order\n> >> to avoid doing unnecessary work.\n> >>\n> >> Signed-off-by: Brandon Williams <bmwill@google.com>\n> >> ---\n> >\n> >> +               # skip inactive submodules\n> >> +               if ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n> \n> Just a style thing, but \">/dev/null 2>&1\" is probably shorter and\n> more idiomatic.\n> \n\nYeah you're right.  I was just moving around the code that was already\nthere.  But this line is removed in the next patch anyways so it\nprobably doesn't matter much.\n\n-- \nBrandon Williams\n"},{"id":"314360","messageId":"CAGZ79kbUC+R1bB64N=wQZrjxdTfA5OzC-i9sU0ymHtKgRVPu=w@mail.gmail.com","threadId":"45207","inReplyTo":"20170316222952.53801-10-bmwill@google.com","subject":"Re: [PATCH v4 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-17T17:22:57Z","receivedAt":"2017-03-17T17:23:43Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> When initializing a submodule set the submodule.<name>.active config to\n> true if the module hasn't already been configured to be active by some\n> other means (e.g. a pathspec set in submodule.active).\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n>  builtin/submodule--helper.c |  7 +++++++\n>  t/t7400-submodule-basic.sh  | 11 +++++++++++\n>  2 files changed, 18 insertions(+)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index e95738b42..a574596cb 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n>                 die(_(\"No url found for submodule path '%s' in .gitmodules\"),\n>                         displaypath);\n>\n> +       /* Set active flag for the submodule being initialized */\n> +       if (!is_submodule_initialized(path)) {\n> +               strbuf_reset(&sb);\n> +               strbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n\nIn case a reroll is needed, you could mark this location with\n\n    /*\n     * NEEDSWORK: in a multi-working-tree world we need to set\n     * this per-worktree here.\n     */\n"},{"id":"314361","messageId":"xmqq8to395j4.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170317065823.GA101452@google.com","subject":"Re: [PATCH v4 03/10] submodule sync: skip work for inactive submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-17T17:28:31Z","receivedAt":"2017-03-17T17:34:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> ...  But this line is removed in the next patch anyways so it\n> probably doesn't matter much.\n\nRight ;-)\n"},{"id":"314364","messageId":"CAGZ79kbvxpAEzVnNYRQ7VqzY30_oH4FGw3cH0TCwzCwCfy3HZw@mail.gmail.com","threadId":"45207","inReplyTo":"20170316222952.53801-9-bmwill@google.com","subject":"Re: [PATCH v4 08/10] clone: teach --recurse-submodules to optionally take a pathspec","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-17T17:37:38Z","receivedAt":"2017-03-17T17:48:33Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> Teach clone --recurse-submodules to optionally take a pathspec argument\n> which describes which submodules should be recursively initialized and\n> cloned.  If no pathspec is provided, --recurse-submodules will\n> recursively initialize and clone all submodules by using a default\n> pathspec of \".\".  In order to construct more complex pathspecs,\n> --recurse-submodules can be given multiple times.\n>\n> Additionally this configures the 'submodule.active' configuration option\n> to be the given pathspec, such that any future invocation of `git\n> submodule update` will keep up with the pathspec.\n\n  Additionally the switch '--recurse' is removed from the Documentation\n  as well as marked hidden in the options array, to streamline the options\n  for submodules.  A simple '--recurse' doesn't convey what is being\n  recursed, e.g. it could mean directories or trees (c.f. ls-tree)\n  In a lot of other commands we already have '--recurse-submodules'\n  to mean recursing into submodules, so advertise this spelling here\n  as the genuine option.\n\nwould also be worth mentioning?\n\n\n>  static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n> -static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;\n> +static int option_local = -1, option_no_hardlinks, option_shared;\n>  static int option_shallow_submodules;\n>  static int deepen;\n>  static char *option_template, *option_depth, *option_since;\n> @@ -56,6 +56,22 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n>  static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n>  static int option_dissociate;\n>  static int max_jobs = -1;\n> +static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;\n> +\n> +static int recurse_submodules_cb(const struct option *opt,\n> +                                const char *arg, int unset)\n> +{\n> +       if (unset)\n> +               return -1;\n> +\n> +       if (arg)\n> +               string_list_append((struct string_list *)opt->value, arg);\n> +       else\n\nin this case I'd rather set the removed (int) option_recursive, because, then\nwe would not need to sort and remove duplicates later on.\nInstead we can pass the string list literally to the config setter.\n(and in case option_recursive is set, we add an additional single\n\".\" then)\n\n> +               string_list_append((struct string_list *)opt->value,\n> +                                  (const char *)opt->defval);\n> +\n> +       return 0;\n> +}\n>\n\n>\n> -       if (!err && option_recursive) {\n> +       if (!err && (option_recurse_submodules.nr > 0)) {\n\nWell, checks like these would become more tangled.\nSo maybe we could set option_recursive unconditionally\nin the callback (unless unset was given, then we reset it to 0)\nand later have a check if we need to add \".\" (when the string list\nis empty).\n\nSpeaking of unset, this seems like a regression here, as the callback\nwould error out to \"git clone --no-recurse\", which is a valid use case\ncurrently? (Searching for \"git clone --no-recurse\" yields no results\nvia Google, so maybe this use case is not so valid)\n\nTo get the behavior as is for unset we could just clear the string\nlist instead of returning -1.\n\nThanks,\nStefan\n"},{"id":"314369","messageId":"CAGZ79ka-rQ3YtdduAMYf-XYitKMfX2iEVh4wfR1vD6RzqhHDzw@mail.gmail.com","threadId":"45207","inReplyTo":"20170316222952.53801-8-bmwill@google.com","subject":"Re: [PATCH v4 07/10] submodule init: initialize active submodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-17T18:17:08Z","receivedAt":"2017-03-17T18:17:13Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> Teach `submodule init` to initialize submodules which have been\n> configured to be active by setting 'submodule.active' with a pathspec.\n>\n> Now if no path arguments are given and 'submodule.active' is configured,\n> `init` will initialize all submodules which have been configured to be\n> active.  If no path arguments are given and 'submodule.active' is not\n> configured, then `init` will retain the old behavior of initializing all\n> submodules.\n>\n> This allows users to record more complex patterns as it saves retyping\n> them whenever you invoke update.\n>\n> Signed-off-by: Brandon Williams <bmwill@google.com>\n> ---\n\n\n> @@ -417,7 +445,13 @@ static int module_init(int argc, const char **argv, const char *prefix)\n>         argc = parse_options(argc, argv, prefix, module_init_options,\n>                              git_submodule_helper_usage, 0);\n>\n> -       if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n> +       /*\n> +        * If there are no path args and submodule.active is set then,\n> +        * by default, only initialize 'active' modules.\n> +        */\n> +       if (!argc && git_config_get_value_multi(\"submodule.active\"))\n> +               module_list_active(&list);\n> +       else if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n>                 return 1;\n\nI would rather reuse module_list_compute and then post-process the list\nto filter out inactive submodules iff \"submodule.active\" is set as that seems\ncleaner and performance is not a pressing issue here?\n\n>\n> +static void module_list_active(struct module_list *list)\n> +{\n> +       int i;\n> +\n> +       if (read_cache() < 0)\n> +               die(_(\"index file corrupt\"));\n> +\n> +       gitmodules_config();\n\nHere we also need to have\n\n  git_config(submodule_config, NULL);\n\nsuch that is_submodule_initialized works correctly,\nI would assume?\n\n> +\n> +       for (i = 0; i < active_nr; i++) {\n> +               const struct cache_entry *ce = active_cache[i];\n> +\n> +               if (!S_ISGITLINK(ce->ce_mode) ||\n> +                   !is_submodule_initialized(ce->name))\n> +                       continue;\n> +\n> +               ALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n> +               list->entries[list->nr++] = ce;\n> +               while (i + 1 < active_nr &&\n> +                      !strcmp(ce->name, active_cache[i + 1]->name))\n> +                       /*\n> +                        * Skip entries with the same name in different stages\n> +                        * to make sure an entry is returned only once.\n> +                        */\n> +                       i++;\n> +       }\n> +}\n"},{"id":"314391","messageId":"20170317212814.GB63813@google.com","threadId":"45207","inReplyTo":"CAGZ79kbvxpAEzVnNYRQ7VqzY30_oH4FGw3cH0TCwzCwCfy3HZw@mail.gmail.com","subject":"Re: [PATCH v4 08/10] clone: teach --recurse-submodules to optionally take a pathspec","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T21:28:14Z","receivedAt":"2017-03-17T21:37:06Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/17, Stefan Beller wrote:\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> > Teach clone --recurse-submodules to optionally take a pathspec argument\n> > which describes which submodules should be recursively initialized and\n> > cloned.  If no pathspec is provided, --recurse-submodules will\n> > recursively initialize and clone all submodules by using a default\n> > pathspec of \".\".  In order to construct more complex pathspecs,\n> > --recurse-submodules can be given multiple times.\n> >\n> > Additionally this configures the 'submodule.active' configuration option\n> > to be the given pathspec, such that any future invocation of `git\n> > submodule update` will keep up with the pathspec.\n> \n>   Additionally the switch '--recurse' is removed from the Documentation\n>   as well as marked hidden in the options array, to streamline the options\n>   for submodules.  A simple '--recurse' doesn't convey what is being\n>   recursed, e.g. it could mean directories or trees (c.f. ls-tree)\n>   In a lot of other commands we already have '--recurse-submodules'\n>   to mean recursing into submodules, so advertise this spelling here\n>   as the genuine option.\n> \n> would also be worth mentioning?\n> \n\nYeah I can just add this into the commit msg.\n\n> \n> >  static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n> > -static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;\n> > +static int option_local = -1, option_no_hardlinks, option_shared;\n> >  static int option_shallow_submodules;\n> >  static int deepen;\n> >  static char *option_template, *option_depth, *option_since;\n> > @@ -56,6 +56,22 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n> >  static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n> >  static int option_dissociate;\n> >  static int max_jobs = -1;\n> > +static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;\n> > +\n> > +static int recurse_submodules_cb(const struct option *opt,\n> > +                                const char *arg, int unset)\n> > +{\n> > +       if (unset)\n> > +               return -1;\n> > +\n> > +       if (arg)\n> > +               string_list_append((struct string_list *)opt->value, arg);\n> > +       else\n> \n> in this case I'd rather set the removed (int) option_recursive, because, then\n> we would not need to sort and remove duplicates later on.\n> Instead we can pass the string list literally to the config setter.\n> (and in case option_recursive is set, we add an additional single\n> \".\" then)\n\nThat's just one more thing to worry about though.  This felt a little\nbit cleaner than doing more special casing.\n\n> \n> > +               string_list_append((struct string_list *)opt->value,\n> > +                                  (const char *)opt->defval);\n> > +\n> > +       return 0;\n> > +}\n> >\n> \n> >\n> > -       if (!err && option_recursive) {\n> > +       if (!err && (option_recurse_submodules.nr > 0)) {\n> \n> Well, checks like these would become more tangled.\n> So maybe we could set option_recursive unconditionally\n> in the callback (unless unset was given, then we reset it to 0)\n> and later have a check if we need to add \".\" (when the string list\n> is empty).\n> \n> Speaking of unset, this seems like a regression here, as the callback\n> would error out to \"git clone --no-recurse\", which is a valid use case\n> currently? (Searching for \"git clone --no-recurse\" yields no results\n> via Google, so maybe this use case is not so valid)\n> \n> To get the behavior as is for unset we could just clear the string\n> list instead of returning -1.\n\nYeah I can do that.\n\n> \n> Thanks,\n> Stefan\n\n-- \nBrandon Williams\n"},{"id":"314395","messageId":"20170317215546.GC63813@google.com","threadId":"45207","inReplyTo":"CAGZ79kbUC+R1bB64N=wQZrjxdTfA5OzC-i9sU0ymHtKgRVPu=w@mail.gmail.com","subject":"Re: [PATCH v4 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T21:55:46Z","receivedAt":"2017-03-17T21:55:54Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/17, Stefan Beller wrote:\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> > When initializing a submodule set the submodule.<name>.active config to\n> > true if the module hasn't already been configured to be active by some\n> > other means (e.g. a pathspec set in submodule.active).\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> >  builtin/submodule--helper.c |  7 +++++++\n> >  t/t7400-submodule-basic.sh  | 11 +++++++++++\n> >  2 files changed, 18 insertions(+)\n> >\n> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> > index e95738b42..a574596cb 100644\n> > --- a/builtin/submodule--helper.c\n> > +++ b/builtin/submodule--helper.c\n> > @@ -361,6 +361,13 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n> >                 die(_(\"No url found for submodule path '%s' in .gitmodules\"),\n> >                         displaypath);\n> >\n> > +       /* Set active flag for the submodule being initialized */\n> > +       if (!is_submodule_initialized(path)) {\n> > +               strbuf_reset(&sb);\n> > +               strbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n> \n> In case a reroll is needed, you could mark this location with\n> \n>     /*\n>      * NEEDSWORK: in a multi-working-tree world we need to set\n>      * this per-worktree here.\n>      */\n\nI'll add this here and where this happens in clone.\n\n-- \nBrandon Williams\n"},{"id":"314402","messageId":"20170317222849.GD63813@google.com","threadId":"45207","inReplyTo":"CAGZ79ka-rQ3YtdduAMYf-XYitKMfX2iEVh4wfR1vD6RzqhHDzw@mail.gmail.com","subject":"Re: [PATCH v4 07/10] submodule init: initialize active submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:28:49Z","receivedAt":"2017-03-17T22:28:56Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 03/17, Stefan Beller wrote:\n> On Thu, Mar 16, 2017 at 3:29 PM, Brandon Williams <bmwill@google.com> wrote:\n> > Teach `submodule init` to initialize submodules which have been\n> > configured to be active by setting 'submodule.active' with a pathspec.\n> >\n> > Now if no path arguments are given and 'submodule.active' is configured,\n> > `init` will initialize all submodules which have been configured to be\n> > active.  If no path arguments are given and 'submodule.active' is not\n> > configured, then `init` will retain the old behavior of initializing all\n> > submodules.\n> >\n> > This allows users to record more complex patterns as it saves retyping\n> > them whenever you invoke update.\n> >\n> > Signed-off-by: Brandon Williams <bmwill@google.com>\n> > ---\n> \n> \n> > @@ -417,7 +445,13 @@ static int module_init(int argc, const char **argv, const char *prefix)\n> >         argc = parse_options(argc, argv, prefix, module_init_options,\n> >                              git_submodule_helper_usage, 0);\n> >\n> > -       if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n> > +       /*\n> > +        * If there are no path args and submodule.active is set then,\n> > +        * by default, only initialize 'active' modules.\n> > +        */\n> > +       if (!argc && git_config_get_value_multi(\"submodule.active\"))\n> > +               module_list_active(&list);\n> > +       else if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n> >                 return 1;\n> \n> I would rather reuse module_list_compute and then post-process the list\n> to filter out inactive submodules iff \"submodule.active\" is set as that seems\n> cleaner and performance is not a pressing issue here?\n\nOk, Can do.  Shouldn't be very hard to do that.\n\n> \n> >\n> > +static void module_list_active(struct module_list *list)\n> > +{\n> > +       int i;\n> > +\n> > +       if (read_cache() < 0)\n> > +               die(_(\"index file corrupt\"));\n> > +\n> > +       gitmodules_config();\n> \n> Here we also need to have\n> \n>   git_config(submodule_config, NULL);\n> \n> such that is_submodule_initialized works correctly,\n> I would assume?\n\nNo I don't think so.  is_submodule_initialized doesn't need them to be\noverlayed, it just needs the .gitmodules mappings.\n\n> \n> > +\n> > +       for (i = 0; i < active_nr; i++) {\n> > +               const struct cache_entry *ce = active_cache[i];\n> > +\n> > +               if (!S_ISGITLINK(ce->ce_mode) ||\n> > +                   !is_submodule_initialized(ce->name))\n> > +                       continue;\n> > +\n> > +               ALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n> > +               list->entries[list->nr++] = ce;\n> > +               while (i + 1 < active_nr &&\n> > +                      !strcmp(ce->name, active_cache[i + 1]->name))\n> > +                       /*\n> > +                        * Skip entries with the same name in different stages\n> > +                        * to make sure an entry is returned only once.\n> > +                        */\n> > +                       i++;\n> > +       }\n> > +}\n\n-- \nBrandon Williams\n"},{"id":"314408","messageId":"20170317223805.95271-7-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 06/10] submodule: decouple url and submodule interest","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:01Z","receivedAt":"2017-03-17T22:44:53Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Currently the submodule.<name>.url config option is used to determine if\na given submodule is of interest to the user.  This ends up being\ncumbersome in a world where we want to have different submodules checked\nout in different worktrees or a more generalized mechanism to select\nwhich submodules are of interest.\n\nIn a future with worktree support for submodules, there will be multiple\nworking trees, each of which may only need a subset of the submodules\nchecked out.  The URL (which is where the submodule repository can be\nobtained) should not differ between different working trees.\n\nIt may also be convenient for users to more easily specify groups of\nsubmodules they are interested in as opposed to running \"git submodule\ninit <path>\" on each submodule they want checked out in their working\ntree.\n\nTo this end two config options are introduced, submodule.active and\nsubmodule.<name>.active.  The submodule.active config holds a pathspec\nthat specifies which submodules should exist in the working tree.  The\nsubmodule.<name>.active config is a boolean flag used to indicate if\nthat particular submodule should exist in the working tree.\n\nIts important to note that submodule.active functions differently than\nthe other configuration options since it takes a pathspec.  This allows\nusers to adopt at least two new workflows:\n\n  1. Submodules can be grouped with a leading directory, such that a\n     pathspec e.g. 'lib/' would cover all library-ish modules to allow\n     those who are interested in library-ish modules to set\n     \"submodule.active = lib/\" just once to say any and all modules in\n     'lib/' are interesting.\n\n  2. Once the pathspec-attribute feature is invented, users can label\n     submodules with attributes to group them, so that a broad pathspec\n     with attribute requirements, e.g. ':(attr:lib)', can be used to say\n     any and all modules with the 'lib' attribute are interesting.\n     Since the .gitattributes file, just like the .gitmodules file, is\n     tracked by the superproject, when a submodule moves in the\n     superproject tree, the project can adjust which path gets the\n     attribute in .gitattributes, just like it can adjust which path has\n     the submodule in .gitmodules.\n\nNeither of these two additional configuration options solve the problem\nof wanting different submodules checked out in different worktrees\nbecause multiple worktrees share .git/config.  Only once per-worktree\nconfigurations become a reality can this be solved, but this is a\nnecessary preparatory step for that future.\n\nGiven these multiple ways to check if a submodule is of interest, the\nmore fine-grained submodule.<name>.active option has the highest order\nof precedence followed by the pathspec check against submodule.active.\nTo ensure backwards compatibility, if neither of these options are set,\ngit falls back to checking the submodule.<name>.url option to determine\nif a submodule is interesting.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/config.txt       | 15 ++++++++++--\n submodule.c                    | 50 ++++++++++++++++++++++++++++++++------\n t/t7413-submodule-is-active.sh | 55 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 110 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5e5c2ae5f..d2d79b9d4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -2920,8 +2920,9 @@ submodule.<name>.url::\n \tThe URL for a submodule. This variable is copied from the .gitmodules\n \tfile to the git config via 'git submodule init'. The user can change\n \tthe configured URL before obtaining the submodule via 'git submodule\n-\tupdate'. After obtaining the submodule, the presence of this variable\n-\tis used as a sign whether the submodule is of interest to git commands.\n+\tupdate'. If neither submodule.<name>.active or submodule.active are\n+\tset, the presence of this variable is used as a fallback to indicate\n+\twhether the submodule is of interest to git commands.\n \tSee linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.\n \n submodule.<name>.update::\n@@ -2959,6 +2960,16 @@ submodule.<name>.ignore::\n \t\"--ignore-submodules\" option. The 'git submodule' commands are not\n \taffected by this setting.\n \n+submodule.<name>.active::\n+\tBoolean value indicating if the submodule is of interest to git\n+\tcommands.  This config option takes precedence over the\n+\tsubmodule.active config option.\n+\n+submodule.active::\n+\tA repeated field which contains a pathspec used to match against a\n+\tsubmodule's path to determine if the submodule is of interest to git\n+\tcommands.\n+\n submodule.fetchJobs::\n \tSpecifies how many submodules are fetched/cloned at the same time.\n \tA positive integer allows up to that number of submodules fetched\ndiff --git a/submodule.c b/submodule.c\nindex 0a2831d84..ad2779ee7 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -212,25 +212,59 @@ void gitmodules_config_sha1(const unsigned char *commit_sha1)\n }\n \n /*\n+ * NEEDSWORK: With the addition of different configuration options to determine\n+ * if a submodule is of interests, the validity of this function's name comes\n+ * into question.  Once the dust has settled and more concrete terminology is\n+ * decided upon, come up with a more proper name for this function.  One\n+ * potential candidate could be 'is_submodule_active()'.\n+ *\n  * Determine if a submodule has been initialized at a given 'path'\n  */\n int is_submodule_initialized(const char *path)\n {\n \tint ret = 0;\n-\tconst struct submodule *module = NULL;\n+\tchar *key = NULL;\n+\tchar *value = NULL;\n+\tconst struct string_list *sl;\n+\tconst struct submodule *module = submodule_from_path(null_sha1, path);\n \n-\tmodule = submodule_from_path(null_sha1, path);\n+\t/* early return if there isn't a path->module mapping */\n+\tif (!module)\n+\t\treturn 0;\n \n-\tif (module) {\n-\t\tchar *key = xstrfmt(\"submodule.%s.url\", module->name);\n-\t\tchar *value = NULL;\n+\t/* submodule.<name>.active is set */\n+\tkey = xstrfmt(\"submodule.%s.active\", module->name);\n+\tif (!git_config_get_bool(key, &ret)) {\n+\t\tfree(key);\n+\t\treturn ret;\n+\t}\n+\tfree(key);\n \n-\t\tret = !git_config_get_string(key, &value);\n+\t/* submodule.active is set */\n+\tsl = git_config_get_value_multi(\"submodule.active\");\n+\tif (sl) {\n+\t\tstruct pathspec ps;\n+\t\tstruct argv_array args = ARGV_ARRAY_INIT;\n+\t\tconst struct string_list_item *item;\n \n-\t\tfree(value);\n-\t\tfree(key);\n+\t\tfor_each_string_list_item(item, sl) {\n+\t\t\targv_array_push(&args, item->string);\n+\t\t}\n+\n+\t\tparse_pathspec(&ps, 0, 0, NULL, args.argv);\n+\t\tret = match_pathspec(&ps, path, strlen(path), 0, NULL, 1);\n+\n+\t\targv_array_clear(&args);\n+\t\tclear_pathspec(&ps);\n+\t\treturn ret;\n \t}\n \n+\t/* fallback to checking if the URL is set */\n+\tkey = xstrfmt(\"submodule.%s.url\", module->name);\n+\tret = !git_config_get_string(key, &value);\n+\n+\tfree(value);\n+\tfree(key);\n \treturn ret;\n }\n \ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex f18e0c925..ea1644b58 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -28,4 +28,59 @@ test_expect_success 'is-active works with urls' '\n \tgit -C super submodule--helper is-active sub1\n '\n \n+test_expect_success 'is-active works with submodule.<name>.active config' '\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\n+\tgit -C super config --bool submodule.sub1.active \"true\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_expect_success 'is-active works with basic submodule.active config' '\n+\ttest_when_finished \"git -C super config submodule.sub1.URL ../sub\" &&\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n+test_expect_success 'is-active correctly works with paths that are not submodules' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\ttest_must_fail git -C super submodule--helper is-active not-a-submodule\n+'\n+\n+test_expect_success 'is-active works with exclusions in submodule.active config' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\n+\tgit -C super config --add submodule.active \".\" &&\n+\tgit -C super config --add submodule.active \":(exclude)sub1\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n+test_expect_success 'is-active with submodule.active and submodule.<name>.active' '\n+\ttest_when_finished \"git -C super config --unset-all submodule.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub1.active\" &&\n+\ttest_when_finished \"git -C super config --unset submodule.sub2.active\" &&\n+\n+\tgit -C super config --add submodule.active \"sub1\" &&\n+\tgit -C super config --bool submodule.sub1.active \"false\" &&\n+\tgit -C super config --bool submodule.sub2.active \"true\" &&\n+\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314409","messageId":"20170317223805.95271-10-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 09/10] submodule--helper init: set submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:04Z","receivedAt":"2017-03-17T22:45:24Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"When initializing a submodule set the submodule.<name>.active config to\ntrue if the module hasn't already been configured to be active by some\nother means (e.g. a pathspec set in submodule.active).\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 12 ++++++++++++\n t/t7400-submodule-basic.sh  | 11 +++++++++++\n 2 files changed, 23 insertions(+)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 65208faa7..7700d8948 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -357,6 +357,18 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\t\tdisplaypath);\n \n \t/*\n+\t * NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t * set in the per-worktree config.\n+\t *\n+\t * Set active flag for the submodule being initialized\n+\t */\n+\tif (!is_submodule_initialized(path)) {\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n+\t\tgit_config_set_gently(sb.buf, \"true\");\n+\t}\n+\n+\t/*\n \t * Copy url setting when it is not set yet.\n \t * To look up the url in .git/config, we must not fall back to\n \t * .gitmodules, so look it up directly.\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 3af1c00ff..cf77a3a35 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1256,4 +1256,15 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm\n \ttest_cmp expect2 actual\n '\n \n+test_expect_success 'init properly sets the config' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule init -- sub0 sub1 &&\n+\tgit -C multisuper_clone config --get submodule.sub0.active &&\n+\ttest_must_fail git -C multisuper_clone config --get submodule.sub1.active\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314410","messageId":"20170317223805.95271-6-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 05/10] submodule--helper clone: check for configured submodules using helper","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:00Z","receivedAt":"2017-03-17T22:45:32Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Use the 'is_submodule_initialized()' helper to check for configured\nsubmodules instead of manually checking for the submodule's URL in the\nconfig.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c | 15 +++------------\n 1 file changed, 3 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 5fe7e23b1..f38e332c5 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -759,7 +759,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstruct strbuf displaypath_sb = STRBUF_INIT;\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *displaypath = NULL;\n-\tchar *url = NULL;\n \tint needs_cloning = 0;\n \n \tif (ce_stage(ce)) {\n@@ -793,15 +792,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\tgoto cleanup;\n \t}\n \n-\t/*\n-\t * Looking up the url in .git/config.\n-\t * We must not fall back to .gitmodules as we only want\n-\t * to process configured submodules.\n-\t */\n-\tstrbuf_reset(&sb);\n-\tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n-\tgit_config_get_string(sb.buf, &url);\n-\tif (!url) {\n+\t/* Check if the submodule has been initialized. */\n+\tif (!is_submodule_initialized(ce->name)) {\n \t\tnext_submodule_warn_missing(suc, out, displaypath);\n \t\tgoto cleanup;\n \t}\n@@ -835,7 +827,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, \"--depth=1\");\n \targv_array_pushl(&child->args, \"--path\", sub->path, NULL);\n \targv_array_pushl(&child->args, \"--name\", sub->name, NULL);\n-\targv_array_pushl(&child->args, \"--url\", url, NULL);\n+\targv_array_pushl(&child->args, \"--url\", sub->url, NULL);\n \tif (suc->references.nr) {\n \t\tstruct string_list_item *item;\n \t\tfor_each_string_list_item(item, &suc->references)\n@@ -845,7 +837,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \t\targv_array_push(&child->args, suc->depth);\n \n cleanup:\n-\tfree(url);\n \tstrbuf_reset(&displaypath_sb);\n \tstrbuf_reset(&sb);\n \n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314414","messageId":"20170317223805.95271-4-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 03/10] submodule sync: skip work for inactive submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:37:58Z","receivedAt":"2017-03-17T23:09:38Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Sync does some work determining what URLs should be used for a submodule\nbut then throws this work away if the submodule isn't active.  Instead\nperform the activity check earlier and skip inactive submodule in order\nto avoid doing unnecessary work.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 38 +++++++++++++++++++++-----------------\n 1 file changed, 21 insertions(+), 17 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ab233712d..577136148 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1090,6 +1090,13 @@ cmd_sync()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\")\n+\n+\t\t# skip inactive submodules\n+\t\tif ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tthen\n+\t\t\tcontinue\n+\t\tfi\n+\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n \t\t# Possibly a url relative to parent\n@@ -1111,27 +1118,24 @@ cmd_sync()\n \t\t\t;;\n \t\tesac\n \n-\t\tif git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n+\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n+\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\n+\t\tif test -e \"$sm_path\"/.git\n \t\tthen\n-\t\t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n-\t\t\tsay \"$(eval_gettext \"Synchronizing submodule url for '\\$displaypath'\")\"\n-\t\t\tgit config submodule.\"$name\".url \"$super_config_url\"\n+\t\t(\n+\t\t\tsanitize_submodule_env\n+\t\t\tcd \"$sm_path\"\n+\t\t\tremote=$(get_default_remote)\n+\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n \n-\t\t\tif test -e \"$sm_path\"/.git\n+\t\t\tif test -n \"$recursive\"\n \t\t\tthen\n-\t\t\t(\n-\t\t\t\tsanitize_submodule_env\n-\t\t\t\tcd \"$sm_path\"\n-\t\t\t\tremote=$(get_default_remote)\n-\t\t\t\tgit config remote.\"$remote\".url \"$sub_origin_url\"\n-\n-\t\t\t\tif test -n \"$recursive\"\n-\t\t\t\tthen\n-\t\t\t\t\tprefix=\"$prefix$sm_path/\"\n-\t\t\t\t\teval cmd_sync\n-\t\t\t\tfi\n-\t\t\t)\n+\t\t\t\tprefix=\"$prefix$sm_path/\"\n+\t\t\t\teval cmd_sync\n \t\t\tfi\n+\t\t)\n \t\tfi\n \tdone\n }\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314415","messageId":"20170317223805.95271-3-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 02/10] submodule status: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:37:57Z","receivedAt":"2017-03-17T23:09:53Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 136e26a2c..ab233712d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1010,14 +1010,13 @@ cmd_status()\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n \t\tname=$(git submodule--helper name \"$sm_path\") || exit\n-\t\turl=$(git config submodule.\"$name\".url)\n \t\tdisplaypath=$(git submodule--helper relative-path \"$prefix$sm_path\" \"$wt_prefix\")\n \t\tif test \"$stage\" = U\n \t\tthen\n \t\t\tsay \"U$sha1 $displaypath\"\n \t\t\tcontinue\n \t\tfi\n-\t\tif test -z \"$url\" ||\n+\t\tif ! git submodule--helper is-active \"$sm_path\" ||\n \t\t{\n \t\t\t! test -d \"$sm_path\"/.git &&\n \t\t\t! test -f \"$sm_path\"/.git\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314419","messageId":"CAGZ79kbUW4L7G8+18Umeysv+tPuWxZUF9e4axBdb_=8BwjqzVQ@mail.gmail.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"Re: [PATCH v5 00/10] decoupling url and submodule interest","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-17T23:25:47Z","receivedAt":"2017-03-17T23:26:39Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Fri, Mar 17, 2017 at 3:37 PM, Brandon Williams <bmwill@google.com> wrote:\n> Changes in v5:\n>   * Add \"NEEDSWORK\" comments to indicate where attention is needed once\n>     per-worktree config is a reality\n>   * --no-recurse now works by clearing the string list of paths.\n>   * module_list_active() now does post-processing instead of duplicating code.\n\nSkimming these patches, they all look good to me.\n\nThanks,\nStefan\n"},{"id":"314420","messageId":"CAGZ79kbMpMjX166nhitTpLuYH+pDN74zSVAGisQhQKLTfUzZTQ@mail.gmail.com","threadId":"45207","inReplyTo":"20170317222849.GD63813@google.com","subject":"Re: [PATCH v4 07/10] submodule init: initialize active submodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-03-17T23:25:00Z","receivedAt":"2017-03-17T23:27:18Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":">> Here we also need to have\n>>\n>>   git_config(submodule_config, NULL);\n>>\n>> such that is_submodule_initialized works correctly,\n>> I would assume?\n>\n> No I don't think so.  is_submodule_initialized doesn't need them to be\n> overlayed, it just needs the .gitmodules mappings.\n\nok, thanks! I assumed it would need it later on, when e.g. looking at\n\"submodule.active\" from the config.\n\nThanks,\nStefan\n"},{"id":"314424","messageId":"20170317223805.95271-9-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 08/10] clone: teach --recurse-submodules to optionally take a pathspec","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:03Z","receivedAt":"2017-03-17T23:43:44Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Teach clone --recurse-submodules to optionally take a pathspec argument\nwhich describes which submodules should be recursively initialized and\ncloned.  If no pathspec is provided, --recurse-submodules will\nrecursively initialize and clone all submodules by using a default\npathspec of \".\".  In order to construct more complex pathspecs,\n--recurse-submodules can be given multiple times.\n\nThis also configures the 'submodule.active' configuration option to be\nthe given pathspec, such that any future invocation of `git submodule\nupdate` will keep up with the pathspec.\n\nAdditionally the switch '--recurse' is removed from the Documentation as\nwell as marked hidden in the options array, to streamline the options\nfor submodules.  A simple '--recurse' doesn't convey what is being\nrecursed, e.g. it could mean directories or trees (c.f. ls-tree) In a\nlot of other commands we already have '--recurse-submodules' to mean\nrecursing into submodules, so advertise this spelling here as the\ngenuine option.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-clone.txt | 14 ++++++----\n builtin/clone.c             | 50 ++++++++++++++++++++++++++++-----\n t/t7400-submodule-basic.sh  | 68 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 120 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 35cc34b2f..30052cce4 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -14,7 +14,7 @@ SYNOPSIS\n \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n \t  [--dissociate] [--separate-git-dir <git dir>]\n \t  [--depth <depth>] [--[no-]single-branch]\n-\t  [--recursive | --recurse-submodules] [--[no-]shallow-submodules]\n+\t  [--recurse-submodules] [--[no-]shallow-submodules]\n \t  [--jobs <n>] [--] <repository> [<directory>]\n \n DESCRIPTION\n@@ -215,10 +215,14 @@ objects from the source repository into a pack in the cloned repository.\n \tbranch when `--single-branch` clone was made, no remote-tracking\n \tbranch is created.\n \n---recursive::\n---recurse-submodules::\n-\tAfter the clone is created, initialize all submodules within,\n-\tusing their default settings. This is equivalent to running\n+--recurse-submodules[=<pathspec]::\n+\tAfter the clone is created, initialize and clone submodules\n+\twithin based on the provided pathspec.  If no pathspec is\n+\tprovided, all submodules are initialized and cloned.\n+\tSubmodules are initialized and cloned using their default\n+\tsettings.  The resulting clone has `submodule.active` set to\n+\tthe provided pathspec, or \".\" (meaning all submodules) if no\n+\tpathspec is provided.  This is equivalent to running\n \t`git submodule update --init --recursive` immediately after\n \tthe clone is finished. This option is ignored if the cloned\n \trepository does not have a worktree/checkout (i.e. if any of\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 3f63edbbf..a7be61d6b 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -39,7 +39,7 @@ static const char * const builtin_clone_usage[] = {\n };\n \n static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n-static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;\n+static int option_local = -1, option_no_hardlinks, option_shared;\n static int option_shallow_submodules;\n static int deepen;\n static char *option_template, *option_depth, *option_since;\n@@ -56,6 +56,21 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;\n static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;\n+\n+static int recurse_submodules_cb(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tif (unset)\n+\t\tstring_list_clear((struct string_list *)opt->value, 0);\n+\telse if (arg)\n+\t\tstring_list_append((struct string_list *)opt->value, arg);\n+\telse\n+\t\tstring_list_append((struct string_list *)opt->value,\n+\t\t\t\t   (const char *)opt->defval);\n+\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -74,10 +89,13 @@ static struct option builtin_clone_options[] = {\n \t\t    N_(\"don't use local hardlinks, always copy\")),\n \tOPT_BOOL('s', \"shared\", &option_shared,\n \t\t    N_(\"setup as shared repository\")),\n-\tOPT_BOOL(0, \"recursive\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n-\tOPT_BOOL(0, \"recurse-submodules\", &option_recursive,\n-\t\t    N_(\"initialize submodules in the clone\")),\n+\t{ OPTION_CALLBACK, 0, \"recursive\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,\n+\t  (intptr_t)\".\" },\n+\t{ OPTION_CALLBACK, 0, \"recurse-submodules\", &option_recurse_submodules,\n+\t  N_(\"pathspec\"), N_(\"initialize submodules in the clone\"),\n+\t  PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)\".\" },\n \tOPT_INTEGER('j', \"jobs\", &max_jobs,\n \t\t    N_(\"number of submodules cloned in parallel\")),\n \tOPT_STRING(0, \"template\", &option_template, N_(\"template-directory\"),\n@@ -733,7 +751,7 @@ static int checkout(int submodule_progress)\n \terr |= run_hook_le(NULL, \"post-checkout\", sha1_to_hex(null_sha1),\n \t\t\t   sha1_to_hex(sha1), \"1\", NULL);\n \n-\tif (!err && option_recursive) {\n+\tif (!err && (option_recurse_submodules.nr > 0)) {\n \t\tstruct argv_array args = ARGV_ARRAY_INIT;\n \t\targv_array_pushl(&args, \"submodule\", \"update\", \"--init\", \"--recursive\", NULL);\n \n@@ -957,7 +975,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\t\tfprintf(stderr, _(\"Cloning into '%s'...\\n\"), dir);\n \t}\n \n-\tif (option_recursive) {\n+\tif (option_recurse_submodules.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\n+\t\t/* remove duplicates */\n+\t\tstring_list_sort(&option_recurse_submodules);\n+\t\tstring_list_remove_duplicates(&option_recurse_submodules, 0);\n+\n+\t\t/*\n+\t\t * NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t\t * set in the per-worktree config.\n+\t\t */\n+\t\tfor_each_string_list_item(item, &option_recurse_submodules) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n+\t\t\t\t    item->string);\n+\t\t\tstring_list_append(&option_config,\n+\t\t\t\t\t   strbuf_detach(&sb, NULL));\n+\t\t}\n+\n \t\tif (option_required_reference.nr &&\n \t\t    option_optional_reference.nr)\n \t\t\tdie(_(\"clone --recursive is not compatible with \"\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex fbbe932d1..3af1c00ff 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1188,4 +1188,72 @@ test_expect_success 'submodule update and setting submodule.<name>.active' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'clone --recurse-submodules with a pathspec works' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expected <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t-sub2\n+\t-sub3\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\"sub0\" multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'clone with multiple --recurse-submodules options' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat >expect <<-\\EOF &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n+\t\t  multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tcat <<-\\EOF >expect &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\tEOF\n+\n+\tcat <<-\\EOF >expect2 &&\n+\t-sub0\n+\t sub1 (test2)\n+\t-sub2\n+\t sub3 (test2)\n+\t-sub4\n+\t sub5 (test2)\n+\tEOF\n+\n+\tgit clone --recurse-submodules=\".\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub0\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub2\" \\\n+\t\t  --recurse-submodules=\":(exclude)sub4\" \\\n+\t\t  multisuper multisuper_clone &&\n+\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect actual &&\n+\n+\tgit -C multisuper submodule add ../sub1 sub4 &&\n+\tgit -C multisuper submodule add ../sub1 sub5 &&\n+\tgit -C multisuper commit -m \"add more submodules\" &&\n+\t# obtain the new superproject\n+\tgit -C multisuper_clone pull &&\n+\tgit -C multisuper_clone submodule update --init &&\n+\tgit -C multisuper_clone submodule status |cut -c1,43- >actual &&\n+\ttest_cmp expect2 actual\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314430","messageId":"20170317223805.95271-2-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 01/10] submodule--helper: add is-active subcommand","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:37:56Z","receivedAt":"2017-03-18T00:24:22Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"The definition of which submodules are of interest by the user\nis tied to the configuration submodule.<name>.url; when it is\nset to a non-empty string, it is of interest.  We'd want to be\nable to later change this definition, but there are many places\nthat explicitly check this condition in the scripted Porcelain.\n\nIntroduce the \"is-active\" subcommand to \"submodule--helper\", so\nthat the exact definition of what submodule is of interest can\nbe centrally defined (and changed in later steps).  In a few\npatches that follow, this helper is used to replace the explicit\nchecks of the configuration variable in scripts.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n builtin/submodule--helper.c    | 11 +++++++++++\n t/t7413-submodule-is-active.sh | 31 +++++++++++++++++++++++++++++++\n 2 files changed, 42 insertions(+)\n create mode 100755 t/t7413-submodule-is-active.sh\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 15a5430c0..5fe7e23b1 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1127,6 +1127,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int is_active(int argc, const char **argv, const char *prefix)\n+{\n+\tif (argc != 2)\n+\t\tdie(\"submodule--helper is-active takes exactly 1 arguments\");\n+\n+\tgitmodules_config();\n+\n+\treturn !is_submodule_initialized(argv[1]);\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -1146,6 +1156,7 @@ static struct cmd_struct commands[] = {\n \t{\"init\", module_init, SUPPORT_SUPER_PREFIX},\n \t{\"remote-branch\", resolve_remote_submodule_branch, 0},\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n+\t{\"is-active\", is_active, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nnew file mode 100755\nindex 000000000..f18e0c925\n--- /dev/null\n+++ b/t/t7413-submodule-is-active.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+\n+test_description='Test submodule--helper is-active\n+\n+This test verifies that `git submodue--helper is-active` correclty identifies\n+submodules which are \"active\" and interesting to the user.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tgit init sub &&\n+\ttest_commit -C sub initial &&\n+\tgit init super &&\n+\ttest_commit -C super initial &&\n+\tgit -C super submodule add ../sub sub1 &&\n+\tgit -C super submodule add ../sub sub2 &&\n+\tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n+'\n+\n+test_expect_success 'is-active works with urls' '\n+\tgit -C super submodule--helper is-active sub1 &&\n+\tgit -C super submodule--helper is-active sub2 &&\n+\n+\tgit -C super config --unset submodule.sub1.URL &&\n+\ttest_must_fail git -C super submodule--helper is-active sub1 &&\n+\tgit -C super config submodule.sub1.URL ../sub &&\n+\tgit -C super submodule--helper is-active sub1\n+'\n+\n+test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314431","messageId":"20170317223805.95271-8-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 07/10] submodule init: initialize active submodules","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:02Z","receivedAt":"2017-03-18T00:32:37Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Teach `submodule init` to initialize submodules which have been\nconfigured to be active by setting 'submodule.active' with a pathspec.\n\nNow if no path arguments are given and 'submodule.active' is configured,\n`init` will initialize all submodules which have been configured to be\nactive.  If no path arguments are given and 'submodule.active' is not\nconfigured, then `init` will retain the old behavior of initializing all\nsubmodules.\n\nThis allows users to record more complex patterns as it saves retyping\nthem whenever you invoke update.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n Documentation/git-submodule.txt |  4 ++-\n builtin/submodule--helper.c     | 30 ++++++++++++++++++++++\n t/t7400-submodule-basic.sh      | 57 +++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 90 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex e05d0cdde..74bc6200d 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -129,7 +129,9 @@ init [--] [<path>...]::\n \trepository will be assumed to be upstream.\n +\n Optional <path> arguments limit which submodules will be initialized.\n-If no path is specified, all submodules are initialized.\n+If no path is specified and submodule.active has been configured, submodules\n+configured to be active will be initialized, otherwise all submodules are\n+initialized.\n +\n When present, it will also copy the value of `submodule.$name.update`.\n This command does not alter existing information in .git/config.\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f38e332c5..65208faa7 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -270,6 +270,29 @@ static int module_list_compute(int argc, const char **argv,\n \treturn result;\n }\n \n+static void module_list_active(struct module_list *list)\n+{\n+\tint i;\n+\tstruct module_list active_modules = MODULE_LIST_INIT;\n+\n+\tgitmodules_config();\n+\n+\tfor (i = 0; i < list->nr; i++) {\n+\t\tconst struct cache_entry *ce = list->entries[i];\n+\n+\t\tif (!is_submodule_initialized(ce->name))\n+\t\t\tcontinue;\n+\n+\t\tALLOC_GROW(active_modules.entries,\n+\t\t\t   active_modules.nr + 1,\n+\t\t\t   active_modules.alloc);\n+\t\tactive_modules.entries[active_modules.nr++] = ce;\n+\t}\n+\n+\tfree(list->entries);\n+\t*list = active_modules;\n+}\n+\n static int module_list(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -420,6 +443,13 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n \t\treturn 1;\n \n+\t/*\n+\t * If there are no path args and submodule.active is set then,\n+\t * by default, only initialize 'active' modules.\n+\t */\n+\tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n+\t\tmodule_list_active(&list);\n+\n \tfor (i = 0; i < list.nr; i++)\n \t\tinit_submodule(list.entries[i]->name, prefix, quiet);\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex c09ce0d4c..fbbe932d1 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1130,5 +1130,62 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'setup superproject with submodules' '\n+\tgit init sub1 &&\n+\ttest_commit -C sub1 test &&\n+\ttest_commit -C sub1 test2 &&\n+\tgit init multisuper &&\n+\tgit -C multisuper submodule add ../sub1 sub0 &&\n+\tgit -C multisuper submodule add ../sub1 sub1 &&\n+\tgit -C multisuper submodule add ../sub1 sub2 &&\n+\tgit -C multisuper submodule add ../sub1 sub3 &&\n+\tgit -C multisuper commit -m \"add some submodules\"\n+'\n+\n+cat >expect <<-EOF\n+-sub0\n+ sub1 (test2)\n+ sub2 (test2)\n+ sub3 (test2)\n+EOF\n+\n+test_expect_success 'submodule update --init with a specification' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone submodule update --init . \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update --init with submodule.active set' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config submodule.active \".\" &&\n+\tgit -C multisuper_clone config --add submodule.active \":(exclude)sub0\" &&\n+\tgit -C multisuper_clone submodule update --init &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'submodule update and setting submodule.<name>.active' '\n+\ttest_when_finished \"rm -rf multisuper_clone\" &&\n+\tpwd=$(pwd) &&\n+\tgit clone file://\"$pwd\"/multisuper multisuper_clone &&\n+\tgit -C multisuper_clone config --bool submodule.sub0.active \"true\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub1.active \"false\" &&\n+\tgit -C multisuper_clone config --bool submodule.sub2.active \"true\" &&\n+\n+\tcat >expect <<-\\EOF &&\n+\t sub0 (test2)\n+\t-sub1\n+\t sub2 (test2)\n+\t-sub3\n+\tEOF\n+\tgit -C multisuper_clone submodule update &&\n+\tgit -C multisuper_clone submodule status |cut -c 1,43- >actual &&\n+\ttest_cmp expect actual\n+'\n \n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314432","messageId":"20170317223805.95271-5-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 04/10] submodule sync: use submodule--helper is-active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:37:59Z","receivedAt":"2017-03-18T00:36:59Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Signed-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 577136148..db94dea3b 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -1089,14 +1089,14 @@ cmd_sync()\n \twhile read mode sha1 stage sm_path\n \tdo\n \t\tdie_if_unmatched \"$mode\" \"$sha1\"\n-\t\tname=$(git submodule--helper name \"$sm_path\")\n \n \t\t# skip inactive submodules\n-\t\tif ! git config \"submodule.$name.url\" >/dev/null 2>/dev/null\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n \t\tthen\n \t\t\tcontinue\n \t\tfi\n \n+\t\tname=$(git submodule--helper name \"$sm_path\")\n \t\turl=$(git config -f .gitmodules --get submodule.\"$name\".url)\n \n \t\t# Possibly a url relative to parent\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314434","messageId":"20170317223805.95271-1-bmwill@google.com","threadId":"45207","inReplyTo":"20170316222952.53801-1-bmwill@google.com","subject":"[PATCH v5 00/10] decoupling url and submodule interest","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:37:55Z","receivedAt":"2017-03-18T00:41:59Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"Changes in v5:\n  * Add \"NEEDSWORK\" comments to indicate where attention is needed once\n    per-worktree config is a reality\n  * --no-recurse now works by clearing the string list of paths.\n  * module_list_active() now does post-processing instead of duplicating code.\n\nBrandon Williams (10):\n  submodule--helper: add is-active subcommand\n  submodule status: use submodule--helper is-active\n  submodule sync: skip work for inactive submodules\n  submodule sync: use submodule--helper is-active\n  submodule--helper clone: check for configured submodules using helper\n  submodule: decouple url and submodule interest\n  submodule init: initialize active submodules\n  clone: teach --recurse-submodules to optionally take a pathspec\n  submodule--helper init: set submodule.<name>.active\n  submodule add: respect submodule.active and submodule.<name>.active\n\n Documentation/config.txt        |  15 ++++-\n Documentation/git-clone.txt     |  14 +++--\n Documentation/git-submodule.txt |   4 +-\n builtin/clone.c                 |  50 ++++++++++++---\n builtin/submodule--helper.c     |  68 ++++++++++++++++----\n git-submodule.sh                |  55 ++++++++++------\n submodule.c                     |  50 ++++++++++++---\n t/t7400-submodule-basic.sh      | 136 ++++++++++++++++++++++++++++++++++++++++\n t/t7413-submodule-is-active.sh  | 107 +++++++++++++++++++++++++++++++\n 9 files changed, 445 insertions(+), 54 deletions(-)\n create mode 100755 t/t7413-submodule-is-active.sh\n\n---interdiff with 'origin/bw/submodule-is-active'\n\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 3dc8faac5..a7be61d6b 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -62,9 +62,8 @@ static int recurse_submodules_cb(const struct option *opt,\n \t\t\t\t const char *arg, int unset)\n {\n \tif (unset)\n-\t\treturn -1;\n-\n-\tif (arg)\n+\t\tstring_list_clear((struct string_list *)opt->value, 0);\n+\telse if (arg)\n \t\tstring_list_append((struct string_list *)opt->value, arg);\n \telse\n \t\tstring_list_append((struct string_list *)opt->value,\n@@ -984,6 +983,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\tstring_list_sort(&option_recurse_submodules);\n \t\tstring_list_remove_duplicates(&option_recurse_submodules, 0);\n\n+\t\t/*\n+\t\t * NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t\t * set in the per-worktree config.\n+\t\t */\n \t\tfor_each_string_list_item(item, &option_recurse_submodules) {\n \t\t\tstrbuf_addf(&sb, \"submodule.active=%s\",\n \t\t\t\t    item->string);\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex a574596cb..7700d8948 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -273,29 +273,24 @@ static int module_list_compute(int argc, const char **argv,\n static void module_list_active(struct module_list *list)\n {\n \tint i;\n-\n-\tif (read_cache() < 0)\n-\t\tdie(_(\"index file corrupt\"));\n+\tstruct module_list active_modules = MODULE_LIST_INIT;\n\n \tgitmodules_config();\n\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tconst struct cache_entry *ce = active_cache[i];\n+\tfor (i = 0; i < list->nr; i++) {\n+\t\tconst struct cache_entry *ce = list->entries[i];\n\n-\t\tif (!S_ISGITLINK(ce->ce_mode) ||\n-\t\t    !is_submodule_initialized(ce->name))\n+\t\tif (!is_submodule_initialized(ce->name))\n \t\t\tcontinue;\n\n-\t\tALLOC_GROW(list->entries, list->nr + 1, list->alloc);\n-\t\tlist->entries[list->nr++] = ce;\n-\t\twhile (i + 1 < active_nr &&\n-\t\t       !strcmp(ce->name, active_cache[i + 1]->name))\n-\t\t\t/*\n-\t\t\t * Skip entries with the same name in different stages\n-\t\t\t * to make sure an entry is returned only once.\n-\t\t\t */\n-\t\t\ti++;\n+\t\tALLOC_GROW(active_modules.entries,\n+\t\t\t   active_modules.nr + 1,\n+\t\t\t   active_modules.alloc);\n+\t\tactive_modules.entries[active_modules.nr++] = ce;\n \t}\n+\n+\tfree(list->entries);\n+\t*list = active_modules;\n }\n\n static int module_list(int argc, const char **argv, const char *prefix)\n@@ -361,7 +356,12 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\tdie(_(\"No url found for submodule path '%s' in .gitmodules\"),\n \t\t\tdisplaypath);\n\n-\t/* Set active flag for the submodule being initialized */\n+\t/*\n+\t * NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t * set in the per-worktree config.\n+\t *\n+\t * Set active flag for the submodule being initialized\n+\t */\n \tif (!is_submodule_initialized(path)) {\n \t\tstrbuf_reset(&sb);\n \t\tstrbuf_addf(&sb, \"submodule.%s.active\", sub->name);\n@@ -452,14 +452,15 @@ static int module_init(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, module_init_options,\n \t\t\t     git_submodule_helper_usage, 0);\n\n+\tif (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n+\t\treturn 1;\n+\n \t/*\n \t * If there are no path args and submodule.active is set then,\n \t * by default, only initialize 'active' modules.\n \t */\n \tif (!argc && git_config_get_value_multi(\"submodule.active\"))\n \t\tmodule_list_active(&list);\n-\telse if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)\n-\t\treturn 1;\n\n \tfor (i = 0; i < list.nr; i++)\n \t\tinit_submodule(list.entries[i]->name, prefix, quiet);\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 6eca93416..6ec35e5fc 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -279,6 +279,8 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n\n+\t# NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t# set in the per-worktree config.\n \tif git config --get submodule.active >/dev/null\n \tthen\n \t\t# If the submodule being adding isn't already covered by the\n\n--\n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314435","messageId":"20170317223805.95271-11-bmwill@google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"[PATCH v5 10/10] submodule add: respect submodule.active and submodule.<name>.active","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-03-17T22:38:05Z","receivedAt":"2017-03-18T01:21:45Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"In addition to adding submodule.<name>.url to the config, set\nsubmodule.<name>.active to true unless submodule.active is configured\nand the submodule's path matches the configured pathspec.\n\nSigned-off-by: Brandon Williams <bmwill@google.com>\n---\n git-submodule.sh               | 14 ++++++++++++++\n t/t7413-submodule-is-active.sh | 21 +++++++++++++++++++++\n 2 files changed, 35 insertions(+)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex db94dea3b..6ec35e5fc 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -278,6 +278,20 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n+\n+\t# NEEDSWORK: In a multi-working-tree world, this needs to be\n+\t# set in the per-worktree config.\n+\tif git config --get submodule.active >/dev/null\n+\tthen\n+\t\t# If the submodule being adding isn't already covered by the\n+\t\t# current configured pathspec, set the submodule's active flag\n+\t\tif ! git submodule--helper is-active \"$sm_path\"\n+\t\tthen\n+\t\t\tgit config submodule.\"$sm_name\".active \"true\"\n+\t\tfi\n+\telse\n+\t\tgit config submodule.\"$sm_name\".active \"true\"\n+\tfi\n }\n \n #\ndiff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh\nindex ea1644b58..9c785b07e 100755\n--- a/t/t7413-submodule-is-active.sh\n+++ b/t/t7413-submodule-is-active.sh\n@@ -15,6 +15,12 @@ test_expect_success 'setup' '\n \ttest_commit -C super initial &&\n \tgit -C super submodule add ../sub sub1 &&\n \tgit -C super submodule add ../sub sub2 &&\n+\n+\t# Remove submodule.<name>.active entries in order to test in an\n+\t# environment where only URLs are present in the conifg\n+\tgit -C super config --unset submodule.sub1.active &&\n+\tgit -C super config --unset submodule.sub2.active &&\n+\n \tgit -C super commit -a -m \"add 2 submodules at sub{1,2}\"\n '\n \n@@ -83,4 +89,19 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active\n \tgit -C super submodule--helper is-active sub2\n '\n \n+test_expect_success 'is-active, submodule.active and submodule add' '\n+\ttest_when_finished \"rm -rf super2\" &&\n+\tgit init super2 &&\n+\ttest_commit -C super2 initial &&\n+\tgit -C super2 config --add submodule.active \"sub*\" &&\n+\n+\t# submodule add should only add submodule.<name>.active\n+\t# to the config if not matched by the pathspec\n+\tgit -C super2 submodule add ../sub sub1 &&\n+\ttest_must_fail git -C super2 config --get submodule.sub1.active &&\n+\n+\tgit -C super2 submodule add ../sub mod &&\n+\tgit -C super2 config --get submodule.mod.active\n+'\n+\n test_done\n-- \n2.12.0.367.g23dc2f6d3c-goog\n\n"},{"id":"314506","messageId":"xmqqwpbm4j0c.fsf@gitster.mtv.corp.google.com","threadId":"45207","inReplyTo":"20170317223805.95271-1-bmwill@google.com","subject":"Re: [PATCH v5 00/10] decoupling url and submodule interest","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-03-18T17:00:51Z","receivedAt":"2017-03-18T17:01:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Brandon Williams <bmwill@google.com> writes:\n\n> Changes in v5:\n>   * Add \"NEEDSWORK\" comments to indicate where attention is needed once\n>     per-worktree config is a reality\n>   * --no-recurse now works by clearing the string list of paths.\n>   * module_list_active() now does post-processing instead of duplicating code.\n>\n> Brandon Williams (10):\n>   submodule--helper: add is-active subcommand\n>   submodule status: use submodule--helper is-active\n>   submodule sync: skip work for inactive submodules\n>   submodule sync: use submodule--helper is-active\n>   submodule--helper clone: check for configured submodules using helper\n>   submodule: decouple url and submodule interest\n>   submodule init: initialize active submodules\n>   clone: teach --recurse-submodules to optionally take a pathspec\n>   submodule--helper init: set submodule.<name>.active\n>   submodule add: respect submodule.active and submodule.<name>.active\n\nReplaced what has been queued with this and read it over\nagain. Looked sensible.\n\nThanks.\n"}]}