1# Create a submodule layout used for all tests below. 2# 3# The following use cases are covered: 4# - New submodule (no_submodule => add_sub1) 5# - Removed submodule (add_sub1 => remove_sub1) 6# - Updated submodule (add_sub1 => modify_sub1) 7# - Updated submodule recursively (add_nested_sub => modify_sub1_recursively) 8# - Submodule updated to invalid commit (add_sub1 => invalid_sub1) 9# - Submodule updated from invalid commit (invalid_sub1 => valid_sub1) 10# - Submodule replaced by tracked files in directory (add_sub1 => 11# replace_sub1_with_directory) 12# - Directory containing tracked files replaced by submodule 13# (replace_sub1_with_directory => replace_directory_with_sub1) 14# - Submodule replaced by tracked file with the same name (add_sub1 => 15# replace_sub1_with_file) 16# - Tracked file replaced by submodule (replace_sub1_with_file => 17# replace_file_with_sub1) 18# 19# ----O 20# / ^ 21# / remove_sub1 22# / 23# add_sub1 /-------O---------O--------O modify_sub1_recursively 24# | / ^ add_nested_sub 25# | / modify_sub1 26# v/ 27# O------O-----------O---------O 28# ^ \ ^ replace_directory_with_sub1 29# | \ replace_sub1_with_directory 30# no_submodule \ 31# --------O---------O 32# \ ^ replace_file_with_sub1 33# \ replace_sub1_with_file 34# \ 35# ----O---------O 36# ^ valid_sub1 37# invalid_sub1 38# 39 40create_lib_submodule_repo () { 41 git init submodule_update_sub1 && 42 ( 43 cd submodule_update_sub1 && 44 echo "expect" >>.gitignore && 45 echo "actual" >>.gitignore && 46 echo "x" >file1 && 47 echo "y" >file2 && 48 git add .gitignore file1 file2 && 49 git commit -m "Base inside first submodule" && 50 git branch "no_submodule" 51 ) && 52 git init submodule_update_sub2 && 53 ( 54 cd submodule_update_sub2 55 echo "expect" >>.gitignore && 56 echo "actual" >>.gitignore && 57 echo "x" >file1 && 58 echo "y" >file2 && 59 git add .gitignore file1 file2 && 60 git commit -m "nested submodule base" && 61 git branch "no_submodule" 62 ) && 63 git init submodule_update_repo && 64 ( 65 cd submodule_update_repo && 66 branch=$(git symbolic-ref --short HEAD) && 67 echo "expect" >>.gitignore && 68 echo "actual" >>.gitignore && 69 echo "x" >file1 && 70 echo "y" >file2 && 71 git add .gitignore file1 file2 && 72 git commit -m "Base" && 73 git branch "no_submodule" && 74 75 git checkout -b "add_sub1" && 76 git submodule add ../submodule_update_sub1 sub1 && 77 git submodule add ../submodule_update_sub1 uninitialized_sub && 78 git config -f .gitmodules submodule.sub1.ignore all && 79 git config submodule.sub1.ignore all && 80 git add .gitmodules && 81 git commit -m "Add sub1" && 82 83 git checkout -b remove_sub1 add_sub1 && 84 git revert HEAD && 85 86 git checkout -b modify_sub1 add_sub1 && 87 git submodule update && 88 ( 89 cd sub1 && 90 git fetch && 91 git checkout -b "modifications" && 92 echo "z" >file2 && 93 echo "x" >file3 && 94 git add file2 file3 && 95 git commit -m "modified file2 and added file3" && 96 git push origin modifications 97 ) && 98 git add sub1 && 99 git commit -m "Modify sub1" && 100 101 git checkout -b add_nested_sub modify_sub1 && 102 git -C sub1 checkout -b "add_nested_sub" && 103 git -C sub1 submodule add --branch no_submodule ../submodule_update_sub2 sub2 && 104 git -C sub1 commit -a -m "add a nested submodule" && 105 git add sub1 && 106 git commit -a -m "update submodule, that updates a nested submodule" && 107 git checkout -b modify_sub1_recursively && 108 git -C sub1 checkout -b modify_sub1_recursively && 109 git -C sub1/sub2 checkout -b modify_sub1_recursively && 110 echo change >sub1/sub2/file3 && 111 git -C sub1/sub2 add file3 && 112 git -C sub1/sub2 commit -m "make a change in nested sub" && 113 git -C sub1 add sub2 && 114 git -C sub1 commit -m "update nested sub" && 115 git add sub1 && 116 git commit -m "update sub1, that updates nested sub" && 117 git -C sub1 push origin modify_sub1_recursively && 118 git -C sub1/sub2 push origin modify_sub1_recursively && 119 git -C sub1 submodule deinit -f --all && 120 121 git checkout -b replace_sub1_with_directory add_sub1 && 122 git submodule update && 123 git -C sub1 checkout modifications && 124 git rm --cached sub1 && 125 rm sub1/.git* && 126 git config -f .gitmodules --remove-section "submodule.sub1" && 127 git add .gitmodules sub1/* && 128 git commit -m "Replace sub1 with directory" && 129 130 git checkout -b replace_directory_with_sub1 && 131 git revert HEAD && 132 133 git checkout -b replace_sub1_with_file add_sub1 && 134 git rm sub1 && 135 echo "content" >sub1 && 136 git add sub1 && 137 git commit -m "Replace sub1 with file" && 138 139 git checkout -b replace_file_with_sub1 && 140 git revert HEAD && 141 142 git checkout -b invalid_sub1 add_sub1 && 143 git update-index --cacheinfo 160000 $(test_oid numeric) sub1 && 144 git commit -m "Invalid sub1 commit" && 145 git checkout -b valid_sub1 && 146 git revert HEAD && 147 148 git checkout "$branch" 149 ) 150} 151 152# Helper function to replace gitfile with .git directory 153replace_gitfile_with_git_dir () { 154 ( 155 cd "$1" && 156 git_dir="$(git rev-parse --git-dir)" && 157 rm -f .git && 158 cp -R "$git_dir" .git && 159 GIT_WORK_TREE=. git config --unset core.worktree 160 ) 161} 162 163# Test that the .git directory in the submodule is unchanged (except for the 164# core.worktree setting, which appears only in $GIT_DIR/modules/$1/config). 165# Call this function before test_submodule_content as the latter might 166# write the index file leading to false positive index differences. 167# 168# Note that this only supports submodules at the root level of the 169# superproject, with the default name, i.e. same as its path. 170test_git_directory_is_unchanged () { 171 ( 172 cd ".git/modules/$1" && 173 # does core.worktree point at the right place? 174 test "$(git config core.worktree)" = "../../../$1" && 175 # remove it temporarily before comparing, as 176 # "$1/.git/config" lacks it... 177 git config --unset core.worktree 178 ) && 179 diff -r ".git/modules/$1" "$1/.git" && 180 ( 181 # ... and then restore. 182 cd ".git/modules/$1" && 183 git config core.worktree "../../../$1" 184 ) 185} 186 187test_git_directory_exists () { 188 test -e ".git/modules/$1" && 189 if test -f sub1/.git 190 then 191 # does core.worktree point at the right place? 192 test "$(git -C .git/modules/$1 config core.worktree)" = "../../../$1" 193 fi 194} 195 196# Helper function to be executed at the start of every test below, it sets up 197# the submodule repo if it doesn't exist and configures the most problematic 198# settings for diff.ignoreSubmodules. 199prolog () { 200 (test -d submodule_update_repo || create_lib_submodule_repo) && 201 test_config_global diff.ignoreSubmodules all && 202 test_config diff.ignoreSubmodules all 203} 204 205# Helper function to bring work tree back into the state given by the 206# commit. This includes trying to populate sub1 accordingly if it exists and 207# should be updated to an existing commit. 208reset_work_tree_to () { 209 rm -rf submodule_update && 210 git clone submodule_update_repo submodule_update && 211 ( 212 cd submodule_update && 213 rm -rf sub1 && 214 git checkout -f "$1" && 215 git status -u -s >actual && 216 test_must_be_empty actual && 217 hash=$(git rev-parse --revs-only HEAD:sub1) && 218 if test -n "$hash" && 219 test $(cd "../submodule_update_sub1" && git rev-parse --verify "$hash^{commit}") 220 then 221 git submodule update --init --recursive "sub1" 222 fi 223 ) 224} 225 226reset_work_tree_to_interested () { 227 reset_work_tree_to $1 && 228 # make the submodule git dirs available 229 if ! test -d submodule_update/.git/modules/sub1 230 then 231 mkdir -p submodule_update/.git/modules && 232 cp -r submodule_update_repo/.git/modules/sub1 submodule_update/.git/modules/sub1 233 GIT_WORK_TREE=. git -C submodule_update/.git/modules/sub1 config --unset core.worktree 234 fi && 235 if ! test -d submodule_update/.git/modules/sub1/modules/sub2 236 then 237 mkdir -p submodule_update/.git/modules/sub1/modules && 238 cp -r submodule_update_repo/.git/modules/sub1/modules/sub2 submodule_update/.git/modules/sub1/modules/sub2 239 # core.worktree is unset for sub2 as it is not checked out 240 fi && 241 # indicate we are interested in the submodule: 242 git -C submodule_update config submodule.sub1.url "bogus" && 243 # sub1 might not be checked out, so use the git dir 244 git -C submodule_update/.git/modules/sub1 config submodule.sub2.url "bogus" 245} 246 247# Test that the superproject contains the content according to commit "$1" 248# (the work tree must match the index for everything but submodules but the 249# index must exactly match the given commit including any submodule SHA-1s). 250test_superproject_content () { 251 git diff-index --cached "$1" >actual && 252 test_must_be_empty actual && 253 git diff-files --ignore-submodules >actual && 254 test_must_be_empty actual 255} 256 257# Test that the given submodule at path "$1" contains the content according 258# to the submodule commit recorded in the superproject's commit "$2" 259test_submodule_content () { 260 if test x"$1" = "x-C" 261 then 262 cd "$2" 263 shift; shift; 264 fi 265 if test $# != 2 266 then 267 echo "test_submodule_content needs two arguments" 268 return 1 269 fi && 270 submodule="$1" && 271 commit="$2" && 272 test -d "$submodule"/ && 273 if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git 274 then 275 echo "Submodule $submodule is not populated" 276 return 1 277 fi && 278 sha1=$(git rev-parse --verify "$commit:$submodule") && 279 if test -z "$sha1" 280 then 281 echo "Couldn't retrieve SHA-1 of $submodule for $commit" 282 return 1 283 fi && 284 ( 285 cd "$submodule" && 286 git status -u -s >actual && 287 test_must_be_empty actual && 288 git diff "$sha1" >actual && 289 test_must_be_empty actual 290 ) 291} 292 293# Test that the following transitions are correctly handled: 294# - Updated submodule 295# - New submodule 296# - Removed submodule 297# - Directory containing tracked files replaced by submodule 298# - Submodule replaced by tracked files in directory 299# - Submodule replaced by tracked file with the same name 300# - Tracked file replaced by submodule 301# 302# The default is that submodule contents aren't changed until "git submodule 303# update" is run. And even then that command doesn't delete the work tree of 304# a removed submodule. 305# 306# The first argument of the callback function will be the name of the submodule. 307# 308# Removing a submodule containing a .git directory must fail even when forced 309# to protect the history! If we are testing this case, the second argument of 310# the callback function will be 'test_must_fail', else it will be the empty 311# string. 312# 313 314# Internal function; use test_submodule_switch_func(), test_submodule_switch(), 315# or test_submodule_forced_switch() instead. 316test_submodule_switch_common () { 317 command="$1" 318 ######################### Appearing submodule ######################### 319 # Switching to a commit letting a submodule appear creates empty dir ... 320 test_expect_success "$command: added submodule creates empty directory" ' 321 prolog && 322 reset_work_tree_to no_submodule && 323 ( 324 cd submodule_update && 325 git branch -t add_sub1 origin/add_sub1 && 326 $command add_sub1 && 327 test_superproject_content origin/add_sub1 && 328 test_dir_is_empty sub1 && 329 git submodule update --init --recursive && 330 test_submodule_content sub1 origin/add_sub1 331 ) 332 ' 333 # ... and doesn't care if it already exists. 334 if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1 335 then 336 # Restoring stash fails to restore submodule index entry 337 RESULT="failure" 338 else 339 RESULT="success" 340 fi 341 test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" ' 342 prolog && 343 reset_work_tree_to no_submodule && 344 ( 345 cd submodule_update && 346 mkdir sub1 && 347 git branch -t add_sub1 origin/add_sub1 && 348 $command add_sub1 && 349 test_superproject_content origin/add_sub1 && 350 test_dir_is_empty sub1 && 351 git submodule update --init --recursive && 352 test_submodule_content sub1 origin/add_sub1 353 ) 354 ' 355 # Replacing a tracked file with a submodule produces an empty 356 # directory ... 357 test_expect_$RESULT "$command: replace tracked file with submodule creates empty directory" ' 358 prolog && 359 reset_work_tree_to replace_sub1_with_file && 360 ( 361 cd submodule_update && 362 git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 && 363 $command replace_file_with_sub1 && 364 test_superproject_content origin/replace_file_with_sub1 && 365 test_dir_is_empty sub1 && 366 git submodule update --init --recursive && 367 test_submodule_content sub1 origin/replace_file_with_sub1 368 ) 369 ' 370 # ... as does removing a directory with tracked files with a 371 # submodule. 372 if test "$KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR" = 1 373 then 374 # Non fast-forward merges fail with "Directory sub1 doesn't 375 # exist. sub1" because the empty submodule directory is not 376 # created 377 RESULT="failure" 378 else 379 RESULT="success" 380 fi 381 test_expect_$RESULT "$command: replace directory with submodule" ' 382 prolog && 383 reset_work_tree_to replace_sub1_with_directory && 384 ( 385 cd submodule_update && 386 git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 && 387 $command replace_directory_with_sub1 && 388 test_superproject_content origin/replace_directory_with_sub1 && 389 test_dir_is_empty sub1 && 390 git submodule update --init --recursive && 391 test_submodule_content sub1 origin/replace_directory_with_sub1 392 ) 393 ' 394 395 ######################## Disappearing submodule ####################### 396 # Removing a submodule doesn't remove its work tree ... 397 if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1 398 then 399 RESULT="failure" 400 else 401 RESULT="success" 402 fi 403 test_expect_$RESULT "$command: removed submodule leaves submodule directory and its contents in place" ' 404 prolog && 405 reset_work_tree_to add_sub1 && 406 ( 407 cd submodule_update && 408 git branch -t remove_sub1 origin/remove_sub1 && 409 $command remove_sub1 && 410 test_superproject_content origin/remove_sub1 && 411 test_submodule_content sub1 origin/add_sub1 412 ) 413 ' 414 # ... especially when it contains a .git directory. 415 test_expect_$RESULT "$command: removed submodule leaves submodule containing a .git directory alone" ' 416 prolog && 417 reset_work_tree_to add_sub1 && 418 ( 419 cd submodule_update && 420 git branch -t remove_sub1 origin/remove_sub1 && 421 replace_gitfile_with_git_dir sub1 && 422 $command remove_sub1 && 423 test_superproject_content origin/remove_sub1 && 424 test_git_directory_is_unchanged sub1 && 425 test_submodule_content sub1 origin/add_sub1 426 ) 427 ' 428 # Replacing a submodule with files in a directory must fail as the 429 # submodule work tree isn't removed ... 430 if test "$KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES" = 1 431 then 432 # Non fast-forward merges attempt to merge the former 433 # submodule files with the newly checked out ones in the 434 # directory of the same name while it shouldn't. 435 RESULT="failure" 436 elif test "$KNOWN_FAILURE_FORCED_SWITCH_TESTS" = 1 437 then 438 # All existing tests that use test_submodule_forced_switch() 439 # require this. 440 RESULT="failure" 441 else 442 RESULT="success" 443 fi 444 test_expect_$RESULT "$command: replace submodule with a directory must fail" ' 445 prolog && 446 reset_work_tree_to add_sub1 && 447 ( 448 cd submodule_update && 449 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 450 $command replace_sub1_with_directory test_must_fail && 451 test_superproject_content origin/add_sub1 && 452 test_submodule_content sub1 origin/add_sub1 453 ) 454 ' 455 # ... especially when it contains a .git directory. 456 test_expect_$RESULT "$command: replace submodule containing a .git directory with a directory must fail" ' 457 prolog && 458 reset_work_tree_to add_sub1 && 459 ( 460 cd submodule_update && 461 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 462 replace_gitfile_with_git_dir sub1 && 463 $command replace_sub1_with_directory test_must_fail && 464 test_superproject_content origin/add_sub1 && 465 test_git_directory_is_unchanged sub1 && 466 test_submodule_content sub1 origin/add_sub1 467 ) 468 ' 469 # Replacing it with a file must fail as it could throw away any local 470 # work tree changes ... 471 test_expect_failure "$command: replace submodule with a file must fail" ' 472 prolog && 473 reset_work_tree_to add_sub1 && 474 ( 475 cd submodule_update && 476 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 477 $command replace_sub1_with_file test_must_fail && 478 test_superproject_content origin/add_sub1 && 479 test_submodule_content sub1 origin/add_sub1 480 ) 481 ' 482 # ... or even destroy unpushed parts of submodule history if that 483 # still uses a .git directory. 484 test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" ' 485 prolog && 486 reset_work_tree_to add_sub1 && 487 ( 488 cd submodule_update && 489 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 490 replace_gitfile_with_git_dir sub1 && 491 $command replace_sub1_with_file test_must_fail && 492 test_superproject_content origin/add_sub1 && 493 test_git_directory_is_unchanged sub1 && 494 test_submodule_content sub1 origin/add_sub1 495 ) 496 ' 497 498 ########################## Modified submodule ######################### 499 # Updating a submodule sha1 doesn't update the submodule's work tree 500 if test "$KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT" = 1 501 then 502 # When cherry picking a SHA-1 update for an ignored submodule 503 # the commit incorrectly fails with "The previous cherry-pick 504 # is now empty, possibly due to conflict resolution." 505 RESULT="failure" 506 else 507 RESULT="success" 508 fi 509 test_expect_$RESULT "$command: modified submodule does not update submodule work tree" ' 510 prolog && 511 reset_work_tree_to add_sub1 && 512 ( 513 cd submodule_update && 514 git branch -t modify_sub1 origin/modify_sub1 && 515 $command modify_sub1 && 516 test_superproject_content origin/modify_sub1 && 517 test_submodule_content sub1 origin/add_sub1 && 518 git submodule update && 519 test_submodule_content sub1 origin/modify_sub1 520 ) 521 ' 522 # Updating a submodule to an invalid sha1 doesn't update the 523 # submodule's work tree, subsequent update will fail 524 test_expect_$RESULT "$command: modified submodule does not update submodule work tree to invalid commit" ' 525 prolog && 526 reset_work_tree_to add_sub1 && 527 ( 528 cd submodule_update && 529 git branch -t invalid_sub1 origin/invalid_sub1 && 530 $command invalid_sub1 && 531 test_superproject_content origin/invalid_sub1 && 532 test_submodule_content sub1 origin/add_sub1 && 533 test_must_fail git submodule update && 534 test_submodule_content sub1 origin/add_sub1 535 ) 536 ' 537 # Updating a submodule from an invalid sha1 doesn't update the 538 # submodule's work tree, subsequent update will succeed 539 test_expect_$RESULT "$command: modified submodule does not update submodule work tree from invalid commit" ' 540 prolog && 541 reset_work_tree_to invalid_sub1 && 542 ( 543 cd submodule_update && 544 git branch -t valid_sub1 origin/valid_sub1 && 545 $command valid_sub1 && 546 test_superproject_content origin/valid_sub1 && 547 test_dir_is_empty sub1 && 548 git submodule update --init --recursive && 549 test_submodule_content sub1 origin/valid_sub1 550 ) 551 ' 552} 553 554# Declares and invokes several tests that, in various situations, checks that 555# the provided transition function: 556# - succeeds in updating the worktree and index of a superproject to a target 557# commit, or fails atomically (depending on the test situation) 558# - if succeeds, the contents of submodule directories are unchanged 559# - if succeeds, once "git submodule update" is invoked, the contents of 560# submodule directories are updated 561# 562# If the command under test is known to not work with submodules in certain 563# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests 564# below to 1. 565# 566# The first argument of the callback function will be the name of the submodule. 567# 568# Removing a submodule containing a .git directory must fail even when forced 569# to protect the history! If we are testing this case, the second argument of 570# the callback function will be 'test_must_fail', else it will be the empty 571# string. 572# 573# The following example uses `git some-command` as an example command to be 574# tested. It updates the worktree and index to match a target, but not any 575# submodule directories. 576# 577# my_func () { 578# ...prepare for `git some-command` to be run... 579# $2 git some-command "$1" && 580# if test -n "$2" 581# then 582# return 583# fi && 584# ...check the state after git some-command is run... 585# } 586# test_submodule_switch_func "my_func" 587test_submodule_switch_func () { 588 command="$1" 589 test_submodule_switch_common "$command" 590 591 # An empty directory does not prevent the creation of a submodule of 592 # the same name, but a file does. 593 test_expect_success "$command: added submodule doesn't remove untracked unignored file with same name" ' 594 prolog && 595 reset_work_tree_to no_submodule && 596 ( 597 cd submodule_update && 598 git branch -t add_sub1 origin/add_sub1 && 599 >sub1 && 600 $command add_sub1 test_must_fail && 601 test_superproject_content origin/no_submodule && 602 test_must_be_empty sub1 603 ) 604 ' 605} 606 607# Ensures that the that the arg either contains "test_must_fail" or is empty. 608may_only_be_test_must_fail () { 609 test -z "$1" || test "$1" = test_must_fail || die 610} 611 612git_test_func () { 613 may_only_be_test_must_fail "$2" && 614 $2 git $gitcmd "$1" 615} 616 617test_submodule_switch () { 618 gitcmd="$1" 619 test_submodule_switch_func "git_test_func" 620} 621 622# Same as test_submodule_switch(), except that throwing away local changes in 623# the superproject is allowed. 624test_submodule_forced_switch () { 625 gitcmd="$1" 626 command="git_test_func" 627 KNOWN_FAILURE_FORCED_SWITCH_TESTS=1 628 test_submodule_switch_common "$command" 629 630 # When forced, a file in the superproject does not prevent creating a 631 # submodule of the same name. 632 test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' 633 prolog && 634 reset_work_tree_to no_submodule && 635 ( 636 cd submodule_update && 637 git branch -t add_sub1 origin/add_sub1 && 638 >sub1 && 639 $command add_sub1 && 640 test_superproject_content origin/add_sub1 && 641 test_dir_is_empty sub1 642 ) 643 ' 644} 645 646# Test that submodule contents are correctly updated when switching 647# between commits that change a submodule. 648# Test that the following transitions are correctly handled: 649# (These tests are also above in the case where we expect no change 650# in the submodule) 651# - Updated submodule 652# - New submodule 653# - Removed submodule 654# - Directory containing tracked files replaced by submodule 655# - Submodule replaced by tracked files in directory 656# - Submodule replaced by tracked file with the same name 657# - Tracked file replaced by submodule 658# 659# New test cases 660# - Removing a submodule with a git directory absorbs the submodules 661# git directory first into the superproject. 662# - Switching from no submodule to nested submodules 663# - Switching from nested submodules to no submodule 664 665# Internal function; use test_submodule_switch_recursing_with_args() or 666# test_submodule_forced_switch_recursing_with_args() instead. 667test_submodule_recursing_with_args_common () { 668 command="$1 --recurse-submodules" 669 670 ######################### Appearing submodule ######################### 671 # Switching to a commit letting a submodule appear checks it out ... 672 test_expect_success "$command: added submodule is checked out" ' 673 prolog && 674 reset_work_tree_to_interested no_submodule && 675 ( 676 cd submodule_update && 677 git branch -t add_sub1 origin/add_sub1 && 678 $command add_sub1 && 679 test_superproject_content origin/add_sub1 && 680 test_submodule_content sub1 origin/add_sub1 681 ) 682 ' 683 # ... ignoring an empty existing directory. 684 test_expect_success "$command: added submodule is checked out in empty dir" ' 685 prolog && 686 reset_work_tree_to_interested no_submodule && 687 ( 688 cd submodule_update && 689 mkdir sub1 && 690 git branch -t add_sub1 origin/add_sub1 && 691 $command add_sub1 && 692 test_superproject_content origin/add_sub1 && 693 test_submodule_content sub1 origin/add_sub1 694 ) 695 ' 696 697 # Replacing a tracked file with a submodule produces a checked out submodule 698 test_expect_success "$command: replace tracked file with submodule checks out submodule" ' 699 prolog && 700 reset_work_tree_to_interested replace_sub1_with_file && 701 ( 702 cd submodule_update && 703 git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 && 704 $command replace_file_with_sub1 && 705 test_superproject_content origin/replace_file_with_sub1 && 706 test_submodule_content sub1 origin/replace_file_with_sub1 707 ) 708 ' 709 # ... as does removing a directory with tracked files with a submodule. 710 test_expect_success "$command: replace directory with submodule" ' 711 prolog && 712 reset_work_tree_to_interested replace_sub1_with_directory && 713 ( 714 cd submodule_update && 715 git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 && 716 $command replace_directory_with_sub1 && 717 test_superproject_content origin/replace_directory_with_sub1 && 718 test_submodule_content sub1 origin/replace_directory_with_sub1 719 ) 720 ' 721 # Switching to a commit with nested submodules recursively checks them out 722 test_expect_success "$command: nested submodules are checked out" ' 723 prolog && 724 reset_work_tree_to_interested no_submodule && 725 ( 726 cd submodule_update && 727 git branch -t modify_sub1_recursively origin/modify_sub1_recursively && 728 $command modify_sub1_recursively && 729 test_superproject_content origin/modify_sub1_recursively && 730 test_submodule_content sub1 origin/modify_sub1_recursively && 731 test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively 732 ) 733 ' 734 735 ######################## Disappearing submodule ####################### 736 # Removing a submodule removes its work tree ... 737 test_expect_success "$command: removed submodule removes submodules working tree" ' 738 prolog && 739 reset_work_tree_to_interested add_sub1 && 740 ( 741 cd submodule_update && 742 git branch -t remove_sub1 origin/remove_sub1 && 743 $command remove_sub1 && 744 test_superproject_content origin/remove_sub1 && 745 ! test -e sub1 && 746 test_must_fail git config -f .git/modules/sub1/config core.worktree 747 ) 748 ' 749 # ... absorbing a .git directory along the way. 750 test_expect_success "$command: removed submodule absorbs submodules .git directory" ' 751 prolog && 752 reset_work_tree_to_interested add_sub1 && 753 ( 754 cd submodule_update && 755 git branch -t remove_sub1 origin/remove_sub1 && 756 replace_gitfile_with_git_dir sub1 && 757 rm -rf .git/modules && 758 $command remove_sub1 && 759 test_superproject_content origin/remove_sub1 && 760 ! test -e sub1 && 761 test_git_directory_exists sub1 762 ) 763 ' 764 765 # Replacing it with a file ... 766 test_expect_success "$command: replace submodule with a file" ' 767 prolog && 768 reset_work_tree_to_interested add_sub1 && 769 ( 770 cd submodule_update && 771 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 772 $command replace_sub1_with_file && 773 test_superproject_content origin/replace_sub1_with_file && 774 test -f sub1 775 ) 776 ' 777 RESULTDS=success 778 if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 779 then 780 RESULTDS=failure 781 fi 782 # ... must check its local work tree for untracked files 783 test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" ' 784 prolog && 785 reset_work_tree_to_interested add_sub1 && 786 ( 787 cd submodule_update && 788 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 789 : >sub1/untrackedfile && 790 test_must_fail $command replace_sub1_with_file && 791 test_superproject_content origin/add_sub1 && 792 test_submodule_content sub1 origin/add_sub1 && 793 test -f sub1/untracked_file 794 ) 795 ' 796 797 # Switching to a commit without nested submodules removes their worktrees 798 test_expect_success "$command: worktrees of nested submodules are removed" ' 799 prolog && 800 reset_work_tree_to_interested add_nested_sub && 801 ( 802 cd submodule_update && 803 git branch -t no_submodule origin/no_submodule && 804 $command no_submodule && 805 test_superproject_content origin/no_submodule && 806 ! test_path_is_dir sub1 && 807 test_must_fail git config -f .git/modules/sub1/config core.worktree && 808 test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree 809 ) 810 ' 811 812 ########################## Modified submodule ######################### 813 # Updating a submodule sha1 updates the submodule's work tree 814 test_expect_success "$command: modified submodule updates submodule work tree" ' 815 prolog && 816 reset_work_tree_to_interested add_sub1 && 817 ( 818 cd submodule_update && 819 git branch -t modify_sub1 origin/modify_sub1 && 820 $command modify_sub1 && 821 test_superproject_content origin/modify_sub1 && 822 test_submodule_content sub1 origin/modify_sub1 823 ) 824 ' 825 # Updating a submodule to an invalid sha1 doesn't update the 826 # superproject nor the submodule's work tree. 827 test_expect_success "$command: updating to a missing submodule commit fails" ' 828 prolog && 829 reset_work_tree_to_interested add_sub1 && 830 ( 831 cd submodule_update && 832 git branch -t invalid_sub1 origin/invalid_sub1 && 833 test_must_fail $command invalid_sub1 2>err && 834 test_i18ngrep sub1 err && 835 test_superproject_content origin/add_sub1 && 836 test_submodule_content sub1 origin/add_sub1 837 ) 838 ' 839 # Updating a submodule does not touch the currently checked out branch in the submodule 840 test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' 841 prolog && 842 reset_work_tree_to_interested add_sub1 && 843 ( 844 cd submodule_update && 845 git -C sub1 checkout -b keep_branch && 846 git -C sub1 rev-parse HEAD >expect && 847 git branch -t modify_sub1 origin/modify_sub1 && 848 $command modify_sub1 && 849 test_superproject_content origin/modify_sub1 && 850 test_submodule_content sub1 origin/modify_sub1 && 851 git -C sub1 rev-parse keep_branch >actual && 852 test_cmp expect actual && 853 test_must_fail git -C sub1 symbolic-ref HEAD 854 ) 855 ' 856} 857 858# Declares and invokes several tests that, in various situations, checks that 859# the provided Git command, when invoked with --recurse-submodules: 860# - succeeds in updating the worktree and index of a superproject to a target 861# commit, or fails atomically (depending on the test situation) 862# - if succeeds, the contents of submodule directories are updated 863# 864# Specify the Git command so that "git $GIT_COMMAND --recurse-submodules" 865# works. 866# 867# If the command under test is known to not work with submodules in certain 868# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests 869# below to 1. 870# 871# Use as follows: 872# 873# test_submodule_switch_recursing_with_args "$GIT_COMMAND" 874test_submodule_switch_recursing_with_args () { 875 cmd_args="$1" 876 command="git $cmd_args" 877 test_submodule_recursing_with_args_common "$command" 878 879 RESULTDS=success 880 if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 881 then 882 RESULTDS=failure 883 fi 884 RESULTOI=success 885 if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1 886 then 887 RESULTOI=failure 888 fi 889 # Switching to a commit letting a submodule appear cannot override an 890 # untracked file. 891 test_expect_success "$command: added submodule doesn't remove untracked file with same name" ' 892 prolog && 893 reset_work_tree_to_interested no_submodule && 894 ( 895 cd submodule_update && 896 git branch -t add_sub1 origin/add_sub1 && 897 : >sub1 && 898 test_must_fail $command add_sub1 && 899 test_superproject_content origin/no_submodule && 900 test_must_be_empty sub1 901 ) 902 ' 903 # ... but an ignored file is fine. 904 test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' 905 test_when_finished "rm submodule_update/.git/info/exclude" && 906 prolog && 907 reset_work_tree_to_interested no_submodule && 908 ( 909 cd submodule_update && 910 git branch -t add_sub1 origin/add_sub1 && 911 : >sub1 && 912 echo sub1 >.git/info/exclude && 913 $command add_sub1 && 914 test_superproject_content origin/add_sub1 && 915 test_submodule_content sub1 origin/add_sub1 916 ) 917 ' 918 919 # Replacing a submodule with files in a directory must succeeds 920 # when the submodule is clean 921 test_expect_$RESULTDS "$command: replace submodule with a directory" ' 922 prolog && 923 reset_work_tree_to_interested add_sub1 && 924 ( 925 cd submodule_update && 926 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 927 $command replace_sub1_with_directory && 928 test_superproject_content origin/replace_sub1_with_directory && 929 test_submodule_content sub1 origin/replace_sub1_with_directory 930 ) 931 ' 932 # ... absorbing a .git directory. 933 test_expect_$RESULTDS "$command: replace submodule containing a .git directory with a directory must absorb the git dir" ' 934 prolog && 935 reset_work_tree_to_interested add_sub1 && 936 ( 937 cd submodule_update && 938 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 939 replace_gitfile_with_git_dir sub1 && 940 rm -rf .git/modules && 941 $command replace_sub1_with_directory && 942 test_superproject_content origin/replace_sub1_with_directory && 943 test_git_directory_exists sub1 944 ) 945 ' 946 947 # ... and ignored files are ignored 948 test_expect_success "$command: replace submodule with a file works ignores ignored files in submodule" ' 949 test_when_finished "rm submodule_update/.git/modules/sub1/info/exclude" && 950 prolog && 951 reset_work_tree_to_interested add_sub1 && 952 ( 953 cd submodule_update && 954 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 955 echo ignored >.git/modules/sub1/info/exclude && 956 : >sub1/ignored && 957 $command replace_sub1_with_file && 958 test_superproject_content origin/replace_sub1_with_file && 959 test -f sub1 960 ) 961 ' 962 963 test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" ' 964 prolog && 965 reset_work_tree_to_interested add_sub1 && 966 ( 967 cd submodule_update && 968 git branch -t modify_sub1 origin/modify_sub1 && 969 git -c submodule.recurse=true $cmd_args modify_sub1 && 970 test_superproject_content origin/modify_sub1 && 971 test_submodule_content sub1 origin/modify_sub1 972 ) 973 ' 974 975 test_expect_success "$command: modified submodule updates submodule recursively" ' 976 prolog && 977 reset_work_tree_to_interested add_nested_sub && 978 ( 979 cd submodule_update && 980 git branch -t modify_sub1_recursively origin/modify_sub1_recursively && 981 $command modify_sub1_recursively && 982 test_superproject_content origin/modify_sub1_recursively && 983 test_submodule_content sub1 origin/modify_sub1_recursively && 984 test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively 985 ) 986 ' 987} 988 989# Same as test_submodule_switch_recursing_with_args(), except that throwing 990# away local changes in the superproject is allowed. 991test_submodule_forced_switch_recursing_with_args () { 992 cmd_args="$1" 993 command="git $cmd_args" 994 test_submodule_recursing_with_args_common "$command" 995 996 RESULT=success 997 if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 998 then 999 RESULT=failure 1000 fi 1001 # Switching to a commit letting a submodule appear does not care about 1002 # an untracked file. 1003 test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' 1004 prolog && 1005 reset_work_tree_to_interested no_submodule && 1006 ( 1007 cd submodule_update && 1008 git branch -t add_sub1 origin/add_sub1 && 1009 >sub1 && 1010 $command add_sub1 && 1011 test_superproject_content origin/add_sub1 && 1012 test_submodule_content sub1 origin/add_sub1 1013 ) 1014 ' 1015 1016 # Replacing a submodule with files in a directory ... 1017 test_expect_success "$command: replace submodule with a directory" ' 1018 prolog && 1019 reset_work_tree_to_interested add_sub1 && 1020 ( 1021 cd submodule_update && 1022 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 1023 $command replace_sub1_with_directory && 1024 test_superproject_content origin/replace_sub1_with_directory 1025 ) 1026 ' 1027 # ... absorbing a .git directory. 1028 test_expect_success "$command: replace submodule containing a .git directory with a directory must fail" ' 1029 prolog && 1030 reset_work_tree_to_interested add_sub1 && 1031 ( 1032 cd submodule_update && 1033 git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && 1034 replace_gitfile_with_git_dir sub1 && 1035 rm -rf .git/modules/sub1 && 1036 $command replace_sub1_with_directory && 1037 test_superproject_content origin/replace_sub1_with_directory && 1038 test_git_directory_exists sub1 1039 ) 1040 ' 1041 1042 # ... even if the submodule contains ignored files 1043 test_expect_success "$command: replace submodule with a file ignoring ignored files" ' 1044 prolog && 1045 reset_work_tree_to_interested add_sub1 && 1046 ( 1047 cd submodule_update && 1048 git branch -t replace_sub1_with_file origin/replace_sub1_with_file && 1049 : >sub1/expect && 1050 $command replace_sub1_with_file && 1051 test_superproject_content origin/replace_sub1_with_file 1052 ) 1053 ' 1054 1055 # Updating a submodule from an invalid sha1 updates 1056 test_expect_success "$command: modified submodule does update submodule work tree from invalid commit" ' 1057 prolog && 1058 reset_work_tree_to_interested invalid_sub1 && 1059 ( 1060 cd submodule_update && 1061 git branch -t valid_sub1 origin/valid_sub1 && 1062 $command valid_sub1 && 1063 test_superproject_content origin/valid_sub1 && 1064 test_submodule_content sub1 origin/valid_sub1 1065 ) 1066 ' 1067 1068 # Old versions of Git were buggy writing the .git link file 1069 # (e.g. before f8eaa0ba98b and then moving the superproject repo 1070 # whose submodules contained absolute paths) 1071 test_expect_success "$command: updating submodules fixes .git links" ' 1072 prolog && 1073 reset_work_tree_to_interested add_sub1 && 1074 ( 1075 cd submodule_update && 1076 git branch -t modify_sub1 origin/modify_sub1 && 1077 echo "gitdir: bogus/path" >sub1/.git && 1078 $command modify_sub1 && 1079 test_superproject_content origin/modify_sub1 && 1080 test_submodule_content sub1 origin/modify_sub1 1081 ) 1082 ' 1083 1084 test_expect_success "$command: changed submodule worktree is reset" ' 1085 prolog && 1086 reset_work_tree_to_interested add_sub1 && 1087 ( 1088 cd submodule_update && 1089 rm sub1/file1 && 1090 : >sub1/new_file && 1091 git -C sub1 add new_file && 1092 $command HEAD && 1093 test_path_is_file sub1/file1 && 1094 test_path_is_missing sub1/new_file 1095 ) 1096 ' 1097} 1098