diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 9058bf978a..38dadd2c29 100755 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -554,6 +554,10 @@ test_submodule_switch_common() { # - if succeeds, once "git submodule update" is invoked, the contents of # submodule directories are updated # +# If the command under test is known to not work with submodules in certain +# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests +# below to 1. +# # Use as follows: # # my_func () { @@ -622,19 +626,11 @@ test_submodule_forced_switch () { # - Removing a submodule with a git directory absorbs the submodules # git directory first into the superproject. -test_submodule_switch_recursing_with_args () { - cmd_args="$1" - command="git $cmd_args --recurse-submodules" - RESULTDS=success - if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 - then - RESULTDS=failure - fi - RESULTOI=success - if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1 - then - RESULTOI=failure - fi +# Internal function; use test_submodule_switch_recursing_with_args() or +# test_submodule_forced_switch_recursing_with_args() instead. +test_submodule_recursing_with_args_common() { + command="$1" + ######################### Appearing submodule ######################### # Switching to a commit letting a submodule appear checks it out ... test_expect_success "$command: added submodule is checked out" ' @@ -648,7 +644,7 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - # ... ignoring an empty existing directory ... + # ... ignoring an empty existing directory. test_expect_success "$command: added submodule is checked out in empty dir" ' prolog && reset_work_tree_to_interested no_submodule && @@ -661,34 +657,6 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - # ... unless there is an untracked file in its place. - test_expect_success "$command: added submodule doesn't remove untracked file with same name" ' - prolog && - reset_work_tree_to_interested no_submodule && - ( - cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - : >sub1 && - test_must_fail $command add_sub1 && - test_superproject_content origin/no_submodule && - test_must_be_empty sub1 - ) - ' - # ... but an ignored file is fine. - test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' - test_when_finished "rm submodule_update/.git/info/exclude" && - prolog && - reset_work_tree_to_interested no_submodule && - ( - cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - : >sub1 && - echo sub1 >.git/info/exclude - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' prolog && reset_work_tree_to_interested add_sub1 && @@ -759,6 +727,128 @@ test_submodule_switch_recursing_with_args () { test_git_directory_exists sub1 ) ' + + # Replacing it with a file ... + test_expect_success "$command: replace submodule with a file" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t replace_sub1_with_file origin/replace_sub1_with_file && + $command replace_sub1_with_file && + test_superproject_content origin/replace_sub1_with_file && + test -f sub1 + ) + ' + RESULTDS=success + if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 + then + RESULTDS=failure + fi + # ... must check its local work tree for untracked files + test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t replace_sub1_with_file origin/replace_sub1_with_file && + : >sub1/untrackedfile && + test_must_fail $command replace_sub1_with_file && + test_superproject_content origin/add_sub1 && + test_submodule_content sub1 origin/add_sub1 + test -f sub1/untracked_file + ) + ' + + ########################## Modified submodule ######################### + # Updating a submodule sha1 updates the submodule's work tree + test_expect_success "$command: modified submodule updates submodule work tree" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t modify_sub1 origin/modify_sub1 && + $command modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 + ) + ' + # Updating a submodule to an invalid sha1 doesn't update the + # superproject nor the submodule's work tree. + test_expect_success "$command: updating to a missing submodule commit fails" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t invalid_sub1 origin/invalid_sub1 && + test_must_fail $command invalid_sub1 && + test_superproject_content origin/add_sub1 && + test_submodule_content sub1 origin/add_sub1 + ) + ' +} + +# Declares and invokes several tests that, in various situations, checks that +# the provided Git command, when invoked with --recurse-submodules: +# - succeeds in updating the worktree and index of a superproject to a target +# commit, or fails atomically (depending on the test situation) +# - if succeeds, the contents of submodule directories are updated +# +# Specify the Git command so that "git $GIT_COMMAND --recurse-submodules" +# works. +# +# If the command under test is known to not work with submodules in certain +# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests +# below to 1. +# +# Use as follows: +# +# test_submodule_switch_recursing_with_args "$GIT_COMMAND" +test_submodule_switch_recursing_with_args () { + cmd_args="$1" + command="git $cmd_args --recurse-submodules" + test_submodule_recursing_with_args_common "$command" + + RESULTDS=success + if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 + then + RESULTDS=failure + fi + RESULTOI=success + if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1 + then + RESULTOI=failure + fi + # Switching to a commit letting a submodule appear cannot override an + # untracked file. + test_expect_success "$command: added submodule doesn't remove untracked file with same name" ' + prolog && + reset_work_tree_to_interested no_submodule && + ( + cd submodule_update && + git branch -t add_sub1 origin/add_sub1 && + : >sub1 && + test_must_fail $command add_sub1 && + test_superproject_content origin/no_submodule && + test_must_be_empty sub1 + ) + ' + # ... but an ignored file is fine. + test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' + test_when_finished "rm submodule_update/.git/info/exclude" && + prolog && + reset_work_tree_to_interested no_submodule && + ( + cd submodule_update && + git branch -t add_sub1 origin/add_sub1 && + : >sub1 && + echo sub1 >.git/info/exclude + $command add_sub1 && + test_superproject_content origin/add_sub1 && + test_submodule_content sub1 origin/add_sub1 + ) + ' + # Replacing a submodule with files in a directory must succeeds # when the submodule is clean test_expect_$RESULTDS "$command: replace submodule with a directory" ' @@ -787,33 +877,6 @@ test_submodule_switch_recursing_with_args () { ) ' - # Replacing it with a file ... - test_expect_success "$command: replace submodule with a file" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - $command replace_sub1_with_file && - test_superproject_content origin/replace_sub1_with_file && - test -f sub1 - ) - ' - - # ... must check its local work tree for untracked files - test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - : >sub1/untrackedfile && - test_must_fail $command replace_sub1_with_file && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' - # ... and ignored files are ignored test_expect_success "$command: replace submodule with a file works ignores ignored files in submodule" ' test_when_finished "rm submodule_update/.git/modules/sub1/info/exclude" && @@ -829,20 +892,6 @@ test_submodule_switch_recursing_with_args () { ) ' - ########################## Modified submodule ######################### - # Updating a submodule sha1 updates the submodule's work tree - test_expect_success "$command: modified submodule updates submodule work tree" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t modify_sub1 origin/modify_sub1 && - $command modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 - ) - ' - test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" ' prolog && reset_work_tree_to_interested add_sub1 && @@ -855,20 +904,6 @@ test_submodule_switch_recursing_with_args () { ) ' - # Updating a submodule to an invalid sha1 doesn't update the - # superproject nor the submodule's work tree. - test_expect_success "$command: updating to a missing submodule commit fails" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t invalid_sub1 origin/invalid_sub1 && - test_must_fail $command invalid_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' - # recursing deeper than one level doesn't work yet. test_expect_success "$command: modified submodule updates submodule recursively" ' prolog && @@ -884,44 +919,20 @@ test_submodule_switch_recursing_with_args () { ' } -# Test that submodule contents are updated when switching between commits -# that change a submodule, but throwing away local changes in -# the superproject as well as the submodule is allowed. +# Same as test_submodule_switch_recursing_with_args(), except that throwing +# away local changes in the superproject is allowed. test_submodule_forced_switch_recursing_with_args () { cmd_args="$1" command="git $cmd_args --recurse-submodules" + test_submodule_recursing_with_args_common "$command" + RESULT=success if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 then RESULT=failure fi - ######################### Appearing submodule ######################### - # Switching to a commit letting a submodule appear creates empty dir ... - test_expect_success "$command: added submodule is checked out" ' - prolog && - reset_work_tree_to_interested no_submodule && - ( - cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' - # ... and doesn't care if it already exists ... - test_expect_success "$command: added submodule ignores empty directory" ' - prolog && - reset_work_tree_to_interested no_submodule && - ( - cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - mkdir sub1 && - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' - # ... not caring about an untracked file either + # Switching to a commit letting a submodule appear does not care about + # an untracked file. test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' prolog && reset_work_tree_to_interested no_submodule && @@ -934,60 +945,7 @@ test_submodule_forced_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - # Replacing a tracked file with a submodule checks out the submodule - test_expect_success "$command: replace tracked file with submodule populates the submodule" ' - prolog && - reset_work_tree_to_interested replace_sub1_with_file && - ( - cd submodule_update && - git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 && - $command replace_file_with_sub1 && - test_superproject_content origin/replace_file_with_sub1 && - test_submodule_content sub1 origin/replace_file_with_sub1 - ) - ' - # ... as does removing a directory with tracked files with a - # submodule. - test_expect_success "$command: replace directory with submodule" ' - prolog && - reset_work_tree_to_interested replace_sub1_with_directory && - ( - cd submodule_update && - git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 && - $command replace_directory_with_sub1 && - test_superproject_content origin/replace_directory_with_sub1 && - test_submodule_content sub1 origin/replace_directory_with_sub1 - ) - ' - ######################## Disappearing submodule ####################### - # Removing a submodule doesn't remove its work tree ... - test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t remove_sub1 origin/remove_sub1 && - $command remove_sub1 && - test_superproject_content origin/remove_sub1 && - ! test -e sub1 - ) - ' - # ... especially when it contains a .git directory. - test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t remove_sub1 origin/remove_sub1 && - replace_gitfile_with_git_dir sub1 && - rm -rf .git/modules/sub1 && - $command remove_sub1 && - test_superproject_content origin/remove_sub1 && - test_git_directory_exists sub1 && - ! test -e sub1 - ) - ' # Replacing a submodule with files in a directory ... test_expect_success "$command: replace submodule with a directory" ' prolog && @@ -1014,17 +972,6 @@ test_submodule_forced_switch_recursing_with_args () { test_git_directory_exists sub1 ) ' - # Replacing it with a file - test_expect_success "$command: replace submodule with a file" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - $command replace_sub1_with_file && - test_superproject_content origin/replace_sub1_with_file - ) - ' # ... even if the submodule contains ignored files test_expect_success "$command: replace submodule with a file ignoring ignored files" ' @@ -1039,46 +986,6 @@ test_submodule_forced_switch_recursing_with_args () { ) ' - # ... but stops for untracked files that would be lost - test_expect_$RESULT "$command: replace submodule with a file stops for untracked files" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - : >sub1/untracked_file && - test_must_fail $command replace_sub1_with_file && - test_superproject_content origin/add_sub1 && - test -f sub1/untracked_file - ) - ' - - ########################## Modified submodule ######################### - # Updating a submodule sha1 updates the submodule's work tree - test_expect_success "$command: modified submodule updates submodule work tree" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t modify_sub1 origin/modify_sub1 && - $command modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 - ) - ' - # Updating a submodule to an invalid sha1 doesn't update the - # submodule's work tree, subsequent update will fail - test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t invalid_sub1 origin/invalid_sub1 && - test_must_fail $command invalid_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' # Updating a submodule from an invalid sha1 updates test_expect_success "$command: modified submodule does update submodule work tree from invalid commit" ' prolog &&