{"thread":{"id":"47128","subject":"[PATCH] Tests: document test_submodule_{,forced_}switch()","startedAt":"2017-11-06T23:50:39Z","lastAt":"2017-11-07T18:45:22Z","messageCount":4,"participants":["Jonathan Tan","Junio C Hamano","Stefan Beller"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"331951","messageId":"20171106235021.113358-1-jonathantanmy@google.com","threadId":"47128","inReplyTo":null,"subject":"[PATCH] Tests: document test_submodule_{,forced_}switch()","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2017-11-06T23:50:21Z","receivedAt":"2017-11-06T23:50:39Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"Factor out the commonalities from test_submodule_switch() and\ntest_submodule_forced_switch() in lib-submodule-update.sh, and document\ntheir usage.\n\nThis also makes explicit (through the KNOWN_FAILURE_FORCED_SWITCH_TESTS\nvariable) the fact that, currently, all functionality tested using\ntest_submodule_forced_switch() do not correctly handle the situation in\nwhich a submodule is replaced with an ordinary directory.\n\nSigned-off-by: Jonathan Tan <jonathantanmy@google.com>\n---\nI find tests that use lib-submodule-update.sh difficult to understand\ndue to the lack of clarity of what test_submodule_switch() and others do\nwith their argument - I hope this will make things easier for future\nreaders.\n---\n t/lib-submodule-update.sh | 250 +++++++++-------------------------------------\n 1 file changed, 46 insertions(+), 204 deletions(-)\n\ndiff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh\nindex 2d26f8680..ca428fdc9 100755\n--- a/t/lib-submodule-update.sh\n+++ b/t/lib-submodule-update.sh\n@@ -306,9 +306,9 @@ test_submodule_content () {\n # to protect the history!\n #\n \n-# Test that submodule contents are currently not updated when switching\n-# between commits that change a submodule.\n-test_submodule_switch () {\n+# Internal function; use test_submodule_switch() or\n+# test_submodule_forced_switch() instead.\n+test_submodule_switch_common() {\n \tcommand=\"$1\"\n \t######################### Appearing submodule #########################\n \t# Switching to a commit letting a submodule appear creates empty dir ...\n@@ -332,7 +332,7 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/add_sub1\n \t\t)\n \t'\n-\t# ... and doesn't care if it already exists ...\n+\t# ... and doesn't care if it already exists.\n \ttest_expect_$RESULT \"$command: added submodule leaves existing empty directory alone\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n@@ -347,19 +347,6 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/add_sub1\n \t\t)\n \t'\n-\t# ... unless there is an untracked file in its place.\n-\ttest_expect_success \"$command: added submodule doesn't remove untracked unignored file with same name\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to no_submodule &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\t>sub1 &&\n-\t\t\ttest_must_fail $command add_sub1 &&\n-\t\t\ttest_superproject_content origin/no_submodule &&\n-\t\t\ttest_must_be_empty sub1\n-\t\t)\n-\t'\n \t# Replacing a tracked file with a submodule produces an empty\n \t# directory ...\n \ttest_expect_$RESULT \"$command: replace tracked file with submodule creates empty directory\" '\n@@ -441,6 +428,11 @@ test_submodule_switch () {\n \t\t# submodule files with the newly checked out ones in the\n \t\t# directory of the same name while it shouldn't.\n \t\tRESULT=\"failure\"\n+\telif test \"$KNOWN_FAILURE_FORCED_SWITCH_TESTS\" = 1\n+\tthen\n+\t\t# All existing tests that use test_submodule_forced_switch()\n+\t\t# require this.\n+\t\tRESULT=\"failure\"\n \telse\n \t\tRESULT=\"success\"\n \tfi\n@@ -522,7 +514,6 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/modify_sub1\n \t\t)\n \t'\n-\n \t# Updating a submodule to an invalid sha1 doesn't update the\n \t# submodule's work tree, subsequent update will fail\n \ttest_expect_$RESULT \"$command: modified submodule does not update submodule work tree to invalid commit\" '\n@@ -538,59 +529,53 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/add_sub1\n \t\t)\n \t'\n-\t# Updating a submodule from an invalid sha1 doesn't update the\n-\t# submodule's work tree, subsequent update will succeed\n-\ttest_expect_$RESULT \"$command: modified submodule does not update submodule work tree from invalid commit\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to invalid_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t valid_sub1 origin/valid_sub1 &&\n-\t\t\t$command valid_sub1 &&\n-\t\t\ttest_superproject_content origin/valid_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/valid_sub1\n-\t\t)\n-\t'\n }\n \n-# Test that submodule contents are currently not updated when switching\n-# between commits that change a submodule, but throwing away local changes in\n-# the superproject is allowed.\n-test_submodule_forced_switch () {\n+# Declares and invokes several tests that, in various situations, checks that\n+# the provided transition function:\n+#  - succeeds in updating the worktree and index of a superproject to a target\n+#    commit, or fails atomically (depending on the test situation)\n+#  - if succeeds, the contents of submodule directories are unchanged\n+#  - if succeeds, once \"git submodule update\" is invoked, the contents of\n+#    submodule directories are updated\n+#\n+# Use as follows:\n+#\n+# my_func () {\n+#   target=$1\n+#   # Do something here that updates the worktree and index to match target,\n+#   # but not any submodule directories.\n+# }\n+# test_submodule_switch \"my_func\"\n+test_submodule_switch () {\n \tcommand=\"$1\"\n-\t######################### Appearing submodule #########################\n-\t# Switching to a commit letting a submodule appear creates empty dir ...\n-\ttest_expect_success \"$command: added submodule creates empty directory\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to no_submodule &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\t$command add_sub1 &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... and doesn't care if it already exists ...\n-\ttest_expect_success \"$command: added submodule leaves existing empty directory alone\" '\n+\ttest_submodule_switch_common \"$command\"\n+\n+\t# An empty directory does not prevent the creation of a submodule of\n+\t# the same name, but a file does.\n+\ttest_expect_success \"$command: added submodule doesn't remove untracked unignored file with same name\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n \t\t(\n \t\t\tcd submodule_update &&\n \t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\tmkdir sub1 &&\n-\t\t\t$command add_sub1 &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n+\t\t\t>sub1 &&\n+\t\t\ttest_must_fail $command add_sub1 &&\n+\t\t\ttest_superproject_content origin/no_submodule &&\n+\t\t\ttest_must_be_empty sub1\n \t\t)\n \t'\n-\t# ... unless there is an untracked file in its place.\n+}\n+\n+# Same as test_submodule_switch(), except that throwing away local changes in\n+# the superproject is allowed.\n+test_submodule_forced_switch () {\n+\tcommand=\"$1\"\n+\tKNOWN_FAILURE_FORCED_SWITCH_TESTS=1\n+\ttest_submodule_switch_common \"$command\"\n+\n+\t# When forced, a file in the superproject does not prevent creating a\n+\t# submodule of the same name.\n \ttest_expect_success \"$command: added submodule does remove untracked unignored file with same name when forced\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n@@ -603,150 +588,7 @@ test_submodule_forced_switch () {\n \t\t\ttest_dir_is_empty sub1\n \t\t)\n \t'\n-\t# Replacing a tracked file with a submodule produces an empty\n-\t# directory ...\n-\ttest_expect_success \"$command: replace tracked file with submodule creates empty directory\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to replace_sub1_with_file &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&\n-\t\t\t$command replace_file_with_sub1 &&\n-\t\t\ttest_superproject_content origin/replace_file_with_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/replace_file_with_sub1\n-\t\t)\n-\t'\n-\t# ... as does removing a directory with tracked files with a\n-\t# submodule.\n-\ttest_expect_success \"$command: replace directory with submodule\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to replace_sub1_with_directory &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&\n-\t\t\t$command replace_directory_with_sub1 &&\n-\t\t\ttest_superproject_content origin/replace_directory_with_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/replace_directory_with_sub1\n-\t\t)\n-\t'\n \n-\t######################## Disappearing submodule #######################\n-\t# Removing a submodule doesn't remove its work tree ...\n-\ttest_expect_success \"$command: removed submodule leaves submodule directory and its contents in place\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n-\t\t\t$command remove_sub1 &&\n-\t\t\ttest_superproject_content origin/remove_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... especially when it contains a .git directory.\n-\ttest_expect_success \"$command: removed submodule leaves submodule containing a .git directory alone\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\t$command remove_sub1 &&\n-\t\t\ttest_superproject_content origin/remove_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# Replacing a submodule with files in a directory must fail as the\n-\t# submodule work tree isn't removed ...\n-\ttest_expect_failure \"$command: replace submodule with a directory must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n-\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... especially when it contains a .git directory.\n-\ttest_expect_failure \"$command: replace submodule containing a .git directory with a directory must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# Replacing it with a file must fail as it could throw away any local\n-\t# work tree changes ...\n-\ttest_expect_failure \"$command: replace submodule with a file must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n-\t\t\ttest_must_fail $command replace_sub1_with_file &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... or even destroy unpushed parts of submodule history if that\n-\t# still uses a .git directory.\n-\ttest_expect_failure \"$command: replace submodule containing a .git directory with a file must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\ttest_must_fail $command replace_sub1_with_file &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\n-\t########################## Modified submodule #########################\n-\t# Updating a submodule sha1 doesn't update the submodule's work tree\n-\ttest_expect_success \"$command: modified submodule does not update submodule work tree\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t modify_sub1 origin/modify_sub1 &&\n-\t\t\t$command modify_sub1 &&\n-\t\t\ttest_superproject_content origin/modify_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n-\t\t\tgit submodule update &&\n-\t\t\ttest_submodule_content sub1 origin/modify_sub1\n-\t\t)\n-\t'\n-\t# Updating a submodule to an invalid sha1 doesn't update the\n-\t# submodule's work tree, subsequent update will fail\n-\ttest_expect_success \"$command: modified submodule does not update submodule work tree to invalid commit\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t invalid_sub1 origin/invalid_sub1 &&\n-\t\t\t$command invalid_sub1 &&\n-\t\t\ttest_superproject_content origin/invalid_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n-\t\t\ttest_must_fail git submodule update &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n \t# Updating a submodule from an invalid sha1 doesn't update the\n \t# submodule's work tree, subsequent update will succeed\n \ttest_expect_success \"$command: modified submodule does not update submodule work tree from invalid commit\" '\n-- \n2.15.0.403.gc27cc4dac6-goog\n\n"},{"id":"331964","messageId":"xmqq8tfihn3a.fsf@gitster.mtv.corp.google.com","threadId":"47128","inReplyTo":"20171106235021.113358-1-jonathantanmy@google.com","subject":"Re: [PATCH] Tests: document test_submodule_{,forced_}switch()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-11-07T01:52:25Z","receivedAt":"2017-11-07T01:52:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Tan <jonathantanmy@google.com> writes:\n\n> Factor out the commonalities from test_submodule_switch() and\n> test_submodule_forced_switch() in lib-submodule-update.sh, and document\n> their usage.\n>\n> This also makes explicit (through the KNOWN_FAILURE_FORCED_SWITCH_TESTS\n> variable) the fact that, currently, all functionality tested using\n> test_submodule_forced_switch() do not correctly handle the situation in\n> which a submodule is replaced with an ordinary directory.\n>\n> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>\n> ---\n> I find tests that use lib-submodule-update.sh difficult to understand\n> due to the lack of clarity of what test_submodule_switch() and others do\n> with their argument - I hope this will make things easier for future\n> readers.\n> ---\n>  t/lib-submodule-update.sh | 250 +++++++++-------------------------------------\n>  1 file changed, 46 insertions(+), 204 deletions(-)\n\nI suspect that the benefit of this is a lot larger than \"document\" a\ntest helper function or two ;-)  \"document & clean-up\", perhaps?\n\n> -\t# ... unless there is an untracked file in its place.\n> -\ttest_expect_success \"$command: added submodule doesn't remove untracked unignored file with same name\" '\n> -\t\tprolog &&\n> -\t\treset_work_tree_to no_submodule &&\n> -\t\t(\n> -\t\t\tcd submodule_update &&\n> -\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n> -\t\t\t>sub1 &&\n> -\t\t\ttest_must_fail $command add_sub1 &&\n> -\t\t\ttest_superproject_content origin/no_submodule &&\n> -\t\t\ttest_must_be_empty sub1\n> -\t\t)\n> -\t'\n\nThis is not included in the _common thing, but is added back to the\nupdated _switch and _forced_switch, both of which call the _common\nthing, at the end.\n\n> @@ -538,59 +529,53 @@ test_submodule_switch () {\n>  \t\t\ttest_submodule_content sub1 origin/add_sub1\n>  \t\t)\n>  \t'\n> -\t# Updating a submodule from an invalid sha1 doesn't update the\n> -\t# submodule's work tree, subsequent update will succeed\n> -\ttest_expect_$RESULT \"$command: modified submodule does not update submodule work tree from invalid commit\" '\n> -\t\tprolog &&\n> -\t\treset_work_tree_to invalid_sub1 &&\n> -\t\t(\n> -\t\t\tcd submodule_update &&\n> -\t\t\tgit branch -t valid_sub1 origin/valid_sub1 &&\n> -\t\t\t$command valid_sub1 &&\n> -\t\t\ttest_superproject_content origin/valid_sub1 &&\n> -\t\t\ttest_dir_is_empty sub1 &&\n> -\t\t\tgit submodule update --init --recursive &&\n> -\t\t\ttest_submodule_content sub1 origin/valid_sub1\n> -\t\t)\n> -\t'\n\nThis piece seems to have been lost from the updated code; _common\ndoes not inherit this test, and _switch does not add it back after\ncalling _common.  Its copy does appear in _forced_switch, though.\n\n\nI didn't compare the before-and-after with fine toothed comb, but\na cursory look didn't find anything glaringly questionable other\nthan the above.\n\n\n"},{"id":"332018","messageId":"CAGZ79kZ3yaKGh2g2QosdzDigi4uXsuRs_v2imL8kPEo8a+qeXg@mail.gmail.com","threadId":"47128","inReplyTo":"xmqq8tfihn3a.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] Tests: document test_submodule_{,forced_}switch()","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-11-07T17:27:43Z","receivedAt":"2017-11-07T17:27:49Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Nov 6, 2017 at 5:52 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jonathan Tan <jonathantanmy@google.com> writes:\n>\n>> Factor out the commonalities from test_submodule_switch() and\n>> test_submodule_forced_switch() in lib-submodule-update.sh, and document\n>> their usage.\n>>\n>> This also makes explicit (through the KNOWN_FAILURE_FORCED_SWITCH_TESTS\n>> variable) the fact that, currently, all functionality tested using\n>> test_submodule_forced_switch() do not correctly handle the situation in\n>> which a submodule is replaced with an ordinary directory.\n>>\n>> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>\n>> ---\n>> I find tests that use lib-submodule-update.sh difficult to understand\n>> due to the lack of clarity of what test_submodule_switch() and others do\n>> with their argument - I hope this will make things easier for future\n>> readers.\n>> ---\n>>  t/lib-submodule-update.sh | 250 +++++++++-------------------------------------\n>>  1 file changed, 46 insertions(+), 204 deletions(-)\n>\n> I suspect that the benefit of this is a lot larger than \"document\" a\n> test helper function or two ;-)  \"document & clean-up\", perhaps?\n\nIt is.\n\n>\n> I didn't compare the before-and-after with fine toothed comb, but\n> a cursory look didn't find anything glaringly questionable other\n> than the above.\n>\n\nI have reviewed the patch and thinks it withstands the test of a fine comb.\n"},{"id":"332020","messageId":"20171107184509.136564-1-jonathantanmy@google.com","threadId":"47128","inReplyTo":"xmqq8tfihn3a.fsf@gitster.mtv.corp.google.com","subject":"[PATCH v2] Tests: clean up and document submodule helpers","fromName":"Jonathan Tan","fromEmail":"jonathantanmy@google.com","sentAt":"2017-11-07T18:45:08Z","receivedAt":"2017-11-07T18:45:22Z","isPatch":true,"sender":{"key":"jonathantanmy@fastmail.com","avatar":null},"body":"Factor out the commonalities from test_submodule_switch() and\ntest_submodule_forced_switch() in lib-submodule-update.sh, and document\ntheir usage.\n\nThis also makes explicit (through the KNOWN_FAILURE_FORCED_SWITCH_TESTS\nvariable) the fact that, currently, all functionality tested using\ntest_submodule_forced_switch() do not correctly handle the situation in\nwhich a submodule is replaced with an ordinary directory.\n\nSigned-off-by: Jonathan Tan <jonathantanmy@google.com>\n---\nThanks for the review.\n\nChange from v1:\n\n- changed commit message title\n- moved a test to the common function, so that it runs both on\n  test_submodule_switch and test_submodule_forced_switch\n---\n t/lib-submodule-update.sh | 251 +++++++++-------------------------------------\n 1 file changed, 46 insertions(+), 205 deletions(-)\n\ndiff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh\nindex 2d26f8680..bb94c2320 100755\n--- a/t/lib-submodule-update.sh\n+++ b/t/lib-submodule-update.sh\n@@ -306,9 +306,9 @@ test_submodule_content () {\n # to protect the history!\n #\n \n-# Test that submodule contents are currently not updated when switching\n-# between commits that change a submodule.\n-test_submodule_switch () {\n+# Internal function; use test_submodule_switch() or\n+# test_submodule_forced_switch() instead.\n+test_submodule_switch_common() {\n \tcommand=\"$1\"\n \t######################### Appearing submodule #########################\n \t# Switching to a commit letting a submodule appear creates empty dir ...\n@@ -332,7 +332,7 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/add_sub1\n \t\t)\n \t'\n-\t# ... and doesn't care if it already exists ...\n+\t# ... and doesn't care if it already exists.\n \ttest_expect_$RESULT \"$command: added submodule leaves existing empty directory alone\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n@@ -347,19 +347,6 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/add_sub1\n \t\t)\n \t'\n-\t# ... unless there is an untracked file in its place.\n-\ttest_expect_success \"$command: added submodule doesn't remove untracked unignored file with same name\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to no_submodule &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\t>sub1 &&\n-\t\t\ttest_must_fail $command add_sub1 &&\n-\t\t\ttest_superproject_content origin/no_submodule &&\n-\t\t\ttest_must_be_empty sub1\n-\t\t)\n-\t'\n \t# Replacing a tracked file with a submodule produces an empty\n \t# directory ...\n \ttest_expect_$RESULT \"$command: replace tracked file with submodule creates empty directory\" '\n@@ -441,6 +428,11 @@ test_submodule_switch () {\n \t\t# submodule files with the newly checked out ones in the\n \t\t# directory of the same name while it shouldn't.\n \t\tRESULT=\"failure\"\n+\telif test \"$KNOWN_FAILURE_FORCED_SWITCH_TESTS\" = 1\n+\tthen\n+\t\t# All existing tests that use test_submodule_forced_switch()\n+\t\t# require this.\n+\t\tRESULT=\"failure\"\n \telse\n \t\tRESULT=\"success\"\n \tfi\n@@ -522,7 +514,6 @@ test_submodule_switch () {\n \t\t\ttest_submodule_content sub1 origin/modify_sub1\n \t\t)\n \t'\n-\n \t# Updating a submodule to an invalid sha1 doesn't update the\n \t# submodule's work tree, subsequent update will fail\n \ttest_expect_$RESULT \"$command: modified submodule does not update submodule work tree to invalid commit\" '\n@@ -555,42 +546,51 @@ test_submodule_switch () {\n \t'\n }\n \n-# Test that submodule contents are currently not updated when switching\n-# between commits that change a submodule, but throwing away local changes in\n-# the superproject is allowed.\n-test_submodule_forced_switch () {\n+# Declares and invokes several tests that, in various situations, checks that\n+# the provided transition function:\n+#  - succeeds in updating the worktree and index of a superproject to a target\n+#    commit, or fails atomically (depending on the test situation)\n+#  - if succeeds, the contents of submodule directories are unchanged\n+#  - if succeeds, once \"git submodule update\" is invoked, the contents of\n+#    submodule directories are updated\n+#\n+# Use as follows:\n+#\n+# my_func () {\n+#   target=$1\n+#   # Do something here that updates the worktree and index to match target,\n+#   # but not any submodule directories.\n+# }\n+# test_submodule_switch \"my_func\"\n+test_submodule_switch () {\n \tcommand=\"$1\"\n-\t######################### Appearing submodule #########################\n-\t# Switching to a commit letting a submodule appear creates empty dir ...\n-\ttest_expect_success \"$command: added submodule creates empty directory\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to no_submodule &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\t$command add_sub1 &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... and doesn't care if it already exists ...\n-\ttest_expect_success \"$command: added submodule leaves existing empty directory alone\" '\n+\ttest_submodule_switch_common \"$command\"\n+\n+\t# An empty directory does not prevent the creation of a submodule of\n+\t# the same name, but a file does.\n+\ttest_expect_success \"$command: added submodule doesn't remove untracked unignored file with same name\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n \t\t(\n \t\t\tcd submodule_update &&\n \t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n-\t\t\tmkdir sub1 &&\n-\t\t\t$command add_sub1 &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n+\t\t\t>sub1 &&\n+\t\t\ttest_must_fail $command add_sub1 &&\n+\t\t\ttest_superproject_content origin/no_submodule &&\n+\t\t\ttest_must_be_empty sub1\n \t\t)\n \t'\n-\t# ... unless there is an untracked file in its place.\n+}\n+\n+# Same as test_submodule_switch(), except that throwing away local changes in\n+# the superproject is allowed.\n+test_submodule_forced_switch () {\n+\tcommand=\"$1\"\n+\tKNOWN_FAILURE_FORCED_SWITCH_TESTS=1\n+\ttest_submodule_switch_common \"$command\"\n+\n+\t# When forced, a file in the superproject does not prevent creating a\n+\t# submodule of the same name.\n \ttest_expect_success \"$command: added submodule does remove untracked unignored file with same name when forced\" '\n \t\tprolog &&\n \t\treset_work_tree_to no_submodule &&\n@@ -603,165 +603,6 @@ test_submodule_forced_switch () {\n \t\t\ttest_dir_is_empty sub1\n \t\t)\n \t'\n-\t# Replacing a tracked file with a submodule produces an empty\n-\t# directory ...\n-\ttest_expect_success \"$command: replace tracked file with submodule creates empty directory\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to replace_sub1_with_file &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&\n-\t\t\t$command replace_file_with_sub1 &&\n-\t\t\ttest_superproject_content origin/replace_file_with_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/replace_file_with_sub1\n-\t\t)\n-\t'\n-\t# ... as does removing a directory with tracked files with a\n-\t# submodule.\n-\ttest_expect_success \"$command: replace directory with submodule\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to replace_sub1_with_directory &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&\n-\t\t\t$command replace_directory_with_sub1 &&\n-\t\t\ttest_superproject_content origin/replace_directory_with_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/replace_directory_with_sub1\n-\t\t)\n-\t'\n-\n-\t######################## Disappearing submodule #######################\n-\t# Removing a submodule doesn't remove its work tree ...\n-\ttest_expect_success \"$command: removed submodule leaves submodule directory and its contents in place\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n-\t\t\t$command remove_sub1 &&\n-\t\t\ttest_superproject_content origin/remove_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... especially when it contains a .git directory.\n-\ttest_expect_success \"$command: removed submodule leaves submodule containing a .git directory alone\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\t$command remove_sub1 &&\n-\t\t\ttest_superproject_content origin/remove_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# Replacing a submodule with files in a directory must fail as the\n-\t# submodule work tree isn't removed ...\n-\ttest_expect_failure \"$command: replace submodule with a directory must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n-\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... especially when it contains a .git directory.\n-\ttest_expect_failure \"$command: replace submodule containing a .git directory with a directory must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# Replacing it with a file must fail as it could throw away any local\n-\t# work tree changes ...\n-\ttest_expect_failure \"$command: replace submodule with a file must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n-\t\t\ttest_must_fail $command replace_sub1_with_file &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# ... or even destroy unpushed parts of submodule history if that\n-\t# still uses a .git directory.\n-\ttest_expect_failure \"$command: replace submodule containing a .git directory with a file must fail\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n-\t\t\treplace_gitfile_with_git_dir sub1 &&\n-\t\t\ttest_must_fail $command replace_sub1_with_file &&\n-\t\t\ttest_superproject_content origin/add_sub1 &&\n-\t\t\ttest_git_directory_is_unchanged sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\n-\t########################## Modified submodule #########################\n-\t# Updating a submodule sha1 doesn't update the submodule's work tree\n-\ttest_expect_success \"$command: modified submodule does not update submodule work tree\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t modify_sub1 origin/modify_sub1 &&\n-\t\t\t$command modify_sub1 &&\n-\t\t\ttest_superproject_content origin/modify_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n-\t\t\tgit submodule update &&\n-\t\t\ttest_submodule_content sub1 origin/modify_sub1\n-\t\t)\n-\t'\n-\t# Updating a submodule to an invalid sha1 doesn't update the\n-\t# submodule's work tree, subsequent update will fail\n-\ttest_expect_success \"$command: modified submodule does not update submodule work tree to invalid commit\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to add_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t invalid_sub1 origin/invalid_sub1 &&\n-\t\t\t$command invalid_sub1 &&\n-\t\t\ttest_superproject_content origin/invalid_sub1 &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n-\t\t\ttest_must_fail git submodule update &&\n-\t\t\ttest_submodule_content sub1 origin/add_sub1\n-\t\t)\n-\t'\n-\t# Updating a submodule from an invalid sha1 doesn't update the\n-\t# submodule's work tree, subsequent update will succeed\n-\ttest_expect_success \"$command: modified submodule does not update submodule work tree from invalid commit\" '\n-\t\tprolog &&\n-\t\treset_work_tree_to invalid_sub1 &&\n-\t\t(\n-\t\t\tcd submodule_update &&\n-\t\t\tgit branch -t valid_sub1 origin/valid_sub1 &&\n-\t\t\t$command valid_sub1 &&\n-\t\t\ttest_superproject_content origin/valid_sub1 &&\n-\t\t\ttest_dir_is_empty sub1 &&\n-\t\t\tgit submodule update --init --recursive &&\n-\t\t\ttest_submodule_content sub1 origin/valid_sub1\n-\t\t)\n-\t'\n }\n \n # Test that submodule contents are correctly updated when switching\n-- \n2.15.0.403.gc27cc4dac6-goog\n\n"}]}