t / lib-submodule-update.shon commit files-backend: convert git_path() to strbuf_git_path() (e9dcc30)
   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# - Submodule updated to invalid commit (add_sub1 => invalid_sub1)
   8# - Submodule updated from invalid commit (invalid_sub1 => valid_sub1)
   9# - Submodule replaced by tracked files in directory (add_sub1 =>
  10#   replace_sub1_with_directory)
  11# - Directory containing tracked files replaced by submodule
  12#   (replace_sub1_with_directory => replace_directory_with_sub1)
  13# - Submodule replaced by tracked file with the same name (add_sub1 =>
  14#   replace_sub1_with_file)
  15# - Tracked file replaced by submodule (replace_sub1_with_file =>
  16#   replace_file_with_sub1)
  17#
  18#                   --O-----O
  19#                  /  ^     replace_directory_with_sub1
  20#                 /   replace_sub1_with_directory
  21#                /----O
  22#               /     ^
  23#              /      modify_sub1
  24#      O------O-------O
  25#      ^      ^\      ^
  26#      |      | \     remove_sub1
  27#      |      |  -----O-----O
  28#      |      |   \   ^     replace_file_with_sub1
  29#      |      |    \  replace_sub1_with_file
  30#      |   add_sub1 --O-----O
  31# no_submodule        ^     valid_sub1
  32#                     invalid_sub1
  33#
  34create_lib_submodule_repo () {
  35        git init submodule_update_repo &&
  36        (
  37                cd submodule_update_repo &&
  38                echo "expect" >>.gitignore &&
  39                echo "actual" >>.gitignore &&
  40                echo "x" >file1 &&
  41                echo "y" >file2 &&
  42                git add .gitignore file1 file2 &&
  43                git commit -m "Base" &&
  44                git branch "no_submodule" &&
  45
  46                git checkout -b "add_sub1" &&
  47                git submodule add ./. sub1 &&
  48                git config -f .gitmodules submodule.sub1.ignore all &&
  49                git config submodule.sub1.ignore all &&
  50                git add .gitmodules &&
  51                git commit -m "Add sub1" &&
  52                git checkout -b remove_sub1 &&
  53                git revert HEAD &&
  54
  55                git checkout -b "modify_sub1" "add_sub1" &&
  56                git submodule update &&
  57                (
  58                        cd sub1 &&
  59                        git fetch &&
  60                        git checkout -b "modifications" &&
  61                        echo "z" >file2 &&
  62                        echo "x" >file3 &&
  63                        git add file2 file3 &&
  64                        git commit -m "modified file2 and added file3" &&
  65                        git push origin modifications
  66                ) &&
  67                git add sub1 &&
  68                git commit -m "Modify sub1" &&
  69
  70                git checkout -b "replace_sub1_with_directory" "add_sub1" &&
  71                git submodule update &&
  72                git -C sub1 checkout modifications &&
  73                git rm --cached sub1 &&
  74                rm sub1/.git* &&
  75                git config -f .gitmodules --remove-section "submodule.sub1" &&
  76                git add .gitmodules sub1/* &&
  77                git commit -m "Replace sub1 with directory" &&
  78                git checkout -b replace_directory_with_sub1 &&
  79                git revert HEAD &&
  80
  81                git checkout -b "replace_sub1_with_file" "add_sub1" &&
  82                git rm sub1 &&
  83                echo "content" >sub1 &&
  84                git add sub1 &&
  85                git commit -m "Replace sub1 with file" &&
  86                git checkout -b replace_file_with_sub1 &&
  87                git revert HEAD &&
  88
  89                git checkout -b "invalid_sub1" "add_sub1" &&
  90                git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 &&
  91                git commit -m "Invalid sub1 commit" &&
  92                git checkout -b valid_sub1 &&
  93                git revert HEAD &&
  94                git checkout master
  95        )
  96}
  97
  98# Helper function to replace gitfile with .git directory
  99replace_gitfile_with_git_dir () {
 100        (
 101                cd "$1" &&
 102                git_dir="$(git rev-parse --git-dir)" &&
 103                rm -f .git &&
 104                cp -R "$git_dir" .git &&
 105                GIT_WORK_TREE=. git config --unset core.worktree
 106        )
 107}
 108
 109# Test that the .git directory in the submodule is unchanged (except for the
 110# core.worktree setting, which appears only in $GIT_DIR/modules/$1/config).
 111# Call this function before test_submodule_content as the latter might
 112# write the index file leading to false positive index differences.
 113#
 114# Note that this only supports submodules at the root level of the
 115# superproject, with the default name, i.e. same as its path.
 116test_git_directory_is_unchanged () {
 117        (
 118                cd ".git/modules/$1" &&
 119                # does core.worktree point at the right place?
 120                test "$(git config core.worktree)" = "../../../$1" &&
 121                # remove it temporarily before comparing, as
 122                # "$1/.git/config" lacks it...
 123                git config --unset core.worktree
 124        ) &&
 125        diff -r ".git/modules/$1" "$1/.git" &&
 126        (
 127                # ... and then restore.
 128                cd ".git/modules/$1" &&
 129                git config core.worktree "../../../$1"
 130        )
 131}
 132
 133# Helper function to be executed at the start of every test below, it sets up
 134# the submodule repo if it doesn't exist and configures the most problematic
 135# settings for diff.ignoreSubmodules.
 136prolog () {
 137        (test -d submodule_update_repo || create_lib_submodule_repo) &&
 138        test_config_global diff.ignoreSubmodules all &&
 139        test_config diff.ignoreSubmodules all
 140}
 141
 142# Helper function to bring work tree back into the state given by the
 143# commit. This includes trying to populate sub1 accordingly if it exists and
 144# should be updated to an existing commit.
 145reset_work_tree_to () {
 146        rm -rf submodule_update &&
 147        git clone submodule_update_repo submodule_update &&
 148        (
 149                cd submodule_update &&
 150                rm -rf sub1 &&
 151                git checkout -f "$1" &&
 152                git status -u -s >actual &&
 153                test_must_be_empty actual &&
 154                sha1=$(git rev-parse --revs-only HEAD:sub1) &&
 155                if test -n "$sha1" &&
 156                   test $(cd "sub1" && git rev-parse --verify "$sha1^{commit}")
 157                then
 158                        git submodule update --init --recursive "sub1"
 159                fi
 160        )
 161}
 162
 163# Test that the superproject contains the content according to commit "$1"
 164# (the work tree must match the index for everything but submodules but the
 165# index must exactly match the given commit including any submodule SHA-1s).
 166test_superproject_content () {
 167        git diff-index --cached "$1" >actual &&
 168        test_must_be_empty actual &&
 169        git diff-files --ignore-submodules >actual &&
 170        test_must_be_empty actual
 171}
 172
 173# Test that the given submodule at path "$1" contains the content according
 174# to the submodule commit recorded in the superproject's commit "$2"
 175test_submodule_content () {
 176        if test $# != 2
 177        then
 178                echo "test_submodule_content needs two arguments"
 179                return 1
 180        fi &&
 181        submodule="$1" &&
 182        commit="$2" &&
 183        test -d "$submodule"/ &&
 184        if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git
 185        then
 186                echo "Submodule $submodule is not populated"
 187                return 1
 188        fi &&
 189        sha1=$(git rev-parse --verify "$commit:$submodule") &&
 190        if test -z "$sha1"
 191        then
 192                echo "Couldn't retrieve SHA-1 of $submodule for $commit"
 193                return 1
 194        fi &&
 195        (
 196                cd "$submodule" &&
 197                git status -u -s >actual &&
 198                test_must_be_empty actual &&
 199                git diff "$sha1" >actual &&
 200                test_must_be_empty actual
 201        )
 202}
 203
 204# Test that the following transitions are correctly handled:
 205# - Updated submodule
 206# - New submodule
 207# - Removed submodule
 208# - Directory containing tracked files replaced by submodule
 209# - Submodule replaced by tracked files in directory
 210# - Submodule replaced by tracked file with the same name
 211# - tracked file replaced by submodule
 212#
 213# The default is that submodule contents aren't changed until "git submodule
 214# update" is run. And even then that command doesn't delete the work tree of
 215# a removed submodule.
 216#
 217# Removing a submodule containing a .git directory must fail even when forced
 218# to protect the history!
 219#
 220
 221# Test that submodule contents are currently not updated when switching
 222# between commits that change a submodule.
 223test_submodule_switch () {
 224        command="$1"
 225        ######################### Appearing submodule #########################
 226        # Switching to a commit letting a submodule appear creates empty dir ...
 227        if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
 228        then
 229                # Restoring stash fails to restore submodule index entry
 230                RESULT="failure"
 231        else
 232                RESULT="success"
 233        fi
 234        test_expect_$RESULT "$command: added submodule creates empty directory" '
 235                prolog &&
 236                reset_work_tree_to no_submodule &&
 237                (
 238                        cd submodule_update &&
 239                        git branch -t add_sub1 origin/add_sub1 &&
 240                        $command add_sub1 &&
 241                        test_superproject_content origin/add_sub1 &&
 242                        test_dir_is_empty sub1 &&
 243                        git submodule update --init --recursive &&
 244                        test_submodule_content sub1 origin/add_sub1
 245                )
 246        '
 247        # ... and doesn't care if it already exists ...
 248        test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" '
 249                prolog &&
 250                reset_work_tree_to no_submodule &&
 251                (
 252                        cd submodule_update &&
 253                        mkdir sub1 &&
 254                        git branch -t add_sub1 origin/add_sub1 &&
 255                        $command add_sub1 &&
 256                        test_superproject_content origin/add_sub1 &&
 257                        test_dir_is_empty sub1 &&
 258                        git submodule update --init --recursive &&
 259                        test_submodule_content sub1 origin/add_sub1
 260                )
 261        '
 262        # ... unless there is an untracked file in its place.
 263        test_expect_success "$command: added submodule doesn't remove untracked unignored file with same name" '
 264                prolog &&
 265                reset_work_tree_to no_submodule &&
 266                (
 267                        cd submodule_update &&
 268                        git branch -t add_sub1 origin/add_sub1 &&
 269                        >sub1 &&
 270                        test_must_fail $command add_sub1 &&
 271                        test_superproject_content origin/no_submodule &&
 272                        test_must_be_empty sub1
 273                )
 274        '
 275        # Replacing a tracked file with a submodule produces an empty
 276        # directory ...
 277        test_expect_$RESULT "$command: replace tracked file with submodule creates empty directory" '
 278                prolog &&
 279                reset_work_tree_to replace_sub1_with_file &&
 280                (
 281                        cd submodule_update &&
 282                        git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
 283                        $command replace_file_with_sub1 &&
 284                        test_superproject_content origin/replace_file_with_sub1 &&
 285                        test_dir_is_empty sub1 &&
 286                        git submodule update --init --recursive &&
 287                        test_submodule_content sub1 origin/replace_file_with_sub1
 288                )
 289        '
 290        # ... as does removing a directory with tracked files with a
 291        # submodule.
 292        if test "$KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR" = 1
 293        then
 294                # Non fast-forward merges fail with "Directory sub1 doesn't
 295                # exist. sub1" because the empty submodule directory is not
 296                # created
 297                RESULT="failure"
 298        else
 299                RESULT="success"
 300        fi
 301        test_expect_$RESULT "$command: replace directory with submodule" '
 302                prolog &&
 303                reset_work_tree_to replace_sub1_with_directory &&
 304                (
 305                        cd submodule_update &&
 306                        git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
 307                        $command replace_directory_with_sub1 &&
 308                        test_superproject_content origin/replace_directory_with_sub1 &&
 309                        test_dir_is_empty sub1 &&
 310                        git submodule update --init --recursive &&
 311                        test_submodule_content sub1 origin/replace_directory_with_sub1
 312                )
 313        '
 314
 315        ######################## Disappearing submodule #######################
 316        # Removing a submodule doesn't remove its work tree ...
 317        if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
 318        then
 319                RESULT="failure"
 320        else
 321                RESULT="success"
 322        fi
 323        test_expect_$RESULT "$command: removed submodule leaves submodule directory and its contents in place" '
 324                prolog &&
 325                reset_work_tree_to add_sub1 &&
 326                (
 327                        cd submodule_update &&
 328                        git branch -t remove_sub1 origin/remove_sub1 &&
 329                        $command remove_sub1 &&
 330                        test_superproject_content origin/remove_sub1 &&
 331                        test_submodule_content sub1 origin/add_sub1
 332                )
 333        '
 334        # ... especially when it contains a .git directory.
 335        test_expect_$RESULT "$command: removed submodule leaves submodule containing a .git directory alone" '
 336                prolog &&
 337                reset_work_tree_to add_sub1 &&
 338                (
 339                        cd submodule_update &&
 340                        git branch -t remove_sub1 origin/remove_sub1 &&
 341                        replace_gitfile_with_git_dir sub1 &&
 342                        $command remove_sub1 &&
 343                        test_superproject_content origin/remove_sub1 &&
 344                        test_git_directory_is_unchanged sub1 &&
 345                        test_submodule_content sub1 origin/add_sub1
 346                )
 347        '
 348        # Replacing a submodule with files in a directory must fail as the
 349        # submodule work tree isn't removed ...
 350        if test "$KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES" = 1
 351        then
 352                # Non fast-forward merges attempt to merge the former
 353                # submodule files with the newly checked out ones in the
 354                # directory of the same name while it shouldn't.
 355                RESULT="failure"
 356        else
 357                RESULT="success"
 358        fi
 359        test_expect_$RESULT "$command: replace submodule with a directory must fail" '
 360                prolog &&
 361                reset_work_tree_to add_sub1 &&
 362                (
 363                        cd submodule_update &&
 364                        git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
 365                        test_must_fail $command replace_sub1_with_directory &&
 366                        test_superproject_content origin/add_sub1 &&
 367                        test_submodule_content sub1 origin/add_sub1
 368                )
 369        '
 370        # ... especially when it contains a .git directory.
 371        test_expect_$RESULT "$command: replace submodule containing a .git directory with a directory must fail" '
 372                prolog &&
 373                reset_work_tree_to add_sub1 &&
 374                (
 375                        cd submodule_update &&
 376                        git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
 377                        replace_gitfile_with_git_dir sub1 &&
 378                        test_must_fail $command replace_sub1_with_directory &&
 379                        test_superproject_content origin/add_sub1 &&
 380                        test_git_directory_is_unchanged sub1 &&
 381                        test_submodule_content sub1 origin/add_sub1
 382                )
 383        '
 384        # Replacing it with a file must fail as it could throw away any local
 385        # work tree changes ...
 386        test_expect_failure "$command: replace submodule with a file must fail" '
 387                prolog &&
 388                reset_work_tree_to add_sub1 &&
 389                (
 390                        cd submodule_update &&
 391                        git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
 392                        test_must_fail $command replace_sub1_with_file &&
 393                        test_superproject_content origin/add_sub1 &&
 394                        test_submodule_content sub1 origin/add_sub1
 395                )
 396        '
 397        # ... or even destroy unpushed parts of submodule history if that
 398        # still uses a .git directory.
 399        test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
 400                prolog &&
 401                reset_work_tree_to add_sub1 &&
 402                (
 403                        cd submodule_update &&
 404                        git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
 405                        replace_gitfile_with_git_dir sub1 &&
 406                        test_must_fail $command replace_sub1_with_file &&
 407                        test_superproject_content origin/add_sub1 &&
 408                        test_git_directory_is_unchanged sub1 &&
 409                        test_submodule_content sub1 origin/add_sub1
 410                )
 411        '
 412
 413        ########################## Modified submodule #########################
 414        # Updating a submodule sha1 doesn't update the submodule's work tree
 415        if test "$KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT" = 1
 416        then
 417                # When cherry picking a SHA-1 update for an ignored submodule
 418                # the commit incorrectly fails with "The previous cherry-pick
 419                # is now empty, possibly due to conflict resolution."
 420                RESULT="failure"
 421        else
 422                RESULT="success"
 423        fi
 424        test_expect_$RESULT "$command: modified submodule does not update submodule work tree" '
 425                prolog &&
 426                reset_work_tree_to add_sub1 &&
 427                (
 428                        cd submodule_update &&
 429                        git branch -t modify_sub1 origin/modify_sub1 &&
 430                        $command modify_sub1 &&
 431                        test_superproject_content origin/modify_sub1 &&
 432                        test_submodule_content sub1 origin/add_sub1 &&
 433                        git submodule update &&
 434                        test_submodule_content sub1 origin/modify_sub1
 435                )
 436        '
 437
 438        # Updating a submodule to an invalid sha1 doesn't update the
 439        # submodule's work tree, subsequent update will fail
 440        test_expect_$RESULT "$command: modified submodule does not update submodule work tree to invalid commit" '
 441                prolog &&
 442                reset_work_tree_to add_sub1 &&
 443                (
 444                        cd submodule_update &&
 445                        git branch -t invalid_sub1 origin/invalid_sub1 &&
 446                        $command invalid_sub1 &&
 447                        test_superproject_content origin/invalid_sub1 &&
 448                        test_submodule_content sub1 origin/add_sub1 &&
 449                        test_must_fail git submodule update &&
 450                        test_submodule_content sub1 origin/add_sub1
 451                )
 452        '
 453        # Updating a submodule from an invalid sha1 doesn't update the
 454        # submodule's work tree, subsequent update will succeed
 455        test_expect_$RESULT "$command: modified submodule does not update submodule work tree from invalid commit" '
 456                prolog &&
 457                reset_work_tree_to invalid_sub1 &&
 458                (
 459                        cd submodule_update &&
 460                        git branch -t valid_sub1 origin/valid_sub1 &&
 461                        $command valid_sub1 &&
 462                        test_superproject_content origin/valid_sub1 &&
 463                        test_dir_is_empty sub1 &&
 464                        git submodule update --init --recursive &&
 465                        test_submodule_content sub1 origin/valid_sub1
 466                )
 467        '
 468}
 469
 470# Test that submodule contents are currently not updated when switching
 471# between commits that change a submodule, but throwing away local changes in
 472# the superproject is allowed.
 473test_submodule_forced_switch () {
 474        command="$1"
 475        ######################### Appearing submodule #########################
 476        # Switching to a commit letting a submodule appear creates empty dir ...
 477        test_expect_success "$command: added submodule creates empty directory" '
 478                prolog &&
 479                reset_work_tree_to no_submodule &&
 480                (
 481                        cd submodule_update &&
 482                        git branch -t add_sub1 origin/add_sub1 &&
 483                        $command add_sub1 &&
 484                        test_superproject_content origin/add_sub1 &&
 485                        test_dir_is_empty sub1 &&
 486                        git submodule update --init --recursive &&
 487                        test_submodule_content sub1 origin/add_sub1
 488                )
 489        '
 490        # ... and doesn't care if it already exists ...
 491        test_expect_success "$command: added submodule leaves existing empty directory alone" '
 492                prolog &&
 493                reset_work_tree_to no_submodule &&
 494                (
 495                        cd submodule_update &&
 496                        git branch -t add_sub1 origin/add_sub1 &&
 497                        mkdir sub1 &&
 498                        $command add_sub1 &&
 499                        test_superproject_content origin/add_sub1 &&
 500                        test_dir_is_empty sub1 &&
 501                        git submodule update --init --recursive &&
 502                        test_submodule_content sub1 origin/add_sub1
 503                )
 504        '
 505        # ... unless there is an untracked file in its place.
 506        test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" '
 507                prolog &&
 508                reset_work_tree_to no_submodule &&
 509                (
 510                        cd submodule_update &&
 511                        git branch -t add_sub1 origin/add_sub1 &&
 512                        >sub1 &&
 513                        $command add_sub1 &&
 514                        test_superproject_content origin/add_sub1 &&
 515                        test_dir_is_empty sub1
 516                )
 517        '
 518        # Replacing a tracked file with a submodule produces an empty
 519        # directory ...
 520        test_expect_success "$command: replace tracked file with submodule creates empty directory" '
 521                prolog &&
 522                reset_work_tree_to replace_sub1_with_file &&
 523                (
 524                        cd submodule_update &&
 525                        git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
 526                        $command replace_file_with_sub1 &&
 527                        test_superproject_content origin/replace_file_with_sub1 &&
 528                        test_dir_is_empty sub1 &&
 529                        git submodule update --init --recursive &&
 530                        test_submodule_content sub1 origin/replace_file_with_sub1
 531                )
 532        '
 533        # ... as does removing a directory with tracked files with a
 534        # submodule.
 535        test_expect_success "$command: replace directory with submodule" '
 536                prolog &&
 537                reset_work_tree_to replace_sub1_with_directory &&
 538                (
 539                        cd submodule_update &&
 540                        git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
 541                        $command replace_directory_with_sub1 &&
 542                        test_superproject_content origin/replace_directory_with_sub1 &&
 543                        test_dir_is_empty sub1 &&
 544                        git submodule update --init --recursive &&
 545                        test_submodule_content sub1 origin/replace_directory_with_sub1
 546                )
 547        '
 548
 549        ######################## Disappearing submodule #######################
 550        # Removing a submodule doesn't remove its work tree ...
 551        test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" '
 552                prolog &&
 553                reset_work_tree_to add_sub1 &&
 554                (
 555                        cd submodule_update &&
 556                        git branch -t remove_sub1 origin/remove_sub1 &&
 557                        $command remove_sub1 &&
 558                        test_superproject_content origin/remove_sub1 &&
 559                        test_submodule_content sub1 origin/add_sub1
 560                )
 561        '
 562        # ... especially when it contains a .git directory.
 563        test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" '
 564                prolog &&
 565                reset_work_tree_to add_sub1 &&
 566                (
 567                        cd submodule_update &&
 568                        git branch -t remove_sub1 origin/remove_sub1 &&
 569                        replace_gitfile_with_git_dir sub1 &&
 570                        $command remove_sub1 &&
 571                        test_superproject_content origin/remove_sub1 &&
 572                        test_git_directory_is_unchanged sub1 &&
 573                        test_submodule_content sub1 origin/add_sub1
 574                )
 575        '
 576        # Replacing a submodule with files in a directory must fail as the
 577        # submodule work tree isn't removed ...
 578        test_expect_failure "$command: replace submodule with a directory must fail" '
 579                prolog &&
 580                reset_work_tree_to add_sub1 &&
 581                (
 582                        cd submodule_update &&
 583                        git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
 584                        test_must_fail $command replace_sub1_with_directory &&
 585                        test_superproject_content origin/add_sub1 &&
 586                        test_submodule_content sub1 origin/add_sub1
 587                )
 588        '
 589        # ... especially when it contains a .git directory.
 590        test_expect_failure "$command: replace submodule containing a .git directory with a directory must fail" '
 591                prolog &&
 592                reset_work_tree_to add_sub1 &&
 593                (
 594                        cd submodule_update &&
 595                        git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
 596                        replace_gitfile_with_git_dir sub1 &&
 597                        test_must_fail $command replace_sub1_with_directory &&
 598                        test_superproject_content origin/add_sub1 &&
 599                        test_git_directory_is_unchanged sub1 &&
 600                        test_submodule_content sub1 origin/add_sub1
 601                )
 602        '
 603        # Replacing it with a file must fail as it could throw away any local
 604        # work tree changes ...
 605        test_expect_failure "$command: replace submodule with a file must fail" '
 606                prolog &&
 607                reset_work_tree_to add_sub1 &&
 608                (
 609                        cd submodule_update &&
 610                        git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
 611                        test_must_fail $command replace_sub1_with_file &&
 612                        test_superproject_content origin/add_sub1 &&
 613                        test_submodule_content sub1 origin/add_sub1
 614                )
 615        '
 616        # ... or even destroy unpushed parts of submodule history if that
 617        # still uses a .git directory.
 618        test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
 619                prolog &&
 620                reset_work_tree_to add_sub1 &&
 621                (
 622                        cd submodule_update &&
 623                        git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
 624                        replace_gitfile_with_git_dir sub1 &&
 625                        test_must_fail $command replace_sub1_with_file &&
 626                        test_superproject_content origin/add_sub1 &&
 627                        test_git_directory_is_unchanged sub1 &&
 628                        test_submodule_content sub1 origin/add_sub1
 629                )
 630        '
 631
 632        ########################## Modified submodule #########################
 633        # Updating a submodule sha1 doesn't update the submodule's work tree
 634        test_expect_success "$command: modified submodule does not update submodule work tree" '
 635                prolog &&
 636                reset_work_tree_to add_sub1 &&
 637                (
 638                        cd submodule_update &&
 639                        git branch -t modify_sub1 origin/modify_sub1 &&
 640                        $command modify_sub1 &&
 641                        test_superproject_content origin/modify_sub1 &&
 642                        test_submodule_content sub1 origin/add_sub1 &&
 643                        git submodule update &&
 644                        test_submodule_content sub1 origin/modify_sub1
 645                )
 646        '
 647        # Updating a submodule to an invalid sha1 doesn't update the
 648        # submodule's work tree, subsequent update will fail
 649        test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" '
 650                prolog &&
 651                reset_work_tree_to add_sub1 &&
 652                (
 653                        cd submodule_update &&
 654                        git branch -t invalid_sub1 origin/invalid_sub1 &&
 655                        $command invalid_sub1 &&
 656                        test_superproject_content origin/invalid_sub1 &&
 657                        test_submodule_content sub1 origin/add_sub1 &&
 658                        test_must_fail git submodule update &&
 659                        test_submodule_content sub1 origin/add_sub1
 660                )
 661        '
 662        # Updating a submodule from an invalid sha1 doesn't update the
 663        # submodule's work tree, subsequent update will succeed
 664        test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" '
 665                prolog &&
 666                reset_work_tree_to invalid_sub1 &&
 667                (
 668                        cd submodule_update &&
 669                        git branch -t valid_sub1 origin/valid_sub1 &&
 670                        $command valid_sub1 &&
 671                        test_superproject_content origin/valid_sub1 &&
 672                        test_dir_is_empty sub1 &&
 673                        git submodule update --init --recursive &&
 674                        test_submodule_content sub1 origin/valid_sub1
 675                )
 676        '
 677}