diff options
Diffstat (limited to 't')
37 files changed, 1526 insertions, 90 deletions
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh new file mode 100755 index 0000000000..79cdd34a54 --- /dev/null +++ b/t/lib-submodule-update.sh @@ -0,0 +1,680 @@ +# 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 +# +create_lib_submodule_repo () { + git init submodule_update_repo && + ( + 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 && + ( + 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 && + ( + 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 +replace_gitfile_with_git_dir () { + ( + cd "$1" && + git_dir="$(git rev-parse --git-dir)" && + rm -f .git && + cp -R "$git_dir" .git && + 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. +test_git_directory_is_unchanged () { + ( + 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" && + ( + # ... 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. +prolog () { + (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. +reset_work_tree_to () { + rm -rf submodule_update && + git clone submodule_update_repo submodule_update && + ( + cd submodule_update && + rm -rf sub1 && + git checkout -f "$1" && + git status -u -s >actual && + test_must_be_empty actual && + sha1=$(git rev-parse --revs-only HEAD:sub1) && + if test -n "$sha1" && + test $(cd "sub1" && git rev-parse --verify "$sha1^{commit}") + then + git submodule update --init --recursive "sub1" + fi + ) +} + +# 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). +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" +test_submodule_content () { + if test $# != 2 + then + echo "test_submodule_content needs two arguments" + return 1 + fi && + submodule="$1" && + commit="$2" && + test -d "$submodule"/ && + if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git + then + echo "Submodule $submodule is not populated" + return 1 + fi && + sha1=$(git rev-parse --verify "$commit:$submodule") && + if test -z "$sha1" + then + echo "Couldn't retrieve SHA-1 of $submodule for $commit" + return 1 + fi && + ( + 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. +test_submodule_switch () { + command="$1" + ######################### Appearing submodule ######################### + # Switching to a commit letting a submodule appear creates empty dir ... + if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1 + then + # Restoring stash fails to restore submodule index entry + RESULT="failure" + else + RESULT="success" + fi + test_expect_$RESULT "$command: added submodule creates empty directory" ' + 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 + then + # Non fast-forward merges fail with "Directory sub1 doesn't + # exist. sub1" because the empty submodule directory is not + # created + RESULT="failure" + else + RESULT="success" + fi + 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 + then + RESULT="failure" + else + RESULT="success" + fi + 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 + then + # 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. + RESULT="failure" + else + RESULT="success" + fi + 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 + then + # 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." + RESULT="failure" + else + RESULT="success" + fi + 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. +test_submodule_forced_switch () { + 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 + ) + ' +} diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh index 391e2b6492..f97c80556f 100755 --- a/t/t0011-hashmap.sh +++ b/t/t0011-hashmap.sh @@ -237,4 +237,17 @@ test_expect_success 'grow / shrink' ' ' +test_expect_success 'string interning' ' + +test_hashmap "intern value1 +intern Value1 +intern value2 +intern value2 +" "value1 +Value1 +value2 +value2" + +' + test_done diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh new file mode 100755 index 0000000000..20526aed34 --- /dev/null +++ b/t/t1013-read-tree-submodule.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +test_description='read-tree can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +test_submodule_switch "git read-tree -u -m" + +test_submodule_forced_switch "git read-tree -u --reset" + +test_done diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh new file mode 100755 index 0000000000..7fdf840b00 --- /dev/null +++ b/t/t1308-config-set.sh @@ -0,0 +1,200 @@ +#!/bin/sh + +test_description='Test git config-set API in different settings' + +. ./test-lib.sh + +# 'check_config get_* section.key value' verifies that the entry for +# section.key is 'value' +check_config () { + if test "$1" = expect_code + then + expect_code="$2" && shift && shift + else + expect_code=0 + fi && + op=$1 key=$2 && shift && shift && + if test $# != 0 + then + printf "%s\n" "$@" + fi >expect && + test_expect_code $expect_code test-config "$op" "$key" >actual && + test_cmp expect actual +} + +test_expect_success 'setup default config' ' + cat >.git/config <<\EOF + [case] + penguin = very blue + Movie = BadPhysics + UPPERCASE = true + MixedCase = true + my = + foo + baz = sam + [Cores] + WhatEver = Second + baz = bar + [cores] + baz = bat + [CORES] + baz = ball + [my "Foo bAr"] + hi = mixed-case + [my "FOO BAR"] + hi = upper-case + [my "foo bar"] + hi = lower-case + [case] + baz = bat + baz = hask + [lamb] + chop = 65 + head = none + [goat] + legs = 4 + head = true + skin = false + nose = 1 + horns + EOF +' + +test_expect_success 'get value for a simple key' ' + check_config get_value case.penguin "very blue" +' + +test_expect_success 'get value for a key with value as an empty string' ' + check_config get_value case.my "" +' + +test_expect_success 'get value for a key with value as NULL' ' + check_config get_value case.foo "(NULL)" +' + +test_expect_success 'upper case key' ' + check_config get_value case.UPPERCASE "true" && + check_config get_value case.uppercase "true" +' + +test_expect_success 'mixed case key' ' + check_config get_value case.MixedCase "true" && + check_config get_value case.MIXEDCASE "true" && + check_config get_value case.mixedcase "true" +' + +test_expect_success 'key and value with mixed case' ' + check_config get_value case.Movie "BadPhysics" +' + +test_expect_success 'key with case sensitive subsection' ' + check_config get_value "my.Foo bAr.hi" "mixed-case" && + check_config get_value "my.FOO BAR.hi" "upper-case" && + check_config get_value "my.foo bar.hi" "lower-case" +' + +test_expect_success 'key with case insensitive section header' ' + check_config get_value cores.baz "ball" && + check_config get_value Cores.baz "ball" && + check_config get_value CORES.baz "ball" && + check_config get_value coreS.baz "ball" +' + +test_expect_success 'key with case insensitive section header & variable' ' + check_config get_value CORES.BAZ "ball" && + check_config get_value cores.baz "ball" && + check_config get_value cores.BaZ "ball" && + check_config get_value cOreS.bAz "ball" +' + +test_expect_success 'find value with misspelled key' ' + check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\"" +' + +test_expect_success 'find value with the highest priority' ' + check_config get_value case.baz "hask" +' + +test_expect_success 'find integer value for a key' ' + check_config get_int lamb.chop 65 +' + +test_expect_success 'find integer if value is non parse-able' ' + check_config expect_code 128 get_int lamb.head +' + +test_expect_success 'find bool value for the entered key' ' + check_config get_bool goat.head 1 && + check_config get_bool goat.skin 0 && + check_config get_bool goat.nose 1 && + check_config get_bool goat.horns 1 && + check_config get_bool goat.legs 1 +' + +test_expect_success 'find multiple values' ' + check_config get_value_multi case.baz sam bat hask +' + +test_expect_success 'find value from a configset' ' + cat >config2 <<-\EOF && + [case] + baz = lama + [my] + new = silk + [case] + baz = ball + EOF + echo silk >expect && + test-config configset_get_value my.new config2 .git/config >actual && + test_cmp expect actual +' + +test_expect_success 'find value with highest priority from a configset' ' + echo hask >expect && + test-config configset_get_value case.baz config2 .git/config >actual && + test_cmp expect actual +' + +test_expect_success 'find value_list for a key from a configset' ' + cat >except <<-\EOF && + sam + bat + hask + lama + ball + EOF + test-config configset_get_value case.baz config2 .git/config >actual && + test_cmp expect actual +' + +test_expect_success 'proper error on non-existent files' ' + echo "Error (-1) reading configuration file non-existent-file." >expect && + test_expect_code 2 test-config configset_get_value foo.bar non-existent-file 2>actual && + test_cmp expect actual +' + +test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' ' + chmod -r .git/config && + test_when_finished "chmod +r .git/config" && + echo "Error (-1) reading configuration file .git/config." >expect && + test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual && + test_cmp expect actual +' + +test_expect_success 'proper error on error in default config files' ' + cp .git/config .git/config.old && + test_when_finished "mv .git/config.old .git/config" && + echo "[" >>.git/config && + echo "fatal: bad config file line 35 in .git/config" >expect && + test_expect_code 128 test-config get_value foo.bar 2>actual && + test_cmp expect actual +' + +test_expect_success 'proper error on error in custom config files' ' + echo "[" >>syntax-error && + echo "fatal: bad config file line 1 in syntax-error" >expect && + test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual && + test_cmp expect actual +' + +test_done diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index 28e93186ab..e5dc62e9ef 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -48,6 +48,7 @@ invalid_ref './foo/bar' invalid_ref 'foo/./bar' invalid_ref 'foo/bar/.' invalid_ref '.refs/foo' +invalid_ref 'refs/heads/foo.' invalid_ref 'heads/foo..bar' invalid_ref 'heads/foo?bar' valid_ref 'foo./bar' @@ -64,7 +65,6 @@ valid_ref "$(printf 'heads/fu\303\237')" invalid_ref 'heads/*foo/bar' --refspec-pattern invalid_ref 'heads/foo*/bar' --refspec-pattern invalid_ref 'heads/f*o/bar' --refspec-pattern -invalid_ref 'heads/foo*//bar' --refspec-pattern ref='foo' invalid_ref "$ref" @@ -129,20 +129,6 @@ valid_ref !MINGW "$ref" '--allow-onelevel --normalize' invalid_ref !MINGW "$ref" '--refspec-pattern --normalize' valid_ref !MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize' - -valid_ref 'refs/heads/a-very-long-refname' -invalid_ref 'refs/heads/.a-very-long-refname' -invalid_ref 'refs/heads/abcdefgh0123..' -invalid_ref 'refs/heads/abcdefgh01234..' -invalid_ref 'refs/heads/abcdefgh012345..' -invalid_ref 'refs/heads/abcdefgh0123456..' -invalid_ref 'refs/heads/abcdefgh01234567..' -valid_ref 'refs/heads/abcdefgh0123.a' -valid_ref 'refs/heads/abcdefgh01234.a' -valid_ref 'refs/heads/abcdefgh012345.a' -valid_ref 'refs/heads/abcdefgh0123456.a' -valid_ref 'refs/heads/abcdefgh01234567.a' - test_expect_success "check-ref-format --branch @{-1}" ' T=$(git write-tree) && sha1=$(echo A | git commit-tree $T) && diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index 06b18f8bc1..6847f75822 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -3,6 +3,7 @@ test_description='checkout can handle submodules' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh test_expect_success 'setup' ' mkdir submodule && @@ -62,4 +63,8 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/ ! test -s actual ' +test_submodule_switch "git checkout" + +test_submodule_forced_switch "git checkout -f" + test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 80e0a951ea..47b5682662 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -169,6 +169,29 @@ test_expect_success 'default to common base in @{upstream}s reflog if no upstrea test_cmp expect actual ' +test_expect_success 'cherry-picked commits and fork-point work together' ' + git checkout default-base && + echo Amended >A && + git commit -a --no-edit --amend && + test_commit B B && + test_commit new_B B "New B" && + test_commit C C && + git checkout default && + git reset --hard default-base@{4} && + test_commit D D && + git cherry-pick -2 default-base^ && + test_commit final_B B "Final B" && + git rebase && + echo Amended >expect && + test_cmp A expect && + echo "Final B" >expect && + test_cmp B expect && + echo C >expect && + test_cmp C expect && + echo D >expect && + test_cmp D expect +' + test_expect_success 'rebase -q is quiet' ' git checkout -b quiet topic && git rebase -q master >output.out 2>&1 && diff --git a/t/t3426-rebase-submodule.sh b/t/t3426-rebase-submodule.sh new file mode 100755 index 0000000000..d5b896d445 --- /dev/null +++ b/t/t3426-rebase-submodule.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +test_description='rebase can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh +. "$TEST_DIRECTORY"/lib-rebase.sh + +git_rebase () { + git status -su >expect && + ls -1pR * >>expect && + git checkout -b ours HEAD && + echo x >>file1 && + git add file1 && + git commit -m add_x && + git revert HEAD && + git status -su >actual && + ls -1pR * >>actual && + test_cmp expect actual && + git rebase "$1" +} + +test_submodule_switch "git_rebase" + +git_rebase_interactive () { + git status -su >expect && + ls -1pR * >>expect && + git checkout -b ours HEAD && + echo x >>file1 && + git add file1 && + git commit -m add_x && + git revert HEAD && + git status -su >actual && + ls -1pR * >>actual && + test_cmp expect actual && + set_fake_editor && + echo "fake-editor.sh" >.git/info/exclude && + git rebase -i "$1" +} + +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +# The real reason "replace directory with submodule" fails is because a +# directory "sub1" exists, but we reuse the suppression added for merge here +test_submodule_switch "git_rebase_interactive" + +test_done diff --git a/t/t3512-cherry-pick-submodule.sh b/t/t3512-cherry-pick-submodule.sh new file mode 100755 index 0000000000..6863b7bb6f --- /dev/null +++ b/t/t3512-cherry-pick-submodule.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +test_description='cherry-pick can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1 +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 +test_submodule_switch "git cherry-pick" + +test_done diff --git a/t/t3513-revert-submodule.sh b/t/t3513-revert-submodule.sh new file mode 100755 index 0000000000..a1c4e0216f --- /dev/null +++ b/t/t3513-revert-submodule.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='revert can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +# Create a revert that moves from HEAD (including any test modifications to +# the work tree) to $1 by first checking out $1 and reverting it. Reverting +# the revert is the transition we test for. We tar the current work tree +# first so we can restore the work tree test setup after doing the checkout +# and revert. We test here that the restored work tree content is identical +# to that at the beginning. The last revert is then tested by the framework. +git_revert () { + git status -su >expect && + ls -1pR * >>expect && + tar czf "$TRASH_DIRECTORY/tmp.tgz" * && + git checkout "$1" && + git revert HEAD && + rm -rf * && + tar xzf "$TRASH_DIRECTORY/tmp.tgz" && + git status -su >actual && + ls -1pR * >>actual && + test_cmp expect actual && + git revert HEAD +} + +KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1 +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +test_submodule_switch "git_revert" + +test_done diff --git a/t/t3906-stash-submodule.sh b/t/t3906-stash-submodule.sh new file mode 100755 index 0000000000..d7219d6f8f --- /dev/null +++ b/t/t3906-stash-submodule.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +test_description='stash apply can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +git_stash () { + git status -su >expect && + ls -1pR * >>expect && + git read-tree -u -m "$1" && + git stash && + git status -su >actual && + ls -1pR * >>actual && + test_cmp expect actual && + git stash apply +} + +KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES=1 +KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1 +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +test_submodule_switch "git_stash" + +test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 805b055c89..6ec6072118 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -324,4 +324,14 @@ test_expect_success 'diff --cached -- file on unborn branch' ' test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result ' +test_expect_success 'diff-tree --stdin with log formatting' ' + cat >expect <<-\EOF && + Side + Third + Second + EOF + git rev-list master | git diff-tree --stdin --format=%s -s >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 34591c23da..1dbaa3864a 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -52,15 +52,15 @@ do echo "*.java diff=$p" >.gitattributes && test_expect_code 1 git diff --no-index \ A.java B.java 2>msg && - ! test_i18ngrep fatal msg && - ! test_i18ngrep error msg + test_i18ngrep ! fatal msg && + test_i18ngrep ! error msg ' test_expect_success "builtin $p wordRegex pattern compiles" ' echo "*.java diff=$p" >.gitattributes && test_expect_code 1 git diff --no-index --word-diff \ A.java B.java 2>msg && - ! test_i18ngrep fatal msg && - ! test_i18ngrep error msg + test_i18ngrep ! fatal msg && + test_i18ngrep ! error msg ' done diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh index 41913c3aa3..0b4f7dfdc6 100755 --- a/t/t4038-diff-combined.sh +++ b/t/t4038-diff-combined.sh @@ -401,4 +401,38 @@ test_expect_success 'combine diff missing delete bug' ' compare_diff_patch expected actual ' +test_expect_success 'combine diff gets tree sorting right' ' + # create a directory and a file that sort differently in trees + # versus byte-wise (implied "/" sorts after ".") + git checkout -f master && + mkdir foo && + echo base >foo/one && + echo base >foo/two && + echo base >foo.ext && + git add foo foo.ext && + git commit -m base && + + # one side modifies a file in the directory, along with the root + # file... + echo master >foo/one && + echo master >foo.ext && + git commit -a -m master && + + # the other side modifies the other file in the directory + git checkout -b other HEAD^ && + echo other >foo/two && + git commit -a -m other && + + # And now we merge. The files in the subdirectory will resolve cleanly, + # meaning that a combined diff will not find them interesting. But it + # will find the tree itself interesting, because it had to be merged. + git checkout master && + git merge other && + + printf "MM\tfoo\n" >expect && + git diff-tree -c --name-status -t HEAD >actual.tmp && + sed 1d <actual.tmp >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 463d63bde0..e4328964a7 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -26,8 +26,10 @@ add_file () { echo "$name" >"$name" && git add "$name" && test_tick && - msg_added_iso88591=$(echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding) && - git -c "i18n.commitEncoding=$test_encoding" commit -m "$msg_added_iso88591" + # "git commit -m" would break MinGW, as Windows refuse to pass + # $test_encoding encoded parameter to git. + echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding | + git -c "i18n.commitEncoding=$test_encoding" commit -F - done >/dev/null && git rev-parse --short --verify HEAD ) diff --git a/t/t4137-apply-submodule.sh b/t/t4137-apply-submodule.sh new file mode 100755 index 0000000000..a9bd40a6d0 --- /dev/null +++ b/t/t4137-apply-submodule.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='git apply handling submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +apply_index () { + git diff --ignore-submodules=dirty "..$1" | git apply --index - +} + +test_submodule_switch "apply_index" + +apply_3way () { + git diff --ignore-submodules=dirty "..$1" | git apply --3way - +} + +test_submodule_switch "apply_3way" + +test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index c84ec9ae61..349c531989 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -31,7 +31,7 @@ test_expect_success 'set up basic repos' ' git add foo && test_tick && git config i18n.commitEncoding $test_encoding && - git commit -m "$(commit_msg $test_encoding)" && + commit_msg $test_encoding | git commit -F - && git add bar && test_tick && git commit -m "add bar" && diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh new file mode 100755 index 0000000000..8bde7dbb6d --- /dev/null +++ b/t/t4255-am-submodule.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +test_description='git am handling submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +am () { + git format-patch --stdout --ignore-submodules=dirty "..$1" | git am - +} + +test_submodule_switch "am" + +am_3way () { + git format-patch --stdout --ignore-submodules=dirty "..$1" | git am --3way - +} + +KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 +test_submodule_switch "am_3way" + +test_done diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 305bcac6b7..83d20c4ba9 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -113,4 +113,9 @@ test_expect_success 'archive empty subtree by direct pathspec' ' check_dir extract sub ' +test_expect_success 'archive applies umask even for pax headers' ' + git archive --format=tar HEAD >archive.tar && + ! grep 0666 archive.tar +' + test_done diff --git a/t/t5311-pack-bitmaps-shallow.sh b/t/t5311-pack-bitmaps-shallow.sh new file mode 100755 index 0000000000..872a95df33 --- /dev/null +++ b/t/t5311-pack-bitmaps-shallow.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +test_description='check bitmap operation with shallow repositories' +. ./test-lib.sh + +# We want to create a situation where the shallow, grafted +# view of reachability does not match reality in a way that +# might cause us to send insufficient objects. +# +# We do this with a history that repeats a state, like: +# +# A -- B -- C +# file=1 file=2 file=1 +# +# and then create a shallow clone to the second commit, B. +# In a non-shallow clone, that would mean we already have +# the tree for A. But in a shallow one, we've grafted away +# A, and fetching A to B requires that the other side send +# us the tree for file=1. +test_expect_success 'setup shallow repo' ' + echo 1 >file && + git add file && + git commit -m orig && + echo 2 >file && + git commit -a -m update && + git clone --no-local --bare --depth=1 . shallow.git && + echo 1 >file && + git commit -a -m repeat +' + +test_expect_success 'turn on bitmaps in the parent' ' + git repack -adb +' + +test_expect_success 'shallow fetch from bitmapped repo' ' + (cd shallow.git && git fetch) +' + +test_done diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh index 94553e1039..b46118846c 100755 --- a/t/t5539-fetch-http-shallow.sh +++ b/t/t5539-fetch-http-shallow.sh @@ -54,6 +54,7 @@ EOF test_expect_success 'no shallow lines after receiving ACK ready' ' ( cd shallow && + test_tick && for i in $(test_seq 15) do git checkout --orphan unrelated$i && diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh new file mode 100755 index 0000000000..accfa5cc0c --- /dev/null +++ b/t/t5572-pull-submodule.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='pull can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +reset_branch_to_HEAD () { + git branch -D "$1" && + git checkout -b "$1" HEAD && + git branch --set-upstream-to="origin/$1" "$1" +} + +git_pull () { + reset_branch_to_HEAD "$1" && + git pull +} + +# pulls without conflicts +test_submodule_switch "git_pull" + +git_pull_ff () { + reset_branch_to_HEAD "$1" && + git pull --ff +} + +test_submodule_switch "git_pull_ff" + +git_pull_ff_only () { + reset_branch_to_HEAD "$1" && + git pull --ff-only +} + +test_submodule_switch "git_pull_ff_only" + +git_pull_noff () { + reset_branch_to_HEAD "$1" && + git pull --no-ff +} + +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 +test_submodule_switch "git_pull_noff" + +test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index 88ed3191e8..a02a45afd2 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -35,13 +35,13 @@ test_expect_success 'setup' ' : >foo && git add foo && git config i18n.commitEncoding $test_encoding && - git commit -m "$added_iso88591" && + echo "$added_iso88591" | git commit -F - && head1=$(git rev-parse --verify HEAD) && head1_short=$(git rev-parse --verify --short $head1) && tree1=$(git rev-parse --verify HEAD:) && tree1_short=$(git rev-parse --verify --short $tree1) && echo "$changed" > foo && - git commit -a -m "$changed_iso88591" && + echo "$changed_iso88591" | git commit -a -F - && head2=$(git rev-parse --verify HEAD) && head2_short=$(git rev-parse --verify --short $head2) && tree2=$(git rev-parse --verify HEAD:) && diff --git a/t/t6041-bisect-submodule.sh b/t/t6041-bisect-submodule.sh new file mode 100755 index 0000000000..c6b7aa6977 --- /dev/null +++ b/t/t6041-bisect-submodule.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='bisect can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +git_bisect () { + git status -su >expect && + ls -1pR * >>expect && + tar czf "$TRASH_DIRECTORY/tmp.tgz" * && + GOOD=$(git rev-parse --verify HEAD) && + git checkout "$1" && + echo "foo" >bar && + git add bar && + git commit -m "bisect bad" && + BAD=$(git rev-parse --verify HEAD) && + git reset --hard HEAD^^ && + git submodule update && + git bisect start && + git bisect good $GOOD && + rm -rf * && + tar xzf "$TRASH_DIRECTORY/tmp.tgz" && + git status -su >actual && + ls -1pR * >>actual && + test_cmp expect actual && + git bisect bad $BAD +} + +test_submodule_switch "git_bisect" + +test_done diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 68b3cb26d9..4d5a25eedf 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -7,8 +7,9 @@ test_description='Tests replace refs functionality' exec </dev/null . ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" -add_and_commit_file() +add_and_commit_file () { _file="$1" _msg="$2" @@ -18,6 +19,38 @@ add_and_commit_file() git commit --quiet -m "$_file: $_msg" } +commit_buffer_contains_parents () +{ + git cat-file commit "$1" >payload && + sed -n -e '/^$/q' -e '/^parent /p' <payload >actual && + shift && + for _parent + do + echo "parent $_parent" + done >expected && + test_cmp expected actual +} + +commit_peeling_shows_parents () +{ + _parent_number=1 + _commit="$1" + shift && + for _parent + do + _found=$(git rev-parse --verify $_commit^$_parent_number) || return 1 + test "$_found" = "$_parent" || return 1 + _parent_number=$(( $_parent_number + 1 )) + done && + test_must_fail git rev-parse --verify $_commit^$_parent_number +} + +commit_has_parents () +{ + commit_buffer_contains_parents "$@" && + commit_peeling_shows_parents "$@" +} + HASH1= HASH2= HASH3= @@ -27,36 +60,36 @@ HASH6= HASH7= test_expect_success 'set up buggy branch' ' - echo "line 1" >> hello && - echo "line 2" >> hello && - echo "line 3" >> hello && - echo "line 4" >> hello && + echo "line 1" >>hello && + echo "line 2" >>hello && + echo "line 3" >>hello && + echo "line 4" >>hello && add_and_commit_file hello "4 lines" && HASH1=$(git rev-parse --verify HEAD) && - echo "line BUG" >> hello && - echo "line 6" >> hello && - echo "line 7" >> hello && - echo "line 8" >> hello && + echo "line BUG" >>hello && + echo "line 6" >>hello && + echo "line 7" >>hello && + echo "line 8" >>hello && add_and_commit_file hello "4 more lines with a BUG" && HASH2=$(git rev-parse --verify HEAD) && - echo "line 9" >> hello && - echo "line 10" >> hello && + echo "line 9" >>hello && + echo "line 10" >>hello && add_and_commit_file hello "2 more lines" && HASH3=$(git rev-parse --verify HEAD) && - echo "line 11" >> hello && + echo "line 11" >>hello && add_and_commit_file hello "1 more line" && HASH4=$(git rev-parse --verify HEAD) && - sed -e "s/BUG/5/" hello > hello.new && + sed -e "s/BUG/5/" hello >hello.new && mv hello.new hello && add_and_commit_file hello "BUG fixed" && HASH5=$(git rev-parse --verify HEAD) && - echo "line 12" >> hello && - echo "line 13" >> hello && + echo "line 12" >>hello && + echo "line 13" >>hello && add_and_commit_file hello "2 more lines" && HASH6=$(git rev-parse --verify HEAD) && - echo "line 14" >> hello && - echo "line 15" >> hello && - echo "line 16" >> hello && + echo "line 14" >>hello && + echo "line 15" >>hello && + echo "line 16" >>hello && add_and_commit_file hello "again 3 more lines" && HASH7=$(git rev-parse --verify HEAD) ' @@ -95,7 +128,7 @@ test_expect_success 'tag replaced commit' ' ' test_expect_success '"git fsck" works' ' - git fsck master > fsck_master.out && + git fsck master >fsck_master.out && grep "dangling commit $R" fsck_master.out && grep "dangling tag $(cat .git/refs/tags/mytag)" fsck_master.out && test -z "$(git fsck)" @@ -217,14 +250,14 @@ test_expect_success 'fetch branch with replacement' ' ( cd clone_dir && git fetch origin refs/heads/tofetch:refs/heads/parallel3 && - git log --pretty=oneline parallel3 > output.txt && + git log --pretty=oneline parallel3 >output.txt && ! grep $PARA3 output.txt && - git show $PARA3 > para3.txt && + git show $PARA3 >para3.txt && grep "A U Thor" para3.txt && git fetch origin "refs/replace/*:refs/replace/*" && - git log --pretty=oneline parallel3 > output.txt && + git log --pretty=oneline parallel3 >output.txt && grep $PARA3 output.txt && - git show $PARA3 > para3.txt && + git show $PARA3 >para3.txt && grep "O Thor" para3.txt ) ' @@ -302,7 +335,7 @@ test_expect_success 'test --format medium' ' echo "$PARA3 -> $S" && echo "$MYTAG -> $HASH1" } | sort >expected && - git replace -l --format medium | sort > actual && + git replace -l --format medium | sort >actual && test_cmp expected actual ' @@ -314,7 +347,7 @@ test_expect_success 'test --format long' ' echo "$PARA3 (commit) -> $S (commit)" && echo "$MYTAG (tag) -> $HASH1 (commit)" } | sort >expected && - git replace --format=long | sort > actual && + git replace --format=long | sort >actual && test_cmp expected actual ' @@ -351,4 +384,60 @@ test_expect_success 'replace ref cleanup' ' test -z "$(git replace)" ' +test_expect_success '--graft with and without already replaced object' ' + test $(git log --oneline | wc -l) = 7 && + git replace --graft $HASH5 && + test $(git log --oneline | wc -l) = 3 && + commit_has_parents $HASH5 && + test_must_fail git replace --graft $HASH5 $HASH4 $HASH3 && + git replace --force -g $HASH5 $HASH4 $HASH3 && + commit_has_parents $HASH5 $HASH4 $HASH3 && + git replace -d $HASH5 +' + +test_expect_success GPG 'set up a signed commit' ' + echo "line 17" >>hello && + echo "line 18" >>hello && + git add hello && + test_tick && + git commit --quiet -S -m "hello: 2 more lines in a signed commit" && + HASH8=$(git rev-parse --verify HEAD) && + git verify-commit $HASH8 +' + +test_expect_success GPG '--graft with a signed commit' ' + git cat-file commit $HASH8 >orig && + git replace --graft $HASH8 && + git cat-file commit $HASH8 >repl && + commit_has_parents $HASH8 && + test_must_fail git verify-commit $HASH8 && + sed -n -e "/^tree /p" -e "/^author /p" -e "/^committer /p" orig >expected && + echo >>expected && + sed -e "/^$/q" repl >actual && + test_cmp expected actual && + git replace -d $HASH8 +' + +test_expect_success GPG 'set up a merge commit with a mergetag' ' + git reset --hard HEAD && + git checkout -b test_branch HEAD~2 && + echo "line 1 from test branch" >>hello && + echo "line 2 from test branch" >>hello && + git add hello && + test_tick && + git commit -m "hello: 2 more lines from a test branch" && + HASH9=$(git rev-parse --verify HEAD) && + git tag -s -m "tag for testing with a mergetag" test_tag HEAD && + git checkout master && + git merge -s ours test_tag && + HASH10=$(git rev-parse --verify HEAD) && + git cat-file commit $HASH10 | grep "^mergetag object" +' + +test_expect_success GPG '--graft on a commit with a mergetag' ' + test_must_fail git replace --graft $HASH10 $HASH8^1 && + git replace --graft $HASH10 $HASH8^1 $HASH9 && + git replace -d $HASH10 +' + test_done diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index e4ab0f5b64..0366653088 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1385,41 +1385,77 @@ test_expect_success 'lexical sort' ' git tag foo1.6 && git tag foo1.10 && git tag -l --sort=refname "foo*" >actual && - cat >expect <<EOF && -foo1.10 -foo1.3 -foo1.6 -EOF + cat >expect <<-\EOF && + foo1.10 + foo1.3 + foo1.6 + EOF test_cmp expect actual ' test_expect_success 'version sort' ' git tag -l --sort=version:refname "foo*" >actual && - cat >expect <<EOF && -foo1.3 -foo1.6 -foo1.10 -EOF + cat >expect <<-\EOF && + foo1.3 + foo1.6 + foo1.10 + EOF test_cmp expect actual ' test_expect_success 'reverse version sort' ' git tag -l --sort=-version:refname "foo*" >actual && - cat >expect <<EOF && -foo1.10 -foo1.6 -foo1.3 -EOF + cat >expect <<-\EOF && + foo1.10 + foo1.6 + foo1.3 + EOF test_cmp expect actual ' test_expect_success 'reverse lexical sort' ' git tag -l --sort=-refname "foo*" >actual && - cat >expect <<EOF && -foo1.6 -foo1.3 -foo1.10 -EOF + cat >expect <<-\EOF && + foo1.6 + foo1.3 + foo1.10 + EOF + test_cmp expect actual +' + +test_expect_success 'configured lexical sort' ' + git config tag.sort "v:refname" && + git tag -l "foo*" >actual && + cat >expect <<-\EOF && + foo1.3 + foo1.6 + foo1.10 + EOF + test_cmp expect actual +' + +test_expect_success 'option override configured sort' ' + git tag -l --sort=-refname "foo*" >actual && + cat >expect <<-\EOF && + foo1.6 + foo1.3 + foo1.10 + EOF + test_cmp expect actual +' + +test_expect_success 'invalid sort parameter on command line' ' + test_must_fail git tag -l --sort=notvalid "foo*" >actual +' + +test_expect_success 'invalid sort parameter in configuratoin' ' + git config tag.sort "v:notvalid" && + git tag -l "foo*" >actual && + cat >expect <<-\EOF && + foo1.10 + foo1.3 + foo1.6 + EOF test_cmp expect actual ' diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index ee703bed64..98bcfe21aa 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -44,7 +44,9 @@ test_expect_success 'creating initial files and commits' ' echo "1st line 2nd file" >secondfile && echo "2nd line 2nd file" >>secondfile && - git -c "i18n.commitEncoding=$test_encoding" commit -a -m "$(commit_msg $test_encoding)" && + # "git commit -m" would break MinGW, as Windows refuse to pass + # $test_encoding encoded parameter to git. + commit_msg $test_encoding | git -c "i18n.commitEncoding=$test_encoding" commit -a -F - && head5=$(git rev-parse --verify HEAD) ' # git log --pretty=oneline # to see those SHA1 involved @@ -334,7 +336,9 @@ test_expect_success 'redoing the last two commits should succeed' ' echo "1st line 2nd file" >secondfile && echo "2nd line 2nd file" >>secondfile && - git -c "i18n.commitEncoding=$test_encoding" commit -a -m "$(commit_msg $test_encoding)" && + # "git commit -m" would break MinGW, as Windows refuse to pass + # $test_encoding encoded parameter to git. + commit_msg $test_encoding | git -c "i18n.commitEncoding=$test_encoding" commit -a -F - && check_changes $head5 ' diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh new file mode 100755 index 0000000000..2eda6adeb1 --- /dev/null +++ b/t/t7112-reset-submodule.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +test_description='reset can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +test_submodule_switch "git reset --keep" + +test_submodule_switch "git reset --merge" + +test_submodule_forced_switch "git reset --hard" + +test_done diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh index b61fd3c3c4..9ac794052d 100755 --- a/t/t7509-commit.sh +++ b/t/t7509-commit.sh @@ -77,6 +77,7 @@ test_expect_success '--amend option copies authorship' ' git commit -a --amend -m "amend test" && author_header Initial >expect && author_header HEAD >actual && + test_cmp expect actual && echo "amend test" >expect && message_body HEAD >actual && diff --git a/t/t7613-merge-submodule.sh b/t/t7613-merge-submodule.sh new file mode 100755 index 0000000000..d1e9fcc781 --- /dev/null +++ b/t/t7613-merge-submodule.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='merge can handle submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-submodule-update.sh + +# merges without conflicts +test_submodule_switch "git merge" + +test_submodule_switch "git merge --ff" + +test_submodule_switch "git merge --ff-only" + +KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 +KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 +test_submodule_switch "git merge --no-ff" + +test_done diff --git a/t/t7702-repack-cyclic-alternate.sh b/t/t7702-repack-cyclic-alternate.sh new file mode 100755 index 0000000000..93b74867ac --- /dev/null +++ b/t/t7702-repack-cyclic-alternate.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Copyright (c) 2014 Ephrim Khong +# + +test_description='repack involving cyclic alternate' +. ./test-lib.sh + +test_expect_success setup ' + GIT_OBJECT_DIRECTORY=.git//../.git/objects && + export GIT_OBJECT_DIRECTORY && + touch a && + git add a && + git commit -m 1 && + git repack -adl && + echo "$(pwd)"/.git/objects/../objects >.git/objects/info/alternates +' + +test_expect_success 're-packing repository with itsself as alternate' ' + git repack -adl && + git fsck +' + +test_done diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 665607c9cb..5b562122a1 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -145,7 +145,7 @@ test_expect_success 'exit when p4 fails to produce marshaled output' ' test_expect_code 1 git p4 clone --dest="$git" //depot >errs 2>&1 ) && cat errs && - ! test_i18ngrep Traceback errs + test_i18ngrep ! Traceback errs ' # Hide a file from p4d, make sure we catch its complaint. This won't fail in diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh index 7fab2ed977..1f74a88385 100755 --- a/t/t9807-git-p4-submit.sh +++ b/t/t9807-git-p4-submit.sh @@ -404,7 +404,7 @@ test_expect_success 'submit --prepare-p4-only' ' git p4 submit --prepare-p4-only >out && test_i18ngrep "prepared for submission" out && test_i18ngrep "must be deleted" out && - ! test_i18ngrep "everything below this line is just the diff" out + test_i18ngrep ! "everything below this line is just the diff" out ) && ( cd "$cli" && diff --git a/t/t9814-git-p4-rename.sh b/t/t9814-git-p4-rename.sh index 1fc1f5f2af..95f4421f71 100755 --- a/t/t9814-git-p4-rename.sh +++ b/t/t9814-git-p4-rename.sh @@ -177,7 +177,10 @@ test_expect_success 'detect copies' ' level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && - test "$src" = file10 || test "$src" = file11 && + case "$src" in + file10 | file11) : ;; # happy + *) false ;; # not + && git config git-p4.detectCopies $(($level + 2)) && git p4 submit && p4 filelog //depot/file12 && @@ -191,7 +194,10 @@ test_expect_success 'detect copies' ' level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && - test "$src" = file10 || test "$src" = file11 || test "$src" = file12 && + case "$src" in + file10 | file11 | file12) : ;; # happy + *) false ;; # not + && git config git-p4.detectCopies $(($level - 2)) && git p4 submit && p4 filelog //depot/file13 && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 0377d3e296..dafd6ad21a 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -489,6 +489,17 @@ test_path_is_dir () { fi } +# Check if the directory exists and is empty as expected, barf otherwise. +test_dir_is_empty () { + test_path_is_dir "$1" && + if test -n "$(ls -a1 "$1" | egrep -v '^\.\.?$')" + then + echo "Directory '$1' is not empty, it contains:" + ls -la "$1" + return 1 + fi +} + test_path_is_missing () { if [ -e "$1" ] then diff --git a/t/test-lib.sh b/t/test-lib.sh index b72f6bd414..2b525a8e1d 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -109,6 +109,10 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export EDITOR +# Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output +GIT_TRACE_BARE=1 +export GIT_TRACE_BARE + if test -n "${TEST_GIT_INDEX_VERSION:+isset}" then GIT_INDEX_VERSION="$TEST_GIT_INDEX_VERSION" diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp index 9d51c92b74..0a6724fcc4 100644 --- a/t/valgrind/default.supp +++ b/t/valgrind/default.supp @@ -49,18 +49,3 @@ Memcheck:Addr4 fun:copy_ref } -{ - ignore-sse-check_refname_format-addr - Memcheck:Addr8 - fun:check_refname_format -} -{ - ignore-sse-check_refname_format-cond - Memcheck:Cond - fun:check_refname_format -} -{ - ignore-sse-check_refname_format-value - Memcheck:Value8 - fun:check_refname_format -} |