# Create a submodule layout used for all tests below. # # The following use cases are covered: # - New submodule (no_submodule => add_sub1) # - Removed submodule (add_sub1 => remove_sub1) # - Updated submodule (add_sub1 => modify_sub1) # - Submodule updated to invalid commit (add_sub1 => invalid_sub1) # - Submodule updated from invalid commit (invalid_sub1 => valid_sub1) # - Submodule replaced by tracked files in directory (add_sub1 => # replace_sub1_with_directory) # - Directory containing tracked files replaced by submodule # (replace_sub1_with_directory => replace_directory_with_sub1) # - Submodule replaced by tracked file with the same name (add_sub1 => # replace_sub1_with_file) # - Tracked file replaced by submodule (replace_sub1_with_file => # replace_file_with_sub1) # # --O-----O # / ^ replace_directory_with_sub1 # / replace_sub1_with_directory # /----O # / ^ # / modify_sub1 # O------O-------O # ^ ^\ ^ # | | \ remove_sub1 # | | -----O-----O # | | \ ^ replace_file_with_sub1 # | | \ replace_sub1_with_file # | add_sub1 --O-----O # no_submodule ^ valid_sub1 # invalid_sub1 # proc create_lib_submodule_repo { git init submodule_update_repo && shell { cd submodule_update_repo && echo "expect" >>.gitignore && echo "actual" >>.gitignore && echo "x" >file1 && echo "y" >file2 && git add .gitignore file1 file2 && git commit -m "Base" && git branch "no_submodule" && git checkout -b "add_sub1" && git submodule add ./. sub1 && git config -f .gitmodules submodule.sub1.ignore all && git config submodule.sub1.ignore all && git add .gitmodules && git commit -m "Add sub1" && git checkout -b remove_sub1 && git revert HEAD && git checkout -b "modify_sub1" "add_sub1" && git submodule update && shell { cd sub1 && git fetch && git checkout -b "modifications" && echo "z" >file2 && echo "x" >file3 && git add file2 file3 && git commit -m "modified file2 and added file3" && git push origin modifications } && git add sub1 && git commit -m "Modify sub1" && git checkout -b "replace_sub1_with_directory" "add_sub1" && git submodule update && shell { cd sub1 && git checkout modifications } && git rm --cached sub1 && rm sub1/.git* && git config -f .gitmodules --remove-section "submodule.sub1" && git add .gitmodules sub1/* && git commit -m "Replace sub1 with directory" && git checkout -b replace_directory_with_sub1 && git revert HEAD && git checkout -b "replace_sub1_with_file" "add_sub1" && git rm sub1 && echo "content" >sub1 && git add sub1 && git commit -m "Replace sub1 with file" && git checkout -b replace_file_with_sub1 && git revert HEAD && git checkout -b "invalid_sub1" "add_sub1" && git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 && git commit -m "Invalid sub1 commit" && git checkout -b valid_sub1 && git revert HEAD && git checkout master } } # Helper function to replace gitfile with .git directory proc replace_gitfile_with_git_dir { shell { cd $1 && global git_dir := $[git rev-parse --git-dir] && rm -f .git && cp -R $git_dir .git && env GIT_WORK_TREE=. git config --unset core.worktree } } # Test that the .git directory in the submodule is unchanged (except for the # core.worktree setting, which appears only in $GIT_DIR/modules/$1/config). # Call this function before test_submodule_content as the latter might # write the index file leading to false positive index differences. # # Note that this only supports submodules at the root level of the # superproject, with the default name, i.e. same as its path. proc test_git_directory_is_unchanged { shell { cd ".git/modules/$1" && # does core.worktree point at the right place? test $[git config core.worktree] = "../../../$1" && # remove it temporarily before comparing, as # "$1/.git/config" lacks it... git config --unset core.worktree } && diff -r ".git/modules/$1" "$1/.git" && shell { # ... and then restore. cd ".git/modules/$1" && git config core.worktree "../../../$1" } } # Helper function to be executed at the start of every test below, it sets up # the submodule repo if it doesn't exist and configures the most problematic # settings for diff.ignoreSubmodules. proc prolog { shell {test -d submodule_update_repo || create_lib_submodule_repo} && test_config_global diff.ignoreSubmodules all && test_config diff.ignoreSubmodules all } # Helper function to bring work tree back into the state given by the # commit. This includes trying to populate sub1 accordingly if it exists and # should be updated to an existing commit. proc reset_work_tree_to { rm -rf submodule_update && git clone submodule_update_repo submodule_update && shell { cd submodule_update && rm -rf sub1 && git checkout -f $1 && git status -u -s >actual && test_must_be_empty actual && global sha1 := $[git rev-parse --revs-only HEAD:sub1] && if test -n $sha1 && test $[cd "sub1" && git rev-parse --verify "$sha1^{commit}] { git submodule update --init --recursive "sub1" } } } # Test that the superproject contains the content according to commit "$1" # (the work tree must match the index for everything but submodules but the # index must exactly match the given commit including any submodule SHA-1s). proc test_superproject_content { git diff-index --cached $1 >actual && test_must_be_empty actual && git diff-files --ignore-submodules >actual && test_must_be_empty actual } # Test that the given submodule at path "$1" contains the content according # to the submodule commit recorded in the superproject's commit "$2" proc test_submodule_content { if test $Argc != 2 { echo "test_submodule_content needs two arguments" return 1 } && global submodule := $1 && global commit := $2 && test -d "$submodule"/ && if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git { echo "Submodule $submodule is not populated" return 1 } && global sha1 := $[git rev-parse --verify "$commit:$submodule] && if test -z $sha1 { echo "Couldn't retrieve SHA-1 of $submodule for $commit" return 1 } && shell { cd $submodule && git status -u -s >actual && test_must_be_empty actual && git diff $sha1 >actual && test_must_be_empty actual } } # Test that the following transitions are correctly handled: # - Updated submodule # - New submodule # - Removed submodule # - 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 # # 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. # # Removing a submodule containing a .git directory must fail even when forced # to protect the history! # # Test that submodule contents are currently not updated when switching # between commits that change a submodule. proc test_submodule_switch { global 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 { # Restoring stash fails to restore submodule index entry global RESULT := '"failure'" } else { global RESULT := '"success'" } test_expect_$RESULT "$command: added submodule creates empty directory" ' prolog && reset_work_tree_to no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && $command add_sub1 && test_superproject_content origin/add_sub1 && test_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/add_sub1 ) ' # ... and doesn't care if it already exists ... test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" ' prolog && reset_work_tree_to no_submodule && ( cd submodule_update && mkdir sub1 && git branch -t add_sub1 origin/add_sub1 && $command add_sub1 && test_superproject_content origin/add_sub1 && test_dir_is_empty sub1 && git submodule update --init --recursive && 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 unignored file with same name" ' prolog && reset_work_tree_to 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 ) ' # Replacing a tracked file with a submodule produces an empty # directory ... test_expect_$RESULT "$command: replace tracked file with submodule creates empty directory" ' prolog && reset_work_tree_to 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_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/replace_file_with_sub1 ) ' # ... as does removing a directory with tracked files with a # submodule. if test $KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR = 1 { # Non fast-forward merges fail with "Directory sub1 doesn't # exist. sub1" because the empty submodule directory is not # created global RESULT := '"failure'" } else { global RESULT := '"success'" } test_expect_$RESULT "$command: replace directory with submodule" ' prolog && reset_work_tree_to 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_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/replace_directory_with_sub1 ) ' ######################## Disappearing submodule ####################### # Removing a submodule doesn't remove its work tree ... if test $KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES = 1 { global RESULT := '"failure'" } else { global RESULT := '"success'" } test_expect_$RESULT "$command: removed submodule leaves submodule directory and its contents in place" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t remove_sub1 origin/remove_sub1 && $command remove_sub1 && test_superproject_content origin/remove_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # ... especially when it contains a .git directory. test_expect_$RESULT "$command: removed submodule leaves submodule containing a .git directory alone" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t remove_sub1 origin/remove_sub1 && replace_gitfile_with_git_dir sub1 && $command remove_sub1 && test_superproject_content origin/remove_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # Replacing a submodule with files in a directory must fail as the # submodule work tree isn't removed ... if test $KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES = 1 { # Non fast-forward merges attempt to merge the former # submodule files with the newly checked out ones in the # directory of the same name while it shouldn't. global RESULT := '"failure'" } else { global RESULT := '"success'" } test_expect_$RESULT "$command: replace submodule with a directory must fail" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && test_must_fail $command replace_sub1_with_directory && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # ... especially when it contains a .git directory. test_expect_$RESULT "$command: replace submodule containing a .git directory with a directory must fail" ' prolog && reset_work_tree_to add_sub1 && ( 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 && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # Replacing it with a file must fail as it could throw away any local # work tree changes ... test_expect_failure "$command: replace submodule with a file must fail" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t replace_sub1_with_file origin/replace_sub1_with_file && test_must_fail $command replace_sub1_with_file && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # ... or even destroy unpushed parts of submodule history if that # still uses a .git directory. test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" ' prolog && reset_work_tree_to add_sub1 && ( 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 && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' ########################## Modified submodule ######################### # Updating a submodule sha1 doesn't update the submodule's work tree if test $KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT = 1 { # When cherry picking a SHA-1 update for an ignored submodule # the commit incorrectly fails with "The previous cherry-pick # is now empty, possibly due to conflict resolution." global RESULT := '"failure'" } else { global RESULT := '"success'" } test_expect_$RESULT "$command: modified submodule does not update submodule work tree" ' prolog && reset_work_tree_to 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/add_sub1 && git submodule update && 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_$RESULT "$command: modified submodule does not update submodule work tree to invalid commit" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t invalid_sub1 origin/invalid_sub1 && $command invalid_sub1 && test_superproject_content origin/invalid_sub1 && test_submodule_content sub1 origin/add_sub1 && test_must_fail git submodule update && test_submodule_content sub1 origin/add_sub1 ) ' # Updating a submodule from an invalid sha1 doesn't update the # submodule's work tree, subsequent update will succeed test_expect_$RESULT "$command: modified submodule does not update submodule work tree from invalid commit" ' prolog && reset_work_tree_to invalid_sub1 && ( cd submodule_update && git branch -t valid_sub1 origin/valid_sub1 && $command valid_sub1 && test_superproject_content origin/valid_sub1 && test_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/valid_sub1 ) ' } # Test that submodule contents are currently not updated when switching # between commits that change a submodule, but throwing away local changes in # the superproject is allowed. proc test_submodule_forced_switch { global command := $1 ######################### Appearing submodule ######################### # Switching to a commit letting a submodule appear creates empty dir ... test_expect_success "$command: added submodule creates empty directory" ' prolog && reset_work_tree_to no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && $command add_sub1 && test_superproject_content origin/add_sub1 && test_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/add_sub1 ) ' # ... and doesn't care if it already exists ... test_expect_success "$command: added submodule leaves existing empty directory alone" ' prolog && reset_work_tree_to 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_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/add_sub1 ) ' # ... unless there is an untracked file in its place. test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' prolog && reset_work_tree_to no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && >sub1 && $command add_sub1 && test_superproject_content origin/add_sub1 && test_dir_is_empty sub1 ) ' # Replacing a tracked file with a submodule produces an empty # directory ... test_expect_success "$command: replace tracked file with submodule creates empty directory" ' prolog && reset_work_tree_to 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_dir_is_empty sub1 && git submodule update --init --recursive && 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 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_dir_is_empty sub1 && git submodule update --init --recursive && 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 add_sub1 && ( cd submodule_update && git branch -t remove_sub1 origin/remove_sub1 && $command remove_sub1 && test_superproject_content origin/remove_sub1 && test_submodule_content sub1 origin/add_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 add_sub1 && ( cd submodule_update && git branch -t remove_sub1 origin/remove_sub1 && replace_gitfile_with_git_dir sub1 && $command remove_sub1 && test_superproject_content origin/remove_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # Replacing a submodule with files in a directory must fail as the # submodule work tree isn't removed ... test_expect_failure "$command: replace submodule with a directory must fail" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && test_must_fail $command replace_sub1_with_directory && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # ... especially when it contains a .git directory. test_expect_failure "$command: replace submodule containing a .git directory with a directory must fail" ' prolog && reset_work_tree_to add_sub1 && ( 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 && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # Replacing it with a file must fail as it could throw away any local # work tree changes ... test_expect_failure "$command: replace submodule with a file must fail" ' prolog && reset_work_tree_to add_sub1 && ( cd submodule_update && git branch -t replace_sub1_with_file origin/replace_sub1_with_file && test_must_fail $command replace_sub1_with_file && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' # ... or even destroy unpushed parts of submodule history if that # still uses a .git directory. test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" ' prolog && reset_work_tree_to add_sub1 && ( 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 && test_superproject_content origin/add_sub1 && test_git_directory_is_unchanged sub1 && test_submodule_content sub1 origin/add_sub1 ) ' ########################## Modified submodule ######################### # Updating a submodule sha1 doesn't update the submodule's work tree test_expect_success "$command: modified submodule does not update submodule work tree" ' prolog && reset_work_tree_to 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/add_sub1 && git submodule update && 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 add_sub1 && ( cd submodule_update && git branch -t invalid_sub1 origin/invalid_sub1 && $command invalid_sub1 && test_superproject_content origin/invalid_sub1 && test_submodule_content sub1 origin/add_sub1 && test_must_fail git submodule update && test_submodule_content sub1 origin/add_sub1 ) ' # Updating a submodule from an invalid sha1 doesn't update the # submodule's work tree, subsequent update will succeed test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" ' prolog && reset_work_tree_to invalid_sub1 && ( cd submodule_update && git branch -t valid_sub1 origin/valid_sub1 && $command valid_sub1 && test_superproject_content origin/valid_sub1 && test_dir_is_empty sub1 && git submodule update --init --recursive && test_submodule_content sub1 origin/valid_sub1 ) ' } (CommandList children: [ (FuncDef name: create_lib_submodule_repo body: (BraceGroup children: [ (AndOr children: [ (C {(git)} {(init)} {(submodule_update_repo)}) (Subshell child: (AndOr children: [ (C {(cd)} {(submodule_update_repo)}) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ (expect))}] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(.gitignore)} spids: [132] ) ] ) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ (actual))}] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(.gitignore)} spids: [144] ) ] ) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ (x))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(file1)} spids: [156] ) ] ) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ (y))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(file2)} spids: [168] ) ] ) (AndOr children: [ (C {(git)} {(add)} {(.gitignore)} {(file1)} {(file2)}) (AndOr children: [ (C {(git)} {(commit)} {(-m)} {(DQ (Base))}) (AndOr children: [ (C {(git)} {(branch)} {(DQ (no_submodule))}) (AndOr children: [ (C {(git)} {(checkout)} {(-b)} {(DQ (add_sub1))}) (AndOr children: [ (C {(git)} {(submodule)} {(add)} {(./.)} {(sub1)} ) (AndOr children: [ (C {(git)} {(config)} {(-f)} {(.gitmodules)} {(submodule.sub1.ignore)} {(all)} ) (AndOr children: [ (C {(git)} {(config)} {(submodule.sub1.ignore)} {(all)} ) (AndOr children: [ (C {(git)} {(add)} {(.gitmodules)} ) (AndOr children: [ (C {(git)} {(commit)} {(-m)} {(DQ ("Add sub1"))} ) (AndOr children: [ (C {(git)} {(checkout)} {(-b)} {(remove_sub1)} ) (AndOr children: [ (C {(git)} {(revert)} {(HEAD)} ) (AndOr children: [ (C {(git)} { ( checkout ) } {(-b)} {(DQ (modify_sub1))} {(DQ (add_sub1))} ) (AndOr children: [ (C {(git)} { ( submodule ) } {(update)} ) (AndOr children: [ (Subshell child: (AndOr children: [ (C { ( cd ) } {(sub1)} ) (AndOr children: [ (C { ( git ) } {(fetch)} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(DQ (modifications))} ) (AndOr children: [ (SimpleCommand words: [ { ( echo ) } { (DQ ( z ) ) } ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: { ( file2 ) } spids: [ 369 ] ) ] ) (AndOr children: [ (SimpleCommand words: [ { ( echo ) } { (DQ ( x ) ) } ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: { ( file3 ) } spids: [ 381 ] ) ] ) (AndOr children: [ (C { ( git ) } {(add)} {(file2)} {(file3)} ) (AndOr children: [ (C { ( git ) } {(commit)} {(-m)} {(DQ ("modified file2 and added file3"))} ) (C { ( git ) } {(push)} {(origin)} {(modifications)} ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [ 333 420 ] ) (AndOr children: [ (C { ( git ) } {(add)} {(sub1)} ) (AndOr children: [ (C { ( git ) } {(commit)} {(-m)} {(DQ ("Modify sub1"))} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(DQ (replace_sub1_with_directory))} {(DQ (add_sub1))} ) (AndOr children: [ (C { ( git ) } {(submodule)} {(update)} ) (AndOr children: [ (Subshell child: (AndOr children: [ (C { ( cd ) } {(sub1)} ) (C { ( git ) } {(checkout)} {(modifications)} ) ] op_id: Op_DAmp ) spids: [ 474 491 ] ) (AndOr children: [ (C { ( git ) } {(rm)} {(--cached)} {(sub1)} ) (AndOr children: [ (C { ( rm ) } {(sub1/.git) (Lit_Other "*")} ) (AndOr children: [ (C { ( git ) } {(config)} {(-f)} {(.gitmodules)} {(--remove-section)} {(DQ (submodule.sub1))} ) (AndOr children: [ (C { ( git ) } {(add)} {(.gitmodules)} {(sub1/) (Lit_Other "*")} ) (AndOr children: [ (C { ( git ) } {(commit)} {(-m)} {(DQ ("Replace sub1 with directory"))} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(replace_directory_with_sub1)} ) (AndOr children: [ (C { ( git ) } {(revert)} {(HEAD)} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(DQ (replace_sub1_with_file))} {(DQ (add_sub1))} ) (AndOr children: [ (C { ( git ) } {(rm)} {(sub1)} ) (AndOr children: [ (SimpleCommand words: [ { ( echo ) } { (DQ ( content ) ) } ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: { ( sub1 ) } spids: [ 610 ] ) ] ) (AndOr children: [ (C { ( git ) } {(add)} {(sub1)} ) (AndOr children: [ (C { ( git ) } {(commit)} {(-m)} {(DQ ("Replace sub1 with file"))} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(replace_file_with_sub1)} ) (AndOr children: [ (C { ( git ) } {(revert)} {(HEAD)} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(DQ (invalid_sub1))} {(DQ (add_sub1))} ) (AndOr children: [ (C { ( git ) } {(update-index)} {(--cacheinfo)} {(160000)} {(0123456789012345678901234567890123456789)} {(sub1)} ) (AndOr children: [ (C { ( git ) } {(commit)} {(-m)} {(DQ ("Invalid sub1 commit"))} ) (AndOr children: [ (C { ( git ) } {(checkout)} {(-b)} {(valid_sub1)} ) (AndOr children: [ (C { ( git ) } {(revert)} {(HEAD)} ) (C { ( git ) } {(checkout)} {(master)} ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [116 731] ) ] op_id: Op_DAmp ) ] spids: [104] ) spids: [99 103] ) (FuncDef name: replace_gitfile_with_git_dir body: (BraceGroup children: [ (Subshell child: (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Number "$1"))}) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:git_dir) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [(C {(git)} {(rev-parse)} {(--git-dir)})] ) left_token: spids: [761 767] ) ) } spids: [759] ) ] spids: [759] ) (AndOr children: [ (C {(rm)} {(-f)} {(.git)}) (AndOr children: [ (C {(cp)} {(-R)} {(DQ ($ VSub_Name "$git_dir"))} {(.git)}) (SimpleCommand words: [{(git)} {(config)} {(--unset)} {(core.worktree)}] more_env: [(env_pair name:GIT_WORK_TREE val:{(.)} spids:[795])] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [747 807] ) ] spids: [744] ) spids: [739 743] ) (FuncDef name: test_git_directory_is_unchanged body: (BraceGroup children: [ (AndOr children: [ (Subshell child: (AndOr children: [ (C {(cd)} {(DQ (.git/modules/) ($ VSub_Number "$1"))}) (AndOr children: [ (C {(test)} { (DQ (CommandSubPart command_list: (CommandList children: [(C {(git)} {(config)} {(core.worktree)})] ) left_token: spids: [861 867] ) ) } {(Lit_Other "=")} {(DQ (../../../) ($ VSub_Number "$1"))} ) (C {(git)} {(config)} {(--unset)} {(core.worktree)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [841 897] ) (AndOr children: [ (C {(diff)} {(-r)} {(DQ (.git/modules/) ($ VSub_Number "$1"))} {(DQ ($ VSub_Number "$1") (/.git))} ) (Subshell child: (AndOr children: [ (C {(cd)} {(DQ (.git/modules/) ($ VSub_Number "$1"))}) (C {(git)} {(config)} {(core.worktree)} {(DQ (../../../) ($ VSub_Number "$1"))} ) ] op_id: Op_DAmp ) spids: [919 948] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [838] ) spids: [833 837] ) (FuncDef name: prolog body: (BraceGroup children: [ (AndOr children: [ (Subshell child: (AndOr children: [ (C {(test)} {(-d)} {(submodule_update_repo)}) (C {(create_lib_submodule_repo)}) ] op_id: Op_DPipe ) spids: [970 980] ) (AndOr children: [ (C {(test_config_global)} {(diff.ignoreSubmodules)} {(all)}) (C {(test_config)} {(diff.ignoreSubmodules)} {(all)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [967] ) spids: [962 966] ) (FuncDef name: reset_work_tree_to body: (BraceGroup children: [ (AndOr children: [ (C {(rm)} {(-rf)} {(submodule_update)}) (AndOr children: [ (C {(git)} {(clone)} {(submodule_update_repo)} {(submodule_update)}) (Subshell child: (AndOr children: [ (C {(cd)} {(submodule_update)}) (AndOr children: [ (C {(rm)} {(-rf)} {(sub1)}) (AndOr children: [ (C {(git)} {(checkout)} {(-f)} {(DQ ($ VSub_Number "$1"))}) (AndOr children: [ (SimpleCommand words: [{(git)} {(status)} {(-u)} {(-s)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [1080] ) ] ) (AndOr children: [ (C {(test_must_be_empty)} {(actual)}) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:sha1) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(git)} {(rev-parse)} {(--revs-only)} {(HEAD) (Lit_Other ":") (sub1)} ) ] ) left_token: spids: [1094 1104] ) } spids: [1093] ) ] spids: [1093] ) (If arms: [ (if_arm cond: [ (AndOr children: [ (C {(test)} {(-n)} {(DQ ($ VSub_Name "$sha1"))} ) (C {(test)} { (CommandSubPart command_list: (CommandList children: [ (AndOr children: [ (C {(cd)} {(DQ (sub1))}) (C {(git)} {(rev-parse)} {(--verify)} {(DQ ($ VSub_Name "$sha1") ("^{commit}"))} ) ] op_id: Op_DAmp ) ] ) left_token: spids: [1124 1143] ) } ) ] op_id: Op_DAmp ) ] action: [ (C {(git)} {(submodule)} {(update)} {(--init)} {(--recursive)} {(DQ (sub1))} ) ] spids: [-1 1146] ) ] spids: [-1 1164] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [1040 1167] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [1017] ) spids: [1012 1016] ) (FuncDef name: test_superproject_content body: (BraceGroup children: [ (AndOr children: [ (SimpleCommand words: [{(git)} {(diff-index)} {(--cached)} {(DQ ($ VSub_Number "$1"))}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(actual)} spids:[1199])] ) (AndOr children: [ (C {(test_must_be_empty)} {(actual)}) (AndOr children: [ (SimpleCommand words: [{(git)} {(diff-files)} {(--ignore-submodules)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [1218] ) ] ) (C {(test_must_be_empty)} {(actual)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [1186] ) spids: [1181 1185] ) (FuncDef name: test_submodule_content body: (BraceGroup children: [ (AndOr children: [ (If arms: [ (if_arm cond: [(C {(test)} {($ VSub_Pound "$#")} {(KW_Bang "!") (Lit_Other "=")} {(2)})] action: [ (C {(echo)} {(DQ ("test_submodule_content needs two arguments"))}) (ControlFlow token: arg_word: {(1)} ) ] spids: [-1 1257] ) ] spids: [-1 1272] ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:submodule) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [1277] ) ] spids: [1277] ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:commit) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [1285] ) ] spids: [1285] ) (AndOr children: [ (C {(test)} {(-d)} {(DQ ($ VSub_Name "$submodule")) (/)}) (AndOr children: [ (If arms: [ (if_arm cond: [ (AndOr children: [ (Pipeline children: [ (C {(test)} {(-f)} {(DQ ($ VSub_Name "$submodule")) (/.git)} ) ] negated: True ) (Pipeline children: [ (C {(test)} {(-d)} {(DQ ($ VSub_Name "$submodule")) (/.git)} ) ] negated: True ) ] op_id: Op_DAmp ) ] action: [ (C {(echo)} { (DQ ("Submodule ") ($ VSub_Name "$submodule") (" is not populated") ) } ) (ControlFlow token: arg_word: {(1)} ) ] spids: [-1 1332] ) ] spids: [-1 1349] ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:sha1) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(git)} {(rev-parse)} {(--verify)} { (DQ ($ VSub_Name "$commit") (":") ($ VSub_Name "$submodule") ) } ) ] ) left_token: spids: [1355 1367] ) } spids: [1354] ) ] spids: [1354] ) (AndOr children: [ (If arms: [ (if_arm cond: [(C {(test)} {(-z)} {(DQ ($ VSub_Name "$sha1"))})] action: [ (C {(echo)} { (DQ ("Couldn't retrieve SHA-1 of ") ($ VSub_Name "$submodule") (" for ") ($ VSub_Name "$commit") ) } ) (ControlFlow token: arg_word: {(1)} ) ] spids: [-1 1383] ) ] spids: [-1 1401] ) (Subshell child: (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Name "$submodule"))}) (AndOr children: [ (SimpleCommand words: [{(git)} {(status)} {(-u)} {(-s)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [1426] ) ] ) (AndOr children: [ (C {(test_must_be_empty)} {(actual)}) (AndOr children: [ (SimpleCommand words: [ {(git)} {(diff)} {(DQ ($ VSub_Name "$sha1"))} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [1447] ) ] ) (C {(test_must_be_empty)} {(actual)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [1406 1458] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [1242] ) spids: [1237 1241] ) (FuncDef name: test_submodule_switch body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:command) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [1526] ) ] spids: [1526] ) (If arms: [ (if_arm cond: [ (C {(test)} {(DQ ($ VSub_Name "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES"))} {(Lit_Other "=")} {(1)} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (failure))} spids: [1560] ) ] spids: [1560] ) ] spids: [-1 1553] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (success))} spids: [1569] ) ] spids: [1569] ) ] spids: [1566 1575] ) (C {(test_expect_) ($ VSub_Name "$RESULT")} {(DQ ($ VSub_Name "$command") (": added submodule creates empty directory"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\t$command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": added submodule leaves existing empty directory alone") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tmkdir sub1 &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\t$command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": added submodule doesn't remove untracked unignored file with same name") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\t>sub1 &&\n"> <"\t\t\ttest_must_fail $command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/no_submodule &&\n"> <"\t\t\ttest_must_be_empty sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": replace tracked file with submodule creates empty directory") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to replace_sub1_with_file &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&\n"> <"\t\t\t$command replace_file_with_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/replace_file_with_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/replace_file_with_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (If arms: [ (if_arm cond: [ (C {(test)} { (DQ ($ VSub_Name "$KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR") ) } {(Lit_Other "=")} {(1)} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (failure))} spids: [1729] ) ] spids: [1729] ) ] spids: [-1 1714] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (success))} spids: [1738] ) ] spids: [1738] ) ] spids: [1735 1744] ) (C {(test_expect_) ($ VSub_Name "$RESULT")} {(DQ ($ VSub_Name "$command") (": replace directory with submodule"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to replace_sub1_with_directory &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> < "\t\t\tgit branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&\n" > <"\t\t\t$command replace_directory_with_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/replace_directory_with_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/replace_directory_with_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (If arms: [ (if_arm cond: [ (C {(test)} {(DQ ($ VSub_Name "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES"))} {(Lit_Other "=")} {(1)} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (failure))} spids: [1797] ) ] spids: [1797] ) ] spids: [-1 1794] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (success))} spids: [1806] ) ] spids: [1806] ) ] spids: [1803 1812] ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": removed submodule leaves submodule directory and its contents in place") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n"> <"\t\t\t$command remove_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/remove_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": removed submodule leaves submodule containing a .git directory alone") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\t$command remove_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/remove_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (If arms: [ (if_arm cond: [ (C {(test)} { (DQ ($ VSub_Name "$KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES" ) ) } {(Lit_Other "=")} {(1)} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (failure))} spids: [1903] ) ] spids: [1903] ) ] spids: [-1 1888] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (success))} spids: [1912] ) ] spids: [1912] ) ] spids: [1909 1918] ) (C {(test_expect_) ($ VSub_Name "$RESULT")} {(DQ ($ VSub_Name "$command") (": replace submodule with a directory must fail"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": replace submodule containing a .git directory with a directory must fail") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} {(DQ ($ VSub_Name "$command") (": replace submodule with a file must fail"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_file &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} { (DQ ($ VSub_Name "$command") (": replace submodule containing a .git directory with a file must fail") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_file &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (If arms: [ (if_arm cond: [ (C {(test)} {(DQ ($ VSub_Name "$KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT"))} {(Lit_Other "=")} {(1)} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (failure))} spids: [2072] ) ] spids: [2072] ) ] spids: [-1 2057] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:RESULT) op: Equal rhs: {(DQ (success))} spids: [2081] ) ] spids: [2081] ) ] spids: [2078 2087] ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t modify_sub1 origin/modify_sub1 &&\n"> <"\t\t\t$command modify_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/modify_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n"> <"\t\t\tgit submodule update &&\n"> <"\t\t\ttest_submodule_content sub1 origin/modify_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree to invalid commit") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t invalid_sub1 origin/invalid_sub1 &&\n"> <"\t\t\t$command invalid_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/invalid_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n"> <"\t\t\ttest_must_fail git submodule update &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_) ($ VSub_Name "$RESULT")} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree from invalid commit") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to invalid_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t valid_sub1 origin/valid_sub1 &&\n"> <"\t\t\t$command valid_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/valid_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/valid_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) ] spids: [1523] ) spids: [1518 1522] ) (FuncDef name: test_submodule_forced_switch body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:command) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [2201] ) ] spids: [2201] ) (C {(test_expect_success)} {(DQ ($ VSub_Name "$command") (": added submodule creates empty directory"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\t$command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": added submodule leaves existing empty directory alone") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\tmkdir sub1 &&\n"> <"\t\t\t$command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") ( ": added submodule does remove untracked unignored file with same name when forced" ) ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to no_submodule &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t add_sub1 origin/add_sub1 &&\n"> <"\t\t\t>sub1 &&\n"> <"\t\t\t$command add_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": replace tracked file with submodule creates empty directory") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to replace_sub1_with_file &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&\n"> <"\t\t\t$command replace_file_with_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/replace_file_with_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/replace_file_with_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} {(DQ ($ VSub_Name "$command") (": replace directory with submodule"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to replace_sub1_with_directory &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> < "\t\t\tgit branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&\n" > <"\t\t\t$command replace_directory_with_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/replace_directory_with_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/replace_directory_with_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": removed submodule leaves submodule directory and its contents in place") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n"> <"\t\t\t$command remove_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/remove_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": removed submodule leaves submodule containing a .git directory alone") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t remove_sub1 origin/remove_sub1 &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\t$command remove_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/remove_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} {(DQ ($ VSub_Name "$command") (": replace submodule with a directory must fail"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} { (DQ ($ VSub_Name "$command") (": replace submodule containing a .git directory with a directory must fail") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_directory &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} {(DQ ($ VSub_Name "$command") (": replace submodule with a file must fail"))} { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_file &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_failure)} { (DQ ($ VSub_Name "$command") (": replace submodule containing a .git directory with a file must fail") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t replace_sub1_with_file origin/replace_sub1_with_file &&\n"> <"\t\t\treplace_gitfile_with_git_dir sub1 &&\n"> <"\t\t\ttest_must_fail $command replace_sub1_with_file &&\n"> <"\t\t\ttest_superproject_content origin/add_sub1 &&\n"> <"\t\t\ttest_git_directory_is_unchanged sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t modify_sub1 origin/modify_sub1 &&\n"> <"\t\t\t$command modify_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/modify_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n"> <"\t\t\tgit submodule update &&\n"> <"\t\t\ttest_submodule_content sub1 origin/modify_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree to invalid commit") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to add_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t invalid_sub1 origin/invalid_sub1 &&\n"> <"\t\t\t$command invalid_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/invalid_sub1 &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1 &&\n"> <"\t\t\ttest_must_fail git submodule update &&\n"> <"\t\t\ttest_submodule_content sub1 origin/add_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ($ VSub_Name "$command") (": modified submodule does not update submodule work tree from invalid commit") ) } { (SQ <"\n"> <"\t\tprolog &&\n"> <"\t\treset_work_tree_to invalid_sub1 &&\n"> <"\t\t(\n"> <"\t\t\tcd submodule_update &&\n"> <"\t\t\tgit branch -t valid_sub1 origin/valid_sub1 &&\n"> <"\t\t\t$command valid_sub1 &&\n"> <"\t\t\ttest_superproject_content origin/valid_sub1 &&\n"> <"\t\t\ttest_dir_is_empty sub1 &&\n"> <"\t\t\tgit submodule update --init --recursive &&\n"> <"\t\t\ttest_submodule_content sub1 origin/valid_sub1\n"> <"\t\t)\n"> <"\t"> ) } ) ] spids: [2198] ) spids: [2193 2197] ) ] )