diff options
Diffstat (limited to 't')
57 files changed, 1820 insertions, 270 deletions
diff --git a/t/.gitattributes b/t/.gitattributes index ab6edbf19e..1b97c5465b 100644 --- a/t/.gitattributes +++ b/t/.gitattributes @@ -1,2 +1 @@ -t[0-9][0-9][0-9][0-9]-*.sh -whitespace t[0-9][0-9][0-9][0-9]/* -whitespace diff --git a/t/.gitignore b/t/.gitignore index 11ffd910c1..b27e280083 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -1 +1,2 @@ /trash directory +/test-results diff --git a/t/Makefile b/t/Makefile index c6a60ab165..a778865ae7 100644 --- a/t/Makefile +++ b/t/Makefile @@ -14,18 +14,24 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) TSVN = $(wildcard t91[0-9][0-9]-*.sh) -all: $(T) clean +all: pre-clean $(T) aggregate-results clean $(T): @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) +pre-clean: + $(RM) -r test-results + clean: - $(RM) -r 'trash directory' + $(RM) -r 'trash directory' test-results + +aggregate-results: + ./aggregate-results.sh test-results/t*-* # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL full-svn-test: $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8 -.PHONY: $(T) clean +.PHONY: pre-clean $(T) aggregate-results clean .NOTPARALLEL: @@ -54,6 +54,38 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate This causes the test to immediately exit upon the first failed test. +--long-tests:: + This causes additional long-running tests to be run (where + available), for more exhaustive testing. + + +Skipping Tests +-------------- + +In some environments, certain tests have no way of succeeding +due to platform limitation, such as lack of 'unzip' program, or +filesystem that do not allow arbitrary sequence of non-NUL bytes +as pathnames. + +You should be able to say something like + + $ GIT_SKIP_TESTS=t9200.8 sh ./t9200-git-cvsexport-commit.sh + +and even: + + $ GIT_SKIP_TESTS='t[0-4]??? t91?? t9200.8' make + +to omit such tests. The value of the environment variable is a +SP separated list of patterns that tells which tests to skip, +and either can match the "t[0-9]{4}" part to skip the whole +test, or t[0-9]{4} followed by ".$number" to say which +particular test to skip. + +Note that some tests in the existing test suite rely on previous +test item, so you cannot arbitrarily disable one and expect the +remainder of test to check what the test originally was intended +to check. + Naming Tests ------------ diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh new file mode 100755 index 0000000000..52e88e3046 --- /dev/null +++ b/t/aggregate-results.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +fixed=0 +success=0 +failed=0 +broken=0 +total=0 + +for file +do + while read type value + do + case $type in + '') + continue ;; + fixed) + fixed=$(($fixed + $value)) ;; + success) + success=$(($success + $value)) ;; + failed) + failed=$(($failed + $value)) ;; + broken) + broken=$(( $broken + $value)) ;; + total) + total=$(( $total + $value)) ;; + esac + done <"$file" +done + +printf "%-8s%d\n" fixed $fixed +printf "%-8s%d\n" success $success +printf "%-8s%d\n" failed $failed +printf "%-8s%d\n" broken $broken +printf "%-8s%d\n" total $total diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index a5c4436fd1..dc473dfb53 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -45,22 +45,22 @@ else error "Could not identify web server at '$LIB_HTTPD_PATH'" fi -HTTPD_PARA="-d $HTTPD_ROOT_PATH -f $TEST_PATH/apache.conf" +HTTPD_PARA="" prepare_httpd() { - mkdir -p $HTTPD_DOCUMENT_ROOT_PATH + mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH" - ln -s $LIB_HTTPD_MODULE_PATH $HTTPD_ROOT_PATH/modules + ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules" if test -n "$LIB_HTTPD_SSL" then HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \ - -config $TEST_PATH/ssl.cnf \ + -config "$TEST_PATH/ssl.cnf" \ -new -x509 -nodes \ - -out $HTTPD_ROOT_PATH/httpd.pem \ - -keyout $HTTPD_ROOT_PATH/httpd.pem + -out "$HTTPD_ROOT_PATH/httpd.pem" \ + -keyout "$HTTPD_ROOT_PATH/httpd.pem" GIT_SSL_NO_VERIFY=t export GIT_SSL_NO_VERIFY HTTPD_PARA="$HTTPD_PARA -DSSL" @@ -86,12 +86,14 @@ start_httpd() { trap 'stop_httpd; die' exit - "$LIB_HTTPD_PATH" $HTTPD_PARA \ + "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ + -f "$TEST_PATH/apache.conf" $HTTPD_PARA \ -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start } stop_httpd() { trap 'die' exit - "$LIB_HTTPD_PATH" $HTTPD_PARA -k stop + "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ + -f "$TEST_PATH/apache.conf" -k stop } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index a4473462d1..4717c2d33b 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -1,3 +1,4 @@ +ServerName dummy PidFile httpd.pid DocumentRoot www ErrorLog error.log diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 690f80ab27..d7cbc5c6da 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -301,14 +301,14 @@ test_expect_success 'absolute path works as expected' ' mkdir third && dir="$(cd .git; pwd -P)" && dir2=third/../second/other/.git && - test "$dir" = "$(test-absolute-path $dir2)" && + test "$dir" = "$(test-path-utils make_absolute_path $dir2)" && file="$dir"/index && - test "$file" = "$(test-absolute-path $dir2/index)" && + test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" && basename=blub && - test "$dir/$basename" = "$(cd .git && test-absolute-path "$basename")" && + test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" && ln -s ../first/file .git/syml && sym="$(cd first; pwd -P)"/file && - test "$sym" = "$(test-absolute-path "$dir2/syml")" + test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")" ' test_expect_success 'very long name in the index handled sanely' ' diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh index 9255c63c08..63e1217e71 100755 --- a/t/t0004-unwritable.sh +++ b/t/t0004-unwritable.sh @@ -8,6 +8,7 @@ test_expect_success setup ' >file && git add file && + test_tick && git commit -m initial && echo >file && git add file @@ -17,11 +18,11 @@ test_expect_success setup ' test_expect_success 'write-tree should notice unwritable repository' ' ( - chmod a-w .git/objects + chmod a-w .git/objects .git/objects/?? && test_must_fail git write-tree ) status=$? - chmod 775 .git/objects + chmod 775 .git/objects .git/objects/?? (exit $status) ' @@ -29,11 +30,11 @@ test_expect_success 'write-tree should notice unwritable repository' ' test_expect_success 'commit should notice unwritable repository' ' ( - chmod a-w .git/objects + chmod a-w .git/objects .git/objects/?? && test_must_fail git commit -m second ) status=$? - chmod 775 .git/objects + chmod 775 .git/objects .git/objects/?? (exit $status) ' @@ -41,12 +42,12 @@ test_expect_success 'commit should notice unwritable repository' ' test_expect_success 'update-index should notice unwritable repository' ' ( - echo a >file && - chmod a-w .git/objects + echo 6O >file && + chmod a-w .git/objects .git/objects/?? && test_must_fail git update-index file ) status=$? - chmod 775 .git/objects + chmod 775 .git/objects .git/objects/?? (exit $status) ' @@ -55,11 +56,11 @@ test_expect_success 'add should notice unwritable repository' ' ( echo b >file && - chmod a-w .git/objects + chmod a-w .git/objects .git/objects/?? && test_must_fail git add file ) status=$? - chmod 775 .git/objects + chmod 775 .git/objects .git/objects/?? (exit $status) ' diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh new file mode 100755 index 0000000000..6e7501f352 --- /dev/null +++ b/t/t0060-path-utils.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Copyright (c) 2008 David Reiss +# + +test_description='Test various path utilities' + +. ./test-lib.sh + +norm_abs() { + test_expect_success "normalize absolute" \ + "test \$(test-path-utils normalize_absolute_path '$1') = '$2'" +} + +ancestor() { + test_expect_success "longest ancestor" \ + "test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'" +} + +norm_abs "" / +norm_abs / / +norm_abs // / +norm_abs /// / +norm_abs /. / +norm_abs /./ / +norm_abs /./.. / +norm_abs /../. / +norm_abs /./../.// / +norm_abs /dir/.. / +norm_abs /dir/sub/../.. / +norm_abs /dir /dir +norm_abs /dir// /dir +norm_abs /./dir /dir +norm_abs /dir/. /dir +norm_abs /dir///./ /dir +norm_abs /dir//sub/.. /dir +norm_abs /dir/sub/../ /dir +norm_abs //dir/sub/../. /dir +norm_abs /dir/s1/../s2/ /dir/s2 +norm_abs /d1/s1///s2/..//../s3/ /d1/s3 +norm_abs /d1/s1//../s2/../../d2 /d2 +norm_abs /d1/.../d2 /d1/.../d2 +norm_abs /d1/..././../d2 /d1/d2 + +ancestor / "" -1 +ancestor / / -1 +ancestor /foo "" -1 +ancestor /foo : -1 +ancestor /foo ::. -1 +ancestor /foo ::..:: -1 +ancestor /foo / 0 +ancestor /foo /fo -1 +ancestor /foo /foo -1 +ancestor /foo /foo/ -1 +ancestor /foo /bar -1 +ancestor /foo /bar/ -1 +ancestor /foo /foo/bar -1 +ancestor /foo /foo:/bar/ -1 +ancestor /foo /foo/:/bar/ -1 +ancestor /foo /foo::/bar/ -1 +ancestor /foo /:/foo:/bar/ 0 +ancestor /foo /foo:/:/bar/ 0 +ancestor /foo /:/bar/:/foo 0 +ancestor /foo/bar "" -1 +ancestor /foo/bar / 0 +ancestor /foo/bar /fo -1 +ancestor /foo/bar foo -1 +ancestor /foo/bar /foo 4 +ancestor /foo/bar /foo/ 4 +ancestor /foo/bar /foo/ba -1 +ancestor /foo/bar /:/fo 0 +ancestor /foo/bar /foo:/foo/ba 4 +ancestor /foo/bar /bar -1 +ancestor /foo/bar /bar/ -1 +ancestor /foo/bar /fo: -1 +ancestor /foo/bar :/fo -1 +ancestor /foo/bar /foo:/bar/ 4 +ancestor /foo/bar /:/foo:/bar/ 4 +ancestor /foo/bar /foo:/:/bar/ 4 +ancestor /foo/bar /:/bar/:/fo 0 +ancestor /foo/bar /:/bar/ 0 +ancestor /foo/bar :://foo/. 4 +ancestor /foo/bar :://foo/.:: 4 +ancestor /foo/bar //foo/./::/bar 4 +ancestor /foo/bar ::/bar -1 + +test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index b8b7ab4103..ca99d37616 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -42,6 +42,14 @@ test_expect_success "delete $m" ' ' rm -f .git/$m +test_expect_success "delete $m without oldvalue verification" " + git update-ref $m $A && + test $A = \$(cat .git/$m) && + git update-ref -d $m && + ! test -f .git/$m +" +rm -f .git/$m + test_expect_success \ "fail to create $n" \ "touch .git/$n_dir @@ -147,7 +155,8 @@ rm -f .git/$m .git/logs/$m expect git update-ref $m $D cat >.git/logs/$m <<EOF -$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 +0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 +$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 @@ -178,6 +187,12 @@ test_expect_success \ 'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \ 'rm -f o e git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e && + test '"$C"' = $(cat o) && + test "" = "$(cat e)"' +test_expect_success \ + 'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \ + 'rm -f o e + git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e && test '"$A"' = $(cat o) && test "" = "$(cat e)"' test_expect_success \ diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index 3508d0a612..997002d4c4 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -5,7 +5,7 @@ test_description='test git rev-parse --parseopt' cat > expect.err <<EOF usage: some-command [options] <args>... - + some-command does foo and bar! -h, --help show the help diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh new file mode 100755 index 0000000000..91b704a3a4 --- /dev/null +++ b/t/t1504-ceiling-dirs.sh @@ -0,0 +1,163 @@ +#!/bin/sh + +test_description='test GIT_CEILING_DIRECTORIES' +. ./test-lib.sh + +test_prefix() { + test_expect_success "$1" \ + "test '$2' = \"\$(git rev-parse --show-prefix)\"" +} + +test_fail() { + test_expect_code 128 "$1: prefix" \ + "git rev-parse --show-prefix" +} + +TRASH_ROOT="$(pwd)" +ROOT_PARENT=$(dirname "$TRASH_ROOT") + + +unset GIT_CEILING_DIRECTORIES +test_prefix no_ceil "" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix ceil_empty "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT" +test_prefix ceil_at_parent "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT/" +test_prefix ceil_at_parent_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_prefix ceil_at_trash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_prefix ceil_at_trash_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_prefix ceil_at_sub "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_prefix ceil_at_sub_slash "" + + +mkdir -p sub/dir || exit 1 +cd sub/dir || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix subdir_no_ceil "sub/dir/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix subdir_ceil_empty "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail subdir_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail subdir_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_fail subdir_ceil_at_sub + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_fail subdir_ceil_at_sub_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir" +test_prefix subdir_ceil_at_subdir "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/" +test_prefix subdir_ceil_at_subdir_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix subdir_ceil_at_su "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix subdir_ceil_at_su_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub" +test_fail second_of_two + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar" +test_fail first_of_two + +GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar" +test_fail second_of_three + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +GIT_DIR=../../.git +export GIT_DIR +test_prefix git_dir_specified "" +unset GIT_DIR + + +cd ../.. || exit 1 +mkdir -p s/d || exit 1 +cd s/d || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix sd_no_ceil "s/d/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix sd_ceil_empty "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail sd_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail sd_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s" +test_fail sd_ceil_at_s + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/" +test_fail sd_ceil_at_s_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d" +test_prefix sd_ceil_at_sd "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/" +test_prefix sd_ceil_at_sd_slash "s/d/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix sd_ceil_at_su "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix sd_ceil_at_su_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi_slash "s/d/" + + +test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index b9e3dbd242..092aa26573 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -96,6 +96,7 @@ chmod a+x fake-editor.sh test_expect_success 'no changes are a nop' ' git rebase -i F && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && test $(git rev-parse I) = $(git rev-parse HEAD) ' @@ -104,14 +105,26 @@ test_expect_success 'test the [branch] option' ' git rm file6 && git commit -m "stop here" && git rebase -i F branch2 && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && + test $(git rev-parse I) = $(git rev-parse branch2) && test $(git rev-parse I) = $(git rev-parse HEAD) ' +test_expect_success 'test --onto <branch>' ' + git checkout -b test-onto branch2 && + git rebase -i --onto branch1 F && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && + test $(git rev-parse HEAD^) = $(git rev-parse branch1) && + test $(git rev-parse I) = $(git rev-parse branch2) +' + test_expect_success 'rebase on top of a non-conflicting commit' ' git checkout branch1 && git tag original-branch1 && git rebase -i branch2 && test file6 = $(git diff --name-only original-branch1) && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && + test $(git rev-parse I) = $(git rev-parse branch2) && test $(git rev-parse I) = $(git rev-parse HEAD~2) ' @@ -144,9 +157,12 @@ EOF test_expect_success 'stop on conflicting pick' ' git tag new-branch1 && - ! git rebase -i master && + test_must_fail git rebase -i master && + test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" && test_cmp expect .git/.dotest-merge/patch && test_cmp expect2 file1 && + test "$(git-diff --name-status | + sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 && test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) && test 0 = $(grep -c "^[^#]" < .git/.dotest-merge/git-rebase-todo) ' @@ -154,6 +170,7 @@ test_expect_success 'stop on conflicting pick' ' 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/.dotest-merge ' @@ -194,7 +211,7 @@ test_expect_success 'preserve merges with -p' ' git add unrelated-file && test_tick && git commit -m "unrelated" && - git checkout -b to-be-rebased master && + git checkout -b another-branch master && echo B > file1 && test_tick && git commit -m J file1 && @@ -203,17 +220,33 @@ test_expect_success 'preserve merges with -p' ' echo C > file1 && test_tick && git commit -m K file1 && + echo D > file1 && + test_tick && + git commit -m L1 file1 && + git checkout HEAD^ && + echo 1 > unrelated-file && + test_tick && + git commit -m L2 unrelated-file && + test_tick && + git merge another-branch && + echo E > file1 && + test_tick && + git commit -m M file1 && + git checkout -b to-be-rebased && test_tick && git rebase -i -p --onto branch1 master && - test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) && - test $(git rev-parse HEAD~3) = $(git rev-parse branch1) && - test $(git show HEAD:file1) = C && - test $(git show HEAD~2:file1) = B + test $(git rev-parse HEAD~6) = $(git rev-parse branch1) && + test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) && + test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) && + test $(git show HEAD~5:file1) = B && + test $(git show HEAD~3:file1) = C && + test $(git show HEAD:file1) = E && + test $(git show HEAD:unrelated-file) = 1 ' test_expect_success '--continue tries to commit' ' test_tick && - ! git rebase -i --onto new-branch1 HEAD^ && + test_must_fail git rebase -i --onto new-branch1 HEAD^ && echo resolved > file1 && git add file1 && FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue && @@ -224,7 +257,7 @@ test_expect_success '--continue tries to commit' ' test_expect_success 'verbose flag is heeded, even after --continue' ' git reset --hard HEAD@{1} && test_tick && - ! git rebase -v -i --onto new-branch1 HEAD^ && + test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && echo resolved > file1 && git add file1 && git rebase --continue > output && @@ -259,10 +292,14 @@ test_expect_success 'interrupted squash works as expected' ' git commit -m $n done && one=$(git rev-parse HEAD~3) && - ! FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 && + ( + FAKE_LINES="1 squash 3 2" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD~3 + ) && (echo one; echo two; echo four) > conflict && git add conflict && - ! git rebase --continue && + test_must_fail git rebase --continue && echo resolved > conflict && git add conflict && git rebase --continue && @@ -277,13 +314,17 @@ test_expect_success 'interrupted squash works as expected (case 2)' ' git commit -m $n done && one=$(git rev-parse HEAD~3) && - ! FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 && + ( + FAKE_LINES="3 squash 1 2" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD~3 + ) && (echo one; echo four) > conflict && git add conflict && - ! git rebase --continue && + test_must_fail git rebase --continue && (echo one; echo two; echo four) > conflict && git add conflict && - ! git rebase --continue && + test_must_fail git rebase --continue && echo resolved > conflict && git add conflict && git rebase --continue && @@ -331,7 +372,7 @@ test_expect_success 'rebase a commit violating pre-commit' ' chmod a+x $PRE_COMMIT && echo "monde! " >> file1 && test_tick && - ! git commit -m doesnt-verify file1 && + test_must_fail git commit -m doesnt-verify file1 && git commit -m doesnt-verify --no-verify file1 && test_tick && FAKE_LINES=2 git rebase -i HEAD~2 diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh new file mode 100755 index 0000000000..b0faa29918 --- /dev/null +++ b/t/t3503-cherry-pick-root.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='test cherry-picking a root commit' + +. ./test-lib.sh + +test_expect_success setup ' + + echo first > file1 && + git add file1 && + test_tick && + git commit -m "first" && + + git symbolic-ref HEAD refs/heads/second && + rm .git/index file1 && + echo second > file2 && + git add file2 && + test_tick && + git commit -m "second" + +' + +test_expect_success 'cherry-pick a root commit' ' + + git cherry-pick master && + test first = $(cat file1) + +' + +test_done diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index fae64eae9f..e95663d8e6 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -66,6 +66,73 @@ test_expect_success 'revert works (commit)' ' grep "unchanged *+3/-0 file" output ' +cat >expected <<EOF +EOF +cat >fake_editor.sh <<EOF +EOF +chmod a+x fake_editor.sh +test_set_editor "$(pwd)/fake_editor.sh" +test_expect_success 'dummy edit works' ' + (echo e; echo a) | git add -p && + git diff > diff && + test_cmp expected diff +' + +cat >patch <<EOF +@@ -1,1 +1,4 @@ + this ++patch +-doesn't + apply +EOF +echo "#!$SHELL_PATH" >fake_editor.sh +cat >>fake_editor.sh <<\EOF +mv -f "$1" oldpatch && +mv -f patch "$1" +EOF +chmod a+x fake_editor.sh +test_set_editor "$(pwd)/fake_editor.sh" +test_expect_success 'bad edit rejected' ' + git reset && + (echo e; echo n; echo d) | git add -p >output && + grep "hunk does not apply" output +' + +cat >patch <<EOF +this patch +is garbage +EOF +test_expect_success 'garbage edit rejected' ' + git reset && + (echo e; echo n; echo d) | git add -p >output && + grep "hunk does not apply" output +' + +cat >patch <<EOF +@@ -1,0 +1,0 @@ + baseline ++content ++newcontent ++lines +EOF +cat >expected <<EOF +diff --git a/file b/file +index b5dd6c9..f910ae9 100644 +--- a/file ++++ b/file +@@ -1,4 +1,4 @@ + baseline + content +-newcontent ++more + lines +EOF +test_expect_success 'real edit works' ' + (echo e; echo n; echo d) | git add -p && + git diff >output && + test_cmp expected output +' + if test "$(git config --bool core.filemode)" = false then say 'skipping filemode tests (filesystem does not properly support modes)' diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index df1fd6f86f..c851db8ca9 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -241,11 +241,11 @@ check_verify_failure 'disallow spaces in tag email' \ ############################################################ # 17. disallow missing tag timestamp -cat >tag.sig <<EOF +tr '_' ' ' >tag.sig <<EOF object $head type commit tag mytag -tagger T A Gger <tagger@example.com> +tagger T A Gger <tagger@example.com>__ EOF diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 2d3ee3b78c..8d4804b658 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -41,7 +41,7 @@ test_expect_success 'apply needs clean working directory' ' echo 4 > other-file && git add other-file && echo 5 > other-file && - test_must_fail git stash apply + test_must_fail git stash apply ' test_expect_success 'apply stashed changes' ' @@ -117,4 +117,64 @@ test_expect_success 'stash pop' ' test 0 = $(git stash list | wc -l) ' +cat > expect << EOF +diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..1fe912c +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++bar2 +EOF + +cat > expect1 << EOF +diff --git a/file b/file +index 257cc56..5716ca5 100644 +--- a/file ++++ b/file +@@ -1 +1 @@ +-foo ++bar +EOF + +cat > expect2 << EOF +diff --git a/file b/file +index 7601807..5716ca5 100644 +--- a/file ++++ b/file +@@ -1 +1 @@ +-baz ++bar +diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..1fe912c +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++bar2 +EOF + +test_expect_success 'stash branch' ' + echo foo > file && + git commit file -m first + echo bar > file && + echo bar2 > file2 && + git add file2 && + git stash && + echo baz > file && + git commit file -m second && + git stash branch stashbranch && + test refs/heads/stashbranch = $(git symbolic-ref HEAD) && + test $(git rev-parse HEAD) = $(git rev-parse master^) && + git diff --cached > output && + test_cmp output expect && + git diff > output && + test_cmp output expect1 && + git add file && + git commit -m alternate\ second && + git diff master..stashbranch > output && + test_cmp output expect2 && + test 0 = $(git stash list | wc -l) +' + test_done diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 3583e68e92..7fe853c20d 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -98,7 +98,7 @@ test_expect_success 'extra headers' ' sed -e "/^$/q" patch2 > hdrs2 && grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 && grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2 - + ' test_expect_success 'extra headers without newlines' ' @@ -109,7 +109,7 @@ test_expect_success 'extra headers without newlines' ' sed -e "/^$/q" patch3 > hdrs3 && grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 && grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3 - + ' test_expect_success 'extra headers with multiple To:s' ' @@ -170,7 +170,7 @@ test_expect_success 'thread cover-letter' ' git checkout side && git format-patch --cover-letter --thread -o patches/ master && FIRST_MID=$(grep "Message-Id:" patches/0000-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") && - for i in patches/0001-* patches/0002-* patches/0003-* + for i in patches/0001-* patches/0002-* patches/0003-* do grep "References: $FIRST_MID" $i && grep "In-Reply-To: $FIRST_MID" $i || break diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index ca0302f41b..0922c708f1 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -62,16 +62,16 @@ EOF git update-index x -cat << EOF > x +tr '_' ' ' << EOF > x whitespace at beginning whitespace change white space in the middle -whitespace at end +whitespace at end__ unchanged line CR at end EOF -tr 'Q' '\015' << EOF > expect +tr 'Q_' '\015 ' << EOF > expect diff --git a/x b/x index d99af23..8b32fb5 100644 --- a/x @@ -84,7 +84,7 @@ index d99af23..8b32fb5 100644 + whitespace at beginning +whitespace change +white space in the middle -+whitespace at end ++whitespace at end__ unchanged line -CR at endQ +CR at end @@ -335,4 +335,10 @@ test_expect_success 'line numbers in --check output are correct' ' ' +test_expect_success 'checkdiff detects trailing blank lines' ' + echo "foo();" >x && + echo "" >>x && + git diff --check | grep "ends with blank" +' + test_done diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index 0950250c9b..f07035ab7e 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -53,13 +53,13 @@ test_expect_success 'git diff --summary -M HEAD' ' ' cat >expect <<\EOF - pathname.1 => "Rpathname\twith HT.0" | 0 - pathname.3 => "Rpathname\nwith LF.0" | 0 - "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 - pathname.2 => Rpathname with SP.0 | 0 - "pathname\twith HT.2" => Rpathname with SP.1 | 0 - pathname.0 => Rpathname.0 | 0 - "pathname\twith HT.0" => Rpathname.1 | 0 + pathname.1 => "Rpathname\twith HT.0" | 0 + pathname.3 => "Rpathname\nwith LF.0" | 0 + "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 + pathname.2 => Rpathname with SP.0 | 0 + "pathname\twith HT.2" => Rpathname with SP.1 | 0 + pathname.0 => Rpathname.0 | 0 + "pathname\twith HT.0" => Rpathname.1 | 0 7 files changed, 0 insertions(+), 0 deletions(-) EOF test_expect_success 'git diff --stat -M HEAD' ' diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh index 0d0fb87f57..60dd2014d5 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -113,4 +113,18 @@ test_expect_success 'check should test not just the last line' ' ' +test_expect_success 'check detects leftover conflict markers' ' + git reset --hard && + git checkout HEAD^ && + echo binary >>b && + git commit -m "side" b && + test_must_fail git merge master && + git add b && ( + git --no-pager diff --cached --check >test.out + test $? = 2 + ) && + test 3 = $(grep "conflict marker" test.out | wc -l) && + git reset --hard +' + test_done diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 8073a5a1f2..e0c67740a5 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -3,44 +3,38 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git apply --stat --summary test. +test_description='git apply --stat --summary test, with --recount ' . ./test-lib.sh -test_expect_success \ - 'rename' \ - 'git apply --stat --summary <../t4100/t-apply-1.patch >current && - test_cmp ../t4100/t-apply-1.expect current' - -test_expect_success \ - 'copy' \ - 'git apply --stat --summary <../t4100/t-apply-2.patch >current && - test_cmp ../t4100/t-apply-2.expect current' - -test_expect_success \ - 'rewrite' \ - 'git apply --stat --summary <../t4100/t-apply-3.patch >current && - test_cmp ../t4100/t-apply-3.expect current' - -test_expect_success \ - 'mode' \ - 'git apply --stat --summary <../t4100/t-apply-4.patch >current && - test_cmp ../t4100/t-apply-4.expect current' - -test_expect_success \ - 'non git' \ - 'git apply --stat --summary <../t4100/t-apply-5.patch >current && - test_cmp ../t4100/t-apply-5.expect current' - -test_expect_success \ - 'non git' \ - 'git apply --stat --summary <../t4100/t-apply-6.patch >current && - test_cmp ../t4100/t-apply-6.expect current' - -test_expect_success \ - 'non git' \ - 'git apply --stat --summary <../t4100/t-apply-7.patch >current && - test_cmp ../t4100/t-apply-7.expect current' +UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/' + +num=0 +while read title +do + num=$(( $num + 1 )) + test_expect_success "$title" ' + git apply --stat --summary \ + <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current && + test_cmp ../t4100/t-apply-$num.expect current + ' + + test_expect_success "$title with recount" ' + sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" | + git apply --recount --stat --summary >current && + test_cmp ../t4100/t-apply-$num.expect current + ' +done <<\EOF +rename +copy +rewrite +mode +non git (1) +non git (2) +non git (3) +incomplete (1) +incomplete (2) +EOF test_done diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect new file mode 100644 index 0000000000..eef7f2e65c --- /dev/null +++ b/t/t4100/t-apply-8.expect @@ -0,0 +1,2 @@ + t/t4100-apply-stat.sh | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/t/t4100/t-apply-8.patch b/t/t4100/t-apply-8.patch new file mode 100644 index 0000000000..5ca13e6594 --- /dev/null +++ b/t/t4100/t-apply-8.patch @@ -0,0 +1,11 @@ +diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh +index be837bb..0798c64 100755 +--- a/t/t4100-apply-stat.sh ++++ b/t/t4100-apply-stat.sh +@@ -35,4 +35,4 @@ non git (2) + non git (3) + EOF + +-test_done ++test_done +\ No newline at end of file diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect new file mode 100644 index 0000000000..eef7f2e65c --- /dev/null +++ b/t/t4100/t-apply-9.expect @@ -0,0 +1,2 @@ + t/t4100-apply-stat.sh | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/t/t4100/t-apply-9.patch b/t/t4100/t-apply-9.patch new file mode 100644 index 0000000000..875d57d567 --- /dev/null +++ b/t/t4100/t-apply-9.patch @@ -0,0 +1,11 @@ +diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh +index 0798c64..be837bb 100755 +--- a/t/t4100-apply-stat.sh ++++ b/t/t4100-apply-stat.sh +@@ -35,4 +35,4 @@ non git (2) + non git (3) + EOF + +-test_done +\ No newline at end of file ++test_done diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh index bd40a218cd..ff5fdf35f9 100755 --- a/t/t4109-apply-multifrag.sh +++ b/t/t4109-apply-multifrag.sh @@ -9,134 +9,10 @@ test_description='git apply test patches with multiple fragments. ' . ./test-lib.sh -# setup - -cat > patch1.patch <<\EOF -diff --git a/main.c b/main.c -new file mode 100644 ---- /dev/null -+++ b/main.c -@@ -0,0 +1,23 @@ -+#include <stdio.h> -+ -+int func(int num); -+void print_int(int num); -+ -+int main() { -+ int i; -+ -+ for (i = 0; i < 10; i++) { -+ print_int(func(i)); -+ } -+ -+ return 0; -+} -+ -+int func(int num) { -+ return num * num; -+} -+ -+void print_int(int num) { -+ printf("%d", num); -+} -+ -EOF -cat > patch2.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,7 +1,9 @@ -+#include <stdlib.h> - #include <stdio.h> - - int func(int num); - void print_int(int num); -+void print_ln(); - - int main() { - int i; -@@ -10,6 +12,8 @@ - print_int(func(i)); - } - -+ print_ln(); -+ - return 0; - } - -@@ -21,3 +25,7 @@ - printf("%d", num); - } - -+void print_ln() { -+ printf("\n"); -+} -+ -EOF -cat > patch3.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,9 +1,7 @@ --#include <stdlib.h> - #include <stdio.h> - - int func(int num); - void print_int(int num); --void print_ln(); - - int main() { - int i; -@@ -12,8 +10,6 @@ - print_int(func(i)); - } - -- print_ln(); -- - return 0; - } - -@@ -25,7 +21,3 @@ - printf("%d", num); - } - --void print_ln() { -- printf("\n"); --} -- -EOF -cat > patch4.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,13 +1,14 @@ - #include <stdio.h> - - int func(int num); --void print_int(int num); -+int func2(int num); - - int main() { - int i; - - for (i = 0; i < 10; i++) { -- print_int(func(i)); -+ printf("%d", func(i)); -+ printf("%d", func3(i)); - } - - return 0; -@@ -17,7 +18,7 @@ - return num * num; - } - --void print_int(int num) { -- printf("%d", num); -+int func2(int num) { -+ return num * num * num; - } - -EOF +cp ../t4109/patch1.patch . +cp ../t4109/patch2.patch . +cp ../t4109/patch3.patch . +cp ../t4109/patch4.patch . test_expect_success "S = git apply (1)" \ 'git apply patch1.patch patch2.patch' diff --git a/t/t4109/patch1.patch b/t/t4109/patch1.patch new file mode 100644 index 0000000000..1d411fc3cc --- /dev/null +++ b/t/t4109/patch1.patch @@ -0,0 +1,28 @@ +diff --git a/main.c b/main.c +new file mode 100644 +--- /dev/null ++++ b/main.c +@@ -0,0 +1,23 @@ ++#include <stdio.h> ++ ++int func(int num); ++void print_int(int num); ++ ++int main() { ++ int i; ++ ++ for (i = 0; i < 10; i++) { ++ print_int(func(i)); ++ } ++ ++ return 0; ++} ++ ++int func(int num) { ++ return num * num; ++} ++ ++void print_int(int num) { ++ printf("%d", num); ++} ++ diff --git a/t/t4109/patch2.patch b/t/t4109/patch2.patch new file mode 100644 index 0000000000..8c6b06d536 --- /dev/null +++ b/t/t4109/patch2.patch @@ -0,0 +1,30 @@ +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,7 +1,9 @@ ++#include <stdlib.h> + #include <stdio.h> + + int func(int num); + void print_int(int num); ++void print_ln(); + + int main() { + int i; +@@ -10,6 +12,8 @@ + print_int(func(i)); + } + ++ print_ln(); ++ + return 0; + } + +@@ -21,3 +25,7 @@ + printf("%d", num); + } + ++void print_ln() { ++ printf("\n"); ++} ++ diff --git a/t/t4109/patch3.patch b/t/t4109/patch3.patch new file mode 100644 index 0000000000..d696c55a75 --- /dev/null +++ b/t/t4109/patch3.patch @@ -0,0 +1,31 @@ +cat > patch3.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,9 +1,7 @@ +-#include <stdlib.h> + #include <stdio.h> + + int func(int num); + void print_int(int num); +-void print_ln(); + + int main() { + int i; +@@ -12,8 +10,6 @@ + print_int(func(i)); + } + +- print_ln(); +- + return 0; + } + +@@ -25,7 +21,3 @@ + printf("%d", num); + } + +-void print_ln() { +- printf("\n"); +-} +- diff --git a/t/t4109/patch4.patch b/t/t4109/patch4.patch new file mode 100644 index 0000000000..4b085909b1 --- /dev/null +++ b/t/t4109/patch4.patch @@ -0,0 +1,30 @@ +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,13 +1,14 @@ + #include <stdio.h> + + int func(int num); +-void print_int(int num); ++int func2(int num); + + int main() { + int i; + + for (i = 0; i < 10; i++) { +- print_int(func(i)); ++ printf("%d", func(i)); ++ printf("%d", func3(i)); + } + + return 0; +@@ -17,7 +18,7 @@ + return num * num; + } + +-void print_int(int num) { +- printf("%d", num); ++int func2(int num) { ++ return num * num * num; + } + diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index 70a1859503..f9ad183758 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -36,6 +36,9 @@ typedef struct __jmp_buf jmp_buf[1]; #endif /* _SETJMP_H */ EOF +cat >klibc/README <<\EOF +This is a simple readme file. +EOF cat >patch <<\EOF diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/cris/klibc/archsetjmp.h @@ -113,6 +116,23 @@ rename to include/arch/m32r/klibc/archsetjmp.h -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ +diff --git a/klibc/README b/klibc/README +--- a/klibc/README ++++ b/klibc/README +@@ -1,1 +1,4 @@ + This is a simple readme file. ++And we add a few ++lines at the ++end of it. +diff --git a/klibc/README b/klibc/arch/README +copy from klibc/README +copy to klibc/arch/README +--- a/klibc/README ++++ b/klibc/arch/README +@@ -1,1 +1,3 @@ + This is a simple readme file. ++And we copy it to one level down, and ++add a few lines at the end of it. EOF find klibc -type f -print | xargs git update-index --add -- diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index b540f7295a..3c73a783a7 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -19,12 +19,12 @@ test_expect_success setup ' ' # Also handcraft GNU diff output; note this has trailing whitespace. -cat >gpatch.file <<\EOF && +tr '_' ' ' >gpatch.file <<\EOF && --- file1 2007-02-21 01:04:24.000000000 -0800 +++ file1+ 2007-02-21 01:07:44.000000000 -0800 @@ -1 +1 @@ -A -+B ++B_ EOF sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file && diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh new file mode 100755 index 0000000000..1f859dd908 --- /dev/null +++ b/t/t4127-apply-same-fn.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='apply same filename' + +. ./test-lib.sh + +modify () { + sed -e "$1" < "$2" > "$2".x && + mv "$2".x "$2" +} + +test_expect_success setup ' + for i in a b c d e f g h i j k l m + do + echo $i + done >same_fn && + cp same_fn other_fn && + git add same_fn other_fn && + git commit -m initial +' +test_expect_success 'apply same filename with independent changes' ' + modify "s/^d/z/" same_fn && + git diff > patch0 && + git add same_fn && + modify "s/^i/y/" same_fn && + git diff >> patch0 && + cp same_fn same_fn2 && + git reset --hard && + git-apply patch0 && + diff same_fn same_fn2 +' + +test_expect_success 'apply same filename with overlapping changes' ' + git reset --hard + modify "s/^d/z/" same_fn && + git diff > patch0 && + git add same_fn && + modify "s/^e/y/" same_fn && + git diff >> patch0 && + cp same_fn same_fn2 && + git reset --hard && + git-apply patch0 && + diff same_fn same_fn2 +' + +test_expect_success 'apply same new filename after rename' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + modify "s/^e/y/" new_fn && + git diff >> patch1 && + cp new_fn new_fn2 && + git reset --hard && + git apply --index patch1 && + diff new_fn new_fn2 +' + +test_expect_success 'apply same old filename after rename -- should fail.' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + git mv new_fn same_fn + modify "s/^e/y/" same_fn && + git diff >> patch1 && + git reset --hard && + test_must_fail git apply patch1 +' + +test_expect_success 'apply A->B (rename), C->A (rename), A->A -- should pass.' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + git commit -m "a rename" && + git mv other_fn same_fn + modify "s/^e/y/" same_fn && + git add same_fn && + git diff -M --cached >> patch1 && + modify "s/^g/x/" same_fn && + git diff >> patch1 && + git reset --hard HEAD^ && + git apply patch1 +' + +test_done diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh new file mode 100755 index 0000000000..2dd0c75f96 --- /dev/null +++ b/t/t4128-apply-root.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='apply same filename' + +. ./test-lib.sh + +test_expect_success 'setup' ' + + mkdir -p some/sub/dir && + echo Hello > some/sub/dir/file && + git add some/sub/dir/file && + git commit -m initial && + git tag initial + +' + +cat > patch << EOF +diff a/bla/blub/dir/file b/bla/blub/dir/file +--- a/bla/blub/dir/file ++++ b/bla/blub/dir/file +@@ -1,1 +1,1 @@ +-Hello ++Bello +EOF + +test_expect_success 'apply --directory -p (1)' ' + + git apply --directory=some/sub -p3 --index patch && + test Bello = $(git show :some/sub/dir/file) && + test Bello = $(cat some/sub/dir/file) + +' + +test_expect_success 'apply --directory -p (2) ' ' + + git reset --hard initial && + git apply --directory=some/sub/ -p3 --index patch && + test Bello = $(git show :some/sub/dir/file) && + test Bello = $(cat some/sub/dir/file) + +' + +test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 722ae96cd5..bc982607d0 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -110,7 +110,7 @@ test_expect_success 'am applies patch correctly' ' GIT_AUTHOR_NAME="Another Thor" GIT_AUTHOR_EMAIL="a.thor@example.com" -GIT_COMMITTER_NAME="Co M Miter" +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 diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 85d7e3edcd..cf10557dd2 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -9,6 +9,8 @@ test_description='git rerere . ./test-lib.sh cat > a1 << EOF +Some title +========== Whether 'tis nobler in the mind to suffer The slings and arrows of outrageous fortune, Or to take arms against a sea of troubles, @@ -24,6 +26,8 @@ git commit -q -a -m initial git checkout -b first cat >> a1 << EOF +Some title +========== To die, to sleep; To sleep: perchance to dream: ay, there's the rub; For in that sleep of death what dreams may come @@ -35,7 +39,7 @@ git commit -q -a -m first git checkout -b second master git show first:a1 | -sed -e 's/To die, t/To die! T/' > a1 +sed -e 's/To die, t/To die! T/' -e 's/Some title/Some Title/' > a1 echo "* END *" >>a1 git commit -q -a -m second @@ -55,14 +59,14 @@ test_expect_success 'conflicting merge' ' sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR) rr=.git/rr-cache/$sha1 -test_expect_success 'recorded preimage' "grep ======= $rr/preimage" +test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage" test_expect_success 'rerere.enabled works, too' ' rm -rf .git/rr-cache && git config rerere.enabled true && git reset --hard && ! git merge first && - grep ======= $rr/preimage + grep ^=======$ $rr/preimage ' test_expect_success 'no postimage or thisimage yet' \ @@ -71,7 +75,7 @@ test_expect_success 'no postimage or thisimage yet' \ test_expect_success 'preimage has right number of lines' ' cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) && - test $cnt = 9 + test $cnt = 13 ' @@ -80,13 +84,23 @@ git show first:a1 > a1 cat > expect << EOF --- a/a1 +++ b/a1 -@@ -6,17 +6,9 @@ +@@ -1,4 +1,4 @@ +-Some Title ++Some title + ========== + Whether 'tis nobler in the mind to suffer + The slings and arrows of outrageous fortune, +@@ -8,21 +8,11 @@ The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. -<<<<<<< +-Some Title +-========== -To die! To sleep; -======= + Some title + ========== To die, to sleep; ->>>>>>> To sleep: perchance to dream: ay, there's the rub; @@ -124,7 +138,7 @@ test_expect_success 'another conflicting merge' ' ' git show first:a1 | sed 's/To die: t/To die! T/' > expect -test_expect_success 'rerere kicked in' "! grep ======= a1" +test_expect_success 'rerere kicked in' "! grep ^=======$ a1" test_expect_success 'rerere prefers first change' 'test_cmp a1 expect' @@ -193,9 +207,19 @@ test_expect_success 'resolution was recorded properly' ' echo Bello > file3 && git add file3 && git commit -m version2 && - ! git merge fifth && - git diff-files -q && - test Cello = "$(cat file3)" + git tag version2 && + test_must_fail git merge fifth && + test Cello = "$(cat file3)" && + test 0 != $(git ls-files -u | wc -l) +' + +test_expect_success 'rerere.autoupdate' ' + git config rerere.autoupdate true + git reset --hard && + git checkout version2 && + test_must_fail git merge fifth && + test 0 = $(git ls-files -u | wc -l) + ' test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 9b0baac8db..3f1e25d921 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -45,6 +45,11 @@ test_expect_success \ (cd a && find .) | sort >a.lst' test_expect_success \ + 'add ignored file' \ + 'echo ignore me >a/ignored && + echo ignored export-ignore >.gitattributes' + +test_expect_success \ 'add files to repository' \ 'find a -type f | xargs git update-index --add && find a -type l | xargs git update-index --add && @@ -54,6 +59,10 @@ test_expect_success \ git commit-tree $treeid </dev/null)' test_expect_success \ + 'remove ignored file' \ + 'rm a/ignored' + +test_expect_success \ 'git archive' \ 'git archive HEAD >b.tar' diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 09fd917672..ecec591634 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -162,4 +162,18 @@ test_expect_success \ '[index v2] 5) pack-objects refuses to reuse corrupted data' \ '! git pack-objects test-5 <obj-list' +test_expect_success \ + '[index v2] 6) verify-pack detects CRC mismatch' \ + 'rm -f .git/objects/pack/* && + git-index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" && + git verify-pack ".git/objects/pack/pack-${pack1}.pack" && + chmod +w ".git/objects/pack/pack-${pack1}.idx" && + dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \ + bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + 0)) && + ( while read obj + do git cat-file -p $obj >/dev/null || exit 1 + done <obj-list ) && + err=$(! git verify-pack ".git/objects/pack/pack-${pack1}.pack" 2>&1) && + echo "$err" | grep "CRC mismatch"' + test_done diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh new file mode 100755 index 0000000000..31b20b21d2 --- /dev/null +++ b/t/t5303-pack-corruption-resilience.sh @@ -0,0 +1,194 @@ +#!/bin/sh +# +# Copyright (c) 2008 Nicolas Pitre +# + +test_description='resilience to pack corruptions with redundant objects' +. ./test-lib.sh + +# Note: the test objects are created with knowledge of their pack encoding +# to ensure good code path coverage, and to facilitate direct alteration +# later on. The assumed characteristics are: +# +# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2 +# for base, such that blob_3 delta depth is 2; +# +# 2) the bulk of object data is uncompressible so the text part remains +# visible; +# +# 3) object header is always 2 bytes. + +create_test_files() { + test-genrandom "foo" 2000 > file_1 && + test-genrandom "foo" 1800 > file_2 && + test-genrandom "foo" 1800 > file_3 && + echo " base " >> file_1 && + echo " delta1 " >> file_2 && + echo " delta delta2 " >> file_3 && + test-genrandom "bar" 150 >> file_2 && + test-genrandom "baz" 100 >> file_3 +} + +create_new_pack() { + rm -rf .git && + git init && + blob_1=`git hash-object -t blob -w file_1` && + blob_2=`git hash-object -t blob -w file_2` && + blob_3=`git hash-object -t blob -w file_3` && + pack=`printf "$blob_1\n$blob_2\n$blob_3\n" | + git pack-objects $@ .git/objects/pack/pack` && + pack=".git/objects/pack/pack-${pack}" && + git verify-pack -v ${pack}.pack +} + +do_corrupt_object() { + ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` && + ofs=$(($ofs + $2)) && + chmod +w ${pack}.pack && + dd if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs && + test_must_fail git verify-pack ${pack}.pack +} + +test_expect_success \ + 'initial setup validation' \ + 'create_test_files && + create_new_pack && + git prune-packed && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in header of first object' \ + 'do_corrupt_object $blob_1 0 && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and loose copy of first delta allows for partial recovery' \ + 'git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in data of first object' \ + 'create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and loose copy of second object allows for partial recovery' \ + 'git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in header of first delta' \ + 'create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 0 && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in data of first delta' \ + 'create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \ + 'create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 2 && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \ + 'create_new_pack --delta-base-offset && + git prune-packed && + do_corrupt_object $blob_2 2 && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and a redundant pack allows for full recovery too' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + git hash-object -t blob -w file_2 && + printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack && + git prune-packed && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_done diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 3def75eeb2..8becbc3f38 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -142,9 +142,12 @@ do set x $cmd; shift git symbolic-ref HEAD refs/heads/$1 ; shift rm -f .git/FETCH_HEAD - rm -f .git/refs/heads/* - rm -f .git/refs/remotes/rem/* - rm -f .git/refs/tags/* + git for-each-ref \ + refs/heads refs/remotes/rem refs/tags | + while read val type refname + do + git update-ref -d "$refname" "$val" + done git fetch "$@" >/dev/null cat .git/FETCH_HEAD } >"$actual_f" && diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index 7372439164..21dbb557b7 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -12,6 +12,13 @@ This test runs various sanity checks on http-push.' ROOT_PATH="$PWD" LIB_HTTPD_DAV=t +if git http-push > /dev/null 2>&1 || [ $? -eq 128 ] +then + say "skipping test, USE_CURL_MULTI is not defined" + test_done + exit +fi + . ../lib-httpd.sh if ! start_httpd >&3 2>&4 @@ -36,24 +43,25 @@ test_expect_success 'setup remote repository' ' git --bare update-server-info && chmod +x hooks/post-update && cd - && - mv test_repo.git $HTTPD_DOCUMENT_ROOT_PATH + mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" ' - + test_expect_success 'clone remote repository' ' cd "$ROOT_PATH" && git clone $HTTPD_URL/test_repo.git test_repo_clone ' -test_expect_success 'push to remote repository' ' +test_expect_failure 'push to remote repository' ' cd "$ROOT_PATH"/test_repo_clone && : >path2 && git add path2 && test_tick && git commit -m path2 && - git push + git push && + [ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ] ' -test_expect_success 'create and delete remote branch' ' +test_expect_failure 'create and delete remote branch' ' cd "$ROOT_PATH"/test_repo_clone && git checkout -b dev && : >path3 && diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh index 88e96fb91b..c4af9ca0a7 100755 --- a/t/t6008-rev-list-submodule.sh +++ b/t/t6008-rev-list-submodule.sh @@ -23,7 +23,7 @@ test_expect_success 'setup' ' : > super-file && git add super-file && - git submodule add . sub && + git submodule add "$(pwd)" sub && git symbolic-ref HEAD refs/heads/super && test_tick && git commit -m super-initial && diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh new file mode 100755 index 0000000000..e51eb41f4b --- /dev/null +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='git rev-list should notice bad commits' + +. ./test-lib.sh + +# Note: +# - compression level is set to zero to make "corruptions" easier to perform +# - reflog is disabled to avoid extra references which would twart the test + +test_expect_success 'setup' \ + ' + git init && + git config core.compression 0 && + git config core.logallrefupdates false && + echo "foo" > foo && + git add foo && + git commit -m "first commit" && + echo "bar" > bar && + git add bar && + git commit -m "second commit" && + echo "baz" > baz && + git add baz && + git commit -m "third commit" && + echo "foo again" >> foo && + git add foo && + git commit -m "fourth commit" && + git repack -a -f -d + ' + +test_expect_success 'verify number of revisions' \ + ' + revs=$(git rev-list --all | wc -l) && + test $revs -eq 4 && + first_commit=$(git rev-parse HEAD~3) + ' + +test_expect_success 'corrupt second commit object' \ + ' + perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack && + test_must_fail git fsck --full + ' + +test_expect_success 'rev-list should fail' \ + ' + test_must_fail git rev-list --all > /dev/null + ' + +test_expect_success 'git repack _MUST_ fail' \ + ' + test_must_fail git repack -a -f -d + ' + +test_expect_success 'first commit is still available' \ + ' + git log $first_commit + ' + +test_done + diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh new file mode 100755 index 0000000000..aac212e936 --- /dev/null +++ b/t/t6040-tracking-info.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='remote tracking stats' + +. ./test-lib.sh + +advance () { + echo "$1" >"$1" && + git add "$1" && + test_tick && + git commit -m "$1" +} + +test_expect_success setup ' + for i in a b c; + do + advance $i || break + done && + git clone . test && + ( + cd test && + git checkout -b b1 origin && + git reset --hard HEAD^ && + advance d && + git checkout -b b2 origin && + git reset --hard b1 && + git checkout -b b3 origin && + git reset --hard HEAD^ && + git checkout -b b4 origin && + advance e && + advance f + ) +' + +script='s/^..\(b.\)[ 0-9a-f]*\[\([^]]*\)\].*/\1 \2/p' +cat >expect <<\EOF +b1 ahead 1, behind 1 +b2 ahead 1, behind 1 +b3 behind 1 +b4 ahead 2 +EOF + +test_expect_success 'branch -v' ' + ( + cd test && + git branch -v + ) | + sed -n -e "$script" >actual && + test_cmp expect actual +' + +test_expect_success 'checkout' ' + ( + cd test && git checkout b1 + ) >actual && + grep -e "have 1 and 1 different" actual +' + +test_expect_success 'status' ' + ( + cd test && + git checkout b1 >/dev/null && + # reports nothing to commit + test_must_fail git status + ) >actual && + grep -e "have 1 and 1 different" actual +' + + +test_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 91ea85d99b..a3c8941c72 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -26,25 +26,78 @@ test_expect_success 'Create sample commit with known timestamp' ' git tag -a -m "Tagging at $datestamp" testtag ' -test_expect_success 'Check atom names are valid' ' - bad= - for token in \ - refname objecttype objectsize objectname tree parent \ - numparent object type author authorname authoremail \ - authordate committer committername committeremail \ - committerdate tag tagger taggername taggeremail \ - taggerdate creator creatordate subject body contents - do - git for-each-ref --format="$token=%($token)" refs/heads || { - bad=$token - break - } - done - test -z "$bad" +test_atom() { + case "$1" in + head) ref=refs/heads/master ;; + tag) ref=refs/tags/testtag ;; + esac + printf '%s\n' "$3" >expected + test_expect_${4:-success} "basic atom: $1 $2" " + git for-each-ref --format='%($2)' $ref >actual && + test_cmp expected actual + " +} + +test_atom head refname refs/heads/master +test_atom head objecttype commit +test_atom head objectsize 171 +test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581 +test_atom head tree 0e51c00fcb93dffc755546f27593d511e1bdb46f +test_atom head parent '' +test_atom head numparent 0 +test_atom head object '' +test_atom head type '' +test_atom head author 'A U Thor <author@example.com> 1151939924 +0200' +test_atom head authorname 'A U Thor' +test_atom head authoremail '<author@example.com>' +test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200' +test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200' +test_atom head committername 'C O Mitter' +test_atom head committeremail '<committer@example.com>' +test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200' +test_atom head tag '' +test_atom head tagger '' +test_atom head taggername '' +test_atom head taggeremail '' +test_atom head taggerdate '' +test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200' +test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200' +test_atom head subject 'Initial' +test_atom head body '' +test_atom head contents 'Initial +' + +test_atom tag refname refs/tags/testtag +test_atom tag objecttype tag +test_atom tag objectsize 154 +test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322 +test_atom tag tree '' +test_atom tag parent '' +test_atom tag numparent '' +test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581' +test_atom tag type 'commit' +test_atom tag author '' +test_atom tag authorname '' +test_atom tag authoremail '' +test_atom tag authordate '' +test_atom tag committer '' +test_atom tag committername '' +test_atom tag committeremail '' +test_atom tag committerdate '' +test_atom tag tag 'testtag' +test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200' +test_atom tag taggername 'C O Mitter' +test_atom tag taggeremail '<committer@example.com>' +test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200' +test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200' +test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200' +test_atom tag subject 'Tagging at 1151939927' +test_atom tag body '' +test_atom tag contents 'Tagging at 1151939927 ' test_expect_success 'Check invalid atoms names are errors' ' - ! git-for-each-ref --format="%(INVALID)" refs/heads + test_must_fail git-for-each-ref --format="%(INVALID)" refs/heads ' test_expect_success 'Check format specifiers are ignored in naming date atoms' ' @@ -64,7 +117,7 @@ test_expect_success 'Check valid format specifiers for date fields' ' ' test_expect_success 'Check invalid format specifiers are errors' ' - ! git-for-each-ref --format="%(authordate:INVALID)" refs/heads + test_must_fail git-for-each-ref --format="%(authordate:INVALID)" refs/heads ' cat >expected <<\EOF diff --git a/t/t7502-status.sh b/t/t7502-status.sh index 80a438d4d9..38a48b57c7 100755 --- a/t/t7502-status.sh +++ b/t/t7502-status.sh @@ -67,6 +67,104 @@ test_expect_success 'status (2)' ' ' +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# +# modified: dir1/modified +# +# Untracked files not listed (use -u option to show untracked files) +EOF +test_expect_success 'status -uno' ' + mkdir dir3 && + : > dir3/untracked1 && + : > dir3/untracked2 && + git status -uno >output && + test_cmp expect output +' + +test_expect_success 'status (status.showUntrackedFiles no)' ' + git config status.showuntrackedfiles no + git status >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# dir3/ +# expect +# output +# untracked +EOF +test_expect_success 'status -unormal' ' + git status -unormal >output && + test_cmp expect output +' + +test_expect_success 'status (status.showUntrackedFiles normal)' ' + git config status.showuntrackedfiles normal + git status >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# dir3/untracked1 +# dir3/untracked2 +# expect +# output +# untracked +EOF +test_expect_success 'status -uall' ' + git status -uall >output && + test_cmp expect output +' +test_expect_success 'status (status.showUntrackedFiles all)' ' + git config status.showuntrackedfiles all + git status >output && + rm -rf dir3 && + git config --unset status.showuntrackedfiles && + test_cmp expect output +' + cat > expect << \EOF # On branch master # Changes to be committed: diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index 6a5211f187..31c340fd38 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -4,6 +4,10 @@ test_description='git-repack works correctly' . ./test-lib.sh +fsha1= +csha1= +tsha1= + test_expect_success '-A option leaves unreachable objects unpacked' ' echo content > file1 && git add . && @@ -44,4 +48,34 @@ test_expect_success '-A option leaves unreachable objects unpacked' ' git show $tsha1 ' +compare_mtimes () +{ + perl -e 'my $reference = shift; + foreach my $file (@ARGV) { + exit(1) unless(-f $file && -M $file == -M $reference); + } + exit(0); + ' -- "$@" +} + +test_expect_success 'unpacked objects receive timestamp of pack file' ' + fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") && + fsha1path=".git/objects/$fsha1path" && + csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") && + csha1path=".git/objects/$csha1path" && + tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") && + tsha1path=".git/objects/$tsha1path" && + git branch transient_branch $csha1 && + git repack -a -d -l && + test ! -f "$fsha1path" && + test ! -f "$csha1path" && + test ! -f "$tsha1path" && + test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) && + packfile=$(ls .git/objects/pack/pack-*.pack) && + git branch -D transient_branch && + sleep 1 && + git repack -A -l && + compare_mtimes "$packfile" "$fsha1path" "$csha1path" "$tsha1path" +' + test_done diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 242cdf092a..3bc6164125 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -4,9 +4,9 @@ # test_description='git-svn basic tests' -GIT_SVN_LC_ALL=$LC_ALL +GIT_SVN_LC_ALL=${LC_ALL:-$LANG} -case "$LC_ALL" in +case "$GIT_SVN_LC_ALL" in *.UTF-8) have_utf8=t ;; @@ -17,7 +17,7 @@ esac . ./lib-git-svn.sh -echo 'define NO_SVN_TESTS to skip git-svn tests' +say 'define NO_SVN_TESTS to skip git-svn tests' test_expect_success \ 'initialize git-svn' ' @@ -183,7 +183,7 @@ then git-svn set-tree HEAD" unset LC_ALL else - echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)" + say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)" fi name='test fetch functionality (svn => git) with alternate GIT_SVN_ID' diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh index a400dc7966..f8f4718c36 100755 --- a/t/t9106-git-svn-dcommit-clobber-series.sh +++ b/t/t9106-git-svn-dcommit-clobber-series.sh @@ -20,8 +20,8 @@ test_expect_success '(supposedly) non-conflicting change from SVN' ' test x"`sed -n -e 61p < file`" = x61 && svn co "$svnrepo" tmp && cd tmp && - perl -i -p -e "s/^58$/5588/" file && - perl -i -p -e "s/^61$/6611/" file && + perl -i.bak -p -e "s/^58$/5588/" file && + perl -i.bak -p -e "s/^61$/6611/" file && poke file && test x"`sed -n -e 58p < file`" = x5588 && test x"`sed -n -e 61p < file`" = x6611 && @@ -40,8 +40,8 @@ test_expect_success 'some unrelated changes to git' " test_expect_success 'change file but in unrelated area' " test x\"\`sed -n -e 4p < file\`\" = x4 && test x\"\`sed -n -e 7p < file\`\" = x7 && - perl -i -p -e 's/^4\$/4444/' file && - perl -i -p -e 's/^7\$/7777/' file && + perl -i.bak -p -e 's/^4\$/4444/' file && + perl -i.bak -p -e 's/^7\$/7777/' file && test x\"\`sed -n -e 4p < file\`\" = x4444 && test x\"\`sed -n -e 7p < file\`\" = x7777 && git commit -m '4 => 4444, 7 => 7777' file && diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh index 047659fde1..04d2a65c08 100755 --- a/t/t9110-git-svn-use-svm-props.sh +++ b/t/t9110-git-svn-use-svm-props.sh @@ -49,4 +49,13 @@ test_expect_success 'verify metadata for /dir' " grep '^git-svn-id: $dir_url@1 $uuid$' " +test_expect_success 'find commit based on SVN revision number' " + git-svn find-rev r12 | + grep `git rev-parse HEAD` + " + +test_expect_success 'empty rebase' " + git-svn rebase + " + test_done diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh index 31c929b573..8da8ce58eb 100755 --- a/t/t9113-git-svn-dcommit-new-file.sh +++ b/t/t9113-git-svn-dcommit-new-file.sh @@ -7,12 +7,18 @@ # I don't like the idea of taking a port and possibly leaving a # daemon running on a users system if the test fails. # Not all git users will need to interact with SVN. -test -z "$SVNSERVE_PORT" && exit 0 test_description='git-svn dcommit new files over svn:// test' . ./lib-git-svn.sh +if test -z "$SVNSERVE_PORT" +then + say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)' + test_done + exit +fi + start_svnserve () { svnserve --listen-port $SVNSERVE_PORT \ --root "$rawsvnrepo" \ diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index f09bfb1117..f1bc5ceef0 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -78,6 +78,29 @@ test_expect_success 'iso-8859-1' ' git cat-file commit i18n | grep "Áéí óú") ' +test_expect_success 'import/export-marks' ' + + git checkout -b marks master && + git fast-export --export-marks=tmp-marks HEAD && + test -s tmp-marks && + test $(wc -l < tmp-marks) -eq 3 && + test $( + git fast-export --import-marks=tmp-marks\ + --export-marks=tmp-marks HEAD | + grep ^commit | + wc -l) \ + -eq 0 && + echo change > file && + git commit -m "last commit" file && + test $( + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks HEAD | + grep ^commit\ | + wc -l) \ + -eq 1 && + test $(wc -l < tmp-marks) -eq 4 + +' cat > signed-tag-import << EOF tag sign-your-name diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh new file mode 100755 index 0000000000..9706ee5773 --- /dev/null +++ b/t/t9700-perl-git.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Copyright (c) 2008 Lea Wiemann +# + +test_description='perl interface (Git.pm)' +. ./test-lib.sh + +perl -MTest::More -e 0 2>/dev/null || { + say_color skip "Perl Test::More unavailable, skipping test" + test_done +} + +# set up test repository + +test_expect_success \ + 'set up test repository' \ + 'echo "test file 1" > file1 && + echo "test file 2" > file2 && + mkdir directory1 && + echo "in directory1" >> directory1/file && + mkdir directory2 && + echo "in directory2" >> directory2/file && + git add . && + git commit -m "first commit" && + + echo "changed file 1" > file1 && + git commit -a -m "second commit" && + + git-config --add color.test.slot1 green && + git-config --add test.string value && + git-config --add test.dupstring value1 && + git-config --add test.dupstring value2 && + git-config --add test.booltrue true && + git-config --add test.boolfalse no && + git-config --add test.boolother other && + git-config --add test.int 2k + ' + +test_external_without_stderr \ + 'Perl API' \ + perl ../t9700/test.pl + +test_done diff --git a/t/t9700/test.pl b/t/t9700/test.pl new file mode 100755 index 0000000000..4d2312548a --- /dev/null +++ b/t/t9700/test.pl @@ -0,0 +1,100 @@ +#!/usr/bin/perl +use lib (split(/:/, $ENV{GITPERLLIB})); + +use 5.006002; +use warnings; +use strict; + +use Test::More qw(no_plan); + +use Cwd; +use File::Basename; +use File::Temp; + +BEGIN { use_ok('Git') } + +# set up +our $repo_dir = "trash directory"; +our $abs_repo_dir = Cwd->cwd; +die "this must be run by calling the t/t97* shell script(s)\n" + if basename(Cwd->cwd) ne $repo_dir; +ok(our $r = Git->repository(Directory => "."), "open repository"); + +# config +is($r->config("test.string"), "value", "config scalar: string"); +is_deeply([$r->config("test.dupstring")], ["value1", "value2"], + "config array: string"); +is($r->config("test.nonexistent"), undef, "config scalar: nonexistent"); +is_deeply([$r->config("test.nonexistent")], [], "config array: nonexistent"); +is($r->config_int("test.int"), 2048, "config_int: integer"); +is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent"); +ok($r->config_bool("test.booltrue"), "config_bool: true"); +ok(!$r->config_bool("test.boolfalse"), "config_bool: false"); +our $ansi_green = "\x1b[32m"; +is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color"); +# Cannot test $r->get_colorbool("color.foo")) because we do not +# control whether our STDOUT is a terminal. + +# Failure cases for config: +# Save and restore STDERR; we will probably extract this into a +# "dies_ok" method and possibly move the STDERR handling to Git.pm. +open our $tmpstderr, ">&", STDERR or die "cannot save STDERR"; close STDERR; +eval { $r->config("test.dupstring") }; +ok($@, "config: duplicate entry in scalar context fails"); +eval { $r->config_bool("test.boolother") }; +ok($@, "config_bool: non-boolean values fail"); +open STDERR, ">&", $tmpstderr or die "cannot restore STDERR"; + +# ident +like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/, + "ident scalar: author (type)"); +like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/, + "ident scalar: committer (type)"); +is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)"); +my ($name, $email, $time_tz) = $r->ident('author'); +is_deeply([$name, $email], ["A U Thor", "author\@example.com"], + "ident array: author"); +like($time_tz, qr/[0-9]+ \+0000/, "ident array: author"); +is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"], + "ident array: ident string"); +is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string"); + +# ident_person +is($r->ident_person("aUthor"), "A U Thor <author\@example.com>", + "ident_person: author (type)"); +is($r->ident_person("Name <email> 123 +0000"), "Name <email>", + "ident_person: ident string"); +is($r->ident_person("Name", "email", "123 +0000"), "Name <email>", + "ident_person: array"); + +# objects and hashes +ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)"); +our $tmpfile = File::Temp->new; +is($r->cat_blob($file1hash, $tmpfile), 15, "cat_blob: size"); +our $blobcontents; +{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +is($blobcontents, "changed file 1\n", "cat_blob: data"); +seek $tmpfile, 0, 0; +is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip"); +$tmpfile = File::Temp->new(); +print $tmpfile my $test_text = "test blob, to be inserted\n"; +like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/, + "hash_and_insert_object: returns hash"); +$tmpfile = File::Temp->new; +is($r->cat_blob($newhash, $tmpfile), length $test_text, "cat_blob: roundtrip size"); +{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +is($blobcontents, $test_text, "cat_blob: roundtrip data"); + +# paths +is($r->repo_path, "./.git", "repo_path"); +is($r->wc_path, $abs_repo_dir . "/", "wc_path"); +is($r->wc_subdir, "", "wc_subdir initial"); +$r->wc_chdir("directory1"); +is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir"); +TODO: { + local $TODO = "commands do not work after wc_chdir"; + # Failure output is active even in non-verbose mode and thus + # annoying. Hence we skip these tests as long as they fail. + todo_skip 'config after wc_chdir', 1; + is($r->config("color.string"), "value", "config after wc_chdir"); +} diff --git a/t/test-lib.sh b/t/test-lib.sh index c861141667..8e2849b5ce 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -35,6 +35,7 @@ unset GIT_WORK_TREE unset GIT_EXTERNAL_DIFF unset GIT_INDEX_FILE unset GIT_OBJECT_DIRECTORY +unset GIT_CEILING_DIRECTORIES unset SHA1_FILE_DIRECTORIES unset SHA1_FILE_DIRECTORY GIT_MERGE_VERBOSITY=5 @@ -80,6 +81,8 @@ do debug=t; shift ;; -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate) immediate=t; shift ;; + -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests) + export GIT_TEST_LONG=t; shift ;; -h|--h|--he|--hel|--help) help=t; shift ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) @@ -152,6 +155,7 @@ test_failure=0 test_count=0 test_fixed=0 test_broken=0 +test_success=0 die () { echo >&5 "FATAL: Unexpected exit with code $?" @@ -193,6 +197,7 @@ test_tick () { test_ok_ () { test_count=$(expr "$test_count" + 1) + test_success=$(expr "$test_success" + 1) say_color "" " ok $test_count: $@" } @@ -302,6 +307,64 @@ test_expect_code () { echo >&3 "" } +# test_external runs external test scripts that provide continuous +# test output about their progress, and succeeds/fails on +# zero/non-zero exit code. It outputs the test output on stdout even +# in non-verbose mode, and announces the external script with "* run +# <n>: ..." before running it. When providing relative paths, keep in +# mind that all scripts run in "trash directory". +# Usage: test_external description command arguments... +# Example: test_external 'Perl API' perl ../path/to/test.pl +test_external () { + test "$#" -eq 3 || + error >&5 "bug in the test script: not 3 parameters to test_external" + descr="$1" + shift + if ! test_skip "$descr" "$@" + then + # Announce the script to reduce confusion about the + # test output that follows. + say_color "" " run $(expr "$test_count" + 1): $descr ($*)" + # Run command; redirect its stderr to &4 as in + # test_run_, but keep its stdout on our stdout even in + # non-verbose mode. + "$@" 2>&4 + if [ "$?" = 0 ] + then + test_ok_ "$descr" + else + test_failure_ "$descr" "$@" + fi + fi +} + +# Like test_external, but in addition tests that the command generated +# no output on stderr. +test_external_without_stderr () { + # The temporary file has no (and must have no) security + # implications. + tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi + stderr="$tmp/git-external-stderr.$$.tmp" + test_external "$@" 4> "$stderr" + [ -f "$stderr" ] || error "Internal error: $stderr disappeared." + descr="no stderr: $1" + shift + say >&3 "expecting no stderr from previous command" + if [ ! -s "$stderr" ]; then + rm "$stderr" + test_ok_ "$descr" + else + if [ "$verbose" = t ]; then + output=`echo; echo Stderr is:; cat "$stderr"` + else + output= + fi + # rm first in case test_failure exits. + rm "$stderr" + test_failure_ "$descr" "$@" "$output" + 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: # @@ -345,7 +408,7 @@ test_create_repo () { repo="$1" mkdir "$repo" cd "$repo" || error "Cannot setup test environment" - "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >/dev/null 2>&1 || + "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 || error "cannot run git init -- have you built things yet?" mv .git/hooks .git/hooks-disabled cd "$owd" @@ -353,6 +416,16 @@ test_create_repo () { test_done () { trap - exit + test_results_dir="$TEST_DIRECTORY/test-results" + mkdir -p "$test_results_dir" + test_results_path="$test_results_dir/${0%-*}-$$" + + echo "total $test_count" >> $test_results_path + echo "success $test_success" >> $test_results_path + echo "fixed $test_fixed" >> $test_results_path + echo "broken $test_broken" >> $test_results_path + echo "failed $test_failure" >> $test_results_path + echo "" >> $test_results_path if test "$test_fixed" != 0 then @@ -387,7 +460,8 @@ test_done () { # Test the binaries we have just built. The tests are kept in # t/ subdirectory and are run in 'trash directory' subdirectory. -PATH=$(pwd)/..:$PATH +TEST_DIRECTORY=$(pwd) +PATH=$TEST_DIRECTORY/..:$PATH GIT_EXEC_PATH=$(pwd)/.. GIT_TEMPLATE_DIR=$(pwd)/../templates/blt unset GIT_CONFIG |