diff options
Diffstat (limited to 't/lib-submodule-update.sh')
-rw-r--r--[-rwxr-xr-x] | t/lib-submodule-update.sh | 163 |
1 files changed, 113 insertions, 50 deletions
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 1dd17fc03e..f7c7df0ca4 100755..100644 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -63,6 +63,7 @@ create_lib_submodule_repo () { git init submodule_update_repo && ( cd submodule_update_repo && + branch=$(git symbolic-ref --short HEAD) && echo "expect" >>.gitignore && echo "actual" >>.gitignore && echo "x" >file1 && @@ -144,7 +145,7 @@ create_lib_submodule_repo () { git checkout -b valid_sub1 && git revert HEAD && - git checkout master + git checkout "$branch" ) } @@ -183,7 +184,7 @@ test_git_directory_is_unchanged () { ) } -test_git_directory_exists() { +test_git_directory_exists () { test -e ".git/modules/$1" && if test -f sub1/.git then @@ -196,7 +197,6 @@ test_git_directory_exists() { # the submodule repo if it doesn't exist and configures the most problematic # settings for diff.ignoreSubmodules. prolog () { - test_oid_init && (test -d submodule_update_repo || create_lib_submodule_repo) && test_config_global diff.ignoreSubmodules all && test_config diff.ignoreSubmodules all @@ -297,30 +297,27 @@ test_submodule_content () { # - Directory containing tracked files replaced by submodule # - Submodule replaced by tracked files in directory # - Submodule replaced by tracked file with the same name -# - tracked file replaced by submodule +# - Tracked file replaced by submodule # # The default is that submodule contents aren't changed until "git submodule # update" is run. And even then that command doesn't delete the work tree of # a removed submodule. # +# The first argument of the callback function will be the name of the submodule. +# # Removing a submodule containing a .git directory must fail even when forced -# to protect the history! +# to protect the history! If we are testing this case, the second argument of +# the callback function will be 'test_must_fail', else it will be the empty +# string. # -# Internal function; use test_submodule_switch() or -# test_submodule_forced_switch() instead. -test_submodule_switch_common() { +# Internal function; use test_submodule_switch_func(), test_submodule_switch(), +# or test_submodule_forced_switch() instead. +test_submodule_switch_common () { command="$1" ######################### Appearing submodule ######################### # Switching to a commit letting a submodule appear creates empty dir ... - if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1 - then - # Restoring stash fails to restore submodule index entry - RESULT="failure" - else - RESULT="success" - fi - test_expect_$RESULT "$command: added submodule creates empty directory" ' + test_expect_success "$command: added submodule creates empty directory" ' prolog && reset_work_tree_to no_submodule && ( @@ -334,6 +331,13 @@ test_submodule_switch_common() { ) ' # ... and doesn't care if it already exists. + if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1 + then + # Restoring stash fails to restore submodule index entry + RESULT="failure" + else + RESULT="success" + fi test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" ' prolog && reset_work_tree_to no_submodule && @@ -443,7 +447,7 @@ test_submodule_switch_common() { ( cd submodule_update && git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && - test_must_fail $command replace_sub1_with_directory && + $command replace_sub1_with_directory test_must_fail && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) @@ -456,7 +460,7 @@ test_submodule_switch_common() { cd submodule_update && git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && replace_gitfile_with_git_dir sub1 && - test_must_fail $command replace_sub1_with_directory && + $command replace_sub1_with_directory test_must_fail && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 @@ -470,7 +474,7 @@ test_submodule_switch_common() { ( cd submodule_update && git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - test_must_fail $command replace_sub1_with_file && + $command replace_sub1_with_file test_must_fail && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) @@ -484,7 +488,7 @@ test_submodule_switch_common() { cd submodule_update && git branch -t replace_sub1_with_file origin/replace_sub1_with_file && replace_gitfile_with_git_dir sub1 && - test_must_fail $command replace_sub1_with_file && + $command replace_sub1_with_file test_must_fail && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 @@ -559,15 +563,28 @@ test_submodule_switch_common() { # conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests # below to 1. # -# Use as follows: +# The first argument of the callback function will be the name of the submodule. +# +# Removing a submodule containing a .git directory must fail even when forced +# to protect the history! If we are testing this case, the second argument of +# the callback function will be 'test_must_fail', else it will be the empty +# string. +# +# The following example uses `git some-command` as an example command to be +# tested. It updates the worktree and index to match a target, but not any +# submodule directories. # # my_func () { -# target=$1 -# # Do something here that updates the worktree and index to match target, -# # but not any submodule directories. +# ...prepare for `git some-command` to be run... +# $2 git some-command "$1" && +# if test -n "$2" +# then +# return +# fi && +# ...check the state after git some-command is run... # } -# test_submodule_switch "my_func" -test_submodule_switch () { +# test_submodule_switch_func "my_func" +test_submodule_switch_func () { command="$1" test_submodule_switch_common "$command" @@ -580,17 +597,33 @@ test_submodule_switch () { cd submodule_update && git branch -t add_sub1 origin/add_sub1 && >sub1 && - test_must_fail $command add_sub1 && + $command add_sub1 test_must_fail && test_superproject_content origin/no_submodule && test_must_be_empty sub1 ) ' } +# Ensures that the that the arg either contains "test_must_fail" or is empty. +may_only_be_test_must_fail () { + test -z "$1" || test "$1" = test_must_fail || die +} + +git_test_func () { + may_only_be_test_must_fail "$2" && + $2 git $gitcmd "$1" +} + +test_submodule_switch () { + gitcmd="$1" + test_submodule_switch_func "git_test_func" +} + # Same as test_submodule_switch(), except that throwing away local changes in # the superproject is allowed. test_submodule_forced_switch () { - command="$1" + gitcmd="$1" + command="git_test_func" KNOWN_FAILURE_FORCED_SWITCH_TESTS=1 test_submodule_switch_common "$command" @@ -621,16 +654,18 @@ test_submodule_forced_switch () { # - Directory containing tracked files replaced by submodule # - Submodule replaced by tracked files in directory # - Submodule replaced by tracked file with the same name -# - tracked file replaced by submodule +# - Tracked file replaced by submodule # # New test cases # - Removing a submodule with a git directory absorbs the submodules # git directory first into the superproject. +# - Switching from no submodule to nested submodules +# - Switching from nested submodules to no submodule # 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" +test_submodule_recursing_with_args_common () { + command="$1 --recurse-submodules" ######################### Appearing submodule ######################### # Switching to a commit letting a submodule appear checks it out ... @@ -658,22 +693,6 @@ test_submodule_recursing_with_args_common() { 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 && - ( - cd submodule_update && - git -C sub1 checkout -b keep_branch && - git -C sub1 rev-parse HEAD >expect && - git branch -t modify_sub1 origin/modify_sub1 && - $command modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 && - git -C sub1 rev-parse keep_branch >actual && - test_cmp expect actual && - test_must_fail git -C sub1 symbolic-ref HEAD - ) - ' # Replacing a tracked file with a submodule produces a checked out submodule test_expect_success "$command: replace tracked file with submodule checks out submodule" ' @@ -699,6 +718,19 @@ test_submodule_recursing_with_args_common() { test_submodule_content sub1 origin/replace_directory_with_sub1 ) ' + # Switching to a commit with nested submodules recursively checks them out + test_expect_success "$command: nested submodules are checked out" ' + prolog && + reset_work_tree_to_interested no_submodule && + ( + cd submodule_update && + git branch -t modify_sub1_recursively origin/modify_sub1_recursively && + $command modify_sub1_recursively && + test_superproject_content origin/modify_sub1_recursively && + test_submodule_content sub1 origin/modify_sub1_recursively && + test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively + ) + ' ######################## Disappearing submodule ####################### # Removing a submodule removes its work tree ... @@ -762,6 +794,21 @@ test_submodule_recursing_with_args_common() { ) ' + # Switching to a commit without nested submodules removes their worktrees + test_expect_success "$command: worktrees of nested submodules are removed" ' + prolog && + reset_work_tree_to_interested add_nested_sub && + ( + cd submodule_update && + git branch -t no_submodule origin/no_submodule && + $command no_submodule && + test_superproject_content origin/no_submodule && + ! test_path_is_dir sub1 && + test_must_fail git config -f .git/modules/sub1/config core.worktree && + test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree + ) + ' + ########################## Modified submodule ######################### # Updating a submodule sha1 updates the submodule's work tree test_expect_success "$command: modified submodule updates submodule work tree" ' @@ -789,6 +836,23 @@ test_submodule_recursing_with_args_common() { test_submodule_content sub1 origin/add_sub1 ) ' + # Updating a submodule does not touch the currently checked out branch in the submodule + test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git -C sub1 checkout -b keep_branch && + git -C sub1 rev-parse HEAD >expect && + git branch -t modify_sub1 origin/modify_sub1 && + $command modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 && + git -C sub1 rev-parse keep_branch >actual && + test_cmp expect actual && + test_must_fail git -C sub1 symbolic-ref HEAD + ) + ' } # Declares and invokes several tests that, in various situations, checks that @@ -809,7 +873,7 @@ test_submodule_recursing_with_args_common() { # test_submodule_switch_recursing_with_args "$GIT_COMMAND" test_submodule_switch_recursing_with_args () { cmd_args="$1" - command="git $cmd_args --recurse-submodules" + command="git $cmd_args" test_submodule_recursing_with_args_common "$command" RESULTDS=success @@ -908,7 +972,6 @@ test_submodule_switch_recursing_with_args () { ) ' - # recursing deeper than one level doesn't work yet. test_expect_success "$command: modified submodule updates submodule recursively" ' prolog && reset_work_tree_to_interested add_nested_sub && @@ -927,7 +990,7 @@ test_submodule_switch_recursing_with_args () { # away local changes in the superproject is allowed. test_submodule_forced_switch_recursing_with_args () { cmd_args="$1" - command="git $cmd_args --recurse-submodules" + command="git $cmd_args" test_submodule_recursing_with_args_common "$command" RESULT=success |