{"thread":{"id":"41775","subject":"[RFC_PATCHv4 0/7] Git submodule labels","startedAt":"2016-03-22T02:06:05Z","lastAt":"2016-03-24T21:14:12Z","messageCount":22,"participants":["Stefan Beller","Sebastian Schuberth","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"281403","messageId":"1458612372-10966-1-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":null,"subject":"[RFC_PATCHv4 0/7] Git submodule labels","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:05Z","receivedAt":"2016-03-22T02:06:05Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"This series introduces labels which you can attach to submodules like so:\n\n    $ cat .gitmodules\n    [submodule \"gcc\"]\n        path = gcc\n        url = git://...\n        label = default\n        label = devel\n    [submodule \"linux\"]\n        path = linux\n        url = git://...\n        label = default\n        \n    $ git submodule add --name emacs --label \"editor\" --label default git://...\n    \n    # If upstream has submodules properly labeled, you can make use of them:\n    $ git config --add submodule.actionOnLabel \"*default\"\n    $ git config --add submodule.actionOnLabel \":name\"\n    $ git config --add submodule.actionOnLabel \"./by/path\"\n    # The prefix * denotes a label as found in .gitmodules\n    # : goes before names \n    # path are prefixed ./ currently\n    # both path and names need work\n\n    # no --init necessary, partially initializes submodules (only those which\n    # were specified by label, name or path)\n    $ git submodule update\n    \n    # time passes, upstream may have added new submodules and we get them without\n    # extra commands!\n    $ git submodule update\n\n    # The above configuration can be given to git clone directly via:\n    $ git clone --init-submodule=*labelA ...\n    \n    # diff/status only apply to label-selected submodules\n    git status\n\nNew since last round:\n* Renamed to submodule.actionOnLabel as it is generic enough to be applicable\n  for lots of commands (submodule update, status, diff, etc)\n* Restructured the code to have a generic \"Given these labels, would I\n  want to operate on this submodule\", which made the implementation for\n  \"submodule update\" easier, as well as the new WIP patch for diff/status.\n\nAny feedback would be welcome!\nThanks,\nStefan\n\nAn earlier version was posted at\nhttp://thread.gmane.org/gmane.comp.version-control.git/284612\n\nThis applies on top of origin/sb/submodule-init or can be found at\nhttps://github.com/stefanbeller/git/tree/submodule-groups-v4\n\nStefan Beller (7):\n  git submodule: teach `add` to label submodules\n  submodule-config: keep labels around\n  submodule-config: add method to check for being labeled\n  submodule init: redirect stdout to stderr\n  submodule update: respect submodule.actionOnLabel\n  clone: allow specification of submodules to be cloned\n  WIP status/diff: respect submodule.actionOnLabel\n\n Documentation/git-clone.txt     |   6 +\n Documentation/git-submodule.txt |   5 +-\n builtin/clone.c                 |  40 +++++-\n builtin/submodule--helper.c     |  25 +++-\n git-submodule.sh                |  14 +-\n submodule-config.c              |  66 ++++++++-\n submodule-config.h              |   5 +\n submodule.c                     |  15 ++\n t/t7400-submodule-basic.sh      | 294 ++++++++++++++++++++++++++++++++++++++++\n 9 files changed, 462 insertions(+), 8 deletions(-)\n\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281407","messageId":"1458612372-10966-2-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 1/7] git submodule: teach `add` to label submodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:06Z","receivedAt":"2016-03-22T02:06:06Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"When adding new submodules, you can specify the\nlabel(s) the submodule belongs to by giving one or more\n--label arguments. This will record each label in the\n.gitmodules file as a value of the key\n\"submodule.$NAME.label\".\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n Documentation/git-submodule.txt |  5 ++++-\n git-submodule.sh                | 14 +++++++++++++-\n t/t7400-submodule-basic.sh      | 32 ++++++++++++++++++++++++++++++++\n 3 files changed, 49 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 13adebf..c0744eb 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -9,7 +9,7 @@ git-submodule - Initialize, update or inspect submodules\n SYNOPSIS\n --------\n [verse]\n-'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]\n+'git submodule' [--quiet] add [-b <branch>] [-f|--force] [-l|--label <label>]\n \t      [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]\n 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]\n 'git submodule' [--quiet] init [--] [<path>...]\n@@ -101,6 +101,9 @@ is the superproject and submodule repositories will be kept\n together in the same relative location, and only the\n superproject's URL needs to be provided: git-submodule will correctly\n locate the submodule using the relative URL in .gitmodules.\n++\n+If at least one label argument was given, all labels are recorded in the\n+.gitmodules file in the label fields.\n \n status::\n \tShow the status of the submodules. This will print the SHA-1 of the\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 97a3097..def1e1c 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -5,7 +5,7 @@\n # Copyright (c) 2007 Lars Hjemli\n \n dashless=$(basename \"$0\" | sed -e 's/-/ /')\n-USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]\n+USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [-l|--label <label>][--] <repository> [<path>]\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] [--] <path>...\n@@ -130,6 +130,7 @@ cmd_add()\n {\n \t# parse $args after \"submodule ... add\".\n \treference_path=\n+\tlabels=\n \twhile test $# -ne 0\n \tdo\n \t\tcase \"$1\" in\n@@ -165,6 +166,13 @@ cmd_add()\n \t\t--depth=*)\n \t\t\tdepth=$1\n \t\t\t;;\n+\t\t-l|--label)\n+\t\t\tlabels=\"${labels} $2\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--label=*)\n+\t\t\tlabels=\"${labels} ${1#--label=}\"\n+\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -292,6 +300,10 @@ Use -f if you really want to add it.\" >&2\n \n \tgit config -f .gitmodules submodule.\"$sm_name\".path \"$sm_path\" &&\n \tgit config -f .gitmodules submodule.\"$sm_name\".url \"$repo\" &&\n+\tfor label in $labels\n+\tdo\n+\t\tgit config --add -f .gitmodules submodule.\"$sm_name\".label \"${label}\"\n+\tdone &&\n \tif test -n \"$branch\"\n \tthen\n \t\tgit config -f .gitmodules submodule.\"$sm_name\".branch \"$branch\"\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 5991e3c..fc948fd 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -986,6 +986,7 @@ test_expect_success 'submodule with UTF-8 name' '\n '\n \n test_expect_success 'submodule add clone shallow submodule' '\n+\ttest_when_finished \"rm -rf super\" &&\n \tmkdir super &&\n \tpwd=$(pwd) &&\n \t(\n@@ -999,5 +1000,36 @@ test_expect_success 'submodule add clone shallow submodule' '\n \t)\n '\n \n+test_expect_success 'submodule add records a label' '\n+\ttest_when_finished \"rm -rf super\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n+\t\tgit config -f .gitmodules submodule.\"submodule\".label >actual &&\n+\t\techo labelA >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+cat >expected <<-EOF\n+labelA\n+labelB\n+EOF\n+\n+test_expect_success 'submodule add records multiple labels' '\n+\ttest_when_finished \"rm -rf super\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label=labelA -l labelB file://\"$pwd\"/example2 submodule &&\n+\t\tgit config --get-all -f .gitmodules submodule.\"submodule\".label >../actual\n+\t) &&\n+\ttest_cmp expected actual\n+'\n \n test_done\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281408","messageId":"1458612372-10966-3-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 2/7] submodule-config: keep labels around","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:07Z","receivedAt":"2016-03-22T02:06:07Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"We need the submodule labels in a later patch.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n submodule-config.c | 18 +++++++++++++++++-\n submodule-config.h |  2 ++\n 2 files changed, 19 insertions(+), 1 deletion(-)\n\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 9fa2269..7b48e59 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -60,6 +60,10 @@ static void free_one_config(struct submodule_entry *entry)\n \tfree((void *) entry->config->path);\n \tfree((void *) entry->config->name);\n \tfree((void *) entry->config->update_strategy.command);\n+\tif (entry->config->labels) {\n+\t\tstring_list_clear(entry->config->labels, 0);\n+\t\tfree(entry->config->labels);\n+\t}\n \tfree(entry->config);\n }\n \n@@ -199,6 +203,7 @@ static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,\n \tsubmodule->update_strategy.command = NULL;\n \tsubmodule->fetch_recurse = RECURSE_SUBMODULES_NONE;\n \tsubmodule->ignore = NULL;\n+\tsubmodule->labels = NULL;\n \n \thashcpy(submodule->gitmodules_sha1, gitmodules_sha1);\n \n@@ -324,7 +329,18 @@ static int parse_config(const char *var, const char *value, void *data)\n \t\telse if (parse_submodule_update_strategy(value,\n \t\t\t &submodule->update_strategy) < 0)\n \t\t\t\tdie(_(\"invalid value for %s\"), var);\n-\t}\n+\t} else if (!strcmp(item.buf, \"label\")) {\n+\t\tif (!value)\n+\t\t\tret = config_error_nonbool(var);\n+\t\telse {\n+\t\t\tif (!submodule->labels) {\n+\t\t\t\tsubmodule->labels =\n+\t\t\t\t\txmalloc(sizeof(*submodule->labels));\n+\t\t\t\tstring_list_init(submodule->labels, 1);\n+\t\t\t}\n+\t\t\tstring_list_insert(submodule->labels, value);\n+\t\t}\n+ \t}\n \n \tstrbuf_release(&name);\n \tstrbuf_release(&item);\ndiff --git a/submodule-config.h b/submodule-config.h\nindex 092ebfc..8d61df3 100644\n--- a/submodule-config.h\n+++ b/submodule-config.h\n@@ -18,6 +18,8 @@ struct submodule {\n \tstruct submodule_update_strategy update_strategy;\n \t/* the sha1 blob id of the responsible .gitmodules file */\n \tunsigned char gitmodules_sha1[20];\n+\t/* sorted, not as on disk */\n+\tstruct string_list *labels;\n };\n \n int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281405","messageId":"1458612372-10966-4-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 3/7] submodule-config: add method to check for being labeled","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:08Z","receivedAt":"2016-03-22T02:06:08Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"In later patches we need to tell if a submodule is labeled by\nthe given labels.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n submodule-config.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\n submodule-config.h |  3 +++\n 2 files changed, 51 insertions(+)\n\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 7b48e59..b10a773 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -493,3 +493,51 @@ void submodule_free(void)\n \tcache_free(&cache);\n \tis_cache_init = 0;\n }\n+\n+int submodule_applicable_by_labels(const struct string_list *list,\n+\t\t\t\t   const struct submodule *sub)\n+{\n+\tint label_apply = 0;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\n+\tif (!list)\n+\t\treturn 1;\n+\n+\tif (sub->labels) {\n+\t\tstruct string_list_item *item;\n+\t\tfor_each_string_list_item(item, sub->labels) {\n+\t\t\tstrbuf_reset(&sb);\n+\t\t\tstrbuf_addf(&sb, \"*%s\", item->string);\n+\t\t\tif (string_list_has_string(list, sb.buf)) {\n+\t\t\t\tlabel_apply = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tif (sub->path) {\n+\t\t/*\n+\t\t * NEEDSWORK: This currently works only for\n+\t\t * exact paths, but we want to enable\n+\t\t * inexact matches such wildcards.\n+\t\t */\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \"./%s\", sub->path);\n+\t\tif (string_list_has_string(list, sb.buf)) {\n+\t\t\tlabel_apply = 1;\n+\t\t}\n+\t}\n+\tif (sub->name) {\n+\t\t/*\n+\t\t * NEEDSWORK: Same as with path. Do we want to\n+\t\t * support wildcards or such?\n+\t\t */\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_addf(&sb, \":%s\", sub->name);\n+\t\tif (string_list_has_string(list, sb.buf)) {\n+\t\t\tlabel_apply = 1;\n+\t\t}\n+\t}\n+\tstrbuf_release(&sb);\n+\n+\treturn label_apply;\n+}\ndiff --git a/submodule-config.h b/submodule-config.h\nindex 8d61df3..d67f666 100644\n--- a/submodule-config.h\n+++ b/submodule-config.h\n@@ -30,4 +30,7 @@ const struct submodule *submodule_from_path(const unsigned char *commit_sha1,\n \t\tconst char *path);\n void submodule_free(void);\n \n+int submodule_applicable_by_labels(const struct string_list *list,\n+\t\t\t\t   const struct submodule *sub);\n+\n #endif /* SUBMODULE_CONFIG_H */\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281404","messageId":"1458612372-10966-5-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:09Z","receivedAt":"2016-03-22T02:06:09Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Reroute the output of stdout to stderr as it is just informative\nmessages, not to be consumed by machines.\n\nWe want to init submodules from the helper for `submodule update`\nin a later patch and the stdout output of said helper is consumed\nby the parts of `submodule update` which are still written in shell.\nSo we have to be careful which messages are on stdout.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n builtin/submodule--helper.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex d942463..a69b1f4 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -268,7 +268,8 @@ static void init_submodule(const char *path, const char *prefix, int quiet)\n \t\t\tdie(_(\"Failed to register url for submodule path '%s'\"),\n \t\t\t    displaypath);\n \t\tif (!quiet)\n-\t\t\tprintf(_(\"Submodule '%s' (%s) registered for path '%s'\\n\"),\n+\t\t\tfprintf(stderr,\n+\t\t\t\t_(\"Submodule '%s' (%s) registered for path '%s'\\n\"),\n \t\t\t\tsub->name, url, displaypath);\n \t}\n \n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281409","messageId":"1458612372-10966-6-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:10Z","receivedAt":"2016-03-22T02:06:10Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"This change introduces the 'submodule.actionOnLabel' variable\nin a repository configuration. Generally speaking 'submodule.actionOnLabel'\nrestricts the action of a command when no submodules are selected via the\ncommand line explicitely to those submodules, which are selected by\n'submodule.actionOnLabel'. It can occur multiple times and can specify\nthe path, the name or one of the labels of a submodule to select that\nsubmodule.\n\nThe introduction of 'submodule.actionOnLabel' starts with\n'git submodule update' in this patch and other commands will follow\nin later patches.\n\n'submodule.actionOnLabel' implies '--init' in 'git submodule update'.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n\nTODO: generic documentation for submodule.actionOnLabel\nTODO: documentation for submodule update\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n builtin/submodule--helper.c |  22 ++++++++-\n t/t7400-submodule-basic.sh  | 115 ++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 136 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex a69b1f4..93760ec 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -573,6 +573,8 @@ struct submodule_update_clone {\n \tint current;\n \tstruct module_list list;\n \tunsigned warn_if_uninitialized : 1;\n+\t/* patterns to initialize */\n+\tstruct string_list *initialize;\n \n \t/* update parameter passed via commandline */\n \tstruct submodule_update_strategy update;\n@@ -590,7 +592,7 @@ struct submodule_update_clone {\n \t/* If we want to stop as fast as possible and return an error */\n \tunsigned quickstop : 1;\n };\n-#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \\\n+#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, NULL, \\\n \tSUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \\\n \tSTRING_LIST_INIT_DUP, 0}\n \n@@ -644,6 +646,15 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n \tstrbuf_reset(&sb);\n \tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n \tgit_config_get_string(sb.buf, &url);\n+\tif (suc->initialize) {\n+\t\tif (!url) {\n+\t\t\tinit_submodule(sub->path, suc->prefix, suc->quiet);\n+\t\t\turl = xstrdup(sub->url);\n+\t\t}\n+\t\tif (!submodule_applicable_by_labels(suc->initialize, sub)\n+\t\t    && !suc->warn_if_uninitialized)\n+\t\t\tgoto cleanup;\n+\t}\n \tif (!url) {\n \t\t/*\n \t\t * Only mention uninitialized submodules when their\n@@ -745,6 +756,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n \tconst char *update = NULL;\n \tint max_jobs = -1;\n \tstruct string_list_item *item;\n+\tconst struct string_list *list;\n \tstruct pathspec pathspec;\n \tstruct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;\n \n@@ -793,6 +805,14 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n \tgitmodules_config();\n \tgit_config(submodule_config, NULL);\n \n+\tlist = git_config_get_value_multi(\"submodule.actionOnLabel\");\n+\tif (list) {\n+\t\tsuc.initialize = xmalloc(sizeof(*suc.initialize));\n+\t\tstring_list_init(suc.initialize, 1);\n+\t\tfor_each_string_list_item(item, list)\n+\t\t\tstring_list_insert(suc.initialize, item->string);\n+\t}\n+\n \tif (max_jobs < 0)\n \t\tmax_jobs = parallel_submodules();\n \ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex fc948fd..dc45551 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1032,4 +1032,119 @@ test_expect_success 'submodule add records multiple labels' '\n \ttest_cmp expected actual\n '\n \n+cat <<EOF > expected\n+submodule\n+-submodule2\n+EOF\n+\n+test_expect_success 'update initializes all modules when action-on-label configured' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule2 &&\n+\t\tgit commit -a -m \"add two modules, one is labled\"\n+\t) &&\n+\tgit clone super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit config submodule.actionOnLabel \\*labelA &&\n+\t\tgit submodule update &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected\n+'\n+\n+test_expect_success 'submodule update applies to action-on-label selection' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\toldSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule2 &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule3 &&\n+\t\tgit commit -a -m \"add two modules, both are labled\"\n+\t) &&\n+\tgit clone super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit config submodule.actionOnLabel \\*labelA &&\n+\t\tgit submodule update\n+\t) &&\n+\t(\n+\t\tcd example2 &&\n+\t\ttouch anotherfile &&\n+\t\tgit add anotherfile &&\n+\t\tgit commit -m \"advance example2\" &&\n+\t\tgit checkout -b branchName\n+\t) &&\n+\tnewSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule4 &&\n+\t\tgit commit -a -m \"add another labeled module\" &&\n+\t\tgit config -f .gitmodules submodule.submodule2.label labelB &&\n+\t\tgit config -f .gitmodules --unset submodule.submodule3.label &&\n+\t\tgit commit -a -m \"unlabel 2 and 3 upstream\" &&\n+\t\tgit submodule foreach git pull origin branchName &&\n+\t\tgit commit -a -m \"update all submodules\" &&\n+\t\tgit submodule status |cut -c1-52 >../actual\n+\t) &&\n+\tcat <<EOF >expected &&\n+ $newSubmoduleHead submodule1\n+ $newSubmoduleHead submodule2\n+ $newSubmoduleHead submodule3\n+ $newSubmoduleHead submodule4\n+EOF\n+\ttest_cmp actual expected &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit pull &&\n+\t\tgit submodule update &&\n+\t\tgit submodule status |cut -c1-52 >../actual\n+\t) &&\n+\tcat <<EOF >expected &&\n+ $newSubmoduleHead submodule1\n++$oldSubmoduleHead submodule2\n++$oldSubmoduleHead submodule3\n+ $newSubmoduleHead submodule4\n+EOF\n+\ttest_cmp actual expected\n+'\n+\n+cat <<EOF > expected\n+submodule1\n+submodule2\n+-submodule3\n+EOF\n+\n+test_expect_success 'Change labels in .git/config' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule2 &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule3 &&\n+\t\tgit commit -a -m \"add two modules, one is labled\"\n+\t) &&\n+\tgit clone super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit config submodule.actionOnLabel \\*labelA &&\n+\t\tgit config submodule.submodule2.label labelA\n+\t\tgit submodule update &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected\n+'\n+\n test_done\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281406","messageId":"1458612372-10966-7-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 6/7] clone: allow specification of submodules to be cloned","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:11Z","receivedAt":"2016-03-22T02:06:11Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"This is in line with clone being the contraction of\n    mkdir <path> && cd <path>\n    git init\n    git config\n    git fetch\n    git submodule update\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n Documentation/git-clone.txt |   6 ++\n builtin/clone.c             |  40 ++++++++++++-\n t/t7400-submodule-basic.sh  | 134 ++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 177 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 6db7b6d..4baf444 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -214,6 +214,12 @@ objects from the source repository into a pack in the cloned repository.\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+--init-submodule::\n+\tAfter the repository is cloned, specified submodules are cloned.\n+\tIt is possible to give multiple specifications by repeating the\n+\targument. This option will be recorded in the repository config\n+\tas `submodule.autoInitialize`.\n+\n --separate-git-dir=<git dir>::\n \tInstead of placing the cloned repository where it is supposed\n \tto be, place the cloned repository at the specified directory,\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex b004fb4..e2af9b8 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -51,6 +51,22 @@ static struct string_list option_config;\n static struct string_list option_reference;\n static int option_dissociate;\n static int max_jobs = -1;\n+static struct string_list init_submodules;\n+\n+static int init_submodules_cb(const struct option *opt, const char *arg, int unset)\n+{\n+\tstruct string_list_item *item;\n+\tstruct string_list sl = STRING_LIST_INIT_DUP;\n+\n+\tif (unset)\n+\t\treturn -1;\n+\n+\tstring_list_split(&sl, arg, ',', -1);\n+\tfor_each_string_list_item(item, &sl)\n+\t\tstring_list_append((struct string_list *)opt->value, item->string);\n+\n+\treturn 0;\n+}\n \n static struct option builtin_clone_options[] = {\n \tOPT__VERBOSITY(&option_verbosity),\n@@ -95,6 +111,8 @@ static struct option builtin_clone_options[] = {\n \t\t   N_(\"separate git dir from working tree\")),\n \tOPT_STRING_LIST('c', \"config\", &option_config, N_(\"key=value\"),\n \t\t\tN_(\"set config inside the new repository\")),\n+\tOPT_CALLBACK(0, \"init-submodule\", &init_submodules, N_(\"string\"),\n+\t\t\tN_(\"clone specific submodules\"), init_submodules_cb),\n \tOPT_END()\n };\n \n@@ -723,17 +741,24 @@ static int checkout(void)\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)\n+\t\tgoto out;\n+\n+\tif (option_recursive || init_submodules.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 (option_recursive) {\n+\t\t\targv_array_pushf(&args, \"--init\");\n+\t\t\targv_array_pushf(&args, \"--recursive\");\n+\t\t}\n \t\tif (max_jobs != -1)\n \t\t\targv_array_pushf(&args, \"--jobs=%d\", max_jobs);\n \n \t\terr = run_command_v_opt(args.argv, RUN_GIT_CMD);\n \t\targv_array_clear(&args);\n \t}\n-\n+out:\n \treturn err;\n }\n \n@@ -868,6 +893,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\toption_no_checkout = 1;\n \t}\n \n+\tif (init_submodules.nr > 0) {\n+\t\tstruct string_list_item *item;\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tfor_each_string_list_item(item, &init_submodules) {\n+\t\t\tstrbuf_addf(&sb, \"submodule.actionOnLabel=%s\", item->string);\n+\t\t\tstring_list_append(&option_config, strbuf_detach(&sb, 0));\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 dc45551..58da5c4 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1147,4 +1147,138 @@ test_expect_success 'Change labels in .git/config' '\n \ttest_cmp actual expected\n '\n \n+cat <<EOF > expected\n+submodule\n+submodule1\n+submodule2\n+-submodule3\n+EOF\n+\n+test_expect_success 'submodule update auto-initializes submodules' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n+\t\tgit submodule add --name specialSnowflake file://\"$pwd\"/example2 submodule1 &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule2 &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule3 &&\n+\t\tgit commit -a -m \"create repository with 4 submodules, one is labeled\"\n+\t) &&\n+\tgit clone super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit config submodule.actionOnLabel \\*labelA &&\n+\t\tgit config --add submodule.actionOnLabel :specialSnowflake &&\n+\t\tgit config --add submodule.actionOnLabel ./submodule2 &&\n+\t\tgit submodule update &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected\n+'\n+\n+cat <<EOF > expected\n+submodule\n+-submodule1\n+EOF\n+\n+test_expect_success 'clone --init-submodule works' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule1 &&\n+\t\tgit commit -a -m \"create repository with 2 submodules, one is in a group\"\n+\t) &&\n+\tgit clone --init-submodule \\*labelA super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected\n+'\n+\n+cat <<EOF > expected\n+-submodule1\n+submoduleA\n+-submoduleB\n+submoduleC\n+-submoduleD\n+submoduleE\n+EOF\n+\n+test_expect_success 'clone with multiple --init-submodule options' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label groupA file://\"$pwd\"/example2 submoduleA &&\n+\t\tgit submodule add --label groupB file://\"$pwd\"/example2 submoduleB &&\n+\t\tgit submodule add --label groupC file://\"$pwd\"/example2 submoduleC &&\n+\t\tgit submodule add --label groupD --name submoduleE file://\"$pwd\"/example2 submoduleD &&\n+\t\tgit submodule add --label groupE --name submoduleD file://\"$pwd\"/example2 submoduleE &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submodule1 &&\n+\t\tgit commit -a -m \"create repository with submodules groups\"\n+\t) &&\n+\tgit clone --init-submodule=\\*groupA --init-submodule ./submoduleC --init-submodule :submoduleD super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected\n+'\n+\n+cat <<EOF > expected1\n+submoduleA\n+-submoduleB\n+EOF\n+\n+cat <<EOF > expected2\n+submoduleA\n+-submoduleB\n+submoduleC\n+EOF\n+\n+test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' '\n+\ttest_when_finished \"rm -rf super super_clone\" &&\n+\tmkdir super &&\n+\tpwd=$(pwd) &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label LA file://\"$pwd\"/example2 submoduleA &&\n+\t\tgit submodule add file://\"$pwd\"/example2 submoduleB &&\n+\t\tgit commit -a -m \"create repository with submodules groups\"\n+\t) &&\n+\tgit clone --init-submodule=\\*LA super super_clone &&\n+\t(\n+\t\tcd super_clone &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected1 &&\n+\t(\n+\t\tcd super &&\n+\t\tgit init &&\n+\t\tgit submodule add --label LA file://\"$pwd\"/example2 submoduleC &&\n+\t\tgit commit -a -m \"add another labled submodule\"\n+\t) &&\n+\t(\n+\t\tcd super_clone &&\n+\t\t# obtain the new superproject\n+\t\tgit pull &&\n+\t\t# submoduleC should just appear as it has the label LA\n+\t\t# which was configured to autoInitialize in git clone\n+\t\tgit submodule update &&\n+\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n+\t) &&\n+\ttest_cmp actual expected2\n+'\n+\n test_done\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281410","messageId":"1458612372-10966-8-git-send-email-sbeller@google.com","threadId":"41775","inReplyTo":"1458612372-10966-1-git-send-email-sbeller@google.com","subject":"[RFC_PATCHv4 7/7] WIP status/diff: respect submodule.actionOnLabel","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T02:06:12Z","receivedAt":"2016-03-22T02:06:12Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"When 'submodule.actionOnLabel' is set, submodules which are selected by\na label will be inspected in status and diff. If a submodule is not\nselected, it is ignored.\n\nSigned-off-by: Stefan Beller <sbeller@google.com>\n---\n submodule.c                | 15 +++++++++++++++\n t/t7400-submodule-basic.sh | 13 +++++++++++++\n 2 files changed, 28 insertions(+)\n\ndiff --git a/submodule.c b/submodule.c\nindex 458189c..86c0a49 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -20,6 +20,8 @@ static struct string_list changed_submodule_paths;\n static int initialized_fetch_ref_tips;\n static struct sha1_array ref_tips_before_fetch;\n static struct sha1_array ref_tips_after_fetch;\n+static struct string_list action_labels = STRING_LIST_INIT_DUP;\n+static int use_action_labels;\n \n /*\n  * The following flag is set if the .gitmodules file is unmerged. We then\n@@ -161,10 +163,20 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,\n {\n \tconst struct submodule *submodule = submodule_from_path(null_sha1, path);\n \tif (submodule) {\n+\t\tchar *ignoreMode;\n \t\tif (submodule->ignore)\n \t\t\thandle_ignore_submodules_arg(diffopt, submodule->ignore);\n \t\telse if (gitmodules_is_unmerged)\n \t\t\tDIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);\n+\n+\t\tif (!use_action_labels)\n+\t\t\treturn;\n+\n+\t\tif (submodule_applicable_by_labels(&action_labels, submodule))\n+\t\t\tignoreMode = \"none\";\n+\t\telse\n+\t\t\tignoreMode = \"all\";\n+\t\thandle_ignore_submodules_arg(diffopt, ignoreMode);\n \t}\n }\n \n@@ -175,6 +187,9 @@ int submodule_config(const char *var, const char *value, void *cb)\n \t\tif (parallel_jobs < 0)\n \t\t\tdie(_(\"negative values not allowed for submodule.fetchJobs\"));\n \t\treturn 0;\n+\t} else if (!strcmp(var, \"submodule.actiononlabel\")) {\n+\t\tuse_action_labels = 1;\n+\t\tstring_list_append(&action_labels, value);\n \t} else if (starts_with(var, \"submodule.\"))\n \t\treturn parse_submodule_config_option(var, value);\n \telse if (!strcmp(var, \"fetch.recursesubmodules\")) {\ndiff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\nindex 58da5c4..52ea3c6 100755\n--- a/t/t7400-submodule-basic.sh\n+++ b/t/t7400-submodule-basic.sh\n@@ -1281,4 +1281,17 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm\n \ttest_cmp actual expected2\n '\n \n+test_expect_success 'status ignores unlabeled submodules' '\n+\t# Add submodules with and without label\n+\t# perform a change on disk\n+\t# observe the change indicated by git status\n+\t# the submodule not in the label system is ignored.\n+\ttrue && true\n+'\n+\n+test_expect_success 'diff applies to action-on-label selection' '\n+\t# similar to status\n+\ttrue && true\n+'\n+\n test_done\n-- \n2.7.0.rc0.45.g6b4c145\n"},{"id":"281415","messageId":"CAHGBnuMs4D0LeMvdcS0yzKoQgmE+UTb+QFfOkSy7T20PbH86UQ@mail.gmail.com","threadId":"41775","inReplyTo":"1458612372-10966-5-git-send-email-sbeller@google.com","subject":"Re: [RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2016-03-22T07:46:15Z","receivedAt":"2016-03-22T07:46:15Z","isPatch":false,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Tue, Mar 22, 2016 at 3:06 AM, Stefan Beller <sbeller@google.com> wrote:\n\n> Reroute the output of stdout to stderr as it is just informative\n> messages, not to be consumed by machines.\n\nJust wondering, what's Git's policy on this? This message is neither\nan error nor a warning, but just purely informational. As such it\nsemantically does not belong to stderr, or? On the other hand I see\nmultiple places in Git's code where printing to stderr is (mis-)used\nfor informational messages, probably to separate output to be consumed\nby humans from output to be consumed by machines, like you do here.\n\n-- \nSebastian Schuberth\n"},{"id":"281436","messageId":"xmqqd1qmjxrl.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"CAHGBnuMs4D0LeMvdcS0yzKoQgmE+UTb+QFfOkSy7T20PbH86UQ@mail.gmail.com","subject":"Re: [RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T16:14:06Z","receivedAt":"2016-03-22T16:14:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sebastian Schuberth <sschuberth@gmail.com> writes:\n\n> Just wondering, what's Git's policy on this? This message is neither\n> an error nor a warning, but just purely informational. As such it\n> semantically does not belong to stderr, or?\n\nSome people believe that a clean execution should not give anything\nto stderr (Tcl is one example, IIRC), but I think the core part of\nGit takes the opposite stance (probably unix tradition?).  Anything\nthat is not the primary output of the program should go to stdout.\n\nWe may not have been very strict in code reviews to enfore it, and\nespecially on the fringes of the system it may be easy to find\nviolators, though.\n"},{"id":"281438","messageId":"CAGZ79kaASKUGs3y9YHUp=QeD=91by4DhJh+tVfj6aNOJSH-3jg@mail.gmail.com","threadId":"41775","inReplyTo":"xmqqd1qmjxrl.fsf@gitster.mtv.corp.google.com","subject":"Re: [RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-22T16:47:15Z","receivedAt":"2016-03-22T16:47:15Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 22, 2016 at 9:14 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Sebastian Schuberth <sschuberth@gmail.com> writes:\n\nMy commit message is bad, and I should feel bad. ;)\nQuoting from 68b939b2f097b6675 (2013-09-18, clone: send diagnostic\nmessages to stderr, by Jeff who writes the best commit messages):\n    Putting messages like \"Cloning into..\" and \"done\" on stdout\n    is un-Unix and uselessly clutters the stdout channel. Send\n    them to stderr.\n    ...\n    This should not regress any scripts that try to parse the\n    current output, as the output is already internationalized\n    and therefore unstable.\n\nQuoting another fbf71645d12d302 (Tue Dec 15 16:04:06 2015,\nsubmodule.c: write \"Fetching submodule <foo>\" to stderr, by Jonathan)\n    The \"Pushing submodule <foo>\" progress output correctly goes to\n    stderr, but \"Fetching submodule <foo>\" is going to stdout by\n    mistake.  Fix it to write to stderr.\n\n>> Just wondering, what's Git's policy on this? This message is neither\n>> an error nor a warning, but just purely informational. As such it\n>> semantically does not belong to stderr, or?\n\nI think the stance of Git is to write only machine readable stuff to stdout,\nand essentially all _(translated) stuff (i.e. human readable) goes to stderr as\nsome sort of help or progress indication.\n\n>\n\n>\n> Some people believe that a clean execution should not give anything\n> to stderr (Tcl is one example, IIRC), but I think the core part of\n> Git takes the opposite stance (probably unix tradition?).  Anything\n> that is not the primary output of the program should go to stdout.\n>\n> We may not have been very strict in code reviews to enfore it, and\n> especially on the fringes of the system it may be easy to find\n> violators, though.\n>\n"},{"id":"281440","messageId":"CAHGBnuMJdW=s5nX3c8xFk_Q2cwMb8EZjOpRim+4mULkDAvd11A@mail.gmail.com","threadId":"41775","inReplyTo":"CAGZ79kaASKUGs3y9YHUp=QeD=91by4DhJh+tVfj6aNOJSH-3jg@mail.gmail.com","subject":"Re: [RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Sebastian Schuberth","fromEmail":"sschuberth@gmail.com","sentAt":"2016-03-22T16:56:38Z","receivedAt":"2016-03-22T16:56:38Z","isPatch":false,"sender":{"key":"sschuberth@gmail.com","avatar":"https://avatars.githubusercontent.com/u/349154?v=4"},"body":"On Tue, Mar 22, 2016 at 5:47 PM, Stefan Beller <sbeller@google.com> wrote:\n\n> I think the stance of Git is to write only machine readable stuff to stdout,\n> and essentially all _(translated) stuff (i.e. human readable) goes to stderr as\n> some sort of help or progress indication.\n\nThanks for the clarification.\n\n-- \nSebastian Schuberth\n"},{"id":"281445","messageId":"xmqqshziigd6.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"xmqqd1qmjxrl.fsf@gitster.mtv.corp.google.com","subject":"Re: [RFC_PATCHv4 4/7] submodule init: redirect stdout to stderr","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T17:15:17Z","receivedAt":"2016-03-22T17:15:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Sebastian Schuberth <sschuberth@gmail.com> writes:\n>\n>> Just wondering, what's Git's policy on this? This message is neither\n>> an error nor a warning, but just purely informational. As such it\n>> semantically does not belong to stderr, or?\n>\n> Some people believe that a clean execution should not give anything\n> to stderr (Tcl is one example, IIRC), but I think the core part of\n> Git takes the opposite stance (probably unix tradition?).  Anything\n> that is not the primary output of the program should go to stdout.\n\nEhh, \"should go to\" is obviously \"should not go to\".\n\n>\n> We may not have been very strict in code reviews to enfore it, and\n> especially on the fringes of the system it may be easy to find\n> violators, though.\n"},{"id":"281503","messageId":"xmqqio0ef8r0.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"1458612372-10966-2-git-send-email-sbeller@google.com","subject":"Re: [RFC_PATCHv4 1/7] git submodule: teach `add` to label submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T22:28:03Z","receivedAt":"2016-03-22T22:28:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> When adding new submodules, you can specify the\n> label(s) the submodule belongs to by giving one or more\n> --label arguments. This will record each label in the\n> .gitmodules file as a value of the key\n> \"submodule.$NAME.label\".\n\nCan you define the semantics of \"label\" with a bit more detail in\nthe doc?  For example, it is unclear from the description if a\nsubmodule can have multiple labels (I can read the patch, and I am\nnot asking you to explain it to _me_).  It also is unclear if a user\ncan tweak the set of labels a submodule has locally, iow, without\nmodifying .gitmodules that would end up affecting other people.\n\nI think the expected use of \"label\" is to have the whole project to\nshare which labels a given submodule should have (i.e. it is not\nlike branches you can freely create in your repository, but more\nlike tags that give all project participant shared understanding of\nstable anchoring points), and I am guessing that there is no need\nfor \"repository local labels\" for that reason, but we'd need to see\nthat kind of design decisions spelled out in the documentation to\navoid end-user confusion.\n\nThanks.\n\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n> ---\n>  Documentation/git-submodule.txt |  5 ++++-\n>  git-submodule.sh                | 14 +++++++++++++-\n>  t/t7400-submodule-basic.sh      | 32 ++++++++++++++++++++++++++++++++\n>  3 files changed, 49 insertions(+), 2 deletions(-)\n>\n> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\n> index 13adebf..c0744eb 100644\n> --- a/Documentation/git-submodule.txt\n> +++ b/Documentation/git-submodule.txt\n> @@ -9,7 +9,7 @@ git-submodule - Initialize, update or inspect submodules\n>  SYNOPSIS\n>  --------\n>  [verse]\n> -'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]\n> +'git submodule' [--quiet] add [-b <branch>] [-f|--force] [-l|--label <label>]\n>  \t      [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]\n>  'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]\n>  'git submodule' [--quiet] init [--] [<path>...]\n> @@ -101,6 +101,9 @@ is the superproject and submodule repositories will be kept\n>  together in the same relative location, and only the\n>  superproject's URL needs to be provided: git-submodule will correctly\n>  locate the submodule using the relative URL in .gitmodules.\n> ++\n> +If at least one label argument was given, all labels are recorded in the\n> +.gitmodules file in the label fields.\n>  \n>  status::\n>  \tShow the status of the submodules. This will print the SHA-1 of the\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 97a3097..def1e1c 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -5,7 +5,7 @@\n>  # Copyright (c) 2007 Lars Hjemli\n>  \n>  dashless=$(basename \"$0\" | sed -e 's/-/ /')\n> -USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]\n> +USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [-l|--label <label>][--] <repository> [<path>]\n>     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n>     or: $dashless [--quiet] init [--] [<path>...]\n>     or: $dashless [--quiet] deinit [-f|--force] [--] <path>...\n> @@ -130,6 +130,7 @@ cmd_add()\n>  {\n>  \t# parse $args after \"submodule ... add\".\n>  \treference_path=\n> +\tlabels=\n>  \twhile test $# -ne 0\n>  \tdo\n>  \t\tcase \"$1\" in\n> @@ -165,6 +166,13 @@ cmd_add()\n>  \t\t--depth=*)\n>  \t\t\tdepth=$1\n>  \t\t\t;;\n> +\t\t-l|--label)\n> +\t\t\tlabels=\"${labels} $2\"\n> +\t\t\tshift\n> +\t\t\t;;\n> +\t\t--label=*)\n> +\t\t\tlabels=\"${labels} ${1#--label=}\"\n> +\t\t\t;;\n>  \t\t--)\n>  \t\t\tshift\n>  \t\t\tbreak\n> @@ -292,6 +300,10 @@ Use -f if you really want to add it.\" >&2\n>  \n>  \tgit config -f .gitmodules submodule.\"$sm_name\".path \"$sm_path\" &&\n>  \tgit config -f .gitmodules submodule.\"$sm_name\".url \"$repo\" &&\n> +\tfor label in $labels\n> +\tdo\n> +\t\tgit config --add -f .gitmodules submodule.\"$sm_name\".label \"${label}\"\n> +\tdone &&\n>  \tif test -n \"$branch\"\n>  \tthen\n>  \t\tgit config -f .gitmodules submodule.\"$sm_name\".branch \"$branch\"\n> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\n> index 5991e3c..fc948fd 100755\n> --- a/t/t7400-submodule-basic.sh\n> +++ b/t/t7400-submodule-basic.sh\n> @@ -986,6 +986,7 @@ test_expect_success 'submodule with UTF-8 name' '\n>  '\n>  \n>  test_expect_success 'submodule add clone shallow submodule' '\n> +\ttest_when_finished \"rm -rf super\" &&\n>  \tmkdir super &&\n>  \tpwd=$(pwd) &&\n>  \t(\n> @@ -999,5 +1000,36 @@ test_expect_success 'submodule add clone shallow submodule' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'submodule add records a label' '\n> +\ttest_when_finished \"rm -rf super\" &&\n> +\tmkdir super &&\n> +\tpwd=$(pwd) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit init &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n> +\t\tgit config -f .gitmodules submodule.\"submodule\".label >actual &&\n> +\t\techo labelA >expected &&\n> +\t\ttest_cmp expected actual\n> +\t)\n> +'\n> +\n> +cat >expected <<-EOF\n> +labelA\n> +labelB\n> +EOF\n> +\n> +test_expect_success 'submodule add records multiple labels' '\n> +\ttest_when_finished \"rm -rf super\" &&\n> +\tmkdir super &&\n> +\tpwd=$(pwd) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit init &&\n> +\t\tgit submodule add --label=labelA -l labelB file://\"$pwd\"/example2 submodule &&\n> +\t\tgit config --get-all -f .gitmodules submodule.\"submodule\".label >../actual\n> +\t) &&\n> +\ttest_cmp expected actual\n> +'\n>  \n>  test_done\n"},{"id":"281504","messageId":"xmqqegb2f8nn.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"1458612372-10966-4-git-send-email-sbeller@google.com","subject":"Re: [RFC_PATCHv4 3/7] submodule-config: add method to check for being labeled","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T22:30:04Z","receivedAt":"2016-03-22T22:30:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> In later patches we need to tell if a submodule is labeled by\n> the given labels.\n>\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n> ---\n\nHmph, I would have expected that something like this would touch the\nmodule_list() implementation.  Probably that would happen in future\nsteps, I guess?\n\n>  submodule-config.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\n>  submodule-config.h |  3 +++\n>  2 files changed, 51 insertions(+)\n>\n> diff --git a/submodule-config.c b/submodule-config.c\n> index 7b48e59..b10a773 100644\n> --- a/submodule-config.c\n> +++ b/submodule-config.c\n> @@ -493,3 +493,51 @@ void submodule_free(void)\n>  \tcache_free(&cache);\n>  \tis_cache_init = 0;\n>  }\n> +\n> +int submodule_applicable_by_labels(const struct string_list *list,\n> +\t\t\t\t   const struct submodule *sub)\n> +{\n> +\tint label_apply = 0;\n> +\tstruct strbuf sb = STRBUF_INIT;\n> +\n> +\tif (!list)\n> +\t\treturn 1;\n> +\n> +\tif (sub->labels) {\n> +\t\tstruct string_list_item *item;\n> +\t\tfor_each_string_list_item(item, sub->labels) {\n> +\t\t\tstrbuf_reset(&sb);\n> +\t\t\tstrbuf_addf(&sb, \"*%s\", item->string);\n> +\t\t\tif (string_list_has_string(list, sb.buf)) {\n> +\t\t\t\tlabel_apply = 1;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t}\n> +\t}\n> +\tif (sub->path) {\n> +\t\t/*\n> +\t\t * NEEDSWORK: This currently works only for\n> +\t\t * exact paths, but we want to enable\n> +\t\t * inexact matches such wildcards.\n> +\t\t */\n> +\t\tstrbuf_reset(&sb);\n> +\t\tstrbuf_addf(&sb, \"./%s\", sub->path);\n> +\t\tif (string_list_has_string(list, sb.buf)) {\n> +\t\t\tlabel_apply = 1;\n> +\t\t}\n> +\t}\n> +\tif (sub->name) {\n> +\t\t/*\n> +\t\t * NEEDSWORK: Same as with path. Do we want to\n> +\t\t * support wildcards or such?\n> +\t\t */\n> +\t\tstrbuf_reset(&sb);\n> +\t\tstrbuf_addf(&sb, \":%s\", sub->name);\n> +\t\tif (string_list_has_string(list, sb.buf)) {\n> +\t\t\tlabel_apply = 1;\n> +\t\t}\n> +\t}\n> +\tstrbuf_release(&sb);\n> +\n> +\treturn label_apply;\n> +}\n> diff --git a/submodule-config.h b/submodule-config.h\n> index 8d61df3..d67f666 100644\n> --- a/submodule-config.h\n> +++ b/submodule-config.h\n> @@ -30,4 +30,7 @@ const struct submodule *submodule_from_path(const unsigned char *commit_sha1,\n>  \t\tconst char *path);\n>  void submodule_free(void);\n>  \n> +int submodule_applicable_by_labels(const struct string_list *list,\n> +\t\t\t\t   const struct submodule *sub);\n> +\n>  #endif /* SUBMODULE_CONFIG_H */\n"},{"id":"281505","messageId":"xmqq7fguf8gq.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"1458612372-10966-2-git-send-email-sbeller@google.com","subject":"Re: [RFC_PATCHv4 1/7] git submodule: teach `add` to label submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T22:34:13Z","receivedAt":"2016-03-22T22:34:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> When adding new submodules, you can specify the\n> label(s) the submodule belongs to by giving one or more\n> --label arguments. This will record each label in the\n> .gitmodules file as a value of the key\n> \"submodule.$NAME.label\".\n\nHaving an ability to add a label when adding a brand new submodule\nwould be a \"nice-to-have\" convenience feature, but I think it is\nbetter to start a series to add a new concept by \"need-to-have\"\ninfrastructure that is lower-level.  E.g. \"git submodule label\"\ncommand that allows you to things like:\n\n - query the labels on a given submodule\n - add a label to a given submodule (or to a set of submodules)\n - remove a label to a given submodule (or to a set of submodules)\n\nAnd with that, the user can start using the feature without having\n\"git submodule add --label\".\n"},{"id":"281507","messageId":"xmqq37rif870.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"1458612372-10966-6-git-send-email-sbeller@google.com","subject":"Re: [RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-22T22:40:03Z","receivedAt":"2016-03-22T22:40:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> This change introduces the 'submodule.actionOnLabel' variable\n> in a repository configuration. Generally speaking 'submodule.actionOnLabel'\n> restricts the action of a command when no submodules are selected via the\n> command line explicitely to those submodules, which are selected by\n> 'submodule.actionOnLabel'. It can occur multiple times and can specify\n> the path, the name or one of the labels of a submodule to select that\n> submodule.\n>\n> The introduction of 'submodule.actionOnLabel' starts with\n> 'git submodule update' in this patch and other commands will follow\n> in later patches.\n>\n> 'submodule.actionOnLabel' implies '--init' in 'git submodule update'.\n>\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n>\n> TODO: generic documentation for submodule.actionOnLabel\n> TODO: documentation for submodule update\n\nTODO: a name that matches the concept better.\n\nSo in general\n\n\t$ git submodule $subcmd .\n\nmay be the way to say \"do $subcmd to all submodules\", and\n\n\t$ git submodule $subcmd\n\nmay have been \"operate on nothing\" (or may have been \"operate on\neverything\"), but with this feature, \n\n\t$ git submodule $subcmd\n\nwill by default operate on submodules that match the criteria the\nnew configuration variable specifies?\n\nI suspect that copying this from .gitmodules to .git/config will\nhave security implications and will not be done?  What is the\nexpected way for projects to suggest which set of submodules are the\ngood ones to work on by default using this mechanism?\n\n> Signed-off-by: Stefan Beller <sbeller@google.com>\n> ---\n>  builtin/submodule--helper.c |  22 ++++++++-\n>  t/t7400-submodule-basic.sh  | 115 ++++++++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 136 insertions(+), 1 deletion(-)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index a69b1f4..93760ec 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -573,6 +573,8 @@ struct submodule_update_clone {\n>  \tint current;\n>  \tstruct module_list list;\n>  \tunsigned warn_if_uninitialized : 1;\n> +\t/* patterns to initialize */\n> +\tstruct string_list *initialize;\n>  \n>  \t/* update parameter passed via commandline */\n>  \tstruct submodule_update_strategy update;\n> @@ -590,7 +592,7 @@ struct submodule_update_clone {\n>  \t/* If we want to stop as fast as possible and return an error */\n>  \tunsigned quickstop : 1;\n>  };\n> -#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \\\n> +#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, NULL, \\\n>  \tSUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \\\n>  \tSTRING_LIST_INIT_DUP, 0}\n>  \n> @@ -644,6 +646,15 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>  \tstrbuf_reset(&sb);\n>  \tstrbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n>  \tgit_config_get_string(sb.buf, &url);\n> +\tif (suc->initialize) {\n> +\t\tif (!url) {\n> +\t\t\tinit_submodule(sub->path, suc->prefix, suc->quiet);\n> +\t\t\turl = xstrdup(sub->url);\n> +\t\t}\n> +\t\tif (!submodule_applicable_by_labels(suc->initialize, sub)\n> +\t\t    && !suc->warn_if_uninitialized)\n> +\t\t\tgoto cleanup;\n> +\t}\n>  \tif (!url) {\n>  \t\t/*\n>  \t\t * Only mention uninitialized submodules when their\n> @@ -745,6 +756,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n>  \tconst char *update = NULL;\n>  \tint max_jobs = -1;\n>  \tstruct string_list_item *item;\n> +\tconst struct string_list *list;\n>  \tstruct pathspec pathspec;\n>  \tstruct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;\n>  \n> @@ -793,6 +805,14 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n>  \tgitmodules_config();\n>  \tgit_config(submodule_config, NULL);\n>  \n> +\tlist = git_config_get_value_multi(\"submodule.actionOnLabel\");\n> +\tif (list) {\n> +\t\tsuc.initialize = xmalloc(sizeof(*suc.initialize));\n> +\t\tstring_list_init(suc.initialize, 1);\n> +\t\tfor_each_string_list_item(item, list)\n> +\t\t\tstring_list_insert(suc.initialize, item->string);\n> +\t}\n> +\n>  \tif (max_jobs < 0)\n>  \t\tmax_jobs = parallel_submodules();\n>  \n> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\n> index fc948fd..dc45551 100755\n> --- a/t/t7400-submodule-basic.sh\n> +++ b/t/t7400-submodule-basic.sh\n> @@ -1032,4 +1032,119 @@ test_expect_success 'submodule add records multiple labels' '\n>  \ttest_cmp expected actual\n>  '\n>  \n> +cat <<EOF > expected\n> +submodule\n> +-submodule2\n> +EOF\n> +\n> +test_expect_success 'update initializes all modules when action-on-label configured' '\n> +\ttest_when_finished \"rm -rf super super_clone\" &&\n> +\tmkdir super &&\n> +\tpwd=$(pwd) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit init &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n> +\t\tgit submodule add file://\"$pwd\"/example2 submodule2 &&\n> +\t\tgit commit -a -m \"add two modules, one is labled\"\n> +\t) &&\n> +\tgit clone super super_clone &&\n> +\t(\n> +\t\tcd super_clone &&\n> +\t\tgit config submodule.actionOnLabel \\*labelA &&\n> +\t\tgit submodule update &&\n> +\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n> +\t) &&\n> +\ttest_cmp actual expected\n> +'\n> +\n> +test_expect_success 'submodule update applies to action-on-label selection' '\n> +\ttest_when_finished \"rm -rf super super_clone\" &&\n> +\tmkdir super &&\n> +\toldSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n> +\tpwd=$(pwd) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit init &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule2 &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule3 &&\n> +\t\tgit commit -a -m \"add two modules, both are labled\"\n> +\t) &&\n> +\tgit clone super super_clone &&\n> +\t(\n> +\t\tcd super_clone &&\n> +\t\tgit config submodule.actionOnLabel \\*labelA &&\n> +\t\tgit submodule update\n> +\t) &&\n> +\t(\n> +\t\tcd example2 &&\n> +\t\ttouch anotherfile &&\n> +\t\tgit add anotherfile &&\n> +\t\tgit commit -m \"advance example2\" &&\n> +\t\tgit checkout -b branchName\n> +\t) &&\n> +\tnewSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule4 &&\n> +\t\tgit commit -a -m \"add another labeled module\" &&\n> +\t\tgit config -f .gitmodules submodule.submodule2.label labelB &&\n> +\t\tgit config -f .gitmodules --unset submodule.submodule3.label &&\n> +\t\tgit commit -a -m \"unlabel 2 and 3 upstream\" &&\n> +\t\tgit submodule foreach git pull origin branchName &&\n> +\t\tgit commit -a -m \"update all submodules\" &&\n> +\t\tgit submodule status |cut -c1-52 >../actual\n> +\t) &&\n> +\tcat <<EOF >expected &&\n> + $newSubmoduleHead submodule1\n> + $newSubmoduleHead submodule2\n> + $newSubmoduleHead submodule3\n> + $newSubmoduleHead submodule4\n> +EOF\n> +\ttest_cmp actual expected &&\n> +\t(\n> +\t\tcd super_clone &&\n> +\t\tgit pull &&\n> +\t\tgit submodule update &&\n> +\t\tgit submodule status |cut -c1-52 >../actual\n> +\t) &&\n> +\tcat <<EOF >expected &&\n> + $newSubmoduleHead submodule1\n> ++$oldSubmoduleHead submodule2\n> ++$oldSubmoduleHead submodule3\n> + $newSubmoduleHead submodule4\n> +EOF\n> +\ttest_cmp actual expected\n> +'\n> +\n> +cat <<EOF > expected\n> +submodule1\n> +submodule2\n> +-submodule3\n> +EOF\n> +\n> +test_expect_success 'Change labels in .git/config' '\n> +\ttest_when_finished \"rm -rf super super_clone\" &&\n> +\tmkdir super &&\n> +\tpwd=$(pwd) &&\n> +\t(\n> +\t\tcd super &&\n> +\t\tgit init &&\n> +\t\tgit submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n> +\t\tgit submodule add file://\"$pwd\"/example2 submodule2 &&\n> +\t\tgit submodule add file://\"$pwd\"/example2 submodule3 &&\n> +\t\tgit commit -a -m \"add two modules, one is labled\"\n> +\t) &&\n> +\tgit clone super super_clone &&\n> +\t(\n> +\t\tcd super_clone &&\n> +\t\tgit config submodule.actionOnLabel \\*labelA &&\n> +\t\tgit config submodule.submodule2.label labelA\n> +\t\tgit submodule update &&\n> +\t\tgit submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n> +\t) &&\n> +\ttest_cmp actual expected\n> +'\n> +\n>  test_done\n"},{"id":"281606","messageId":"CAGZ79kYtS_TBMnNhK6FjkQcJt=r1hnFsx=TyatoENjEXBAmRug@mail.gmail.com","threadId":"41775","inReplyTo":"xmqqegb2f8nn.fsf@gitster.mtv.corp.google.com","subject":"Re: [RFC_PATCHv4 3/7] submodule-config: add method to check for being labeled","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-23T21:05:58Z","receivedAt":"2016-03-23T21:05:58Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 22, 2016 at 3:30 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> In later patches we need to tell if a submodule is labeled by\n>> the given labels.\n>>\n>> Signed-off-by: Stefan Beller <sbeller@google.com>\n>> ---\n>\n> Hmph, I would have expected that something like this would touch the\n> module_list() implementation.  Probably that would happen in future\n> steps, I guess?\n\nI would have guessed, too. And I was about to say Jens argued against that in\nan earlier patch series [1]. However I miss remembered and Jens pointed at\n\"git submodule init --label/groups\" being a bad idea, not in the helper.\n\nSo we could still have a \"git submodule--helper labels_apply <submodule>\"\nquery to expose this to shell parts. Most of the shell parts use module_list\nso we could integrate that there too. (\"git submodule_helper list\n--labeled-only\")\n\n[1] $gmane/281670, specifically $gmane/281720\n\n\n>\n>>  submodule-config.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\n>>  submodule-config.h |  3 +++\n>>  2 files changed, 51 insertions(+)\n>>\n>> diff --git a/submodule-config.c b/submodule-config.c\n>> index 7b48e59..b10a773 100644\n>> --- a/submodule-config.c\n>> +++ b/submodule-config.c\n>> @@ -493,3 +493,51 @@ void submodule_free(void)\n>>       cache_free(&cache);\n>>       is_cache_init = 0;\n>>  }\n>> +\n>> +int submodule_applicable_by_labels(const struct string_list *list,\n>> +                                const struct submodule *sub)\n>> +{\n>> +     int label_apply = 0;\n>> +     struct strbuf sb = STRBUF_INIT;\n>> +\n>> +     if (!list)\n>> +             return 1;\n>> +\n>> +     if (sub->labels) {\n>> +             struct string_list_item *item;\n>> +             for_each_string_list_item(item, sub->labels) {\n>> +                     strbuf_reset(&sb);\n>> +                     strbuf_addf(&sb, \"*%s\", item->string);\n>> +                     if (string_list_has_string(list, sb.buf)) {\n>> +                             label_apply = 1;\n>> +                             break;\n>> +                     }\n>> +             }\n>> +     }\n>> +     if (sub->path) {\n>> +             /*\n>> +              * NEEDSWORK: This currently works only for\n>> +              * exact paths, but we want to enable\n>> +              * inexact matches such wildcards.\n>> +              */\n>> +             strbuf_reset(&sb);\n>> +             strbuf_addf(&sb, \"./%s\", sub->path);\n>> +             if (string_list_has_string(list, sb.buf)) {\n>> +                     label_apply = 1;\n>> +             }\n>> +     }\n>> +     if (sub->name) {\n>> +             /*\n>> +              * NEEDSWORK: Same as with path. Do we want to\n>> +              * support wildcards or such?\n>> +              */\n>> +             strbuf_reset(&sb);\n>> +             strbuf_addf(&sb, \":%s\", sub->name);\n>> +             if (string_list_has_string(list, sb.buf)) {\n>> +                     label_apply = 1;\n>> +             }\n>> +     }\n>> +     strbuf_release(&sb);\n>> +\n>> +     return label_apply;\n>> +}\n>> diff --git a/submodule-config.h b/submodule-config.h\n>> index 8d61df3..d67f666 100644\n>> --- a/submodule-config.h\n>> +++ b/submodule-config.h\n>> @@ -30,4 +30,7 @@ const struct submodule *submodule_from_path(const unsigned char *commit_sha1,\n>>               const char *path);\n>>  void submodule_free(void);\n>>\n>> +int submodule_applicable_by_labels(const struct string_list *list,\n>> +                                const struct submodule *sub);\n>> +\n>>  #endif /* SUBMODULE_CONFIG_H */\n"},{"id":"281617","messageId":"CAGZ79kaEmDFDf+1BZV1C5ETswbXmAUYk_OMsZf_ka6tJ=pfwcQ@mail.gmail.com","threadId":"41775","inReplyTo":"xmqq37rif870.fsf@gitster.mtv.corp.google.com","subject":"Re: [RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-23T23:21:48Z","receivedAt":"2016-03-23T23:21:48Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Mar 22, 2016 at 3:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> This change introduces the 'submodule.actionOnLabel' variable\n>> in a repository configuration. Generally speaking 'submodule.actionOnLabel'\n>> restricts the action of a command when no submodules are selected via the\n>> command line explicitely to those submodules, which are selected by\n>> 'submodule.actionOnLabel'. It can occur multiple times and can specify\n>> the path, the name or one of the labels of a submodule to select that\n>> submodule.\n>>\n>> The introduction of 'submodule.actionOnLabel' starts with\n>> 'git submodule update' in this patch and other commands will follow\n>> in later patches.\n>>\n>> 'submodule.actionOnLabel' implies '--init' in 'git submodule update'.\n>>\n>> Signed-off-by: Stefan Beller <sbeller@google.com>\n>>\n>> TODO: generic documentation for submodule.actionOnLabel\n>> TODO: documentation for submodule update\n>\n> TODO: a name that matches the concept better.\n\nThis is one of the hardest parts of the series so far. The last reviews\nwere mostly bike shedding about the name of the concept and I thought\nwe were settled to actionOnLabel as that fits best to what we want to do.\n\nSo let's revisit that. My current understanding of the design:\n\nGeneric properties in the data model:\n * Each submodule has a set of \"things\" attached to it. (A submodule\n   can have none, one or many)\n * A \"thing\" can be attached to many submodules (That's why\n   it was called groups in v1, and labels now)\n * The attachments of \"things\" to submodules can be viewed as a bipartite\n   graph.\n * The attachment needs to work in a way, such that upstream\n   can influence and redefine these attachments (e.g. .gitmodules file\n   as part of the repo; another approach would be to have yet another file\n   .gitlabels or such where you'd have a list of submodules belonging to a\n   \"thing\")\n * If this feature is enabled, the user can select a set of submodules by\n   selecting a set of \"things\" and all submodules connected to these things\n   in the bipartite graph are selected. The expectation for a graph is to\n   select a lot fewer \"things\" than submodules. By having this indirection\n   via the graph, the selection of a subset of submodules is expected to\n   be easier.\n\nProperties I derived from discussion and the data model:\n * The user does not need to have a way of overwriting the bipartite graph,\n   because they can specify submodules by these \"things\", by path or by name.\n   (It would be convenient to do be able to overwrite these, but it is\nnot a strict\n   requirement as the you can get any specification via a set of paths)\n\n * The user needs to make the explicit choice to use the new feature\n   or not, as it has implications on the default behavior of submodule\n   commands.\n\n * To make change of selection easy (which happens e.g. when switching\n   branches or pulling in upstream changes), all submodules are initialized\n   by default.\n\n * Once this feature is enabled a command doesn't apply to all initialized\n   submodules by default any more, but the\n   default set of submodules will be the selected set via the\n   bipartite graph of \"things\".\n\n(Originally I typed out some implementation specific thoughts, but they are\nloaded with even more assumptions, so maybe we'd want to stay on this\nhigh level first)\n\nSo any other naming proposals?\n\nThanks,\nStefan\n\n>\n> So in general\n>\n>         $ git submodule $subcmd .\n>\n> may be the way to say \"do $subcmd to all submodules\", and\n>\n>         $ git submodule $subcmd\n>\n> may have been \"operate on nothing\" (or may have been \"operate on\n> everything\"), but with this feature,\n>\n>         $ git submodule $subcmd\n>\n> will by default operate on submodules that match the criteria the\n> new configuration variable specifies?\n>\n> I suspect that copying this from .gitmodules to .git/config will\n> have security implications and will not be done?  What is the\n> expected way for projects to suggest which set of submodules are the\n> good ones to work on by default using this mechanism?\n>\n>> Signed-off-by: Stefan Beller <sbeller@google.com>\n>> ---\n>>  builtin/submodule--helper.c |  22 ++++++++-\n>>  t/t7400-submodule-basic.sh  | 115 ++++++++++++++++++++++++++++++++++++++++++++\n>>  2 files changed, 136 insertions(+), 1 deletion(-)\n>>\n>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n>> index a69b1f4..93760ec 100644\n>> --- a/builtin/submodule--helper.c\n>> +++ b/builtin/submodule--helper.c\n>> @@ -573,6 +573,8 @@ struct submodule_update_clone {\n>>       int current;\n>>       struct module_list list;\n>>       unsigned warn_if_uninitialized : 1;\n>> +     /* patterns to initialize */\n>> +     struct string_list *initialize;\n>>\n>>       /* update parameter passed via commandline */\n>>       struct submodule_update_strategy update;\n>> @@ -590,7 +592,7 @@ struct submodule_update_clone {\n>>       /* If we want to stop as fast as possible and return an error */\n>>       unsigned quickstop : 1;\n>>  };\n>> -#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \\\n>> +#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, NULL, \\\n>>       SUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \\\n>>       STRING_LIST_INIT_DUP, 0}\n>>\n>> @@ -644,6 +646,15 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,\n>>       strbuf_reset(&sb);\n>>       strbuf_addf(&sb, \"submodule.%s.url\", sub->name);\n>>       git_config_get_string(sb.buf, &url);\n>> +     if (suc->initialize) {\n>> +             if (!url) {\n>> +                     init_submodule(sub->path, suc->prefix, suc->quiet);\n>> +                     url = xstrdup(sub->url);\n>> +             }\n>> +             if (!submodule_applicable_by_labels(suc->initialize, sub)\n>> +                 && !suc->warn_if_uninitialized)\n>> +                     goto cleanup;\n>> +     }\n>>       if (!url) {\n>>               /*\n>>                * Only mention uninitialized submodules when their\n>> @@ -745,6 +756,7 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n>>       const char *update = NULL;\n>>       int max_jobs = -1;\n>>       struct string_list_item *item;\n>> +     const struct string_list *list;\n>>       struct pathspec pathspec;\n>>       struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;\n>>\n>> @@ -793,6 +805,14 @@ static int update_clone(int argc, const char **argv, const char *prefix)\n>>       gitmodules_config();\n>>       git_config(submodule_config, NULL);\n>>\n>> +     list = git_config_get_value_multi(\"submodule.actionOnLabel\");\n>> +     if (list) {\n>> +             suc.initialize = xmalloc(sizeof(*suc.initialize));\n>> +             string_list_init(suc.initialize, 1);\n>> +             for_each_string_list_item(item, list)\n>> +                     string_list_insert(suc.initialize, item->string);\n>> +     }\n>> +\n>>       if (max_jobs < 0)\n>>               max_jobs = parallel_submodules();\n>>\n>> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh\n>> index fc948fd..dc45551 100755\n>> --- a/t/t7400-submodule-basic.sh\n>> +++ b/t/t7400-submodule-basic.sh\n>> @@ -1032,4 +1032,119 @@ test_expect_success 'submodule add records multiple labels' '\n>>       test_cmp expected actual\n>>  '\n>>\n>> +cat <<EOF > expected\n>> +submodule\n>> +-submodule2\n>> +EOF\n>> +\n>> +test_expect_success 'update initializes all modules when action-on-label configured' '\n>> +     test_when_finished \"rm -rf super super_clone\" &&\n>> +     mkdir super &&\n>> +     pwd=$(pwd) &&\n>> +     (\n>> +             cd super &&\n>> +             git init &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule &&\n>> +             git submodule add file://\"$pwd\"/example2 submodule2 &&\n>> +             git commit -a -m \"add two modules, one is labled\"\n>> +     ) &&\n>> +     git clone super super_clone &&\n>> +     (\n>> +             cd super_clone &&\n>> +             git config submodule.actionOnLabel \\*labelA &&\n>> +             git submodule update &&\n>> +             git submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n>> +     ) &&\n>> +     test_cmp actual expected\n>> +'\n>> +\n>> +test_expect_success 'submodule update applies to action-on-label selection' '\n>> +     test_when_finished \"rm -rf super super_clone\" &&\n>> +     mkdir super &&\n>> +     oldSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n>> +     pwd=$(pwd) &&\n>> +     (\n>> +             cd super &&\n>> +             git init &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule2 &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule3 &&\n>> +             git commit -a -m \"add two modules, both are labled\"\n>> +     ) &&\n>> +     git clone super super_clone &&\n>> +     (\n>> +             cd super_clone &&\n>> +             git config submodule.actionOnLabel \\*labelA &&\n>> +             git submodule update\n>> +     ) &&\n>> +     (\n>> +             cd example2 &&\n>> +             touch anotherfile &&\n>> +             git add anotherfile &&\n>> +             git commit -m \"advance example2\" &&\n>> +             git checkout -b branchName\n>> +     ) &&\n>> +     newSubmoduleHead=$(cd example2 && git rev-parse HEAD) &&\n>> +     (\n>> +             cd super &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule4 &&\n>> +             git commit -a -m \"add another labeled module\" &&\n>> +             git config -f .gitmodules submodule.submodule2.label labelB &&\n>> +             git config -f .gitmodules --unset submodule.submodule3.label &&\n>> +             git commit -a -m \"unlabel 2 and 3 upstream\" &&\n>> +             git submodule foreach git pull origin branchName &&\n>> +             git commit -a -m \"update all submodules\" &&\n>> +             git submodule status |cut -c1-52 >../actual\n>> +     ) &&\n>> +     cat <<EOF >expected &&\n>> + $newSubmoduleHead submodule1\n>> + $newSubmoduleHead submodule2\n>> + $newSubmoduleHead submodule3\n>> + $newSubmoduleHead submodule4\n>> +EOF\n>> +     test_cmp actual expected &&\n>> +     (\n>> +             cd super_clone &&\n>> +             git pull &&\n>> +             git submodule update &&\n>> +             git submodule status |cut -c1-52 >../actual\n>> +     ) &&\n>> +     cat <<EOF >expected &&\n>> + $newSubmoduleHead submodule1\n>> ++$oldSubmoduleHead submodule2\n>> ++$oldSubmoduleHead submodule3\n>> + $newSubmoduleHead submodule4\n>> +EOF\n>> +     test_cmp actual expected\n>> +'\n>> +\n>> +cat <<EOF > expected\n>> +submodule1\n>> +submodule2\n>> +-submodule3\n>> +EOF\n>> +\n>> +test_expect_success 'Change labels in .git/config' '\n>> +     test_when_finished \"rm -rf super super_clone\" &&\n>> +     mkdir super &&\n>> +     pwd=$(pwd) &&\n>> +     (\n>> +             cd super &&\n>> +             git init &&\n>> +             git submodule add --label labelA file://\"$pwd\"/example2 submodule1 &&\n>> +             git submodule add file://\"$pwd\"/example2 submodule2 &&\n>> +             git submodule add file://\"$pwd\"/example2 submodule3 &&\n>> +             git commit -a -m \"add two modules, one is labled\"\n>> +     ) &&\n>> +     git clone super super_clone &&\n>> +     (\n>> +             cd super_clone &&\n>> +             git config submodule.actionOnLabel \\*labelA &&\n>> +             git config submodule.submodule2.label labelA\n>> +             git submodule update &&\n>> +             git submodule status |cut -c1,42-52 | tr -d \" \" >../actual\n>> +     ) &&\n>> +     test_cmp actual expected\n>> +'\n>> +\n>>  test_done\n"},{"id":"281626","messageId":"xmqqlh58bun7.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"CAGZ79kaEmDFDf+1BZV1C5ETswbXmAUYk_OMsZf_ka6tJ=pfwcQ@mail.gmail.com","subject":"Re: [RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T00:13:16Z","receivedAt":"2016-03-24T00:13:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> On Tue, Mar 22, 2016 at 3:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Stefan Beller <sbeller@google.com> writes:\n>>\n>>> This change introduces the 'submodule.actionOnLabel' variable\n>>> in a repository configuration. Generally speaking 'submodule.actionOnLabel'\n>>> restricts the action of a command when no submodules are selected via the\n>>> command line explicitely to those submodules, which are selected by\n>>> 'submodule.actionOnLabel'. It can occur multiple times and can specify\n>>> the path, the name or one of the labels of a submodule to select that\n>>> submodule.\n>>>\n>>> The introduction of 'submodule.actionOnLabel' starts with\n>>> 'git submodule update' in this patch and other commands will follow\n>>> in later patches.\n>>>\n>>> 'submodule.actionOnLabel' implies '--init' in 'git submodule update'.\n>>>\n>>> Signed-off-by: Stefan Beller <sbeller@google.com>\n>>>\n>>> TODO: generic documentation for submodule.actionOnLabel\n>>> TODO: documentation for submodule update\n>>\n>> TODO: a name that matches the concept better.\n>\n> This is one of the hardest parts of the series so far. The last reviews\n> were mostly bike shedding about the name of the concept and I thought\n> we were settled to actionOnLabel as that fits best to what we want to do.\n>\n> So let's revisit that. My current understanding of the design:\n\nI am not questioning the name \"label\" to call the facility that\nallows projects to group submodules together, and that serves as one\nof the ways to choose what subset of submodules are worked on by\ndefault.  There is no need to revisit that part.\n\nWhat I am questioning is\n\n\taction On Label\n\nbecause\n\n (1) it sounds as if that configuration were a way to choose what\n     action is done to the chosen subset of submodules;\n\n (2) it sounds as if the only way to choose a subset of submodules\n     to be operated on by default is via the \"label\" mechanism.\n\nAnd from your writing (omitted), I think we agree that we definitely\nwant to avoid the misunderstanding that is (1).  This variable does\nnot specify what is done--this specifies what subset of submodules\nare to be operated on.  Having \"action\" in the name of the variable\nis wrong.\n\nAnd from the proposed log message, it is clear that \"label\" is not\nthe only way to specify the subset of submodules to be worked on,\ni.e. \"... can specify the path, name or the labels\".   Having\n\"label\" in the variable name is wrong.\n\nI am tempted to suggest submodule.defaultOperand and I am fairly\nsure \"default\" part of that name gets the concept much better than\n\"actionOnLabel\", but there probably are much better words than\nOperand.\n"},{"id":"281714","messageId":"CAGZ79kZCHv6z6zT2Q2MzMNXfGWcqk9uxsqQ-uEjAPw3h+cSjsQ@mail.gmail.com","threadId":"41775","inReplyTo":"xmqqlh58bun7.fsf@gitster.mtv.corp.google.com","subject":"Re: [RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-03-24T19:54:05Z","receivedAt":"2016-03-24T19:54:05Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Mar 23, 2016 at 5:13 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> On Tue, Mar 22, 2016 at 3:40 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Stefan Beller <sbeller@google.com> writes:\n>>>\n>>>> This change introduces the 'submodule.actionOnLabel' variable\n>>>> in a repository configuration. Generally speaking 'submodule.actionOnLabel'\n>>>> restricts the action of a command when no submodules are selected via the\n>>>> command line explicitely to those submodules, which are selected by\n>>>> 'submodule.actionOnLabel'. It can occur multiple times and can specify\n>>>> the path, the name or one of the labels of a submodule to select that\n>>>> submodule.\n>>>>\n>>>> The introduction of 'submodule.actionOnLabel' starts with\n>>>> 'git submodule update' in this patch and other commands will follow\n>>>> in later patches.\n>>>>\n>>>> 'submodule.actionOnLabel' implies '--init' in 'git submodule update'.\n>>>>\n>>>> Signed-off-by: Stefan Beller <sbeller@google.com>\n>>>>\n>>>> TODO: generic documentation for submodule.actionOnLabel\n>>>> TODO: documentation for submodule update\n>>>\n>>> TODO: a name that matches the concept better.\n>>\n>> This is one of the hardest parts of the series so far. The last reviews\n>> were mostly bike shedding about the name of the concept and I thought\n>> we were settled to actionOnLabel as that fits best to what we want to do.\n>>\n>> So let's revisit that. My current understanding of the design:\n>\n> I am not questioning the name \"label\" to call the facility that\n> allows projects to group submodules together, and that serves as one\n> of the ways to choose what subset of submodules are worked on by\n> default.  There is no need to revisit that part.\n>\n> What I am questioning is\n>\n>         action On Label\n>\n> because\n>\n>  (1) it sounds as if that configuration were a way to choose what\n>      action is done to the chosen subset of submodules;\n>\n>  (2) it sounds as if the only way to choose a subset of submodules\n>      to be operated on by default is via the \"label\" mechanism.\n>\n> And from your writing (omitted), I think we agree that we definitely\n> want to avoid the misunderstanding that is (1).  This variable does\n> not specify what is done--this specifies what subset of submodules\n> are to be operated on.  Having \"action\" in the name of the variable\n> is wrong.\n>\n> And from the proposed log message, it is clear that \"label\" is not\n> the only way to specify the subset of submodules to be worked on,\n> i.e. \"... can specify the path, name or the labels\".   Having\n> \"label\" in the variable name is wrong.\n>\n> I am tempted to suggest submodule.defaultOperand and I am fairly\n> sure \"default\" part of that name gets the concept much better than\n> \"actionOnLabel\", but there probably are much better words than\n> Operand.\n\nI immediately thought of defaultActionset, because \"default\", as well as the\n\"actionset\" conveys the concept of choosing a subset of submodules to operate\non. However You may mistake it as defaultActionSet, i.e. what action is set\nby default.\n\nMaybe we can revive the term \"group\" and call it submodule.defaultGroup.\nThe defaultGroup is defined by selection of names, paths and labels.\n"},{"id":"281725","messageId":"xmqq37rf8tp7.fsf@gitster.mtv.corp.google.com","threadId":"41775","inReplyTo":"CAGZ79kZCHv6z6zT2Q2MzMNXfGWcqk9uxsqQ-uEjAPw3h+cSjsQ@mail.gmail.com","subject":"Re: [RFC_PATCHv4 5/7] submodule update: respect submodule.actionOnLabel","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-24T21:14:12Z","receivedAt":"2016-03-24T21:14:12Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> Maybe we can revive the term \"group\" and call it submodule.defaultGroup.\n> The defaultGroup is defined by selection of names, paths and labels.\n\nThere are many ways to specify one or more of submodules:\n\n - By giving \"pathspecs\", you would choose submodules whose paths\n   match them;\n\n - By giving one or more \"names\", you would choose the submodule\n   with one of these names; or\n\n - By giving one or more \"labels\", you would choose submodules that\n   have one of these labels.\n\nIt is perfectly fine to call the chosen set of submodules \"group of\nsubmodules\".  It does not have any connotation on what is to be done\nabout the group, so that is probably the best word suggested so far\nin the thread.\n"}]}