{"thread":{"id":"49490","subject":"[PATCH v6 03/10] t7411: merge tests 5 and 6","startedAt":"2018-10-05T13:06:10Z","lastAt":"2018-10-25T13:21:04Z","messageCount":23,"participants":["Antonio Ospite","Stefan Beller","Junio C Hamano"],"isPatch":true,"patchVersion":6,"patchTotal":10},"messages":[{"id":"359674","messageId":"20181005130601.15879-4-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 03/10] t7411: merge tests 5 and 6","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:54Z","receivedAt":"2018-10-05T13:06:10Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Tests 5 and 6 check for the effects of the same commit, merge the two\ntests to make it more straightforward to clean things up after the test\nhas finished.\n\nThe cleanup will be added in a future commit.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n t/t7411-submodule-config.sh | 18 +++++-------------\n 1 file changed, 5 insertions(+), 13 deletions(-)\n\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 0bde5850ac..f2cd1f4a2c 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -82,29 +82,21 @@ Submodule name: 'a' for path 'b'\n Submodule name: 'submodule' for path 'submodule'\n EOF\n \n-test_expect_success 'error in one submodule config lets continue' '\n+test_expect_success 'error in history of one submodule config lets continue, stderr message contains blob ref' '\n \t(cd super &&\n \t\tcp .gitmodules .gitmodules.bak &&\n \t\techo \"\tvalue = \\\"\" >>.gitmodules &&\n \t\tgit add .gitmodules &&\n \t\tmv .gitmodules.bak .gitmodules &&\n \t\tgit commit -m \"add error\" &&\n-\t\ttest-tool submodule-config \\\n-\t\t\tHEAD b \\\n-\t\t\tHEAD submodule \\\n-\t\t\t\t>actual &&\n-\t\ttest_cmp expect_error actual\n-\t)\n-'\n-\n-test_expect_success 'error message contains blob reference' '\n-\t(cd super &&\n \t\tsha1=$(git rev-parse HEAD) &&\n \t\ttest-tool submodule-config \\\n \t\t\tHEAD b \\\n \t\t\tHEAD submodule \\\n-\t\t\t\t2>actual_err &&\n-\t\ttest_i18ngrep \"submodule-blob $sha1:.gitmodules\" actual_err >/dev/null\n+\t\t\t\t>actual \\\n+\t\t\t\t2>actual_stderr &&\n+\t\ttest_cmp expect_error actual &&\n+\t\ttest_i18ngrep \"submodule-blob $sha1:.gitmodules\" actual_stderr >/dev/null\n \t)\n '\n \n-- \n2.19.0\n\n"},{"id":"359675","messageId":"20181005130601.15879-1-ao2@ao2.it","threadId":"49490","inReplyTo":null,"subject":"[PATCH v6 00/10] Make submodules work if .gitmodules is not checked out","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:51Z","receivedAt":"2018-10-05T13:06:12Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Hi,\n\nthis series teaches git to try and read the .gitmodules file from the\nindex (:.gitmodules) or from the current branch (HEAD:.gitmodules) when\nthe file is not readily available in the working tree.\n\nThis can be used, together with sparse checkouts, to enable submodule\nusage with programs like vcsh[1] which manage multiple repositories with\ntheir working trees sharing the same path.\n\n[1] https://github.com/RichiH/vcsh\n\n\nThanks to SZEDER Gábor we found out that the changes in patch 9 could\nallow to access the object store in an inconsistent way when using\nmulti-threading in \"git grep --recurse-submodules\", this has been dealt\nwith in this revision.\n\nBTW, with Stefan Beller we also identified some unneeded code which\ncould have been removed to alleviate the issue, but that would not have\nsolved it completely; so, I am not removing the unnecessary call to\nrepo_read_gitmodules() builtin/grep.c in this series, possibly this can\nbecome a stand-alone change.\n\nThe problems from above also made me investigate what implications the\ncurrent use of a global object store had on my new addition, and now\nI know that there is one case which I cannot support just yet: nested\nsubmodules without .gitmodules in their working tree.\n\nThis case has been documented with a warning and test_expect_failure\nitems in tests, and hitting the unsupported case does not alter the\ncurrent behavior of git.\n\nApart form patch 9 and 10 there are no major changes to the previous\niteration.\n\nIMHO we are in a place where the problem has been analyzed with enough\ndepth, the limitations have been identified and dealt with in a way that\nshould not affect current users nor diminish the usefulness of the new\ncode.\n\nv5 of the series is here:\nhttps://public-inbox.org/git/20180917140940.3839-1-ao2@ao2.it/\n\nv4 of the series is here:\nhttps://public-inbox.org/git/20180824132951.8000-1-ao2@ao2.it/\n\nv3 of the series is here:\nhttps://public-inbox.org/git/20180814110525.17801-1-ao2@ao2.it/\n\nv2 of the series is here:\nhttps://public-inbox.org/git/20180802134634.10300-1-ao2@ao2.it/\n\nv1 of the series, with some background info, is here:\nhttps://public-inbox.org/git/20180514105823.8378-1-ao2@ao2.it/\n\nChanges since v5:\n\n  * print_config_from_gitmodules() in patch 1 now accepts a struct\n    repository argument.\n\n  * submodule--helper config in patch 5 has been adjusted to use the new\n    signature of print_config_from_gitmodules().\n\n  * In patch 9 the grep read lock in builtin/grep.c now covers all code\n    paths involving config_from_gitmodules().\n    \n    FTR git-grep is the only place where config_from_gitmodules() is\n    called from multi-threaded code.\n\n  * Patch 9 also documents the rare case that cannot be supported just\n    yet, and adds a warning to the user.\n\n  * In patch 9, config_from_gitmodules() now does not read any config\n    when the config source is not specified.(I added a catch-all \"else\"\n    block) This match more closely the behavior of the old code using\n    git_config_from_file.\n\n  * Added a new test tool in patch 10 to exercise config_read_config()\n    in a more direct way, passing an arbitrary repository.\n    \n    Admittedly, patch 10 performs a similar test to the one added to\n    t7814 in patch 9, so I'd be OK with dropping patch 10 if it is too\n    specific.\n\nThank you,\n   Antonio\n\nAntonio Ospite (10):\n  submodule: add a print_config_from_gitmodules() helper\n  submodule: factor out a config_set_in_gitmodules_file_gently function\n  t7411: merge tests 5 and 6\n  t7411: be nicer to future tests and really clean things up\n  submodule--helper: add a new 'config' subcommand\n  submodule: use the 'submodule--helper config' command\n  t7506: clean up .gitmodules properly before setting up new scenario\n  submodule: add a helper to check if it is safe to write to .gitmodules\n  submodule: support reading .gitmodules when it's not in the working\n    tree\n  t/helper: add test-submodule-nested-repo-config\n\n Makefile                                     |   1 +\n builtin/grep.c                               |  17 ++-\n builtin/submodule--helper.c                  |  40 ++++++\n cache.h                                      |   2 +\n git-submodule.sh                             |  13 +-\n submodule-config.c                           |  68 ++++++++-\n submodule-config.h                           |   2 +\n submodule.c                                  |  28 +++-\n submodule.h                                  |   1 +\n t/helper/test-submodule-nested-repo-config.c |  30 ++++\n t/helper/test-tool.c                         |   1 +\n t/helper/test-tool.h                         |   1 +\n t/t7411-submodule-config.sh                  | 141 +++++++++++++++++--\n t/t7416-submodule-sparse-gitmodules.sh       |  78 ++++++++++\n t/t7506-status-submodule.sh                  |   3 +-\n t/t7814-grep-recurse-submodules.sh           |  16 +++\n 16 files changed, 410 insertions(+), 32 deletions(-)\n create mode 100644 t/helper/test-submodule-nested-repo-config.c\n create mode 100755 t/t7416-submodule-sparse-gitmodules.sh\n\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"},{"id":"359676","messageId":"20181005130601.15879-10-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:06:00Z","receivedAt":"2018-10-05T13:06:12Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"When the .gitmodules file is not available in the working tree, try\nusing the content from the index and from the current branch. This\ncovers the case when the file is part of the repository but for some\nreason it is not checked out, for example because of a sparse checkout.\n\nThis makes it possible to use at least the 'git submodule' commands\nwhich *read* the gitmodules configuration file without fully populating\nthe working tree.\n\nWriting to .gitmodules will still require that the file is checked out,\nso check for that before calling config_set_in_gitmodules_file_gently.\n\nAdd a similar check also in git-submodule.sh::cmd_add() to anticipate\nthe eventual failure of the \"git submodule add\" command when .gitmodules\nis not safely writeable; this prevents the command from leaving the\nrepository in a spurious state (e.g. the submodule repository was cloned\nbut .gitmodules was not updated because\nconfig_set_in_gitmodules_file_gently failed).\n\nMoreover, since config_from_gitmodules() now accesses the global object\nstore, it is necessary to protect all code paths which call the function\nagainst concurrent access to the global object store. Currently this\nonly happens in builtin/grep.c::grep_submodules(), so call\ngrep_read_lock() before invoking code involving\nconfig_from_gitmodules().\n\nFinally, add t7416-submodule-sparse-gitmodules.sh to verify that reading\nfrom .gitmodules succeeds and that writing to it fails when the file is\nnot checked out.\n\nNOTE: there is one rare case where this new feature does not work\nproperly yet: nested submodules without .gitmodules in their working\ntree.  This has been documented with a warning and a test_expect_failure\nitem in t7814, and in this case the current behavior is not altered: no\nconfig is read.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n builtin/grep.c                         | 17 +++++-\n builtin/submodule--helper.c            |  6 +-\n git-submodule.sh                       |  5 ++\n submodule-config.c                     | 31 +++++++++-\n t/t7411-submodule-config.sh            | 26 ++++++++-\n t/t7416-submodule-sparse-gitmodules.sh | 78 ++++++++++++++++++++++++++\n t/t7814-grep-recurse-submodules.sh     | 16 ++++++\n 7 files changed, 172 insertions(+), 7 deletions(-)\n create mode 100755 t/t7416-submodule-sparse-gitmodules.sh\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 601f801158..7da8fef31a 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -421,11 +421,23 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,\n \tstruct repository submodule;\n \tint hit;\n \n-\tif (!is_submodule_active(superproject, path))\n+\t/*\n+\t * NEEDSWORK: submodules functions need to be protected because they\n+\t * access the object store via config_from_gitmodules(): the latter\n+\t * uses get_oid() which, for now, relies on the global the_repository\n+\t * object.\n+\t */\n+\tgrep_read_lock();\n+\n+\tif (!is_submodule_active(superproject, path)) {\n+\t\tgrep_read_unlock();\n \t\treturn 0;\n+\t}\n \n-\tif (repo_submodule_init(&submodule, superproject, path))\n+\tif (repo_submodule_init(&submodule, superproject, path)) {\n+\t\tgrep_read_unlock();\n \t\treturn 0;\n+\t}\n \n \trepo_read_gitmodules(&submodule);\n \n@@ -439,7 +451,6 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,\n \t * store is no longer global and instead is a member of the repository\n \t * object.\n \t */\n-\tgrep_read_lock();\n \tadd_to_alternates_memory(submodule.objects->objectdir);\n \tgrep_read_unlock();\n \ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 28f3ccca6d..5f8a804a6e 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2154,8 +2154,12 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n \n \t/* Equivalent to ACTION_SET in builtin/config.c */\n-\tif (argc == 3)\n+\tif (argc == 3) {\n+\t\tif (!is_writing_gitmodules_ok())\n+\t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n+\n \t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\t}\n \n \tusage_with_options(git_submodule_helper_usage, module_config_options);\n }\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 0805fadf47..f5124bbf23 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -159,6 +159,11 @@ cmd_add()\n \t\tshift\n \tdone\n \n+\tif ! git submodule--helper config --check-writeable >/dev/null 2>&1\n+\tthen\n+\t\t die \"$(eval_gettext \"please make sure that the .gitmodules file is in the working tree\")\"\n+\tfi\n+\n \tif test -n \"$reference_path\"\n \tthen\n \t\tis_absolute_path \"$reference_path\" ||\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 8659d97e06..69bebb721e 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"dir.h\"\n #include \"repository.h\"\n #include \"config.h\"\n #include \"submodule-config.h\"\n@@ -603,8 +604,34 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tchar *file = repo_worktree_path(repo, GITMODULES_FILE);\n-\t\tgit_config_from_file(fn, file, data);\n+\t\tstruct git_config_source config_source = { 0 };\n+\t\tconst struct config_options opts = { 0 };\n+\t\tstruct object_id oid;\n+\t\tchar *file;\n+\n+\t\tfile = repo_worktree_path(repo, GITMODULES_FILE);\n+\t\tif (file_exists(file)) {\n+\t\t\tconfig_source.file = file;\n+\t\t} else if (repo->submodule_prefix) {\n+\t\t\t/*\n+\t\t\t * When get_oid and config_with_options, used below,\n+\t\t\t * become able to work on a specific repository, this\n+\t\t\t * warning branch can be removed.\n+\t\t\t */\n+\t\t\twarning(\"nested submodules without %s in the working tree are not supported yet\",\n+\t\t\t\tGITMODULES_FILE);\n+\t\t\tgoto out;\n+\t\t} else if (get_oid(GITMODULES_INDEX, &oid) >= 0) {\n+\t\t\tconfig_source.blob = GITMODULES_INDEX;\n+\t\t} else if (get_oid(GITMODULES_HEAD, &oid) >= 0) {\n+\t\t\tconfig_source.blob = GITMODULES_HEAD;\n+\t\t} else {\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tconfig_with_options(fn, data, &config_source, &opts);\n+\n+out:\n \t\tfree(file);\n \t}\n }\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 45953f9300..2cfabb18bc 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -134,7 +134,7 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '\n \t)\n '\n \n-test_expect_success 'reading submodules config with \"submodule--helper config\"' '\n+test_expect_success 'reading submodules config from the working tree with \"submodule--helper config\"' '\n \t(cd super &&\n \t\techo \"../submodule\" >expect &&\n \t\tgit submodule--helper config submodule.submodule.url >actual &&\n@@ -192,4 +192,28 @@ test_expect_success 'non-writeable .gitmodules when it is in the current branch\n \t)\n '\n \n+test_expect_success 'reading submodules config from the index when .gitmodules is not in the working tree' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n+\t(cd super &&\n+\t\tgit submodule--helper config submodule.submodule.url \"staged_url\" &&\n+\t\tgit add .gitmodules &&\n+\t\trm -f .gitmodules &&\n+\t\techo \"staged_url\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'reading submodules config from the current branch when .gitmodules is not in the index' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n+\t(cd super &&\n+\t\tgit rm .gitmodules &&\n+\t\techo \"../submodule\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n test_done\ndiff --git a/t/t7416-submodule-sparse-gitmodules.sh b/t/t7416-submodule-sparse-gitmodules.sh\nnew file mode 100755\nindex 0000000000..908a4e6958\n--- /dev/null\n+++ b/t/t7416-submodule-sparse-gitmodules.sh\n@@ -0,0 +1,78 @@\n+#!/bin/sh\n+#\n+# Copyright (C) 2018  Antonio Ospite <ao2@ao2.it>\n+#\n+\n+test_description='Test reading/writing .gitmodules when not in the working tree\n+\n+This test verifies that, when .gitmodules is in the current branch but is not\n+in the working tree reading from it still works but writing to it does not.\n+\n+The test setup uses a sparse checkout, however the same scenario can be set up\n+also by committing .gitmodules and then just removing it from the filesystem.\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'sparse checkout setup which hides .gitmodules' '\n+\techo file >file &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m upstream &&\n+\tgit clone . super &&\n+\tgit clone super submodule &&\n+\tgit clone super new_submodule &&\n+\t(cd super &&\n+\t\tgit submodule add ../submodule &&\n+\t\ttest_tick &&\n+\t\tgit commit -m submodule &&\n+\t\tcat >.git/info/sparse-checkout <<-\\EOF &&\n+\t\t/*\n+\t\t!/.gitmodules\n+\t\tEOF\n+\t\tgit config core.sparsecheckout true &&\n+\t\tgit read-tree -m -u HEAD &&\n+\t\ttest_path_is_missing .gitmodules\n+\t)\n+'\n+\n+test_expect_success 'reading gitmodules config file when it is not checked out' '\n+\t(cd super &&\n+\t\techo \"../submodule\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'not writing gitmodules config file when it is not checked out' '\n+\t test_must_fail git -C super submodule--helper config submodule.submodule.url newurl\n+'\n+\n+test_expect_success 'initialising submodule when the gitmodules config is not checked out' '\n+\tgit -C super submodule init\n+'\n+\n+test_expect_success 'showing submodule summary when the gitmodules config is not checked out' '\n+\tgit -C super submodule summary\n+'\n+\n+test_expect_success 'updating submodule when the gitmodules config is not checked out' '\n+\t(cd submodule &&\n+\t\techo file2 >file2 &&\n+\t\tgit add file2 &&\n+\t\tgit commit -m \"add file2 to submodule\"\n+\t) &&\n+\tgit -C super submodule update\n+'\n+\n+test_expect_success 'not adding submodules when the gitmodules config is not checked out' '\n+\ttest_must_fail git -C super submodule add ../new_submodule\n+'\n+\n+# This test checks that the previous \"git submodule add\" did not leave the\n+# repository in a spurious state when it failed.\n+test_expect_success 'init submodule still works even after the previous add failed' '\n+\tgit -C super submodule init\n+'\n+\n+test_done\ndiff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh\nindex 7184113b9b..fa475d52fa 100755\n--- a/t/t7814-grep-recurse-submodules.sh\n+++ b/t/t7814-grep-recurse-submodules.sh\n@@ -380,4 +380,20 @@ test_expect_success 'grep --recurse-submodules should pass the pattern type alon\n \tfi\n '\n \n+# Recursing down into nested submodules which do not have .gitmodules in their\n+# working tree does not work yet. This is because config_from_gitmodules()\n+# uses get_oid() and the latter is still not able to get objects from an\n+# arbitrary repository (the nested submodule, in this case).\n+test_expect_failure 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '\n+\ttest_when_finished \"git -C submodule checkout .gitmodules\" &&\n+\trm submodule/.gitmodules &&\n+\tgit grep --recurse-submodules -e \"(.|.)[\\d]\" >actual &&\n+\tcat >expect <<-\\EOF &&\n+\ta:(1|2)d(3|4)\n+\tsubmodule/a:(1|2)d(3|4)\n+\tsubmodule/sub/a:(1|2)d(3|4)\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.19.0\n\n"},{"id":"359677","messageId":"20181005130601.15879-5-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 04/10] t7411: be nicer to future tests and really clean things up","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:55Z","receivedAt":"2018-10-05T13:06:14Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Tests 5 and 7 in t/t7411-submodule-config.sh add two commits with\ninvalid lines in .gitmodules but then only the second commit is removed.\n\nThis may affect future subsequent tests if they assume that the\n.gitmodules file has no errors.\n\nRemove both the commits as soon as they are not needed anymore.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n t/t7411-submodule-config.sh | 7 +++++--\n 1 file changed, 5 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex f2cd1f4a2c..b1f3c6489b 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -83,6 +83,8 @@ Submodule name: 'submodule' for path 'submodule'\n EOF\n \n test_expect_success 'error in history of one submodule config lets continue, stderr message contains blob ref' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n \t(cd super &&\n \t\tcp .gitmodules .gitmodules.bak &&\n \t\techo \"\tvalue = \\\"\" >>.gitmodules &&\n@@ -115,6 +117,8 @@ test_expect_success 'using different treeishs works' '\n '\n \n test_expect_success 'error in history in fetchrecursesubmodule lets continue' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n \t(cd super &&\n \t\tgit config -f .gitmodules \\\n \t\t\tsubmodule.submodule.fetchrecursesubmodules blabla &&\n@@ -126,8 +130,7 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '\n \t\t\tHEAD b \\\n \t\t\tHEAD submodule \\\n \t\t\t\t>actual &&\n-\t\ttest_cmp expect_error actual  &&\n-\t\tgit reset --hard HEAD^\n+\t\ttest_cmp expect_error actual\n \t)\n '\n \n-- \n2.19.0\n\n"},{"id":"359678","messageId":"20181005130601.15879-11-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 10/10] t/helper: add test-submodule-nested-repo-config","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:06:01Z","receivedAt":"2018-10-05T13:06:16Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Add a test tool to exercise config_from_gitmodules(), in particular for\nthe case of nested submodules.\n\nAdd also a test to document that reading the submoudles config of nested\nsubmodules does not work yet when the .gitmodules file is not in the\nworking tree but it still in the index.\n\nThis is because the git API does not always make it possible access the\nobject store  of an arbitrary repository (see get_oid() usage in\nconfig_from_gitmodules()).\n\nWhen this git limitation gets fixed the aforementioned use case will be\nsupported too.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n Makefile                                     |  1 +\n t/helper/test-submodule-nested-repo-config.c | 30 +++++++++++++++++\n t/helper/test-tool.c                         |  1 +\n t/helper/test-tool.h                         |  1 +\n t/t7411-submodule-config.sh                  | 34 ++++++++++++++++++++\n 5 files changed, 67 insertions(+)\n create mode 100644 t/helper/test-submodule-nested-repo-config.c\n\ndiff --git a/Makefile b/Makefile\nindex 13e1c52478..fe8587cd8c 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -737,6 +737,7 @@ TEST_BUILTINS_OBJS += test-sigchain.o\n TEST_BUILTINS_OBJS += test-strcmp-offset.o\n TEST_BUILTINS_OBJS += test-string-list.o\n TEST_BUILTINS_OBJS += test-submodule-config.o\n+TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o\n TEST_BUILTINS_OBJS += test-subprocess.o\n TEST_BUILTINS_OBJS += test-urlmatch-normalization.o\n TEST_BUILTINS_OBJS += test-wildmatch.o\ndiff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c\nnew file mode 100644\nindex 0000000000..a31e2a9bea\n--- /dev/null\n+++ b/t/helper/test-submodule-nested-repo-config.c\n@@ -0,0 +1,30 @@\n+#include \"test-tool.h\"\n+#include \"submodule-config.h\"\n+\n+static void die_usage(int argc, const char **argv, const char *msg)\n+{\n+\tfprintf(stderr, \"%s\\n\", msg);\n+\tfprintf(stderr, \"Usage: %s <submodulepath> <config name>\\n\", argv[0]);\n+\texit(1);\n+}\n+\n+int cmd__submodule_nested_repo_config(int argc, const char **argv)\n+{\n+\tstruct repository submodule;\n+\n+\tif (argc < 3)\n+\t\tdie_usage(argc, argv, \"Wrong number of arguments.\");\n+\n+\tsetup_git_directory();\n+\n+\tif (repo_submodule_init(&submodule, the_repository, argv[1])) {\n+\t\tdie_usage(argc, argv, \"Submodule not found.\");\n+\t}\n+\n+\t/* Read the config of _child_ submodules. */\n+\tprint_config_from_gitmodules(&submodule, argv[2]);\n+\n+\tsubmodule_free(the_repository);\n+\n+\treturn 0;\n+}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex b87a8c1f22..3b473bccd8 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -42,6 +42,7 @@ static struct test_cmd cmds[] = {\n \t{ \"strcmp-offset\", cmd__strcmp_offset },\n \t{ \"string-list\", cmd__string_list },\n \t{ \"submodule-config\", cmd__submodule_config },\n+\t{ \"submodule-nested-repo-config\", cmd__submodule_nested_repo_config },\n \t{ \"subprocess\", cmd__subprocess },\n \t{ \"urlmatch-normalization\", cmd__urlmatch_normalization },\n \t{ \"wildmatch\", cmd__wildmatch },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex e074957279..3ca351230c 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -38,6 +38,7 @@ int cmd__sigchain(int argc, const char **argv);\n int cmd__strcmp_offset(int argc, const char **argv);\n int cmd__string_list(int argc, const char **argv);\n int cmd__submodule_config(int argc, const char **argv);\n+int cmd__submodule_nested_repo_config(int argc, const char **argv);\n int cmd__subprocess(int argc, const char **argv);\n int cmd__urlmatch_normalization(int argc, const char **argv);\n int cmd__wildmatch(int argc, const char **argv);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 2cfabb18bc..89690b7adb 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -216,4 +216,38 @@ test_expect_success 'reading submodules config from the current branch when .git\n \t)\n '\n \n+test_expect_success 'reading nested submodules config' '\n+\t(cd super &&\n+\t\tgit init submodule/nested_submodule &&\n+\t\techo \"a\" >submodule/nested_submodule/a &&\n+\t\tgit -C submodule/nested_submodule add a &&\n+\t\tgit -C submodule/nested_submodule commit -m \"add a\" &&\n+\t\tgit -C submodule submodule add ./nested_submodule &&\n+\t\tgit -C submodule add nested_submodule &&\n+\t\tgit -C submodule commit -m \"added nested_submodule\" &&\n+\t\tgit add submodule &&\n+\t\tgit commit -m \"updated submodule\" &&\n+\t\techo \"./nested_submodule\" >expect &&\n+\t\ttest-tool submodule-nested-repo-config \\\n+\t\t\tsubmodule submodule.nested_submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+# When this test eventually passes, before turning it into\n+# test_expect_success, remember to replace the test_i18ngrep below with\n+# a \"test_must_be_empty warning\" to be sure that the warning is actually\n+# removed from the code.\n+test_expect_failure 'reading nested submodules config when .gitmodules is not in the working tree' '\n+\ttest_when_finished \"git -C super/submodule checkout .gitmodules\" &&\n+\t(cd super &&\n+\t\techo \"./nested_submodule\" >expect &&\n+\t\trm submodule/.gitmodules &&\n+\t\ttest-tool submodule-nested-repo-config \\\n+\t\t\tsubmodule submodule.nested_submodule.url >actual 2>warning &&\n+\t\ttest_i18ngrep \"nested submodules without %s in the working tree are not supported yet\" warning &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n test_done\n-- \n2.19.0\n\n"},{"id":"359679","messageId":"20181005130601.15879-3-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 02/10] submodule: factor out a config_set_in_gitmodules_file_gently function","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:53Z","receivedAt":"2018-10-05T13:06:16Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Introduce a new config_set_in_gitmodules_file_gently() function to write\nconfig values to the .gitmodules file.\n\nThis is in preparation for a future change which will use the function\nto write to the .gitmodules file in a more controlled way instead of\nusing \"git config -f .gitmodules\".\n\nThe purpose of the change is mainly to centralize the code that writes\nto the .gitmodules file to avoid some duplication.\n\nThe naming follows git_config_set_in_file_gently() but the git_ prefix\nis removed to communicate that this is not a generic git-config API.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n submodule-config.c | 12 ++++++++++++\n submodule-config.h |  1 +\n submodule.c        | 10 +++-------\n 3 files changed, 16 insertions(+), 7 deletions(-)\n\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 823bc76812..8659d97e06 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -707,6 +707,18 @@ int print_config_from_gitmodules(struct repository *repo, const char *key)\n \treturn 0;\n }\n \n+int config_set_in_gitmodules_file_gently(const char *key, const char *value)\n+{\n+\tint ret;\n+\n+\tret = git_config_set_in_file_gently(GITMODULES_FILE, key, value);\n+\tif (ret < 0)\n+\t\t/* Maybe the user already did that, don't error out here */\n+\t\twarning(_(\"Could not update .gitmodules entry %s\"), key);\n+\n+\treturn ret;\n+}\n+\n struct fetch_config {\n \tint *max_children;\n \tint *recurse_submodules;\ndiff --git a/submodule-config.h b/submodule-config.h\nindex 031747ccf8..4dc9b0771c 100644\n--- a/submodule-config.h\n+++ b/submodule-config.h\n@@ -49,6 +49,7 @@ const struct submodule *submodule_from_path(struct repository *r,\n \t\t\t\t\t    const char *path);\n void submodule_free(struct repository *r);\n int print_config_from_gitmodules(struct repository *repo, const char *key);\n+int config_set_in_gitmodules_file_gently(const char *key, const char *value);\n \n /*\n  * Returns 0 if the name is syntactically acceptable as a submodule \"name\"\ndiff --git a/submodule.c b/submodule.c\nindex b53cb6e9c4..3b23e76e55 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -89,6 +89,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n {\n \tstruct strbuf entry = STRBUF_INIT;\n \tconst struct submodule *submodule;\n+\tint ret;\n \n \tif (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */\n \t\treturn -1;\n@@ -104,14 +105,9 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)\n \tstrbuf_addstr(&entry, \"submodule.\");\n \tstrbuf_addstr(&entry, submodule->name);\n \tstrbuf_addstr(&entry, \".path\");\n-\tif (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {\n-\t\t/* Maybe the user already did that, don't error out here */\n-\t\twarning(_(\"Could not update .gitmodules entry %s\"), entry.buf);\n-\t\tstrbuf_release(&entry);\n-\t\treturn -1;\n-\t}\n+\tret = config_set_in_gitmodules_file_gently(entry.buf, newpath);\n \tstrbuf_release(&entry);\n-\treturn 0;\n+\treturn ret;\n }\n \n /*\n-- \n2.19.0\n\n"},{"id":"359680","messageId":"20181005130601.15879-2-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 01/10] submodule: add a print_config_from_gitmodules() helper","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:52Z","receivedAt":"2018-10-05T13:06:18Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Add a new print_config_from_gitmodules() helper function to print values\nfrom .gitmodules just like \"git config -f .gitmodules\" would.\n\nThis will be used by a new submodule--helper subcommand to be able to\naccess the .gitmodules file in a more controlled way.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n submodule-config.c | 25 +++++++++++++++++++++++++\n submodule-config.h |  1 +\n 2 files changed, 26 insertions(+)\n\ndiff --git a/submodule-config.c b/submodule-config.c\nindex e04ba756d9..823bc76812 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -682,6 +682,31 @@ void submodule_free(struct repository *r)\n \t\tsubmodule_cache_clear(r->submodule_cache);\n }\n \n+static int config_print_callback(const char *var, const char *value, void *cb_data)\n+{\n+\tchar *wanted_key = cb_data;\n+\n+\tif (!strcmp(wanted_key, var))\n+\t\tprintf(\"%s\\n\", value);\n+\n+\treturn 0;\n+}\n+\n+int print_config_from_gitmodules(struct repository *repo, const char *key)\n+{\n+\tint ret;\n+\tchar *store_key;\n+\n+\tret = git_config_parse_key(key, &store_key, NULL);\n+\tif (ret < 0)\n+\t\treturn CONFIG_INVALID_KEY;\n+\n+\tconfig_from_gitmodules(config_print_callback, repo, store_key);\n+\n+\tfree(store_key);\n+\treturn 0;\n+}\n+\n struct fetch_config {\n \tint *max_children;\n \tint *recurse_submodules;\ndiff --git a/submodule-config.h b/submodule-config.h\nindex dc7278eea4..031747ccf8 100644\n--- a/submodule-config.h\n+++ b/submodule-config.h\n@@ -48,6 +48,7 @@ const struct submodule *submodule_from_path(struct repository *r,\n \t\t\t\t\t    const struct object_id *commit_or_tree,\n \t\t\t\t\t    const char *path);\n void submodule_free(struct repository *r);\n+int print_config_from_gitmodules(struct repository *repo, const char *key);\n \n /*\n  * Returns 0 if the name is syntactically acceptable as a submodule \"name\"\n-- \n2.19.0\n\n"},{"id":"359681","messageId":"20181005130601.15879-7-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 06/10] submodule: use the 'submodule--helper config' command","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:57Z","receivedAt":"2018-10-05T13:06:18Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Use the 'submodule--helper config' command in git-submodules.sh to avoid\nreferring explicitly to .gitmodules by the hardcoded file path.\n\nThis makes it possible to access the submodules configuration in a more\ncontrolled way.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n git-submodule.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 1b568e29b9..0805fadf47 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -72,7 +72,7 @@ get_submodule_config () {\n \tvalue=$(git config submodule.\"$name\".\"$option\")\n \tif test -z \"$value\"\n \tthen\n-\t\tvalue=$(git config -f .gitmodules submodule.\"$name\".\"$option\")\n+\t\tvalue=$(git submodule--helper config submodule.\"$name\".\"$option\")\n \tfi\n \tprintf '%s' \"${value:-$default}\"\n }\n@@ -283,11 +283,11 @@ or you are unsure what this means choose another name with the '--name' option.\"\n \tgit add --no-warn-embedded-repo $force \"$sm_path\" ||\n \tdie \"$(eval_gettext \"Failed to add submodule '\\$sm_path'\")\"\n \n-\tgit config -f .gitmodules submodule.\"$sm_name\".path \"$sm_path\" &&\n-\tgit config -f .gitmodules submodule.\"$sm_name\".url \"$repo\" &&\n+\tgit submodule--helper config submodule.\"$sm_name\".path \"$sm_path\" &&\n+\tgit submodule--helper config submodule.\"$sm_name\".url \"$repo\" &&\n \tif test -n \"$branch\"\n \tthen\n-\t\tgit config -f .gitmodules submodule.\"$sm_name\".branch \"$branch\"\n+\t\tgit submodule--helper config submodule.\"$sm_name\".branch \"$branch\"\n \tfi &&\n \tgit add --force .gitmodules ||\n \tdie \"$(eval_gettext \"Failed to register submodule '\\$sm_path'\")\"\n-- \n2.19.0\n\n"},{"id":"359682","messageId":"20181005130601.15879-6-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 05/10] submodule--helper: add a new 'config' subcommand","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:56Z","receivedAt":"2018-10-05T13:06:18Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Add a new 'config' subcommand to 'submodule--helper', this extra level\nof indirection makes it possible to add some flexibility to how the\nsubmodules configuration is handled.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n builtin/submodule--helper.c | 14 ++++++++++++++\n t/t7411-submodule-config.sh | 27 +++++++++++++++++++++++++++\n 2 files changed, 41 insertions(+)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 40844870cf..e1bdca8f0b 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2125,6 +2125,19 @@ static int check_name(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static int module_config(int argc, const char **argv, const char *prefix)\n+{\n+\t/* Equivalent to ACTION_GET in builtin/config.c */\n+\tif (argc == 2)\n+\t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n+\n+\t/* Equivalent to ACTION_SET in builtin/config.c */\n+\tif (argc == 3)\n+\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\n+\tdie(\"submodule--helper config takes 1 or 2 arguments: name [value]\");\n+}\n+\n #define SUPPORT_SUPER_PREFIX (1<<0)\n \n struct cmd_struct {\n@@ -2154,6 +2167,7 @@ static struct cmd_struct commands[] = {\n \t{\"absorb-git-dirs\", absorb_git_dirs, SUPPORT_SUPER_PREFIX},\n \t{\"is-active\", is_active, 0},\n \t{\"check-name\", check_name, 0},\n+\t{\"config\", module_config, 0},\n };\n \n int cmd_submodule__helper(int argc, const char **argv, const char *prefix)\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex b1f3c6489b..791245f18d 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -134,4 +134,31 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' '\n \t)\n '\n \n+test_expect_success 'reading submodules config with \"submodule--helper config\"' '\n+\t(cd super &&\n+\t\techo \"../submodule\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'writing submodules config with \"submodule--helper config\"' '\n+\t(cd super &&\n+\t\techo \"new_url\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url \"new_url\" &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'overwriting unstaged submodules config with \"submodule--helper config\"' '\n+\ttest_when_finished \"git -C super checkout .gitmodules\" &&\n+\t(cd super &&\n+\t\techo \"newer_url\" >expect &&\n+\t\tgit submodule--helper config submodule.submodule.url \"newer_url\" &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n test_done\n-- \n2.19.0\n\n"},{"id":"359683","messageId":"20181005130601.15879-9-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 08/10] submodule: add a helper to check if it is safe to write to .gitmodules","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:59Z","receivedAt":"2018-10-05T13:06:20Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"Introduce a helper function named is_writing_gitmodules_ok() to verify\nthat the .gitmodules file is safe to write.\n\nThe function name follows the scheme of is_staging_gitmodules_ok().\n\nThe two symbolic constants GITMODULES_INDEX and GITMODULES_HEAD are used\nto get help from the C preprocessor in preventing typos, especially for\nfuture users.\n\nThis is in preparation for a future change which teaches git how to read\n.gitmodules from the index or from the current branch if the file is not\navailable in the working tree.\n\nThe rationale behind the check is that writing to .gitmodules requires\nthe file to be present in the working tree, unless a brand new\n.gitmodules is being created (in which case the .gitmodules file would\nnot exist at all: neither in the working tree nor in the index or in the\ncurrent branch).\n\nExpose the functionality also via a \"submodule-helper config\n--check-writeable\" command, as git scripts may want to perform the check\nbefore modifying submodules configuration.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n builtin/submodule--helper.c | 24 +++++++++++++++++++++++-\n cache.h                     |  2 ++\n submodule.c                 | 18 ++++++++++++++++++\n submodule.h                 |  1 +\n t/t7411-submodule-config.sh | 31 +++++++++++++++++++++++++++++++\n 5 files changed, 75 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex e1bdca8f0b..28f3ccca6d 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2127,6 +2127,28 @@ static int check_name(int argc, const char **argv, const char *prefix)\n \n static int module_config(int argc, const char **argv, const char *prefix)\n {\n+\tenum {\n+\t\tCHECK_WRITEABLE = 1\n+\t} command = 0;\n+\n+\tstruct option module_config_options[] = {\n+\t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n+\t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n+\t\t\t    CHECK_WRITEABLE),\n+\t\tOPT_END()\n+\t};\n+\tconst char *const git_submodule_helper_usage[] = {\n+\t\tN_(\"git submodule--helper config name [value]\"),\n+\t\tN_(\"git submodule--helper config --check-writeable\"),\n+\t\tNULL\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, module_config_options,\n+\t\t\t     git_submodule_helper_usage, PARSE_OPT_KEEP_ARGV0);\n+\n+\tif (argc == 1 && command == CHECK_WRITEABLE)\n+\t\treturn is_writing_gitmodules_ok() ? 0 : -1;\n+\n \t/* Equivalent to ACTION_GET in builtin/config.c */\n \tif (argc == 2)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n@@ -2135,7 +2157,7 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \tif (argc == 3)\n \t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n \n-\tdie(\"submodule--helper config takes 1 or 2 arguments: name [value]\");\n+\tusage_with_options(git_submodule_helper_usage, module_config_options);\n }\n \n #define SUPPORT_SUPER_PREFIX (1<<0)\ndiff --git a/cache.h b/cache.h\nindex d508f3d4f8..2d495fc800 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -486,6 +486,8 @@ static inline enum object_type object_type(unsigned int mode)\n #define INFOATTRIBUTES_FILE \"info/attributes\"\n #define ATTRIBUTE_MACRO_PREFIX \"[attr]\"\n #define GITMODULES_FILE \".gitmodules\"\n+#define GITMODULES_INDEX \":.gitmodules\"\n+#define GITMODULES_HEAD \"HEAD:.gitmodules\"\n #define GIT_NOTES_REF_ENVIRONMENT \"GIT_NOTES_REF\"\n #define GIT_NOTES_DEFAULT_REF \"refs/notes/commits\"\n #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT \"GIT_NOTES_DISPLAY_REF\"\ndiff --git a/submodule.c b/submodule.c\nindex 3b23e76e55..bd2506c5ba 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -51,6 +51,24 @@ int is_gitmodules_unmerged(const struct index_state *istate)\n \treturn 0;\n }\n \n+/*\n+ * Check if the .gitmodules file is safe to write.\n+ *\n+ * Writing to the .gitmodules file requires that the file exists in the\n+ * working tree or, if it doesn't, that a brand new .gitmodules file is going\n+ * to be created (i.e. it's neither in the index nor in the current branch).\n+ *\n+ * It is not safe to write to .gitmodules if it's not in the working tree but\n+ * it is in the index or in the current branch, because writing new values\n+ * (and staging them) would blindly overwrite ALL the old content.\n+ */\n+int is_writing_gitmodules_ok(void)\n+{\n+\tstruct object_id oid;\n+\treturn file_exists(GITMODULES_FILE) ||\n+\t\t(get_oid(GITMODULES_INDEX, &oid) < 0 && get_oid(GITMODULES_HEAD, &oid) < 0);\n+}\n+\n /*\n  * Check if the .gitmodules file has unstaged modifications.  This must be\n  * checked before allowing modifications to the .gitmodules file with the\ndiff --git a/submodule.h b/submodule.h\nindex e452919aa4..7a22f71cb9 100644\n--- a/submodule.h\n+++ b/submodule.h\n@@ -40,6 +40,7 @@ struct submodule_update_strategy {\n #define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}\n \n int is_gitmodules_unmerged(const struct index_state *istate);\n+int is_writing_gitmodules_ok(void);\n int is_staging_gitmodules_ok(struct index_state *istate);\n int update_path_in_gitmodules(const char *oldpath, const char *newpath);\n int remove_path_from_gitmodules(const char *path);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 791245f18d..45953f9300 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -161,4 +161,35 @@ test_expect_success 'overwriting unstaged submodules config with \"submodule--hel\n \t)\n '\n \n+test_expect_success 'writeable .gitmodules when it is in the working tree' '\n+\tgit -C super submodule--helper config --check-writeable\n+'\n+\n+test_expect_success 'writeable .gitmodules when it is nowhere in the repository' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n+\t(cd super &&\n+\t\tgit rm .gitmodules &&\n+\t\tgit commit -m \"remove .gitmodules from the current branch\" &&\n+\t\tgit submodule--helper config --check-writeable\n+\t)\n+'\n+\n+test_expect_success 'non-writeable .gitmodules when it is in the index but not in the working tree' '\n+\ttest_when_finished \"git -C super checkout .gitmodules\" &&\n+\t(cd super &&\n+\t\trm -f .gitmodules &&\n+\t\ttest_must_fail git submodule--helper config --check-writeable\n+\t)\n+'\n+\n+test_expect_success 'non-writeable .gitmodules when it is in the current branch but not in the index' '\n+\tORIG=$(git -C super rev-parse HEAD) &&\n+\ttest_when_finished \"git -C super reset --hard $ORIG\" &&\n+\t(cd super &&\n+\t\tgit rm .gitmodules &&\n+\t\ttest_must_fail git submodule--helper config --check-writeable\n+\t)\n+'\n+\n test_done\n-- \n2.19.0\n\n"},{"id":"359684","messageId":"20181005130601.15879-8-ao2@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"[PATCH v6 07/10] t7506: clean up .gitmodules properly before setting up new scenario","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-05T13:05:58Z","receivedAt":"2018-10-05T13:06:22Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"In t/t7506-status-submodule.sh at some point a new scenario is set up to\ntest different things, in particular new submodules are added which are\nmeant to completely replace the previous ones.\n\nHowever before calling the \"git submodule add\" commands for the new\nlayout, the .gitmodules file is removed only from the working tree still\nleaving the previous content in current branch.\n\nThis can break if, in the future, \"git submodule add\" starts\ndifferentiating between the following two cases:\n\n  - .gitmodules is not in the working tree but it is in the current\n    branch (it may not be safe to add new submodules in this case);\n\n  - .gitmodules is neither in the working tree nor anywhere in the\n    current branch (it is safe to add new submodules).\n\nSince the test intends to get rid of .gitmodules anyways, let's\ncompletely remove it from the current branch, to actually start afresh\nin the new scenario.\n\nThis is more future-proof and does not break current tests.\n\nSigned-off-by: Antonio Ospite <ao2@ao2.it>\n---\n t/t7506-status-submodule.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh\nindex 943708fb04..08629a6e70 100755\n--- a/t/t7506-status-submodule.sh\n+++ b/t/t7506-status-submodule.sh\n@@ -325,7 +325,8 @@ test_expect_success 'setup superproject with untracked file in nested submodule'\n \t(\n \t\tcd super &&\n \t\tgit clean -dfx &&\n-\t\trm .gitmodules &&\n+\t\tgit rm .gitmodules &&\n+\t\tgit commit -m \"remove .gitmodules\" &&\n \t\tgit submodule add -f ./sub1 &&\n \t\tgit submodule add -f ./sub2 &&\n \t\tgit submodule add -f ./sub1 sub3 &&\n-- \n2.19.0\n\n"},{"id":"359760","messageId":"CAGZ79kbaeRVBLhYiqzisADHs+Af+c2giXcsCySAEe4jue_rWwA@mail.gmail.com","threadId":"49490","inReplyTo":"20181005130601.15879-9-ao2@ao2.it","subject":"Re: [PATCH v6 08/10] submodule: add a helper to check if it is safe to write to .gitmodules","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-10-05T23:50:10Z","receivedAt":"2018-10-05T23:50:24Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":">  static int module_config(int argc, const char **argv, const char *prefix)\n>  {\n> +       enum {\n> +               CHECK_WRITEABLE = 1\n> +       } command = 0;\n\nCan we have the default named? Then we would only use states\nfrom within the enum?\n"},{"id":"359766","messageId":"20181006111904.cb45cb24e097ad86f7525fcd@ao2.it","threadId":"49490","inReplyTo":"CAGZ79kbaeRVBLhYiqzisADHs+Af+c2giXcsCySAEe4jue_rWwA@mail.gmail.com","subject":"Re: [PATCH v6 08/10] submodule: add a helper to check if it is safe to write to .gitmodules","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-06T09:19:04Z","receivedAt":"2018-10-06T09:19:18Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"On Fri, 5 Oct 2018 16:50:10 -0700\nStefan Beller <sbeller@google.com> wrote:\n\n> >  static int module_config(int argc, const char **argv, const char *prefix)\n> >  {\n> > +       enum {\n> > +               CHECK_WRITEABLE = 1\n> > +       } command = 0;\n> \n> Can we have the default named? Then we would only use states\n> from within the enum?\n\nThe default would mean:\n\n  \"no command passed as a CLI *option*\"\n\nI copied this style from builtin/bisect--helper.c::cmd_bisect__helper()\nand it's also used in builtin/rebase--helper.c\n\nI can add a name for the default enum value but I am not sure what it\nshould be: NO_COMMAND_OPTION, COMMAND_DEFAULT, MODE_DEFAULT?\n\nCiao,\n   Antonio\n\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"},{"id":"359767","messageId":"20181006112020.1651e4b0dd895afd06f93bbf@ao2.it","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"Re: [PATCH v6 00/10] Make submodules work if .gitmodules is not checked out","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-06T09:20:20Z","receivedAt":"2018-10-06T09:21:08Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"On Fri,  5 Oct 2018 15:05:51 +0200\nAntonio Ospite <ao2@ao2.it> wrote:\n\n[...]\n>  t/t7416-submodule-sparse-gitmodules.sh       |  78 ++++++++++\n>  16 files changed, 410 insertions(+), 32 deletions(-)\n>  create mode 100755 t/t7416-submodule-sparse-gitmodules.sh\n\nI just saw that t7416 and t7417 have been added in the latest stable\nrelease, I'll wait some days before sending a v7 which renames the newly\nadded test to t/t7418-submodule-sparse-gitmodules.sh\n\nThanks,\n   Antonio\n\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"},{"id":"359777","messageId":"xmqq36tiwsh7.fsf@gitster-ct.c.googlers.com","threadId":"49490","inReplyTo":"CAGZ79kbaeRVBLhYiqzisADHs+Af+c2giXcsCySAEe4jue_rWwA@mail.gmail.com","subject":"Re: [PATCH v6 08/10] submodule: add a helper to check if it is safe to write to .gitmodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-06T23:44:20Z","receivedAt":"2018-10-06T23:44:28Z","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>>  static int module_config(int argc, const char **argv, const char *prefix)\n>>  {\n>> +       enum {\n>> +               CHECK_WRITEABLE = 1\n>> +       } command = 0;\n>\n> Can we have the default named? Then we would only use states\n> from within the enum?\n\nWhy?  Do we use a half-intelligent \"switch () { case ...: ... }\"\nchecker that would otherwise complain if we handled \"case 0\" in such\na switch statement, or something like that?\n\nAre we going to gain a lot more enum members, by the way?  At this\npoint, this looks more like a\n\n\tunsigned check_writable = 0; /* default is not to check */\n\n\nto me.\n"},{"id":"359818","messageId":"20181008143709.dfcc845ab393c9caea66035e@ao2.it","threadId":"49490","inReplyTo":"xmqq36tiwsh7.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 08/10] submodule: add a helper to check if it is safe to write to .gitmodules","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-08T12:37:09Z","receivedAt":"2018-10-08T12:37:15Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"On Sun, 07 Oct 2018 08:44:20 +0900\nJunio C Hamano <gitster@pobox.com> wrote:\n\n> Stefan Beller <sbeller@google.com> writes:\n> \n> >>  static int module_config(int argc, const char **argv, const char *prefix)\n> >>  {\n> >> +       enum {\n> >> +               CHECK_WRITEABLE = 1\n> >> +       } command = 0;\n> >\n> > Can we have the default named? Then we would only use states\n> > from within the enum?\n> \n> Why?  Do we use a half-intelligent \"switch () { case ...: ... }\"\n> checker that would otherwise complain if we handled \"case 0\" in such\n> a switch statement, or something like that?\n> \n> Are we going to gain a lot more enum members, by the way?  At this\n> point, this looks more like a\n> \n> \tunsigned check_writable = 0; /* default is not to check */\n> \n> to me.\n\nHi,\n\nthe CHECK_WRITEABLE operation is alternative to the get/set ones, not\nan addition, so I can see the rationale behind Stefan's suggestion:\neither have named enums members for all command \"modes\" or for none of\nthem; however other users of enum+OPT_CMDMODE seems to think like the\nenum is for commands passed as *options* and the unnamed default is for\nactions derived from *arguments*. I don't have a strong opinion on this\nmatter, tho, so just tell me what you prefer and I'll do it for v7.\n\nUsing an enum was to have a more explicit syntax in case other commands\nwere going to be added in the future (I imagine \"--stage\" or\n\"--list-all\" as possible additions), and does not affect the generated\ncode, so I though it was worth it.\n\nAnyways, these are really details, let's concentrate on patches 9 and\n10 which deserve much more attention. :)\n\nThanks you,\n   Antonio\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"},{"id":"359874","messageId":"CAGZ79kZTQB29SuB52Efk-j7jX11BRU_RFiX+znttvP2tFRaNvg@mail.gmail.com","threadId":"49490","inReplyTo":"20181005130601.15879-10-ao2@ao2.it","subject":"Re: [PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-10-08T22:19:00Z","receivedAt":"2018-10-08T22:19:15Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"> +test_expect_success 'not writing gitmodules config file when it is not checked out' '\n> +        test_must_fail git -C super submodule--helper config submodule.submodule.url newurl\n\nThis only checks the exit code, do we also want to check for\n\n    test_path_is_missing .gitmodules ?\n\n> +test_expect_success 'initialising submodule when the gitmodules config is not checked out' '\n> +       git -C super submodule init\n> +'\n> +\n> +test_expect_success 'showing submodule summary when the gitmodules config is not checked out' '\n> +       git -C super submodule summary\n> +'\n\nSame for these, is the exit code enough, or do we want to look at\nspecific things?\n\n> +\n> +test_expect_success 'updating submodule when the gitmodules config is not checked out' '\n> +       (cd submodule &&\n> +               echo file2 >file2 &&\n> +               git add file2 &&\n> +               git commit -m \"add file2 to submodule\"\n> +       ) &&\n> +       git -C super submodule update\n\ngit status would want to be clean afterwards?\n"},{"id":"359894","messageId":"xmqqd0sjss91.fsf@gitster-ct.c.googlers.com","threadId":"49490","inReplyTo":"20181005130601.15879-10-ao2@ao2.it","subject":"Re: [PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-09T03:39:38Z","receivedAt":"2018-10-09T03:39:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Antonio Ospite <ao2@ao2.it> writes:\n\n> Finally, add t7416-submodule-sparse-gitmodules.sh to verify that reading\n> from .gitmodules succeeds and that writing to it fails when the file is\n> not checked out.\n> ...\n>  t/t7416-submodule-sparse-gitmodules.sh | 78 ++++++++++++++++++++++++++\n\nThis now triggers test-lint errors as the most recent maintenance\nrelease took t/t7416 for something else.  I'll do s/t7416-/t7418-/g\non the mailbox before running \"git am -s\" on this series.\n\n"},{"id":"359895","messageId":"xmqq5zybsrv3.fsf@gitster-ct.c.googlers.com","threadId":"49490","inReplyTo":"xmqqd0sjss91.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-09T03:48:00Z","receivedAt":"2018-10-09T03:48:06Z","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> Antonio Ospite <ao2@ao2.it> writes:\n>\n>> Finally, add t7416-submodule-sparse-gitmodules.sh to verify that reading\n>> from .gitmodules succeeds and that writing to it fails when the file is\n>> not checked out.\n>> ...\n>>  t/t7416-submodule-sparse-gitmodules.sh | 78 ++++++++++++++++++++++++++\n>\n> This now triggers test-lint errors as the most recent maintenance\n> release took t/t7416 for something else.  I'll do s/t7416-/t7418-/g\n> on the mailbox before running \"git am -s\" on this series.\n\nThis is an unrelated tangent to the topic, but running \"range-diff\"\non what has been queued on 'pu' since mid September and this\nreplacement after doing the renaming was a surprisingly pleasant\nexperience.  In its comparison between 09/10 of the two iterations,\nit showed that 7416's name has been changed to 7418 but otherwise\nthere is no change in the contents of that test script.\n\nFWIW, tbdiff also gets this right, so the pleasant experience was\ninherited without getting broken.  Kudos should go to both Thomas\nand Dscho ;-).\n"},{"id":"360056","messageId":"20181010205645.e1529eff9099805029b1d6ef@ao2.it","threadId":"49490","inReplyTo":"CAGZ79kZTQB29SuB52Efk-j7jX11BRU_RFiX+znttvP2tFRaNvg@mail.gmail.com","subject":"Re: [PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-10T18:56:45Z","receivedAt":"2018-10-10T18:56:50Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"On Mon, 8 Oct 2018 15:19:00 -0700\nStefan Beller <sbeller@google.com> wrote:\n\n> > +test_expect_success 'not writing gitmodules config file when it is not checked out' '\n> > +        test_must_fail git -C super submodule--helper config submodule.submodule.url newurl\n> \n> This only checks the exit code, do we also want to check for\n> \n>     test_path_is_missing .gitmodules ?\n>\n\nOK, I agree, let's re-check also *after* we tried and failed to set\na config value, just to be sure that the code does not get accidentally\nchanged in the future to create the file. I'll add the check.\n\n> > +test_expect_success 'initialising submodule when the gitmodules config is not checked out' '\n> > +       git -C super submodule init\n> > +'\n> > +\n> > +test_expect_success 'showing submodule summary when the gitmodules config is not checked out' '\n> > +       git -C super submodule summary\n> > +'\n> \n> Same for these, is the exit code enough, or do we want to look at\n> specific things?\n>\n\nExcept for the \"summary\" test which was not even exercising the\nconfig_from_gitmodule path,  checking exist status should be sufficient\nto verify that \"submodule--helper config\" does not fail, but we can\nsurely do better.\n\nI will add checks to confirm that not only the commands exited without\nerrors but they also achieved the desired effect, to validate the actual\nhigh-level use case advertised by the test file. This should be more\nfuture-proof.\n\nAnd I think I'll merge the summary and the update tests.\n\n> > +\n> > +test_expect_success 'updating submodule when the gitmodules config is not checked out' '\n> > +       (cd submodule &&\n> > +               echo file2 >file2 &&\n> > +               git add file2 &&\n> > +               git commit -m \"add file2 to submodule\"\n> > +       ) &&\n> > +       git -C super submodule update\n> \n> git status would want to be clean afterwards?\n\nMmh, this should have been \"submodule update --remote\" in the first\nplace to have any effect, I'll take the chance and rewrite this test in\na different way and also check the effect of the update operation, and\nthe repository status.\n\nI'll be something like this:\n\nORIG_SUBMODULE=$(git -C submodule rev-parse HEAD)\nORIG_UPSTREAM=$(git -C upstream rev-parse HEAD)\nORIG_SUPER=$(git -C super rev-parse HEAD)\n\ntest_expect_success 're-updating submodule when the gitmodules config is not checked out' '\n\ttest_when_finished \"git -C submodule reset --hard $ORIG_SUBMODULE;\n\t                    git -C upstream reset --hard $ORIG_UPSTREAM;\n\t                    git -C super reset --hard $ORIG_SUPER;\n\t                    git -C upstream submodule update --remote;\n\t                    git -C super pull;\n\t                    git -C super submodule update --remote\" &&\n\t(cd submodule &&\n\t\techo file2 >file2 &&\n\t\tgit add file2 &&\n\t\ttest_tick &&\n\t\tgit commit -m \"add file2 to submodule\"\n\t) &&\n\t(cd upstream &&\n\t\tgit submodule update --remote &&\n\t\tgit add submodule &&\n\t\ttest_tick &&\n\t\tgit commit -m \"Update submodule\"\n\t) &&\n\tgit -C super pull &&\n\t# The --for-status options reads the gitmdoules config\n\tgit -C super submodule summary --for-status >actual &&\n\tcat >expect <<-\\EOF &&\n\t* submodule 951c301...a939200 (1):\n\t  < add file2 to submodule\n\t\n\tEOF\n\ttest_cmp expect actual &&\n\t# Test that the update actually succeeds\n\ttest_path_is_missing super/submodule/file2 &&\n\tgit -C super submodule update &&\n\ttest_cmp submodule/file2 super/submodule/file2 &&\n\tgit -C super status --short >output &&\n\ttest_must_be_empty output\n'\n\nMaybe a little overkill?\n\nThe \"upstream\" repo will be added in test 1 to better clarify the roles\nof the involved repositories.\n\nThe commit ids should be stable because of test_tick, shouldn't they?\n\nThanks for the comments, they helped improving the quality of the tests\nonce again.\n\nI'll wait a few days before sending a v7, hopefully someone will find\ntime to take another look at patch 9 and comment also on patch 10, and\ngive an opinion on the \"mergeability\" status of the whole patchset.\n\nCiao ciao,\n   Antonio\n\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"},{"id":"360103","messageId":"CAGZ79kZ5HRcTsfWRbOW-kQg2UFBf6suc+7px_FbCSPwcOE5w3g@mail.gmail.com","threadId":"49490","inReplyTo":"20181010205645.e1529eff9099805029b1d6ef@ao2.it","subject":"Re: [PATCH v6 09/10] submodule: support reading .gitmodules when it's not in the working tree","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-10-10T22:55:15Z","receivedAt":"2018-10-10T22:55:31Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Wed, Oct 10, 2018 at 11:56 AM Antonio Ospite <ao2@ao2.it> wrote:\n>\n> On Mon, 8 Oct 2018 15:19:00 -0700\n> Stefan Beller <sbeller@google.com> wrote:\n>\n> > > +test_expect_success 'not writing gitmodules config file when it is not checked out' '\n> > > +        test_must_fail git -C super submodule--helper config submodule.submodule.url newurl\n> >\n> > This only checks the exit code, do we also want to check for\n> >\n> >     test_path_is_missing .gitmodules ?\n> >\n>\n> OK, I agree, let's re-check also *after* we tried and failed to set\n> a config value, just to be sure that the code does not get accidentally\n> changed in the future to create the file. I'll add the check.\n>\n> > > +test_expect_success 'initialising submodule when the gitmodules config is not checked out' '\n> > > +       git -C super submodule init\n> > > +'\n> > > +\n> > > +test_expect_success 'showing submodule summary when the gitmodules config is not checked out' '\n> > > +       git -C super submodule summary\n> > > +'\n> >\n> > Same for these, is the exit code enough, or do we want to look at\n> > specific things?\n> >\n>\n> Except for the \"summary\" test which was not even exercising the\n> config_from_gitmodule path,  checking exist status should be sufficient\n> to verify that \"submodule--helper config\" does not fail, but we can\n> surely do better.\n>\n> I will add checks to confirm that not only the commands exited without\n> errors but they also achieved the desired effect, to validate the actual\n> high-level use case advertised by the test file. This should be more\n> future-proof.\n>\n> And I think I'll merge the summary and the update tests.\n>\n> > > +\n> > > +test_expect_success 'updating submodule when the gitmodules config is not checked out' '\n> > > +       (cd submodule &&\n> > > +               echo file2 >file2 &&\n> > > +               git add file2 &&\n> > > +               git commit -m \"add file2 to submodule\"\n> > > +       ) &&\n> > > +       git -C super submodule update\n> >\n> > git status would want to be clean afterwards?\n>\n> Mmh, this should have been \"submodule update --remote\" in the first\n> place to have any effect, I'll take the chance and rewrite this test in\n> a different way and also check the effect of the update operation, and\n> the repository status.\n>\n> I'll be something like this:\n>\n> ORIG_SUBMODULE=$(git -C submodule rev-parse HEAD)\n> ORIG_UPSTREAM=$(git -C upstream rev-parse HEAD)\n> ORIG_SUPER=$(git -C super rev-parse HEAD)\n>\n> test_expect_success 're-updating submodule when the gitmodules config is not checked out' '\n>         test_when_finished \"git -C submodule reset --hard $ORIG_SUBMODULE;\n>                             git -C upstream reset --hard $ORIG_UPSTREAM;\n>                             git -C super reset --hard $ORIG_SUPER;\n>                             git -C upstream submodule update --remote;\n>                             git -C super pull;\n>                             git -C super submodule update --remote\" &&\n>         (cd submodule &&\n>                 echo file2 >file2 &&\n>                 git add file2 &&\n>                 test_tick &&\n>                 git commit -m \"add file2 to submodule\"\n>         ) &&\n>         (cd upstream &&\n>                 git submodule update --remote &&\n>                 git add submodule &&\n>                 test_tick &&\n>                 git commit -m \"Update submodule\"\n>         ) &&\n>         git -C super pull &&\n>         # The --for-status options reads the gitmdoules config\n\ngitmodules\n\n>         git -C super submodule summary --for-status >actual &&\n>         cat >expect <<-\\EOF &&\n>         * submodule 951c301...a939200 (1):\n\nhardcoding hash values burdens the plan to migrate to another\nhash function,\n\n    rev1=$(git -C submodule rev-parse --short HEAD^)\n    rev2=$(git -C submodule rev-parse --short HEAD)\n\nand then use ${rev1}..${rev2} ?\n\n\n>           < add file2 to submodule\n>\n>         EOF\n>         test_cmp expect actual &&\n>         # Test that the update actually succeeds\n>         test_path_is_missing super/submodule/file2 &&\n>         git -C super submodule update &&\n>         test_cmp submodule/file2 super/submodule/file2 &&\n>         git -C super status --short >output &&\n>         test_must_be_empty output\n> '\n>\n> Maybe a little overkill?\n\nWow, very thorough! You might call it overkill, but now that you have it...\n\n> The \"upstream\" repo will be added in test 1 to better clarify the roles\n> of the involved repositories.\n>\n> The commit ids should be stable because of test_tick, shouldn't they?\n\nYes, but see\nDocumentation/technical/hash-function-transition.txt\nthat a couple people are working on. Let's be nice to them. :-)\n\nStefan\n"},{"id":"361489","messageId":"xmqqd0ryiflc.fsf@gitster-ct.c.googlers.com","threadId":"49490","inReplyTo":"20181005130601.15879-1-ao2@ao2.it","subject":"Re: [PATCH v6 00/10] Make submodules work if .gitmodules is not checked out","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-25T08:40:47Z","receivedAt":"2018-10-25T08:40:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Antonio Ospite <ao2@ao2.it> writes:\n\n> this series teaches git to try and read the .gitmodules file from the\n> index (:.gitmodules) or from the current branch (HEAD:.gitmodules) when\n> the file is not readily available in the working tree.\n\nWhat you said in [*1*] the discussion on [09/10] sounded like you\nare preparing an update of the series, so the topic is marked as\n\"Expecting a reroll\" in the recent \"What's cooking\" report.  At\nleast one topic now depends on the enhancement this topic makes, so\nI'd like to know what the current status and ETA of the reroll would\nbe, in order to sort-of act as a traffic cop.\n\nYour answer could even be \"I have been too busy, and I do not think\nan update will come for some time\"---in other words, I do not mean\nto tell you to drop other things and work on this instead.\n\nIf you are too busy, I can even see if other stakeholders\n(e.g. Stefan, whose topic now depends on this series) can take it\nover and update it after re-reading the discussion on the latest\nround.\n\nThanks.\n\n\n[Reference]\n\n*1* http://public-inbox.org/git/20181010205645.e1529eff9099805029b1d6ef@ao2.it/\n"},{"id":"361513","messageId":"20181025152059.78c488d5b24aa2b0b6817259@ao2.it","threadId":"49490","inReplyTo":"xmqqd0ryiflc.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v6 00/10] Make submodules work if .gitmodules is not checked out","fromName":"Antonio Ospite","fromEmail":"ao2@ao2.it","sentAt":"2018-10-25T13:20:59Z","receivedAt":"2018-10-25T13:21:04Z","isPatch":true,"sender":{"key":"ao2@ao2.it","avatar":"https://avatars.githubusercontent.com/u/1249395?v=4"},"body":"On Thu, 25 Oct 2018 17:40:47 +0900\nJunio C Hamano <gitster@pobox.com> wrote:\n\n> Antonio Ospite <ao2@ao2.it> writes:\n> \n> > this series teaches git to try and read the .gitmodules file from the\n> > index (:.gitmodules) or from the current branch (HEAD:.gitmodules) when\n> > the file is not readily available in the working tree.\n> \n> What you said in [*1*] the discussion on [09/10] sounded like you\n> are preparing an update of the series, so the topic is marked as\n> \"Expecting a reroll\" in the recent \"What's cooking\" report.  At\n> least one topic now depends on the enhancement this topic makes, so\n> I'd like to know what the current status and ETA of the reroll would\n> be, in order to sort-of act as a traffic cop.\n> \n\nHi Junio,\n\nI can send a v7 later today.\n\nIt will only contain the improvements to\n7416-submodule-sparse-gitmodules.sh as discussed in [*1*], it won't\ncontain changes to patch 8 as motivated in\nhttps://public-inbox.org/git/20181008143709.dfcc845ab393c9caea66035e@ao2.it/\n\nI will also leave patch 10 unchanged, improvements can be made in\nfollow-up patches.\n\nBTW, what is the new topic which depends on this one?\n\nThank you,\n   Antonio\n\n> [Reference]\n> \n> *1* http://public-inbox.org/git/20181010205645.e1529eff9099805029b1d6ef@ao2.it/\n\n\n-- \nAntonio Ospite\nhttps://ao2.it\nhttps://twitter.com/ao2it\n\nA: Because it messes up the order in which people normally read text.\n   See http://en.wikipedia.org/wiki/Posting_style\nQ: Why is top-posting such a bad thing?\n"}]}