diff options
Diffstat (limited to 't')
61 files changed, 2485 insertions, 522 deletions
diff --git a/t/.gitignore b/t/.gitignore index 7dcbb232cd..4e731dc1e3 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -1,2 +1,3 @@ /trash directory* /test-results +/.prove diff --git a/t/Makefile b/t/Makefile index cf5f9e2e1e..819b936870 100644 --- a/t/Makefile +++ b/t/Makefile @@ -30,6 +30,7 @@ clean: $(RM) -r 'trash directory'.* test-results $(RM) t????/cvsroot/CVSROOT/?* $(RM) -r valgrind/bin + $(RM) .prove aggregate-results-and-cleanup: $(T) $(MAKE) aggregate-results @@ -467,6 +467,13 @@ library for your script to use. <expected> file. This behaves like "cmp" but produces more helpful output when the test is run with "-v" option. + - test_path_is_file <file> [<diagnosis>] + test_path_is_dir <dir> [<diagnosis>] + test_path_is_missing <path> [<diagnosis>] + + Check whether a file/directory exists or doesn't. <diagnosis> will + be displayed if the test fails. + - test_when_finished <script> Prepend <script> to a list of commands to run to clean up diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index c3f6676ca2..92d6d31942 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -16,7 +16,6 @@ fi GIT_DIR=$PWD/.git GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn SVN_TREE=$GIT_SVN_DIR/svn-tree -PERL=${PERL:-perl} svn >/dev/null 2>&1 if test $? -ne 1 @@ -30,7 +29,7 @@ export svnrepo svnconf=$PWD/svnconf export svnconf -$PERL -w -e " +"$PERL_PATH" -w -e " use SVN::Core; use SVN::Repos; \$SVN::Core::VERSION gt '1.1.0' or exit(42); @@ -130,7 +129,7 @@ stop_httpd () { } convert_to_rev_db () { - $PERL -w -- - "$@" <<\EOF + "$PERL_PATH" -w -- - "$@" <<\EOF use strict; @ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>"; open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]"; diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 6aefe27593..6ccf797091 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -47,6 +47,8 @@ for line in $FAKE_LINES; do case $line in squash|fixup|edit|reword) action="$line";; + exec*) + echo "$line" | sed 's/_/ /g' >> "$1";; "#") echo '# comment' >> "$1";; ">") diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 53bd7fcc4a..de38c7f7aa 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -48,11 +48,11 @@ test_expect_success 'attribute test' ' attr_check a/b/g a/b/g && attr_check b/g unspecified && attr_check a/b/h a/b/h && - attr_check a/b/d/g "a/b/d/*" - attr_check onoff unset - attr_check offon set - attr_check no unspecified - attr_check a/b/d/no "a/b/d/*" + attr_check a/b/d/g "a/b/d/*" && + attr_check onoff unset && + attr_check offon set && + attr_check no unspecified && + attr_check a/b/d/no "a/b/d/*" && attr_check a/b/d/yes unspecified ' diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 0c562bb820..93ca84f9e6 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -359,7 +359,7 @@ test_expect_success \ test_expect_success \ 'a/b (untracked) vs a, plus c/d case test.' \ - '! git read-tree -u -m "$treeH" "$treeM" && + 'test_must_fail git read-tree -u -m "$treeH" "$treeM" && git ls-files --stage && test -f a/b' diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 62246dbf95..9a07de1a5b 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -1,16 +1,30 @@ #!/bin/sh -test_description='sparse checkout tests' +test_description='sparse checkout tests + +* (tag: removed, master) removed +| D sub/added +* (HEAD, tag: top) modified and added +| M init.t +| A sub/added +* (tag: init) init + A init.t +' . ./test-lib.sh -cat >expected <<EOF -100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added -EOF test_expect_success 'setup' ' + cat >expected <<-\EOF && + 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t + 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added + EOF + cat >expected.swt <<-\EOF && + H init.t + H sub/added + EOF + test_commit init && - echo modified >> init.t && + echo modified >>init.t && mkdir sub && touch sub/added && git add init.t sub/added && @@ -20,26 +34,22 @@ test_expect_success 'setup' ' git commit -m removed && git tag removed && git checkout top && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result ' -cat >expected.swt <<EOF -H init.t -H sub/added -EOF test_expect_success 'read-tree without .git/info/sparse-checkout' ' git read-tree -m -u HEAD && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result ' test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' - echo > .git/info/sparse-checkout + echo >.git/info/sparse-checkout git read-tree -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added @@ -47,9 +57,9 @@ test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' ' git config core.sparsecheckout true && - echo > .git/info/sparse-checkout && + echo >.git/info/sparse-checkout && git read-tree --no-sparse-checkout -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added @@ -57,94 +67,113 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse- test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' git config core.sparsecheckout true && - echo > .git/info/sparse-checkout && + echo >.git/info/sparse-checkout && test_must_fail git read-tree -m -u HEAD && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -S init.t -H sub/added -EOF test_expect_success 'match directories with trailing slash' ' + cat >expected.swt-noinit <<-\EOF && + S init.t + H sub/added + EOF + echo sub/ > .git/info/sparse-checkout && git read-tree -m -u HEAD && git ls-files -t > result && - test_cmp expected.swt result && + test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -H init.t -H sub/added -EOF test_expect_failure 'match directories without trailing slash' ' - echo init.t > .git/info/sparse-checkout && - echo sub >> .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && + echo sub >>.git/info/sparse-checkout && git read-tree -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test ! -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -H init.t -S sub/added -EOF test_expect_success 'checkout area changes' ' - echo init.t > .git/info/sparse-checkout && + cat >expected.swt-nosub <<-\EOF && + H init.t + S sub/added + EOF + + echo init.t >.git/info/sparse-checkout && git read-tree -m -u HEAD && - git ls-files -t > result && - test_cmp expected.swt result && + git ls-files -t >result && + test_cmp expected.swt-nosub result && test -f init.t && test ! -f sub/added ' test_expect_success 'read-tree updates worktree, absent case' ' - echo sub/added > .git/info/sparse-checkout && + echo sub/added >.git/info/sparse-checkout && git checkout -f top && git read-tree -m -u HEAD^ && test ! -f init.t ' test_expect_success 'read-tree updates worktree, dirty case' ' - echo sub/added > .git/info/sparse-checkout && + echo sub/added >.git/info/sparse-checkout && git checkout -f top && - echo dirty > init.t && + echo dirty >init.t && git read-tree -m -u HEAD^ && grep -q dirty init.t && rm init.t ' test_expect_success 'read-tree removes worktree, dirty case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f top && - echo dirty > added && + echo dirty >added && git read-tree -m -u HEAD^ && grep -q dirty added ' test_expect_success 'read-tree adds to worktree, absent case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f removed && git read-tree -u -m HEAD^ && test ! -f sub/added ' test_expect_success 'read-tree adds to worktree, dirty case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f removed && mkdir sub && - echo dirty > sub/added && + echo dirty >sub/added && git read-tree -u -m HEAD^ && grep -q dirty sub/added ' +test_expect_success 'index removal and worktree narrowing at the same time' ' + >empty && + echo init.t >.git/info/sparse-checkout && + echo sub/added >>.git/info/sparse-checkout && + git checkout -f top && + echo init.t >.git/info/sparse-checkout && + git checkout removed && + git ls-files sub/added >result && + test ! -f sub/added && + test_cmp empty result +' + +test_expect_success 'read-tree --reset removes outside worktree' ' + >empty && + echo init.t >.git/info/sparse-checkout && + git checkout -f top && + git reset --hard removed && + git ls-files sub/added >result && + test_cmp empty result +' + test_done diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 64f05080b6..074f2f2e3e 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -707,19 +707,41 @@ test_expect_success 'set --path' ' git config --path path.trailingtilde "foo~" && test_cmp expect .git/config' +if test "${HOME+set}" +then + test_set_prereq HOMEVAR +fi + cat >expect <<EOF $HOME/ /dev/null foo~ EOF -test_expect_success 'get --path' ' +test_expect_success HOMEVAR 'get --path' ' git config --get --path path.home > result && git config --get --path path.normal >> result && git config --get --path path.trailingtilde >> result && test_cmp expect result ' +cat >expect <<\EOF +/dev/null +foo~ +EOF + +test_expect_success 'get --path copes with unset $HOME' ' + ( + unset HOME; + test_must_fail git config --get --path path.home \ + >result 2>msg && + git config --get --path path.normal >>result && + git config --get --path path.trailingtilde >>result + ) && + grep "[Ff]ailed to expand.*~/" msg && + test_cmp expect result +' + rm .git/config git config quote.leading " test" diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index eb45afb018..782e75d000 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -41,6 +41,23 @@ test_expect_success "check-ref-format --branch @{-1}" ' refname2=$(git check-ref-format --branch @{-2}) && test "$refname2" = master' +test_expect_success 'check-ref-format --branch from subdir' ' + mkdir subdir && + + T=$(git write-tree) && + sha1=$(echo A | git commit-tree $T) && + git update-ref refs/heads/master $sha1 && + git update-ref refs/remotes/origin/master $sha1 + git checkout master && + git checkout origin/master && + git checkout master && + refname=$( + cd subdir && + git check-ref-format --branch @{-1} + ) && + test "$refname" = "$sha1" +' + valid_ref_normalized() { test_expect_success "ref name '$1' simplifies to '$2'" " refname=\$(git check-ref-format --print '$1') && diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index bd8b60732b..2c8f01f668 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -3,183 +3,320 @@ test_description='test separate work tree' . ./test-lib.sh -test_rev_parse() { - name=$1 - shift - - test_expect_success "$name: is-bare-repository" \ - "test '$1' = \"\$(git rev-parse --is-bare-repository)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: is-inside-git-dir" \ - "test '$1' = \"\$(git rev-parse --is-inside-git-dir)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: is-inside-work-tree" \ - "test '$1' = \"\$(git rev-parse --is-inside-work-tree)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: prefix" \ - "test '$1' = \"\$(git rev-parse --show-prefix)\"" - shift - [ $# -eq 0 ] && return -} - -EMPTY_TREE=$(git write-tree) -mkdir -p work/sub/dir || exit 1 -mkdir -p work2 || exit 1 -mv .git repo.git || exit 1 - -say "core.worktree = relative path" -GIT_DIR=repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -export GIT_DIR GIT_CONFIG -unset GIT_WORK_TREE -git config core.worktree ../work -test_rev_parse 'outside' false false false -cd work || exit 1 -GIT_DIR=../repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -GIT_DIR=../../../repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -say "core.worktree = absolute path" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -git config core.worktree "$(pwd)/work" -test_rev_parse 'outside' false false false -cd work2 -test_rev_parse 'outside2' false false false -cd ../work || exit 1 -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -say "GIT_WORK_TREE=relative path (override core.worktree)" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -git config core.worktree non-existent -GIT_WORK_TREE=work -export GIT_WORK_TREE -test_rev_parse 'outside' false false false -cd work2 -test_rev_parse 'outside' false false false -cd ../work || exit 1 -GIT_WORK_TREE=. -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -GIT_WORK_TREE=../.. -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -mv work repo.git/work -mv work2 repo.git/work2 - -say "GIT_WORK_TREE=absolute path, work tree below git dir" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -GIT_WORK_TREE=$(pwd)/repo.git/work -test_rev_parse 'outside' false false false -cd repo.git || exit 1 -test_rev_parse 'in repo.git' false true false -cd objects || exit 1 -test_rev_parse 'in repo.git/objects' false true false -cd ../work2 || exit 1 -test_rev_parse 'in repo.git/work2' false true false -cd ../work || exit 1 -test_rev_parse 'in repo.git/work' false true true '' -cd sub/dir || exit 1 -test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/ -cd ../../../.. || exit 1 - -test_expect_success 'repo finds its work tree' ' - (cd repo.git && - : > work/sub/dir/untracked && - test sub/dir/untracked = "$(git ls-files --others)") -' - -test_expect_success 'repo finds its work tree from work tree, too' ' - (cd repo.git/work/sub/dir && - : > tracked && - git --git-dir=../../.. add tracked && - cd ../../.. && - test sub/dir/tracked = "$(git ls-files)") +test_expect_success 'setup' ' + EMPTY_TREE=$(git write-tree) && + EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) && + CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) && + ZEROES=0000000000000000000000000000000000000000 && + EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") && + CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") && + + mkdir -p work/sub/dir && + mkdir -p work2 && + mv .git repo.git +' + +test_expect_success 'setup: helper for testing rev-parse' ' + test_rev_parse() { + echo $1 >expected.bare && + echo $2 >expected.inside-git && + echo $3 >expected.inside-worktree && + if test $# -ge 4 + then + echo $4 >expected.prefix + fi && + + git rev-parse --is-bare-repository >actual.bare && + git rev-parse --is-inside-git-dir >actual.inside-git && + git rev-parse --is-inside-work-tree >actual.inside-worktree && + if test $# -ge 4 + then + git rev-parse --show-prefix >actual.prefix + fi && + + test_cmp expected.bare actual.bare && + test_cmp expected.inside-git actual.inside-git && + test_cmp expected.inside-worktree actual.inside-worktree && + if test $# -ge 4 + then + # rev-parse --show-prefix should output + # a single newline when at the top of the work tree, + # but we test for that separately. + test -z "$4" && ! test -s actual.prefix || + test_cmp expected.prefix actual.prefix + fi + } +' + +test_expect_success 'setup: core.worktree = relative path' ' + unset GIT_WORK_TREE; + GIT_DIR=repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + export GIT_DIR GIT_CONFIG && + git config core.worktree ../work +' + +test_expect_success 'outside' ' + test_rev_parse false false false +' + +test_expect_success 'inside work tree' ' + ( + cd work && + GIT_DIR=../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + test_rev_parse false false true "" + ) +' + +test_expect_failure 'empty prefix is actually written out' ' + echo >expected && + ( + cd work && + GIT_DIR=../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + git rev-parse --show-prefix >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + GIT_DIR=../../../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: core.worktree = absolute path' ' + unset GIT_WORK_TREE; + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + export GIT_DIR GIT_CONFIG && + git config core.worktree "$(pwd)/work" +' + +test_expect_success 'outside' ' + test_rev_parse false false false && + ( + cd work2 && + test_rev_parse false false false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd work && + test_rev_parse false false true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' ' + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + git config core.worktree non-existent && + GIT_WORK_TREE=work && + export GIT_DIR GIT_CONFIG GIT_WORK_TREE +' + +test_expect_success 'outside' ' + test_rev_parse false false false && + ( + cd work2 && + test_rev_parse false false false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd work && + GIT_WORK_TREE=. && + test_rev_parse false false true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + GIT_WORK_TREE=../.. && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' ' + mv work repo.git/work && + mv work2 repo.git/work2 && + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + GIT_WORK_TREE=$(pwd)/repo.git/work && + export GIT_DIR GIT_CONFIG GIT_WORK_TREE +' + +test_expect_success 'outside' ' + echo outside && + test_rev_parse false false false +' + +test_expect_success 'in repo.git' ' + ( + cd repo.git && + test_rev_parse false true false + ) && + ( + cd repo.git/objects && + test_rev_parse false true false + ) && + ( + cd repo.git/work2 && + test_rev_parse false true false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd repo.git/work && + test_rev_parse false true true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd repo.git/work/sub/dir && + test_rev_parse false true true sub/dir/ + ) +' + +test_expect_success 'find work tree from repo' ' + echo sub/dir/untracked >expected && + cat <<-\EOF >repo.git/work/.gitignore && + expected.* + actual.* + .gitignore + EOF + >repo.git/work/sub/dir/untracked && + ( + cd repo.git && + git ls-files --others --exclude-standard >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'find work tree from work tree' ' + echo sub/dir/tracked >expected && + >repo.git/work/sub/dir/tracked && + ( + cd repo.git/work/sub/dir && + git --git-dir=../../.. add tracked + ) && + ( + cd repo.git && + git ls-files >../actual + ) && + test_cmp expected actual ' test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' ' - (cd repo.git/work/sub/dir && - GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \ + ( + cd repo.git/work/sub/dir && + GIT_DIR=../../.. && + GIT_WORK_TREE=../.. && + GIT_PAGER= && + export GIT_DIR GIT_WORK_TREE GIT_PAGER && + git diff --exit-code tracked && - echo changed > tracked && - ! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \ - git diff --exit-code tracked) -' -cat > diff-index-cached.expected <<\EOF -:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A sub/dir/tracked -EOF -cat > diff-index.expected <<\EOF -:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A sub/dir/tracked -EOF - - -test_expect_success 'git diff-index' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result && - test_cmp diff-index.expected result && - GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result && - test_cmp diff-index-cached.expected result -' -cat >diff-files.expected <<\EOF -:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M sub/dir/tracked -EOF - -test_expect_success 'git diff-files' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result && - test_cmp diff-files.expected result -' - -cat >diff-TREE.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -new file mode 100644 -index 0000000..5ea2ed4 ---- /dev/null -+++ b/sub/dir/tracked -@@ -0,0 +1 @@ -+changed -EOF -cat >diff-TREE-cached.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -new file mode 100644 -index 0000000..e69de29 -EOF -cat >diff-FILES.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -index e69de29..5ea2ed4 100644 ---- a/sub/dir/tracked -+++ b/sub/dir/tracked -@@ -0,0 +1 @@ -+changed -EOF - -test_expect_success 'git diff' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result && - test_cmp diff-TREE.expected result && - GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result && - test_cmp diff-TREE-cached.expected result && - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result && - test_cmp diff-FILES.expected result + echo changed >tracked && + test_must_fail git diff --exit-code tracked + ) +' + +test_expect_success 'diff-index respects work tree under .git dir' ' + cat >diff-index-cached.expected <<-EOF && + :000000 100644 $ZEROES $EMPTY_BLOB A sub/dir/tracked + EOF + cat >diff-index.expected <<-EOF && + :000000 100644 $ZEROES $ZEROES A sub/dir/tracked + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff-index $EMPTY_TREE >diff-index.actual && + git diff-index --cached $EMPTY_TREE >diff-index-cached.actual + ) && + test_cmp diff-index.expected diff-index.actual && + test_cmp diff-index-cached.expected diff-index-cached.actual +' + +test_expect_success 'diff-files respects work tree under .git dir' ' + cat >diff-files.expected <<-EOF && + :100644 100644 $EMPTY_BLOB $ZEROES M sub/dir/tracked + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff-files >diff-files.actual + ) && + test_cmp diff-files.expected diff-files.actual +' + +test_expect_success 'git diff respects work tree under .git dir' ' + cat >diff-TREE.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + new file mode 100644 + index 0000000..$CHANGED_BLOB7 + --- /dev/null + +++ b/sub/dir/tracked + @@ -0,0 +1 @@ + +changed + EOF + cat >diff-TREE-cached.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + new file mode 100644 + index 0000000..$EMPTY_BLOB7 + EOF + cat >diff-FILES.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + index $EMPTY_BLOB7..$CHANGED_BLOB7 100644 + --- a/sub/dir/tracked + +++ b/sub/dir/tracked + @@ -0,0 +1 @@ + +changed + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff $EMPTY_TREE >diff-TREE.actual && + git diff --cached $EMPTY_TREE >diff-TREE-cached.actual && + git diff >diff-FILES.actual + ) && + test_cmp diff-TREE.expected diff-TREE.actual && + test_cmp diff-TREE-cached.expected diff-TREE-cached.actual && + test_cmp diff-FILES.expected diff-FILES.actual ' test_expect_success 'git grep' ' - (cd repo.git/work/sub && - GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked) + echo dir/tracked >expected.grep && + ( + cd repo.git/work/sub && + GIT_DIR=../.. && + GIT_WORK_TREE=.. && + export GIT_DIR GIT_WORK_TREE && + git grep -l changed >../../../actual.grep + ) && + test_cmp expected.grep actual.grep ' test_expect_success 'git commit' ' @@ -191,14 +328,14 @@ test_expect_success 'git commit' ' test_expect_success 'absolute pathspec should fail gracefully' ' ( - cd repo.git || exit 1 - git config --unset core.worktree + cd repo.git && + test_might_fail git config --unset core.worktree && test_must_fail git log HEAD -- /home ) ' test_expect_success 'make_relative_path handles double slashes in GIT_DIR' ' - : > dummy_file + >dummy_file echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file && git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh new file mode 100755 index 0000000000..fa69016381 --- /dev/null +++ b/t/t2018-checkout-branch.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +test_description='checkout ' + +. ./test-lib.sh + +# Arguments: <branch> <sha> [<checkout options>] +# +# Runs "git checkout" to switch to <branch>, testing that +# +# 1) we are on the specified branch, <branch>; +# 2) HEAD is <sha>; if <sha> is not specified, the old HEAD is used. +# +# If <checkout options> is not specified, "git checkout" is run with -b. +do_checkout() { + exp_branch=$1 && + exp_ref="refs/heads/$exp_branch" && + + # if <sha> is not specified, use HEAD. + exp_sha=${2:-$(git rev-parse --verify HEAD)} && + + # default options for git checkout: -b + if [ -z "$3" ]; then + opts="-b" + else + opts="$3" + fi + + git checkout $opts $exp_branch $exp_sha && + + test $exp_ref = $(git rev-parse --symbolic-full-name HEAD) && + test $exp_sha = $(git rev-parse --verify HEAD) +} + +test_dirty_unmergeable() { + ! git diff --exit-code >/dev/null +} + +setup_dirty_unmergeable() { + echo >>file1 change2 +} + +test_dirty_mergeable() { + ! git diff --cached --exit-code >/dev/null +} + +setup_dirty_mergeable() { + echo >file2 file2 && + git add file2 +} + +test_expect_success 'setup' ' + test_commit initial file1 && + HEAD1=$(git rev-parse --verify HEAD) && + + test_commit change1 file1 && + HEAD2=$(git rev-parse --verify HEAD) && + + git branch -m branch1 +' + +test_expect_success 'checkout -b to a new branch, set to HEAD' ' + do_checkout branch2 +' + +test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' + git checkout branch1 && + git branch -D branch2 && + + do_checkout branch2 $HEAD1 +' + +test_expect_success 'checkout -b to a new branch with unmergeable changes fails' ' + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_unmergeable && + test_must_fail do_checkout branch2 $HEAD1 && + test_dirty_unmergeable +' + +test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' ' + # still dirty and on branch1 + do_checkout branch2 $HEAD1 "-f -b" && + test_must_fail test_dirty_unmergeable +' + +test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 && + test_dirty_mergeable +' + +test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' ' + # clean up from previous test + git reset --hard && + + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 "-f -b" && + test_must_fail test_dirty_mergeable +' + +test_expect_success 'checkout -b to an existing branch fails' ' + git reset --hard HEAD && + + test_must_fail do_checkout branch2 $HEAD2 +' + +test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' + git checkout branch1 && + + do_checkout branch2 "" -B +' + +test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' ' + git checkout $(git rev-parse --verify HEAD) && + + do_checkout branch2 "" -B +' + +test_expect_success 'checkout -B to an existing branch with an explicit ref resets branch to that ref' ' + git checkout branch1 && + + do_checkout branch2 $HEAD1 -B +' + +test_expect_success 'checkout -B to an existing branch with unmergeable changes fails' ' + git checkout branch1 && + + setup_dirty_unmergeable && + test_must_fail do_checkout branch2 $HEAD1 -B && + test_dirty_unmergeable +' + +test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' ' + # still dirty and on branch1 + do_checkout branch2 $HEAD1 "-f -B" && + test_must_fail test_dirty_unmergeable +' + +test_expect_success 'checkout -B to an existing branch preserves mergeable changes' ' + git checkout branch1 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 -B && + test_dirty_mergeable +' + +test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' ' + # clean up from previous test + git reset --hard && + + git checkout branch1 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 "-f -B" && + test_must_fail test_dirty_mergeable +' + +test_done diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index d541544537..efe2900a37 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -294,7 +294,7 @@ test_expect_success 'fail if the index has unresolved entries' ' grep "You have not concluded your merge" out && rm -f .git/MERGE_HEAD && test_must_fail git merge "$c5" 2> out && - grep "Your local changes to .* would be overwritten by merge." out + grep "Your local changes to the following files would be overwritten by merge:" out ' test_expect_success 'merge-recursive remove conflict' ' diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index 525174013c..cd04361df8 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -60,6 +60,12 @@ test_expect_success 'see if git pack-refs --prune remove ref files' ' ! test -f .git/refs/heads/f ' +test_expect_success 'see if git pack-refs --prune removes empty dirs' ' + git branch r/s/t && + git pack-refs --all --prune && + ! test -e .git/refs/heads/r +' + test_expect_success \ 'git branch g should work when git branch g/h has been deleted' \ 'git branch g/h && diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 1d82f79ee0..96b75813d7 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -299,7 +299,7 @@ cat expect-F >> expect-rm-F test_expect_success 'verify note removal with -F /dev/null' ' git log -4 > output && test_cmp expect-rm-F output && - ! git notes show + test_must_fail git notes show ' test_expect_success 'do not create empty note with -m "" (setup)' ' @@ -309,7 +309,7 @@ test_expect_success 'do not create empty note with -m "" (setup)' ' test_expect_success 'verify non-creation of note with -m ""' ' git log -4 > output && test_cmp expect-rm-F output && - ! git notes show + test_must_fail git notes show ' cat > expect-combine_m_and_F << EOF @@ -357,7 +357,7 @@ cat expect-multiline >> expect-rm-remove test_expect_success 'verify note removal with "git notes remove"' ' git log -4 > output && test_cmp expect-rm-remove output && - ! git notes show HEAD^ + test_must_fail git notes show HEAD^ ' cat > expect << EOF diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh index 361a10aeb1..8ab333dbd9 100755 --- a/t/t3302-notes-index-expensive.sh +++ b/t/t3302-notes-index-expensive.sh @@ -98,7 +98,7 @@ time_notes () { for mode in no-notes notes do echo $mode - /usr/bin/time sh ../time_notes $mode $1 + /usr/bin/time "$SHELL_PATH" ../time_notes $mode $1 done } diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh index b4554041b4..c4282179b3 100755 --- a/t/t3306-notes-prune.sh +++ b/t/t3306-notes-prune.sh @@ -67,7 +67,7 @@ test_expect_success 'remove some commits' ' test_expect_success 'verify that commits are gone' ' - ! git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + test_must_fail git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 && git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f ' @@ -106,7 +106,7 @@ test_expect_success 'prune notes' ' test_expect_success 'verify that notes are gone' ' - ! git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f ' @@ -130,8 +130,8 @@ test_expect_success 'prune -v notes' ' test_expect_success 'verify that notes are gone' ' - ! git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - ! git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && + test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + test_must_fail git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f ' diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index d98c7b5571..349eebd542 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -14,140 +14,165 @@ GIT_AUTHOR_NAME=author@name GIT_AUTHOR_EMAIL=bogus@email@address export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL -test_expect_success \ - 'prepare repository with topic branches' \ - 'git config core.logAllRefUpdates true && - echo First > A && - git update-index --add A && - git commit -m "Add A." && - git checkout -b my-topic-branch && - echo Second > B && - git update-index --add B && - git commit -m "Add B." && - git checkout -f master && - echo Third >> A && - git update-index A && - git commit -m "Modify A." && - git checkout -b side my-topic-branch && - echo Side >> C && - git add C && - git commit -m "Add C" && - git checkout -b nonlinear my-topic-branch && - echo Edit >> B && - git add B && - git commit -m "Modify B" && - git merge side && - git checkout -b upstream-merged-nonlinear && - git merge master && - git checkout -f my-topic-branch && - git tag topic +test_expect_success 'prepare repository with topic branches' ' + git config core.logAllRefUpdates true && + echo First >A && + git update-index --add A && + git commit -m "Add A." && + git checkout -b force-3way && + echo Dummy >Y && + git update-index --add Y && + git commit -m "Add Y." && + git checkout -b filemove && + git reset --soft master && + mkdir D && + git mv A D/A && + git commit -m "Move A." && + git checkout -b my-topic-branch master && + echo Second >B && + git update-index --add B && + git commit -m "Add B." && + git checkout -f master && + echo Third >>A && + git update-index A && + git commit -m "Modify A." && + git checkout -b side my-topic-branch && + echo Side >>C && + git add C && + git commit -m "Add C" && + git checkout -b nonlinear my-topic-branch && + echo Edit >>B && + git add B && + git commit -m "Modify B" && + git merge side && + git checkout -b upstream-merged-nonlinear && + git merge master && + git checkout -f my-topic-branch && + git tag topic ' test_expect_success 'rebase on dirty worktree' ' - echo dirty >> A && - test_must_fail git rebase master' + echo dirty >>A && + test_must_fail git rebase master +' test_expect_success 'rebase on dirty cache' ' - git add A && - test_must_fail git rebase master' + git add A && + test_must_fail git rebase master +' test_expect_success 'rebase against master' ' - git reset --hard HEAD && - git rebase master' + git reset --hard HEAD && + git rebase master +' test_expect_success 'rebase against master twice' ' - git rebase master >out && - grep "Current branch my-topic-branch is up to date" out + git rebase master >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase against master twice with --force' ' - git rebase --force-rebase master >out && - grep "Current branch my-topic-branch is up to date, rebase forced" out + git rebase --force-rebase master >out && + grep "Current branch my-topic-branch is up to date, rebase forced" out ' test_expect_success 'rebase against master twice from another branch' ' - git checkout my-topic-branch^ && - git rebase master my-topic-branch >out && - grep "Current branch my-topic-branch is up to date" out + git checkout my-topic-branch^ && + git rebase master my-topic-branch >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase fast-forward to master' ' - git checkout my-topic-branch^ && - git rebase my-topic-branch >out && - grep "Fast-forwarded HEAD to my-topic-branch" out + git checkout my-topic-branch^ && + git rebase my-topic-branch >out && + grep "Fast-forwarded HEAD to my-topic-branch" out ' -test_expect_success \ - 'the rebase operation should not have destroyed author information' \ - '! (git log | grep "Author:" | grep "<>")' +test_expect_success 'the rebase operation should not have destroyed author information' ' + ! (git log | grep "Author:" | grep "<>") +' -test_expect_success \ - 'the rebase operation should not have destroyed author information (2)' \ - "git log -1 | grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'" +test_expect_success 'the rebase operation should not have destroyed author information (2)' " + git log -1 | + grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>' +" test_expect_success 'HEAD was detached during rebase' ' - test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) + test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) ' test_expect_success 'rebase after merge master' ' - git reset --hard topic && - git merge master && - git rebase master && - ! (git show | grep "^Merge:") + git reset --hard topic && + git merge master && + git rebase master && + ! (git show | grep "^Merge:") ' test_expect_success 'rebase of history with merges is linearized' ' - git checkout nonlinear && - test 4 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) + git checkout nonlinear && + test 4 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' -test_expect_success \ - 'rebase of history with merges after upstream merge is linearized' ' - git checkout upstream-merged-nonlinear && - test 5 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) +test_expect_success 'rebase of history with merges after upstream merge is linearized' ' + git checkout upstream-merged-nonlinear && + test 5 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' test_expect_success 'rebase a single mode change' ' - git checkout master && - echo 1 > X && - git add X && - test_tick && - git commit -m prepare && - git checkout -b modechange HEAD^ && - echo 1 > X && - git add X && - test_chmod +x A && - test_tick && - git commit -m modechange && - GIT_TRACE=1 git rebase master + git checkout master && + echo 1 >X && + git add X && + test_tick && + git commit -m prepare && + git checkout -b modechange HEAD^ && + echo 1 >X && + git add X && + test_chmod +x A && + test_tick && + git commit -m modechange && + GIT_TRACE=1 git rebase master +' + +test_expect_success 'rebase is not broken by diff.renames' ' + git config diff.renames copies && + test_when_finished "git config --unset diff.renames" && + git checkout filemove && + GIT_TRACE=1 git rebase force-3way +' + +test_expect_success 'setup: recover' ' + test_might_fail git rebase --abort && + git reset --hard && + git checkout modechange ' test_expect_success 'Show verbose error when HEAD could not be detached' ' - : > B && - test_must_fail git rebase topic 2> output.err > output.out && - grep "Untracked working tree file .B. would be overwritten" output.err + >B && + test_must_fail git rebase topic 2>output.err >output.out && + grep "The following untracked working tree files would be overwritten by checkout:" output.err && + grep B output.err ' rm -f B test_expect_success 'dump usage when upstream arg is missing' ' - git checkout -b usage topic && - test_must_fail git rebase 2>error1 && - grep "[Uu]sage" error1 && - test_must_fail git rebase --abort 2>error2 && - grep "No rebase in progress" error2 && - test_must_fail git rebase --onto master 2>error3 && - grep "[Uu]sage" error3 && - ! grep "can.t shift" error3 + git checkout -b usage topic && + test_must_fail git rebase 2>error1 && + grep "[Uu]sage" error1 && + test_must_fail git rebase --abort 2>error2 && + grep "No rebase in progress" error2 && + test_must_fail git rebase --onto master 2>error3 && + grep "[Uu]sage" error3 && + ! grep "can.t shift" error3 ' test_expect_success 'rebase -q is quiet' ' - git checkout -b quiet topic && - git rebase -q master > output.out 2>&1 && - test ! -s output.out + git checkout -b quiet topic && + git rebase -q master >output.out 2>&1 && + test ! -s output.out ' test_expect_success 'Rebase a commit that sprinkles CRs in' ' diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index 7b7d07269a..2bea65634a 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -74,6 +74,15 @@ test_expect_success 'rebase the other way' ' git rebase --merge side ' +test_expect_success 'rebase -Xtheirs' ' + git checkout -b conflicting master~2 && + echo "AB $T" >> original && + git commit -mconflicting original && + git rebase -Xtheirs master && + grep AB original && + ! grep 11 original +' + test_expect_success 'merge and rebase should match' ' git diff-tree -r test-rebase test-merge >difference && if test -s difference diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 47ca88fc52..af3b663aee 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -64,6 +64,67 @@ test_expect_success 'setup' ' done ' +# "exec" commands are ran with the user shell by default, but this may +# be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work +# to create a file. Unseting SHELL avoids such non-portable behavior +# in tests. +SHELL= + +test_expect_success 'rebase -i with the exec command' ' + git checkout master && + ( + FAKE_LINES="1 exec_>touch-one + 2 exec_>touch-two exec_false exec_>touch-three + 3 4 exec_>\"touch-file__name_with_spaces\";_>touch-after-semicolon 5" && + export FAKE_LINES && + test_must_fail git rebase -i A + ) && + test_path_is_file touch-one && + test_path_is_file touch-two && + test_path_is_missing touch-three " (should have stopped before)" && + test $(git rev-parse C) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of C)" + false + } && + git rebase --continue && + test_path_is_file touch-three && + test_path_is_file "touch-file name with spaces" && + test_path_is_file touch-after-semicolon && + test $(git rev-parse master) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of master)" + false + } && + rm -f touch-* +' + +test_expect_success 'rebase -i with the exec command runs from tree root' ' + git checkout master && + mkdir subdir && cd subdir && + FAKE_LINES="1 exec_>touch-subdir" \ + git rebase -i HEAD^ && + cd .. && + test_path_is_file touch-subdir && + rm -fr subdir +' + +test_expect_success 'rebase -i with the exec command checks tree cleanness' ' + git checkout master && + ( + FAKE_LINES="exec_echo_foo_>file1 1" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD^ + ) && + test $(git rev-parse master^) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of master^)" + false + } && + git reset --hard && + git rebase --continue +' + test_expect_success 'no changes are a nop' ' git checkout branch2 && git rebase -i F && @@ -143,16 +204,17 @@ test_expect_success 'abort' ' git rebase --abort && test $(git rev-parse new-branch1) = $(git rev-parse HEAD) && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && - ! test -d .git/rebase-merge + test_path_is_missing .git/rebase-merge ' test_expect_success 'abort with error when new base cannot be checked out' ' git rm --cached file1 && git commit -m "remove file in base" && test_must_fail git rebase -i master > output 2>&1 && - grep "Untracked working tree file .file1. would be overwritten" \ + grep "The following untracked working tree files would be overwritten by checkout:" \ output && - ! test -d .git/rebase-merge && + grep "file1" output && + test_path_is_missing .git/rebase-merge && git reset --hard HEAD^ ' @@ -637,13 +699,19 @@ test_expect_success 'set up commits with funny messages' ' git commit -a -m "end with slash\\" && echo >>file1 && test_tick && + git commit -a -m "something (\000) that looks like octal" && + echo >>file1 && + test_tick && + git commit -a -m "something (\n) that looks like a newline" && + echo >>file1 && + test_tick && git commit -a -m "another commit" ' test_expect_success 'rebase-i history with funny messages' ' git rev-list A..funny >expect && test_tick && - FAKE_LINES="1 2" git rebase -i A && + FAKE_LINES="1 2 3 4" git rebase -i A && git rev-list A.. >actual && test_cmp expect actual ' diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh index 2999e78937..fbb3f2e0df 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -38,7 +38,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && git rebase --abort && test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && test ! -d "$dotest" @@ -49,7 +49,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && test_must_fail git rebase --skip && test $(git rev-parse HEAD) = $(git rev-parse master) && git rebase --abort && @@ -62,7 +62,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && echo c > a && echo d >> a && git add a && diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh index c49143a1a4..6f73b95558 100755 --- a/t/t3410-rebase-preserve-dropped-merges.sh +++ b/t/t3410-rebase-preserve-dropped-merges.sh @@ -43,11 +43,11 @@ test_expect_success 'setup' ' # G2 = same changes as G test_expect_success 'skip same-resolution merges with -p' ' git checkout H && - ! git merge E && + test_must_fail git merge E && test_commit L file1 23 && git checkout I && test_commit G2 file1 3 && - ! git merge E && + test_must_fail git merge E && test_commit J file1 23 && test_commit K file7 file7 && git rebase -i -p L && @@ -65,11 +65,11 @@ test_expect_success 'skip same-resolution merges with -p' ' # G2 = different changes as G test_expect_success 'keep different-resolution merges with -p' ' git checkout H && - ! git merge E && + test_must_fail git merge E && test_commit L2 file1 23 && git checkout I && test_commit G3 file1 4 && - ! git merge E && + test_must_fail git merge E && test_commit J2 file1 24 && test_commit K2 file7 file7 && test_must_fail git rebase -i -p L2 && diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index b63f4e2d67..37cb89ab53 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -21,38 +21,62 @@ test_expect_success setup ' git tag base ' -test_expect_success 'auto fixup' ' +test_auto_fixup() { git reset --hard base && echo 1 >file1 && git add -u && test_tick && git commit -m "fixup! first" - git tag final-fixup && + git tag $1 && test_tick && - git rebase --autosquash -i HEAD^^^ && + git rebase $2 -i HEAD^^^ && git log --oneline >actual && test 3 = $(wc -l <actual) && - git diff --exit-code final-fixup && + git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) +} + +test_expect_success 'auto fixup (option)' ' + test_auto_fixup final-fixup-option --autosquash +' + +test_expect_success 'auto fixup (config)' ' + git config rebase.autosquash true && + test_auto_fixup final-fixup-config-true && + test_must_fail test_auto_fixup fixup-config-true-no --no-autosquash && + git config rebase.autosquash false && + test_must_fail test_auto_fixup final-fixup-config-false ' -test_expect_success 'auto squash' ' +test_auto_squash() { git reset --hard base && echo 1 >file1 && git add -u && test_tick && git commit -m "squash! first" - git tag final-squash && + git tag $1 && test_tick && - git rebase --autosquash -i HEAD^^^ && + git rebase $2 -i HEAD^^^ && git log --oneline >actual && test 3 = $(wc -l <actual) && - git diff --exit-code final-squash && + git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 2 = $(git cat-file commit HEAD^ | grep first | wc -l) +} + +test_expect_success 'auto squash (option)' ' + test_auto_squash final-squash --autosquash +' + +test_expect_success 'auto squash (config)' ' + git config rebase.autosquash true && + test_auto_squash final-squash-config-true && + test_must_fail test_auto_squash squash-config-true-no --no-autosquash && + git config rebase.autosquash false && + test_must_fail test_auto_squash final-squash-config-false ' test_expect_success 'misspelled auto squash' ' diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh new file mode 100755 index 0000000000..3b0d27350e --- /dev/null +++ b/t/t3418-rebase-continue.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='git rebase --continue tests' + +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +test_expect_success 'setup' ' + test_commit "commit-new-file-F1" F1 1 && + test_commit "commit-new-file-F2" F2 2 && + + git checkout -b topic HEAD^ && + test_commit "commit-new-file-F2-on-topic-branch" F2 22 && + + git checkout master +' + +test_expect_success 'interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + FAKE_LINES="edit 1" git rebase -i HEAD^ && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_expect_success 'non-interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + test_must_fail git rebase --onto master master topic && + echo "Resolved" >F2 && + git add F2 && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_done diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh index e51e505a9f..c10b28cf57 100755 --- a/t/t3505-cherry-pick-empty.sh +++ b/t/t3505-cherry-pick-empty.sh @@ -13,12 +13,30 @@ test_expect_success setup ' git checkout -b empty-branch && test_tick && - git commit --allow-empty -m "empty" + git commit --allow-empty -m "empty" && + + echo third >> file1 && + git add file1 && + test_tick && + git commit --allow-empty-message -m "" ' test_expect_success 'cherry-pick an empty commit' ' git checkout master && { + git cherry-pick empty-branch^ + test "$?" = 1 + } +' + +test_expect_success 'index lockfile was removed' ' + + test ! -f .git/index.lock + +' + +test_expect_success 'cherry-pick a commit with an empty message' ' + git checkout master && { git cherry-pick empty-branch test "$?" = 1 } diff --git a/t/t3700-add.sh b/t/t3700-add.sh index d03495dc7a..7d7140db38 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -272,17 +272,20 @@ test_expect_success 'git add --dry-run of non-existing file' " echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual " -cat >expect <<EOF +cat >expect.err <<\EOF The following paths are ignored by one of your .gitignore files: ignored-file Use -f if you really want to add them. fatal: no files added +EOF +cat >expect.out <<\EOF add 'track-this' EOF test_expect_success 'git add --dry-run --ignore-missing of non-existing file' ' - test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual 2>&1 && - test_cmp expect actual + test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err ' test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index dae6358516..19857f4326 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -208,6 +208,7 @@ log -p --first-parent master log -m -p --first-parent master log -m -p master log -SF master +log -S F master log -SF -p master log --decorate --all log --decorate=full --all @@ -282,4 +283,8 @@ diff master master^ side diff --dirstat master~1 master~2 EOF +test_expect_success 'log -S requires an argument' ' + test_must_fail git log -S +' + test_done diff --git a/t/t4013/diff.log_-S_F_master b/t/t4013/diff.log_-S_F_master new file mode 100644 index 0000000000..978d2b4118 --- /dev/null +++ b/t/t4013/diff.log_-S_F_master @@ -0,0 +1,7 @@ +$ git log -S F master +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third +$ diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 5b10e976a3..61de8a2718 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -32,7 +32,7 @@ EOF sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java -builtin_patterns="bibtex cpp html java objc pascal php python ruby tex" +builtin_patterns="bibtex cpp csharp html java objc pascal php python ruby tex" for p in $builtin_patterns do test_expect_success "builtin $p pattern compiles" ' diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 1bd8e5ee3a..d99814ac64 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -114,6 +114,69 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' ! test -s actual4 ' +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.git/config]' ' + git config diff.ignoreSubmodules all && + git diff HEAD >actual && + ! test -s actual && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff HEAD --ignore-submodules=none >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' ' + git config diff.ignoreSubmodules dirty && + git diff HEAD >actual && + ! test -s actual && + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git config -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + git config --unset diff.ignoreSubmodules && + rm .gitmodules +' + test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' ' ( cd sub && @@ -146,6 +209,103 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)' ! test -s actual4 ' +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.git/config]' ' + git config submodule.subname.ignore all && + git config submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff --ignore-submodules=none HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname +' + +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.gitmodules]' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + +test_expect_success 'git diff between submodule commits' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules HEAD^..HEAD >actual && + ! test -s actual +' + +test_expect_success 'git diff between submodule commits [.git/config]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname +' + +test_expect_success 'git diff between submodule commits [.gitmodules]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + test_expect_success 'git diff (empty submodule dir)' ' : >empty && rm -rf sub/* sub/.git && diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh new file mode 100755 index 0000000000..8a3c63b9e2 --- /dev/null +++ b/t/t4045-diff-relative.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='diff --relative tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + git commit --allow-empty -m empty && + echo content >file1 && + mkdir subdir && + echo other content >subdir/file2 && + git add . && + git commit -m one +' + +check_diff() { +expect=$1; shift +cat >expected <<EOF +diff --git a/$expect b/$expect +new file mode 100644 +index 0000000..25c05ef +--- /dev/null ++++ b/$expect +@@ -0,0 +1 @@ ++other content +EOF +test_expect_success "-p $*" " + git diff -p $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_stat() { +expect=$1; shift +cat >expected <<EOF + $expect | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) +EOF +test_expect_success "--stat $*" " + git diff --stat $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_raw() { +expect=$1; shift +cat >expected <<EOF +:000000 100644 0000000000000000000000000000000000000000 25c05ef3639d2d270e7fe765a67668f098092bc5 A $expect +EOF +test_expect_success "--raw $*" " + git diff --no-abbrev --raw $* HEAD^ >actual && + test_cmp expected actual +" +} + +for type in diff stat raw; do + check_$type file2 --relative=subdir/ + check_$type file2 --relative=subdir + check_$type dir/file2 --relative=sub +done + +test_done diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh new file mode 100755 index 0000000000..a52d94ae21 --- /dev/null +++ b/t/t4111-apply-subdir.sh @@ -0,0 +1,142 @@ +#!/bin/sh + +test_description='patching from inconvenient places' + +. ./test-lib.sh + +test_expect_success 'setup' ' + cat >patch <<-\EOF && + diff file.orig file + --- a/file.orig + +++ b/file + @@ -1 +1,2 @@ + 1 + +2 + EOF + patch="$(pwd)/patch" && + + echo 1 >preimage && + printf "%s\n" 1 2 >postimage && + echo 3 >other && + + test_tick && + git commit --allow-empty -m basis +' + +test_expect_success 'setup: subdir' ' + reset_subdir() { + git reset && + mkdir -p sub/dir/b && + mkdir -p objects && + cp "$1" file && + cp "$1" objects/file && + cp "$1" sub/dir/file && + cp "$1" sub/dir/b/file && + git add file sub/dir/file sub/dir/b/file objects/file && + cp "$2" file && + cp "$2" sub/dir/file && + cp "$2" sub/dir/b/file && + cp "$2" objects/file && + test_might_fail git update-index --refresh -q + } +' + +test_expect_success 'apply from subdir of toplevel' ' + cp postimage expected && + reset_subdir other preimage && + ( + cd sub/dir && + git apply "$patch" + ) && + test_cmp expected sub/dir/file +' + +test_expect_success 'apply --cached from subdir of toplevel' ' + cp postimage expected && + cp other expected.working && + reset_subdir preimage other && + ( + cd sub/dir && + git apply --cached "$patch" + ) && + git show :sub/dir/file >actual && + test_cmp expected actual && + test_cmp expected.working sub/dir/file +' + +test_expect_success 'apply --index from subdir of toplevel' ' + cp postimage expected && + reset_subdir preimage other && + ( + cd sub/dir && + test_must_fail git apply --index "$patch" + ) && + reset_subdir other preimage && + ( + cd sub/dir && + test_must_fail git apply --index "$patch" + ) && + reset_subdir preimage preimage && + ( + cd sub/dir && + git apply --index "$patch" + ) && + git show :sub/dir/file >actual && + test_cmp expected actual && + test_cmp expected sub/dir/file +' + +test_expect_success 'apply from .git dir' ' + cp postimage expected && + cp preimage .git/file && + cp preimage .git/objects/file + ( + cd .git && + git apply "$patch" + ) && + test_cmp expected .git/file +' + +test_expect_success 'apply from subdir of .git dir' ' + cp postimage expected && + cp preimage .git/file && + cp preimage .git/objects/file + ( + cd .git/objects && + git apply "$patch" + ) && + test_cmp expected .git/objects/file +' + +test_expect_success 'apply --cached from .git dir' ' + cp postimage expected && + cp other expected.working && + cp other .git/file && + reset_subdir preimage other && + ( + cd .git && + git apply --cached "$patch" + ) && + git show :file >actual && + test_cmp expected actual && + test_cmp expected.working file && + test_cmp expected.working .git/file +' + +test_expect_success 'apply --cached from subdir of .git dir' ' + cp postimage expected && + cp preimage expected.subdir && + cp other .git/file && + cp other .git/objects/file && + reset_subdir preimage other && + ( + cd .git/objects && + git apply --cached "$patch" + ) && + git show :file >actual && + git show :objects/file >actual.subdir && + test_cmp expected actual && + test_cmp expected.subdir actual.subdir +' + +test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 810b04b817..1c3d8ed548 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -4,66 +4,71 @@ test_description='git am running' . ./test-lib.sh -cat >msg <<EOF -second - -Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy -eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam -voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita -kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem -ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod -tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At -vero eos et accusam et justo duo dolores et ea rebum. - - Duis autem vel eum iriure dolor in hendrerit in vulputate velit - esse molestie consequat, vel illum dolore eu feugiat nulla facilisis - at vero eros et accumsan et iusto odio dignissim qui blandit - praesent luptatum zzril delenit augue duis dolore te feugait nulla - facilisi. - - -Lorem ipsum dolor sit amet, -consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut -laoreet dolore magna aliquam erat volutpat. - - git - --- - +++ - -Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit -lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure -dolor in hendrerit in vulputate velit esse molestie consequat, vel illum -dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio -dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te -feugait nulla facilisi. -EOF - -cat >failmail <<EOF -From foo@example.com Fri May 23 10:43:49 2008 -From: foo@example.com -To: bar@example.com -Subject: Re: [RFC/PATCH] git-foo.sh -Date: Fri, 23 May 2008 05:23:42 +0200 - -Sometimes we have to find out that there's nothing left. - -EOF - -cat >pine <<EOF -From MAILER-DAEMON Fri May 23 10:43:49 2008 -Date: 23 May 2008 05:23:42 +0200 -From: Mail System Internal Data <MAILER-DAEMON@example.com> -Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA -Message-ID: <foo-0001@example.com> - -This text is part of the internal format of your mail folder, and is not -a real message. It is created automatically by the mail system software. -If deleted, important folder data will be lost, and it will be re-created -with the data reset to initial values. - -EOF - -echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected +test_expect_success 'setup: messages' ' + cat >msg <<-\EOF && + second + + Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy + eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam + voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita + kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem + ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod + tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At + vero eos et accusam et justo duo dolores et ea rebum. + + EOF + q_to_tab <<-\EOF >>msg && + QDuis autem vel eum iriure dolor in hendrerit in vulputate velit + Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis + Qat vero eros et accumsan et iusto odio dignissim qui blandit + Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla + Qfacilisi. + EOF + cat >>msg <<-\EOF && + + Lorem ipsum dolor sit amet, + consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut + laoreet dolore magna aliquam erat volutpat. + + git + --- + +++ + + Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit + lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure + dolor in hendrerit in vulputate velit esse molestie consequat, vel illum + dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio + dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te + feugait nulla facilisi. + EOF + + cat >failmail <<-\EOF && + From foo@example.com Fri May 23 10:43:49 2008 + From: foo@example.com + To: bar@example.com + Subject: Re: [RFC/PATCH] git-foo.sh + Date: Fri, 23 May 2008 05:23:42 +0200 + + Sometimes we have to find out that there'\''s nothing left. + + EOF + + cat >pine <<-\EOF && + From MAILER-DAEMON Fri May 23 10:43:49 2008 + Date: 23 May 2008 05:23:42 +0200 + From: Mail System Internal Data <MAILER-DAEMON@example.com> + Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA + Message-ID: <foo-0001@example.com> + + This text is part of the internal format of your mail folder, and is not + a real message. It is created automatically by the mail system software. + If deleted, important folder data will be lost, and it will be re-created + with the data reset to initial values. + + EOF + + signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +' test_expect_success setup ' echo hello >file && @@ -71,11 +76,13 @@ test_expect_success setup ' test_tick && git commit -m first && git tag first && + echo world >>file && git add file && test_tick && git commit -s -F msg && git tag second && + git format-patch --stdout first >patch1 && { echo "X-Fake-Field: Line One" && @@ -89,74 +96,101 @@ test_expect_success setup ' echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } | append_cr >patch1-crlf.eml && + sed -n -e "3,\$p" msg >file && git add file && test_tick && git commit -m third && + git format-patch --stdout first >patch2 && + git checkout -b lorem && sed -n -e "11,\$p" msg >file && head -n 9 msg >>file && test_tick && git commit -a -m "moved stuff" && + echo goodbye >another && git add another && test_tick && git commit -m "added another file" && - git format-patch --stdout master >lorem-move.patch -' -# reset time -unset test_tick -test_tick + git format-patch --stdout master >lorem-move.patch && + + git checkout -b rename && + git mv file renamed && + git commit -m "renamed a file" && + + git format-patch -M --stdout lorem >rename.patch && + + git reset --soft lorem^ && + git commit -m "renamed a file and added another" && + + git format-patch -M --stdout lorem^ >rename-add.patch && + + # reset time + unset test_tick && + test_tick +' test_expect_success 'am applies patch correctly' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am <patch1 && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox with CRLF' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1-crlf.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' -GIT_AUTHOR_NAME="Another Thor" -GIT_AUTHOR_EMAIL="a.thor@example.com" -GIT_COMMITTER_NAME="Co M Miter" -GIT_COMMITTER_EMAIL="c.miter@example.com" -export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +test_expect_success 'setup: new author and committer' ' + GIT_AUTHOR_NAME="Another Thor" && + GIT_AUTHOR_EMAIL="a.thor@example.com" && + GIT_COMMITTER_NAME="Co M Miter" && + GIT_COMMITTER_EMAIL="c.miter@example.com" && + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +' compare () { - test "$(git cat-file commit "$2" | grep "^$1 ")" = \ - "$(git cat-file commit "$3" | grep "^$1 ")" + a=$(git cat-file commit "$2" | grep "^$1 ") && + b=$(git cat-file commit "$3" | grep "^$1 ") && + test "$a" = "$b" } test_expect_success 'am changes committer and keeps author' ' test_tick && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch2 && ! test -d .git/rebase-apply && test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" && - test -z "$(git diff master..HEAD)" && - test -z "$(git diff master^..HEAD^)" && + git diff --exit-code master..HEAD && + git diff --exit-code master^..HEAD^ && compare author master HEAD && compare author master^ HEAD^ && test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \ @@ -164,41 +198,55 @@ test_expect_success 'am changes committer and keeps author' ' ' test_expect_success 'am --signoff adds Signed-off-by: line' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b master2 first && git am --signoff <patch2 && + printf "%s\n" "$signoff" >expected && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected && git cat-file commit HEAD^ | grep "Signed-off-by:" >actual && - test_cmp actual expected && + test_cmp expected actual && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected && git cat-file commit HEAD | grep "Signed-off-by:" >actual && - test_cmp actual expected + test_cmp expected actual ' test_expect_success 'am stays in branch' ' - test "refs/heads/master2" = "$(git symbolic-ref HEAD)" + echo refs/heads/master2 >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual ' test_expect_success 'am --signoff does not add Signed-off-by: line if already there' ' git format-patch --stdout HEAD^ >patch3 && sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4 + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --signoff patch4 && - test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1 + git cat-file commit HEAD >actual && + test $(grep -c "^Signed-off-by:" actual) -eq 1 ' test_expect_success 'am without --keep removes Re: and [PATCH] stuff' ' - test "$(git rev-parse HEAD)" = "$(git rev-parse master2)" + git rev-parse HEAD >expected && + git rev-parse master2 >actual && + test_cmp expected actual ' test_expect_success 'am --keep really keeps the subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --keep patch4 && ! test -d .git/rebase-apply && - git cat-file commit HEAD | - fgrep "Re: Re: Re: [PATCH 1/5 v2] third" + git cat-file commit HEAD >actual && + grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual ' test_expect_success 'am -3 falls back to 3-way merge' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b lorem2 master2 && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && @@ -207,34 +255,75 @@ test_expect_success 'am -3 falls back to 3-way merge' ' git commit -m "copied stuff" && git am -3 lorem-move.patch && ! test -d .git/rebase-apply && - test -z "$(git diff lorem)" + git diff --exit-code lorem +' + +test_expect_success 'am can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file after falling back to 3-way merge' ' + grep "^rename from" rename-add.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename-add.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename ' test_expect_success 'am -3 -q is quiet' ' + rm -fr .git/rebase-apply && + git checkout -f lorem2 && git reset master2 --hard && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && git add file && test_tick && git commit -m "copied stuff" && - git am -3 -q lorem-move.patch > output.out 2>&1 && + git am -3 -q lorem-move.patch >output.out 2>&1 && ! test -s output.out ' test_expect_success 'am pauses on conflict' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply ' test_expect_success 'am --skip works' ' + echo goodbye >expected && git am --skip && ! test -d .git/rebase-apply && - test -z "$(git diff lorem2^^ -- file)" && - test goodbye = "$(cat another)" + git diff --exit-code lorem2^^ -- file && + test_cmp expected another ' test_expect_success 'am --resolved works' ' + echo goodbye >expected && + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply && @@ -242,22 +331,29 @@ test_expect_success 'am --resolved works' ' git add file && git am --resolved && ! test -d .git/rebase-apply && - test goodbye = "$(cat another)" + test_cmp expected another ' test_expect_success 'am takes patches from a Pine mailbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && cat pine patch1 | git am && ! test -d .git/rebase-apply && - test -z "$(git diff master^..HEAD)" + git diff --exit-code master^..HEAD ' test_expect_success 'am fails on mail without patch' ' + rm -fr .git/rebase-apply && + git reset --hard && test_must_fail git am <failmail && - rm -r .git/rebase-apply/ + git am --abort && + ! test -d .git/rebase-apply ' test_expect_success 'am fails on empty patch' ' + rm -fr .git/rebase-apply && + git reset --hard && echo "---" >>failmail && test_must_fail git am <failmail && git am --skip && @@ -266,28 +362,34 @@ test_expect_success 'am fails on empty patch' ' test_expect_success 'am works from stdin in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am <../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (relative path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am ../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (absolute path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && P=$(pwd) && ( @@ -295,27 +397,31 @@ test_expect_success 'am works from file (absolute path given) in subdirectory' ' cd subdir && git am "$P/patch1" ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --committer-date-is-author-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" = "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + test_cmp at ct ' test_expect_success 'am without --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" != "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + ! test_cmp at ct ' # This checks for +0000 because TZ is set to UTC and that should @@ -323,41 +429,51 @@ test_expect_success 'am without --committer-date-is-author-date' ' # by test_tick that uses -0700 timezone; if this feature does not # work, we will see that instead of +0000. test_expect_success 'am --ignore-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --ignore-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - echo "$at" | grep "+0000" + sed -ne "/^author /s/.*> //p" head1 >at && + grep "+0000" at ' test_expect_success 'am into an unborn branch' ' + git rev-parse first^{tree} >expected && + rm -fr .git/rebase-apply && + git reset --hard && rm -fr subdir && - mkdir -p subdir && + mkdir subdir && git format-patch --numbered-files -o subdir -1 first && ( cd subdir && git init && git am 1 ) && - result=$( - cd subdir && git rev-parse HEAD^{tree} + ( + cd subdir && + git rev-parse HEAD^{tree} >../actual ) && - test "z$result" = "z$(git rev-parse first^{tree})" + test_cmp expected actual ' test_expect_success 'am newline in subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - sed -e "s/second/second \\\n foo/" patch1 > patchnl && - git am < patchnl > output.out 2>&1 && + sed -e "s/second/second \\\n foo/" patch1 >patchnl && + git am <patchnl >output.out 2>&1 && grep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - git am -q < patch1 > output.out 2>&1 && + git am -q <patch1 >output.out 2>&1 && ! test -s output.out ' diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 70856d07ed..093b138911 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -132,6 +132,8 @@ test_expect_success 'commit succeeds' \ test_expect_success 'recorded postimage' "test -f $rr/postimage" +oldmtimepost=$(test-chmtime -v -60 $rr/postimage |cut -f 1) + test_expect_success 'another conflicting merge' ' git checkout -b third master && git show second^:a1 | sed "s/To die: t/To die! T/" > a1 && @@ -144,6 +146,11 @@ test_expect_success 'rerere kicked in' "! grep ^=======$ a1" test_expect_success 'rerere prefers first change' 'test_cmp a1 expect' +test_expect_success 'rerere updates postimage timestamp' ' + newmtimepost=$(test-chmtime -v +0 $rr/postimage |cut -f 1) && + test $oldmtimepost -lt $newmtimepost +' + rm $rr/postimage echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR @@ -165,15 +172,16 @@ just_over_15_days_ago=$((-1-15*86400)) almost_60_days_ago=$((60-60*86400)) just_over_60_days_ago=$((-1-60*86400)) -test-chmtime =$almost_60_days_ago $rr/preimage +test-chmtime =$just_over_60_days_ago $rr/preimage +test-chmtime =$almost_60_days_ago $rr/postimage test-chmtime =$almost_15_days_ago $rr2/preimage test_expect_success 'garbage collection (part1)' 'git rerere gc' -test_expect_success 'young records still live' \ +test_expect_success 'young or recently used records still live' \ "test -f $rr/preimage && test -f $rr2/preimage" -test-chmtime =$just_over_60_days_ago $rr/preimage +test-chmtime =$just_over_60_days_ago $rr/postimage test-chmtime =$just_over_15_days_ago $rr2/preimage test_expect_success 'garbage collection (part2)' 'git rerere gc' diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 2230e606ed..2e51356947 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -100,13 +100,11 @@ test_expect_success 'oneline' ' test_expect_success 'diff-filter=A' ' - actual=$(git log --pretty="format:%s" --diff-filter=A HEAD) && - expect=$(echo fifth ; echo fourth ; echo third ; echo initial) && - test "$actual" = "$expect" || { - echo Oops - echo "Actual: $actual" - false - } + git log --pretty="format:%s" --diff-filter=A HEAD > actual && + git log --pretty="format:%s" --diff-filter A HEAD > actual-separate && + printf "fifth\nfourth\nthird\ninitial" > expect && + test_cmp expect actual && + test_cmp expect actual-separate ' @@ -203,6 +201,13 @@ test_expect_success 'log --grep' ' test_cmp expect actual ' +test_expect_success 'log --grep option parsing' ' + echo second >expect && + git log -1 --pretty="tformat:%s" --grep sec >actual && + test_cmp expect actual && + test_must_fail git log -1 --pretty="tformat:%s" --grep +' + test_expect_success 'log -i --grep' ' echo Second >expect && git log -1 --pretty="tformat:%s" -i --grep=sec >actual && @@ -436,5 +441,17 @@ test_expect_success 'log.decorate configuration' ' ' -test_done +test_expect_success 'show added path under "--follow -M"' ' + # This tests for a regression introduced in v1.7.2-rc0~103^2~2 + test_create_repo regression && + ( + cd regression && + test_commit needs-another-commit && + test_commit foo.bar && + git log -M --follow -p foo.bar.t && + git log -M --follow --stat foo.bar.t && + git log -M --follow --name-only foo.bar.t + ) +' +test_done diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 426b319bd3..02d4d2284d 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -4,7 +4,7 @@ test_description='git archive attribute tests' . ./test-lib.sh -SUBSTFORMAT=%H%n +SUBSTFORMAT='%H (%h)%n' test_expect_exists() { test_expect_success " $1 exists" "test -e $1" diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 319e389ed0..0b489f5b12 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -4,6 +4,11 @@ test_description='pulling into void' . ./test-lib.sh +modify () { + sed -e "$1" <"$2" >"$2.x" && + mv "$2.x" "$2" +} + D=`pwd` test_expect_success setup ' @@ -160,4 +165,61 @@ test_expect_success 'pull --rebase works on branch yet to be born' ' test_cmp expect actual ' +test_expect_success 'setup for detecting upstreamed changes' ' + mkdir src && + (cd src && + git init && + printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff && + git add stuff && + git commit -m "Initial revision" + ) && + git clone src dst && + (cd src && + modify s/5/43/ stuff && + git commit -a -m "5->43" && + modify s/6/42/ stuff && + git commit -a -m "Make it bigger" + ) && + (cd dst && + modify s/5/43/ stuff && + git commit -a -m "Independent discovery of 5->43" + ) +' + +test_expect_success 'git pull --rebase detects upstreamed changes' ' + (cd dst && + git pull --rebase && + test -z "$(git ls-files -u)" + ) +' + +test_expect_success 'setup for avoiding reapplying old patches' ' + (cd dst && + test_might_fail git rebase --abort && + git reset --hard origin/master + ) && + git clone --bare src src-replace.git && + rm -rf src && + mv src-replace.git src && + (cd dst && + modify s/2/22/ stuff && + git commit -a -m "Change 2" && + modify s/3/33/ stuff && + git commit -a -m "Change 3" && + modify s/4/44/ stuff && + git commit -a -m "Change 4" && + git push && + + modify s/44/55/ stuff && + git commit --amend -a -m "Modified Change 4" + ) +' + +test_expect_success 'git pull --rebase does not reapply old patches' ' + (cd dst && + test_must_fail git pull --rebase && + test 1 = $(find .git/rebase-apply -name "000*" | wc -l) + ) +' + test_done diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 044603c26e..6b2a5f4a65 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -60,6 +60,15 @@ test_expect_success 'upload-pack fails due to error in rev-list' ' grep "bad tree object" output.err ' +test_expect_success 'upload-pack error message when bad ref requested' ' + + printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input && + test_must_fail git upload-pack . <input >output 2>output.err && + grep -q "not our ref" output.err && + ! grep -q multi_ack_detailed output.err +' + test_expect_success 'upload-pack fails due to error in pack-objects enumeration' ' printf "0032want %s\n00000009done\n0000" \ diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index 58428d9f5c..fb8291c812 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -123,6 +123,12 @@ test_expect_success 'rev-list --glob=refs/heads/subspace/*' ' ' +test_expect_success 'rev-list --glob refs/heads/subspace/*' ' + + compare rev-list "subspace/one subspace/two" "--glob refs/heads/subspace/*" + +' + test_expect_success 'rev-list --glob=heads/subspace/*' ' compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/*" diff --git a/t/t6037-merge-ours-theirs.sh b/t/t6037-merge-ours-theirs.sh index 8ab3d61f44..2cf42c73f1 100755 --- a/t/t6037-merge-ours-theirs.sh +++ b/t/t6037-merge-ours-theirs.sh @@ -58,7 +58,7 @@ test_expect_success 'pull with -X' ' git reset --hard master && git pull -s recursive -X ours . side && git reset --hard master && git pull -s recursive -Xtheirs . side && git reset --hard master && git pull -s recursive -X theirs . side && - git reset --hard master && ! git pull -s recursive -X bork . side + git reset --hard master && test_must_fail git pull -s recursive -X bork . side ' test_done diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 203ffdb17a..4185b7ca1d 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -219,6 +219,12 @@ test_expect_success 'bisect and replacements' ' git bisect reset ' +test_expect_success 'index-pack and replacements' ' + git --no-replace-objects rev-list --objects HEAD | + git --no-replace-objects pack-objects test- && + git index-pack test-*.pack +' + # # test_done diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 0da13a8d6b..2c55801ee8 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -143,11 +143,12 @@ test_expect_success 'more setup' ' test_expect_success 'use index-filter to move into a subdirectory' ' git branch directorymoved && git filter-branch -f --index-filter \ - "git ls-files -s | sed \"s-\\t-&newsubdir/-\" | + "git ls-files -s | sed \"s- -&newsubdir/-\" | GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \ git update-index --index-info && mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved && - test -z "$(git diff HEAD directorymoved:newsubdir)"' + git diff --exit-code HEAD directorymoved:newsubdir +' test_expect_success 'stops when msg filter fails' ' old=$(git rev-parse HEAD) && diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index 71d3ceff8f..fb744e3c4a 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -58,6 +58,21 @@ test_expect_success TTY 'some commands use a pager' ' test -e paginated.out ' +test_expect_failure TTY 'pager runs from subdir' ' + echo subdir/paginated.out >expected && + mkdir -p subdir && + rm -f paginated.out subdir/paginated.out && + ( + cd subdir && + test_terminal git log + ) && + { + ls paginated.out subdir/paginated.out || + : + } >actual && + test_cmp expected actual +' + test_expect_success TTY 'some commands do not use a pager' ' rm -f paginated.out || cleanup_fail && @@ -106,6 +121,45 @@ test_expect_success TTY 'no pager with --no-pager' ' ! test -e paginated.out ' +test_expect_success TTY 'configuration can disable pager' ' + rm -f paginated.out && + test_might_fail git config --unset pager.grep && + test_terminal git grep initial && + test -e paginated.out && + + rm -f paginated.out && + git config pager.grep false && + test_when_finished "git config --unset pager.grep" && + test_terminal git grep initial && + ! test -e paginated.out +' + +test_expect_success TTY 'git config uses a pager if configured to' ' + rm -f paginated.out && + git config pager.config true && + test_when_finished "git config --unset pager.config" && + test_terminal git config --list && + test -e paginated.out +' + +test_expect_success TTY 'configuration can enable pager (from subdir)' ' + rm -f paginated.out && + mkdir -p subdir && + git config pager.bundle true && + test_when_finished "git config --unset pager.bundle" && + + git bundle create test.bundle --all && + rm -f paginated.out subdir/paginated.out && + ( + cd subdir && + test_terminal git bundle unbundle ../test.bundle + ) && + { + test -e paginated.out || + test -e subdir/paginated.out + } +' + # A colored commit log will begin with an appropriate ANSI escape # for the first color; the text "commit" comes later. colorful() { @@ -369,4 +423,16 @@ test_GIT_PAGER_overrides expect_success test_must_fail 'git -p' test_doesnt_paginate expect_failure test_must_fail 'git -p nonsense' +test_pager_choices 'git shortlog' +test_expect_success 'setup: configure shortlog not to paginate' ' + git config pager.shortlog false +' +test_doesnt_paginate expect_success 'git shortlog' +test_no_local_config_subdir expect_success 'git shortlog' +test_default_pager expect_success 'git -p shortlog' +test_core_pager_subdir expect_success 'git -p shortlog' + +test_core_pager_subdir expect_success test_must_fail \ + 'git -p apply </dev/null' + test_done diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 7d8ed68bef..3a43571cab 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -438,4 +438,20 @@ test_expect_success 'force removal of nested git work tree' ' ! test -d bar ' +test_expect_success 'git clean -e' ' + rm -fr repo && + mkdir repo && + ( + cd repo && + git init && + touch 1 2 3 known && + git add known && + git clean -f -e 1 -e 2 && + test -e 1 && + test -e 2 && + ! (test -e 3) && + test -e known + ) +' + test_done diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 7538756487..bade2179b1 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -14,7 +14,7 @@ test_expect_success setup ' echo file > file && git add file && test_tick && - git commit -m upstream + git commit -m upstream && git clone . super && git clone super submodule && (cd super && @@ -42,7 +42,7 @@ test_expect_success 'change submodule url' ' ) && mv submodule moved-submodule && (cd super && - git config -f .gitmodules submodule.submodule.url ../moved-submodule + git config -f .gitmodules submodule.submodule.url ../moved-submodule && test_tick && git commit -a -m moved-submodule ) diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh index 4a7b8933f4..6ec559db0f 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -54,13 +54,129 @@ test_expect_success setup ' git merge -s ours a ' -test_expect_success 'merging with modify/modify conflict' ' +# History setup +# +# b +# / \ +# a d +# \ / +# c +# +# a in the main repository records to sub-a in the submodule and +# analogous b and c. d should be automatically found by merging c into +# b in the main repository. +test_expect_success 'setup for merge search' ' + mkdir merge-search && + cd merge-search && + git init && + mkdir sub && + (cd sub && + git init && + echo "file-a" > file-a && + git add file-a && + git commit -m "sub-a" && + git branch sub-a) && + git add sub && + git commit -m "a" && + git branch a && + + git checkout -b b && + (cd sub && + git checkout -b sub-b && + echo "file-b" > file-b && + git add file-b && + git commit -m "sub-b") && + git commit -a -m "b" && + + git checkout -b c a && + (cd sub && + git checkout -b sub-c sub-a && + echo "file-c" > file-c && + git add file-c && + git commit -m "sub-c") && + git commit -a -m "c" && + + git checkout -b d a && + (cd sub && + git checkout -b sub-d sub-b && + git merge sub-c) && + git commit -a -m "d" && + git branch test b && + cd .. +' + +test_expect_success 'merge with one side as a fast-forward of the other' ' + (cd merge-search && + git checkout -b test-forward b && + git merge d && + git ls-tree test-forward sub | cut -f1 | cut -f3 -d" " > actual && + (cd sub && + git rev-parse sub-d > ../expect) && + test_cmp actual expect) +' + +test_expect_success 'merging should conflict for non fast-forward' ' + (cd merge-search && + git checkout -b test-nonforward b && + (cd sub && + git rev-parse sub-d > ../expect) && + test_must_fail git merge c 2> actual && + grep $(cat expect) actual > /dev/null && + git reset --hard) +' + +test_expect_success 'merging should fail for ambiguous common parent' ' + cd merge-search && + git checkout -b test-ambiguous b && + (cd sub && + git checkout -b ambiguous sub-b && + git merge sub-c && + git rev-parse sub-d > ../expect1 && + git rev-parse ambiguous > ../expect2) && + test_must_fail git merge c 2> actual && + grep $(cat expect1) actual > /dev/null && + grep $(cat expect2) actual > /dev/null && + git reset --hard && + cd .. +' + +# in a situation like this +# +# submodule tree: +# +# sub-a --- sub-b --- sub-d +# +# main tree: +# +# e (sub-a) +# / +# bb (sub-b) +# \ +# f (sub-d) +# +# A merge between e and f should fail because one of the submodule +# commits (sub-a) does not descend from the submodule merge-base (sub-b). +# +test_expect_success 'merging should fail for changes that are backwards' ' + cd merge-search && + git checkout -b bb a && + (cd sub && + git checkout sub-b) && + git commit -a -m "bb" && + + git checkout -b e bb && + (cd sub && + git checkout sub-a) && + git commit -a -m "e" && + + git checkout -b f bb && + (cd sub && + git checkout sub-d) && + git commit -a -m "f" && - git checkout -b test1 a && - test_must_fail git merge b && - test -f .git/MERGE_MSG && - git diff && - test -n "$(git ls-files -u)" + git checkout -b test-backward e && + test_must_fail git merge f && + cd .. ' test_expect_success 'merging with a modify/modify conflict between merge bases' ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index a72fe3ae64..9c14b853c0 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -808,24 +808,38 @@ test_expect_success POSIXPERM 'status succeeds in a read-only repository' ' (exit $status) ' +(cd sm && echo > bar && git add bar && git commit -q -m 'Add bar' && cd .. && git add sm) +new_head=$(cd sm && git rev-parse --short=7 --verify HEAD) +touch .gitmodules + cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: dir1/modified # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Untracked files: # (use "git add <file>..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' @@ -834,19 +848,89 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un test_cmp expect output ' +test_expect_success '.gitmodules ignore=untracked suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + test_cmp expect output && + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname +' + test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' ' git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + ! test -s actual && + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' ' echo modified > sm/foo && git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success '.gitmodules ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success '.git/config ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) @@ -855,16 +939,21 @@ cat > expect << EOF # modified: dir1/modified # modified: sm (modified content) # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Untracked files: # (use "git add <file>..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' @@ -872,10 +961,34 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w test_cmp expect output ' +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD) cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) @@ -883,21 +996,26 @@ cat > expect << EOF # modified: dir1/modified # modified: sm (new commits) # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Submodules changed but not updated: # -# * sm $head...$head2 (1): +# * sm $new_head...$head2 (1): # > 2nd commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' @@ -905,10 +1023,47 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodule su test_cmp expect output ' +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" ' git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success ".gitmodules ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' cat > expect << EOF # On branch master @@ -921,6 +1076,7 @@ cat > expect << EOF # Untracked files: # (use "git add <file>..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked @@ -935,4 +1091,23 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" ' test_cmp expect output ' +test_expect_failure '.gitmodules ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_failure '.git/config ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore all && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + test_done diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh index 3ea33db6c7..643ab03f99 100755 --- a/t/t7509-commit.sh +++ b/t/t7509-commit.sh @@ -111,7 +111,7 @@ test_expect_success '--amend option with empty author' ' test_when_finished "git checkout Initial" && echo "Empty author test" >>foo && test_tick && - ! git commit -a -m "empty author" --amend 2>err && + test_must_fail git commit -a -m "empty author" --amend 2>err && grep "empty ident" err ' @@ -125,7 +125,7 @@ test_expect_success '--amend option with missing author' ' test_when_finished "git checkout Initial" && echo "Missing author test" >>foo && test_tick && - ! git commit -a -m "malformed author" --amend 2>err && + test_must_fail git commit -a -m "malformed author" --amend 2>err && grep "empty ident" err ' diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 49f4e1599a..d82349a6a8 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -31,7 +31,7 @@ test_expect_success 'setup' ' test_expect_success 'will not overwrite untracked file' ' git reset --hard c1 && cat important > c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@ -39,7 +39,7 @@ test_expect_success 'will not overwrite new file' ' git reset --hard c1 && cat important > c2.c && git add c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@ -48,7 +48,7 @@ test_expect_success 'will not overwrite staged changes' ' cat important > c2.c && git add c2.c && rm c2.c && - ! git merge c2 && + test_must_fail git merge c2 && git checkout c2.c && test_cmp important c2.c ' @@ -58,7 +58,7 @@ test_expect_success 'will not overwrite removed file' ' git rm c1.c && git commit -m "rm c1.c" && cat important > c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@ -68,7 +68,7 @@ test_expect_success 'will not overwrite re-added file' ' git commit -m "rm c1.c" && cat important > c1.c && git add c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@ -79,7 +79,7 @@ test_expect_success 'will not overwrite removed file with staged changes' ' cat important > c1.c && git add c1.c && rm c1.c && - ! git merge c1a && + test_must_fail git merge c1a && git checkout c1.c && test_cmp important c1.c ' diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh new file mode 100755 index 0000000000..1a109b41dc --- /dev/null +++ b/t/t7609-merge-co-error-msgs.sh @@ -0,0 +1,125 @@ +#!/bin/sh + +test_description='unpack-trees error messages' + +. ./test-lib.sh + + +test_expect_success 'setup' ' + echo one >one && + git add one && + git commit -a -m First && + + git checkout -b branch && + echo two >two && + echo three >three && + echo four >four && + echo five >five && + git add two three four five && + git commit -m Second && + + git checkout master && + echo other >two && + echo other >three && + echo other >four && + echo other >five +' + +cat >expect <<\EOF +error: The following untracked working tree files would be overwritten by merge: + two + three + four + five +Please move or remove them before you can merge. +EOF + +test_expect_success 'untracked files overwritten by merge' ' + test_must_fail git merge branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by merge: + two + three + four +Please, commit your changes or stash them before you can merge. +error: The following untracked working tree files would be overwritten by merge: + five +Please move or remove them before you can merge. +EOF + +test_expect_success 'untracked files or local changes ovewritten by merge' ' + git add two && + git add three && + git add four && + test_must_fail git merge branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by checkout: + rep/two + rep/one +Please, commit your changes or stash them before you can switch branches. +EOF + +test_expect_success 'cannot switch branches because of local changes' ' + git add five && + mkdir rep && + echo one >rep/one && + echo two >rep/two && + git add rep/one rep/two && + git commit -m Fourth && + git checkout master && + echo uno >rep/one && + echo dos >rep/two && + test_must_fail git checkout branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by checkout: + rep/two + rep/one +Please, commit your changes or stash them before you can switch branches. +EOF + +test_expect_success 'not uptodate file porcelain checkout error' ' + git add rep/one rep/two && + test_must_fail git checkout branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Updating the following directories would lose untracked files in it: + rep2 + rep + +EOF + +test_expect_success 'not_uptodate_dir porcelain checkout error' ' + git init uptodate && + cd uptodate && + mkdir rep && + mkdir rep2 && + touch rep/foo && + touch rep2/foo && + git add rep/foo rep2/foo && + git commit -m init && + git checkout -b branch && + git rm rep -r && + git rm rep2 -r && + >rep && + >rep2 && + git add rep rep2&& + git commit -m "added test as a file" && + git checkout master && + >rep/untracked-file && + >rep2/untracked-file && + test_must_fail git checkout branch 2>out && + test_cmp out ../expect +' + +test_done diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index e768c3eb2d..3bd74042ef 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -14,6 +14,7 @@ Testing basic merge tool invocation' # running mergetool test_expect_success 'setup' ' + git config rerere.enabled true && echo master >file1 && mkdir subdir && echo master sub >subdir/file3 && @@ -67,23 +68,47 @@ test_expect_success 'mergetool crlf' ' ' test_expect_success 'mergetool in subdir' ' - git checkout -b test3 branch1 - cd subdir && ( - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && - test "$(cat file3)" = "master new sub" ) + git checkout -b test3 branch1 && + ( + cd subdir && + test_must_fail git merge master >/dev/null 2>&1 && + ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && + test "$(cat file3)" = "master new sub" + ) ' -# We can't merge files from parent directories when running mergetool -# from a subdir. Is this a bug? -# -#test_expect_failure 'mergetool in subdir' ' -# cd subdir && ( -# ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && -# ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) && -# test "$(cat ../file1)" = "master updated" && -# test "$(cat ../file2)" = "master new" && -# git commit -m "branch1 resolved with mergetool - subdir" ) -#' +test_expect_success 'mergetool on file in parent dir' ' + ( + cd subdir && + ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && + ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) && + test "$(cat ../file1)" = "master updated" && + test "$(cat ../file2)" = "master new" && + git commit -m "branch1 resolved with mergetool - subdir" + ) +' + +test_expect_success 'mergetool skips autoresolved' ' + git checkout -b test4 branch1 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git reset --hard +' + +test_expect_success 'mergetool merges all from subdir' ' + ( + cd subdir && + git config rerere.enabled false && + test_must_fail git merge master && + git mergetool --no-prompt && + test "$(cat ../file1)" = "master updated" && + test "$(cat ../file2)" = "master new" && + test "$(cat file3)" = "master new sub" && + git add ../file1 ../file2 file3 && + git commit -m "branch2 resolved by mergetool from subdir" + ) +' test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 8a6322765c..023f225a4b 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -65,7 +65,7 @@ do test_expect_success "grep -w $L (w)" ' : >expected && - ! git grep -n -w -e "^w" >actual && + test_must_fail git grep -n -w -e "^w" >actual && test_cmp expected actual ' diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 13766ab160..d5adae640b 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -271,6 +271,17 @@ test_expect_success 'able to dcommit to a subdirectory' " test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" " +test_expect_success 'dcommit should not fail with a touched file' ' + test_commit "commit-new-file-foo2" foo2 && + test-chmtime =-60 foo && + git svn dcommit +' + +test_expect_success 'rebase should not fail with a touched file' ' + test-chmtime =-60 foo && + git svn rebase +' + test_expect_success 'able to set-tree to a subdirectory' " echo cba > d && git update-index d && diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh index 134411e0a5..3c4f31925f 100755 --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@ -20,7 +20,7 @@ test_expect_success 'setup svnrepo' ' ' test_expect_success 'start import with incomplete authors file' ' - ! git svn clone --authors-file=svn-authors "$svnrepo" x + test_must_fail git svn clone --authors-file=svn-authors "$svnrepo" x ' test_expect_success 'imported 2 revisions successfully' ' @@ -63,7 +63,7 @@ test_expect_success 'authors-file against globs' ' ' test_expect_success 'fetch fails on ee' ' - ( cd aa-work && ! git svn fetch --authors-file=../svn-authors ) + ( cd aa-work && test_must_fail git svn fetch --authors-file=../svn-authors ) ' tmp_config_get () { diff --git a/t/t9139-git-svn-non-utf8-commitencoding.sh b/t/t9139-git-svn-non-utf8-commitencoding.sh index f337959ccc..22d80b0be2 100755 --- a/t/t9139-git-svn-non-utf8-commitencoding.sh +++ b/t/t9139-git-svn-non-utf8-commitencoding.sh @@ -39,7 +39,7 @@ do ( cd $H && git config --unset i18n.commitencoding && - ! git svn dcommit + test_must_fail git svn dcommit ) ' done diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh index 0735526d4b..e855904629 100755 --- a/t/t9140-git-svn-reset.sh +++ b/t/t9140-git-svn-reset.sh @@ -41,7 +41,7 @@ test_expect_success 'modify hidden file in SVN repo' ' test_expect_success 'fetch fails on modified hidden file' ' ( cd g && git svn find-rev refs/remotes/git-svn > ../expect && - ! git svn fetch 2> ../errors && + test_must_fail git svn fetch 2> ../errors && git svn find-rev refs/remotes/git-svn > ../expect2 ) && fgrep "not found in commit" errors && test_cmp expect expect2 diff --git a/t/t9155-git-svn-fetch-deleted-tag.sh b/t/t9155-git-svn-fetch-deleted-tag.sh new file mode 100755 index 0000000000..a486a98f84 --- /dev/null +++ b/t/t9155-git-svn-fetch-deleted-tag.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='git svn fetch deleted tag' + +. ./lib-git-svn.sh + +test_expect_success 'setup svn repo' ' + mkdir -p import/trunk/subdir && + mkdir -p import/branches && + mkdir -p import/tags && + echo "base" >import/trunk/subdir/file && + svn_cmd import -m "import for git svn" import "$svnrepo" && + rm -rf import && + + svn_cmd mkdir -m "create mybranch directory" "$svnrepo/branches/mybranch" && + svn_cmd cp -m "create branch mybranch" "$svnrepo/trunk" "$svnrepo/branches/mybranch/trunk" && + + svn_cmd co "$svnrepo/trunk" svn_project && + (cd svn_project && + echo "trunk change" >>subdir/file && + svn_cmd ci -m "trunk change" subdir/file && + + svn_cmd switch "$svnrepo/branches/mybranch/trunk" && + echo "branch change" >>subdir/file && + svn_cmd ci -m "branch change" subdir/file + ) && + + svn_cmd cp -m "create mytag attempt 1" -r5 "$svnrepo/trunk/subdir" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag attempt 1" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag attempt 2" -r5 "$svnrepo/branches/mybranch/trunk/subdir" "$svnrepo/tags/mytag" +' + +test_expect_success 'fetch deleted tags from same revision with checksum error' ' + git svn init --stdlayout "$svnrepo" git_project && + cd git_project && + git svn fetch && + + git diff --exit-code mybranch:trunk/subdir/file tags/mytag:file && + git diff --exit-code master:subdir/file tags/mytag^:file +' + +test_done diff --git a/t/t9156-git-svn-fetch-deleted-tag-2.sh b/t/t9156-git-svn-fetch-deleted-tag-2.sh new file mode 100755 index 0000000000..5ce7e2f3b0 --- /dev/null +++ b/t/t9156-git-svn-fetch-deleted-tag-2.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='git svn fetch deleted tag 2' + +. ./lib-git-svn.sh + +test_expect_success 'setup svn repo' ' + mkdir -p import/branches && + mkdir -p import/tags && + mkdir -p import/trunk/subdir1 && + mkdir -p import/trunk/subdir2 && + mkdir -p import/trunk/subdir3 && + echo "file1" >import/trunk/subdir1/file && + echo "file2" >import/trunk/subdir2/file && + echo "file3" >import/trunk/subdir3/file && + svn_cmd import -m "import for git svn" import "$svnrepo" && + rm -rf import && + + svn_cmd co "$svnrepo/trunk" svn_project && + (cd svn_project && + echo "change1" >>subdir1/file && + echo "change2" >>subdir2/file && + echo "change3" >>subdir3/file && + svn_cmd ci -m "change" . + ) && + + svn_cmd cp -m "create mytag 1" -r2 "$svnrepo/trunk/subdir1" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag 1" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag 2" -r2 "$svnrepo/trunk/subdir2" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag 2" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag 3" -r2 "$svnrepo/trunk/subdir3" "$svnrepo/tags/mytag" +' + +test_expect_success 'fetch deleted tags from same revision with no checksum error' ' + git svn init --stdlayout "$svnrepo" git_project && + cd git_project && + git svn fetch && + + git diff --exit-code master:subdir3/file tags/mytag:file && + git diff --exit-code master:subdir2/file tags/mytag^:file && + git diff --exit-code master:subdir1/file tags/mytag^^:file +' + +test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 131f032988..96d07f1833 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -166,6 +166,63 @@ test_expect_success \ test `git rev-parse --verify master:file2` \ = `git rev-parse --verify verify--import-marks:copy-of-file2`' +test_tick +mt=$(git hash-object --stdin < /dev/null) +: >input.blob +: >marks.exp +: >tree.exp + +cat >input.commit <<EOF +commit refs/heads/verify--dump-marks +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +test the sparse array dumping routines with exponentially growing marks +COMMIT +EOF + +i=0 +l=4 +m=6 +n=7 +while test "$i" -lt 27; do + cat >>input.blob <<EOF +blob +mark :$l +data 0 +blob +mark :$m +data 0 +blob +mark :$n +data 0 +EOF + echo "M 100644 :$l l$i" >>input.commit + echo "M 100644 :$m m$i" >>input.commit + echo "M 100644 :$n n$i" >>input.commit + + echo ":$l $mt" >>marks.exp + echo ":$m $mt" >>marks.exp + echo ":$n $mt" >>marks.exp + + printf "100644 blob $mt\tl$i\n" >>tree.exp + printf "100644 blob $mt\tm$i\n" >>tree.exp + printf "100644 blob $mt\tn$i\n" >>tree.exp + + l=$(($l + $l)) + m=$(($m + $m)) + n=$(($l + $n)) + + i=$((1 + $i)) +done + +sort tree.exp > tree.exp_s + +test_expect_success 'A: export marks with large values' ' + cat input.blob input.commit | git fast-import --export-marks=marks.large && + git ls-tree refs/heads/verify--dump-marks >tree.out && + test_cmp tree.exp_s tree.out && + test_cmp marks.exp marks.large' + ### ### series B ### @@ -796,6 +853,60 @@ test_expect_success \ 'git fast-import <input && test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`' +test_expect_success \ + 'N: copy directory by id' \ + 'cat >expect <<-\EOF && + :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf + :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf + EOF + subdir=$(git rev-parse refs/heads/branch^0:file2) && + cat >input <<-INPUT_END && + commit refs/heads/N4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy by tree hash + COMMIT + + from refs/heads/branch^0 + M 040000 $subdir file3 + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N4^ N4 >actual && + compare_diff_raw expect actual' + +test_expect_success \ + 'N: modify copied tree' \ + 'cat >expect <<-\EOF && + :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting file3/file5 + :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf + :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf + EOF + subdir=$(git rev-parse refs/heads/branch^0:file2) && + cat >input <<-INPUT_END && + commit refs/heads/N5 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy by tree hash + COMMIT + + from refs/heads/branch^0 + M 040000 $subdir file3 + + commit refs/heads/N5 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + modify directory copy + COMMIT + + M 644 inline file3/file5 + data <<EOF + $file5_data + EOF + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N5^^ N5 >actual && + compare_diff_raw expect actual' + ### ### series O ### diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index d43f37ccaf..d831404fba 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -355,6 +355,20 @@ test_expect_failure 'no exact-ref revisions included' ' ) ' +test_expect_success 'path limiting with import-marks does not lose unmodified files' ' + git checkout -b simple marks~2 && + git fast-export --export-marks=marks simple -- file > /dev/null && + echo more content >> file && + test_tick && + git commit -mnext file && + git fast-export --import-marks=marks simple -- file file0 | grep file0 +' + +test_expect_success 'full-tree re-shows unmodified files' ' + git checkout -f simple && + test $(git fast-export --full-tree simple | grep -c file0) -eq 3 +' + test_expect_success 'set-up a few more tags for tag export tests' ' git checkout -f master && HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` && diff --git a/t/test-lib.sh b/t/test-lib.sh index e5523dd690..3a3d4c4723 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -127,14 +127,13 @@ do -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; -q|--q|--qu|--qui|--quie|--quiet) - quiet=t; shift ;; + # Ignore --quiet under a TAP::Harness. Saying how many tests + # passed without the ok/not ok details is always an error. + test -z "$HARNESS_ACTIVE" && quiet=t; shift ;; --with-dashes) with_dashes=t; shift ;; --no-color) color=; shift ;; - --no-python) - # noop now... - shift ;; --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) valgrind=t; verbose=t; shift ;; --tee) @@ -257,6 +256,10 @@ q_to_cr () { tr Q '\015' } +q_to_tab () { + tr Q '\011' +} + append_cr () { sed -e 's/$/Q/' | tr Q '\015' } @@ -542,6 +545,38 @@ test_external_without_stderr () { fi } +# debugging-friendly alternatives to "test [-f|-d|-e]" +# The commands test the existence or non-existence of $1. $2 can be +# given to provide a more precise diagnosis. +test_path_is_file () { + if ! [ -f "$1" ] + then + echo "File $1 doesn't exist. $*" + false + fi +} + +test_path_is_dir () { + if ! [ -d "$1" ] + then + echo "Directory $1 doesn't exist. $*" + false + fi +} + +test_path_is_missing () { + if [ -e "$1" ] + then + echo "Path exists:" + ls -ld "$1" + if [ $# -ge 1 ]; then + echo "$*" + fi + false + fi +} + + # This is not among top-level (test_expect_success | test_expect_failure) # but is a prefix that can be used in the test script, like: # |