diff options
Diffstat (limited to 't')
312 files changed, 16211 insertions, 1824 deletions
diff --git a/t/Makefile b/t/Makefile index 47cbeb6e68..9046ec9816 100644 --- a/t/Makefile +++ b/t/Makefile @@ -71,7 +71,7 @@ gitweb-test: $(MAKE) $(TGITWEB) valgrind: - GIT_TEST_OPTS=--valgrind $(MAKE) + $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind" # Smoke testing targets -include ../GIT-VERSION-FILE @@ -79,6 +79,10 @@ appropriately before running "make". --debug:: This may help the person who is developing a new test. It causes the command defined with test_debug to run. + The "trash" directory (used to store all temporary data + during testing) is not deleted even if there are no + failed tests so that you can inspect its contents after + the test finished. --immediate:: This causes the test to immediately exit upon the first @@ -98,6 +102,13 @@ appropriately before running "make". not see any output, this option implies --verbose. For convenience, it also implies --tee. + Note that valgrind is run with the option --leak-check=no, + as the git process is short-lived and some errors are not + interesting. In order to run a single command under the same + conditions manually, you should set GIT_VALGRIND to point to + the 't/valgrind/' directory and use the commands under + 't/valgrind/bin/'. + --tee:: In addition to printing the test output to the terminal, write it to files named 't/test-results/$TEST_NAME.out'. @@ -190,7 +201,7 @@ we are testing. If you create files under t/ directory (i.e. here) that is not the top-level test script, never name the file to match the above pattern. The Makefile here considers all such files as the -top-level test script and tries to run all of them. A care is +top-level test script and tries to run all of them. Care is especially needed if you are creating a common test library file, similar to test-lib.sh, because such a library file may not be suitable for standalone execution. @@ -274,9 +285,8 @@ Do: - Check the test coverage for your tests. See the "Test coverage" below. - Don't blindly follow test coverage metrics, they're a good way to - spot if you've missed something. If a new function you added - doesn't have any coverage you're probably doing something wrong, + Don't blindly follow test coverage metrics; if a new function you added + doesn't have any coverage, then you're probably doing something wrong, but having 100% coverage doesn't necessarily mean that you tested everything. @@ -328,7 +338,7 @@ Keep in mind: Skipping tests -------------- -If you need to skip tests you should do so be using the three-arg form +If you need to skip tests you should do so by using the three-arg form of the test_* functions (see the "Test harness library" section below), e.g.: @@ -369,7 +379,7 @@ library for your script to use. - test_expect_success [<prereq>] <message> <script> - Usually takes two strings as parameter, and evaluates the + Usually takes two strings as parameters, and evaluates the <script>. If it yields success, test is considered successful. <message> should state what it is testing. @@ -380,7 +390,7 @@ library for your script to use. 'tree=$(git-write-tree)' If you supply three parameters the first will be taken to be a - prerequisite, see the test_set_prereq and test_have_prereq + prerequisite; see the test_set_prereq and test_have_prereq documentation below: test_expect_success TTY 'git --paginate rev-list uses a pager' \ @@ -420,7 +430,7 @@ library for your script to use. - test_tick Make commit and tag names consistent by setting the author and - committer times to defined stated. Subsequent calls will + committer times to defined state. Subsequent calls will advance the times by a fixed amount. - test_commit <message> [<filename> [<contents>]] @@ -436,7 +446,7 @@ library for your script to use. Merges the given rev using the given message. Like test_commit, creates a tag and calls test_tick before committing. - - test_set_prereq SOME_PREREQ + - test_set_prereq <prereq> Set a test prerequisite to be used later with test_have_prereq. The test-lib will set some prerequisites for you, see the @@ -446,7 +456,7 @@ library for your script to use. test_have_prereq directly, or the three argument invocation of test_expect_success and test_expect_failure. - - test_have_prereq SOME PREREQ + - test_have_prereq <prereq> Check if we have a prerequisite previously set with test_set_prereq. The most common use of this directly is to skip @@ -516,12 +526,13 @@ library for your script to use. Check whether a file has the length it is expected to. - - test_path_is_file <file> [<diagnosis>] - test_path_is_dir <dir> [<diagnosis>] + - test_path_is_file <path> [<diagnosis>] + test_path_is_dir <path> [<diagnosis>] test_path_is_missing <path> [<diagnosis>] - Check whether a file/directory exists or doesn't. <diagnosis> will - be displayed if the test fails. + Check if the named path is a file, if the named path is a + directory, or if the named path does not exist, respectively, + and fail otherwise, showing the <diagnosis> text. - test_when_finished <script> @@ -577,6 +588,11 @@ use these, and "test_set_prereq" for how to define your own. Test is not run by root user, and an attempt to write to an unwritable file is expected to fail correctly. + - LIBPCRE + + Git was compiled with USE_LIBPCRE=YesPlease. Wrap any tests + that use git-grep --perl-regexp or git-grep -P in these. + Tips for Writing Tests ---------------------- diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index d206b7c4cf..7913e206ed 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -1,5 +1,6 @@ #!/bin/sh +failed_tests= fixed=0 success=0 failed=0 @@ -18,7 +19,13 @@ do success) success=$(($success + $value)) ;; failed) - failed=$(($failed + $value)) ;; + failed=$(($failed + $value)) + if test $value != 0 + then + testnum=$(expr "$file" : 'test-results/\(t[0-9]*\)-') + failed_tests="$failed_tests $testnum" + fi + ;; broken) broken=$(($broken + $value)) ;; total) @@ -27,6 +34,11 @@ do done <"$file" done +if test -n "$failed_tests" +then + printf "\nfailed test(s):$failed_tests\n\n" +fi + printf "%-8s%d\n" fixed $fixed printf "%-8s%d\n" success $success printf "%-8s%d\n" failed $failed diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index d34208cc27..c56a77d237 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -1,5 +1,5 @@ # This file isn't used as a test script directly, instead it is -# sourced from t8001-annotate.sh and t8001-blame.sh. +# sourced from t8001-annotate.sh and t8002-blame.sh. check_count () { head= @@ -124,3 +124,14 @@ test_expect_success \ test_expect_success \ 'some edit' \ 'check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1' + +test_expect_success \ + 'an obfuscated email added' \ + 'echo "No robots allowed" > file.new && + cat file >> file.new && + mv file.new file && + GIT_AUTHOR_NAME="E" GIT_AUTHOR_EMAIL="E at test dot git" git commit -a -m "norobots"' + +test_expect_success \ + 'obfuscated email parsed' \ + 'check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1' diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh index b9bb95feaa..21d11d6c2d 100644 --- a/t/gitweb-lib.sh +++ b/t/gitweb-lib.sh @@ -16,6 +16,7 @@ our \$projectroot = "$safe_pwd"; our \$project_maxdepth = 8; our \$home_link_str = 'projects'; our \$site_name = '[localhost]'; +our \$site_html_head_string = ''; our \$site_header = ''; our \$site_footer = ''; our \$home_text = 'indextext.html'; @@ -82,7 +83,12 @@ gitweb_run () { } close O; ' gitweb.output && - if grep '^[[]' gitweb.log >/dev/null 2>&1; then false; else true; fi + if grep '^[[]' gitweb.log >/dev/null 2>&1; then + test_debug 'cat gitweb.log >&2' && + false + else + true + fi # gitweb.log is left for debugging # gitweb.output is used to parse HTTP output @@ -102,4 +108,9 @@ perl -MEncode -e '$e="";decode_utf8($e, Encode::FB_CROAK)' >/dev/null 2>&1 || { test_done } +perl -MCGI -MCGI::Util -MCGI::Carp -e 0 >/dev/null 2>&1 || { + skip_all='skipping gitweb tests, CGI module unusable' + test_done +} + gitweb_init diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh new file mode 100644 index 0000000000..75ffd9174f --- /dev/null +++ b/t/lib-diff-alternative.sh @@ -0,0 +1,165 @@ +#!/bin/sh + +test_diff_frobnitz() { + cat >file1 <<\EOF +#include <stdio.h> + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("Your answer is: "); + printf("%d\n", foo); + } +} + +int fact(int n) +{ + if(n > 1) + { + return fact(n-1) * n; + } + return 1; +} + +int main(int argc, char **argv) +{ + frobnitz(fact(10)); +} +EOF + + cat >file2 <<\EOF +#include <stdio.h> + +int fib(int n) +{ + if(n > 2) + { + return fib(n-1) + fib(n-2); + } + return 1; +} + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("%d\n", foo); + } +} + +int main(int argc, char **argv) +{ + frobnitz(fib(10)); +} +EOF + + cat >expect <<\EOF +diff --git a/file1 b/file2 +index 6faa5a3..e3af329 100644 +--- a/file1 ++++ b/file2 +@@ -1,26 +1,25 @@ + #include <stdio.h> + ++int fib(int n) ++{ ++ if(n > 2) ++ { ++ return fib(n-1) + fib(n-2); ++ } ++ return 1; ++} ++ + // Frobs foo heartily + int frobnitz(int foo) + { + int i; + for(i = 0; i < 10; i++) + { +- printf("Your answer is: "); + printf("%d\n", foo); + } + } + +-int fact(int n) +-{ +- if(n > 1) +- { +- return fact(n-1) * n; +- } +- return 1; +-} +- + int main(int argc, char **argv) + { +- frobnitz(fact(10)); ++ frobnitz(fib(10)); + } +EOF + + STRATEGY=$1 + + test_expect_success "$STRATEGY diff" ' + test_must_fail git diff --no-index "--$STRATEGY" file1 file2 > output && + test_cmp expect output + ' + + test_expect_success "$STRATEGY diff output is valid" ' + mv file2 expect && + git apply < output && + test_cmp expect file2 + ' +} + +test_diff_unique() { + cat >uniq1 <<\EOF +1 +2 +3 +4 +5 +6 +EOF + + cat >uniq2 <<\EOF +a +b +c +d +e +f +EOF + + cat >expect <<\EOF +diff --git a/uniq1 b/uniq2 +index b414108..0fdf397 100644 +--- a/uniq1 ++++ b/uniq2 +@@ -1,6 +1,6 @@ +-1 +-2 +-3 +-4 +-5 +-6 ++a ++b ++c ++d ++e ++f +EOF + + STRATEGY=$1 + + test_expect_success 'completely different files' ' + test_must_fail git diff --no-index "--$STRATEGY" uniq1 uniq2 > output && + test_cmp expect output + ' +} + diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh new file mode 100644 index 0000000000..a870f9a5d2 --- /dev/null +++ b/t/lib-git-p4.sh @@ -0,0 +1,74 @@ +# +# Library code for git-p4 tests +# + +. ./test-lib.sh + +if ! test_have_prereq PYTHON; then + skip_all='skipping git-p4 tests; python not available' + test_done +fi +( p4 -h && p4d -h ) >/dev/null 2>&1 || { + skip_all='skipping git-p4 tests; no p4 or p4d' + test_done +} + +GITP4="$GIT_BUILD_DIR/contrib/fast-import/git-p4" + +# Try to pick a unique port: guess a large number, then hope +# no more than one of each test is running. +# +# This does not handle the case where somebody else is running the +# same tests and has chosen the same ports. +testid=${this_test#t} +git_p4_test_start=9800 +P4DPORT=$((10669 + ($testid - $git_p4_test_start))) + +export P4PORT=localhost:$P4DPORT +export P4CLIENT=client + +db="$TRASH_DIRECTORY/db" +cli="$TRASH_DIRECTORY/cli" +git="$TRASH_DIRECTORY/git" +pidfile="$TRASH_DIRECTORY/p4d.pid" + +start_p4d() { + mkdir -p "$db" "$cli" "$git" && + ( + p4d -q -r "$db" -p $P4DPORT & + echo $! >"$pidfile" + ) && + for i in 1 2 3 4 5 ; do + p4 info >/dev/null 2>&1 && break || true && + echo waiting for p4d to start && + sleep 1 + done && + # complain if it never started + p4 info >/dev/null && + ( + cd "$cli" && + p4 client -i <<-EOF + Client: client + Description: client + Root: $cli + View: //depot/... //client/... + EOF + ) +} + +kill_p4d() { + pid=$(cat "$pidfile") + # it had better exist for the first kill + kill $pid && + for i in 1 2 3 4 5 ; do + kill $pid >/dev/null 2>&1 || break + sleep 1 + done && + # complain if it would not die + test_must_fail kill $pid >/dev/null 2>&1 && + rm -rf "$db" "$cli" "$pidfile" +} + +cleanup_git() { + rm -rf "$git" +} diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh new file mode 100755 index 0000000000..05824fa8e4 --- /dev/null +++ b/t/lib-gpg.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +gpg_version=`gpg --version 2>&1` +if test $? = 127; then + say "You do not seem to have gpg installed" +else + # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 + # the gpg version 1.0.6 didn't parse trust packets correctly, so for + # that version, creation of signed tags using the generated key fails. + case "$gpg_version" in + 'gpg (GnuPG) 1.0.6'*) + say "Your version of gpg (1.0.6) is too buggy for testing" + ;; + *) + # key generation info: gpg --homedir t/lib-gpg --gen-key + # Type DSA and Elgamal, size 2048 bits, no expiration date. + # Name and email: C O Mitter <committer@example.com> + # No password given, to enable non-interactive operation. + cp -R "$TEST_DIRECTORY"/lib-gpg ./gpghome + chmod 0700 gpghome + GNUPGHOME="$(pwd)/gpghome" + export GNUPGHOME + test_set_prereq GPG + ;; + esac +fi + +sanitize_pgp() { + perl -ne ' + /^-----END PGP/ and $in_pgp = 0; + print unless $in_pgp; + /^-----BEGIN PGP/ and $in_pgp = 1; + ' +} diff --git a/t/t7004/pubring.gpg b/t/lib-gpg/pubring.gpg Binary files differindex 83855fa4e1..83855fa4e1 100644 --- a/t/t7004/pubring.gpg +++ b/t/lib-gpg/pubring.gpg diff --git a/t/t7004/random_seed b/t/lib-gpg/random_seed Binary files differindex 8fed1339ed..8fed1339ed 100644 --- a/t/t7004/random_seed +++ b/t/lib-gpg/random_seed diff --git a/t/t7004/secring.gpg b/t/lib-gpg/secring.gpg Binary files differindex d831cd9eb3..d831cd9eb3 100644 --- a/t/t7004/secring.gpg +++ b/t/lib-gpg/secring.gpg diff --git a/t/t7004/trustdb.gpg b/t/lib-gpg/trustdb.gpg Binary files differindex abace962b8..abace962b8 100644 --- a/t/t7004/trustdb.gpg +++ b/t/lib-gpg/trustdb.gpg diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index 3f24384371..f7dc0781d5 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -81,8 +81,7 @@ prepare_httpd() { if test -n "$LIB_HTTPD_SSL" then - HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT - AUTH_HTTPD_URL=https://user%40host:user%40host@127.0.0.1:$LIB_HTTPD_PORT + HTTPD_PROTO=https RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \ -config "$TEST_PATH/ssl.cnf" \ @@ -93,9 +92,12 @@ prepare_httpd() { export GIT_SSL_NO_VERIFY HTTPD_PARA="$HTTPD_PARA -DSSL" else - HTTPD_URL=http://127.0.0.1:$LIB_HTTPD_PORT - AUTH_HTTPD_URL=http://user%40host:user%40host@127.0.0.1:$LIB_HTTPD_PORT + HTTPD_PROTO=http fi + HTTPD_DEST=127.0.0.1:$LIB_HTTPD_PORT + HTTPD_URL=$HTTPD_PROTO://$HTTPD_DEST + HTTPD_URL_USER=$HTTPD_PROTO://user%40host@$HTTPD_DEST + HTTPD_URL_USER_PASS=$HTTPD_PROTO://user%40host:user%40host@$HTTPD_DEST if test -n "$LIB_HTTPD_DAV" -o -n "$LIB_HTTPD_SVN" then @@ -158,7 +160,6 @@ test_http_push_nonff() { ' test_expect_success 'non-fast-forward push shows help message' ' - grep "To prevent you from losing history, non-fast-forward updates were rejected" \ - output + test_i18ngrep "To prevent you from losing history, non-fast-forward updates were rejected" output ' } diff --git a/t/lib-read-tree.sh b/t/lib-read-tree.sh new file mode 100644 index 0000000000..abc2c6f57f --- /dev/null +++ b/t/lib-read-tree.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# +# Helper functions to check if read-tree would succeed/fail as expected with +# and without the dry-run option. They also test that the dry-run does not +# write the index and that together with -u it doesn't touch the work tree. +# +read_tree_must_succeed () { + git ls-files -s >pre-dry-run && + git read-tree -n "$@" && + git ls-files -s >post-dry-run && + test_cmp pre-dry-run post-dry-run && + git read-tree "$@" +} + +read_tree_must_fail () { + git ls-files -s >pre-dry-run && + test_must_fail git read-tree -n "$@" && + git ls-files -s >post-dry-run && + test_cmp pre-dry-run post-dry-run && + test_must_fail git read-tree "$@" +} + +read_tree_u_must_succeed () { + git ls-files -s >pre-dry-run && + git diff-files -p >pre-dry-run-wt && + git read-tree -n "$@" && + git ls-files -s >post-dry-run && + git diff-files -p >post-dry-run-wt && + test_cmp pre-dry-run post-dry-run && + test_cmp pre-dry-run-wt post-dry-run-wt && + git read-tree "$@" +} + +read_tree_u_must_fail () { + git ls-files -s >pre-dry-run && + git diff-files -p >pre-dry-run-wt && + test_must_fail git read-tree -n "$@" && + git ls-files -s >post-dry-run && + git diff-files -p >post-dry-run-wt && + test_cmp pre-dry-run post-dry-run && + test_cmp pre-dry-run-wt post-dry-run-wt && + test_must_fail git read-tree "$@" +} diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh index c383b57ed9..58d911d21b 100644 --- a/t/lib-terminal.sh +++ b/t/lib-terminal.sh @@ -1,8 +1,24 @@ #!/bin/sh -test_expect_success 'set up terminal for tests' ' - if - test_have_prereq PERL && +test_expect_success PERL 'set up terminal for tests' ' + # Reading from the pty master seems to get stuck _sometimes_ + # on Mac OS X 10.5.0, using Perl 5.10.0 or 5.8.9. + # + # Reproduction recipe: run + # + # i=0 + # while ./test-terminal.perl echo hi $i + # do + # : $((i = $i + 1)) + # done + # + # After 2000 iterations or so it hangs. + # https://rt.cpan.org/Ticket/Display.html?id=65692 + # + if test "$(uname -s)" = Darwin + then + : + elif "$PERL_PATH" "$TEST_DIRECTORY"/test-terminal.perl \ sh -c "test -t 1 && test -t 2" then diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 8deec75c3a..f4e8f43bae 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -435,7 +435,7 @@ test_expect_success 'update-index D/F conflict' ' test $numpath0 = 1 ' -test_expect_success SYMLINKS 'absolute path works as expected' ' +test_expect_success SYMLINKS 'real path works as expected' ' mkdir first && ln -s ../.git first/.git && mkdir second && @@ -443,14 +443,14 @@ test_expect_success SYMLINKS 'absolute path works as expected' ' mkdir third && dir="$(cd .git; pwd -P)" && dir2=third/../second/other/.git && - test "$dir" = "$(test-path-utils make_absolute_path $dir2)" && + test "$dir" = "$(test-path-utils real_path $dir2)" && file="$dir"/index && - test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" && + test "$file" = "$(test-path-utils real_path $dir2/index)" && basename=blub && - test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" && + test "$dir/$basename" = "$(cd .git && test-path-utils real_path "$basename")" && ln -s ../first/file .git/syml && sym="$(cd first; pwd -P)"/file && - test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")" + test "$sym" = "$(test-path-utils real_path "$dir2/syml")" ' test_expect_success 'very long name in the index handled sanely' ' diff --git a/t/t0001-init.sh b/t/t0001-init.sh index f684993211..ad66410564 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -47,7 +47,7 @@ test_expect_success 'plain nested in bare' ' test_expect_success 'plain through aliased command, outside any git repo' ' ( - sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG_NOGLOBAL && + sane_unset GIT_DIR GIT_WORK_TREE && HOME=$(pwd)/alias-config && export HOME && mkdir alias-config && @@ -190,11 +190,11 @@ test_expect_success 'reinit' ' git init >out1 2>err1 && git init >out2 2>err2 ) && - grep "Initialized empty" again/out1 && - grep "Reinitialized existing" again/out2 && + test_i18ngrep "Initialized empty" again/out1 && + test_i18ngrep "Reinitialized existing" again/out2 && >again/empty && - test_cmp again/empty again/err1 && - test_cmp again/empty again/err2 + test_i18ncmp again/empty again/err1 && + test_i18ncmp again/empty again/err2 ' test_expect_success 'init with --template' ' @@ -231,7 +231,6 @@ test_expect_success 'init with init.templatedir set' ' git config -f "$test_config" init.templatedir "${HOME}/templatedir-source" && mkdir templatedir-set && cd templatedir-set && - sane_unset GIT_CONFIG_NOGLOBAL && sane_unset GIT_TEMPLATE_DIR && NO_SET_GIT_TEMPLATE_DIR=t && export NO_SET_GIT_TEMPLATE_DIR && @@ -243,7 +242,6 @@ test_expect_success 'init with init.templatedir set' ' test_expect_success 'init --bare/--shared overrides system/global config' ' ( test_config="$HOME"/.gitconfig && - sane_unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" core.bare false && git config -f "$test_config" core.sharedRepository 0640 && mkdir init-bare-shared-override && @@ -258,7 +256,6 @@ test_expect_success 'init --bare/--shared overrides system/global config' ' test_expect_success 'init honors global core.sharedRepository' ' ( test_config="$HOME"/.gitconfig && - sane_unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" core.sharedRepository 0666 && mkdir shared-honor-global && cd shared-honor-global && @@ -374,4 +371,50 @@ test_expect_success 'init prefers command line to GIT_DIR' ' ! test -d otherdir/refs ' +test_expect_success 'init with separate gitdir' ' + rm -rf newdir && + git init --separate-git-dir realgitdir newdir && + echo "gitdir: `pwd`/realgitdir" >expected && + test_cmp expected newdir/.git && + test -d realgitdir/refs +' + +test_expect_success 're-init to update git link' ' + ( + cd newdir && + git init --separate-git-dir ../surrealgitdir + ) && + echo "gitdir: `pwd`/surrealgitdir" >expected && + test_cmp expected newdir/.git && + test -d surrealgitdir/refs && + ! test -d realgitdir/refs +' + +test_expect_success 're-init to move gitdir' ' + rm -rf newdir realgitdir surrealgitdir && + git init newdir && + ( + cd newdir && + git init --separate-git-dir ../realgitdir + ) && + echo "gitdir: `pwd`/realgitdir" >expected && + test_cmp expected newdir/.git && + test -d realgitdir/refs +' + +test_expect_success SYMLINKS 're-init to move gitdir symlink' ' + rm -rf newdir realgitdir && + git init newdir && + ( + cd newdir && + mv .git here && + ln -s here .git && + git init --separate-git-dir ../realgitdir + ) && + echo "gitdir: `pwd`/realgitdir" >expected && + test_cmp expected newdir/.git && + test -d realgitdir/refs && + ! test -d newdir/here +' + test_done diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index ebbc7554a7..dbb2623d93 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -5,20 +5,17 @@ test_description=gitattributes . ./test-lib.sh attr_check () { + path="$1" expect="$2" - path="$1" - expect="$2" - - git check-attr test -- "$path" >actual && + git $3 check-attr test -- "$path" >actual 2>err && echo "$path: test: $2" >expect && - test_cmp expect actual - + test_cmp expect actual && + test_line_count = 0 err } test_expect_success 'setup' ' - - mkdir -p a/b/d a/c && + mkdir -p a/b/d a/c b && ( echo "[attr]notest !test" echo "f test=f" @@ -26,6 +23,7 @@ test_expect_success 'setup' ' echo "onoff test -test" echo "offon -test test" echo "no notest" + echo "A/e/F test=A/e/F" ) >.gitattributes && ( echo "g test=a/g" && @@ -35,15 +33,43 @@ test_expect_success 'setup' ' echo "h test=a/b/h" && echo "d/* test=a/b/d/*" echo "d/yes notest" - ) >a/b/.gitattributes + ) >a/b/.gitattributes && ( echo "global test=global" - ) >"$HOME"/global-gitattributes + ) >"$HOME"/global-gitattributes && + cat <<-EOF >expect-all + f: test: f + a/f: test: f + a/c/f: test: f + a/g: test: a/g + a/b/g: test: a/b/g + b/g: test: unspecified + a/b/h: test: a/b/h + a/b/d/g: test: a/b/d/* + onoff: test: unset + offon: test: set + no: notest: set + no: test: unspecified + a/b/d/no: notest: set + a/b/d/no: test: a/b/d/* + a/b/d/yes: notest: set + a/b/d/yes: test: unspecified + EOF +' +test_expect_success 'command line checks' ' + test_must_fail git check-attr && + test_must_fail git check-attr -- && + test_must_fail git check-attr test && + test_must_fail git check-attr test -- && + test_must_fail git check-attr -- f && + echo "f" | test_must_fail git check-attr --stdin && + echo "f" | test_must_fail git check-attr --stdin -- f && + echo "f" | test_must_fail git check-attr --stdin test -- f && + test_must_fail git check-attr "" -- f ' test_expect_success 'attribute test' ' - attr_check f f && attr_check a/f f && attr_check a/c/f f && @@ -57,7 +83,80 @@ test_expect_success 'attribute test' ' attr_check no unspecified && attr_check a/b/d/no "a/b/d/*" && attr_check a/b/d/yes unspecified +' + +test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' ' + + test_must_fail attr_check F f "-c core.ignorecase=0" && + test_must_fail attr_check a/F f "-c core.ignorecase=0" && + test_must_fail attr_check a/c/F f "-c core.ignorecase=0" && + test_must_fail attr_check a/G a/g "-c core.ignorecase=0" && + test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" && + test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" && + test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" && + test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" && + test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" && + test_must_fail attr_check oFfOn set "-c core.ignorecase=0" && + attr_check NO unspecified "-c core.ignorecase=0" && + test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" && + test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0" + +' + +test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' ' + + attr_check F f "-c core.ignorecase=1" && + attr_check a/F f "-c core.ignorecase=1" && + attr_check a/c/F f "-c core.ignorecase=1" && + attr_check a/G a/g "-c core.ignorecase=1" && + attr_check a/B/g a/b/g "-c core.ignorecase=1" && + attr_check a/b/G a/b/g "-c core.ignorecase=1" && + attr_check a/b/H a/b/h "-c core.ignorecase=1" && + attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" && + attr_check oNoFf unset "-c core.ignorecase=1" && + attr_check oFfOn set "-c core.ignorecase=1" && + attr_check NO unspecified "-c core.ignorecase=1" && + attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" && + attr_check a/b/d/YES unspecified "-c core.ignorecase=1" && + attr_check a/E/f "A/e/F" "-c core.ignorecase=1" + +' + +test_expect_success 'check whether FS is case-insensitive' ' + mkdir junk && + echo good >junk/CamelCase && + echo bad >junk/camelcase && + if test "$(cat junk/CamelCase)" != good + then + test_set_prereq CASE_INSENSITIVE_FS + fi +' + +test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' ' + test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" && + test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check A/b/h a/b/h "-c core.ignorecase=1" && + attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" && + attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1" +' + +test_expect_success 'unnormalized paths' ' + attr_check ./f f && + attr_check ./a/g a/g && + attr_check a/./g a/g && + attr_check a/c/../b/g a/b/g +' +test_expect_success 'relative paths' ' + (cd a && attr_check ../f f) && + (cd a && attr_check f f) && + (cd a && attr_check i a/i) && + (cd a && attr_check g a/g) && + (cd a && attr_check b/g a/b/g) && + (cd b && attr_check ../a/f f) && + (cd b && attr_check ../a/g a/g) && + (cd b && attr_check ../a/b/g a/b/g) ' test_expect_success 'core.attributesfile' ' @@ -66,48 +165,43 @@ test_expect_success 'core.attributesfile' ' attr_check global global && git config core.attributesfile "~/global-gitattributes" && attr_check global global && - echo "global test=precedence" >> .gitattributes && + echo "global test=precedence" >>.gitattributes && attr_check global precedence ' test_expect_success 'attribute test: read paths from stdin' ' - - cat <<EOF > expect && -f: test: f -a/f: test: f -a/c/f: test: f -a/g: test: a/g -a/b/g: test: a/b/g -b/g: test: unspecified -a/b/h: test: a/b/h -a/b/d/g: test: a/b/d/* -onoff: test: unset -offon: test: set -no: test: unspecified -a/b/d/no: test: a/b/d/* -a/b/d/yes: test: unspecified -EOF - - sed -e "s/:.*//" < expect | git check-attr --stdin test > actual && + grep -v notest <expect-all >expect && + sed -e "s/:.*//" <expect | git check-attr --stdin test >actual && test_cmp expect actual ' -test_expect_success 'root subdir attribute test' ' +test_expect_success 'attribute test: --all option' ' + grep -v unspecified <expect-all | sort >specified-all && + sed -e "s/:.*//" <expect-all | uniq >stdin-all && + git check-attr --stdin --all <stdin-all | sort >actual && + test_cmp specified-all actual +' + +test_expect_success 'attribute test: --cached option' ' + : >empty && + git check-attr --cached --stdin --all <stdin-all | sort >actual && + test_cmp empty actual && + git add .gitattributes a/.gitattributes a/b/.gitattributes && + git check-attr --cached --stdin --all <stdin-all | sort >actual && + test_cmp specified-all actual +' +test_expect_success 'root subdir attribute test' ' attr_check a/i a/i && attr_check subdir/a/i unspecified - ' test_expect_success 'setup bare' ' - git clone --bare . bare.git && cd bare.git - ' test_expect_success 'bare repository: check that .gitattribute is ignored' ' - ( echo "f test=f" echo "a/i test=a/i" @@ -117,11 +211,16 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' ' attr_check a/c/f unspecified && attr_check a/i unspecified && attr_check subdir/a/i unspecified +' +test_expect_success 'bare repository: check that --cached honors index' ' + GIT_INDEX_FILE=../.git/index \ + git check-attr --cached --stdin --all <../stdin-all | + sort >actual && + test_cmp ../specified-all actual ' test_expect_success 'bare repository: test info/attributes' ' - ( echo "f test=f" echo "a/i test=a/i" @@ -131,7 +230,6 @@ test_expect_success 'bare repository: test info/attributes' ' attr_check a/c/f f && attr_check a/i a/i && attr_check subdir/a/i unspecified - ' test_done diff --git a/t/t0006-date.sh b/t/t0006-date.sh index 1d4d0a5c7d..1d29810a7a 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -25,6 +25,7 @@ check_show 37500000 '1 year, 2 months ago' check_show 55188000 '1 year, 9 months ago' check_show 630000000 '20 years ago' check_show 31449600 '12 months ago' +check_show 62985600 '2 years ago' check_parse() { echo "$1 -> $2" >expect @@ -39,6 +40,12 @@ check_parse 2008-02 bad check_parse 2008-02-14 bad check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000' check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015' +check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000' +check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000' +check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500' +check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000' +check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500' check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5 check_approxidate() { diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 9078b84ae6..f19e6510d0 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -66,31 +66,48 @@ test_expect_success expanded_in_repo ' echo "\$Id:NoSpaceAtEitherEnd\$" echo "\$Id: NoTerminatingSymbol" echo "\$Id: Foreign Commit With Spaces \$" - echo "\$Id: NoTerminatingSymbolAtEOF" - } > expanded-keywords && + } >expanded-keywords.0 && + + { + cat expanded-keywords.0 && + printf "\$Id: NoTerminatingSymbolAtEOF" + } >expanded-keywords && + cat expanded-keywords >expanded-keywords-crlf && + git add expanded-keywords expanded-keywords-crlf && + git commit -m "File with keywords expanded" && + id=$(git rev-parse --verify :expanded-keywords) && { echo "File with expanded keywords" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" - echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: $id \$" + echo "\$Id: $id \$" + echo "\$Id: $id \$" + echo "\$Id: $id \$" + echo "\$Id: $id \$" + echo "\$Id: $id \$" echo "\$Id: NoTerminatingSymbol" echo "\$Id: Foreign Commit With Spaces \$" - echo "\$Id: NoTerminatingSymbolAtEOF" - } > expected-output && - - git add expanded-keywords && - git commit -m "File with keywords expanded" && + } >expected-output.0 && + { + cat expected-output.0 && + printf "\$Id: NoTerminatingSymbolAtEOF" + } >expected-output && + { + append_cr <expected-output.0 && + printf "\$Id: NoTerminatingSymbolAtEOF" + } >expected-output-crlf && + { + echo "expanded-keywords ident" + echo "expanded-keywords-crlf ident text eol=crlf" + } >>.gitattributes && - echo "expanded-keywords ident" >> .gitattributes && + rm -f expanded-keywords expanded-keywords-crlf && - rm -f expanded-keywords && git checkout -- expanded-keywords && - cat expanded-keywords && - cmp expanded-keywords expected-output + test_cmp expanded-keywords expected-output && + + git checkout -- expanded-keywords-crlf && + test_cmp expanded-keywords-crlf expected-output-crlf ' # The use of %f in a filter definition is expanded to the path to diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 20924506af..a1e4616feb 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -19,7 +19,7 @@ usage: test-parse-options <options> --set23 set integer to 23 -t <time> get timestamp of <time> -L, --length <str> get length of <str> - -F, --file <FILE> set file to <FILE> + -F, --file <file> set file to <file> String options -s, --string <string> @@ -28,6 +28,7 @@ String options --st <st> get another string (pervert ordering) -o <str> get another string --default-string set string to default + --list <str> add str to list Magic arguments --quux means --quux @@ -86,7 +87,7 @@ EOF test_expect_success 'long options' ' test-parse-options --boolean --integer 1729 --boolean --string2=321 \ --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\ - > output 2> output.err && + --obsolete > output 2> output.err && test ! -s output.err && test_cmp expect output ' @@ -337,4 +338,20 @@ test_expect_success 'negation of OPT_NONEG flags is not ambiguous' ' test_cmp expect output ' +cat >>expect <<'EOF' +list: foo +list: bar +list: baz +EOF +test_expect_success '--list keeps list of strings' ' + test-parse-options --list foo --list=bar --list=baz >output && + test_cmp expect output +' + +test_expect_success '--no-list resets list' ' + test-parse-options --list=other --list=irrelevant --list=options \ + --no-list --list=foo --list=bar --list=baz >output && + test_cmp expect output +' + test_done diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index 10b26e4d8e..8d4938f019 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -7,8 +7,31 @@ test_description='Test run command' . ./test-lib.sh +cat >hello-script <<-EOF + #!$SHELL_PATH + cat hello-script +EOF +>empty + test_expect_success 'start_command reports ENOENT' ' test-run-command start-command-ENOENT ./does-not-exist ' +test_expect_success 'run_command can run a command' ' + cat hello-script >hello.sh && + chmod +x hello.sh && + test-run-command run-command ./hello.sh >actual 2>err && + + test_cmp hello-script actual && + test_cmp empty err +' + +test_expect_success POSIXPERM 'run_command reports EACCES' ' + cat hello-script >hello.sh && + chmod -x hello.sh && + test_must_fail test-run-command run-command ./hello.sh 2>err && + + grep "fatal: cannot exec.*hello.sh" err +' + test_done diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh index 680d7d6861..9bee8bfd2e 100755 --- a/t/t0070-fundamental.sh +++ b/t/t0070-fundamental.sh @@ -12,4 +12,17 @@ test_expect_success 'character classes (isspace, isalpha etc.)' ' test-ctype ' +test_expect_success 'mktemp to nonexistent directory prints filename' ' + test_must_fail test-mktemp doesnotexist/testXXXXXX 2>err && + grep "doesnotexist/test" err +' + +test_expect_success POSIXPERM 'mktemp to unwritable directory prints filename' ' + mkdir cannotwrite && + chmod -w cannotwrite && + test_when_finished "chmod +w cannotwrite" && + test_must_fail test-mktemp cannotwrite/testXXXXXX 2>err && + grep "cannotwrite/test" err +' + test_done diff --git a/t/t0080-vcs-svn.sh b/t/t0080-vcs-svn.sh index d3225ada68..99a314b080 100755 --- a/t/t0080-vcs-svn.sh +++ b/t/t0080-vcs-svn.sh @@ -76,60 +76,6 @@ test_expect_success 'obj pool: high-water mark' ' test_cmp expected actual ' -test_expect_success 'line buffer' ' - echo HELLO >expected1 && - printf "%s\n" "" HELLO >expected2 && - echo >expected3 && - printf "%s\n" "" Q | q_to_nul >expected4 && - printf "%s\n" foo "" >expected5 && - printf "%s\n" "" foo >expected6 && - - test-line-buffer <<-\EOF >actual1 && - 5 - HELLO - EOF - - test-line-buffer <<-\EOF >actual2 && - 0 - - 5 - HELLO - EOF - - q_to_nul <<-\EOF | - 1 - Q - EOF - test-line-buffer >actual3 && - - q_to_nul <<-\EOF | - 0 - - 1 - Q - EOF - test-line-buffer >actual4 && - - test-line-buffer <<-\EOF >actual5 && - 5 - foo - EOF - - test-line-buffer <<-\EOF >actual6 && - 0 - - 5 - foo - EOF - - test_cmp expected1 actual1 && - test_cmp expected2 actual2 && - test_cmp expected3 actual3 && - test_cmp expected4 actual4 && - test_cmp expected5 actual5 && - test_cmp expected6 actual6 -' - test_expect_success 'string pool' ' echo a does not equal b >expected.differ && echo a equals a >expected.match && diff --git a/t/t0081-line-buffer.sh b/t/t0081-line-buffer.sh new file mode 100755 index 0000000000..bd83ed371a --- /dev/null +++ b/t/t0081-line-buffer.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description="Test the svn importer's input handling routines. + +These tests provide some simple checks that the line_buffer API +behaves as advertised. + +While at it, check that input of newlines and null bytes are handled +correctly. +" +. ./test-lib.sh + +test_expect_success 'hello world' ' + echo ">HELLO" >expect && + test-line-buffer <<-\EOF >actual && + binary 6 + HELLO + EOF + test_cmp expect actual +' + +test_expect_success '0-length read, send along greeting' ' + echo ">HELLO" >expect && + test-line-buffer <<-\EOF >actual && + binary 0 + copy 6 + HELLO + EOF + test_cmp expect actual +' + +test_expect_success 'read from file descriptor' ' + rm -f input && + echo hello >expect && + echo hello >input && + echo copy 6 | + test-line-buffer "&4" 4<input >actual && + test_cmp expect actual +' + +test_expect_success 'skip, copy null byte' ' + echo Q | q_to_nul >expect && + q_to_nul <<-\EOF | test-line-buffer >actual && + skip 2 + Q + copy 2 + Q + EOF + test_cmp expect actual +' + +test_expect_success 'read null byte' ' + echo ">QhelloQ" | q_to_nul >expect && + q_to_nul <<-\EOF | test-line-buffer >actual && + binary 8 + QhelloQ + EOF + test_cmp expect actual +' + +test_expect_success 'long reads are truncated' ' + echo ">foo" >expect && + test-line-buffer <<-\EOF >actual && + binary 5 + foo + EOF + test_cmp expect actual +' + +test_expect_success 'long copies are truncated' ' + printf "%s\n" ">" foo >expect && + test-line-buffer <<-\EOF >actual && + binary 1 + + copy 5 + foo + EOF + test_cmp expect actual +' + +test_expect_success 'long binary reads are truncated' ' + echo ">foo" >expect && + test-line-buffer <<-\EOF >actual && + binary 5 + foo + EOF + test_cmp expect actual +' + +test_done diff --git a/t/t0201-gettext-fallbacks.sh b/t/t0201-gettext-fallbacks.sh new file mode 100755 index 0000000000..54d98b9b10 --- /dev/null +++ b/t/t0201-gettext-fallbacks.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description='Gettext Shell fallbacks' + +. ./test-lib.sh +. "$GIT_BUILD_DIR"/git-sh-i18n + +test_expect_success 'gettext: our gettext() fallback has pass-through semantics' ' + printf "test" >expect && + gettext "test" >actual && + test_i18ncmp expect actual && + printf "test more words" >expect && + gettext "test more words" >actual && + test_i18ncmp expect actual +' + +test_expect_success 'eval_gettext: our eval_gettext() fallback has pass-through semantics' ' + printf "test" >expect && + eval_gettext "test" >actual && + test_i18ncmp expect actual && + printf "test more words" >expect && + eval_gettext "test more words" >actual && + test_i18ncmp expect actual +' + +test_expect_success 'eval_gettext: our eval_gettext() fallback can interpolate variables' ' + printf "test YesPlease" >expect && + GIT_INTERNAL_GETTEXT_TEST_FALLBACKS=YesPlease eval_gettext "test \$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" >actual && + test_i18ncmp expect actual +' + +test_expect_success 'eval_gettext: our eval_gettext() fallback can interpolate variables with spaces' ' + cmdline="git am" && + export cmdline; + printf "When you have resolved this problem run git am --resolved." >expect && + eval_gettext "When you have resolved this problem run \$cmdline --resolved." >actual + test_i18ncmp expect actual +' + +test_expect_success 'eval_gettext: our eval_gettext() fallback can interpolate variables with spaces and quotes' ' + cmdline="git am" && + export cmdline; + printf "When you have resolved this problem run \"git am --resolved\"." >expect && + eval_gettext "When you have resolved this problem run \"\$cmdline --resolved\"." >actual + test_i18ncmp expect actual +' + +test_done diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh index ca8a4098fa..babcdd2343 100755 --- a/t/t1000-read-tree-m-3way.sh +++ b/t/t1000-read-tree-m-3way.sh @@ -72,6 +72,7 @@ In addition: ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh ################################################################ @@ -137,7 +138,7 @@ test_expect_success \ '3-way merge with git read-tree -m, empty cache' \ "rm -fr [NDMALTS][NDMALTSF] Z && rm .git/index && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" # This starts out with the first head, which is the normal @@ -146,9 +147,9 @@ test_expect_success \ '3-way merge with git read-tree -m, match H' \ "rm -fr [NDMALTS][NDMALTSF] Z && rm .git/index && - git read-tree $tree_A && + read_tree_must_succeed $tree_A && git checkout-index -f -u -a && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" : <<\END_OF_CASE_TABLE @@ -211,7 +212,7 @@ test_expect_success '1 - must not have an entry not in A.' " rm -f .git/index XX && echo XX >XX && git update-index --add XX && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -219,7 +220,7 @@ test_expect_success \ "rm -f .git/index NA && cp .orig-B/NA NA && git update-index --add NA && - git read-tree -m $tree_O $tree_A $tree_B" + read_tree_must_succeed -m $tree_O $tree_A $tree_B" test_expect_success \ '2 - matching B alone is OK in !O && !A && B case.' \ @@ -227,14 +228,14 @@ test_expect_success \ cp .orig-B/NA NA && git update-index --add NA && echo extra >>NA && - git read-tree -m $tree_O $tree_A $tree_B" + read_tree_must_succeed -m $tree_O $tree_A $tree_B" test_expect_success \ '3 - must match A in !O && A && !B case.' \ "rm -f .git/index AN && cp .orig-A/AN AN && git update-index --add AN && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -243,7 +244,7 @@ test_expect_success \ cp .orig-A/AN AN && git update-index --add AN && echo extra >>AN && - git read-tree -m $tree_O $tree_A $tree_B" + read_tree_must_succeed -m $tree_O $tree_A $tree_B" test_expect_success \ '3 (fail) - must match A in !O && A && !B case.' " @@ -251,7 +252,7 @@ test_expect_success \ cp .orig-A/AN AN && echo extra >>AN && git update-index --add AN && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -259,7 +260,7 @@ test_expect_success \ "rm -f .git/index AA && cp .orig-A/AA AA && git update-index --add AA && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -268,7 +269,7 @@ test_expect_success \ cp .orig-A/AA AA && git update-index --add AA && echo extra >>AA && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -277,7 +278,7 @@ test_expect_success \ cp .orig-A/AA AA && echo extra >>AA && git update-index --add AA && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -285,7 +286,7 @@ test_expect_success \ "rm -f .git/index LL && cp .orig-A/LL LL && git update-index --add LL && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -294,7 +295,7 @@ test_expect_success \ cp .orig-A/LL LL && git update-index --add LL && echo extra >>LL && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -303,7 +304,7 @@ test_expect_success \ cp .orig-A/LL LL && echo extra >>LL && git update-index --add LL && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -311,7 +312,7 @@ test_expect_success \ rm -f .git/index DD && echo DD >DD && git update-index --add DD && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -319,7 +320,7 @@ test_expect_success \ rm -f .git/index DM && cp .orig-B/DM DM && git update-index --add DM && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -327,7 +328,7 @@ test_expect_success \ rm -f .git/index DN && cp .orig-B/DN DN && git update-index --add DN && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -335,7 +336,7 @@ test_expect_success \ "rm -f .git/index MD && cp .orig-A/MD MD && git update-index --add MD && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -344,7 +345,7 @@ test_expect_success \ cp .orig-A/MD MD && git update-index --add MD && echo extra >>MD && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -353,7 +354,7 @@ test_expect_success \ cp .orig-A/MD MD && echo extra >>MD && git update-index --add MD && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -361,7 +362,7 @@ test_expect_success \ "rm -f .git/index ND && cp .orig-A/ND ND && git update-index --add ND && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -370,7 +371,7 @@ test_expect_success \ cp .orig-A/ND ND && git update-index --add ND && echo extra >>ND && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -379,7 +380,7 @@ test_expect_success \ cp .orig-A/ND ND && echo extra >>ND && git update-index --add ND && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -387,7 +388,7 @@ test_expect_success \ "rm -f .git/index MM && cp .orig-A/MM MM && git update-index --add MM && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -396,7 +397,7 @@ test_expect_success \ cp .orig-A/MM MM && git update-index --add MM && echo extra >>MM && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -405,7 +406,7 @@ test_expect_success \ cp .orig-A/MM MM && echo extra >>MM && git update-index --add MM && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -413,7 +414,7 @@ test_expect_success \ "rm -f .git/index SS && cp .orig-A/SS SS && git update-index --add SS && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -422,7 +423,7 @@ test_expect_success \ cp .orig-A/SS SS && git update-index --add SS && echo extra >>SS && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -431,7 +432,7 @@ test_expect_success \ cp .orig-A/SS SS && echo extra >>SS && git update-index --add SS && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -439,7 +440,7 @@ test_expect_success \ "rm -f .git/index MN && cp .orig-A/MN MN && git update-index --add MN && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -448,7 +449,7 @@ test_expect_success \ cp .orig-A/MN MN && git update-index --add MN && echo extra >>MN && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -456,7 +457,7 @@ test_expect_success \ "rm -f .git/index NM && cp .orig-A/NM NM && git update-index --add NM && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -465,7 +466,7 @@ test_expect_success \ cp .orig-B/NM NM && git update-index --add NM && echo extra >>NM && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -474,7 +475,7 @@ test_expect_success \ cp .orig-A/NM NM && git update-index --add NM && echo extra >>NM && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -483,7 +484,7 @@ test_expect_success \ cp .orig-A/NM NM && echo extra >>NM && git update-index --add NM && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " test_expect_success \ @@ -491,7 +492,7 @@ test_expect_success \ "rm -f .git/index NN && cp .orig-A/NN NN && git update-index --add NN && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -500,7 +501,7 @@ test_expect_success \ cp .orig-A/NN NN && git update-index --add NN && echo extra >>NN && - git read-tree -m $tree_O $tree_A $tree_B && + read_tree_must_succeed -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ @@ -509,7 +510,7 @@ test_expect_success \ cp .orig-A/NN NN && echo extra >>NN && git update-index --add NN && - test_must_fail git read-tree -m $tree_O $tree_A $tree_B + read_tree_must_fail -m $tree_O $tree_A $tree_B " # #16 @@ -522,7 +523,7 @@ test_expect_success \ echo E16 >F16 && git update-index F16 && tree1=`git write-tree` && - git read-tree -m $tree0 $tree1 $tree1 $tree0 && + read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 && git ls-files --stage' test_done diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 680d992f22..acaab07fac 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -21,6 +21,7 @@ In the test, these paths are used: yomin - not in H nor M ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh read_tree_twoway () { git read-tree -m "$1" "$2" && git ls-files --stage @@ -94,7 +95,7 @@ echo '+100644 X 0 yomin' >expected test_expect_success \ '4 - carry forward local addition.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && git update-index --add yomin && read_tree_twoway $treeH $treeM && @@ -106,7 +107,7 @@ test_expect_success \ test_expect_success \ '5 - carry forward local addition.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo yomin >yomin && git update-index --add yomin && @@ -120,7 +121,7 @@ test_expect_success \ test_expect_success \ '6 - local addition already has the same.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && git update-index --add frotz && read_tree_twoway $treeH $treeM && @@ -131,7 +132,7 @@ test_expect_success \ test_expect_success \ '7 - local addition already has the same.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo frotz >frotz && git update-index --add frotz && @@ -144,7 +145,7 @@ test_expect_success \ test_expect_success \ '8 - conflicting addition.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo frotz frotz >frotz && git update-index --add frotz && @@ -153,7 +154,7 @@ test_expect_success \ test_expect_success \ '9 - conflicting addition.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo frotz frotz >frotz && git update-index --add frotz && @@ -163,7 +164,7 @@ test_expect_success \ test_expect_success \ '10 - path removed.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo rezrov >rezrov && git update-index --add rezrov && @@ -174,7 +175,7 @@ test_expect_success \ test_expect_success \ '11 - dirty path removed.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo rezrov >rezrov && git update-index --add rezrov && @@ -184,7 +185,7 @@ test_expect_success \ test_expect_success \ '12 - unmatching local changes being removed.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo rezrov rezrov >rezrov && git update-index --add rezrov && @@ -193,7 +194,7 @@ test_expect_success \ test_expect_success \ '13 - unmatching local changes being removed.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo rezrov rezrov >rezrov && git update-index --add rezrov && @@ -208,7 +209,7 @@ EOF test_expect_success \ '14 - unchanged in two heads.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo nitfol nitfol >nitfol && git update-index --add nitfol && @@ -221,7 +222,7 @@ test_expect_success \ test_expect_success \ '15 - unchanged in two heads.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo nitfol nitfol >nitfol && git update-index --add nitfol && @@ -235,7 +236,7 @@ test_expect_success \ test_expect_success \ '16 - conflicting local change.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo bozbar bozbar >bozbar && git update-index --add bozbar && @@ -244,7 +245,7 @@ test_expect_success \ test_expect_success \ '17 - conflicting local change.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && echo bozbar bozbar >bozbar && git update-index --add bozbar && @@ -254,7 +255,7 @@ test_expect_success \ test_expect_success \ '18 - local change already having a good result.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && cat bozbar-new >bozbar && git update-index --add bozbar && @@ -266,7 +267,7 @@ test_expect_success \ test_expect_success \ '19 - local change already having a good result, further modified.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && cat bozbar-new >bozbar && git update-index --add bozbar && @@ -279,7 +280,7 @@ test_expect_success \ test_expect_success \ '20 - no local change, use new tree.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && cat bozbar-old >bozbar && git update-index --add bozbar && @@ -291,7 +292,7 @@ test_expect_success \ test_expect_success \ '21 - no local change, dirty cache.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && cat bozbar-old >bozbar && git update-index --add bozbar && @@ -302,7 +303,7 @@ test_expect_success \ test_expect_success \ '22 - local change cache updated.' \ 'rm -f .git/index && - git read-tree $treeH && + read_tree_must_succeed $treeH && git checkout-index -u -f -q -a && sed -e "s/such as/SUCH AS/" bozbar-old >bozbar && git update-index --add bozbar && @@ -359,7 +360,7 @@ test_expect_success \ test_expect_success \ 'a/b (untracked) vs a, plus c/d case test.' \ - 'test_must_fail git read-tree -u -m "$treeH" "$treeM" && + 'read_tree_u_must_fail -u -m "$treeH" "$treeM" && git ls-files --stage && test -f a/b' @@ -386,7 +387,7 @@ test_expect_success \ test_expect_success \ 'a/b vs a, plus c/d case test.' \ - 'git read-tree -u -m "$treeH" "$treeM" && + 'read_tree_u_must_succeed -u -m "$treeH" "$treeM" && git ls-files --stage | tee >treeMcheck.out && test_cmp treeM.out treeMcheck.out' @@ -401,7 +402,7 @@ test_expect_success '-m references the correct modified tree' ' echo a >file-a && git add file-a && git ls-tree $(git write-tree) file-a >expect && - git read-tree -m HEAD initial-mod && + read_tree_must_succeed -m HEAD initial-mod && git ls-tree $(git write-tree) file-a >actual && test_cmp expect actual ' diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh index a4a17e0017..a847709a13 100755 --- a/t/t1002-read-tree-m-u-2way.sh +++ b/t/t1002-read-tree-m-u-2way.sh @@ -9,6 +9,7 @@ This is identical to t1001, but uses -u to update the work tree as well. ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh compare_change () { sed >current \ @@ -56,8 +57,8 @@ test_expect_success \ test_expect_success \ '1, 2, 3 - no carry forward' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed --reset -u $treeH && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >1-3.out && cmp M.out 1-3.out && sum bozbar frotz nitfol >actual3.sum && @@ -69,11 +70,11 @@ test_expect_success \ test_expect_success \ '4 - carry forward local addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo "+100644 X 0 yomin" >expected && echo yomin >yomin && git update-index --add yomin && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >4.out || return 1 git diff -U0 --no-index M.out 4.out >4diff.out compare_change 4diff.out expected && @@ -87,12 +88,12 @@ test_expect_success \ test_expect_success \ '5 - carry forward local addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && - git read-tree -m -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && + read_tree_u_must_succeed -m -u $treeH && echo yomin >yomin && git update-index --add yomin && echo yomin yomin >yomin && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >5.out || return 1 git diff -U0 --no-index M.out 5.out >5diff.out compare_change 5diff.out expected && @@ -107,10 +108,10 @@ test_expect_success \ test_expect_success \ '6 - local addition already has the same.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo frotz >frotz && git update-index --add frotz && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >6.out && test_cmp M.out 6.out && check_cache_at frotz clean && @@ -123,11 +124,11 @@ test_expect_success \ test_expect_success \ '7 - local addition already has the same.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo frotz >frotz && git update-index --add frotz && echo frotz frotz >frotz && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >7.out && test_cmp M.out 7.out && check_cache_at frotz dirty && @@ -141,27 +142,27 @@ test_expect_success \ test_expect_success \ '8 - conflicting addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo frotz frotz >frotz && git update-index --add frotz && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '9 - conflicting addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo frotz frotz >frotz && git update-index --add frotz && echo frotz >frotz && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '10 - path removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo rezrov >rezrov && git update-index --add rezrov && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >10.out && cmp M.out 10.out && sum bozbar frotz nitfol >actual10.sum && @@ -170,28 +171,28 @@ test_expect_success \ test_expect_success \ '11 - dirty path removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo rezrov >rezrov && git update-index --add rezrov && echo rezrov rezrov >rezrov && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '12 - unmatching local changes being removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo rezrov rezrov >rezrov && git update-index --add rezrov && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '13 - unmatching local changes being removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo rezrov rezrov >rezrov && git update-index --add rezrov && echo rezrov >rezrov && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' cat >expected <<EOF -100644 X 0 nitfol @@ -201,10 +202,10 @@ EOF test_expect_success \ '14 - unchanged in two heads.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo nitfol nitfol >nitfol && git update-index --add nitfol && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >14.out && test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out && compare_change 14diff.out expected && @@ -221,11 +222,11 @@ test_expect_success \ test_expect_success \ '15 - unchanged in two heads.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo nitfol nitfol >nitfol && git update-index --add nitfol && echo nitfol nitfol nitfol >nitfol && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >15.out && test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out && compare_change 15diff.out expected && @@ -242,27 +243,27 @@ test_expect_success \ test_expect_success \ '16 - conflicting local change.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo bozbar bozbar >bozbar && git update-index --add bozbar && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '17 - conflicting local change.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo bozbar bozbar >bozbar && git update-index --add bozbar && echo bozbar bozbar bozbar >bozbar && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '18 - local change already having a good result.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo gnusto >bozbar && git update-index --add bozbar && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >18.out && test_cmp M.out 18.out && check_cache_at bozbar clean && @@ -272,11 +273,11 @@ test_expect_success \ test_expect_success \ '19 - local change already having a good result, further modified.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo gnusto >bozbar && git update-index --add bozbar && echo gnusto gnusto >bozbar && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >19.out && test_cmp M.out 19.out && check_cache_at bozbar dirty && @@ -292,10 +293,10 @@ test_expect_success \ test_expect_success \ '20 - no local change, use new tree.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo bozbar >bozbar && git update-index --add bozbar && - git read-tree -m -u $treeH $treeM && + read_tree_u_must_succeed -m -u $treeH $treeM && git ls-files --stage >20.out && test_cmp M.out 20.out && check_cache_at bozbar clean && @@ -305,11 +306,11 @@ test_expect_success \ test_expect_success \ '21 - no local change, dirty cache.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git read-tree --reset -u $treeH && + read_tree_u_must_succeed --reset -u $treeH && echo bozbar >bozbar && git update-index --add bozbar && echo gnusto gnusto >bozbar && - if git read-tree -m -u $treeH $treeM; then false; else :; fi' + if read_tree_u_must_succeed -m -u $treeH $treeM; then false; else :; fi' # Also make sure we did not break DF vs DF/DF case. test_expect_success \ @@ -336,7 +337,7 @@ test_expect_success \ rm -fr DF && echo DF >DF && git update-index --add DF && - git read-tree -m -u $treeDF $treeDFDF && + read_tree_u_must_succeed -m -u $treeDF $treeDFDF && git ls-files --stage >DFDFcheck.out && test_cmp DFDF.out DFDFcheck.out && check_cache_at DF/DF clean' diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index eb8e3d4476..b3ae7d52c6 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -3,6 +3,7 @@ test_description='read-tree -m -u checks working tree files' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh # two-tree test @@ -29,7 +30,7 @@ test_expect_success 'two-way not clobbering' ' echo >file2 master creates untracked file2 && echo >subdir/file2 master creates untracked subdir/file2 && - if err=`git read-tree -m -u master side 2>&1` + if err=`read_tree_u_must_succeed -m -u master side 2>&1` then echo should have complained false @@ -42,7 +43,7 @@ echo file2 >.gitignore test_expect_success 'two-way with incorrect --exclude-per-directory (1)' ' - if err=`git read-tree -m --exclude-per-directory=.gitignore master side 2>&1` + if err=`read_tree_u_must_succeed -m --exclude-per-directory=.gitignore master side 2>&1` then echo should have complained false @@ -53,7 +54,7 @@ test_expect_success 'two-way with incorrect --exclude-per-directory (1)' ' test_expect_success 'two-way with incorrect --exclude-per-directory (2)' ' - if err=`git read-tree -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1` + if err=`read_tree_u_must_succeed -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1` then echo should have complained false @@ -64,7 +65,7 @@ test_expect_success 'two-way with incorrect --exclude-per-directory (2)' ' test_expect_success 'two-way clobbering a ignored file' ' - git read-tree -m -u --exclude-per-directory=.gitignore master side + read_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore master side ' rm -f .gitignore @@ -84,7 +85,7 @@ test_expect_success 'three-way not complaining on an untracked path in both' ' echo >file2 file two is untracked on the master side && echo >subdir/file2 file two is untracked on the master side && - git read-tree -m -u branch-point master side + read_tree_u_must_succeed -m -u branch-point master side ' test_expect_success 'three-way not clobbering a working tree file' ' @@ -94,7 +95,7 @@ test_expect_success 'three-way not clobbering a working tree file' ' git checkout master && echo >file3 file three created in master, untracked && echo >subdir/file3 file three created in master, untracked && - if err=`git read-tree -m -u branch-point master side 2>&1` + if err=`read_tree_u_must_succeed -m -u branch-point master side 2>&1` then echo should have complained false @@ -113,7 +114,7 @@ test_expect_success 'three-way not complaining on an untracked file' ' echo >file3 file three created in master, untracked && echo >subdir/file3 file three created in master, untracked && - git read-tree -m -u --exclude-per-directory=.gitignore branch-point master side + read_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore branch-point master side ' test_expect_success '3-way not overwriting local changes (setup)' ' @@ -137,7 +138,7 @@ test_expect_success '3-way not overwriting local changes (our side)' ' git reset --hard && echo >>file1 "local changes" && - git read-tree -m -u branch-point side-a side-b && + read_tree_u_must_succeed -m -u branch-point side-a side-b && grep "new line to be kept" file1 && grep "local changes" file1 @@ -151,7 +152,7 @@ test_expect_success '3-way not overwriting local changes (their side)' ' git reset --hard && echo >>file2 "local changes" && - test_must_fail git read-tree -m -u branch-point side-a side-b && + read_tree_u_must_fail -m -u branch-point side-a side-b && ! grep "new line to be kept" file2 && grep "local changes" file2 @@ -173,7 +174,7 @@ test_expect_success SYMLINKS 'funny symlink in work tree' ' git add a/b && git commit -m "we add a/b" && - git read-tree -m -u sym-a sym-a sym-b + read_tree_u_must_succeed -m -u sym-a sym-a sym-b ' @@ -209,7 +210,7 @@ test_expect_success 'D/F setup' ' test_expect_success 'D/F' ' git checkout side-b && - git read-tree -m -u branch-point side-b side-a && + read_tree_u_must_succeed -m -u branch-point side-b side-a && git ls-files -u >actual && ( a=$(git rev-parse branch-point:subdir/file2) diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh index 849911683a..f53de79e56 100755 --- a/t/t1005-read-tree-reset.sh +++ b/t/t1005-read-tree-reset.sh @@ -3,6 +3,7 @@ test_description='read-tree -u --reset' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh # two-tree test @@ -22,13 +23,13 @@ test_expect_success 'setup' ' ' test_expect_success 'reset should work' ' - git read-tree -u --reset HEAD^ && + read_tree_u_must_succeed -u --reset HEAD^ && git ls-files >actual && test_cmp expect actual ' test_expect_success 'reset should remove remnants from a failed merge' ' - git read-tree --reset -u HEAD && + read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >expect && sha1=$(git rev-parse :new) && ( @@ -37,13 +38,13 @@ test_expect_success 'reset should remove remnants from a failed merge' ' ) | git update-index --index-info && >old && git ls-files -s && - git read-tree --reset -u HEAD && + read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >actual && ! test -f old ' test_expect_success 'Porcelain reset should remove remnants too' ' - git read-tree --reset -u HEAD && + read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >expect && sha1=$(git rev-parse :new) && ( @@ -58,7 +59,7 @@ test_expect_success 'Porcelain reset should remove remnants too' ' ' test_expect_success 'Porcelain checkout -f should remove remnants too' ' - git read-tree --reset -u HEAD && + read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >expect && sha1=$(git rev-parse :new) && ( @@ -73,7 +74,7 @@ test_expect_success 'Porcelain checkout -f should remove remnants too' ' ' test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' ' - git read-tree --reset -u HEAD && + read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >expect && sha1=$(git rev-parse :new) && ( diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index dd32432d62..6d52b824b1 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -188,4 +188,17 @@ for args in "-w --stdin-paths" "--stdin-paths -w"; do pop_repo done +test_expect_success 'corrupt tree' ' + echo abc >malformed-tree + test_must_fail git hash-object -t tree malformed-tree +' + +test_expect_success 'corrupt commit' ' + test_must_fail git hash-object -t commit --stdin </dev/null +' + +test_expect_success 'corrupt tag' ' + test_must_fail git hash-object -t tag --stdin </dev/null +' + test_done diff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh index f9e00285db..4c50ed955e 100755 --- a/t/t1008-read-tree-overlay.sh +++ b/t/t1008-read-tree-overlay.sh @@ -3,6 +3,7 @@ test_description='test multi-tree read-tree without merging' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh test_expect_success setup ' echo one >a && @@ -21,7 +22,7 @@ test_expect_success setup ' ' test_expect_success 'multi-read' ' - git read-tree initial master side && + read_tree_must_succeed initial master side && (echo a; echo b/c) >expect && git ls-files >actual && test_cmp expect actual diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index de84e35c43..5c0053a20b 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -12,24 +12,27 @@ test_description='sparse checkout tests ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh test_expect_success 'setup' ' cat >expected <<-\EOF && 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added + 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/addedtoo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 subsub/added EOF cat >expected.swt <<-\EOF && H init.t H sub/added + H sub/addedtoo H subsub/added EOF test_commit init && echo modified >>init.t && mkdir sub subsub && - touch sub/added subsub/added && - git add init.t sub/added subsub/added && + touch sub/added sub/addedtoo subsub/added && + git add init.t sub/added sub/addedtoo subsub/added && git commit -m "modified and added" && git tag top && git rm sub/added && @@ -41,7 +44,7 @@ test_expect_success 'setup' ' ' test_expect_success 'read-tree without .git/info/sparse-checkout' ' - git read-tree -m -u HEAD && + read_tree_u_must_succeed -m -u HEAD && git ls-files --stage >result && test_cmp expected result && git ls-files -t >result && @@ -50,7 +53,7 @@ test_expect_success 'read-tree without .git/info/sparse-checkout' ' test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' echo >.git/info/sparse-checkout && - git read-tree -m -u HEAD && + read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && test -f init.t && @@ -60,7 +63,7 @@ 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 && - git read-tree --no-sparse-checkout -m -u HEAD && + read_tree_u_must_succeed --no-sparse-checkout -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && test -f init.t && @@ -70,7 +73,7 @@ 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 && - test_must_fail git read-tree -m -u HEAD && + read_tree_u_must_fail -m -u HEAD && git ls-files --stage >result && test_cmp expected result && git ls-files -t >result && @@ -83,11 +86,12 @@ test_expect_success 'match directories with trailing slash' ' cat >expected.swt-noinit <<-\EOF && S init.t H sub/added + H sub/addedtoo S subsub/added EOF echo sub/ > .git/info/sparse-checkout && - git read-tree -m -u HEAD && + read_tree_u_must_succeed -m -u HEAD && git ls-files -t > result && test_cmp expected.swt-noinit result && test ! -f init.t && @@ -95,18 +99,59 @@ test_expect_success 'match directories with trailing slash' ' ' test_expect_success 'match directories without trailing slash' ' - echo sub >>.git/info/sparse-checkout && - git read-tree -m -u HEAD && + echo sub >.git/info/sparse-checkout && + read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' -test_expect_success 'match directory pattern' ' - echo "s?b" >>.git/info/sparse-checkout && +test_expect_success 'match directories with negated patterns' ' + cat >expected.swt-negation <<\EOF && +S init.t +S sub/added +H sub/addedtoo +S subsub/added +EOF + + cat >.git/info/sparse-checkout <<\EOF && +sub +!sub/added +EOF + git read-tree -m -u HEAD && + git ls-files -t >result && + test_cmp expected.swt-negation result && + test ! -f init.t && + test ! -f sub/added && + test -f sub/addedtoo +' + +test_expect_success 'match directories with negated patterns (2)' ' + cat >expected.swt-negation2 <<\EOF && +H init.t +H sub/added +S sub/addedtoo +H subsub/added +EOF + + cat >.git/info/sparse-checkout <<\EOF && +/* +!sub +sub/added +EOF git read-tree -m -u HEAD && git ls-files -t >result && + test_cmp expected.swt-negation2 result && + test -f init.t && + test -f sub/added && + test ! -f sub/addedtoo +' + +test_expect_success 'match directory pattern' ' + echo "s?b" >.git/info/sparse-checkout && + read_tree_u_must_succeed -m -u HEAD && + git ls-files -t >result && test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added @@ -116,11 +161,12 @@ test_expect_success 'checkout area changes' ' cat >expected.swt-nosub <<-\EOF && H init.t S sub/added + S sub/addedtoo S subsub/added EOF echo init.t >.git/info/sparse-checkout && - git read-tree -m -u HEAD && + read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-nosub result && test -f init.t && @@ -130,7 +176,7 @@ test_expect_success 'checkout area changes' ' test_expect_success 'read-tree updates worktree, absent case' ' echo sub/added >.git/info/sparse-checkout && git checkout -f top && - git read-tree -m -u HEAD^ && + read_tree_u_must_succeed -m -u HEAD^ && test ! -f init.t ' @@ -138,7 +184,7 @@ test_expect_success 'read-tree updates worktree, dirty case' ' echo sub/added >.git/info/sparse-checkout && git checkout -f top && echo dirty >init.t && - git read-tree -m -u HEAD^ && + read_tree_u_must_succeed -m -u HEAD^ && grep -q dirty init.t && rm init.t ' @@ -147,14 +193,14 @@ test_expect_success 'read-tree removes worktree, dirty case' ' echo init.t >.git/info/sparse-checkout && git checkout -f top && echo dirty >added && - git read-tree -m -u HEAD^ && + read_tree_u_must_succeed -m -u HEAD^ && grep -q dirty added ' test_expect_success 'read-tree adds to worktree, absent case' ' echo init.t >.git/info/sparse-checkout && git checkout -f removed && - git read-tree -u -m HEAD^ && + read_tree_u_must_succeed -u -m HEAD^ && test ! -f sub/added ' @@ -163,7 +209,7 @@ test_expect_success 'read-tree adds to worktree, dirty case' ' git checkout -f removed && mkdir sub && echo dirty >sub/added && - git read-tree -u -m HEAD^ && + read_tree_u_must_succeed -u -m HEAD^ && grep -q dirty sub/added ' @@ -188,4 +234,20 @@ test_expect_success 'read-tree --reset removes outside worktree' ' test_cmp empty result ' +test_expect_success 'print errors when failed to update worktree' ' + echo sub >.git/info/sparse-checkout && + git checkout -f init && + mkdir sub && + touch sub/added sub/addedtoo && + test_must_fail git checkout top 2>actual && + cat >expected <<\EOF && +error: The following untracked working tree files would be overwritten by checkout: + sub/added + sub/addedtoo +Please move or remove them before you can switch branches. +Aborting +EOF + test_cmp expected actual +' + test_done diff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh index 9811d467da..a6a04b6b90 100755 --- a/t/t1012-read-tree-df.sh +++ b/t/t1012-read-tree-df.sh @@ -3,6 +3,7 @@ test_description='read-tree D/F conflict corner cases' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh maketree () { ( @@ -53,7 +54,7 @@ test_expect_success setup ' test_expect_success '3-way (1)' ' settree A-000 && - git read-tree -m -u O-000 A-000 B-000 && + read_tree_u_must_succeed -m -u O-000 A-000 B-000 && checkindex <<-EOF 3 a/b 0 a/b-2/c/d @@ -65,7 +66,7 @@ test_expect_success '3-way (1)' ' test_expect_success '3-way (2)' ' settree A-001 && - git read-tree -m -u O-000 A-001 B-000 && + read_tree_u_must_succeed -m -u O-000 A-001 B-000 && checkindex <<-EOF 3 a/b 0 a/b-2/c/d @@ -78,7 +79,7 @@ test_expect_success '3-way (2)' ' test_expect_success '3-way (3)' ' settree A-010 && - git read-tree -m -u O-010 A-010 B-010 && + read_tree_u_must_succeed -m -u O-010 A-010 B-010 && checkindex <<-EOF 2 t 1 t-0 @@ -92,7 +93,7 @@ test_expect_success '3-way (3)' ' test_expect_success '2-way (1)' ' settree O-020 && - git read-tree -m -u O-020 A-020 && + read_tree_u_must_succeed -m -u O-020 A-020 && checkindex <<-EOF 0 ds/dma/ioat/Makefile 0 ds/dma/ioat/registers.h diff --git a/t/t1013-loose-object-format.sh b/t/t1013-loose-object-format.sh new file mode 100755 index 0000000000..0a9cedd374 --- /dev/null +++ b/t/t1013-loose-object-format.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2011 Roberto Tyley +# + +test_description='Correctly identify and parse loose object headers + +There are two file formats for loose objects - the original standard +format, and the experimental format introduced with Git v1.4.3, later +deprecated with v1.5.3. Although Git no longer writes the +experimental format, objects in both formats must be read, with the +format for a given file being determined by the header. + +Detecting file format based on header is not entirely trivial, not +least because the first byte of a zlib-deflated stream will vary +depending on how much memory was allocated for the deflation window +buffer when the object was written out (for example 4KB on Android, +rather that 32KB on a normal PC). + +The loose objects used as test vectors have been generated with the +following Git versions: + +standard format: Git v1.7.4.1 +experimental format: Git v1.4.3 (legacyheaders=false) +standard format, deflated with 4KB window size: Agit/JGit on Android +' + +. ./test-lib.sh + +assert_blob_equals() { + printf "%s" "$2" >expected && + git cat-file -p "$1" >actual && + test_cmp expected actual +} + +test_expect_success setup ' + cp -R "$TEST_DIRECTORY/t1013/objects" .git/ + git --version +' + +test_expect_success 'read standard-format loose objects' ' + git cat-file tag 8d4e360d6c70fbd72411991c02a09c442cf7a9fa && + git cat-file commit 6baee0540ea990d9761a3eb9ab183003a71c3696 && + git ls-tree 7a37b887a73791d12d26c0d3e39568a8fb0fa6e8 && + assert_blob_equals "257cc5642cb1a054f08cc83f2d943e56fd3ebe99" "foo$LF" +' + +test_expect_success 'read experimental-format loose objects' ' + git cat-file tag 76e7fa9941f4d5f97f64fea65a2cba436bc79cbb && + git cat-file commit 7875c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 && + git ls-tree 95b1625de3ba8b2214d1e0d0591138aea733f64f && + assert_blob_equals "2e65efe2a145dda7ee51d1741299f848e5bf752e" "a" && + assert_blob_equals "9ae9e86b7bd6cb1472d9373702d8249973da0832" "ab" && + assert_blob_equals "85df50785d62d3b05ab03d9cbf7e4a0b49449730" "abcd" && + assert_blob_equals "1656f9233d999f61ef23ef390b9c71d75399f435" "abcdefgh" && + assert_blob_equals "1e72a6b2c4a577ab0338860fa9fe87f761fc9bbd" "abcdefghi" && + assert_blob_equals "70e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd" "abcdefghijklmnop" && + assert_blob_equals "bd15045f6ce8ff75747562173640456a394412c8" "abcdefghijklmnopqrstuvwx" +' + +test_expect_success 'read standard-format objects deflated with smaller window buffer' ' + git cat-file tag f816d5255855ac160652ee5253b06cd8ee14165a && + git cat-file tag 149cedb5c46929d18e0f118e9fa31927487af3b6 +' + +test_done diff --git a/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6 b/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6 Binary files differnew file mode 100644 index 0000000000..472fd1458e --- /dev/null +++ b/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6 diff --git a/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435 b/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435 Binary files differnew file mode 100644 index 0000000000..c379d74ae2 --- /dev/null +++ b/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435 diff --git a/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd b/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd Binary files differnew file mode 100644 index 0000000000..93706305bc --- /dev/null +++ b/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd diff --git a/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 b/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 Binary files differnew file mode 100644 index 0000000000..bdcf704c9e --- /dev/null +++ b/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 diff --git a/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e b/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e Binary files differnew file mode 100644 index 0000000000..ad62c43e41 --- /dev/null +++ b/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e diff --git a/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696 b/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696 Binary files differnew file mode 100644 index 0000000000..3d2f0337db --- /dev/null +++ b/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696 diff --git a/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd b/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd Binary files differnew file mode 100644 index 0000000000..b3f71a6ee5 --- /dev/null +++ b/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd diff --git a/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb b/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb new file mode 100644 index 0000000000..af4e9a7b0c --- /dev/null +++ b/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb @@ -0,0 +1,2 @@ +Âxœ%ÌA‚0@Ñ}O1{cSZ(˜ãνáÃthª”’ZŒÜÞ Ëÿ?
¦m×6dµiÉ9…¤Gå˜h´Ø¨ÁZR'Q¶…RŒ¡ˆ‚ø³p‘ç‚ÓqL9âÏ=g¸§sIÐoopÎÿ”eÏ«_1»€³¤$×ç*Si«ëNwpP•RBôûÅÁú +³‡[(ð®d-øÁL9á
\ No newline at end of file diff --git a/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 b/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 Binary files differnew file mode 100644 index 0000000000..3dd28be5c6 --- /dev/null +++ b/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 diff --git a/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8 b/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8 Binary files differnew file mode 100644 index 0000000000..2b97b264c3 --- /dev/null +++ b/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8 diff --git a/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730 b/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730 Binary files differnew file mode 100644 index 0000000000..6dff746876 --- /dev/null +++ b/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730 diff --git a/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa b/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa Binary files differnew file mode 100644 index 0000000000..cb41e92d07 --- /dev/null +++ b/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa diff --git a/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f b/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f Binary files differnew file mode 100644 index 0000000000..7ac46b4f70 --- /dev/null +++ b/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f diff --git a/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832 b/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832 Binary files differnew file mode 100644 index 0000000000..9d8316d4e5 --- /dev/null +++ b/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832 diff --git a/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8 b/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8 Binary files differnew file mode 100644 index 0000000000..eebf23956e --- /dev/null +++ b/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8 diff --git a/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 Binary files differnew file mode 100644 index 0000000000..134cf19379 --- /dev/null +++ b/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a b/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a new file mode 100644 index 0000000000..26b75aec56 --- /dev/null +++ b/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a @@ -0,0 +1 @@ +H‰ÌÁ‚0€aÏ{ŠÞ
I»e&Æø*¥ˆG°ß^¸ýù¿ËDåÒ†wU‡Ò—¬S±4ªŠÆªž ,fÅ[ðßVAÛºÎüxÈÇö6[wtG§Lu¸?—¦²¼Ú×@‰"gì{†+by¾%M
\ No newline at end of file diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 1fd187c5eb..e23ac0e69d 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -7,6 +7,7 @@ test_description='Try various core-level commands in subdirectory. ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-read-tree.sh test_expect_success setup ' long="a b c d e f g h i j k l m n o p q r s t u v w x y z" && @@ -16,8 +17,6 @@ test_expect_success setup ' cp one original.one && cp dir/two original.two ' -LF=' -' test_expect_success 'update-index and ls-files' ' git update-index --add one && @@ -98,13 +97,13 @@ test_expect_success 'checkout-index' ' test_expect_success 'read-tree' ' rm -f one dir/two && tree=`git write-tree` && - git read-tree --reset -u "$tree" && + read_tree_u_must_succeed --reset -u "$tree" && cmp one original.one && cmp dir/two original.two && ( cd dir && rm -f two && - git read-tree --reset -u "$tree" && + read_tree_u_must_succeed --reset -u "$tree" && cmp two ../original.two && cmp ../one ../original.one ) @@ -118,6 +117,43 @@ test_expect_success 'alias expansion' ' git ss ) ' + +test_expect_success NOT_MINGW '!alias expansion' ' + pwd >expect && + ( + git config alias.test !pwd && + cd dir && + git test >../actual + ) && + test_cmp expect actual +' + +test_expect_success 'GIT_PREFIX for !alias' ' + printf "dir/" >expect && + ( + git config alias.test "!sh -c \"printf \$GIT_PREFIX\"" && + cd dir && + git test >../actual + ) && + test_cmp expect actual +' + +test_expect_success 'GIT_PREFIX for built-ins' ' + # Use GIT_EXTERNAL_DIFF to test that the "diff" built-in + # receives the GIT_PREFIX variable. + printf "dir/" >expect && + printf "#!/bin/sh\n" >diff && + printf "printf \"\$GIT_PREFIX\"" >>diff && + chmod +x diff && + ( + cd dir && + printf "change" >two && + env GIT_EXTERNAL_DIFF=./diff git diff >../actual + git checkout -- two + ) && + test_cmp expect actual +' + test_expect_success 'no file/rev ambiguity check inside .git' ' git commit -a -m 1 && ( diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh new file mode 100755 index 0000000000..301e071ff7 --- /dev/null +++ b/t/t1021-rerere-in-workdir.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='rerere run in a workdir' +. ./test-lib.sh + +test_expect_success SYMLINKS setup ' + git config rerere.enabled true && + >world && + git add world && + test_tick && + git commit -m initial && + + echo hello >world && + test_tick && + git commit -a -m hello && + + git checkout -b side HEAD^ && + echo goodbye >world && + test_tick && + git commit -a -m goodbye && + + git checkout master +' + +test_expect_success SYMLINKS 'rerere in workdir' ' + rm -rf .git/rr-cache && + "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . work && + ( + cd work && + test_must_fail git merge side && + git rerere status >actual && + echo world >expect && + test_cmp expect actual + ) +' + +# This fails because we don't resolve relative symlink in mkdir_in_gitdir() +# For the purpose of helping contrib/workdir/git-new-workdir users, we do not +# have to support relative symlinks, but it might be nicer to make this work +# with a relative symbolic link someday. +test_expect_failure SYMLINKS 'rerere in workdir (relative)' ' + rm -rf .git/rr-cache && + "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . krow && + ( + cd krow && + rm -f .git/rr-cache && + ln -s ../.git/rr-cache .git/rr-cache && + test_must_fail git merge side && + git rerere status >actual && + echo world >expect && + test_cmp expect actual + ) +' + +test_done diff --git a/t/t1050-large.sh b/t/t1050-large.sh new file mode 100755 index 0000000000..deba111bd7 --- /dev/null +++ b/t/t1050-large.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# Copyright (c) 2011, Google Inc. + +test_description='adding and checking out large blobs' + +. ./test-lib.sh + +test_expect_success setup ' + git config core.bigfilethreshold 200k && + echo X | dd of=large bs=1k seek=2000 +' + +test_expect_success 'add a large file' ' + git add large && + # make sure we got a packfile and no loose objects + test -f .git/objects/pack/pack-*.pack && + test ! -f .git/objects/??/?????????????????????????????????????? +' + +test_expect_success 'checkout a large file' ' + large=$(git rev-parse :large) && + git update-index --add --cacheinfo 100644 $large another && + git checkout another && + cmp large another ;# this must not be test_cmp +' + +test_done diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index bfa2c2190d..5e29e13782 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -163,8 +163,11 @@ test_expect_success 'git resolve' ' git checkout mybranch && git merge -m "Merge upstream changes." master | sed -e "1s/[0-9a-f]\{7\}/VARIABLE/g" \ - -e "s/^Fast[- ]forward /FASTFORWARD /" >resolve.output && - test_cmp resolve.expect resolve.output + -e "s/^Fast[- ]forward /FASTFORWARD /" >resolve.output +' + +test_expect_success 'git resolve output' ' + test_i18ncmp resolve.expect resolve.output ' cat > show-branch2.expect << EOF diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index d0e55465ff..51caff047b 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -7,28 +7,28 @@ test_description='Test git config in different settings' . ./test-lib.sh -test -f .git/config && rm .git/config - -git config core.penguin "little blue" +test_expect_success 'clear default config' ' + rm -f .git/config +' cat > expect << EOF [core] penguin = little blue EOF - -test_expect_success 'initial' 'cmp .git/config expect' - -git config Core.Movie BadPhysics +test_expect_success 'initial' ' + git config core.penguin "little blue" && + test_cmp expect .git/config +' cat > expect << EOF [core] penguin = little blue Movie = BadPhysics EOF - -test_expect_success 'mixed case' 'cmp .git/config expect' - -git config Cores.WhatEver Second +test_expect_success 'mixed case' ' + git config Core.Movie BadPhysics && + test_cmp expect .git/config +' cat > expect << EOF [core] @@ -37,10 +37,10 @@ cat > expect << EOF [Cores] WhatEver = Second EOF - -test_expect_success 'similar section' 'cmp .git/config expect' - -git config CORE.UPPERCASE true +test_expect_success 'similar section' ' + git config Cores.WhatEver Second + test_cmp expect .git/config +' cat > expect << EOF [core] @@ -50,8 +50,10 @@ cat > expect << EOF [Cores] WhatEver = Second EOF - -test_expect_success 'similar section' 'cmp .git/config expect' +test_expect_success 'uppercase section' ' + git config CORE.UPPERCASE true && + test_cmp expect .git/config +' test_expect_success 'replace with non-match' \ 'git config core.penguin kingpin !blue' @@ -69,7 +71,34 @@ cat > expect << EOF WhatEver = Second EOF -test_expect_success 'non-match result' 'cmp .git/config expect' +test_expect_success 'non-match result' 'test_cmp expect .git/config' + +test_expect_success 'find mixed-case key by canonical name' ' + echo Second >expect && + git config cores.whatever >actual && + test_cmp expect actual +' + +test_expect_success 'find mixed-case key by non-canonical name' ' + echo Second >expect && + git config CoReS.WhAtEvEr >actual && + test_cmp expect actual +' + +test_expect_success 'subsections are not canonicalized by git-config' ' + cat >>.git/config <<-\EOF && + [section.SubSection] + key = one + [section "SubSection"] + key = two + EOF + echo one >expect && + git config section.subsection.key >actual && + test_cmp expect actual && + echo two >expect && + git config section.SubSection.key >actual && + test_cmp expect actual +' cat > .git/config <<\EOF [alpha] @@ -88,7 +117,7 @@ bar = foo [beta] EOF -test_expect_success 'unset with cont. lines is correct' 'cmp .git/config expect' +test_expect_success 'unset with cont. lines is correct' 'test_cmp expect .git/config' cat > .git/config << EOF [beta] ; silly comment # another comment @@ -116,7 +145,7 @@ noIndent= sillyValue ; 'nother silly comment [nextSection] noNewline = ouch EOF -test_expect_success 'multiple unset is correct' 'cmp .git/config expect' +test_expect_success 'multiple unset is correct' 'test_cmp expect .git/config' cp .git/config2 .git/config @@ -140,9 +169,7 @@ noIndent= sillyValue ; 'nother silly comment [nextSection] noNewline = ouch EOF -test_expect_success 'all replaced' 'cmp .git/config expect' - -git config beta.haha alpha +test_expect_success 'all replaced' 'test_cmp expect .git/config' cat > expect << EOF [beta] ; silly comment # another comment @@ -153,10 +180,10 @@ noIndent= sillyValue ; 'nother silly comment haha = alpha [nextSection] noNewline = ouch EOF - -test_expect_success 'really mean test' 'cmp .git/config expect' - -git config nextsection.nonewline wow +test_expect_success 'really mean test' ' + git config beta.haha alpha && + test_cmp expect .git/config +' cat > expect << EOF [beta] ; silly comment # another comment @@ -168,11 +195,12 @@ noIndent= sillyValue ; 'nother silly comment [nextSection] nonewline = wow EOF - -test_expect_success 'really really mean test' 'cmp .git/config expect' +test_expect_success 'really really mean test' ' + git config nextsection.nonewline wow && + test_cmp expect .git/config +' test_expect_success 'get value' 'test alpha = $(git config beta.haha)' -git config --unset beta.haha cat > expect << EOF [beta] ; silly comment # another comment @@ -183,10 +211,10 @@ noIndent= sillyValue ; 'nother silly comment [nextSection] nonewline = wow EOF - -test_expect_success 'unset' 'cmp .git/config expect' - -git config nextsection.NoNewLine "wow2 for me" "for me$" +test_expect_success 'unset' ' + git config --unset beta.haha && + test_cmp expect .git/config +' cat > expect << EOF [beta] ; silly comment # another comment @@ -198,8 +226,10 @@ noIndent= sillyValue ; 'nother silly comment nonewline = wow NoNewLine = wow2 for me EOF - -test_expect_success 'multivar' 'cmp .git/config expect' +test_expect_success 'multivar' ' + git config nextsection.NoNewLine "wow2 for me" "for me$" && + test_cmp expect .git/config +' test_expect_success 'non-match' \ 'git config --get nextsection.nonewline !for' @@ -214,8 +244,6 @@ test_expect_success 'ambiguous get' ' test_expect_success 'get multivar' \ 'git config --get-all nextsection.nonewline' -git config nextsection.nonewline "wow3" "wow$" - cat > expect << EOF [beta] ; silly comment # another comment noIndent= sillyValue ; 'nother silly comment @@ -226,8 +254,10 @@ noIndent= sillyValue ; 'nother silly comment nonewline = wow3 NoNewLine = wow2 for me EOF - -test_expect_success 'multivar replace' 'cmp .git/config expect' +test_expect_success 'multivar replace' ' + git config nextsection.nonewline "wow3" "wow$" && + test_cmp expect .git/config +' test_expect_success 'ambiguous value' ' test_must_fail git config nextsection.nonewline @@ -241,8 +271,6 @@ test_expect_success 'invalid unset' ' test_must_fail git config --unset somesection.nonewline ' -git config --unset nextsection.nonewline "wow3$" - cat > expect << EOF [beta] ; silly comment # another comment noIndent= sillyValue ; 'nother silly comment @@ -253,7 +281,10 @@ noIndent= sillyValue ; 'nother silly comment NoNewLine = wow2 for me EOF -test_expect_success 'multivar unset' 'cmp .git/config expect' +test_expect_success 'multivar unset' ' + git config --unset nextsection.nonewline "wow3$" && + test_cmp expect .git/config +' test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla' @@ -276,7 +307,7 @@ noIndent= sillyValue ; 'nother silly comment Alpha = beta EOF -test_expect_success 'hierarchical section value' 'cmp .git/config expect' +test_expect_success 'hierarchical section value' 'test_cmp expect .git/config' cat > expect << EOF beta.noindent=sillyValue @@ -304,15 +335,16 @@ EOF test_expect_success '--get-regexp' \ 'git config --get-regexp in > output && cmp output expect' -git config --add nextsection.nonewline "wow4 for you" - cat > expect << EOF wow2 for me wow4 for you EOF -test_expect_success '--add' \ - 'git config --get-all nextsection.nonewline > output && cmp output expect' +test_expect_success '--add' ' + git config --add nextsection.nonewline "wow4 for you" && + git config --get-all nextsection.nonewline > output && + test_cmp expect output +' cat > .git/config << EOF [novalue] @@ -333,6 +365,12 @@ test_expect_success 'get-regexp variable with no value' \ 'git config --get-regexp novalue > output && cmp output expect' +echo 'novalue.variable true' > expect + +test_expect_success 'get-regexp --bool variable with no value' \ + 'git config --bool --get-regexp novalue > output && + cmp output expect' + echo 'emptyvalue.variable ' > expect test_expect_success 'get-regexp variable with empty value' \ @@ -361,8 +399,6 @@ cat > .git/config << EOF c = d EOF -git config a.x y - cat > expect << EOF [a.b] c = d @@ -370,10 +406,10 @@ cat > expect << EOF x = y EOF -test_expect_success 'new section is partial match of another' 'cmp .git/config expect' - -git config b.x y -git config a.b c +test_expect_success 'new section is partial match of another' ' + git config a.x y && + test_cmp expect .git/config +' cat > expect << EOF [a.b] @@ -385,7 +421,11 @@ cat > expect << EOF x = y EOF -test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect' +test_expect_success 'new variable inserts into proper section' ' + git config b.x y && + git config a.b c && + test_cmp expect .git/config +' test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' \ 'test_must_fail git config --file non-existing-config -l' @@ -399,9 +439,10 @@ cat > expect << EOF ein.bahn=strasse EOF -GIT_CONFIG=other-config git config -l > output - -test_expect_success 'alternative GIT_CONFIG' 'cmp output expect' +test_expect_success 'alternative GIT_CONFIG' ' + GIT_CONFIG=other-config git config -l >output && + test_cmp expect output +' test_expect_success 'alternative GIT_CONFIG (--file)' \ 'git config --file other-config -l > output && cmp output expect' @@ -417,8 +458,6 @@ test_expect_success 'refer config from subdirectory' ' ' -GIT_CONFIG=other-config git config anwohner.park ausweis - cat > expect << EOF [ein] bahn = strasse @@ -426,7 +465,10 @@ cat > expect << EOF park = ausweis EOF -test_expect_success '--set in alternative GIT_CONFIG' 'cmp other-config expect' +test_expect_success '--set in alternative GIT_CONFIG' ' + GIT_CONFIG=other-config git config anwohner.park ausweis && + test_cmp expect other-config +' cat > .git/config << EOF # Hallo @@ -516,8 +558,6 @@ EOF test_expect_success "section was removed properly" \ "test_cmp expect .git/config" -rm .git/config - cat > expect << EOF [gitcvs] enabled = true @@ -528,10 +568,11 @@ EOF test_expect_success 'section ending' ' + rm -f .git/config && git config gitcvs.enabled true && git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && - cmp .git/config expect + test_cmp expect .git/config ' @@ -600,8 +641,6 @@ test_expect_success 'invalid bool (set)' ' test_must_fail git config --bool bool.nobool foobar' -rm .git/config - cat > expect <<\EOF [bool] true1 = true @@ -616,6 +655,7 @@ EOF test_expect_success 'set --bool' ' + rm -f .git/config && git config --bool bool.true1 01 && git config --bool bool.true2 -1 && git config --bool bool.true3 YeS && @@ -626,8 +666,6 @@ test_expect_success 'set --bool' ' git config --bool bool.false4 FALSE && cmp expect .git/config' -rm .git/config - cat > expect <<\EOF [int] val1 = 1 @@ -637,13 +675,12 @@ EOF test_expect_success 'set --int' ' + rm -f .git/config && git config --int int.val1 01 && git config --int int.val2 -1 && git config --int int.val3 5m && cmp expect .git/config' -rm .git/config - cat >expect <<\EOF [bool] true1 = true @@ -657,6 +694,7 @@ cat >expect <<\EOF EOF test_expect_success 'get --bool-or-int' ' + rm -f .git/config && ( echo "[bool]" echo true1 @@ -676,7 +714,6 @@ test_expect_success 'get --bool-or-int' ' ' -rm .git/config cat >expect <<\EOF [bool] true1 = true @@ -690,6 +727,7 @@ cat >expect <<\EOF EOF test_expect_success 'set --bool-or-int' ' + rm -f .git/config && git config --bool-or-int bool.true1 true && git config --bool-or-int bool.false1 false && git config --bool-or-int bool.true2 yes && @@ -700,8 +738,6 @@ test_expect_success 'set --bool-or-int' ' test_cmp expect .git/config ' -rm .git/config - cat >expect <<\EOF [path] home = ~/ @@ -710,6 +746,7 @@ cat >expect <<\EOF EOF test_expect_success NOT_MINGW 'set --path' ' + rm -f .git/config && git config --path path.home "~/" && git config --path path.normal "/dev/null" && git config --path path.trailingtilde "foo~" && @@ -750,13 +787,6 @@ test_expect_success NOT_MINGW 'get --path copes with unset $HOME' ' test_cmp expect result ' -rm .git/config - -git config quote.leading " test" -git config quote.ending "test " -git config quote.semicolon "test;test" -git config quote.hash "test#test" - cat > expect << EOF [quote] leading = " test" @@ -764,8 +794,14 @@ cat > expect << EOF semicolon = "test;test" hash = "test#test" EOF - -test_expect_success 'quoting' 'cmp .git/config expect' +test_expect_success 'quoting' ' + rm -f .git/config && + git config quote.leading " test" && + git config quote.ending "test " && + git config quote.semicolon "test;test" && + git config quote.hash "test#test" && + test_cmp expect .git/config +' test_expect_success 'key with newline' ' test_must_fail git config "key.with @@ -790,9 +826,10 @@ section.noncont=not continued section.quotecont=cont;inued EOF -git config --list > result - -test_expect_success 'value continued on next line' 'cmp result expect' +test_expect_success 'value continued on next line' ' + git config --list > result && + cmp result expect +' cat > .git/config <<\EOF [section "sub=section"] @@ -813,16 +850,17 @@ barQsection.sub=section.val3 Qsection.sub=section.val4 Qsection.sub=section.val5Q EOF +test_expect_success '--null --list' ' + git config --null --list | nul_to_q >result && + echo >>result && + test_cmp expect result +' -git config --null --list | perl -pe 'y/\000/Q/' > result -echo >>result - -test_expect_success '--null --list' 'cmp result expect' - -git config --null --get-regexp 'val[0-9]' | perl -pe 'y/\000/Q/' > result -echo >>result - -test_expect_success '--null --get-regexp' 'cmp result expect' +test_expect_success '--null --get-regexp' ' + git config --null --get-regexp "val[0-9]" | nul_to_q >result && + echo >>result && + test_cmp expect result +' test_expect_success 'inner whitespace kept verbatim' ' git config section.val "foo bar" && @@ -876,11 +914,50 @@ test_expect_success 'check split_cmdline return' " " test_expect_success 'git -c "key=value" support' ' - test "z$(git -c name=value config name)" = zvalue && test "z$(git -c core.name=value config core.name)" = zvalue && - test "z$(git -c CamelCase=value config camelcase)" = zvalue && - test "z$(git -c flag config --bool flag)" = ztrue && - test_must_fail git -c core.name=value config name + test "z$(git -c foo.CamelCase=value config foo.camelcase)" = zvalue && + test "z$(git -c foo.flag config --bool foo.flag)" = ztrue && + test_must_fail git -c name=value config core.name +' + +test_expect_success 'key sanity-checking' ' + test_must_fail git config foo=bar && + test_must_fail git config foo=.bar && + test_must_fail git config foo.ba=r && + test_must_fail git config foo.1bar && + test_must_fail git config foo."ba + z".bar && + test_must_fail git config . false && + test_must_fail git config .foo false && + test_must_fail git config foo. false && + test_must_fail git config .foo. false && + git config foo.bar true && + git config foo."ba =z".bar false +' + +test_expect_success 'git -c works with aliases of builtins' ' + git config alias.checkconfig "-c foo.check=bar config foo.check" && + echo bar >expect && + git checkconfig >actual && + test_cmp expect actual +' + +test_expect_success 'git -c does not split values on equals' ' + echo "value with = in it" >expect && + git -c core.foo="value with = in it" config core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'git -c dies on bogus config' ' + test_must_fail git -c core.bare=foo rev-parse +' + +test_expect_success 'git -c complains about empty key' ' + test_must_fail git -c "=foo" rev-parse +' + +test_expect_success 'git -c complains about empty key and value' ' + test_must_fail git -c "" rev-parse ' test_done diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh index 080117c6bc..46103a1591 100755 --- a/t/t1303-wacky-config.sh +++ b/t/t1303-wacky-config.sh @@ -44,7 +44,7 @@ LONG_VALUE=$(printf "x%01021dx a" 7) test_expect_success 'do not crash on special long config line' ' setup && git config section.key "$LONG_VALUE" && - check section.key "fatal: bad config file line 2 in .git/config" + check section.key "$LONG_VALUE" ' test_done diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh index b5d89a2250..2b962cfda7 100755 --- a/t/t1304-default-acl.sh +++ b/t/t1304-default-acl.sh @@ -25,6 +25,11 @@ else test_set_prereq SETFACL fi +if test -z "$LOGNAME" +then + LOGNAME=$USER +fi + check_perms_and_acl () { test -r "$1" && getfacl "$1" > actual && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index ff747f8229..4fd83a667a 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -6,7 +6,7 @@ test_description='Test git update-ref and basic ref logging' . ./test-lib.sh -Z=0000000000000000000000000000000000000000 +Z=$_z40 test_expect_success setup ' diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index 1b0f82fa4c..1ae4d87c92 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -5,28 +5,126 @@ test_description='Test git check-ref-format' . ./test-lib.sh valid_ref() { - test_expect_success "ref name '$1' is valid" \ - "git check-ref-format '$1'" + prereq= + case $1 in + [A-Z]*) + prereq=$1 + shift + esac + test_expect_success $prereq "ref name '$1' is valid${2:+ with options $2}" " + git check-ref-format $2 '$1' + " } invalid_ref() { - test_expect_success "ref name '$1' is not valid" \ - "test_must_fail git check-ref-format '$1'" + prereq= + case $1 in + [A-Z]*) + prereq=$1 + shift + esac + test_expect_success $prereq "ref name '$1' is invalid${2:+ with options $2}" " + test_must_fail git check-ref-format $2 '$1' + " } -valid_ref 'heads/foo' -invalid_ref 'foo' +invalid_ref '' +invalid_ref NOT_MINGW '/' +invalid_ref NOT_MINGW '/' --allow-onelevel +invalid_ref NOT_MINGW '/' --normalize +invalid_ref NOT_MINGW '/' '--allow-onelevel --normalize' valid_ref 'foo/bar/baz' -valid_ref 'refs///heads/foo' +valid_ref 'foo/bar/baz' --normalize +invalid_ref 'refs///heads/foo' +valid_ref 'refs///heads/foo' --normalize invalid_ref 'heads/foo/' +invalid_ref NOT_MINGW '/heads/foo' +valid_ref NOT_MINGW '/heads/foo' --normalize +invalid_ref '///heads/foo' +valid_ref '///heads/foo' --normalize invalid_ref './foo' +invalid_ref './foo/bar' +invalid_ref 'foo/./bar' +invalid_ref 'foo/bar/.' invalid_ref '.refs/foo' invalid_ref 'heads/foo..bar' invalid_ref 'heads/foo?bar' valid_ref 'foo./bar' invalid_ref 'heads/foo.lock' +invalid_ref 'heads///foo.lock' +invalid_ref 'foo.lock/bar' +invalid_ref 'foo.lock///bar' valid_ref 'heads/foo@bar' invalid_ref 'heads/v@{ation' invalid_ref 'heads/foo\bar' +invalid_ref "$(printf 'heads/foo\t')" +invalid_ref "$(printf 'heads/foo\177')" +valid_ref "$(printf 'heads/fu\303\237')" +invalid_ref 'heads/*foo/bar' --refspec-pattern +invalid_ref 'heads/foo*/bar' --refspec-pattern +invalid_ref 'heads/f*o/bar' --refspec-pattern + +ref='foo' +invalid_ref "$ref" +valid_ref "$ref" --allow-onelevel +invalid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' +invalid_ref "$ref" --normalize +valid_ref "$ref" '--allow-onelevel --normalize' + +ref='foo/bar' +valid_ref "$ref" +valid_ref "$ref" --allow-onelevel +valid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' +valid_ref "$ref" --normalize + +ref='foo/*' +invalid_ref "$ref" +invalid_ref "$ref" --allow-onelevel +valid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='*/foo' +invalid_ref "$ref" +invalid_ref "$ref" --allow-onelevel +valid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' +invalid_ref "$ref" --normalize +valid_ref "$ref" '--refspec-pattern --normalize' + +ref='foo/*/bar' +invalid_ref "$ref" +invalid_ref "$ref" --allow-onelevel +valid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='*' +invalid_ref "$ref" +invalid_ref "$ref" --allow-onelevel +invalid_ref "$ref" --refspec-pattern +valid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='foo/*/*' +invalid_ref "$ref" --refspec-pattern +invalid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='*/foo/*' +invalid_ref "$ref" --refspec-pattern +invalid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='*/*/foo' +invalid_ref "$ref" --refspec-pattern +invalid_ref "$ref" '--refspec-pattern --allow-onelevel' + +ref='/foo' +invalid_ref NOT_MINGW "$ref" +invalid_ref NOT_MINGW "$ref" --allow-onelevel +invalid_ref NOT_MINGW "$ref" --refspec-pattern +invalid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel' +invalid_ref NOT_MINGW "$ref" --normalize +valid_ref NOT_MINGW "$ref" '--allow-onelevel --normalize' +invalid_ref NOT_MINGW "$ref" '--refspec-pattern --normalize' +valid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize' test_expect_success "check-ref-format --branch @{-1}" ' T=$(git write-tree) && @@ -59,20 +157,41 @@ test_expect_success 'check-ref-format --branch from subdir' ' ' valid_ref_normalized() { - test_expect_success "ref name '$1' simplifies to '$2'" " - refname=\$(git check-ref-format --print '$1') && - test \"\$refname\" = '$2'" + prereq= + case $1 in + [A-Z]*) + prereq=$1 + shift + esac + test_expect_success $prereq "ref name '$1' simplifies to '$2'" " + refname=\$(git check-ref-format --normalize '$1') && + test \"\$refname\" = '$2' + " } invalid_ref_normalized() { - test_expect_success "check-ref-format --print rejects '$1'" " - test_must_fail git check-ref-format --print '$1'" + prereq= + case $1 in + [A-Z]*) + prereq=$1 + shift + esac + test_expect_success $prereq "check-ref-format --normalize rejects '$1'" " + test_must_fail git check-ref-format --normalize '$1' + " } valid_ref_normalized 'heads/foo' 'heads/foo' valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo' +valid_ref_normalized NOT_MINGW '/heads/foo' 'heads/foo' +valid_ref_normalized '///heads/foo' 'heads/foo' invalid_ref_normalized 'foo' +invalid_ref_normalized NOT_MINGW '/foo' invalid_ref_normalized 'heads/foo/../bar' invalid_ref_normalized 'heads/./foo' invalid_ref_normalized 'heads\foo' +invalid_ref_normalized 'heads/foo.lock' +invalid_ref_normalized 'heads///foo.lock' +invalid_ref_normalized 'foo.lock/bar' +invalid_ref_normalized 'foo.lock///bar' test_done diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh index ba25ff354d..caa687b5b4 100755 --- a/t/t1411-reflog-show.sh +++ b/t/t1411-reflog-show.sh @@ -28,6 +28,24 @@ test_expect_success 'oneline reflog format' ' test_cmp expect actual ' +test_expect_success 'reflog default format' ' + git reflog -1 >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +commit e46513e +Reflog: HEAD@{0} (C O Mitter <committer@example.com>) +Reflog message: commit (initial): one +Author: A U Thor <author@example.com> + + one +EOF +test_expect_success 'override reflog default format' ' + git reflog --format=short -1 >actual && + test_cmp expect actual +' + cat >expect <<'EOF' Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>) Reflog message: commit (initial): one diff --git a/t/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index 7f519e5ebe..647d888507 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -21,10 +21,10 @@ test_expect_success 'setup reflog with alternating commits' ' test_expect_success 'reflog shows all entries' ' cat >expect <<-\EOF - topic@{0} two: updating HEAD - topic@{1} one: updating HEAD - topic@{2} two: updating HEAD - topic@{3} one: updating HEAD + topic@{0} reset: moving to two + topic@{1} reset: moving to one + topic@{2} reset: moving to two + topic@{3} reset: moving to one topic@{4} branch: Created from HEAD EOF git log -g --format="%gd %gs" topic >actual && diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index bb01d5ab8f..523ce9c45b 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -110,6 +110,42 @@ test_expect_success 'email with embedded > is not okay' ' grep "error in commit $new" out ' +test_expect_success 'missing < email delimiter is reported nicely' ' + git cat-file commit HEAD >basis && + sed "s/<//" basis >bad-email-2 && + new=$(git hash-object -t commit -w --stdin <bad-email-2) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + grep "error in commit $new.* - bad name" out +' + +test_expect_success 'missing email is reported nicely' ' + git cat-file commit HEAD >basis && + sed "s/[a-z]* <[^>]*>//" basis >bad-email-3 && + new=$(git hash-object -t commit -w --stdin <bad-email-3) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + grep "error in commit $new.* - missing email" out +' + +test_expect_success '> in name is reported' ' + git cat-file commit HEAD >basis && + sed "s/ </> </" basis >bad-email-4 && + new=$(git hash-object -t commit -w --stdin <bad-email-4) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + grep "error in commit $new" out +' + test_expect_success 'tag pointing to nonexistent' ' cat >invalid-tag <<-\EOF && object ffffffffffffffffffffffffffffffffffffffff diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index da6252b117..63849836c8 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -7,7 +7,6 @@ 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/") && @@ -239,10 +238,10 @@ test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' ' 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 + :000000 100644 $_z40 $EMPTY_BLOB A sub/dir/tracked EOF cat >diff-index.expected <<-EOF && - :000000 100644 $ZEROES $ZEROES A sub/dir/tracked + :000000 100644 $_z40 $_z40 A sub/dir/tracked EOF ( @@ -258,7 +257,7 @@ test_expect_success 'diff-index respects work tree under .git dir' ' 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 + :100644 100644 $EMPTY_BLOB $_z40 M sub/dir/tracked EOF ( diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 9f8adb1f82..0843a1c13b 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -6,6 +6,16 @@ exec </dev/null . ./test-lib.sh +test_did_you_mean () +{ + sq="'" && + cat >expected <<-EOF && + fatal: Path '$2$3' $4, but not ${5:-$sq$3$sq}. + Did you mean '$1:$2$3'${2:+ aka $sq$1:./$3$sq}? + EOF + test_cmp expected error +} + HASH_file= test_expect_success 'set up basic repo' ' @@ -106,7 +116,7 @@ test_expect_success 'incorrect file in sha1:path' ' grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error && (cd subdir && test_must_fail git rev-parse HEAD:file2.txt 2> error && - grep "Did you mean '"'"'HEAD:subdir/file2.txt'"'"'?" error ) + test_did_you_mean HEAD subdir/ file2.txt exists ) ' test_expect_success 'incorrect file in :path and :N:path' ' @@ -115,14 +125,14 @@ test_expect_success 'incorrect file in :path and :N:path' ' test_must_fail git rev-parse :1:nothing.txt 2> error && grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error && test_must_fail git rev-parse :1:file.txt 2> error && - grep "Did you mean '"'"':0:file.txt'"'"'?" error && + test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" && (cd subdir && test_must_fail git rev-parse :1:file.txt 2> error && - grep "Did you mean '"'"':0:file.txt'"'"'?" error && + test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" && test_must_fail git rev-parse :file2.txt 2> error && - grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error && + test_did_you_mean ":0" subdir/ file2.txt "is in the index" && test_must_fail git rev-parse :2:file2.txt 2> error && - grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error) && + test_did_you_mean :0 subdir/ file2.txt "is in the index") && test_must_fail git rev-parse :disk-only.txt 2> error && grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error ' diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh index 15101d5e03..ec50a9ad70 100755 --- a/t/t1510-repo-setup.sh +++ b/t/t1510-repo-setup.sh @@ -57,7 +57,7 @@ test_repo () { export GIT_WORK_TREE fi && rm -f trace && - GIT_TRACE="$(pwd)/trace" git symbolic-ref HEAD >/dev/null && + GIT_TRACE_SETUP="$(pwd)/trace" git symbolic-ref HEAD >/dev/null && grep '^setup: ' trace >result && test_cmp expected result ) diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh index 15ebdc26eb..300f8bf25c 100755 --- a/t/t2011-checkout-invalid-head.sh +++ b/t/t2011-checkout-invalid-head.sh @@ -15,7 +15,7 @@ test_expect_success 'checkout should not start branch from a tree' ' ' test_expect_success 'checkout master from invalid HEAD' ' - echo 0000000000000000000000000000000000000000 >.git/HEAD && + echo $_z40 >.git/HEAD && git checkout master -- ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index fa69016381..75874e85df 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -118,6 +118,15 @@ test_expect_success 'checkout -b to an existing branch fails' ' test_must_fail do_checkout branch2 $HEAD2 ' +test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' + git reset --hard HEAD && + git checkout branch1 && + git checkout branch2 && + echo >expect "fatal: A branch named '\''branch1'\'' already exists." && + test_must_fail git checkout -b @{-1} 2>actual && + test_cmp expect actual +' + test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' git checkout branch1 && @@ -169,4 +178,23 @@ test_expect_success 'checkout -f -B to an existing branch with mergeable changes test_must_fail test_dirty_mergeable ' +test_expect_success 'checkout -b <describe>' ' + git tag -f -m "First commit" initial initial && + git checkout -f change1 && + name=$(git describe) && + git checkout -b $name && + git diff --exit-code change1 && + echo "refs/heads/$name" >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'checkout -B to the current branch fails before merging' ' + git checkout branch1 && + setup_dirty_mergeable && + git commit -mfooble && + test_must_fail git checkout -B branch1 initial && + test_must_fail test_dirty_mergeable +' + test_done diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh new file mode 100755 index 0000000000..b99d5192a9 --- /dev/null +++ b/t/t2019-checkout-ambiguous-ref.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +test_description='checkout handling of ambiguous (branch/tag) refs' +. ./test-lib.sh + +test_expect_success 'setup ambiguous refs' ' + test_commit branch file && + git branch ambiguity && + git branch vagueness && + test_commit tag file && + git tag ambiguity && + git tag vagueness HEAD:file && + test_commit other file +' + +test_expect_success 'checkout ambiguous ref succeeds' ' + git checkout ambiguity >stdout 2>stderr +' + +test_expect_success 'checkout produces ambiguity warning' ' + grep "warning.*ambiguous" stderr +' + +test_expect_success 'checkout chooses branch over tag' ' + echo refs/heads/ambiguity >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual && + echo branch >expect && + test_cmp expect file +' + +test_expect_success 'checkout reports switch to branch' ' + test_i18ngrep "Switched to branch" stderr && + test_i18ngrep ! "^HEAD is now at" stderr +' + +test_expect_success 'checkout vague ref succeeds' ' + git checkout vagueness >stdout 2>stderr && + test_set_prereq VAGUENESS_SUCCESS +' + +test_expect_success VAGUENESS_SUCCESS 'checkout produces ambiguity warning' ' + grep "warning.*ambiguous" stderr +' + +test_expect_success VAGUENESS_SUCCESS 'checkout chooses branch over tag' ' + echo refs/heads/vagueness >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual && + echo branch >expect && + test_cmp expect file +' + +test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' ' + test_i18ngrep "Switched to branch" stderr && + test_i18ngrep ! "^HEAD is now at" stderr +' + +test_done diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh new file mode 100755 index 0000000000..068fba4c8e --- /dev/null +++ b/t/t2020-checkout-detach.sh @@ -0,0 +1,154 @@ +#!/bin/sh + +test_description='checkout into detached HEAD state' +. ./test-lib.sh + +check_detached () { + test_must_fail git symbolic-ref -q HEAD >/dev/null +} + +check_not_detached () { + git symbolic-ref -q HEAD >/dev/null +} + +ORPHAN_WARNING='you are leaving .* commit.*behind' +PREV_HEAD_DESC='Previous HEAD position was' +check_orphan_warning() { + test_i18ngrep "$ORPHAN_WARNING" "$1" && + test_i18ngrep ! "$PREV_HEAD_DESC" "$1" +} +check_no_orphan_warning() { + test_i18ngrep ! "$ORPHAN_WARNING" "$1" && + test_i18ngrep "$PREV_HEAD_DESC" "$1" +} + +reset () { + git checkout master && + check_not_detached +} + +test_expect_success 'setup' ' + test_commit one && + test_commit two && + test_commit three && git tag -d three && + test_commit four && git tag -d four && + git branch branch && + git tag tag +' + +test_expect_success 'checkout branch does not detach' ' + reset && + git checkout branch && + check_not_detached +' + +test_expect_success 'checkout tag detaches' ' + reset && + git checkout tag && + check_detached +' + +test_expect_success 'checkout branch by full name detaches' ' + reset && + git checkout refs/heads/branch && + check_detached +' + +test_expect_success 'checkout non-ref detaches' ' + reset && + git checkout branch^ && + check_detached +' + +test_expect_success 'checkout ref^0 detaches' ' + reset && + git checkout branch^0 && + check_detached +' + +test_expect_success 'checkout --detach detaches' ' + reset && + git checkout --detach branch && + check_detached +' + +test_expect_success 'checkout --detach without branch name' ' + reset && + git checkout --detach && + check_detached +' + +test_expect_success 'checkout --detach errors out for non-commit' ' + reset && + test_must_fail git checkout --detach one^{tree} && + check_not_detached +' + +test_expect_success 'checkout --detach errors out for extra argument' ' + reset && + git checkout master && + test_must_fail git checkout --detach tag one.t && + check_not_detached +' + +test_expect_success 'checkout --detached and -b are incompatible' ' + reset && + test_must_fail git checkout --detach -b newbranch tag && + check_not_detached +' + +test_expect_success 'checkout --detach moves HEAD' ' + reset && + git checkout one && + git checkout --detach two && + git diff --exit-code HEAD && + git diff --exit-code two +' + +test_expect_success 'checkout warns on orphan commits' ' + reset && + git checkout --detach two && + echo content >orphan && + git add orphan && + git commit -a -m orphan && + git checkout master 2>stderr +' + +test_expect_success 'checkout warns on orphan commits: output' ' + check_orphan_warning stderr +' + +test_expect_success 'checkout does not warn leaving ref tip' ' + reset && + git checkout --detach two && + git checkout master 2>stderr +' + +test_expect_success 'checkout does not warn leaving ref tip' ' + check_no_orphan_warning stderr +' + +test_expect_success 'checkout does not warn leaving reachable commit' ' + reset && + git checkout --detach HEAD^ && + git checkout master 2>stderr +' + +test_expect_success 'checkout does not warn leaving reachable commit' ' + check_no_orphan_warning stderr +' + +cat >expect <<'EOF' +Your branch is behind 'master' by 1 commit, and can be fast-forwarded. +EOF +test_expect_success 'tracking count is accurate after orphan check' ' + reset && + git branch child master^ && + git config branch.child.remote . && + git config branch.child.merge refs/heads/master && + git checkout child^ && + git checkout child >stdout && + test_cmp expect stdout +' + +test_done diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh new file mode 100755 index 0000000000..5da63e9fa2 --- /dev/null +++ b/t/t2021-checkout-overwrite.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='checkout must not overwrite an untracked objects' +. ./test-lib.sh + +test_expect_success 'setup' ' + + mkdir -p a/b/c && + >a/b/c/d && + git add -A && + git commit -m base && + git tag start +' + +test_expect_success 'create a commit where dir a/b changed to file' ' + + git checkout -b file && + rm -rf a/b && + >a/b && + git add -A && + git commit -m "dir to file" +' + +test_expect_success 'checkout commit with dir must not remove untracked a/b' ' + + git rm --cached a/b && + git commit -m "un-track the file" && + test_must_fail git checkout start && + test -f a/b +' + +test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' ' + + rm -rf a/b && # cleanup if previous test failed + git checkout -f -b symlink start && + rm -rf a/b && + ln -s foo a/b && + git add -A && + git commit -m "dir to symlink" +' + +test_expect_success SYMLINKS 'checkout commit with dir must not remove untracked a/b' ' + + git rm --cached a/b && + git commit -m "un-track the symlink" && + test_must_fail git checkout start && + test -h a/b +' + +test_done diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh new file mode 100755 index 0000000000..56090d2eba --- /dev/null +++ b/t/t2022-checkout-paths.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='checkout $tree -- $paths' +. ./test-lib.sh + +test_expect_success setup ' + mkdir dir && + >dir/master && + echo common >dir/common && + git add dir/master dir/common && + test_tick && git commit -m "master has dir/master" && + git checkout -b next && + git mv dir/master dir/next0 && + echo next >dir/next1 && + git add dir && + test_tick && git commit -m "next has dir/next but not dir/master" +' + +test_expect_success 'checking out paths out of a tree does not clobber unrelated paths' ' + git checkout next && + git reset --hard && + rm dir/next0 && + cat dir/common >expect.common && + echo modified >expect.next1 && + cat expect.next1 >dir/next1 && + echo untracked >expect.next2 && + cat expect.next2 >dir/next2 && + + git checkout master dir && + + test_cmp expect.common dir/common && + test_path_is_file dir/master && + git diff --exit-code master dir/master && + + test_path_is_missing dir/next0 && + test_cmp expect.next1 dir/next1 && + test_path_is_file dir/next2 && + test_must_fail git ls-files --error-unmatch dir/next2 && + test_cmp expect.next2 dir/next2 +' + +test_done diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index 0692427cb6..4cdebda6a5 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -124,7 +124,7 @@ test_expect_success 'add -n -u should not add but just report' ' after=$(git ls-files -s check top) && test "$before" = "$after" && - test_cmp expect actual + test_i18ncmp expect actual ' @@ -149,31 +149,21 @@ test_expect_success 'add -u resolves unmerged paths' ' echo 3 >path1 && echo 2 >path3 && echo 2 >path5 && - git add -u && - git ls-files -s path1 path2 path3 path4 path5 path6 >actual && - { - echo "100644 $three 0 path1" - echo "100644 $one 1 path3" - echo "100644 $one 1 path4" - echo "100644 $one 3 path5" - echo "100644 $one 3 path6" - } >expect && - test_cmp expect actual && - # Bonus tests. Explicit resolving - git add path3 path5 && + # Explicit resolving by adding removed paths should fail test_must_fail git add path4 && test_must_fail git add path6 && - git rm path4 && - git rm path6 && - git ls-files -s "path?" >actual && + # "add -u" should notice removals no matter what stages + # the index entries are in. + git add -u && + git ls-files -s path1 path2 path3 path4 path5 path6 >actual && { echo "100644 $three 0 path1" echo "100644 $two 0 path3" echo "100644 $two 0 path5" - } >expect - + } >expect && + test_cmp expect actual ' test_expect_success '"add -u non-existent" should fail' ' diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh index 2e8f702452..954fc51e5b 100755 --- a/t/t2201-add-update-typechange.sh +++ b/t/t2201-add-update-typechange.sh @@ -4,8 +4,6 @@ test_description='more git add -u' . ./test-lib.sh -_z40=0000000000000000000000000000000000000000 - test_expect_success setup ' >xyzzy && _empty=$(git hash-object --stdin <xyzzy) && diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh index 24afdabab7..8340ac2f07 100755 --- a/t/t2204-add-ignored.sh +++ b/t/t2204-add-ignored.sh @@ -31,18 +31,21 @@ do rm -f .git/index && test_must_fail git add "$i" 2>err && git ls-files "$i" >out && - ! test -s out && - grep -e "Use -f if" err && - cat err + ! test -s out + ' + + test_expect_success "complaints for ignored $i output" ' + test_i18ngrep -e "Use -f if" err ' test_expect_success "complaints for ignored $i with unignored file" ' rm -f .git/index && test_must_fail git add "$i" file 2>err && git ls-files "$i" >out && - ! test -s out && - grep -e "Use -f if" err && - cat err + ! test -s out + ' + test_expect_success "complaints for ignored $i with unignored file output" ' + test_i18ngrep -e "Use -f if" err ' done @@ -54,9 +57,14 @@ do cd dir && test_must_fail git add "$i" 2>err && git ls-files "$i" >out && - ! test -s out && - grep -e "Use -f if" err && - cat err + ! test -s out + ) + ' + + test_expect_success "complaints for ignored $i in dir output" ' + ( + cd dir && + test_i18ngrep -e "Use -f if" err ) ' done @@ -69,9 +77,14 @@ do cd sub && test_must_fail git add "$i" 2>err && git ls-files "$i" >out && - ! test -s out && - grep -e "Use -f if" err && - cat err + ! test -s out + ) + ' + + test_expect_success "complaints for ignored $i in sub output" ' + ( + cd sub && + test_i18ngrep -e "Use -f if" err ) ' done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 2eec0118c4..88be904c09 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -65,4 +65,23 @@ test_expect_success '--no-empty-directory hides empty directory' ' test_cmp expected3 output ' +test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' ' + git init super && + git init sub && + ( + cd sub && + >a && + git add a && + git commit -m sub && + git pack-refs --all + ) && + ( + cd super && + "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" ../sub sub + git ls-files --others --exclude-standard >../actual + ) && + echo sub/ >expect && + test_cmp expect actual +' + test_done diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh new file mode 100755 index 0000000000..377869432e --- /dev/null +++ b/t/t3005-ls-files-relative.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +test_description='ls-files tests with relative paths + +This test runs git ls-files with various relative path arguments. +' + +. ./test-lib.sh + +new_line=' +' +sq=\' + +test_expect_success 'prepare' ' + : >never-mind-me && + git add never-mind-me && + mkdir top && + ( + cd top && + mkdir sub && + x="x xa xbc xdef xghij xklmno" && + y=$(echo "$x" | tr x y) && + touch $x && + touch $y && + cd sub && + git add ../x* + ) +' + +test_expect_success 'ls-files with mixed levels' ' + ( + cd top/sub && + cat >expect <<-EOF && + ../../never-mind-me + ../x + EOF + git ls-files $(cat expect) >actual && + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -c' ' + ( + cd top/sub && + for f in ../y* + do + echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + done >expect.err && + echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + ls ../x* >expect.out && + test_must_fail git ls-files -c --error-unmatch ../[xy]* >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err + ) +' + +test_expect_success 'ls-files -o' ' + ( + cd top/sub && + for f in ../x* + do + echo "error: pathspec $sq$f$sq did not match any file(s) known to git." + done >expect.err && + echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + ls ../y* >expect.out && + test_must_fail git ls-files -o --error-unmatch ../[xy]* >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err + ) +' + +test_done diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 34794f8a70..55ef1895d7 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -267,7 +267,8 @@ test_expect_success 'setup 8' ' ln -s e a && git add a e && test_tick && - git commit -m "rename a->e, symlink a->e" + git commit -m "rename a->e, symlink a->e" && + oln=`printf e | git hash-object --stdin` fi ' @@ -319,13 +320,13 @@ test_expect_success 'fail if the index has unresolved entries' ' test_must_fail git merge "$c5" && test_must_fail git merge "$c5" 2> out && - grep "not possible because you have unmerged files" out && + test_i18ngrep "not possible because you have unmerged files" out && git add -u && test_must_fail git merge "$c5" 2> out && - grep "You have not concluded your merge" out && + test_i18ngrep "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 the following files would be overwritten by merge:" out + test_i18ngrep "Your local changes to the following files would be overwritten by merge:" out ' test_expect_success 'merge-recursive remove conflict' ' @@ -630,16 +631,18 @@ test_expect_success 'merge-recursive copy vs. rename' ' if test_have_prereq SYMLINKS then - test_expect_success 'merge-recursive rename vs. rename/symlink' ' + test_expect_failure 'merge-recursive rename vs. rename/symlink' ' git checkout -f rename && git merge rename-ln && ( git ls-tree -r HEAD ; git ls-files -s ) >actual && ( + echo "120000 blob $oln a" echo "100644 blob $o0 b" echo "100644 blob $o0 c" echo "100644 blob $o0 d/e" echo "100644 blob $o0 e" + echo "120000 $oln 0 a" echo "100644 $o0 0 b" echo "100644 $o0 0 c" echo "100644 $o0 0 d/e" diff --git a/t/t3032-merge-recursive-options.sh b/t/t3032-merge-recursive-options.sh index 44f5421be4..2b17311cb0 100755 --- a/t/t3032-merge-recursive-options.sh +++ b/t/t3032-merge-recursive-options.sh @@ -110,6 +110,20 @@ test_expect_success '--ignore-space-change makes merge succeed' ' git merge-recursive --ignore-space-change HEAD^ -- HEAD remote ' +test_expect_success 'naive cherry-pick fails' ' + git read-tree --reset -u HEAD && + test_must_fail git cherry-pick --no-commit remote && + git read-tree --reset -u HEAD && + test_must_fail git cherry-pick remote && + test_must_fail git update-index --refresh && + grep "<<<<<<" text.txt +' + +test_expect_success '-Xignore-space-change makes cherry-pick succeed' ' + git read-tree --reset -u HEAD && + git cherry-pick --no-commit -Xignore-space-change remote +' + test_expect_success '--ignore-space-change: our w/s-only change wins' ' q_to_cr <<-\EOF >expected && justice and holiness and is the nurse of his age and theQ diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh new file mode 100755 index 0000000000..c286854485 --- /dev/null +++ b/t/t3102-ls-tree-wildcards.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +test_description='ls-tree with(out) globs' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir a aa "a[a]" && + touch a/one aa/two "a[a]/three" && + git add a/one aa/two "a[a]/three" && + git commit -m test +' + +test_expect_success 'ls-tree a[a] matches literally' ' + cat >expected <<EOF && +100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a[a]/three +EOF + git ls-tree -r HEAD "a[a]" >actual && + test_cmp expected actual +' + +test_done diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh new file mode 100755 index 0000000000..09dcf043fd --- /dev/null +++ b/t/t3103-ls-tree-misc.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +test_description=' +Miscellaneous tests for git ls-tree. + + 1. git ls-tree fails in presence of tree damage. + +' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir a && + touch a/one && + git add a/one && + git commit -m test +' + +test_expect_success 'ls-tree fails with non-zero exit code on broken tree' ' + rm -f .git/objects/5f/cffbd6e4c5c5b8d81f5e9314b20e338e3ffff5 && + test_must_fail git ls-tree -r HEAD +' + +test_done diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index f308235f5d..2f5eada0d2 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -23,7 +23,7 @@ test_expect_success \ test_expect_success \ 'git branch --help should not have created a bogus branch' ' git branch --help </dev/null >/dev/null 2>/dev/null; - ! test -f .git/refs/heads/--help + test_path_is_missing .git/refs/heads/--help ' test_expect_success 'branch -h in broken repository' ' @@ -39,28 +39,28 @@ test_expect_success 'branch -h in broken repository' ' test_expect_success \ 'git branch abc should create a branch' \ - 'git branch abc && test -f .git/refs/heads/abc' + 'git branch abc && test_path_is_file .git/refs/heads/abc' test_expect_success \ 'git branch a/b/c should create a branch' \ - 'git branch a/b/c && test -f .git/refs/heads/a/b/c' + 'git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c' cat >expect <<EOF -0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master +$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master EOF test_expect_success \ 'git branch -l d/e/f should create a branch and a log' \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ git branch -l d/e/f && - test -f .git/refs/heads/d/e/f && - test -f .git/logs/refs/heads/d/e/f && + test_path_is_file .git/refs/heads/d/e/f && + test_path_is_file .git/logs/refs/heads/d/e/f && test_cmp expect .git/logs/refs/heads/d/e/f' test_expect_success \ 'git branch -d d/e/f should delete a branch and a log' \ 'git branch -d d/e/f && - test ! -f .git/refs/heads/d/e/f && - test ! -f .git/logs/refs/heads/d/e/f' + test_path_is_missing .git/refs/heads/d/e/f && + test_path_is_missing .git/logs/refs/heads/d/e/f' test_expect_success \ 'git branch j/k should work after branch j has been deleted' \ @@ -78,13 +78,13 @@ test_expect_success \ 'git branch -m m m/m should work' \ 'git branch -l m && git branch -m m m/m && - test -f .git/logs/refs/heads/m/m' + test_path_is_file .git/logs/refs/heads/m/m' test_expect_success \ 'git branch -m n/n n should work' \ 'git branch -l n/n && git branch -m n/n n - test -f .git/logs/refs/heads/n' + test_path_is_file .git/logs/refs/heads/n' test_expect_success 'git branch -m o/o o should fail when o/p exists' ' git branch o/o && @@ -98,6 +98,50 @@ test_expect_success 'git branch -m q r/q should fail when r exists' ' test_must_fail git branch -m q r/q ' +test_expect_success 'git branch -M foo bar should fail when bar is checked out' ' + git branch bar && + git checkout -b foo && + test_must_fail git branch -M bar foo +' + +test_expect_success 'git branch -M baz bam should succeed when baz is checked out' ' + git checkout -b baz && + git branch bam && + git branch -M baz bam +' + +test_expect_success 'git branch -v -d t should work' ' + git branch t && + test_path_is_file .git/refs/heads/t && + git branch -v -d t && + test_path_is_missing .git/refs/heads/t +' + +test_expect_success 'git branch -v -m t s should work' ' + git branch t && + test_path_is_file .git/refs/heads/t && + git branch -v -m t s && + test_path_is_missing .git/refs/heads/t && + test_path_is_file .git/refs/heads/s && + git branch -d s +' + +test_expect_success 'git branch -m -d t s should fail' ' + git branch t && + test_path_is_file .git/refs/heads/t && + test_must_fail git branch -m -d t s && + git branch -d t && + test_path_is_missing .git/refs/heads/t +' + +test_expect_success 'git branch --list -d t should fail' ' + git branch t && + test_path_is_file .git/refs/heads/t && + test_must_fail git branch --list -d t && + git branch -d t && + test_path_is_missing .git/refs/heads/t +' + mv .git/config .git/config-saved test_expect_success 'git branch -m q q2 without config should succeed' ' @@ -112,12 +156,12 @@ git config branch.s/s.dummy Hello test_expect_success \ 'git branch -m s/s s should work when s/t is deleted' \ 'git branch -l s/s && - test -f .git/logs/refs/heads/s/s && + test_path_is_file .git/logs/refs/heads/s/s && git branch -l s/t && - test -f .git/logs/refs/heads/s/t && + test_path_is_file .git/logs/refs/heads/s/t && git branch -d s/t && git branch -m s/s s && - test -f .git/logs/refs/heads/s' + test_path_is_file .git/logs/refs/heads/s' test_expect_success 'config information was renamed, too' \ "test $(git config branch.s.dummy) = Hello && @@ -128,8 +172,8 @@ test_expect_success 'renaming a symref is not allowed' \ git symbolic-ref refs/heads/master2 refs/heads/master && test_must_fail git branch -m master2 master3 && git symbolic-ref refs/heads/master2 && - test -f .git/refs/heads/master && - ! test -f .git/refs/heads/master3 + test_path_is_file .git/refs/heads/master && + test_path_is_missing .git/refs/heads/master3 ' test_expect_success SYMLINKS \ @@ -206,7 +250,9 @@ test_expect_success 'test deleting branch deletes branch config' \ test_expect_success 'test deleting branch without config' \ 'git branch my7 s && sha1=$(git rev-parse my7 | cut -c 1-7) && - test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."' + echo "Deleted branch my7 (was $sha1)." >expect && + git branch -d my7 >actual 2>&1 && + test_i18ncmp expect actual' test_expect_success 'test --track without .fetch entries' \ 'git branch --track my8 && @@ -223,16 +269,21 @@ test_expect_success \ 'branch from non-branch HEAD w/--track causes failure' \ 'test_must_fail git branch --track my10 HEAD^' +test_expect_success \ + 'branch from tag w/--track causes failure' \ + 'git tag foobar && + test_must_fail git branch --track my11 foobar' + # Keep this test last, as it changes the current branch cat >expect <<EOF -0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master +$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master EOF test_expect_success \ 'git checkout -b g/h/i -l should create a branch and a log' \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ git checkout -b g/h/i -l master && - test -f .git/refs/heads/g/h/i && - test -f .git/logs/refs/heads/g/h/i && + test_path_is_file .git/refs/heads/g/h/i && + test_path_is_file .git/logs/refs/heads/g/h/i && test_cmp expect .git/logs/refs/heads/g/h/i' test_expect_success 'checkout -b makes reflog by default' ' @@ -488,6 +539,15 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' ' test "z$(git config branch.myr20.rebase)" = z ' +test_expect_success 'autosetuprebase always on detached HEAD' ' + git config branch.autosetupmerge always && + test_when_finished git checkout master && + git checkout HEAD^0 && + git branch my11 && + test -z "$(git config branch.my11.remote)" && + test -z "$(git config branch.my11.merge)" +' + test_expect_success 'detect misconfigured autosetuprebase (bad value)' ' git config branch.autosetuprebase garbage && test_must_fail git branch @@ -526,4 +586,17 @@ test_expect_success 'attempt to delete a branch merged to its base' ' test_must_fail git branch -d my10 ' +test_expect_success 'use set-upstream on the current branch' ' + git checkout master && + git --bare init myupstream.git && + git push myupstream.git master:refs/heads/frotz && + git remote add origin myupstream.git && + git fetch && + git branch --set-upstream master origin/frotz && + + test "z$(git config branch.master.remote)" = "zorigin" && + test "z$(git config branch.master.merge)" = "zrefs/heads/frotz" + +' + test_done diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 6028748c6c..76fe7e0060 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -32,6 +32,20 @@ test_expect_success 'git branch shows local branches' ' test_cmp expect actual ' +test_expect_success 'git branch --list shows local branches' ' + git branch --list >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' + branch-one + branch-two +EOF +test_expect_success 'git branch --list pattern shows matching local branches' ' + git branch --list branch* >actual && + test_cmp expect actual +' + cat >expect <<'EOF' origin/HEAD -> origin/branch-one origin/branch-one @@ -67,6 +81,20 @@ test_expect_success 'git branch -v shows branch summaries' ' ' cat >expect <<'EOF' +two +one +EOF +test_expect_success 'git branch --list -v pattern shows branch summaries' ' + git branch --list -v branch* >tmp && + awk "{print \$NF}" <tmp >actual && + test_cmp expect actual +' + +test_expect_success 'git branch -v pattern does not show branch summaries' ' + test_must_fail git branch -v branch* +' + +cat >expect <<'EOF' * (no branch) branch-one branch-two @@ -75,7 +103,7 @@ EOF test_expect_success 'git branch shows detached HEAD properly' ' git checkout HEAD^0 && git branch >actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_done diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 1921ca3a73..16de05aff9 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -101,8 +101,8 @@ test_expect_success 'edit existing notes' ' test_must_fail git notes show HEAD^ ' -test_expect_success 'cannot add note where one exists' ' - ! MSG=b2 git notes add && +test_expect_success 'cannot "git notes add -m" where notes already exists' ' + test_must_fail git notes add -m "b2" && test ! -f .git/NOTES_EDITMSG && test 1 = $(git ls-tree refs/notes/commits | wc -l) && test b3 = $(git notes show) && @@ -110,6 +110,24 @@ test_expect_success 'cannot add note where one exists' ' test_must_fail git notes show HEAD^ ' +test_expect_success 'can overwrite existing note with "git notes add -f -m"' ' + git notes add -f -m "b1" && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b1 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + +test_expect_success 'add w/no options on existing note morphs into edit' ' + MSG=b2 git notes add && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b2 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + test_expect_success 'can overwrite existing note with "git notes add -f"' ' MSG=b1 git notes add -f && test ! -f .git/NOTES_EDITMSG && @@ -194,6 +212,13 @@ test_expect_success 'show -F notes' ' test_cmp expect-F output ' +test_expect_success 'Re-adding -F notes without -f fails' ' + echo "zyxxy" > note5 && + test_must_fail git notes add -F note5 && + git log -3 > output && + test_cmp expect-F output +' + cat >expect << EOF commit 15023535574ded8b1a89052b32673f84cf9582b8 tree e070e3af51011e47b183c33adf9736736a525709 @@ -247,6 +272,44 @@ do ' done +test_expect_success 'setup alternate notes ref' ' + git notes --ref=alternate add -m alternate +' + +test_expect_success 'git log --notes shows default notes' ' + git log -1 --notes >output && + grep xyzzy output && + ! grep alternate output +' + +test_expect_success 'git log --notes=X shows only X' ' + git log -1 --notes=alternate >output && + ! grep xyzzy output && + grep alternate output +' + +test_expect_success 'git log --notes --notes=X shows both' ' + git log -1 --notes --notes=alternate >output && + grep xyzzy output && + grep alternate output +' + +test_expect_success 'git log --no-notes resets default state' ' + git log -1 --notes --notes=alternate \ + --no-notes --notes=alternate \ + >output && + ! grep xyzzy output && + grep alternate output +' + +test_expect_success 'git log --no-notes resets ref list' ' + git log -1 --notes --notes=alternate \ + --no-notes --notes \ + >output && + grep xyzzy output && + ! grep alternate output +' + test_expect_success 'create -m notes (setup)' ' : > a5 && git add a5 && @@ -372,6 +435,81 @@ test_expect_success 'removing non-existing note should not create new commit' ' test_cmp before_commit after_commit ' +test_expect_success 'removing more than one' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + + # We have only two -- add another and make sure it stays + git notes add -m "extra" && + git notes list HEAD >after-removal-expect && + git notes remove HEAD^^ HEAD^^^ && + git notes list | sed -e "s/ .*//" >actual && + test_cmp after-removal-expect actual +' + +test_expect_success 'removing is atomic' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + test_must_fail git notes remove HEAD^^ HEAD^^^ HEAD^ && + after=$(git rev-parse --verify refs/notes/commits) && + test "$before" = "$after" +' + +test_expect_success 'removing with --ignore-missing' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + + # We have only two -- add another and make sure it stays + git notes add -m "extra" && + git notes list HEAD >after-removal-expect && + git notes remove --ignore-missing HEAD^^ HEAD^^^ HEAD^ && + git notes list | sed -e "s/ .*//" >actual && + test_cmp after-removal-expect actual +' + +test_expect_success 'removing with --ignore-missing but bogus ref' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + test_must_fail git notes remove --ignore-missing HEAD^^ HEAD^^^ NO-SUCH-COMMIT && + after=$(git rev-parse --verify refs/notes/commits) && + test "$before" = "$after" +' + +test_expect_success 'remove reads from --stdin' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + + # We have only two -- add another and make sure it stays + git notes add -m "extra" && + git notes list HEAD >after-removal-expect && + git rev-parse HEAD^^ HEAD^^^ >input && + git notes remove --stdin <input && + git notes list | sed -e "s/ .*//" >actual && + test_cmp after-removal-expect actual +' + +test_expect_success 'remove --stdin is also atomic' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + git rev-parse HEAD^^ HEAD^^^ HEAD^ >input && + test_must_fail git notes remove --stdin <input && + after=$(git rev-parse --verify refs/notes/commits) && + test "$before" = "$after" +' + +test_expect_success 'removing with --stdin --ignore-missing' ' + before=$(git rev-parse --verify refs/notes/commits) && + test_when_finished "git update-ref refs/notes/commits $before" && + + # We have only two -- add another and make sure it stays + git notes add -m "extra" && + git notes list HEAD >after-removal-expect && + git rev-parse HEAD^^ HEAD^^^ HEAD^ >input && + git notes remove --ignore-missing --stdin <input && + git notes list | sed -e "s/ .*//" >actual && + test_cmp after-removal-expect actual +' + test_expect_success 'list notes with "git notes list"' ' git notes list > output && test_cmp expect output diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh index c4282179b3..86bf909ee3 100755 --- a/t/t3306-notes-prune.sh +++ b/t/t3306-notes-prune.sh @@ -20,6 +20,9 @@ test_expect_success 'setup: create a few commits with notes' ' git add file3 && test_tick && git commit -m 3rd && + COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + test -f $COMMIT_FILE && + test-chmtime =+0 $COMMIT_FILE && git notes add -m "Note #3" ' diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh index 2ea3be6546..1aa366a410 100755 --- a/t/t3307-notes-man.sh +++ b/t/t3307-notes-man.sh @@ -26,13 +26,13 @@ test_expect_success 'example 1: notes to add an Acked-by line' ' ' test_expect_success 'example 2: binary notes' ' - cp "$TEST_DIRECTORY"/test4012.png . && + cp "$TEST_DIRECTORY"/test-binary-1.png . && git checkout B && - blob=$(git hash-object -w test4012.png) && + blob=$(git hash-object -w test-binary-1.png) && git notes --ref=logo add -C "$blob" && git notes --ref=logo copy B C && git notes --ref=logo show C >actual && - test_cmp test4012.png actual + test_cmp test-binary-1.png actual ' test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 349eebd542..6eaecec906 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -158,15 +158,24 @@ test_expect_success 'Show verbose error when HEAD could not be detached' ' ' 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 +test_expect_success 'fail when upstream arg is missing and not on branch' ' + git checkout topic && + test_must_fail git rebase >output.out && + grep "You are not currently on a branch" output.out +' + +test_expect_success 'fail when upstream arg is missing and not configured' ' + git checkout -b no-config topic && + test_must_fail git rebase >output.out && + grep "branch.no-config.merge" output.out +' + +test_expect_success 'default to @{upstream} when upstream arg is missing' ' + git checkout -b default topic && + git config branch.default.remote . + git config branch.default.merge refs/heads/master + git rebase && + test "$(git rev-parse default~1)" = "$(git rev-parse master)" ' test_expect_success 'rebase -q is quiet' ' diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 64446e3db3..826500bd18 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -35,6 +35,11 @@ test_expect_success 'rebase with git am -3 (default)' ' test_must_fail git rebase master ' +test_expect_success 'rebase --skip can not be used with other options' ' + test_must_fail git rebase -v --skip && + test_must_fail git rebase --skip -v +' + test_expect_success 'rebase --skip with am -3' ' git rebase --skip ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 7d8147bb93..b981572d73 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -295,7 +295,7 @@ test_expect_success 'preserve merges with -p' ' ' test_expect_success 'edit ancestor with -p' ' - FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 && + FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 && echo 2 > unrelated-file && test_tick && git commit -m L2-modified --amend unrelated-file && @@ -317,7 +317,7 @@ test_expect_success '--continue tries to commit' ' ' test_expect_success 'verbose flag is heeded, even after --continue' ' - git reset --hard HEAD@{1} && + git reset --hard master@{1} && test_tick && test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && echo resolved > file1 && @@ -527,6 +527,20 @@ test_expect_success 'auto-amend only edited commits after "edit"' ' git rebase --abort ' +test_expect_success 'clean error after failed "exec"' ' + test_tick && + test_when_finished "git rebase --abort || :" && + ( + FAKE_LINES="1 exec_false" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD^ + ) && + echo "edited again" > file7 && + git add file7 && + test_must_fail git rebase --continue 2>error && + grep "You have staged changes in your working tree." error +' + test_expect_success 'rebase a detached HEAD' ' grandparent=$(git rev-parse HEAD~2) && git checkout $(git rev-parse HEAD) && diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh index e573dc845b..a6a6c40a98 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -84,6 +84,16 @@ testrebase() { test_cmp reflog_before reflog_after && rm reflog_before reflog_after ' + + test_expect_success 'rebase --abort can not be used with other options' ' + cd "$work_dir" && + # Clean up the state from the previous one + git reset --hard pre-rebase && + test_must_fail git rebase$type master && + test_must_fail git rebase -v --abort && + test_must_fail git rebase --abort -v && + git rebase --abort + ' } testrebase "" .git/rebase-apply diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh index 19341e5ca1..6de4e2263f 100755 --- a/t/t3409-rebase-preserve-merges.sh +++ b/t/t3409-rebase-preserve-merges.sh @@ -27,7 +27,25 @@ export GIT_AUTHOR_EMAIL # \ # B2 <-- origin/topic # -# In both cases, 'topic' is rebased onto 'origin/topic'. +# Clone 3 (no-ff merge): +# +# A1--A2--B3 <-- origin/master +# \ +# B1------M <-- topic +# \ / +# \--A3 <-- topic2 +# \ +# B2 <-- origin/topic +# +# Clone 4 (merge using second parent as base): +# +# A1--A2--B3 <-- origin/master +# \ +# B1--A3--M <-- topic +# \ / +# \--A4 <-- topic2 +# \ +# B2 <-- origin/topic test_expect_success 'setup for merge-preserving rebase' \ 'echo First > A && @@ -47,6 +65,13 @@ test_expect_success 'setup for merge-preserving rebase' \ git merge origin/master ) && + git clone ./. clone4 && + ( + cd clone4 && + git checkout -b topic origin/topic && + git merge origin/master + ) && + echo Fifth > B && git add B && git commit -m "Add different B" && @@ -61,6 +86,16 @@ test_expect_success 'setup for merge-preserving rebase' \ git commit -m "Merge origin/master into topic" ) && + git clone ./. clone3 && + ( + cd clone3 && + git checkout -b topic2 origin/topic && + echo Sixth > A && + git commit -a -m "Modify A3" && + git checkout -b topic origin/topic && + git merge --no-ff topic2 + ) && + git checkout topic && echo Fourth >> B && git commit -a -m "Modify B2" @@ -93,4 +128,25 @@ test_expect_success '--continue works after a conflict' ' ) ' +test_expect_success 'rebase -p preserves no-ff merges' ' + ( + cd clone3 && + git fetch && + git rebase -p origin/topic && + test 3 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Merge branch" | wc -l) + ) +' + +test_expect_success 'rebase -p works when base inside second parent' ' + ( + cd clone4 && + git fetch && + git rebase -p HEAD^2 && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify B" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l) + ) +' + test_done diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh index 14a23cd872..ace8e54e9b 100755 --- a/t/t3411-rebase-preserve-around-merges.sh +++ b/t/t3411-rebase-preserve-around-merges.sh @@ -37,7 +37,7 @@ test_expect_success 'setup' ' # -- C1 -- # test_expect_success 'squash F1 into D1' ' - FAKE_LINES="1 squash 3 2" git rebase -i -p B1 && + FAKE_LINES="1 squash 4 2 3" git rebase -i -p B1 && test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" && test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" && git tag E2 diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 3b0d27350e..1e855cdae5 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -40,4 +40,59 @@ test_expect_success 'non-interactive rebase --continue works with touched file' git rebase --continue ' +test_expect_success 'rebase --continue can not be used with other options' ' + test_must_fail git rebase -v --continue && + test_must_fail git rebase --continue -v +' + +test_expect_success 'rebase --continue remembers merge strategy and options' ' + rm -fr .git/rebase-* && + git reset --hard commit-new-file-F2-on-topic-branch && + test_commit "commit-new-file-F3-on-topic-branch" F3 32 && + test_when_finished "rm -fr test-bin funny.was.run" && + mkdir test-bin && + cat >test-bin/git-merge-funny <<-EOF + #!$SHELL_PATH + case "\$1" in --opt) ;; *) exit 2 ;; esac + shift && + >funny.was.run && + exec git merge-recursive "\$@" + EOF + chmod +x test-bin/git-merge-funny && + ( + PATH=./test-bin:$PATH + test_must_fail git rebase -s funny -Xopt master topic + ) && + test -f funny.was.run && + rm funny.was.run && + echo "Resolved" >F2 && + git add F2 && + ( + PATH=./test-bin:$PATH + git rebase --continue + ) && + test -f funny.was.run +' + +test_expect_success 'rebase --continue remembers --rerere-autoupdate' ' + rm -fr .git/rebase-* && + git reset --hard commit-new-file-F3-on-topic-branch && + git checkout master + test_commit "commit-new-file-F3" F3 3 && + git config rerere.enabled true && + test_must_fail git rebase -m master topic && + echo "Resolved" >F2 && + git add F2 && + test_must_fail git rebase --continue && + echo "Resolved" >F3 && + git add F3 && + git rebase --continue && + git reset --hard topic@{1} && + test_must_fail git rebase -m --rerere-autoupdate master && + test "$(cat F2)" = "Resolved" && + test_must_fail git rebase --continue && + test "$(cat F3)" = "Resolved" && + git rebase --continue +' + test_done diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 043954422c..595d2ff990 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -96,7 +96,7 @@ test_expect_success 'revert forbidden on dirty working tree' ' echo content >extra_file && git add extra_file && test_must_fail git revert HEAD 2>errors && - grep "Your local changes would be overwritten by " errors + test_i18ngrep "Your local changes would be overwritten by " errors ' diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh index b0faa29918..e27f39d1e5 100755 --- a/t/t3503-cherry-pick-root.sh +++ b/t/t3503-cherry-pick-root.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='test cherry-picking a root commit' +test_description='test cherry-picking (and reverting) a root commit' . ./test-lib.sh @@ -16,14 +16,62 @@ test_expect_success setup ' echo second > file2 && git add file2 && test_tick && - git commit -m "second" + git commit -m "second" && + + git symbolic-ref HEAD refs/heads/third && + rm .git/index file2 && + echo third > file3 && + git add file3 && + test_tick && + git commit -m "third" ' test_expect_success 'cherry-pick a root commit' ' + git checkout second^0 && git cherry-pick master && - test first = $(cat file1) + echo first >expect && + test_cmp expect file1 + +' + +test_expect_success 'revert a root commit' ' + + git revert master && + test_path_is_missing file1 + +' + +test_expect_success 'cherry-pick a root commit with an external strategy' ' + + git cherry-pick --strategy=resolve master && + echo first >expect && + test_cmp expect file1 + +' + +test_expect_success 'revert a root commit with an external strategy' ' + + git revert --strategy=resolve master && + test_path_is_missing file1 + +' + +test_expect_success 'cherry-pick two root commits' ' + + echo first >expect.file1 && + echo second >expect.file2 && + echo third >expect.file3 && + + git checkout second^0 && + git cherry-pick master third && + + test_cmp expect.file1 file1 && + test_cmp expect.file2 file2 && + test_cmp expect.file3 file3 && + git rev-parse --verify HEAD^^ && + test_must_fail git rev-parse --verify HEAD^^^ ' diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 607bf25d8f..cb45574a7b 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -11,6 +11,18 @@ test_description='test cherry-pick and revert with conflicts . ./test-lib.sh +test_cmp_rev () { + git rev-parse --verify "$1" >expect.rev && + git rev-parse --verify "$2" >actual.rev && + test_cmp expect.rev actual.rev +} + +pristine_detach () { + git checkout -f "$1^0" && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x +} + test_expect_success setup ' echo unrelated >unrelated && @@ -23,13 +35,7 @@ test_expect_success setup ' ' test_expect_success 'failed cherry-pick does not advance HEAD' ' - - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && - - git update-index --refresh && - git diff-index --exit-code HEAD && + pristine_detach initial && head=$(git rev-parse HEAD) && test_must_fail git cherry-pick picked && @@ -39,33 +45,111 @@ test_expect_success 'failed cherry-pick does not advance HEAD' ' ' test_expect_success 'advice from failed cherry-pick' " - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && - - git update-index --refresh && - git diff-index --exit-code HEAD && + pristine_detach initial && picked=\$(git rev-parse --short picked) && cat <<-EOF >expected && error: could not apply \$picked... picked hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' - hint: and commit the result with 'git commit -c \$picked' + hint: and commit the result with 'git commit' EOF test_must_fail git cherry-pick picked 2>actual && - test_cmp expected actual + test_i18ncmp expected actual " -test_expect_success 'failed cherry-pick produces dirty index' ' +test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' ' + pristine_detach initial && + test_must_fail git cherry-pick picked && + test_cmp_rev picked CHERRY_PICK_HEAD +' - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && +test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' ' + pristine_detach initial && + git cherry-pick base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' ' + pristine_detach initial && + git cherry-pick --no-commit base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' - git update-index --refresh && - git diff-index --exit-code HEAD && +test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' ' + pristine_detach initial && + echo foo > foo && + test_must_fail git cherry-pick base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success \ + 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' ' + pristine_detach initial && + echo foo > foo && + test_must_fail git cherry-pick --strategy=resolve base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' ' + pristine_detach initial && + ( + GIT_CHERRY_PICK_HELP="and then do something else" && + export GIT_CHERRY_PICK_HELP && + test_must_fail git cherry-pick picked + ) && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success 'git reset clears CHERRY_PICK_HEAD' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + git reset && + + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + test_must_fail git commit && + + test_cmp_rev picked CHERRY_PICK_HEAD +' + +test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + echo resolved >foo && + git add foo && + git update-index --refresh -q && + test_must_fail git diff-index --exit-code HEAD && + ( + GIT_EDITOR=false && + export GIT_EDITOR && + test_must_fail git commit + ) && + + test_cmp_rev picked CHERRY_PICK_HEAD +' + +test_expect_success 'successful commit clears CHERRY_PICK_HEAD' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + echo resolved >foo && + git add foo && + git commit && + + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success 'failed cherry-pick produces dirty index' ' + pristine_detach initial && test_must_fail git cherry-pick picked && @@ -74,9 +158,7 @@ test_expect_success 'failed cherry-pick produces dirty index' ' ' test_expect_success 'failed cherry-pick registers participants in index' ' - - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && + pristine_detach initial && { git checkout base -- foo && git ls-files --stage foo && @@ -90,10 +172,7 @@ test_expect_success 'failed cherry-pick registers participants in index' ' 2 s/ 0 / 2 / 3 s/ 0 / 3 / " < stages > expected && - git checkout -f initial^0 && - - git update-index --refresh && - git diff-index --exit-code HEAD && + git read-tree -u --reset HEAD && test_must_fail git cherry-pick picked && git ls-files --stage --unmerged > actual && @@ -102,10 +181,7 @@ test_expect_success 'failed cherry-pick registers participants in index' ' ' test_expect_success 'failed cherry-pick describes conflict in work tree' ' - - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && + pristine_detach initial && cat <<-EOF > expected && <<<<<<< HEAD a @@ -114,9 +190,6 @@ test_expect_success 'failed cherry-pick describes conflict in work tree' ' >>>>>>> objid picked EOF - git update-index --refresh && - git diff-index --exit-code HEAD && - test_must_fail git cherry-pick picked && sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && @@ -124,11 +197,8 @@ test_expect_success 'failed cherry-pick describes conflict in work tree' ' ' test_expect_success 'diff3 -m style' ' - + pristine_detach initial && git config merge.conflictstyle diff3 && - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && cat <<-EOF > expected && <<<<<<< HEAD a @@ -139,9 +209,6 @@ test_expect_success 'diff3 -m style' ' >>>>>>> objid picked EOF - git update-index --refresh && - git diff-index --exit-code HEAD && - test_must_fail git cherry-pick picked && sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && @@ -149,10 +216,8 @@ test_expect_success 'diff3 -m style' ' ' test_expect_success 'revert also handles conflicts sanely' ' - git config --unset merge.conflictstyle && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && + pristine_detach initial && cat <<-EOF > expected && <<<<<<< HEAD a @@ -173,10 +238,7 @@ test_expect_success 'revert also handles conflicts sanely' ' 2 s/ 0 / 2 / 3 s/ 0 / 3 / " < stages > expected-stages && - git checkout -f initial^0 && - - git update-index --refresh && - git diff-index --exit-code HEAD && + git read-tree -u --reset HEAD && head=$(git rev-parse HEAD) && test_must_fail git revert picked && @@ -192,10 +254,8 @@ test_expect_success 'revert also handles conflicts sanely' ' ' test_expect_success 'revert conflict, diff3 -m style' ' + pristine_detach initial && git config merge.conflictstyle diff3 && - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && cat <<-EOF > expected && <<<<<<< HEAD a @@ -206,9 +266,6 @@ test_expect_success 'revert conflict, diff3 -m style' ' >>>>>>> parent of objid picked EOF - git update-index --refresh && - git diff-index --exit-code HEAD && - test_must_fail git revert picked && sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh index 948ca1bce6..df921d1f33 100755 --- a/t/t3509-cherry-pick-merge-df.sh +++ b/t/t3509-cherry-pick-merge-df.sh @@ -3,12 +3,14 @@ test_description='Test cherry-pick with directory/file conflicts' . ./test-lib.sh -test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' ' +test_expect_success 'Initialize repository' ' mkdir a && >a/f && git add a && - git commit -m a && + git commit -m a +' +test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' ' mkdir b && ln -s ../a b/a && git add b && diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh new file mode 100755 index 0000000000..3bca2b3dd5 --- /dev/null +++ b/t/t3510-cherry-pick-sequence.sh @@ -0,0 +1,214 @@ +#!/bin/sh + +test_description='Test cherry-pick continuation features + + + anotherpick: rewrites foo to d + + picked: rewrites foo to c + + unrelatedpick: rewrites unrelated to reallyunrelated + + base: rewrites foo to b + + initial: writes foo as a, unrelated as unrelated + +' + +. ./test-lib.sh + +pristine_detach () { + git cherry-pick --reset && + git checkout -f "$1^0" && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x +} + +test_expect_success setup ' + echo unrelated >unrelated && + git add unrelated && + test_commit initial foo a && + test_commit base foo b && + test_commit unrelatedpick unrelated reallyunrelated && + test_commit picked foo c && + test_commit anotherpick foo d && + git config advice.detachedhead false + +' + +test_expect_success 'cherry-pick persists data on failure' ' + pristine_detach initial && + test_must_fail git cherry-pick -s base..anotherpick && + test_path_is_dir .git/sequencer && + test_path_is_file .git/sequencer/head && + test_path_is_file .git/sequencer/todo && + test_path_is_file .git/sequencer/opts +' + +test_expect_success 'cherry-pick persists opts correctly' ' + pristine_detach initial && + test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick && + test_path_is_dir .git/sequencer && + test_path_is_file .git/sequencer/head && + test_path_is_file .git/sequencer/todo && + test_path_is_file .git/sequencer/opts && + echo "true" >expect && + git config --file=.git/sequencer/opts --get-all options.signoff >actual && + test_cmp expect actual && + echo "1" >expect && + git config --file=.git/sequencer/opts --get-all options.mainline >actual && + test_cmp expect actual && + echo "recursive" >expect && + git config --file=.git/sequencer/opts --get-all options.strategy >actual && + test_cmp expect actual && + cat >expect <<-\EOF && + patience + ours + EOF + git config --file=.git/sequencer/opts --get-all options.strategy-option >actual && + test_cmp expect actual +' + +test_expect_success 'cherry-pick cleans up sequencer state upon success' ' + pristine_detach initial && + git cherry-pick initial..picked && + test_path_is_missing .git/sequencer +' + +test_expect_success '--reset does not complain when no cherry-pick is in progress' ' + pristine_detach initial && + git cherry-pick --reset +' + +test_expect_success '--reset cleans up sequencer state' ' + pristine_detach initial && + test_must_fail git cherry-pick base..picked && + git cherry-pick --reset && + test_path_is_missing .git/sequencer +' + +test_expect_success 'cherry-pick cleans up sequencer state when one commit is left' ' + pristine_detach initial && + test_must_fail git cherry-pick base..picked && + test_path_is_missing .git/sequencer && + echo "resolved" >foo && + git add foo && + git commit && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + cat >expect <<-\EOF && + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M unrelated + OBJID + :000000 100644 OBJID OBJID A foo + :000000 100644 OBJID OBJID A unrelated + EOF + test_cmp expect actual +' + +test_expect_success 'cherry-pick does not implicitly stomp an existing operation' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + test-chmtime -v +0 .git/sequencer >expect && + test_must_fail git cherry-pick unrelatedpick && + test-chmtime -v +0 .git/sequencer >actual && + test_cmp expect actual +' + +test_expect_success '--continue complains when no cherry-pick is in progress' ' + pristine_detach initial && + test_must_fail git cherry-pick --continue +' + +test_expect_success '--continue complains when there are unresolved conflicts' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + test_must_fail git cherry-pick --continue +' + +test_expect_success '--continue continues after conflicts are resolved' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + echo "c" >foo && + git add foo && + git commit && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + cat >expect <<-\EOF && + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M unrelated + OBJID + :000000 100644 OBJID OBJID A foo + :000000 100644 OBJID OBJID A unrelated + EOF + test_cmp expect actual +' + +test_expect_success '--continue respects opts' ' + pristine_detach initial && + test_must_fail git cherry-pick -x base..anotherpick && + echo "c" >foo && + git add foo && + git commit && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + git cat-file commit HEAD >anotherpick_msg && + git cat-file commit HEAD~1 >picked_msg && + git cat-file commit HEAD~2 >unrelatedpick_msg && + git cat-file commit HEAD~3 >initial_msg && + test_must_fail grep "cherry picked from" initial_msg && + grep "cherry picked from" unrelatedpick_msg && + grep "cherry picked from" picked_msg && + grep "cherry picked from" anotherpick_msg +' + +test_expect_success '--signoff is not automatically propagated to resolved conflict' ' + pristine_detach initial && + test_must_fail git cherry-pick --signoff base..anotherpick && + echo "c" >foo && + git add foo && + git commit && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + git cat-file commit HEAD >anotherpick_msg && + git cat-file commit HEAD~1 >picked_msg && + git cat-file commit HEAD~2 >unrelatedpick_msg && + git cat-file commit HEAD~3 >initial_msg && + test_must_fail grep "Signed-off-by:" initial_msg && + grep "Signed-off-by:" unrelatedpick_msg && + test_must_fail grep "Signed-off-by:" picked_msg && + grep "Signed-off-by:" anotherpick_msg +' + +test_expect_success 'malformed instruction sheet 1' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + echo "resolved" >foo && + git add foo && + git commit && + sed "s/pick /pick/" .git/sequencer/todo >new_sheet && + cp new_sheet .git/sequencer/todo && + test_must_fail git cherry-pick --continue +' + +test_expect_success 'malformed instruction sheet 2' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + echo "resolved" >foo && + git add foo && + git commit && + sed "s/pick/revert/" .git/sequencer/todo >new_sheet && + cp new_sheet .git/sequencer/todo && + test_must_fail git cherry-pick --continue +' + +test_done diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index cd093bd347..9fd28bcf34 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -240,11 +240,10 @@ test_expect_success 'refresh index before checking if it is up-to-date' ' test_expect_success 'choking "git rm" should not let it die with cruft' ' git reset -q --hard && - H=0000000000000000000000000000000000000000 && i=0 && while test $i -lt 12000 do - echo "100644 $H 0 some-file-$i" + echo "100644 $_z40 0 some-file-$i" i=$(( $i + 1 )) done | git update-index --index-info && git rm -n "some-file-*" | :; diff --git a/t/t3700-add.sh b/t/t3700-add.sh index ec7108358e..575d9508a0 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -268,8 +268,12 @@ test_expect_success 'git add --dry-run of existing changed file' " test_expect_success 'git add --dry-run of non-existing file' " echo ignored-file >>.gitignore && - test_must_fail git add --dry-run track-this ignored-file >actual 2>&1 && - echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual + test_must_fail git add --dry-run track-this ignored-file >actual 2>&1 +" + +test_expect_success 'git add --dry-run of an existing file output' " + echo \"fatal: pathspec 'ignored-file' did not match any files\" >expect && + test_i18ncmp expect actual " cat >expect.err <<\EOF @@ -283,9 +287,12 @@ 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.out 2>actual.err && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err +' + +test_expect_success 'git add --dry-run --ignore-missing of non-existing file output' ' + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_done diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index d6327e7c74..9e236f9cc0 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -82,10 +82,9 @@ EOF ' test_expect_success PERL 'setup fake editor' ' - cat >fake_editor.sh <<EOF - EOF + >fake_editor.sh && chmod a+x fake_editor.sh && - test_set_editor "$(pwd)/fake_editor.sh" && + test_set_editor "$(pwd)/fake_editor.sh" ' test_expect_success PERL 'dummy edit works' ' @@ -295,4 +294,40 @@ test_expect_success PERL 'deleting an empty file' ' test_cmp expected diff ' +test_expect_success PERL 'split hunk setup' ' + git reset --hard && + for i in 10 20 30 40 50 60 + do + echo $i + done >test && + git add test && + test_tick && + git commit -m test && + + for i in 10 15 20 21 22 23 24 30 40 50 60 + do + echo $i + done >test +' + +test_expect_success PERL 'split hunk "add -p (edit)"' ' + # Split, say Edit and do nothing. Then: + # + # 1. Broken version results in a patch that does not apply and + # only takes [y/n] (edit again) so the first q is discarded + # and then n attempts to discard the edit. Repeat q enough + # times to get out. + # + # 2. Correct version applies the (not)edited version, and asks + # about the next hunk, against wich we say q and program + # exits. + for a in s e q n q q + do + echo $a + done | + EDITOR=: git add -p && + git diff >actual && + ! grep "^+15" actual +' + test_done diff --git a/t/t3703-add-magic-pathspec.sh b/t/t3703-add-magic-pathspec.sh new file mode 100755 index 0000000000..5115de7036 --- /dev/null +++ b/t/t3703-add-magic-pathspec.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +test_description='magic pathspec tests using git-add' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir sub anothersub && + : >sub/foo && + : >anothersub/foo +' + +test_expect_success 'add :/' " + cat >expected <<-EOF && + add 'anothersub/foo' + add 'expected' + add 'sub/actual' + add 'sub/foo' + EOF + (cd sub && git add -n :/ >actual) && + test_cmp expected sub/actual +" + +cat >expected <<EOF +add 'anothersub/foo' +EOF + +test_expect_success 'add :/anothersub' ' + (cd sub && git add -n :/anothersub >actual) && + test_cmp expected sub/actual +' + +test_expect_success 'add :/non-existent' ' + (cd sub && test_must_fail git add -n :/non-existent) +' + +cat >expected <<EOF +add 'sub/foo' +EOF + +if mkdir ":" 2>/dev/null +then + test_set_prereq COLON_DIR +fi + +test_expect_success COLON_DIR 'a file with the same (long) magic name exists' ' + : >":(icase)ha" && + test_must_fail git add -n ":(icase)ha" && + git add -n "./:(icase)ha" +' + +test_expect_success COLON_DIR 'a file with the same (short) magic name exists' ' + : >":/bar" && + test_must_fail git add -n :/bar && + git add -n "./:/bar" +' + +test_done diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index c06a5ee766..1f62c151b0 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -147,7 +147,7 @@ test_commit_autosquash_flags () { git commit -a -m "intermediate commit" && test_tick && echo $H $flag >>F && - git commit -a --$flag HEAD~1 $3 && + git commit -a --$flag HEAD~1 && E=$(git cat-file commit '$H-$flag' | sed -ne "s/^encoding //p") && test "z$E" = "z$H" && @@ -160,6 +160,6 @@ test_commit_autosquash_flags () { test_commit_autosquash_flags eucJP fixup -test_commit_autosquash_flags ISO-2022-JP squash '-m "squash message"' +test_commit_autosquash_flags ISO-2022-JP squash test_done diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh index da82b655b3..534ee08a44 100755 --- a/t/t3902-quoted.sh +++ b/t/t3902-quoted.sh @@ -10,8 +10,6 @@ test_description='quoted output' FN='濱野' GN='純' HT=' ' -LF=' -' DQ='"' echo foo 2>/dev/null > "Name and an${HT}HT" diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 6fd560ccf1..fcdb18217a 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -37,14 +37,32 @@ test_expect_success 'parents of stash' ' test_cmp output expect ' -test_expect_success 'apply needs clean working directory' ' - echo 4 > other-file && +test_expect_success 'applying bogus stash does nothing' ' + test_must_fail git stash apply stash@{1} && + echo 1 >expect && + test_cmp expect file +' + +test_expect_success 'apply does not need clean working directory' ' + echo 4 >other-file && git add other-file && - echo 5 > other-file && - test_must_fail git stash apply + echo 5 >other-file && + git stash apply && + echo 3 >expect && + test_cmp expect file +' + +test_expect_success 'apply does not clobber working directory changes' ' + git reset --hard && + echo 4 >file && + test_must_fail git stash apply && + echo 4 >expect && + test_cmp expect file ' test_expect_success 'apply stashed changes' ' + git reset --hard && + echo 5 >other-file && git add other-file && test_tick && git commit -m other-file && @@ -218,6 +236,14 @@ test_expect_success 'stash -k' ' test bar,bar4 = $(cat file),$(cat file2) ' +test_expect_success 'stash --no-keep-index' ' + echo bar33 > file && + echo bar44 > file2 && + git add file2 && + git stash --no-keep-index && + test bar,bar2 = $(cat file),$(cat file2) +' + test_expect_success 'stash --invalid-option' ' echo bar5 > file && echo bar6 > file2 && @@ -510,13 +536,13 @@ test_expect_success 'stash pop - fail early if specified stash is not a stash re git reset --hard HEAD ' -test_expect_success 'ref with non-existant reflog' ' +test_expect_success 'ref with non-existent reflog' ' git stash clear && echo bar5 > file && echo bar6 > file2 && git add file2 && git stash && - ! "git rev-parse --quiet --verify does-not-exist" && + test_must_fail git rev-parse --quiet --verify does-not-exist && test_must_fail git stash drop does-not-exist && test_must_fail git stash drop does-not-exist@{0} && test_must_fail git stash pop does-not-exist && @@ -537,11 +563,11 @@ test_expect_success 'invalid ref of the form stash@{n}, n >= N' ' echo bar6 > file2 && git add file2 && git stash && - test_must_fail git drop stash@{1} && - test_must_fail git pop stash@{1} && - test_must_fail git apply stash@{1} && - test_must_fail git show stash@{1} && - test_must_fail git branch tmp stash@{1} && + test_must_fail git stash drop stash@{1} && + test_must_fail git stash pop stash@{1} && + test_must_fail git stash apply stash@{1} && + test_must_fail git stash show stash@{1} && + test_must_fail git stash branch tmp stash@{1} && git stash drop ' @@ -556,4 +582,23 @@ test_expect_success 'stash branch should not drop the stash if the branch exists git rev-parse stash@{0} -- ' +test_expect_success 'stash apply shows status same as git status (relative to current directory)' ' + git stash clear && + echo 1 >subdir/subfile1 && + echo 2 >subdir/subfile2 && + git add subdir/subfile1 && + git commit -m subdir && + ( + cd subdir && + echo x >subfile1 && + echo x >../file && + git status >../expect && + git stash && + sane_unset GIT_MERGE_VERBOSITY && + git stash apply + ) | + sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..." + test_cmp expect actual +' + test_done diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index 1e7193ac0b..781fd71681 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -48,6 +48,18 @@ test_expect_success PERL 'git stash -p --no-keep-index' ' verify_state bar dummy bar_index ' +test_expect_success PERL 'git stash --no-keep-index -p' ' + set_state dir/foo work index && + set_state bar bar_work bar_index && + (echo n; echo y) | git stash save --no-keep-index -p && + verify_state dir/foo head head && + verify_state bar bar_work dummy && + git reset --hard && + git stash apply --index && + verify_state dir/foo work index && + verify_state bar dummy bar_index +' + test_expect_success PERL 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh new file mode 100755 index 0000000000..ef44fb2260 --- /dev/null +++ b/t/t3905-stash-include-untracked.sh @@ -0,0 +1,175 @@ +#!/bin/sh +# +# Copyright (c) 2011 David Caldwell +# + +test_description='Test git stash --include-untracked' + +. ./test-lib.sh + +test_expect_success 'stash save --include-untracked some dirty working directory' ' + echo 1 > file && + git add file && + test_tick && + git commit -m initial && + echo 2 > file && + git add file && + echo 3 > file && + test_tick && + echo 1 > file2 && + mkdir untracked && + echo untracked >untracked/untracked && + git stash --include-untracked && + git diff-files --quiet && + git diff-index --cached --quiet HEAD +' + +cat > expect <<EOF +?? actual +?? expect +EOF + +test_expect_success 'stash save --include-untracked cleaned the untracked files' ' + git status --porcelain >actual && + test_cmp expect actual +' + +cat > expect.diff <<EOF +diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..d00491f +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++1 +diff --git a/untracked/untracked b/untracked/untracked +new file mode 100644 +index 0000000..5a72eb2 +--- /dev/null ++++ b/untracked/untracked +@@ -0,0 +1 @@ ++untracked +EOF +cat > expect.lstree <<EOF +file2 +untracked +EOF + +test_expect_success 'stash save --include-untracked stashed the untracked files' ' + test "!" -f file2 && + test ! -e untracked && + git diff HEAD stash^3 -- file2 untracked >actual && + test_cmp expect.diff actual && + git ls-tree --name-only stash^3: >actual && + test_cmp expect.lstree actual +' +test_expect_success 'stash save --patch --include-untracked fails' ' + test_must_fail git stash --patch --include-untracked +' + +test_expect_success 'stash save --patch --all fails' ' + test_must_fail git stash --patch --all +' + +git clean --force --quiet + +cat > expect <<EOF + M file +?? actual +?? expect +?? file2 +?? untracked/ +EOF + +test_expect_success 'stash pop after save --include-untracked leaves files untracked again' ' + git stash pop && + git status --porcelain >actual && + test_cmp expect actual && + test "1" = "`cat file2`" && + test untracked = "`cat untracked/untracked`" +' + +git clean --force --quiet -d + +test_expect_success 'stash save -u dirty index' ' + echo 4 > file3 && + git add file3 && + test_tick && + git stash -u +' + +cat > expect <<EOF +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..b8626c4 +--- /dev/null ++++ b/file3 +@@ -0,0 +1 @@ ++4 +EOF + +test_expect_success 'stash save --include-untracked dirty index got stashed' ' + git stash pop --index && + git diff --cached >actual && + test_cmp expect actual +' + +git reset > /dev/null + +test_expect_success 'stash save --include-untracked -q is quiet' ' + echo 1 > file5 && + git stash save --include-untracked --quiet > output.out 2>&1 && + test ! -s output.out +' + +test_expect_success 'stash save --include-untracked removed files' ' + rm -f file && + git stash save --include-untracked && + echo 1 > expect && + test_cmp file expect +' + +rm -f expect + +test_expect_success 'stash save --include-untracked removed files got stashed' ' + git stash pop && + test ! -f file +' + +cat > .gitignore <<EOF +.gitignore +ignored +ignored.d/ +EOF + +test_expect_success 'stash save --include-untracked respects .gitignore' ' + echo ignored > ignored && + mkdir ignored.d && + echo ignored >ignored.d/untracked && + git stash -u && + test -s ignored && + test -s ignored.d/untracked && + test -s .gitignore +' + +test_expect_success 'stash save -u can stash with only untracked files different' ' + echo 4 > file4 && + git stash -u && + test "!" -f file4 +' + +test_expect_success 'stash save --all does not respect .gitignore' ' + git stash -a && + test "!" -f ignored && + test "!" -e ignored.d && + test "!" -f .gitignore +' + +test_expect_success 'stash save --all is stash poppable' ' + git stash pop && + test -s ignored && + test -s ignored.d/untracked && + test -s .gitignore +' + +test_done diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 71bac83dd5..844277cfa6 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -71,10 +71,35 @@ test_expect_success 'favour same basenames over different ones' ' git rm path1 && mkdir subdir && git mv another-path subdir/path1 && - git status | grep "renamed: .*path1 -> subdir/path1"' + git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"' -test_expect_success 'favour same basenames even with minor differences' ' +test_expect_success 'favour same basenames even with minor differences' ' git show HEAD:path1 | sed "s/15/16/" > subdir/path1 && - git status | grep "renamed: .*path1 -> subdir/path1"' + git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"' + +test_expect_success 'setup for many rename source candidates' ' + git reset --hard && + for i in 0 1 2 3 4 5 6 7 8 9; + do + for j in 0 1 2 3 4 5 6 7 8 9; + do + echo "$i$j" >"path$i$j" + done + done && + git add "path??" && + test_tick && + git commit -m "hundred" && + (cat path1; echo new) >new-path && + echo old >>path1 && + git add new-path path1 && + git diff -l 4 -C -C --cached --name-status >actual 2>actual.err && + sed -e "s/^\([CM]\)[0-9]* /\1 /" actual >actual.munged && + cat >expect <<-EOF && + C path1 new-path + M path1 + EOF + test_cmp expect actual.munged && + grep warning actual.err +' test_done diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index 9fb8ca06a8..a5e8b83083 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -126,15 +126,12 @@ cat >.test-recursive-AB <<\EOF :100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M Z/NM EOF -x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -x40="$x40$x40$x40$x40$x40$x40$x40$x40" -z40='0000000000000000000000000000000000000000' cmp_diff_files_output () { # diff-files never reports additions. Also it does not fill in the # object ID for the changed files because it wants you to look at the # filesystem. sed <"$2" >.test-tmp \ - -e '/^:000000 /d;s/'$x40'\( [MCRNDU][0-9]*\) /'$z40'\1 /' && + -e '/^:000000 /d;s/'$_x40'\( [MCRNDU][0-9]*\) /'$_z40'\1 /' && test_cmp "$1" .test-tmp } diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh index c6130c4019..bfa8835638 100755 --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -29,7 +29,7 @@ test_expect_success \ # copy-and-edit one, and rename-and-edit the other. We do not say # anything about rezrov. -GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current +GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current cat >expected <<\EOF diff --git a/COPYING b/COPYING.1 copy from COPYING diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index 92a65f4852..6e562c80d1 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -35,7 +35,7 @@ test_expect_success SYMLINKS \ # a new creation. test_expect_success SYMLINKS 'setup diff output' " - GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && + GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current && cat >expected <<\EOF diff --git a/bozbar b/bozbar new file mode 120000 diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh index 1ba359d478..77d7f4946f 100755 --- a/t/t4005-diff-rename-2.sh +++ b/t/t4005-diff-rename-2.sh @@ -29,7 +29,7 @@ test_expect_success \ # and COPYING.2 are based on COPYING, and do not say anything about # rezrov. -git diff-index -M $tree >current +git diff-index -C $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh index d79d9e1e71..73b4a24f5e 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -173,8 +173,8 @@ test_expect_success \ 'compare_diff_raw expected current' test_expect_success \ - 'run diff with -B -M' \ - 'git diff-index -B -M "$tree" >current' + 'run diff with -B -C' \ + 'git diff-index -B -C "$tree" >current' cat >expected <<\EOF :100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095 file0 file1 diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh index de3f17478e..f22c8e3dba 100755 --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -29,7 +29,7 @@ test_expect_success \ # and COPYING.2 are based on COPYING, and do not say anything about # rezrov. -git diff-index -z -M $tree >current +git diff-index -z -C $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 94df7ae53a..fbc8cd8f05 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -70,4 +70,36 @@ test_expect_success 'diff-tree pathspec' ' test_cmp expected current ' +EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + +test_expect_success 'diff-tree with wildcard shows dir also matches' ' + git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result && + echo file0 >expected && + test_cmp expected result +' + +test_expect_success 'diff-tree -r with wildcard' ' + git diff-tree -r --name-only $EMPTY_TREE $tree -- "*file1" >result && + echo path1/file1 >expected && + test_cmp expected result +' + +test_expect_success 'diff-tree with wildcard shows dir also matches' ' + git diff-tree --name-only $tree $tree2 -- "path1/f*" >result && + echo path1 >expected && + test_cmp expected result +' + +test_expect_success 'diff-tree -r with wildcard from beginning' ' + git diff-tree -r --name-only $tree $tree2 -- "path1/*file1" >result && + echo path1/file1 >expected && + test_cmp expected result +' + +test_expect_success 'diff-tree -r with wildcard' ' + git diff-tree -r --name-only $tree $tree2 -- "path1/f*" >result && + echo path1/file1 >expected && + test_cmp expected result +' + test_done diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 05ec062832..2d9f9a0cf1 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \ 'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d && git update-index --add a b c d && echo git >a && - cat "$TEST_DIRECTORY"/test4012.png >b && + cat "$TEST_DIRECTORY"/test-binary-1.png >b && echo git >c && cat b b >d' diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 9a66520588..93a6f20871 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -80,18 +80,31 @@ test_expect_success setup ' git config log.showroot false && git commit --amend && + + GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" && + GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" && + export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && + git checkout -b rearrange initial && + for i in B A; do echo $i; done >dir/sub && + git add dir/sub && + git commit -m "Rearranged lines in dir/sub" && + git checkout master && + git show-branch ' : <<\EOF ! [initial] Initial * [master] Merge branch 'side' - ! [side] Side ---- - - [master] Merge branch 'side' - *+ [side] Side - * [master^] Second -+*+ [initial] Initial + ! [rearrange] Rearranged lines in dir/sub + ! [side] Side +---- + + [rearrange] Rearranged lines in dir/sub + - [master] Merge branch 'side' + * + [side] Side + * [master^] Third + * [master~2] Second ++*++ [initial] Initial EOF V=`git version | sed -e 's/^git version //' -e 's/\./\\./g'` @@ -210,6 +223,9 @@ log -m -p master log -SF master log -S F master log -SF -p master +log -SF master --max-count=0 +log -SF master --max-count=1 +log -SF master --max-count=2 log -GF master log -GF -p master log -GF -p --pickaxe-all master @@ -284,10 +300,23 @@ diff --no-index --name-status -- dir2 dir diff --no-index dir dir3 diff master master^ side diff --dirstat master~1 master~2 +diff --dirstat initial rearrange +diff --dirstat-by-file initial rearrange EOF test_expect_success 'log -S requires an argument' ' test_must_fail git log -S ' +test_expect_success 'diff --cached on unborn branch' ' + echo ref: refs/heads/unborn >.git/HEAD && + git diff --cached >result && + test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached" result +' + +test_expect_success 'diff --cached -- file on unborn branch' ' + git diff --cached -- file0 >result && + test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result +' + test_done diff --git a/t/t4013/diff.diff_--cached b/t/t4013/diff.diff_--cached new file mode 100644 index 0000000000..ff16e83e7c --- /dev/null +++ b/t/t4013/diff.diff_--cached @@ -0,0 +1,38 @@ +diff --git a/dir/sub b/dir/sub +new file mode 100644 +index 0000000..992913c +--- /dev/null ++++ b/dir/sub +@@ -0,0 +1,8 @@ ++A ++B ++C ++D ++E ++F ++1 ++2 +diff --git a/file0 b/file0 +new file mode 100644 +index 0000000..10a8a9f +--- /dev/null ++++ b/file0 +@@ -0,0 +1,9 @@ ++1 ++2 ++3 ++4 ++5 ++6 ++A ++B ++C +diff --git a/file1 b/file1 +new file mode 100644 +index 0000000..b1e6722 +--- /dev/null ++++ b/file1 +@@ -0,0 +1,3 @@ ++A ++B ++C diff --git a/t/t4013/diff.diff_--cached_--_file0 b/t/t4013/diff.diff_--cached_--_file0 new file mode 100644 index 0000000000..b9bb858a03 --- /dev/null +++ b/t/t4013/diff.diff_--cached_--_file0 @@ -0,0 +1,15 @@ +diff --git a/file0 b/file0 +new file mode 100644 +index 0000000..10a8a9f +--- /dev/null ++++ b/file0 +@@ -0,0 +1,9 @@ ++1 ++2 ++3 ++4 ++5 ++6 ++A ++B ++C diff --git a/t/t4013/diff.diff_--dirstat-by-file_initial_rearrange b/t/t4013/diff.diff_--dirstat-by-file_initial_rearrange new file mode 100644 index 0000000000..e48e33f678 --- /dev/null +++ b/t/t4013/diff.diff_--dirstat-by-file_initial_rearrange @@ -0,0 +1,3 @@ +$ git diff --dirstat-by-file initial rearrange + 100.0% dir/ +$ diff --git a/t/t4013/diff.diff_--dirstat_initial_rearrange b/t/t4013/diff.diff_--dirstat_initial_rearrange new file mode 100644 index 0000000000..5fb02c13bc --- /dev/null +++ b/t/t4013/diff.diff_--dirstat_initial_rearrange @@ -0,0 +1,3 @@ +$ git diff --dirstat initial rearrange + 100.0% dir/ +$ diff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ index 1f0f9ad44b..3b4e113012 100644 --- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ +++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ @@ -1,7 +1,7 @@ $ git format-patch --stdout --cover-letter -n initial..master^ From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 From: C O Mitter <committer@example.com> -Date: Mon, 26 Jun 2006 00:05:00 +0000 +Date: Mon, 26 Jun 2006 00:06:00 +0000 Subject: [DIFFERENT_PREFIX 0/2] *** SUBJECT HERE *** *** BLURB HERE *** diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all index d155e0bab2..44d45257da 100644 --- a/t/t4013/diff.log_--decorate=full_--all +++ b/t/t4013/diff.log_--decorate=full_--all @@ -1,4 +1,10 @@ $ git log --decorate=full --all +commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Rearranged lines in dir/sub + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, refs/heads/master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all index fd7c3e6439..27d3eabc26 100644 --- a/t/t4013/diff.log_--decorate_--all +++ b/t/t4013/diff.log_--decorate_--all @@ -1,4 +1,10 @@ $ git log --decorate --all +commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Rearranged lines in dir/sub + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4013/diff.log_-SF_master_--max-count=0 b/t/t4013/diff.log_-SF_master_--max-count=0 new file mode 100644 index 0000000000..c1fc6c8731 --- /dev/null +++ b/t/t4013/diff.log_-SF_master_--max-count=0 @@ -0,0 +1,2 @@ +$ git log -SF master --max-count=0 +$ diff --git a/t/t4013/diff.log_-SF_master_--max-count=1 b/t/t4013/diff.log_-SF_master_--max-count=1 new file mode 100644 index 0000000000..c981a03814 --- /dev/null +++ b/t/t4013/diff.log_-SF_master_--max-count=1 @@ -0,0 +1,7 @@ +$ git log -SF master --max-count=1 +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third +$ diff --git a/t/t4013/diff.log_-SF_master_--max-count=2 b/t/t4013/diff.log_-SF_master_--max-count=2 new file mode 100644 index 0000000000..a6c55fd482 --- /dev/null +++ b/t/t4013/diff.log_-SF_master_--max-count=2 @@ -0,0 +1,7 @@ +$ git log -SF master --max-count=2 +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third +$ diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 027c13d52c..67975129bc 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -179,12 +179,21 @@ test_expect_success 'configuration To: header' ' grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9 ' +# check_patch <patch>: Verify that <patch> looks like a half-sane +# patch email to avoid a false positive with !grep +check_patch () { + grep -e "^From:" "$1" && + grep -e "^Date:" "$1" && + grep -e "^Subject:" "$1" +} + test_expect_success '--no-to overrides config.to' ' git config --replace-all format.to \ "R. E. Cipient <rcipient@example.com>" && git format-patch --no-to --stdout master..side | sed -e "/^\$/q" >patch10 && + check_patch patch10 && ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10 ' @@ -195,6 +204,7 @@ test_expect_success '--no-to and --to replaces config.to' ' git format-patch --no-to --to="Someone Else <else@out.there>" \ --stdout master..side | sed -e "/^\$/q" >patch11 && + check_patch patch11 && ! grep "^To: Someone <someone@out.there>\$" patch11 && grep "^To: Someone Else <else@out.there>\$" patch11 ' @@ -205,15 +215,17 @@ test_expect_success '--no-cc overrides config.cc' ' "C. E. Cipient <rcipient@example.com>" && git format-patch --no-cc --stdout master..side | sed -e "/^\$/q" >patch12 && + check_patch patch12 && ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12 ' -test_expect_success '--no-add-headers overrides config.headers' ' +test_expect_success '--no-add-header overrides config.headers' ' git config --replace-all format.headers \ "Header1: B. E. Cipient <rcipient@example.com>" && - git format-patch --no-add-headers --stdout master..side | + git format-patch --no-add-header --stdout master..side | sed -e "/^\$/q" >patch13 && + check_patch patch13 && ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13 ' @@ -445,22 +457,22 @@ test_expect_success 'thread deep cover-letter in-reply-to' ' ' test_expect_success 'thread via config' ' - git config format.thread true && + test_config format.thread true && check_threading expect.thread master ' test_expect_success 'thread deep via config' ' - git config format.thread deep && + test_config format.thread deep && check_threading expect.deep master ' test_expect_success 'thread config + override' ' - git config format.thread deep && + test_config format.thread deep && check_threading expect.thread --thread master ' test_expect_success 'thread config + --no-thread' ' - git config format.thread deep && + test_config format.thread deep && check_threading expect.no-threading --no-thread master ' @@ -480,6 +492,7 @@ test_expect_success 'cover-letter inherits diff options' ' git mv file foo && git commit -m foo && git format-patch --cover-letter -1 && + check_patch 0000-cover-letter.patch && ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch && git format-patch --cover-letter -1 -M && grep "file => foo .* 0 *\$" 0000-cover-letter.patch @@ -616,11 +629,11 @@ echo "fatal: --check does not make sense" > expect.check test_expect_success 'options no longer allowed for format-patch' ' test_must_fail git format-patch --name-only 2> output && - test_cmp expect.name-only output && + test_i18ncmp expect.name-only output && test_must_fail git format-patch --name-status 2> output && - test_cmp expect.name-status output && + test_i18ncmp expect.name-status output && test_must_fail git format-patch --check 2> output && - test_cmp expect.check output' + test_i18ncmp expect.check output' test_expect_success 'format-patch --numstat should produce a patch' ' git format-patch --numstat --stdout master..side > output && @@ -657,6 +670,7 @@ test_expect_success 'format-patch --no-signature ignores format.signature' ' git config format.signature "config sig" && git format-patch --stdout --signature="my sig" --no-signature \ -1 >output && + check_patch output && ! grep "config sig" output && ! grep "my sig" output && ! grep "^-- \$" output @@ -673,17 +687,20 @@ test_expect_success 'format-patch --signature --cover-letter' ' test_expect_success 'format.signature="" supresses signatures' ' git config format.signature "" && git format-patch --stdout -1 >output && + check_patch output && ! grep "^-- \$" output ' test_expect_success 'format-patch --no-signature supresses signatures' ' git config --unset-all format.signature && git format-patch --stdout --no-signature -1 >output && + check_patch output && ! grep "^-- \$" output ' test_expect_success 'format-patch --signature="" supresses signatures' ' - git format-patch --signature="" -1 >output && + git format-patch --stdout --signature="" -1 >output && + check_patch output && ! grep "^-- \$" output ' @@ -709,4 +726,172 @@ test_expect_success TTY 'format-patch --stdout paginates' ' test_path_is_missing .git/pager_used ' +test_expect_success 'format-patch handles multi-line subjects' ' + rm -rf patches/ && + echo content >>file && + for i in one two three; do echo $i; done >msg && + git add file && + git commit -F msg && + git format-patch -o patches -1 && + grep ^Subject: patches/0001-one.patch >actual && + echo "Subject: [PATCH] one two three" >expect && + test_cmp expect actual +' + +test_expect_success 'format-patch handles multi-line encoded subjects' ' + rm -rf patches/ && + echo content >>file && + for i in en två tre; do echo $i; done >msg && + git add file && + git commit -F msg && + git format-patch -o patches -1 && + grep ^Subject: patches/0001-en.patch >actual && + echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect && + test_cmp expect actual +' + +M8="foo bar " +M64=$M8$M8$M8$M8$M8$M8$M8$M8 +M512=$M64$M64$M64$M64$M64$M64$M64$M64 +cat >expect <<'EOF' +Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo + bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar + foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo + bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar + foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo + bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar + foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo + bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar + foo bar foo bar foo bar foo bar +EOF +test_expect_success 'format-patch wraps extremely long headers (ascii)' ' + echo content >>file && + git add file && + git commit -m "$M512" && + git format-patch --stdout -1 >patch && + sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject && + test_cmp expect subject +' + +M8="föö bar " +M64=$M8$M8$M8$M8$M8$M8$M8$M8 +M512=$M64$M64$M64$M64$M64$M64$M64$M64 +cat >expect <<'EOF' +Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?= + =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?= +EOF +test_expect_success 'format-patch wraps extremely long headers (rfc2047)' ' + rm -rf patches/ && + echo content >>file && + git add file && + git commit -m "$M512" && + git format-patch --stdout -1 >patch && + sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject && + test_cmp expect subject +' + +M8="foo_bar_" +M64=$M8$M8$M8$M8$M8$M8$M8$M8 +cat >expect <<EOF +From: $M64 + <foobar@foo.bar> +EOF +test_expect_success 'format-patch wraps non-quotable headers' ' + rm -rf patches/ && + echo content >>file && + git add file && + git commit -mfoo --author "$M64 <foobar@foo.bar>" && + git format-patch --stdout -1 >patch && + sed -n "/^From: /p; /^ /p; /^$/q" <patch >from && + test_cmp expect from +' + +check_author() { + echo content >>file && + git add file && + GIT_AUTHOR_NAME=$1 git commit -m author-check && + git format-patch --stdout -1 >patch && + grep ^From: patch >actual && + test_cmp expect actual +} + +cat >expect <<'EOF' +From: "Foo B. Bar" <author@example.com> +EOF +test_expect_success 'format-patch quotes dot in headers' ' + check_author "Foo B. Bar" +' + +cat >expect <<'EOF' +From: "Foo \"The Baz\" Bar" <author@example.com> +EOF +test_expect_success 'format-patch quotes double-quote in headers' ' + check_author "Foo \"The Baz\" Bar" +' + +cat >expect <<'EOF' +From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com> +EOF +test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' ' + check_author "Föo B. Bar" +' + +cat >expect <<'EOF' +Subject: header with . in it +EOF +test_expect_success 'subject lines do not have 822 atom-quoting' ' + echo content >>file && + git add file && + git commit -m "header with . in it" && + git format-patch -k -1 --stdout >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Subject: [PREFIX 1/1] header with . in it +EOF +test_expect_success 'subject prefixes have space prepended' ' + git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Subject: [1/1] header with . in it +EOF +test_expect_success 'empty subject prefix does not have extra space' ' + git format-patch -n -1 --stdout --subject-prefix= >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +test_expect_success 'format patch ignores color.ui' ' + test_unconfig color.ui && + git format-patch --stdout -1 >expect && + test_config color.ui always && + git format-patch --stdout -1 >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 3646930623..b68c56b68c 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -9,8 +9,7 @@ test_description='Test custom diff function name patterns' LF=' ' - -cat > Beer.java << EOF +cat >Beer.java <<\EOF public class Beer { int special; @@ -29,61 +28,163 @@ public class Beer } } EOF +sed 's/beer\\/beer,\\/' <Beer.java >Beer-correct.java +cat >Beer.perl <<\EOT +package Beer; + +use strict; +use warnings; +use parent qw(Exporter); +our @EXPORT_OK = qw(round finalround); + +sub other; # forward declaration + +# hello + +sub round { + my ($n) = @_; + print "$n bottles of beer on the wall "; + print "$n bottles of beer\n"; + print "Take one down, pass it around, "; + $n = $n - 1; + print "$n bottles of beer on the wall.\n"; +} + +sub finalround +{ + print "Go to the store, buy some more\n"; + print "99 bottles of beer on the wall.\n"); +} + +sub withheredocument { + print <<"EOF" +decoy here-doc +EOF + # some lines of context + # to pad it out + print "hello\n"; +} + +__END__ + +=head1 NAME + +Beer - subroutine to output fragment of a drinking song + +=head1 SYNOPSIS + + use Beer qw(round finalround); + + sub song { + for (my $i = 99; $i > 0; $i--) { + round $i; + } + finalround; + } -sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java + song; -builtin_patterns="bibtex cpp csharp fortran html java objc pascal perl php python ruby tex" -for p in $builtin_patterns +=cut +EOT +sed -e ' + s/hello/goodbye/ + s/beer\\/beer,\\/ + s/more\\/more,\\/ + s/song;/song();/ +' <Beer.perl >Beer-correct.perl + +test_config () { + git config "$1" "$2" && + test_when_finished "git config --unset $1" +} + +test_expect_funcname () { + lang=${2-java} + test_expect_code 1 git diff --no-index -U1 \ + "Beer.$lang" "Beer-correct.$lang" >diff && + grep "^@@.*@@ $1" diff +} + +for p in bibtex cpp csharp fortran html java objc pascal perl php python ruby tex do test_expect_success "builtin $p pattern compiles" ' - echo "*.java diff=$p" > .gitattributes && - ! { git diff --no-index Beer.java Beer-correct.java 2>&1 | - grep "fatal" > /dev/null; } + echo "*.java diff=$p" >.gitattributes && + test_expect_code 1 git diff --no-index \ + Beer.java Beer-correct.java 2>msg && + ! grep fatal msg && + ! grep error msg ' test_expect_success "builtin $p wordRegex pattern compiles" ' - ! { git diff --no-index --word-diff \ - Beer.java Beer-correct.java 2>&1 | - grep "fatal" > /dev/null; } + echo "*.java diff=$p" >.gitattributes && + test_expect_code 1 git diff --no-index --word-diff \ + Beer.java Beer-correct.java 2>msg && + ! grep fatal msg && + ! grep error msg ' done test_expect_success 'default behaviour' ' rm -f .gitattributes && - git diff --no-index Beer.java Beer-correct.java | - grep "^@@.*@@ public class Beer" + test_expect_funcname "public class Beer\$" +' + +test_expect_success 'set up .gitattributes declaring drivers to test' ' + cat >.gitattributes <<-\EOF + *.java diff=java + *.perl diff=perl + EOF ' test_expect_success 'preset java pattern' ' - echo "*.java diff=java" >.gitattributes && - git diff --no-index Beer.java Beer-correct.java | - grep "^@@.*@@ public static void main(" + test_expect_funcname "public static void main(" ' -git config diff.java.funcname '!static -!String -[^ ].*s.*' +test_expect_success 'preset perl pattern' ' + test_expect_funcname "sub round {\$" perl +' + +test_expect_success 'perl pattern accepts K&R style brace placement, too' ' + test_expect_funcname "sub finalround\$" perl +' + +test_expect_success 'but is not distracted by end of <<here document' ' + test_expect_funcname "sub withheredocument {\$" perl +' + +test_expect_success 'perl pattern is not distracted by sub within POD' ' + test_expect_funcname "=head" perl +' + +test_expect_success 'perl pattern gets full line of POD header' ' + test_expect_funcname "=head1 SYNOPSIS\$" perl +' + +test_expect_success 'perl pattern is not distracted by forward declaration' ' + test_expect_funcname "package Beer;\$" perl +' test_expect_success 'custom pattern' ' - git diff --no-index Beer.java Beer-correct.java | - grep "^@@.*@@ int special;$" + test_config diff.java.funcname "!static +!String +[^ ].*s.*" && + test_expect_funcname "int special;\$" ' test_expect_success 'last regexp must not be negated' ' - git config diff.java.funcname "!static" && - git diff --no-index Beer.java Beer-correct.java 2>&1 | - grep "fatal: Last expression must not be negated:" + test_config diff.java.funcname "!static" && + test_expect_code 128 git diff --no-index Beer.java Beer-correct.java 2>msg && + grep ": Last expression must not be negated:" msg ' test_expect_success 'pattern which matches to end of line' ' - git config diff.java.funcname "Beer$" && - git diff --no-index Beer.java Beer-correct.java | - grep "^@@.*@@ Beer" + test_config diff.java.funcname "Beer\$" && + test_expect_funcname "Beer\$" ' test_expect_success 'alternation in pattern' ' - git config diff.java.xfuncname "^[ ]*((public|static).*)$" && - git diff --no-index Beer.java Beer-correct.java | - grep "^@@.*@@ public static void main(" + test_config diff.java.funcname "Beer$" && + test_config diff.java.xfuncname "^[ ]*((public|static).*)$" && + test_expect_funcname "public static void main(" ' test_done diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index a7602cf923..083f62d1d6 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -4,8 +4,6 @@ test_description='external diff interface test' . ./test-lib.sh -_z40=0000000000000000000000000000000000000000 - test_expect_success setup ' test_tick && diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh index 2a537a21e8..c00a94b9ba 100755 --- a/t/t4022-diff-rewrite.sh +++ b/t/t4022-diff-rewrite.sh @@ -11,7 +11,9 @@ test_expect_success setup ' tr \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \ "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \ - <"$TEST_DIRECTORY"/../COPYING >test + <"$TEST_DIRECTORY"/../COPYING >test && + echo "to be deleted" >test2 && + git add test2 ' @@ -25,5 +27,44 @@ test_expect_success 'detect rewrite' ' ' +cat >expect <<EOF +diff --git a/test2 b/test2 +deleted file mode 100644 +index 4202011..0000000 +--- a/test2 ++++ /dev/null +@@ -1 +0,0 @@ +-to be deleted +EOF +test_expect_success 'show deletion diff without -D' ' + + rm test2 && + git diff -- test2 >actual && + test_cmp expect actual +' + +cat >expect <<EOF +diff --git a/test2 b/test2 +deleted file mode 100644 +index 4202011..0000000 +EOF +test_expect_success 'suppress deletion diff with -D' ' + + git diff -D -- test2 >actual && + test_cmp expect actual +' + +test_expect_success 'show deletion diff with -B' ' + + git diff -B -- test >actual && + grep "Linus Torvalds" actual +' + +test_expect_success 'suppress deletion diff with -B -D' ' + + git diff -B -D -- test >actual && + grep -v "Linus Torvalds" actual +' + test_done diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 241a74d2a2..518bf9524e 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -5,7 +5,6 @@ test_description='difference in submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -_z40=0000000000000000000000000000000000000000 test_expect_success setup ' test_tick && test_create_repo sub && diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh index 7e7b307a24..7d7470f21b 100755 --- a/t/t4031-diff-rewrite-binary.sh +++ b/t/t4031-diff-rewrite-binary.sh @@ -44,6 +44,13 @@ test_expect_success 'rewrite diff can show binary patch' ' grep "GIT binary patch" diff ' +test_expect_success 'rewrite diff --stat shows binary changes' ' + git diff -B --stat --summary >diff && + grep "Bin" diff && + grep "0 insertions.*0 deletions" diff && + grep " rewrite file" diff +' + { echo "#!$SHELL_PATH" cat <<'EOF' diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh index 1eb14989df..3c9932edf3 100755 --- a/t/t4033-diff-patience.sh +++ b/t/t4033-diff-patience.sh @@ -3,166 +3,10 @@ test_description='patience diff algorithm' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-diff-alternative.sh -cat >file1 <<\EOF -#include <stdio.h> +test_diff_frobnitz "patience" -// Frobs foo heartily -int frobnitz(int foo) -{ - int i; - for(i = 0; i < 10; i++) - { - printf("Your answer is: "); - printf("%d\n", foo); - } -} - -int fact(int n) -{ - if(n > 1) - { - return fact(n-1) * n; - } - return 1; -} - -int main(int argc, char **argv) -{ - frobnitz(fact(10)); -} -EOF - -cat >file2 <<\EOF -#include <stdio.h> - -int fib(int n) -{ - if(n > 2) - { - return fib(n-1) + fib(n-2); - } - return 1; -} - -// Frobs foo heartily -int frobnitz(int foo) -{ - int i; - for(i = 0; i < 10; i++) - { - printf("%d\n", foo); - } -} - -int main(int argc, char **argv) -{ - frobnitz(fib(10)); -} -EOF - -cat >expect <<\EOF -diff --git a/file1 b/file2 -index 6faa5a3..e3af329 100644 ---- a/file1 -+++ b/file2 -@@ -1,26 +1,25 @@ - #include <stdio.h> - -+int fib(int n) -+{ -+ if(n > 2) -+ { -+ return fib(n-1) + fib(n-2); -+ } -+ return 1; -+} -+ - // Frobs foo heartily - int frobnitz(int foo) - { - int i; - for(i = 0; i < 10; i++) - { -- printf("Your answer is: "); - printf("%d\n", foo); - } - } - --int fact(int n) --{ -- if(n > 1) -- { -- return fact(n-1) * n; -- } -- return 1; --} -- - int main(int argc, char **argv) - { -- frobnitz(fact(10)); -+ frobnitz(fib(10)); - } -EOF - -test_expect_success 'patience diff' ' - - test_must_fail git diff --no-index --patience file1 file2 > output && - test_cmp expect output - -' - -test_expect_success 'patience diff output is valid' ' - - mv file2 expect && - git apply < output && - test_cmp expect file2 - -' - -cat >uniq1 <<\EOF -1 -2 -3 -4 -5 -6 -EOF - -cat >uniq2 <<\EOF -a -b -c -d -e -f -EOF - -cat >expect <<\EOF -diff --git a/uniq1 b/uniq2 -index b414108..0fdf397 100644 ---- a/uniq1 -+++ b/uniq2 -@@ -1,6 +1,6 @@ --1 --2 --3 --4 --5 --6 -+a -+b -+c -+d -+e -+f -EOF - -test_expect_success 'completely different files' ' - - test_must_fail git diff --no-index --patience uniq1 uniq2 > output && - test_cmp expect output - -' +test_diff_unique "patience" test_done diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 8096d8a337..c374aa4c1c 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -4,331 +4,333 @@ test_description='word diff colors' . ./test-lib.sh -test_expect_success setup ' +cat >pre.simple <<-\EOF + h(4) - git config diff.color.old red && - git config diff.color.new green && - git config diff.color.func magenta + a = b + c +EOF +cat >post.simple <<-\EOF + h(4),hh[44] -' + a = b + c -word_diff () { - test_must_fail git diff --no-index "$@" pre post > output && - test_decode_color <output >output.decrypted && - test_cmp expect output.decrypted -} + aa = a -cat > pre <<\EOF -h(4) - -a = b + c + aeff = aeff * ( aaa ) EOF +cat >expect.letter-runs-are-words <<-\EOF + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + h(4),<GREEN>hh<RESET>[44] -cat > post <<\EOF -h(4),hh[44] - -a = b + c + a = b + c<RESET> -aa = a + <GREEN>aa = a<RESET> -aeff = aeff * ( aaa ) + <GREEN>aeff = aeff * ( aaa<RESET> ) EOF +cat >expect.non-whitespace-is-word <<-\EOF + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + h(4)<GREEN>,hh[44]<RESET> -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> - -a = b + c<RESET> + a = b + c<RESET> -<GREEN>aa = a<RESET> + <GREEN>aa = a<RESET> -<GREEN>aeff = aeff * ( aaa )<RESET> + <GREEN>aeff = aeff * ( aaa )<RESET> EOF -test_expect_success 'word diff with runs of whitespace' ' +word_diff () { + test_must_fail git diff --no-index "$@" pre post >output && + test_decode_color <output >output.decrypted && + test_cmp expect output.decrypted +} - word_diff --color-words +test_language_driver () { + lang=$1 + test_expect_success "diff driver '$lang'" ' + cp "$TEST_DIRECTORY/t4034/'"$lang"'/pre" \ + "$TEST_DIRECTORY/t4034/'"$lang"'/post" \ + "$TEST_DIRECTORY/t4034/'"$lang"'/expect" . && + echo "* diff='"$lang"'" >.gitattributes && + word_diff --color-words + ' +} +test_expect_success setup ' + git config diff.color.old red && + git config diff.color.new green && + git config diff.color.func magenta ' -test_expect_success '--word-diff=color' ' - - word_diff --word-diff=color - +test_expect_success 'set up pre and post with runs of whitespace' ' + cp pre.simple pre && + cp post.simple post ' -test_expect_success '--color --word-diff=color' ' - +test_expect_success 'word diff with runs of whitespace' ' + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + <RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> + + a = b + c<RESET> + + <GREEN>aa = a<RESET> + + <GREEN>aeff = aeff * ( aaa )<RESET> + EOF + word_diff --color-words && + word_diff --word-diff=color && word_diff --color --word-diff=color - ' -sed 's/#.*$//' > expect <<EOF -diff --git a/pre b/post -index 330b04f..5ed8eff 100644 ---- a/pre -+++ b/post -@@ -1,3 +1,7 @@ --h(4) -+h(4),hh[44] -~ - # significant space -~ - a = b + c -~ -~ -+aa = a -~ -~ -+aeff = aeff * ( aaa ) -~ -EOF - test_expect_success '--word-diff=porcelain' ' - + sed 's/#.*$//' >expect <<-\EOF && + diff --git a/pre b/post + index 330b04f..5ed8eff 100644 + --- a/pre + +++ b/post + @@ -1,3 +1,7 @@ + -h(4) + +h(4),hh[44] + ~ + # significant space + ~ + a = b + c + ~ + ~ + +aa = a + ~ + ~ + +aeff = aeff * ( aaa ) + ~ + EOF word_diff --word-diff=porcelain - ' -cat > expect <<EOF -diff --git a/pre b/post -index 330b04f..5ed8eff 100644 ---- a/pre -+++ b/post -@@ -1,3 +1,7 @@ -[-h(4)-]{+h(4),hh[44]+} - -a = b + c - -{+aa = a+} - -{+aeff = aeff * ( aaa )+} -EOF - test_expect_success '--word-diff=plain' ' + cat >expect <<-\EOF && + diff --git a/pre b/post + index 330b04f..5ed8eff 100644 + --- a/pre + +++ b/post + @@ -1,3 +1,7 @@ + [-h(4)-]{+h(4),hh[44]+} - word_diff --word-diff=plain - -' + a = b + c -test_expect_success '--word-diff=plain --no-color' ' + {+aa = a+} + {+aeff = aeff * ( aaa )+} + EOF + word_diff --word-diff=plain && word_diff --word-diff=plain --no-color - ' -cat > expect <<EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -<RED>[-h(4)-]<RESET><GREEN>{+h(4),hh[44]+}<RESET> - -a = b + c<RESET> - -<GREEN>{+aa = a+}<RESET> +test_expect_success '--word-diff=plain --color' ' + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + <RED>[-h(4)-]<RESET><GREEN>{+h(4),hh[44]+}<RESET> -<GREEN>{+aeff = aeff * ( aaa )+}<RESET> -EOF + a = b + c<RESET> -test_expect_success '--word-diff=plain --color' ' + <GREEN>{+aa = a+}<RESET> + <GREEN>{+aeff = aeff * ( aaa )+}<RESET> + EOF word_diff --word-diff=plain --color - ' -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1 +1 @@<RESET> -<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> -<CYAN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET> - -<GREEN>aa = a<RESET> - -<GREEN>aeff = aeff * ( aaa )<RESET> -EOF - test_expect_success 'word diff without context' ' - + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1 +1 @@<RESET> + <RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> + <CYAN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET> + + <GREEN>aa = a<RESET> + + <GREEN>aeff = aeff * ( aaa )<RESET> + EOF word_diff --color-words --unified=0 - ' -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -h(4),<GREEN>hh<RESET>[44] - -a = b + c<RESET> - -<GREEN>aa = a<RESET> - -<GREEN>aeff = aeff * ( aaa<RESET> ) -EOF -cp expect expect.letter-runs-are-words - test_expect_success 'word diff with a regular expression' ' - + cp expect.letter-runs-are-words expect && word_diff --color-words="[a-z]+" - ' -test_expect_success 'set a diff driver' ' +test_expect_success 'set up a diff driver' ' git config diff.testdriver.wordRegex "[^[:space:]]" && - cat <<EOF > .gitattributes -pre diff=testdriver -post diff=testdriver -EOF + cat <<-\EOF >.gitattributes + pre diff=testdriver + post diff=testdriver + EOF ' test_expect_success 'option overrides .gitattributes' ' - + cp expect.letter-runs-are-words expect && word_diff --color-words="[a-z]+" - ' -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -h(4)<GREEN>,hh[44]<RESET> - -a = b + c<RESET> - -<GREEN>aa = a<RESET> - -<GREEN>aeff = aeff * ( aaa )<RESET> -EOF -cp expect expect.non-whitespace-is-word - test_expect_success 'use regex supplied by driver' ' - + cp expect.non-whitespace-is-word expect && word_diff --color-words - ' -test_expect_success 'set diff.wordRegex option' ' +test_expect_success 'set up diff.wordRegex option' ' git config diff.wordRegex "[[:alnum:]]+" ' -cp expect.letter-runs-are-words expect - test_expect_success 'command-line overrides config' ' + cp expect.letter-runs-are-words expect && word_diff --color-words="[a-z]+" ' -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -h(4),<GREEN>{+hh+}<RESET>[44] - -a = b + c<RESET> +test_expect_success 'command-line overrides config: --word-diff-regex' ' + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + h(4),<GREEN>{+hh+}<RESET>[44] -<GREEN>{+aa = a+}<RESET> + a = b + c<RESET> -<GREEN>{+aeff = aeff * ( aaa+}<RESET> ) -EOF + <GREEN>{+aa = a+}<RESET> -test_expect_success 'command-line overrides config: --word-diff-regex' ' + <GREEN>{+aeff = aeff * ( aaa+}<RESET> ) + EOF word_diff --color --word-diff-regex="[a-z]+" ' -cp expect.non-whitespace-is-word expect - test_expect_success '.gitattributes override config' ' + cp expect.non-whitespace-is-word expect && word_diff --color-words ' -test_expect_success 'remove diff driver regex' ' - git config --unset diff.testdriver.wordRegex +test_expect_success 'setup: remove diff driver regex' ' + test_might_fail git config --unset diff.testdriver.wordRegex ' -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 330b04f..5ed8eff 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1,3 +1,7 @@<RESET> -h(4),<GREEN>hh[44<RESET>] - -a = b + c<RESET> +test_expect_success 'use configured regex' ' + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1,3 +1,7 @@<RESET> + h(4),<GREEN>hh[44<RESET>] -<GREEN>aa = a<RESET> + a = b + c<RESET> -<GREEN>aeff = aeff * ( aaa<RESET> ) -EOF + <GREEN>aa = a<RESET> -test_expect_success 'use configured regex' ' + <GREEN>aeff = aeff * ( aaa<RESET> ) + EOF word_diff --color-words ' -echo 'aaa (aaa)' > pre -echo 'aaa (aaa) aaa' > post - -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index c29453b..be22f37 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1 +1 @@<RESET> -aaa (aaa) <GREEN>aaa<RESET> -EOF - test_expect_success 'test parsing words for newline' ' - + echo "aaa (aaa)" >pre && + echo "aaa (aaa) aaa" >post && + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index c29453b..be22f37 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1 +1 @@<RESET> + aaa (aaa) <GREEN>aaa<RESET> + EOF word_diff --color-words="a+" - - ' -echo '(:' > pre -echo '(' > post - -cat > expect <<\EOF -<BOLD>diff --git a/pre b/post<RESET> -<BOLD>index 289cb9d..2d06f37 100644<RESET> -<BOLD>--- a/pre<RESET> -<BOLD>+++ b/post<RESET> -<CYAN>@@ -1 +1 @@<RESET> -(<RED>:<RESET> -EOF - test_expect_success 'test when words are only removed at the end' ' - + echo "(:" >pre && + echo "(" >post && + cat >expect <<-\EOF && + <BOLD>diff --git a/pre b/post<RESET> + <BOLD>index 289cb9d..2d06f37 100644<RESET> + <BOLD>--- a/pre<RESET> + <BOLD>+++ b/post<RESET> + <CYAN>@@ -1 +1 @@<RESET> + (<RED>:<RESET> + EOF word_diff --color-words=. - ' -cat > expect <<\EOF -diff --git a/pre b/post -index 289cb9d..2d06f37 100644 ---- a/pre -+++ b/post -@@ -1 +1 @@ --(: -+( -EOF - test_expect_success '--word-diff=none' ' - + echo "(:" >pre && + echo "(" >post && + cat >expect <<-\EOF && + diff --git a/pre b/post + index 289cb9d..2d06f37 100644 + --- a/pre + +++ b/post + @@ -1 +1 @@ + -(: + +( + EOF word_diff --word-diff=plain --word-diff=none +' +test_language_driver bibtex +test_language_driver cpp +test_language_driver csharp +test_language_driver fortran +test_language_driver html +test_language_driver java +test_language_driver objc +test_language_driver pascal +test_language_driver perl +test_language_driver php +test_language_driver python +test_language_driver ruby +test_language_driver tex + +test_expect_success 'word-diff with diff.sbe' ' + cat >expect <<-\EOF && + diff --git a/pre b/post + index a1a53b5..bc8fe6d 100644 + --- a/pre + +++ b/post + @@ -1,3 +1,3 @@ + a + + [-b-]{+c+} + EOF + cat >pre <<-\EOF && + a + + b + EOF + cat >post <<-\EOF && + a + + c + EOF + test_when_finished "git config --unset diff.suppress-blank-empty" && + git config diff.suppress-blank-empty true && + word_diff --word-diff=plain ' test_done diff --git a/t/t4034/bibtex/expect b/t/t4034/bibtex/expect new file mode 100644 index 0000000000..a157774f9d --- /dev/null +++ b/t/t4034/bibtex/expect @@ -0,0 +1,15 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 95cd55b..ddcba9b 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,9 +1,10 @@<RESET> +@article{aldous1987uie,<RESET> + title={{Ultimate instability of exponential back-off protocol for acknowledgment-based transmission control of random access communication channels}},<RESET> + author={Aldous, <RED>D.<RESET><GREEN>David<RESET>}, + journal={Information Theory, IEEE Transactions on},<RESET> + volume={<RED>33<RESET><GREEN>Bogus.<RESET>}, + number={<RED>2<RESET><GREEN>4<RESET>}, + pages={219--223},<RESET> + year=<GREEN>1987,<RESET> +<GREEN> note={This is in fact a rather funny read since ethernet works well in practice. The<RESET> {<RED>1987<RESET><GREEN>\em pre} reference is the right one, however.<RESET>}<RED>,<RESET> +}<RESET> diff --git a/t/t4034/bibtex/post b/t/t4034/bibtex/post new file mode 100644 index 0000000000..ddcba9b2fc --- /dev/null +++ b/t/t4034/bibtex/post @@ -0,0 +1,10 @@ +@article{aldous1987uie, + title={{Ultimate instability of exponential back-off protocol for acknowledgment-based transmission control of random access communication channels}}, + author={Aldous, David}, + journal={Information Theory, IEEE Transactions on}, + volume={Bogus.}, + number={4}, + pages={219--223}, + year=1987, + note={This is in fact a rather funny read since ethernet works well in practice. The {\em pre} reference is the right one, however.} +} diff --git a/t/t4034/bibtex/pre b/t/t4034/bibtex/pre new file mode 100644 index 0000000000..95cd55bd7b --- /dev/null +++ b/t/t4034/bibtex/pre @@ -0,0 +1,9 @@ +@article{aldous1987uie, + title={{Ultimate instability of exponential back-off protocol for acknowledgment-based transmission control of random access communication channels}}, + author={Aldous, D.}, + journal={Information Theory, IEEE Transactions on}, + volume={33}, + number={2}, + pages={219--223}, + year={1987}, +} diff --git a/t/t4034/cpp/expect b/t/t4034/cpp/expect new file mode 100644 index 0000000000..37d1ea2587 --- /dev/null +++ b/t/t4034/cpp/expect @@ -0,0 +1,36 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 23d5c8a..7e8c026 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,19 +1,19 @@<RESET> +Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <GREEN>bar(x);<RESET> } +cout<<"Hello World<RED>!<RESET><GREEN>?<RESET>\n"<<endl; +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y +<RED>a<RESET><GREEN>x<RESET>::<RED>b<RESET><GREEN>y<RESET> diff --git a/t/t4034/cpp/post b/t/t4034/cpp/post new file mode 100644 index 0000000000..7e8c026cef --- /dev/null +++ b/t/t4034/cpp/post @@ -0,0 +1,19 @@ +Foo() : x(0&42) { bar(x); } +cout<<"Hello World?\n"<<endl; +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y +x::y diff --git a/t/t4034/cpp/pre b/t/t4034/cpp/pre new file mode 100644 index 0000000000..23d5c8adf5 --- /dev/null +++ b/t/t4034/cpp/pre @@ -0,0 +1,19 @@ +Foo():x(0&&1){} +cout<<"Hello World!\n"<<endl; +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y +a::b diff --git a/t/t4034/csharp/expect b/t/t4034/csharp/expect new file mode 100644 index 0000000000..e5d1dd2b3d --- /dev/null +++ b/t/t4034/csharp/expect @@ -0,0 +1,35 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 9106d63..dd5f421 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,18 +1,18 @@<RESET> +Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <GREEN>bar(x);<RESET> } +cout<<"Hello World<RED>!<RESET><GREEN>?<RESET>\n"<<endl; +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y diff --git a/t/t4034/csharp/post b/t/t4034/csharp/post new file mode 100644 index 0000000000..dd5f4218a6 --- /dev/null +++ b/t/t4034/csharp/post @@ -0,0 +1,18 @@ +Foo() : x(0&42) { bar(x); } +cout<<"Hello World?\n"<<endl; +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y diff --git a/t/t4034/csharp/pre b/t/t4034/csharp/pre new file mode 100644 index 0000000000..9106d63e87 --- /dev/null +++ b/t/t4034/csharp/pre @@ -0,0 +1,18 @@ +Foo():x(0&&1){} +cout<<"Hello World!\n"<<endl; +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y diff --git a/t/t4034/fortran/expect b/t/t4034/fortran/expect new file mode 100644 index 0000000000..b233dbd621 --- /dev/null +++ b/t/t4034/fortran/expect @@ -0,0 +1,10 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 87f0d0b..d308da2 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,5 +1,5 @@<RESET> +print *, "Hello World<RED>!<RESET><GREEN>?<RESET>" + +DO10I = 1,10<RESET> +<RED>DO10I<RESET><GREEN>DO 10 I<RESET> = 1,10 +<RED>DO10I<RESET><GREEN>DO 1 0 I<RESET> = 1,10 diff --git a/t/t4034/fortran/post b/t/t4034/fortran/post new file mode 100644 index 0000000000..d308da2ad2 --- /dev/null +++ b/t/t4034/fortran/post @@ -0,0 +1,5 @@ +print *, "Hello World?" + +DO10I = 1,10 +DO 10 I = 1,10 +DO 1 0 I = 1,10 diff --git a/t/t4034/fortran/pre b/t/t4034/fortran/pre new file mode 100644 index 0000000000..87f0d0b031 --- /dev/null +++ b/t/t4034/fortran/pre @@ -0,0 +1,5 @@ +print *, "Hello World!" + +DO10I = 1,10 +DO10I = 1,10 +DO10I = 1,10 diff --git a/t/t4034/html/expect b/t/t4034/html/expect new file mode 100644 index 0000000000..447b49ab6d --- /dev/null +++ b/t/t4034/html/expect @@ -0,0 +1,8 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 8ca4aea..46921e5 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,3 +1,3 @@<RESET> +<tag <GREEN>newattr="newvalue"<RESET>><GREEN>added<RESET> content</tag> +<tag attr=<RED>"value"<RESET><GREEN>"newvalue"<RESET>><RED>content<RESET><GREEN>changed<RESET></tag> +<<RED>tag<RESET><GREEN>newtag<RESET>>content <RED>&entity;<RESET><GREEN>&newentity;<RESET><<RED>/tag<RESET><GREEN>/newtag<RESET>> diff --git a/t/t4034/html/post b/t/t4034/html/post new file mode 100644 index 0000000000..46921e586c --- /dev/null +++ b/t/t4034/html/post @@ -0,0 +1,3 @@ +<tag newattr="newvalue">added content</tag> +<tag attr="newvalue">changed</tag> +<newtag>content &newentity;</newtag> diff --git a/t/t4034/html/pre b/t/t4034/html/pre new file mode 100644 index 0000000000..8ca4aeae83 --- /dev/null +++ b/t/t4034/html/pre @@ -0,0 +1,3 @@ +<tag>content</tag> +<tag attr="value">content</tag> +<tag>content &entity;</tag> diff --git a/t/t4034/java/expect b/t/t4034/java/expect new file mode 100644 index 0000000000..37d1ea2587 --- /dev/null +++ b/t/t4034/java/expect @@ -0,0 +1,36 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 23d5c8a..7e8c026 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,19 +1,19 @@<RESET> +Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <GREEN>bar(x);<RESET> } +cout<<"Hello World<RED>!<RESET><GREEN>?<RESET>\n"<<endl; +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y +<RED>a<RESET><GREEN>x<RESET>::<RED>b<RESET><GREEN>y<RESET> diff --git a/t/t4034/java/post b/t/t4034/java/post new file mode 100644 index 0000000000..7e8c026cef --- /dev/null +++ b/t/t4034/java/post @@ -0,0 +1,19 @@ +Foo() : x(0&42) { bar(x); } +cout<<"Hello World?\n"<<endl; +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y +x::y diff --git a/t/t4034/java/pre b/t/t4034/java/pre new file mode 100644 index 0000000000..23d5c8adf5 --- /dev/null +++ b/t/t4034/java/pre @@ -0,0 +1,19 @@ +Foo():x(0&&1){} +cout<<"Hello World!\n"<<endl; +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y +a::b diff --git a/t/t4034/objc/expect b/t/t4034/objc/expect new file mode 100644 index 0000000000..e5d1dd2b3d --- /dev/null +++ b/t/t4034/objc/expect @@ -0,0 +1,35 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 9106d63..dd5f421 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,18 +1,18 @@<RESET> +Foo() : x(0<RED>&&1<RESET><GREEN>&42<RESET>) { <GREEN>bar(x);<RESET> } +cout<<"Hello World<RED>!<RESET><GREEN>?<RESET>\n"<<endl; +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y diff --git a/t/t4034/objc/post b/t/t4034/objc/post new file mode 100644 index 0000000000..dd5f4218a6 --- /dev/null +++ b/t/t4034/objc/post @@ -0,0 +1,18 @@ +Foo() : x(0&42) { bar(x); } +cout<<"Hello World?\n"<<endl; +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y diff --git a/t/t4034/objc/pre b/t/t4034/objc/pre new file mode 100644 index 0000000000..9106d63e87 --- /dev/null +++ b/t/t4034/objc/pre @@ -0,0 +1,18 @@ +Foo():x(0&&1){} +cout<<"Hello World!\n"<<endl; +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y diff --git a/t/t4034/pascal/expect b/t/t4034/pascal/expect new file mode 100644 index 0000000000..2ce4230954 --- /dev/null +++ b/t/t4034/pascal/expect @@ -0,0 +1,35 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 077046c..8865e6b 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,18 +1,18 @@<RESET> +writeln("Hello World<RED>!<RESET><GREEN>?<RESET>"); +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y +<RED>a<RESET><GREEN>x<RESET>::<RED>b<RESET><GREEN>y<RESET> diff --git a/t/t4034/pascal/post b/t/t4034/pascal/post new file mode 100644 index 0000000000..8865e6bddd --- /dev/null +++ b/t/t4034/pascal/post @@ -0,0 +1,18 @@ +writeln("Hello World?"); +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y +x::y diff --git a/t/t4034/pascal/pre b/t/t4034/pascal/pre new file mode 100644 index 0000000000..077046c832 --- /dev/null +++ b/t/t4034/pascal/pre @@ -0,0 +1,18 @@ +writeln("Hello World!"); +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y +a::b diff --git a/t/t4034/perl/expect b/t/t4034/perl/expect new file mode 100644 index 0000000000..a1deb6b6ad --- /dev/null +++ b/t/t4034/perl/expect @@ -0,0 +1,13 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index f6610d3..e8b72ef 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -4,8 +4,8 @@<RESET> + +package Frotz;<RESET> +sub new {<RESET> + my <GREEN>(<RESET>$class<GREEN>, %opts)<RESET> = <RED>shift<RESET><GREEN>@_<RESET>; + return bless { <GREEN>xyzzy => "nitfol", %opts<RESET> }, $class; +}<RESET> + +__END__<RESET> diff --git a/t/t4034/perl/post b/t/t4034/perl/post new file mode 100644 index 0000000000..e8b72ef5dc --- /dev/null +++ b/t/t4034/perl/post @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; + +package Frotz; +sub new { + my ($class, %opts) = @_; + return bless { xyzzy => "nitfol", %opts }, $class; +} + +__END__ +=head1 NAME + +frotz - Frotz + +=head1 SYNOPSIS + + use frotz; + + $nitfol = new Frotz(); + +=cut diff --git a/t/t4034/perl/pre b/t/t4034/perl/pre new file mode 100644 index 0000000000..f6610d37b8 --- /dev/null +++ b/t/t4034/perl/pre @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; + +package Frotz; +sub new { + my $class = shift; + return bless {}, $class; +} + +__END__ +=head1 NAME + +frotz - Frotz + +=head1 SYNOPSIS + + use frotz; + + $nitfol = new Frotz(); + +=cut diff --git a/t/t4034/php/expect b/t/t4034/php/expect new file mode 100644 index 0000000000..040440860a --- /dev/null +++ b/t/t4034/php/expect @@ -0,0 +1,35 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index cf6e06b..4420a49 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,18 +1,18 @@<RESET> +<GREEN>(<RESET>$var<GREEN>)<RESET> $ var +<?="Hello World<RED>!<RESET><GREEN>?<RESET>"?> +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y diff --git a/t/t4034/php/post b/t/t4034/php/post new file mode 100644 index 0000000000..4420a49192 --- /dev/null +++ b/t/t4034/php/post @@ -0,0 +1,18 @@ +($var) $ var +<?="Hello World?"?> +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y diff --git a/t/t4034/php/pre b/t/t4034/php/pre new file mode 100644 index 0000000000..cf6e06bc22 --- /dev/null +++ b/t/t4034/php/pre @@ -0,0 +1,18 @@ +$var $var +<?= "Hello World!" ?> +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y diff --git a/t/t4034/python/expect b/t/t4034/python/expect new file mode 100644 index 0000000000..8abb8a48b4 --- /dev/null +++ b/t/t4034/python/expect @@ -0,0 +1,34 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 438f776..68baf34 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,17 +1,17 @@<RESET> +print<RED>u<RESET> "Hello World<RED>!<RESET><GREEN>?<RESET>\n"<GREEN>; print<RESET> +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>) u<RESET>'<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>?<RED>b<RESET><GREEN>y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y diff --git a/t/t4034/python/post b/t/t4034/python/post new file mode 100644 index 0000000000..68baf34f0e --- /dev/null +++ b/t/t4034/python/post @@ -0,0 +1,17 @@ +print "Hello World?\n"; print +(1) (-1e10) (0xabcdef) u'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y diff --git a/t/t4034/python/pre b/t/t4034/python/pre new file mode 100644 index 0000000000..438f776875 --- /dev/null +++ b/t/t4034/python/pre @@ -0,0 +1,17 @@ +print u"Hello World!\n" +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y diff --git a/t/t4034/ruby/expect b/t/t4034/ruby/expect new file mode 100644 index 0000000000..16e1dd5674 --- /dev/null +++ b/t/t4034/ruby/expect @@ -0,0 +1,34 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 30ed9a1..7678f14 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,17 +1,17 @@<RESET> +10.downto(1) {|<RED>x<RESET><GREEN>y<RESET>| puts <RED>x<RESET><GREEN>y<RESET>} +<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>' +[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET> +!<RED>a<RESET><GREEN>x<RESET> ~<RED>a a<RESET><GREEN>x x<RESET>++ <RED>a<RESET><GREEN>x<RESET>-- <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<<RED>b a<RESET><GREEN>y x<RESET>>><RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>^<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>|<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>&&<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>||<RED>b<RESET> +<RED>a?b<RESET><GREEN>y<RESET> +<GREEN>x?y<RESET>:z +<RED>a<RESET><GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET> +<RED>a<RESET><GREEN>y<RESET> +<GREEN>x<RESET>,y diff --git a/t/t4034/ruby/post b/t/t4034/ruby/post new file mode 100644 index 0000000000..7678f14e14 --- /dev/null +++ b/t/t4034/ruby/post @@ -0,0 +1,17 @@ +10.downto(1) {|y| puts y} +(1) (-1e10) (0xabcdef) 'y' +[x] x->y x.y +!x ~x x++ x-- x*y x&y +x*y x/y x%y +x+y x-y +x<<y x>>y +x<y x<=y x>y x>=y +x==y x!=y +x&y +x^y +x|y +x&&y +x||y +x?y:z +x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y +x,y diff --git a/t/t4034/ruby/pre b/t/t4034/ruby/pre new file mode 100644 index 0000000000..30ed9a1595 --- /dev/null +++ b/t/t4034/ruby/pre @@ -0,0 +1,17 @@ +10.downto(1) {|x| puts x} +1 -1e10 0xabcdef 'x' +[a] a->b a.b +!a ~a a++ a-- a*b a&b +a*b a/b a%b +a+b a-b +a<<b a>>b +a<b a<=b a>b a>=b +a==b a!=b +a&b +a^b +a|b +a&&b +a||b +a?b:z +a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b +a,y diff --git a/t/t4034/tex/expect b/t/t4034/tex/expect new file mode 100644 index 0000000000..604969bcde --- /dev/null +++ b/t/t4034/tex/expect @@ -0,0 +1,9 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 2b2dfcb..65cab61 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,4 +1,4 @@<RESET> +\section{Something <GREEN>new<RESET>} +<RED>\emph<RESET><GREEN>\textbf<RESET>{Macro style} +{<RED>\em<RESET><GREEN>\bfseries<RESET> State toggle style} +\\[<RED>1em<RESET><GREEN>1cm<RESET>] diff --git a/t/t4034/tex/post b/t/t4034/tex/post new file mode 100644 index 0000000000..65cab61a10 --- /dev/null +++ b/t/t4034/tex/post @@ -0,0 +1,4 @@ +\section{Something new} +\textbf{Macro style} +{\bfseries State toggle style} +\\[1cm] diff --git a/t/t4034/tex/pre b/t/t4034/tex/pre new file mode 100644 index 0000000000..2b2dfcb65c --- /dev/null +++ b/t/t4034/tex/pre @@ -0,0 +1,4 @@ +\section{Something} +\emph{Macro style} +{\em State toggle style} +\\[1em] diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh index a30b03bcf2..3c728a3ebf 100755 --- a/t/t4040-whitespace-status.sh +++ b/t/t4040-whitespace-status.sh @@ -60,4 +60,16 @@ test_expect_success 'diff-files -b -p --exit-code' ' git diff-files -b -p --exit-code ' +test_expect_success 'diff-files --diff-filter --quiet' ' + git reset --hard && + rm a/d && + echo x >>b/e && + test_must_fail git diff-files --diff-filter=M --quiet +' + +test_expect_success 'diff-tree --diff-filter --quiet' ' + git commit -a -m "worktree state" && + test_must_fail git diff-tree --diff-filter=M --quiet HEAD^ HEAD +' + test_done diff --git a/t/t4046-diff-unmerged.sh b/t/t4046-diff-unmerged.sh new file mode 100755 index 0000000000..25d50a654a --- /dev/null +++ b/t/t4046-diff-unmerged.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='diff with unmerged index entries' +. ./test-lib.sh + +test_expect_success setup ' + for i in 0 1 2 3 + do + blob=$(echo $i | git hash-object --stdin) && + eval "blob$i=$blob" && + eval "m$i=\"100644 \$blob$i $i\"" || break + done && + paths= && + for b in o x + do + for o in o x + do + for t in o x + do + path="$b$o$t" && + case "$path" in ooo) continue ;; esac + paths="$paths$path " && + p=" $path" && + case "$b" in x) echo "$m1$p" ;; esac && + case "$o" in x) echo "$m2$p" ;; esac && + case "$t" in x) echo "$m3$p" ;; esac || + break + done || break + done || break + done >ls-files-s.expect && + git update-index --index-info <ls-files-s.expect && + git ls-files -s >ls-files-s.actual && + test_cmp ls-files-s.expect ls-files-s.actual +' + +test_expect_success 'diff-files -0' ' + for path in $paths + do + >"$path" && + echo ":000000 100644 $_z40 $_z40 U $path" + done >diff-files-0.expect && + git diff-files -0 >diff-files-0.actual && + test_cmp diff-files-0.expect diff-files-0.actual +' + +test_expect_success 'diff-files -1' ' + for path in $paths + do + >"$path" && + echo ":000000 100644 $_z40 $_z40 U $path" && + case "$path" in + x??) echo ":100644 100644 $blob1 $_z40 M $path" + esac + done >diff-files-1.expect && + git diff-files -1 >diff-files-1.actual && + test_cmp diff-files-1.expect diff-files-1.actual +' + +test_expect_success 'diff-files -2' ' + for path in $paths + do + >"$path" && + echo ":000000 100644 $_z40 $_z40 U $path" && + case "$path" in + ?x?) echo ":100644 100644 $blob2 $_z40 M $path" + esac + done >diff-files-2.expect && + git diff-files -2 >diff-files-2.actual && + test_cmp diff-files-2.expect diff-files-2.actual && + git diff-files >diff-files-default-2.actual && + test_cmp diff-files-2.expect diff-files-default-2.actual +' + +test_expect_success 'diff-files -3' ' + for path in $paths + do + >"$path" && + echo ":000000 100644 $_z40 $_z40 U $path" && + case "$path" in + ??x) echo ":100644 100644 $blob3 $_z40 M $path" + esac + done >diff-files-3.expect && + git diff-files -3 >diff-files-3.actual && + test_cmp diff-files-3.expect diff-files-3.actual +' + +test_done diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh new file mode 100755 index 0000000000..29e80a58cd --- /dev/null +++ b/t/t4047-diff-dirstat.sh @@ -0,0 +1,979 @@ +#!/bin/sh + +test_description='diff --dirstat tests' +. ./test-lib.sh + +# set up two commits where the second commit has these files +# (10 lines in each file): +# +# unchanged/text (unchanged from 1st commit) +# changed/text (changed 1st line) +# rearranged/text (swapped 1st and 2nd line) +# dst/copy/unchanged/text (copied from src/copy/unchanged/text, unchanged) +# dst/copy/changed/text (copied from src/copy/changed/text, changed) +# dst/copy/rearranged/text (copied from src/copy/rearranged/text, rearranged) +# dst/move/unchanged/text (moved from src/move/unchanged/text, unchanged) +# dst/move/changed/text (moved from src/move/changed/text, changed) +# dst/move/rearranged/text (moved from src/move/rearranged/text, rearranged) + +test_expect_success 'setup' ' + mkdir unchanged && + mkdir changed && + mkdir rearranged && + mkdir src && + mkdir src/copy && + mkdir src/copy/unchanged && + mkdir src/copy/changed && + mkdir src/copy/rearranged && + mkdir src/move && + mkdir src/move/unchanged && + mkdir src/move/changed && + mkdir src/move/rearranged && + cat <<EOF >unchanged/text && +unchanged line #0 +unchanged line #1 +unchanged line #2 +unchanged line #3 +unchanged line #4 +unchanged line #5 +unchanged line #6 +unchanged line #7 +unchanged line #8 +unchanged line #9 +EOF + cat <<EOF >changed/text && +changed line #0 +changed line #1 +changed line #2 +changed line #3 +changed line #4 +changed line #5 +changed line #6 +changed line #7 +changed line #8 +changed line #9 +EOF + cat <<EOF >rearranged/text && +rearranged line #0 +rearranged line #1 +rearranged line #2 +rearranged line #3 +rearranged line #4 +rearranged line #5 +rearranged line #6 +rearranged line #7 +rearranged line #8 +rearranged line #9 +EOF + cat <<EOF >src/copy/unchanged/text && +copy unchanged line #0 +copy unchanged line #1 +copy unchanged line #2 +copy unchanged line #3 +copy unchanged line #4 +copy unchanged line #5 +copy unchanged line #6 +copy unchanged line #7 +copy unchanged line #8 +copy unchanged line #9 +EOF + cat <<EOF >src/copy/changed/text && +copy changed line #0 +copy changed line #1 +copy changed line #2 +copy changed line #3 +copy changed line #4 +copy changed line #5 +copy changed line #6 +copy changed line #7 +copy changed line #8 +copy changed line #9 +EOF + cat <<EOF >src/copy/rearranged/text && +copy rearranged line #0 +copy rearranged line #1 +copy rearranged line #2 +copy rearranged line #3 +copy rearranged line #4 +copy rearranged line #5 +copy rearranged line #6 +copy rearranged line #7 +copy rearranged line #8 +copy rearranged line #9 +EOF + cat <<EOF >src/move/unchanged/text && +move unchanged line #0 +move unchanged line #1 +move unchanged line #2 +move unchanged line #3 +move unchanged line #4 +move unchanged line #5 +move unchanged line #6 +move unchanged line #7 +move unchanged line #8 +move unchanged line #9 +EOF + cat <<EOF >src/move/changed/text && +move changed line #0 +move changed line #1 +move changed line #2 +move changed line #3 +move changed line #4 +move changed line #5 +move changed line #6 +move changed line #7 +move changed line #8 +move changed line #9 +EOF + cat <<EOF >src/move/rearranged/text && +move rearranged line #0 +move rearranged line #1 +move rearranged line #2 +move rearranged line #3 +move rearranged line #4 +move rearranged line #5 +move rearranged line #6 +move rearranged line #7 +move rearranged line #8 +move rearranged line #9 +EOF + git add . && + git commit -m "initial" && + mkdir dst && + mkdir dst/copy && + mkdir dst/copy/unchanged && + mkdir dst/copy/changed && + mkdir dst/copy/rearranged && + mkdir dst/move && + mkdir dst/move/unchanged && + mkdir dst/move/changed && + mkdir dst/move/rearranged && + cat <<EOF >changed/text && +CHANGED XXXXXXX line #0 +changed line #1 +changed line #2 +changed line #3 +changed line #4 +changed line #5 +changed line #6 +changed line #7 +changed line #8 +changed line #9 +EOF + cat <<EOF >rearranged/text && +rearranged line #1 +rearranged line #0 +rearranged line #2 +rearranged line #3 +rearranged line #4 +rearranged line #5 +rearranged line #6 +rearranged line #7 +rearranged line #8 +rearranged line #9 +EOF + cat <<EOF >dst/copy/unchanged/text && +copy unchanged line #0 +copy unchanged line #1 +copy unchanged line #2 +copy unchanged line #3 +copy unchanged line #4 +copy unchanged line #5 +copy unchanged line #6 +copy unchanged line #7 +copy unchanged line #8 +copy unchanged line #9 +EOF + cat <<EOF >dst/copy/changed/text && +copy XXXCHANGED line #0 +copy changed line #1 +copy changed line #2 +copy changed line #3 +copy changed line #4 +copy changed line #5 +copy changed line #6 +copy changed line #7 +copy changed line #8 +copy changed line #9 +EOF + cat <<EOF >dst/copy/rearranged/text && +copy rearranged line #1 +copy rearranged line #0 +copy rearranged line #2 +copy rearranged line #3 +copy rearranged line #4 +copy rearranged line #5 +copy rearranged line #6 +copy rearranged line #7 +copy rearranged line #8 +copy rearranged line #9 +EOF + cat <<EOF >dst/move/unchanged/text && +move unchanged line #0 +move unchanged line #1 +move unchanged line #2 +move unchanged line #3 +move unchanged line #4 +move unchanged line #5 +move unchanged line #6 +move unchanged line #7 +move unchanged line #8 +move unchanged line #9 +EOF + cat <<EOF >dst/move/changed/text && +move XXXCHANGED line #0 +move changed line #1 +move changed line #2 +move changed line #3 +move changed line #4 +move changed line #5 +move changed line #6 +move changed line #7 +move changed line #8 +move changed line #9 +EOF + cat <<EOF >dst/move/rearranged/text && +move rearranged line #1 +move rearranged line #0 +move rearranged line #2 +move rearranged line #3 +move rearranged line #4 +move rearranged line #5 +move rearranged line #6 +move rearranged line #7 +move rearranged line #8 +move rearranged line #9 +EOF + git add . && + git rm -r src/move/unchanged && + git rm -r src/move/changed && + git rm -r src/move/rearranged && + git commit -m "changes" +' + +cat <<EOF >expect_diff_stat + changed/text | 2 +- + dst/copy/changed/text | 10 ++++++++++ + dst/copy/rearranged/text | 10 ++++++++++ + dst/copy/unchanged/text | 10 ++++++++++ + dst/move/changed/text | 10 ++++++++++ + dst/move/rearranged/text | 10 ++++++++++ + dst/move/unchanged/text | 10 ++++++++++ + rearranged/text | 2 +- + src/move/changed/text | 10 ---------- + src/move/rearranged/text | 10 ---------- + src/move/unchanged/text | 10 ---------- + 11 files changed, 62 insertions(+), 32 deletions(-) +EOF + +cat <<EOF >expect_diff_stat_M + changed/text | 2 +- + dst/copy/changed/text | 10 ++++++++++ + dst/copy/rearranged/text | 10 ++++++++++ + dst/copy/unchanged/text | 10 ++++++++++ + {src => dst}/move/changed/text | 2 +- + {src => dst}/move/rearranged/text | 2 +- + {src => dst}/move/unchanged/text | 0 + rearranged/text | 2 +- + 8 files changed, 34 insertions(+), 4 deletions(-) +EOF + +cat <<EOF >expect_diff_stat_CC + changed/text | 2 +- + {src => dst}/copy/changed/text | 2 +- + {src => dst}/copy/rearranged/text | 2 +- + {src => dst}/copy/unchanged/text | 0 + {src => dst}/move/changed/text | 2 +- + {src => dst}/move/rearranged/text | 2 +- + {src => dst}/move/unchanged/text | 0 + rearranged/text | 2 +- + 8 files changed, 6 insertions(+), 6 deletions(-) +EOF + +test_expect_success 'sanity check setup (--stat)' ' + git diff --stat HEAD^..HEAD >actual_diff_stat && + test_cmp expect_diff_stat actual_diff_stat && + git diff --stat -M HEAD^..HEAD >actual_diff_stat_M && + test_cmp expect_diff_stat_M actual_diff_stat_M && + git diff --stat -C -C HEAD^..HEAD >actual_diff_stat_CC && + test_cmp expect_diff_stat_CC actual_diff_stat_CC +' + +# changed/text and rearranged/text falls below default 3% threshold +cat <<EOF >expect_diff_dirstat + 10.8% dst/copy/changed/ + 10.8% dst/copy/rearranged/ + 10.8% dst/copy/unchanged/ + 10.8% dst/move/changed/ + 10.8% dst/move/rearranged/ + 10.8% dst/move/unchanged/ + 10.8% src/move/changed/ + 10.8% src/move/rearranged/ + 10.8% src/move/unchanged/ +EOF + +# rearranged/text falls below default 3% threshold +cat <<EOF >expect_diff_dirstat_M + 5.8% changed/ + 29.3% dst/copy/changed/ + 29.3% dst/copy/rearranged/ + 29.3% dst/copy/unchanged/ + 5.8% dst/move/changed/ +EOF + +# rearranged/text falls below default 3% threshold +cat <<EOF >expect_diff_dirstat_CC + 32.6% changed/ + 32.6% dst/copy/changed/ + 32.6% dst/move/changed/ +EOF + +test_expect_success 'various ways to misspell --dirstat' ' + test_must_fail git show --dirstat10 && + test_must_fail git show --dirstat10,files && + test_must_fail git show -X=20 && + test_must_fail git show -X=20,cumulative +' + +test_expect_success 'vanilla --dirstat' ' + git diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'vanilla -X' ' + git diff -X HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff -X -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff -X -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'explicit defaults: --dirstat=changes,noncumulative,3' ' + git diff --dirstat=changes,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=changes,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=changes,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'explicit defaults: -Xchanges,noncumulative,3' ' + git diff -Xchanges,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff -Xchanges,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff -Xchanges,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'later options override earlier options:' ' + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,10,cumulative,changes,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files --dirstat=10 --dirstat=cumulative --dirstat=changes --dirstat=noncumulative -X3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'non-defaults in config overridden by explicit defaults on command line' ' + git -c diff.dirstat=files,cumulative,50 diff --dirstat=changes,noncumulative,3 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=files,cumulative,50 diff --dirstat=changes,noncumulative,3 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=files,cumulative,50 diff --dirstat=changes,noncumulative,3 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 2.1% changed/ + 10.8% dst/copy/changed/ + 10.8% dst/copy/rearranged/ + 10.8% dst/copy/unchanged/ + 10.8% dst/move/changed/ + 10.8% dst/move/rearranged/ + 10.8% dst/move/unchanged/ + 0.0% rearranged/ + 10.8% src/move/changed/ + 10.8% src/move/rearranged/ + 10.8% src/move/unchanged/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 5.8% changed/ + 29.3% dst/copy/changed/ + 29.3% dst/copy/rearranged/ + 29.3% dst/copy/unchanged/ + 5.8% dst/move/changed/ + 0.1% dst/move/rearranged/ + 0.1% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 32.6% changed/ + 32.6% dst/copy/changed/ + 0.6% dst/copy/rearranged/ + 32.6% dst/move/changed/ + 0.6% dst/move/rearranged/ + 0.6% rearranged/ +EOF + +test_expect_success '--dirstat=0' ' + git diff --dirstat=0 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=0 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=0 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '-X0' ' + git diff -X0 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff -X0 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff -X0 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=0' ' + git -c diff.dirstat=0 diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=0 diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=0 diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 2.1% changed/ + 10.8% dst/copy/changed/ + 10.8% dst/copy/rearranged/ + 10.8% dst/copy/unchanged/ + 32.5% dst/copy/ + 10.8% dst/move/changed/ + 10.8% dst/move/rearranged/ + 10.8% dst/move/unchanged/ + 32.5% dst/move/ + 65.1% dst/ + 0.0% rearranged/ + 10.8% src/move/changed/ + 10.8% src/move/rearranged/ + 10.8% src/move/unchanged/ + 32.5% src/move/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 5.8% changed/ + 29.3% dst/copy/changed/ + 29.3% dst/copy/rearranged/ + 29.3% dst/copy/unchanged/ + 88.0% dst/copy/ + 5.8% dst/move/changed/ + 0.1% dst/move/rearranged/ + 5.9% dst/move/ + 94.0% dst/ + 0.1% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 32.6% changed/ + 32.6% dst/copy/changed/ + 0.6% dst/copy/rearranged/ + 33.3% dst/copy/ + 32.6% dst/move/changed/ + 0.6% dst/move/rearranged/ + 33.3% dst/move/ + 66.6% dst/ + 0.6% rearranged/ +EOF + +test_expect_success '--dirstat=0 --cumulative' ' + git diff --dirstat=0 --cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=0 --cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=0 --cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=0,cumulative' ' + git diff --dirstat=0,cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=0,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=0,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '-X0,cumulative' ' + git diff -X0,cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff -X0,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff -X0,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=0,cumulative' ' + git -c diff.dirstat=0,cumulative diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=0,cumulative diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=0,cumulative diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=0 & --dirstat=cumulative' ' + git -c diff.dirstat=0 diff --dirstat=cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=0 diff --dirstat=cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=0 diff --dirstat=cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 9.0% changed/ + 9.0% dst/copy/changed/ + 9.0% dst/copy/rearranged/ + 9.0% dst/copy/unchanged/ + 9.0% dst/move/changed/ + 9.0% dst/move/rearranged/ + 9.0% dst/move/unchanged/ + 9.0% rearranged/ + 9.0% src/move/changed/ + 9.0% src/move/rearranged/ + 9.0% src/move/unchanged/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 14.2% changed/ + 14.2% dst/copy/changed/ + 14.2% dst/copy/rearranged/ + 14.2% dst/copy/unchanged/ + 14.2% dst/move/changed/ + 14.2% dst/move/rearranged/ + 14.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat-by-file' ' + git diff --dirstat-by-file HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat-by-file -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat-by-file -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=files' ' + git diff --dirstat=files HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=files' ' + git -c diff.dirstat=files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 27.2% dst/copy/ + 27.2% dst/move/ + 27.2% src/move/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 14.2% changed/ + 14.2% dst/copy/changed/ + 14.2% dst/copy/rearranged/ + 14.2% dst/copy/unchanged/ + 14.2% dst/move/changed/ + 14.2% dst/move/rearranged/ + 14.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat-by-file=10' ' + git diff --dirstat-by-file=10 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat-by-file=10 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat-by-file=10 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=files,10' ' + git diff --dirstat=files,10 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,10 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,10 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=10,files' ' + git -c diff.dirstat=10,files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=10,files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=10,files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 9.0% changed/ + 9.0% dst/copy/changed/ + 9.0% dst/copy/rearranged/ + 9.0% dst/copy/unchanged/ + 27.2% dst/copy/ + 9.0% dst/move/changed/ + 9.0% dst/move/rearranged/ + 9.0% dst/move/unchanged/ + 27.2% dst/move/ + 54.5% dst/ + 9.0% rearranged/ + 9.0% src/move/changed/ + 9.0% src/move/rearranged/ + 9.0% src/move/unchanged/ + 27.2% src/move/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 14.2% changed/ + 14.2% dst/copy/changed/ + 14.2% dst/copy/rearranged/ + 14.2% dst/copy/unchanged/ + 42.8% dst/copy/ + 14.2% dst/move/changed/ + 14.2% dst/move/rearranged/ + 28.5% dst/move/ + 71.4% dst/ + 14.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 33.3% dst/copy/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 33.3% dst/move/ + 66.6% dst/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat-by-file --cumulative' ' + git diff --dirstat-by-file --cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat-by-file --cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat-by-file --cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=files,cumulative' ' + git diff --dirstat=files,cumulative HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,cumulative -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,cumulative -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=cumulative,files' ' + git -c diff.dirstat=cumulative,files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=cumulative,files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=cumulative,files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 27.2% dst/copy/ + 27.2% dst/move/ + 54.5% dst/ + 27.2% src/move/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 14.2% changed/ + 14.2% dst/copy/changed/ + 14.2% dst/copy/rearranged/ + 14.2% dst/copy/unchanged/ + 42.8% dst/copy/ + 14.2% dst/move/changed/ + 14.2% dst/move/rearranged/ + 28.5% dst/move/ + 71.4% dst/ + 14.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 33.3% dst/copy/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 33.3% dst/move/ + 66.6% dst/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat=files,cumulative,10' ' + git diff --dirstat=files,cumulative,10 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,cumulative,10 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,cumulative,10 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=10,cumulative,files' ' + git -c diff.dirstat=10,cumulative,files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=10,cumulative,files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=10,cumulative,files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 27.2% dst/copy/ + 27.2% dst/move/ + 54.5% dst/ + 27.2% src/move/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 42.8% dst/copy/ + 28.5% dst/move/ + 71.4% dst/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 33.3% dst/copy/ + 33.3% dst/move/ + 66.6% dst/ +EOF + +test_expect_success '--dirstat=files,cumulative,16.7' ' + git diff --dirstat=files,cumulative,16.7 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,cumulative,16.7 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,cumulative,16.7 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=16.7,cumulative,files' ' + git -c diff.dirstat=16.7,cumulative,files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=16.7,cumulative,files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=16.7,cumulative,files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=16.70,cumulative,files' ' + git -c diff.dirstat=16.70,cumulative,files diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=16.70,cumulative,files diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=16.70,cumulative,files diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=files,cumulative,27.2' ' + git diff --dirstat=files,cumulative,27.2 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,cumulative,27.2 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,cumulative,27.2 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=files,cumulative,27.09' ' + git diff --dirstat=files,cumulative,27.09 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=files,cumulative,27.09 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=files,cumulative,27.09 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 10.6% dst/copy/changed/ + 10.6% dst/copy/rearranged/ + 10.6% dst/copy/unchanged/ + 10.6% dst/move/changed/ + 10.6% dst/move/rearranged/ + 10.6% dst/move/unchanged/ + 10.6% src/move/changed/ + 10.6% src/move/rearranged/ + 10.6% src/move/unchanged/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 5.2% changed/ + 26.3% dst/copy/changed/ + 26.3% dst/copy/rearranged/ + 26.3% dst/copy/unchanged/ + 5.2% dst/move/changed/ + 5.2% dst/move/rearranged/ + 5.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat=lines' ' + git diff --dirstat=lines HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=lines -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=lines -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=lines' ' + git -c diff.dirstat=lines diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=lines diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=lines diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +cat <<EOF >expect_diff_dirstat + 2.1% changed/ + 10.6% dst/copy/changed/ + 10.6% dst/copy/rearranged/ + 10.6% dst/copy/unchanged/ + 10.6% dst/move/changed/ + 10.6% dst/move/rearranged/ + 10.6% dst/move/unchanged/ + 2.1% rearranged/ + 10.6% src/move/changed/ + 10.6% src/move/rearranged/ + 10.6% src/move/unchanged/ +EOF + +cat <<EOF >expect_diff_dirstat_M + 5.2% changed/ + 26.3% dst/copy/changed/ + 26.3% dst/copy/rearranged/ + 26.3% dst/copy/unchanged/ + 5.2% dst/move/changed/ + 5.2% dst/move/rearranged/ + 5.2% rearranged/ +EOF + +cat <<EOF >expect_diff_dirstat_CC + 16.6% changed/ + 16.6% dst/copy/changed/ + 16.6% dst/copy/rearranged/ + 16.6% dst/move/changed/ + 16.6% dst/move/rearranged/ + 16.6% rearranged/ +EOF + +test_expect_success '--dirstat=lines,0' ' + git diff --dirstat=lines,0 HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git diff --dirstat=lines,0 -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git diff --dirstat=lines,0 -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success 'diff.dirstat=0,lines' ' + git -c diff.dirstat=0,lines diff --dirstat HEAD^..HEAD >actual_diff_dirstat && + test_cmp expect_diff_dirstat actual_diff_dirstat && + git -c diff.dirstat=0,lines diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + git -c diff.dirstat=0,lines diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC +' + +test_expect_success '--dirstat=future_param,lines,0 should fail loudly' ' + test_must_fail git diff --dirstat=future_param,lines,0 HEAD^..HEAD >actual_diff_dirstat 2>actual_error && + test_debug "cat actual_error" && + test_cmp /dev/null actual_diff_dirstat && + test_i18ngrep -q "future_param" actual_error && + test_i18ngrep -q "\--dirstat" actual_error +' + +test_expect_success '--dirstat=dummy1,cumulative,2dummy should report both unrecognized parameters' ' + test_must_fail git diff --dirstat=dummy1,cumulative,2dummy HEAD^..HEAD >actual_diff_dirstat 2>actual_error && + test_debug "cat actual_error" && + test_cmp /dev/null actual_diff_dirstat && + test_i18ngrep -q "dummy1" actual_error && + test_i18ngrep -q "2dummy" actual_error && + test_i18ngrep -q "\--dirstat" actual_error +' + +test_expect_success 'diff.dirstat=future_param,0,lines should warn, but still work' ' + git -c diff.dirstat=future_param,0,lines diff --dirstat HEAD^..HEAD >actual_diff_dirstat 2>actual_error && + test_debug "cat actual_error" && + test_cmp expect_diff_dirstat actual_diff_dirstat && + test_i18ngrep -q "future_param" actual_error && + test_i18ngrep -q "diff\\.dirstat" actual_error && + + git -c diff.dirstat=future_param,0,lines diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M 2>actual_error && + test_debug "cat actual_error" && + test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && + test_i18ngrep -q "future_param" actual_error && + test_i18ngrep -q "diff\\.dirstat" actual_error && + + git -c diff.dirstat=future_param,0,lines diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC 2>actual_error && + test_debug "cat actual_error" && + test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC && + test_i18ngrep -q "future_param" actual_error && + test_i18ngrep -q "diff\\.dirstat" actual_error +' + +test_done diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh new file mode 100755 index 0000000000..87a8949500 --- /dev/null +++ b/t/t4048-diff-combined-binary.sh @@ -0,0 +1,212 @@ +#!/bin/sh + +test_description='combined and merge diff handle binary files and textconv' +. ./test-lib.sh + +test_expect_success 'setup binary merge conflict' ' + echo oneQ1 | q_to_nul >binary && + git add binary && + git commit -m one && + echo twoQ2 | q_to_nul >binary && + git commit -a -m two && + git checkout -b branch-binary HEAD^ && + echo threeQ3 | q_to_nul >binary && + git commit -a -m three && + test_must_fail git merge master && + echo resolvedQhooray | q_to_nul >binary && + git commit -a -m resolved +' + +cat >expect <<'EOF' +resolved + +diff --git a/binary b/binary +index 7ea6ded..9563691 100644 +Binary files a/binary and b/binary differ +resolved + +diff --git a/binary b/binary +index 6197570..9563691 100644 +Binary files a/binary and b/binary differ +EOF +test_expect_success 'diff -m indicates binary-ness' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff -c indicates binary-ness' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff --cc indicates binary-ness' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_expect_success 'setup non-binary with binary attribute' ' + git checkout master && + test_commit one text && + test_commit two text && + git checkout -b branch-text HEAD^ && + test_commit three text && + test_must_fail git merge master && + test_commit resolved text && + echo text -diff >.gitattributes +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +Binary files a/text and b/text differ +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +Binary files a/text and b/text differ +EOF +test_expect_success 'diff -m respects binary attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff -c respects binary attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff --cc respects binary attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_expect_success 'setup textconv attribute' ' + echo "text diff=upcase" >.gitattributes && + git config diff.upcase.textconv "tr a-z A-Z <" +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-THREE ++RESOLVED +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-TWO ++RESOLVED +EOF +test_expect_success 'diff -m respects textconv attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff -c respects textconv attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff --cc respects textconv attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- three + -two +++resolved +EOF +test_expect_success 'diff-tree plumbing does not respect textconv' ' + git diff-tree HEAD -c -p >full && + tail -n +2 full >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --cc text +index 2bdf67a,f719efd..0000000 +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,5 @@@ +++<<<<<<< HEAD + +THREE +++======= ++ TWO +++>>>>>>> MASTER +EOF +test_expect_success 'diff --cc respects textconv on worktree file' ' + git reset --hard HEAD^ && + test_must_fail git merge master && + git diff >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4049-diff-stat-count.sh b/t/t4049-diff-stat-count.sh new file mode 100755 index 0000000000..641e70d14d --- /dev/null +++ b/t/t4049-diff-stat-count.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# Copyright (c) 2011, Google Inc. + +test_description='diff --stat-count' +. ./test-lib.sh + +test_expect_success setup ' + >a && + >b && + >c && + >d && + git add a b c d && + chmod +x c d && + echo a >a && + echo b >b && + cat >expect <<-\EOF + a | 1 + + b | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + EOF + git diff --stat --stat-count=2 >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4050-diff-histogram.sh b/t/t4050-diff-histogram.sh new file mode 100755 index 0000000000..fd3e86a74f --- /dev/null +++ b/t/t4050-diff-histogram.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +test_description='histogram diff algorithm' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-diff-alternative.sh + +test_diff_frobnitz "histogram" + +test_diff_unique "histogram" + +test_done diff --git a/t/t4051-diff-function-context.sh b/t/t4051-diff-function-context.sh new file mode 100755 index 0000000000..001d678e09 --- /dev/null +++ b/t/t4051-diff-function-context.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='diff function context' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh + + +cat <<\EOF >hello.c +#include <stdio.h> + +static int a(void) +{ + /* + * Dummy. + */ +} + +static int hello_world(void) +{ + /* Classic. */ + printf("Hello world.\n"); + + /* Success! */ + return 0; +} +static int b(void) +{ + /* + * Dummy, too. + */ +} + +int main(int argc, char **argv) +{ + a(); + b(); + return hello_world(); +} +EOF + +test_expect_success 'setup' ' + git add hello.c && + test_tick && + git commit -m initial && + + grep -v Classic <hello.c >hello.c.new && + mv hello.c.new hello.c +' + +cat <<\EOF >expected +diff --git a/hello.c b/hello.c +--- a/hello.c ++++ b/hello.c +@@ -10,8 +10,7 @@ static int a(void) + static int hello_world(void) + { +- /* Classic. */ + printf("Hello world.\n"); + + /* Success! */ + return 0; + } +EOF + +test_expect_success 'diff -U0 -W' ' + git diff -U0 -W >actual && + compare_diff_patch actual expected +' + +cat <<\EOF >expected +diff --git a/hello.c b/hello.c +--- a/hello.c ++++ b/hello.c +@@ -9,9 +9,8 @@ static int a(void) + + static int hello_world(void) + { +- /* Classic. */ + printf("Hello world.\n"); + + /* Success! */ + return 0; + } +EOF + +test_expect_success 'diff -W' ' + git diff -W >actual && + compare_diff_patch actual expected +' + +test_done diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh index 579c9e6105..a33d510bf6 100755 --- a/t/t4120-apply-popt.sh +++ b/t/t4120-apply-popt.sh @@ -6,6 +6,7 @@ test_description='git apply -p handling.' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh test_expect_success setup ' mkdir sub && @@ -62,8 +63,12 @@ test_expect_success 'apply (-p2) diff, mode change only' ' old mode 100644 new mode 100755 EOF - chmod 644 file1 && - git apply -p2 patch.chmod && + test_chmod -x file1 && + git apply --index -p2 patch.chmod && + case $(git ls-files -s file1) in 100755*) : good;; *) false;; esac +' + +test_expect_success FILEMODE 'file mode was changed' ' test -x file1 ' diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 850fc96d1f..d7d9ccc1c8 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -96,6 +96,13 @@ test_expect_success setup ' echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } | append_cr >patch1-crlf.eml && + { + printf "%255s\\n" "" + echo "X-Fake-Field: Line One" && + echo "X-Fake-Field: Line Two" && + echo "X-Fake-Field: Line Three" && + git format-patch --stdout first | sed -e "1d" + } > patch1-ws.eml && sed -n -e "3,\$p" msg >file && git add file && @@ -167,6 +174,17 @@ test_expect_success 'am applies patch e-mail not in a mbox with CRLF' ' test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' +test_expect_success 'am applies patch e-mail with preceding whitespace' ' + rm -fr .git/rebase-apply && + git reset --hard && + git checkout first && + git am patch1-ws.eml && + ! test -d .git/rebase-apply && + 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 'setup: new author and committer' ' GIT_AUTHOR_NAME="Another Thor" && GIT_AUTHOR_EMAIL="a.thor@example.com" && @@ -465,7 +483,7 @@ test_expect_success 'am newline in subject' ' test_tick && sed -e "s/second/second \\\n foo/" patch1 >patchnl && git am <patchnl >output.out 2>&1 && - grep "^Applying: second \\\n foo$" output.out + test_i18ngrep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index c95c4ccc39..1176bcccf3 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -45,8 +45,9 @@ do test_expect_success "am$with3 --skip continue after failed am$with3" ' test_must_fail git am$with3 --skip >output && - test "$(grep "^Applying" output)" = "Applying: 6" && - test_cmp file-2-expect file-2 && + test_i18ngrep "^Applying" output >output.applying && + test_i18ngrep "^Applying: 6$" output.applying && + test_i18ncmp file-2-expect file-2 && test ! -f .git/MERGE_RR ' diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh new file mode 100755 index 0000000000..4c68245aca --- /dev/null +++ b/t/t4152-am-subjects.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +test_description='test subject preservation with format-patch | am' +. ./test-lib.sh + +make_patches() { + type=$1 + subject=$2 + test_expect_success "create patches with $type subject" ' + git reset --hard baseline && + echo $type >file && + git commit -a -m "$subject" && + git format-patch -1 --stdout >$type.patch && + git format-patch -1 --stdout -k >$type-k.patch + ' +} + +check_subject() { + git reset --hard baseline && + git am $2 $1.patch && + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +} + +test_expect_success 'setup baseline commit' ' + test_commit baseline file +' + +SHORT_SUBJECT='short subject' +make_patches short "$SHORT_SUBJECT" + +LONG_SUBJECT1='this is a long subject that is virtually guaranteed' +LONG_SUBJECT2='to require wrapping via format-patch if it is all' +LONG_SUBJECT3='going to appear on a single line' +LONG_SUBJECT="$LONG_SUBJECT1 $LONG_SUBJECT2 $LONG_SUBJECT3" +make_patches long "$LONG_SUBJECT" + +MULTILINE_SUBJECT="$LONG_SUBJECT1 +$LONG_SUBJECT2 +$LONG_SUBJECT3" +make_patches multiline "$MULTILINE_SUBJECT" + +echo "$SHORT_SUBJECT" >expect +test_expect_success 'short subject preserved (format-patch | am)' ' + check_subject short +' +test_expect_success 'short subject preserved (format-patch -k | am)' ' + check_subject short-k +' +test_expect_success 'short subject preserved (format-patch -k | am -k)' ' + check_subject short-k -k +' + +echo "$LONG_SUBJECT" >expect +test_expect_success 'long subject preserved (format-patch | am)' ' + check_subject long +' +test_expect_success 'long subject preserved (format-patch -k | am)' ' + check_subject long-k +' +test_expect_success 'long subject preserved (format-patch -k | am -k)' ' + check_subject long-k -k +' + +echo "$LONG_SUBJECT" >expect +test_expect_success 'multiline subject unwrapped (format-patch | am)' ' + check_subject multiline +' +test_expect_success 'multiline subject unwrapped (format-patch -k | am)' ' + check_subject multiline-k +' +echo "$MULTILINE_SUBJECT" >expect +test_expect_success 'multiline subject preserved (format-patch -k | am -k)' ' + check_subject multiline-k -k +' + +test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 2fcc31a6f3..983e34bec6 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -448,6 +448,59 @@ test_expect_success 'log.decorate configuration' ' git log --oneline --decorate >actual && test_cmp expect.short actual + git config --unset-all log.decorate && + git log --pretty=raw >expect.raw && + git config log.decorate full && + git log --pretty=raw >actual && + test_cmp expect.raw actual + +' + +test_expect_success 'reflog is expected format' ' + test_might_fail git config --remove-section log && + git log -g --abbrev-commit --pretty=oneline >expect && + git reflog >actual && + test_cmp expect actual +' + +test_expect_success 'whatchanged is expected format' ' + git log --no-merges --raw >expect && + git whatchanged >actual && + test_cmp expect actual +' + +test_expect_success 'log.abbrevCommit configuration' ' + test_when_finished "git config --unset log.abbrevCommit" && + + test_might_fail git config --unset log.abbrevCommit && + + git log --abbrev-commit >expect.log.abbrev && + git log --no-abbrev-commit >expect.log.full && + git log --pretty=raw >expect.log.raw && + git reflog --abbrev-commit >expect.reflog.abbrev && + git reflog --no-abbrev-commit >expect.reflog.full && + git whatchanged --abbrev-commit >expect.whatchanged.abbrev && + git whatchanged --no-abbrev-commit >expect.whatchanged.full && + + git config log.abbrevCommit true && + + git log >actual && + test_cmp expect.log.abbrev actual && + git log --no-abbrev-commit >actual && + test_cmp expect.log.full actual && + + git log --pretty=raw >actual && + test_cmp expect.log.raw actual && + + git reflog >actual && + test_cmp expect.reflog.abbrev actual && + git reflog --no-abbrev-commit >actual && + test_cmp expect.reflog.full actual && + + git whatchanged >actual && + test_cmp expect.whatchanged.abbrev actual && + git whatchanged --no-abbrev-commit >actual && + test_cmp expect.whatchanged.full actual ' test_expect_success 'show added path under "--follow -M"' ' diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index e818de6ddd..1f182f612c 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -94,7 +94,7 @@ nick1 (1): EOF -test_expect_success 'mailmap.file non-existant' ' +test_expect_success 'mailmap.file non-existent' ' rm internal_mailmap/.mailmap && rmdir internal_mailmap && git shortlog HEAD >actual && diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh index 68e2652814..d2c930de87 100755 --- a/t/t4204-patch-id.sh +++ b/t/t4204-patch-id.sh @@ -63,4 +63,40 @@ test_expect_success 'patch-id supports git-format-patch MIME output' ' test_cmp patch-id_master patch-id_same ' +cat >nonl <<\EOF +diff --git i/a w/a +index e69de29..2e65efe 100644 +--- i/a ++++ w/a +@@ -0,0 +1 @@ ++a +\ No newline at end of file +diff --git i/b w/b +index e69de29..6178079 100644 +--- i/b ++++ w/b +@@ -0,0 +1 @@ ++b +EOF + +cat >withnl <<\EOF +diff --git i/a w/a +index e69de29..7898192 100644 +--- i/a ++++ w/a +@@ -0,0 +1 @@ ++a +diff --git i/b w/b +index e69de29..6178079 100644 +--- i/b ++++ w/b +@@ -0,0 +1 @@ ++b +EOF + +test_expect_success 'patch-id handles no-nl-at-eof markers' ' + cat nonl | calc_patch_id nonl && + cat withnl | calc_patch_id withnl && + test_cmp patch-id_nonl patch-id_withnl +' test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index cb9f2bdd29..2ae9faa8b3 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -45,7 +45,7 @@ test_expect_success 'alias user-defined tformat' ' test_cmp expected actual ' -test_expect_success 'alias non-existant format' ' +test_expect_success 'alias non-existent format' ' git config pretty.test-alias format-that-will-never-exist && test_must_fail git log --pretty=test-alias ' diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh new file mode 100755 index 0000000000..2c482b622b --- /dev/null +++ b/t/t4208-log-magic-pathspec.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +test_description='magic pathspec tests using git-log' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit initial && + test_tick && + git commit --allow-empty -m empty && + mkdir sub +' + +test_expect_success '"git log :/" should be ambiguous' ' + test_must_fail git log :/ 2>error && + grep ambiguous error +' + +test_expect_success '"git log :" should be ambiguous' ' + test_must_fail git log : 2>error && + grep ambiguous error +' + +test_expect_success 'git log -- :' ' + git log -- : +' + +test_expect_success 'git log HEAD -- :/' ' + cat >expected <<-EOF && + 24b24cf initial + EOF + (cd sub && git log --oneline HEAD -- :/ >../actual) && + test_cmp expected actual +' + +test_done diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh new file mode 100755 index 0000000000..b7da95fac5 --- /dev/null +++ b/t/t4254-am-corrupt.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='git am with corrupt input' +. ./test-lib.sh + +# Note the missing "+++" line: +cat > bad-patch.diff <<'EOF' +From: A U Thor <au.thor@example.com> +diff --git a/f b/f +index 7898192..6178079 100644 +--- a/f +@@ -1 +1 @@ +-a ++b +EOF + +test_expect_success setup ' + test $? = 0 && + echo a > f && + git add f && + test_tick && + git commit -m initial +' + +# This used to fail before, too, but with a different diagnostic. +# fatal: unable to write file '(null)' mode 100644: Bad address +# Also, it had the unwanted side-effect of deleting f. +test_expect_success 'try to apply corrupted patch' ' + git am bad-patch.diff 2> actual + test $? = 1 +' + +cat > expected <<EOF +fatal: git diff header lacks filename information (line 4) +EOF + +test_expect_success 'compare diagnostic; ensure file is still here' ' + test $? = 0 && + test -f f && + test_cmp expected actual +' + +test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index cff1b3e050..d9068981f8 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -26,6 +26,8 @@ commit id embedding: . ./test-lib.sh UNZIP=${UNZIP:-unzip} +GZIP=${GZIP:-gzip} +GUNZIP=${GUNZIP:-gzip -d} SUBSTFORMAT=%H%n @@ -252,4 +254,102 @@ test_expect_success 'git-archive --prefix=olde-' ' test -f h/olde-a/bin/sh ' +test_expect_success 'setup tar filters' ' + git config tar.tar.foo.command "tr ab ba" && + git config tar.bar.command "tr ab ba" && + git config tar.bar.remote true +' + +test_expect_success 'archive --list mentions user filter' ' + git archive --list >output && + grep "^tar\.foo\$" output && + grep "^bar\$" output +' + +test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' ' + git archive --list --remote=. >output && + ! grep "^tar\.foo\$" output && + grep "^bar\$" output +' + +test_expect_success 'invoke tar filter by format' ' + git archive --format=tar.foo HEAD >config.tar.foo && + tr ab ba <config.tar.foo >config.tar && + test_cmp b.tar config.tar && + git archive --format=bar HEAD >config.bar && + tr ab ba <config.bar >config.tar && + test_cmp b.tar config.tar +' + +test_expect_success 'invoke tar filter by extension' ' + git archive -o config-implicit.tar.foo HEAD && + test_cmp config.tar.foo config-implicit.tar.foo && + git archive -o config-implicit.bar HEAD && + test_cmp config.tar.foo config-implicit.bar +' + +test_expect_success 'default output format remains tar' ' + git archive -o config-implicit.baz HEAD && + test_cmp b.tar config-implicit.baz +' + +test_expect_success 'extension matching requires dot' ' + git archive -o config-implicittar.foo HEAD && + test_cmp b.tar config-implicittar.foo +' + +test_expect_success NOT_MINGW 'only enabled filters are available remotely' ' + test_must_fail git archive --remote=. --format=tar.foo HEAD \ + >remote.tar.foo && + git archive --remote=. --format=bar >remote.bar HEAD && + test_cmp remote.bar config.bar +' + +if $GZIP --version >/dev/null 2>&1; then + test_set_prereq GZIP +else + say "Skipping some tar.gz tests because gzip not found" +fi + +test_expect_success GZIP 'git archive --format=tgz' ' + git archive --format=tgz HEAD >j.tgz +' + +test_expect_success GZIP 'git archive --format=tar.gz' ' + git archive --format=tar.gz HEAD >j1.tar.gz && + test_cmp j.tgz j1.tar.gz +' + +test_expect_success GZIP 'infer tgz from .tgz filename' ' + git archive --output=j2.tgz HEAD && + test_cmp j.tgz j2.tgz +' + +test_expect_success GZIP 'infer tgz from .tar.gz filename' ' + git archive --output=j3.tar.gz HEAD && + test_cmp j.tgz j3.tar.gz +' + +if $GUNZIP --version >/dev/null 2>&1; then + test_set_prereq GUNZIP +else + say "Skipping some tar.gz tests because gunzip was not found" +fi + +test_expect_success GZIP,GUNZIP 'extract tgz file' ' + $GUNZIP -c <j.tgz >j.tar && + test_cmp b.tar j.tar +' + +test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' ' + git archive --remote=. --format=tar.gz HEAD >remote.tar.gz && + test_cmp j.tgz remote.tar.gz +' + +test_expect_success GZIP,NOT_MINGW 'remote tar.gz can be disabled' ' + git config tar.tar.gz.remote false && + test_must_fail git archive --remote=. --format=tar.gz HEAD \ + >remote.tar.gz +' + test_done diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 02d4d2284d..f47d8717fd 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -57,6 +57,15 @@ test_expect_missing worktree/ignored test_expect_exists worktree/ignored-by-tree test_expect_missing worktree/ignored-by-worktree +test_expect_success 'git archive --worktree-attributes option' ' + git archive --worktree-attributes --worktree-attributes HEAD >worktree.tar && + (mkdir worktree2 && cd worktree2 && "$TAR" xf -) <worktree.tar +' + +test_expect_missing worktree2/ignored +test_expect_exists worktree2/ignored-by-tree +test_expect_missing worktree2/ignored-by-worktree + test_expect_success 'git archive vs. bare' ' (cd bare && git archive HEAD) >bare-archive.tar && test_cmp archive.tar bare-archive.tar diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index b34ea93a80..f8fa92446c 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -65,6 +65,14 @@ test_expect_success \ 'cmp "test-1-${pack1}.idx" "1.idx" && cmp "test-2-${pack2}.idx" "2.idx"' +test_expect_success 'index-pack --verify on index version 1' ' + git index-pack --verify "test-1-${pack1}.pack" +' + +test_expect_success 'index-pack --verify on index version 2' ' + git index-pack --verify "test-2-${pack2}.pack" +' + test_expect_success \ 'index v2: force some 64-bit offsets with pack-objects' \ 'pack3=$(git pack-objects --index-version=2,0x40000 test-3 <obj-list)' @@ -93,6 +101,16 @@ test_expect_success OFF64_T \ '64-bit offsets: index-pack result should match pack-objects one' \ 'cmp "test-3-${pack3}.idx" "3.idx"' +test_expect_success OFF64_T 'index-pack --verify on 64-bit offset v2 (cheat)' ' + # This cheats by knowing which lower offset should still be encoded + # in 64-bit representation. + git index-pack --verify --index-version=2,0x40000 "test-3-${pack3}.pack" +' + +test_expect_success OFF64_T 'index-pack --verify on 64-bit offset v2' ' + git index-pack --verify "test-3-${pack3}.pack" +' + # returns the object number for given object in given pack index index_obj_nr() { @@ -208,9 +226,8 @@ test_expect_success \ ( while read obj do git cat-file -p $obj >/dev/null || exit 1 done <obj-list ) && - err=$(test_must_fail git verify-pack \ - ".git/objects/pack/pack-${pack1}.pack" 2>&1) && - echo "$err" | grep "CRC mismatch"' + test_must_fail git verify-pack ".git/objects/pack/pack-${pack1}.pack" +' test_expect_success 'running index-pack in the object store' ' rm -f .git/objects/pack/* && diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index e2ed13dba2..d645328609 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -14,7 +14,8 @@ add_blob() { BLOB=$(echo aleph_0 | git hash-object -w --stdin) && BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && - test -f $BLOB_FILE + test -f $BLOB_FILE && + test-chmtime =+0 $BLOB_FILE } test_expect_success setup ' diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index b0b2684a1f..0eace37a03 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -190,7 +190,7 @@ test_expect_success 'pushing explicit refspecs respects forcing' ' +refs/heads/master:refs/heads/master ) && parent_head=$(cd parent && git rev-parse --verify master) && - child_head=$(cd parent && git rev-parse --verify master) && + child_head=$(cd child && git rev-parse --verify master) && test "$parent_head" = "$child_head" ' @@ -210,7 +210,7 @@ test_expect_success 'pushing wildcard refspecs respects forcing' ' "+refs/heads/*:refs/heads/*" ) && parent_head=$(cd parent && git rev-parse --verify master) && - child_head=$(cd parent && git rev-parse --verify master) && + child_head=$(cd child && git rev-parse --verify master) && test "$parent_head" = "$child_head" ' diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh index d05a9138b4..1753ef2b91 100755 --- a/t/t5403-post-checkout-hook.sh +++ b/t/t5403-post-checkout-hook.sh @@ -31,44 +31,44 @@ EOF done test_expect_success 'post-checkout runs as expected ' ' - GIT_DIR=clone1/.git git checkout master && - test -e clone1/.git/post-checkout.args + GIT_DIR=clone1/.git git checkout master && + test -e clone1/.git/post-checkout.args ' test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' ' - old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && - new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && - flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && - test $old = $new -a $flag = 1 + old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && + test $old = $new -a $flag = 1 ' test_expect_success 'post-checkout runs as expected ' ' - GIT_DIR=clone1/.git git checkout master && - test -e clone1/.git/post-checkout.args + GIT_DIR=clone1/.git git checkout master && + test -e clone1/.git/post-checkout.args ' test_expect_success 'post-checkout args are correct with git checkout -b ' ' - GIT_DIR=clone1/.git git checkout -b new1 && - old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && - new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && - flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && - test $old = $new -a $flag = 1 + GIT_DIR=clone1/.git git checkout -b new1 && + old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && + test $old = $new -a $flag = 1 ' test_expect_success 'post-checkout receives the right args with HEAD changed ' ' - GIT_DIR=clone2/.git git checkout new2 && - old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && - new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && - flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && - test $old != $new -a $flag = 1 + GIT_DIR=clone2/.git git checkout new2 && + old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && + test $old != $new -a $flag = 1 ' test_expect_success 'post-checkout receives the right args when not switching branches ' ' - GIT_DIR=clone2/.git git checkout master b && - old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && - new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && - flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && - test $old = $new -a $flag = 0 + GIT_DIR=clone2/.git git checkout master b && + old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && + test $old = $new -a $flag = 0 ' if test "$(git config --bool core.filemode)" = true; then diff --git a/t/t5501-fetch-push-alternates.sh b/t/t5501-fetch-push-alternates.sh new file mode 100755 index 0000000000..b5ced8483a --- /dev/null +++ b/t/t5501-fetch-push-alternates.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +test_description='fetch/push involving alternates' +. ./test-lib.sh + +count_objects () { + loose=0 inpack=0 + eval "$( + git count-objects -v | + sed -n -e 's/^count: \(.*\)/loose=\1/p' \ + -e 's/^in-pack: \(.*\)/inpack=\1/p' + )" && + echo $(( $loose + $inpack )) +} + + +test_expect_success setup ' + ( + git init original && + cd original && + i=0 && + while test $i -le 100 + do + echo "$i" >count && + git add count && + git commit -m "$i" || exit + i=$(($i + 1)) + done + ) && + ( + git clone --reference=original "file:///$(pwd)/original" one && + cd one && + echo Z >count && + git add count && + git commit -m Z && + count_objects >../one.count + ) && + A=$(pwd)/original/.git/objects && + git init receiver && + echo "$A" >receiver/.git/objects/info/alternates && + git init fetcher && + echo "$A" >fetcher/.git/objects/info/alternates +' + +test_expect_success 'pushing into a repository with the same alternate' ' + ( + cd one && + git push ../receiver master:refs/heads/it + ) && + ( + cd receiver && + count_objects >../receiver.count + ) && + test_cmp one.count receiver.count +' + +test_expect_success 'fetching from a repository with the same alternate' ' + ( + cd fetcher && + git fetch ../one master:refs/heads/it && + count_objects >../fetcher.count + ) && + test_cmp one.count fetcher.count +' + +test_done diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh new file mode 100755 index 0000000000..8341fc4d15 --- /dev/null +++ b/t/t5504-fetch-receive-strict.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +test_description='fetch/receive strict mode' +. ./test-lib.sh + +test_expect_success setup ' + echo hello >greetings && + git add greetings && + git commit -m greetings && + + S=$(git rev-parse :greetings | sed -e "s|^..|&/|") && + X=$(echo bye | git hash-object -w --stdin | sed -e "s|^..|&/|") && + mv -f .git/objects/$X .git/objects/$S && + + test_must_fail git fsck +' + +test_expect_success 'fetch without strict' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config fetch.fsckobjects false && + git config transfer.fsckobjects false && + test_must_fail git fetch ../.git master + ) +' + +test_expect_success 'fetch with !fetch.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config fetch.fsckobjects false && + git config transfer.fsckobjects true && + test_must_fail git fetch ../.git master + ) +' + +test_expect_success 'fetch with fetch.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config fetch.fsckobjects true && + git config transfer.fsckobjects false && + test_must_fail git fetch ../.git master + ) +' + +test_expect_success 'fetch with transfer.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config transfer.fsckobjects true && + test_must_fail git fetch ../.git master + ) +' + +test_expect_success 'push without strict' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config fetch.fsckobjects false && + git config transfer.fsckobjects false + ) && + git push dst master:refs/heads/test +' + +test_expect_success 'push with !receive.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config receive.fsckobjects false && + git config transfer.fsckobjects true + ) && + git push dst master:refs/heads/test +' + +test_expect_success 'push with receive.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config receive.fsckobjects true && + git config transfer.fsckobjects false + ) && + test_must_fail git push dst master:refs/heads/test +' + +test_expect_success 'push with transfer.fsckobjects' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config transfer.fsckobjects true + ) && + test_must_fail git push dst master:refs/heads/test +' + +test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index d189add2d0..e8af615e6d 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -304,6 +304,106 @@ test_expect_success 'add --mirror && prune' ' git rev-parse --verify refs/heads/side) ' +test_expect_success 'add --mirror=fetch' ' + mkdir mirror-fetch && + git init mirror-fetch/parent && + (cd mirror-fetch/parent && + test_commit one) && + git init --bare mirror-fetch/child && + (cd mirror-fetch/child && + git remote add --mirror=fetch -f parent ../parent) +' + +test_expect_success 'fetch mirrors act as mirrors during fetch' ' + (cd mirror-fetch/parent && + git branch new && + git branch -m master renamed + ) && + (cd mirror-fetch/child && + git fetch parent && + git rev-parse --verify refs/heads/new && + git rev-parse --verify refs/heads/renamed + ) +' + +test_expect_success 'fetch mirrors can prune' ' + (cd mirror-fetch/child && + git remote prune parent && + test_must_fail git rev-parse --verify refs/heads/master + ) +' + +test_expect_success 'fetch mirrors do not act as mirrors during push' ' + (cd mirror-fetch/parent && + git checkout HEAD^0 + ) && + (cd mirror-fetch/child && + git branch -m renamed renamed2 && + git push parent + ) && + (cd mirror-fetch/parent && + git rev-parse --verify renamed && + test_must_fail git rev-parse --verify refs/heads/renamed2 + ) +' + +test_expect_success 'add fetch mirror with specific branches' ' + git init --bare mirror-fetch/track && + (cd mirror-fetch/track && + git remote add --mirror=fetch -t heads/new parent ../parent + ) +' + +test_expect_success 'fetch mirror respects specific branches' ' + (cd mirror-fetch/track && + git fetch parent && + git rev-parse --verify refs/heads/new && + test_must_fail git rev-parse --verify refs/heads/renamed + ) +' + +test_expect_success 'add --mirror=push' ' + mkdir mirror-push && + git init --bare mirror-push/public && + git init mirror-push/private && + (cd mirror-push/private && + test_commit one && + git remote add --mirror=push public ../public + ) +' + +test_expect_success 'push mirrors act as mirrors during push' ' + (cd mirror-push/private && + git branch new && + git branch -m master renamed && + git push public + ) && + (cd mirror-push/private && + git rev-parse --verify refs/heads/new && + git rev-parse --verify refs/heads/renamed && + test_must_fail git rev-parse --verify refs/heads/master + ) +' + +test_expect_success 'push mirrors do not act as mirrors during fetch' ' + (cd mirror-push/public && + git branch -m renamed renamed2 && + git symbolic-ref HEAD refs/heads/renamed2 + ) && + (cd mirror-push/private && + git fetch public && + git rev-parse --verify refs/heads/renamed && + test_must_fail git rev-parse --verify refs/heads/renamed2 + ) +' + +test_expect_success 'push mirrors do not allow you to specify refs' ' + git init mirror-push/track && + (cd mirror-push/track && + test_must_fail git remote add --mirror=push -t new public ../public + ) +' + test_expect_success 'add alt && prune' ' (mkdir alttst && cd alttst && @@ -531,6 +631,37 @@ test_expect_success 'rename a remote' ' ' +test_expect_success 'rename does not update a non-default fetch refspec' ' + + git clone one four.one && + (cd four.one && + git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* && + git remote rename origin upstream && + test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" && + git rev-parse -q origin/master) + +' + +test_expect_success 'rename a remote with name part of fetch spec' ' + + git clone one four.two && + (cd four.two && + git remote rename origin remote && + git remote rename remote upstream && + test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*") + +' + +test_expect_success 'rename a remote with name prefix of other remote' ' + + git clone one four.three && + (cd four.three && + git remote add o git://example.com/repo.git && + git remote rename o upstream && + test "$(git rev-parse origin/master)" = "$(git rev-parse master)") + +' + cat > remotes_origin << EOF URL: $(pwd)/one Push: refs/heads/master:refs/heads/upstream diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh index b7b7ddaa40..530b01678e 100755 --- a/t/t5506-remote-groups.sh +++ b/t/t5506-remote-groups.sh @@ -43,10 +43,10 @@ test_expect_success 'no group updates all' ' repo_fetched two ' -test_expect_success 'nonexistant group produces error' ' - mark nonexistant && +test_expect_success 'nonexistent group produces error' ' + mark nonexistent && update_repos && - test_must_fail git remote update nonexistant && + test_must_fail git remote update nonexistent && ! repo_fetched one && ! repo_fetched two ' diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh new file mode 100755 index 0000000000..cc0b31f6b0 --- /dev/null +++ b/t/t5509-fetch-push-namespaces.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +test_description='fetch/push involving ref namespaces' +. ./test-lib.sh + +test_expect_success setup ' + test_tick && + git init original && + ( + cd original && + echo 0 >count && + git add count && + test_commit 0 && + echo 1 >count && + git add count && + test_commit 1 && + git remote add pushee-namespaced "ext::git --namespace=namespace %s ../pushee" && + git remote add pushee-unnamespaced ../pushee + ) && + commit0=$(cd original && git rev-parse HEAD^) && + commit1=$(cd original && git rev-parse HEAD) && + git init pushee && + git init puller +' + +test_expect_success 'pushing into a repository using a ref namespace' ' + ( + cd original && + git push pushee-namespaced master && + git ls-remote pushee-namespaced >actual && + printf "$commit1\trefs/heads/master\n" >expected && + test_cmp expected actual && + git push pushee-namespaced --tags && + git ls-remote pushee-namespaced >actual && + printf "$commit0\trefs/tags/0\n" >>expected && + printf "$commit1\trefs/tags/1\n" >>expected && + test_cmp expected actual && + # Verify that the GIT_NAMESPACE environment variable works as well + GIT_NAMESPACE=namespace git ls-remote "ext::git %s ../pushee" >actual && + test_cmp expected actual && + # Verify that --namespace overrides GIT_NAMESPACE + GIT_NAMESPACE=garbage git ls-remote pushee-namespaced >actual && + test_cmp expected actual && + # Try a namespace with no content + git ls-remote "ext::git --namespace=garbage %s ../pushee" >actual && + test_cmp /dev/null actual && + git ls-remote pushee-unnamespaced >actual && + sed -e "s|refs/|refs/namespaces/namespace/refs/|" expected >expected.unnamespaced && + test_cmp expected.unnamespaced actual + ) +' + +test_expect_success 'pulling from a repository using a ref namespace' ' + ( + cd puller && + git remote add -f pushee-namespaced "ext::git --namespace=namespace %s ../pushee" && + git for-each-ref refs/ >actual && + printf "$commit1 commit\trefs/remotes/pushee-namespaced/master\n" >expected && + printf "$commit0 commit\trefs/tags/0\n" >>expected && + printf "$commit1 commit\trefs/tags/1\n" >>expected && + test_cmp expected actual + ) +' + +# This test with clone --mirror checks for possible regressions in clone +# or the machinery underneath it. It ensures that no future change +# causes clone to ignore refs in refs/namespaces/*. In particular, it +# protects against a regression caused by any future change to the refs +# machinery that might cause it to ignore refs outside of refs/heads/* +# or refs/tags/*. More generally, this test also checks the high-level +# functionality of using clone --mirror to back up a set of repos hosted +# in the namespaces of a single repo. +test_expect_success 'mirroring a repository using a ref namespace' ' + git clone --mirror pushee mirror && + ( + cd mirror && + git for-each-ref refs/ >actual && + printf "$commit1 commit\trefs/namespaces/namespace/refs/heads/master\n" >expected && + printf "$commit0 commit\trefs/namespaces/namespace/refs/tags/0\n" >>expected && + printf "$commit1 commit\trefs/namespaces/namespace/refs/tags/1\n" >>expected && + test_cmp expected actual + ) +' + +test_done diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 7e433b179f..e0af4c4e62 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -76,6 +76,56 @@ test_expect_success "fetch test for-merge" ' cut -f -2 .git/FETCH_HEAD >actual && test_cmp expected actual' +test_expect_success 'fetch --prune on its own works as expected' ' + cd "$D" && + git clone . prune && + cd prune && + git fetch origin refs/heads/master:refs/remotes/origin/extrabranch && + + git fetch --prune origin && + test_must_fail git rev-parse origin/extrabranch +' + +test_expect_success 'fetch --prune with a branch name keeps branches' ' + cd "$D" && + git clone . prune-branch && + cd prune-branch && + git fetch origin refs/heads/master:refs/remotes/origin/extrabranch && + + git fetch --prune origin master && + git rev-parse origin/extrabranch +' + +test_expect_success 'fetch --prune with a namespace keeps other namespaces' ' + cd "$D" && + git clone . prune-namespace && + cd prune-namespace && + + git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* && + git rev-parse origin/master +' + +test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' ' + cd "$D" && + git clone . prune-tags && + cd prune-tags && + git fetch origin refs/heads/master:refs/tags/sometag && + + git fetch --prune --tags origin && + git rev-parse origin/master && + test_must_fail git rev-parse somebranch +' + +test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' ' + cd "$D" && + git clone . prune-tags-branch && + cd prune-tags-branch && + git fetch origin refs/heads/master:refs/remotes/origin/extrabranch && + + git fetch --prune --tags origin master && + git rev-parse origin/extrabranch +' + test_expect_success 'fetch tags when there is no tags' ' cd "$D" && diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index d1912351db..5c546c99a5 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -123,4 +123,28 @@ test_expect_success 'confuses pattern as remote when no remote specified' ' ' +test_expect_success 'die with non-2 for wrong repository even with --exit-code' ' + git ls-remote --exit-code ./no-such-repository ;# not && + status=$? && + test $status != 2 && test $status != 0 +' + +test_expect_success 'Report success even when nothing matches' ' + git ls-remote other.git "refs/nsn/*" >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'Report no-match with --exit-code' ' + test_expect_code 2 git ls-remote --exit-code other.git "refs/nsn/*" >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'Report match with --exit-code' ' + git ls-remote --exit-code other.git "refs/tags/*" >actual && + git ls-remote . tags/mark >expect && + test_cmp expect actual +' + test_done diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index d73731e644..b69cf574d7 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -40,6 +40,40 @@ mk_test () { ) } +mk_test_with_hooks() { + mk_test "$@" && + ( + cd testrepo && + mkdir .git/hooks && + cd .git/hooks && + + cat >pre-receive <<-'EOF' && + #!/bin/sh + cat - >>pre-receive.actual + EOF + + cat >update <<-'EOF' && + #!/bin/sh + printf "%s %s %s\n" "$@" >>update.actual + EOF + + cat >post-receive <<-'EOF' && + #!/bin/sh + cat - >>post-receive.actual + EOF + + cat >post-update <<-'EOF' && + #!/bin/sh + for ref in "$@" + do + printf "%s\n" "$ref" >>post-update.actual + done + EOF + + chmod +x pre-receive update post-receive post-update + ) +} + mk_child() { rm -rf "$1" && git clone testrepo "$1" @@ -367,7 +401,7 @@ test_expect_success 'push with colon-less refspec (4)' ' ' -test_expect_success 'push head with non-existant, incomplete dest' ' +test_expect_success 'push head with non-existent, incomplete dest' ' mk_test && git push testrepo master:branch && @@ -375,7 +409,7 @@ test_expect_success 'push head with non-existant, incomplete dest' ' ' -test_expect_success 'push tag with non-existant, incomplete dest' ' +test_expect_success 'push tag with non-existent, incomplete dest' ' mk_test && git tag -f v1.0 && @@ -384,14 +418,14 @@ test_expect_success 'push tag with non-existant, incomplete dest' ' ' -test_expect_success 'push sha1 with non-existant, incomplete dest' ' +test_expect_success 'push sha1 with non-existent, incomplete dest' ' mk_test && test_must_fail git push testrepo `git rev-parse master`:foo ' -test_expect_success 'push ref expression with non-existant, incomplete dest' ' +test_expect_success 'push ref expression with non-existent, incomplete dest' ' mk_test && test_must_fail git push testrepo master^:branch @@ -436,7 +470,7 @@ test_expect_success 'push with +HEAD' ' ' -test_expect_success 'push HEAD with non-existant, incomplete dest' ' +test_expect_success 'push HEAD with non-existent, incomplete dest' ' mk_test && git checkout master && @@ -559,6 +593,169 @@ test_expect_success 'allow deleting an invalid remote ref' ' ' +test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' ' + mk_test_with_hooks heads/master heads/next && + orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) && + newmaster=$(git show-ref -s --verify refs/heads/master) && + orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) && + newnext=$_z40 && + git push testrepo refs/heads/master:refs/heads/master :refs/heads/next && + ( + cd testrepo/.git && + cat >pre-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + $orgnext $newnext refs/heads/next + EOF + + cat >update.expect <<-EOF && + refs/heads/master $orgmaster $newmaster + refs/heads/next $orgnext $newnext + EOF + + cat >post-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + $orgnext $newnext refs/heads/next + EOF + + cat >post-update.expect <<-EOF && + refs/heads/master + refs/heads/next + EOF + + test_cmp pre-receive.expect pre-receive.actual && + test_cmp update.expect update.actual && + test_cmp post-receive.expect post-receive.actual && + test_cmp post-update.expect post-update.actual + ) +' + +test_expect_success 'deleting dangling ref triggers hooks with correct args' ' + mk_test_with_hooks heads/master && + rm -f testrepo/.git/objects/??/* && + git push testrepo :refs/heads/master && + ( + cd testrepo/.git && + cat >pre-receive.expect <<-EOF && + $_z40 $_z40 refs/heads/master + EOF + + cat >update.expect <<-EOF && + refs/heads/master $_z40 $_z40 + EOF + + cat >post-receive.expect <<-EOF && + $_z40 $_z40 refs/heads/master + EOF + + cat >post-update.expect <<-EOF && + refs/heads/master + EOF + + test_cmp pre-receive.expect pre-receive.actual && + test_cmp update.expect update.actual && + test_cmp post-receive.expect post-receive.actual && + test_cmp post-update.expect post-update.actual + ) +' + +test_expect_success 'deletion of a non-existent ref is not fed to post-receive and post-update hooks' ' + mk_test_with_hooks heads/master && + orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) && + newmaster=$(git show-ref -s --verify refs/heads/master) && + git push testrepo master :refs/heads/nonexistent && + ( + cd testrepo/.git && + cat >pre-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + $_z40 $_z40 refs/heads/nonexistent + EOF + + cat >update.expect <<-EOF && + refs/heads/master $orgmaster $newmaster + refs/heads/nonexistent $_z40 $_z40 + EOF + + cat >post-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + EOF + + cat >post-update.expect <<-EOF && + refs/heads/master + EOF + + test_cmp pre-receive.expect pre-receive.actual && + test_cmp update.expect update.actual && + test_cmp post-receive.expect post-receive.actual && + test_cmp post-update.expect post-update.actual + ) +' + +test_expect_success 'deletion of a non-existent ref alone does trigger post-receive and post-update hooks' ' + mk_test_with_hooks heads/master && + git push testrepo :refs/heads/nonexistent && + ( + cd testrepo/.git && + cat >pre-receive.expect <<-EOF && + $_z40 $_z40 refs/heads/nonexistent + EOF + + cat >update.expect <<-EOF && + refs/heads/nonexistent $_z40 $_z40 + EOF + + test_cmp pre-receive.expect pre-receive.actual && + test_cmp update.expect update.actual && + test_path_is_missing post-receive.actual && + test_path_is_missing post-update.actual + ) +' + +test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks with correct input' ' + mk_test_with_hooks heads/master heads/next heads/pu && + orgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) && + newmaster=$(git show-ref -s --verify refs/heads/master) && + orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) && + newnext=$_z40 && + orgpu=$(cd testrepo && git show-ref -s --verify refs/heads/pu) && + newpu=$(git show-ref -s --verify refs/heads/master) && + git push testrepo refs/heads/master:refs/heads/master \ + refs/heads/master:refs/heads/pu :refs/heads/next \ + :refs/heads/nonexistent && + ( + cd testrepo/.git && + cat >pre-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + $orgnext $newnext refs/heads/next + $orgpu $newpu refs/heads/pu + $_z40 $_z40 refs/heads/nonexistent + EOF + + cat >update.expect <<-EOF && + refs/heads/master $orgmaster $newmaster + refs/heads/next $orgnext $newnext + refs/heads/pu $orgpu $newpu + refs/heads/nonexistent $_z40 $_z40 + EOF + + cat >post-receive.expect <<-EOF && + $orgmaster $newmaster refs/heads/master + $orgnext $newnext refs/heads/next + $orgpu $newpu refs/heads/pu + EOF + + cat >post-update.expect <<-EOF && + refs/heads/master + refs/heads/next + refs/heads/pu + EOF + + test_cmp pre-receive.expect pre-receive.actual && + test_cmp update.expect update.actual && + test_cmp post-receive.expect post-receive.actual && + test_cmp post-update.expect post-update.actual + ) +' + test_expect_success 'allow deleting a ref using --delete' ' mk_test heads/master && (cd testrepo && git config receive.denyDeleteCurrent warn) && diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 0470a81be0..0e5eb678ce 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -46,6 +46,17 @@ test_expect_success 'pulling into void using master:master' ' test_cmp file cloned-uho/file ' +test_expect_success 'pulling into void does not overwrite untracked files' ' + git init cloned-untracked && + ( + cd cloned-untracked && + echo untracked >file && + test_must_fail git pull .. master && + echo untracked >expect && + test_cmp expect file + ) +' + test_expect_success 'test . as a remote' ' git branch copy master && diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index 884a5e567c..ca5b027c55 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -47,7 +47,7 @@ test_expect_success setup ' git init && echo subcontent > subfile && git add subfile && - git submodule add "$pwd/deepsubmodule" deepsubmodule && + git submodule add "$pwd/deepsubmodule" subdir/deepsubmodule && git commit -a -m new ) && git submodule add "$pwd/submodule" submodule && @@ -58,7 +58,7 @@ test_expect_success setup ' git submodule update --init --recursive ) && echo "Fetching submodule submodule" > expect.out && - echo "Fetching submodule submodule/deepsubmodule" >> expect.out + echo "Fetching submodule submodule/subdir/deepsubmodule" >> expect.out ' test_expect_success "fetch --recurse-submodules recurses into submodules" ' @@ -67,8 +67,8 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" ' cd downstream && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "fetch alone only fetches superproject" ' @@ -96,8 +96,8 @@ test_expect_success "using fetchRecurseSubmodules=true in .gitmodules recurses i git config -f .gitmodules submodule.submodule.fetchRecurseSubmodules true && git fetch >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "--no-recurse-submodules overrides .gitmodules config" ' @@ -124,11 +124,11 @@ test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setti ( cd downstream && git fetch --recurse-submodules >../actual.out 2>../actual.err && - git config -f --unset .gitmodules submodule.submodule.fetchRecurseSubmodules true && + git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules && git config --unset submodule.submodule.fetchRecurseSubmodules ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "--quiet propagates to submodules" ' @@ -146,14 +146,17 @@ test_expect_success "--dry-run propagates to submodules" ' cd downstream && git fetch --recurse-submodules --dry-run >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err && + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err +' + +test_expect_success "Without --dry-run propagates to submodules" ' ( cd downstream && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "recurseSubmodules=true propagates into submodules" ' @@ -163,8 +166,8 @@ test_expect_success "recurseSubmodules=true propagates into submodules" ' git config fetch.recurseSubmodules true git fetch >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "--recurse-submodules overrides config in submodule" ' @@ -177,8 +180,8 @@ test_expect_success "--recurse-submodules overrides config in submodule" ' ) && git fetch --recurse-submodules >../actual.out 2>../actual.err ) && - test_cmp expect.out actual.out && - test_cmp expect.err actual.err + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err ' test_expect_success "--no-recurse-submodules overrides config setting" ' @@ -192,4 +195,259 @@ test_expect_success "--no-recurse-submodules overrides config setting" ' ! test -s actual.err ' +test_expect_success "Recursion doesn't happen when no new commits are fetched in the superproject" ' + ( + cd downstream && + ( + cd submodule && + git config --unset fetch.recurseSubmodules + ) && + git config --unset fetch.recurseSubmodules + git fetch >../actual.out 2>../actual.err + ) && + ! test -s actual.out && + ! test -s actual.err +' + +test_expect_success "Recursion stops when no new submodule commits are fetched" ' + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + echo "Fetching submodule submodule" > expect.out.sub && + echo "From $pwd/." > expect.err.sub && + echo " $head1..$head2 master -> origin/master" >> expect.err.sub + head -2 expect.err >> expect.err.sub && + ( + cd downstream && + git fetch >../actual.out 2>../actual.err + ) && + test_i18ncmp expect.err.sub actual.err && + test_i18ncmp expect.out.sub actual.out +' + +test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" ' + add_upstream_commit && + head1=$(git rev-parse --short HEAD) && + echo a > file && + git add file && + git commit -m "new file" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.file && + echo " $head1..$head2 master -> origin/master" >> expect.err.file && + ( + cd downstream && + git fetch >../actual.out 2>../actual.err + ) && + ! test -s actual.out && + test_i18ncmp expect.err.file actual.err +' + +test_expect_success "Recursion picks up config in submodule" ' + ( + cd downstream && + git fetch --recurse-submodules && + ( + cd submodule && + git config fetch.recurseSubmodules true + ) + ) && + add_upstream_commit && + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.sub && + echo " $head1..$head2 master -> origin/master" >> expect.err.sub && + cat expect.err >> expect.err.sub && + ( + cd downstream && + git fetch >../actual.out 2>../actual.err && + ( + cd submodule && + git config --unset fetch.recurseSubmodules + ) + ) && + test_i18ncmp expect.err.sub actual.err && + test_i18ncmp expect.out actual.out +' + +test_expect_success "Recursion picks up all submodules when necessary" ' + add_upstream_commit && + ( + cd submodule && + ( + cd subdir/deepsubmodule && + git fetch && + git checkout -q FETCH_HEAD + ) && + head1=$(git rev-parse --short HEAD^) && + git add subdir/deepsubmodule && + git commit -m "new deepsubmodule" + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/submodule" > ../expect.err.sub && + echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub + ) && + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.2 && + echo " $head1..$head2 master -> origin/master" >> expect.err.2 && + cat expect.err.sub >> expect.err.2 && + tail -2 expect.err >> expect.err.2 && + ( + cd downstream && + git fetch >../actual.out 2>../actual.err + ) && + test_i18ncmp expect.err.2 actual.err && + test_i18ncmp expect.out actual.out +' + +test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" ' + add_upstream_commit && + ( + cd submodule && + ( + cd subdir/deepsubmodule && + git fetch && + git checkout -q FETCH_HEAD + ) && + head1=$(git rev-parse --short HEAD^) && + git add subdir/deepsubmodule && + git commit -m "new deepsubmodule" + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/submodule" > ../expect.err.sub && + echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub + ) && + ( + cd downstream && + git config fetch.recurseSubmodules true && + git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err && + git config --unset fetch.recurseSubmodules + ) && + ! test -s actual.out && + ! test -s actual.err +' + +test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" ' + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + tail -2 expect.err > expect.err.deepsub && + echo "From $pwd/." > expect.err && + echo " $head1..$head2 master -> origin/master" >> expect.err + cat expect.err.sub >> expect.err && + cat expect.err.deepsub >> expect.err && + ( + cd downstream && + git config fetch.recurseSubmodules false && + ( + cd submodule && + git config -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive false + ) && + git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err && + git config --unset fetch.recurseSubmodules + ( + cd submodule && + git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive + ) + ) && + test_i18ncmp expect.out actual.out && + test_i18ncmp expect.err actual.err +' + +test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" ' + add_upstream_commit && + head1=$(git rev-parse --short HEAD) && + echo a >> file && + git add file && + git commit -m "new file" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.file && + echo " $head1..$head2 master -> origin/master" >> expect.err.file && + ( + cd downstream && + git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err + ) && + ! test -s actual.out && + test_i18ncmp expect.err.file actual.err +' + +test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config" ' + ( + cd downstream && + git fetch --recurse-submodules + ) && + add_upstream_commit && + git config --global fetch.recurseSubmodules false && + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.2 && + echo " $head1..$head2 master -> origin/master" >> expect.err.2 + head -2 expect.err >> expect.err.2 && + ( + cd downstream && + git config fetch.recurseSubmodules on-demand && + git fetch >../actual.out 2>../actual.err + ) && + git config --global --unset fetch.recurseSubmodules && + ( + cd downstream && + git config --unset fetch.recurseSubmodules + ) && + test_i18ncmp expect.out.sub actual.out && + test_i18ncmp expect.err.2 actual.err +' + +test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' overrides fetch.recurseSubmodules" ' + ( + cd downstream && + git fetch --recurse-submodules + ) && + add_upstream_commit && + git config fetch.recurseSubmodules false && + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "new submodule" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err.2 && + echo " $head1..$head2 master -> origin/master" >> expect.err.2 + head -2 expect.err >> expect.err.2 && + ( + cd downstream && + git config submodule.submodule.fetchRecurseSubmodules on-demand && + git fetch >../actual.out 2>../actual.err + ) && + git config --unset fetch.recurseSubmodules && + ( + cd downstream && + git config --unset submodule.submodule.fetchRecurseSubmodules + ) && + test_i18ncmp expect.out.sub actual.out && + test_i18ncmp expect.err.2 actual.err +' + +test_expect_success "don't fetch submodule when newly recorded commits are already present" ' + ( + cd submodule && + git checkout -q HEAD^^ + ) && + head1=$(git rev-parse --short HEAD) && + git add submodule && + git commit -m "submodule rewound" && + head2=$(git rev-parse --short HEAD) && + echo "From $pwd/." > expect.err && + echo " $head1..$head2 master -> origin/master" >> expect.err && + ( + cd downstream && + git fetch >../actual.out 2>../actual.err + ) && + ! test -s actual.out && + test_i18ncmp expect.err actual.err +' + test_done diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index faa2e96337..30bec4b5f9 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -32,4 +32,91 @@ test_expect_success push ' ) ' +test_expect_success 'push if submodule has no remote' ' + ( + cd work/gar/bage && + >junk2 && + git add junk2 && + git commit -m "Second junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Second commit for gar/bage" && + git push --recurse-submodules=check ../pub.git master + ) +' + +test_expect_success 'push fails if submodule commit not on remote' ' + ( + cd work/gar && + git clone --bare bage ../../submodule.git && + cd bage && + git remote add origin ../../../submodule.git && + git fetch && + >junk3 && + git add junk3 && + git commit -m "Third junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Third commit for gar/bage" && + test_must_fail git push --recurse-submodules=check ../pub.git master + ) +' + +test_expect_success 'push succeeds after commit was pushed to remote' ' + ( + cd work/gar/bage && + git push origin master + ) && + ( + cd work && + git push --recurse-submodules=check ../pub.git master + ) +' + +test_expect_success 'push fails when commit on multiple branches if one branch has no remote' ' + ( + cd work/gar/bage && + >junk4 && + git add junk4 && + git commit -m "Fourth junk" + ) && + ( + cd work && + git branch branch2 && + git add gar/bage && + git commit -m "Fourth commit for gar/bage" && + git checkout branch2 && + ( + cd gar/bage && + git checkout HEAD~1 + ) && + >junk1 && + git add junk1 && + git commit -m "First junk" && + test_must_fail git push --recurse-submodules=check ../pub.git + ) +' + +test_expect_success 'push succeeds if submodule has no remote and is on the first superproject commit' ' + git init --bare a + git clone a a1 && + ( + cd a1 && + git init b + ( + cd b && + >junk && + git add junk && + git commit -m "initial" + ) && + git add b && + git commit -m "added submodule" && + git push --recurse-submodule=check origin master + ) +' + test_done diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh new file mode 100755 index 0000000000..62f2460047 --- /dev/null +++ b/t/t5532-fetch-proxy.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='fetching via git:// using core.gitproxy' +. ./test-lib.sh + +test_expect_success 'setup remote repo' ' + git init remote && + (cd remote && + echo content >file && + git add file && + git commit -m one + ) +' + +cat >proxy <<'EOF' +#!/bin/sh +echo >&2 "proxying for $*" +cmd=`perl -e ' + read(STDIN, $buf, 4); + my $n = hex($buf) - 4; + read(STDIN, $buf, $n); + my ($cmd, $other) = split /\0/, $buf; + # drop absolute-path on repo name + $cmd =~ s{ /}{ }; + print $cmd; +'` +echo >&2 "Running '$cmd'" +exec $cmd +EOF +chmod +x proxy +test_expect_success 'setup local repo' ' + git remote add fake git://example.com/remote && + git config core.gitproxy ./proxy +' + +test_expect_success 'fetch through proxy works' ' + git fetch fake && + echo one >expect && + git log -1 --format=%s FETCH_HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index a266ca5636..64767d8705 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -132,8 +132,12 @@ x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1" x40="$x38$x2" test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' ' - sed -e "s/PUT /OP /" -e "s/MOVE /OP /" "$HTTPD_ROOT_PATH"/access.log | - grep -e "\"OP .*/objects/$x2/${x38}_$x40 HTTP/[.0-9]*\" 20[0-9] " + sed \ + -e "s/PUT /OP /" \ + -e "s/MOVE /OP /" \ + -e "s|/objects/$x2/${x38}_$x40|WANTED_PATH_REQUEST|" \ + "$HTTPD_ROOT_PATH"/access.log | + grep -e "\"OP .*WANTED_PATH_REQUEST HTTP/[.0-9]*\" 20[0-9] " ' diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh index b0c2a2c3ae..a73c82635f 100755 --- a/t/t5541-http-push.sh +++ b/t/t5541-http-push.sh @@ -65,14 +65,16 @@ test_expect_success 'clone remote repository' ' git clone $HTTPD_URL/smart/test_repo.git test_repo_clone ' -test_expect_success 'push to remote repository' ' +test_expect_success 'push to remote repository (standard)' ' cd "$ROOT_PATH"/test_repo_clone && : >path2 && git add path2 && test_tick && git commit -m path2 && HEAD=$(git rev-parse --verify HEAD) && - git push && + GIT_CURL_VERBOSE=1 git push -v -v 2>err && + ! grep "Expect: 100-continue" err && + grep "POST git-receive-pack ([0-9]* bytes)" err && (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && test $HEAD = $(git rev-parse --verify HEAD)) ' @@ -128,14 +130,29 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he # push master too; this ensures there is at least one '"'push'"' command to # the remote helper and triggers interaction with the helper. - test_must_fail git push -v origin +master master:retsam >output 2>&1 && + test_must_fail git push -v origin +master master:retsam >output 2>&1' +test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' ' grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output && - grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output && + grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output +' - grep "To prevent you from losing history, non-fast-forward updates were rejected" \ +test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' ' + test_i18ngrep "To prevent you from losing history, non-fast-forward updates were rejected" \ output ' +test_expect_success 'push (chunked)' ' + git checkout master && + test_commit commit path3 && + HEAD=$(git rev-parse --verify HEAD) && + git config http.postbuffer 4 && + test_when_finished "git config --unset http.postbuffer" && + git push -v -v origin $BRANCH 2>err && + grep "POST git-receive-pack (chunked)" err && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD = $(git rev-parse --verify HEAD)) +' + stop_httpd test_done diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index a1883ca6b6..311a33ca84 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -8,8 +8,8 @@ if test -n "$NO_CURL"; then test_done fi -. "$TEST_DIRECTORY"/lib-httpd.sh LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'} +. "$TEST_DIRECTORY"/lib-httpd.sh start_httpd test_expect_success 'setup repository' ' @@ -35,11 +35,54 @@ test_expect_success 'clone http repository' ' test_cmp file clone/file ' -test_expect_success 'clone http repository with authentication' ' +test_expect_success 'create password-protected repository' ' mkdir "$HTTPD_DOCUMENT_ROOT_PATH/auth/" && - cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" "$HTTPD_DOCUMENT_ROOT_PATH/auth/repo.git" && - git clone $AUTH_HTTPD_URL/auth/repo.git clone-auth && - test_cmp file clone-auth/file + cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \ + "$HTTPD_DOCUMENT_ROOT_PATH/auth/repo.git" +' + +test_expect_success 'setup askpass helpers' ' + cat >askpass <<-EOF && + #!/bin/sh + echo >>"$PWD/askpass-query" "askpass: \$*" && + cat "$PWD/askpass-response" + EOF + chmod +x askpass && + GIT_ASKPASS="$PWD/askpass" && + export GIT_ASKPASS && + >askpass-expect-none && + echo "askpass: Password for '\''$HTTPD_DEST'\'': " >askpass-expect-pass && + { echo "askpass: Username for '\''$HTTPD_DEST'\'': " && + cat askpass-expect-pass + } >askpass-expect-both +' + +test_expect_success 'cloning password-protected repository can fail' ' + >askpass-query && + echo wrong >askpass-response && + test_must_fail git clone "$HTTPD_URL/auth/repo.git" clone-auth-fail && + test_cmp askpass-expect-both askpass-query +' + +test_expect_success 'http auth can use user/pass in URL' ' + >askpass-query && + echo wrong >askpass-reponse && + git clone "$HTTPD_URL_USER_PASS/auth/repo.git" clone-auth-none && + test_cmp askpass-expect-none askpass-query +' + +test_expect_success 'http auth can use just user in URL' ' + >askpass-query && + echo user@host >askpass-response && + git clone "$HTTPD_URL_USER/auth/repo.git" clone-auth-pass && + test_cmp askpass-expect-pass askpass-query +' + +test_expect_success 'http auth can request both user and pass' ' + >askpass-query && + echo user@host >askpass-response && + git clone "$HTTPD_URL/auth/repo.git" clone-auth-both && + test_cmp askpass-expect-both askpass-query ' test_expect_success 'fetch changes via http' ' diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 987e0c8463..87ee01662c 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -31,7 +31,7 @@ test_expect_success 'clone with excess parameters (2)' ' ' -test_expect_success 'output from clone' ' +test_expect_success C_LOCALE_OUTPUT 'output from clone' ' rm -fr dst && git clone -n "file://$(pwd)/src" dst >output && test $(grep Clon output | wc -l) = 1 @@ -164,7 +164,6 @@ test_expect_success 'clone a void' ' test_expect_success 'clone respects global branch.autosetuprebase' ' ( test_config="$HOME/.gitconfig" && - unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" branch.autosetuprebase remote && rm -fr dst && git clone src dst && @@ -192,4 +191,61 @@ test_expect_success 'do not respect url-encoding of non-url path' ' git clone x+y xy-regular ' +test_expect_success 'clone separate gitdir' ' + rm -rf dst && + git clone --separate-git-dir realgitdir src dst && + test -d realgitdir/refs +' + +test_expect_success 'clone separate gitdir: output' ' + echo "gitdir: `pwd`/realgitdir" >expected && + test_cmp expected dst/.git +' + +test_expect_success 'clone from .git file' ' + git clone dst/.git dst2 +' + +test_expect_success 'fetch from .git gitfile' ' + ( + cd dst2 && + git fetch ../dst/.git + ) +' + +test_expect_success 'fetch from gitfile parent' ' + ( + cd dst2 && + git fetch ../dst + ) +' + +test_expect_success 'clone separate gitdir where target already exists' ' + rm -rf dst && + test_must_fail git clone --separate-git-dir realgitdir src dst +' + +test_expect_success 'clone --reference from original' ' + git clone --shared --bare src src-1 && + git clone --bare src src-2 && + git clone --reference=src-2 --bare src-1 target-8 && + grep /src-2/ target-8/objects/info/alternates +' + +test_expect_success 'clone with more than one --reference' ' + git clone --bare src src-3 && + git clone --bare src src-4 && + git clone --reference=src-3 --reference=src-4 src target-9 && + grep /src-3/ target-9/.git/objects/info/alternates && + grep /src-4/ target-9/.git/objects/info/alternates +' + +test_expect_success 'clone from original with relative alternate' ' + mkdir nest && + git clone --bare src nest/src-5 && + echo ../../../src/.git/objects >nest/src-5/objects/info/alternates && + git clone --bare nest/src-5 target-10 && + grep /src/\\.git/objects target-10/objects/info/alternates +' + test_done diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh index 0f4d487be3..6972258b27 100755 --- a/t/t5701-clone-local.sh +++ b/t/t5701-clone-local.sh @@ -144,4 +144,17 @@ test_expect_success 'clone empty repository, and then push should not segfault.' test_must_fail git push) ' +test_expect_success 'cloning non-existent directory fails' ' + cd "$D" && + rm -rf does-not-exist && + test_must_fail git clone does-not-exist +' + +test_expect_success 'cloning non-git directory fails' ' + cd "$D" && + rm -rf not-a-git-repo not-a-git-repo-clone && + mkdir not-a-git-repo && + test_must_fail git clone not-a-git-repo not-a-git-repo-clone +' + test_done diff --git a/t/t5707-clone-detached.sh b/t/t5707-clone-detached.sh new file mode 100755 index 0000000000..8b0d607df1 --- /dev/null +++ b/t/t5707-clone-detached.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +test_description='test cloning a repository with detached HEAD' +. ./test-lib.sh + +head_is_detached() { + git --git-dir=$1/.git rev-parse --verify HEAD && + test_must_fail git --git-dir=$1/.git symbolic-ref HEAD +} + +test_expect_success 'setup' ' + echo one >file && + git add file && + git commit -m one && + echo two >file && + git commit -a -m two && + git tag two && + echo three >file && + git commit -a -m three +' + +test_expect_success 'clone repo (detached HEAD points to branch)' ' + git checkout master^0 && + git clone "file://$PWD" detached-branch +' +test_expect_success 'cloned HEAD matches' ' + echo three >expect && + git --git-dir=detached-branch/.git log -1 --format=%s >actual && + test_cmp expect actual +' +test_expect_failure 'cloned HEAD is detached' ' + head_is_detached detached-branch +' + +test_expect_success 'clone repo (detached HEAD points to tag)' ' + git checkout two^0 && + git clone "file://$PWD" detached-tag +' +test_expect_success 'cloned HEAD matches' ' + echo two >expect && + git --git-dir=detached-tag/.git log -1 --format=%s >actual && + test_cmp expect actual +' +test_expect_success 'cloned HEAD is detached' ' + head_is_detached detached-tag +' + +test_expect_success 'clone repo (detached HEAD points to history)' ' + git checkout two^ && + git clone "file://$PWD" detached-history +' +test_expect_success 'cloned HEAD matches' ' + echo one >expect && + git --git-dir=detached-history/.git log -1 --format=%s >actual && + test_cmp expect actual +' +test_expect_success 'cloned HEAD is detached' ' + head_is_detached detached-history +' + +test_expect_success 'clone repo (orphan detached HEAD)' ' + git checkout master^0 && + echo four >file && + git commit -a -m four && + git clone "file://$PWD" detached-orphan +' +test_expect_success 'cloned HEAD matches' ' + echo four >expect && + git --git-dir=detached-orphan/.git log -1 --format=%s >actual && + test_cmp expect actual +' +test_expect_success 'cloned HEAD is detached' ' + head_is_detached detached-orphan +' + +test_done diff --git a/t/t5708-clone-config.sh b/t/t5708-clone-config.sh new file mode 100755 index 0000000000..27d730c0a7 --- /dev/null +++ b/t/t5708-clone-config.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +test_description='tests for git clone -c key=value' +. ./test-lib.sh + +test_expect_success 'clone -c sets config in cloned repo' ' + rm -rf child && + git clone -c core.foo=bar . child && + echo bar >expect && + git --git-dir=child/.git config core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c can set multi-keys' ' + rm -rf child && + git clone -c core.foo=bar -c core.foo=baz . child && + { echo bar; echo baz; } >expect && + git --git-dir=child/.git config --get-all core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c without a value is boolean true' ' + rm -rf child && + git clone -c core.foo . child && + echo true >expect && + git --git-dir=child/.git config --bool core.foo >actual && + test_cmp expect actual +' + +test_expect_success 'clone -c config is available during clone' ' + echo content >file && + git add file && + git commit -m one && + rm -rf child && + git clone -c core.autocrlf . child && + printf "content\\r\\n" >expect && + test_cmp expect child/file +' + +test_done diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh index 1fb6380fce..1c62001fce 100755 --- a/t/t5800-remote-helpers.sh +++ b/t/t5800-remote-helpers.sh @@ -7,17 +7,27 @@ test_description='Test remote-helper import and export commands' . ./test-lib.sh -if test_have_prereq PYTHON && "$PYTHON_PATH" -c ' +if ! test_have_prereq PYTHON ; then + skip_all='skipping git-remote-hg tests, python not available' + test_done +fi + +"$PYTHON_PATH" -c ' import sys if sys.hexversion < 0x02040000: sys.exit(1) -' -then - # Requires Python 2.4 or newer - test_set_prereq PYTHON_24 -fi +' || { + skip_all='skipping git-remote-hg tests, python version < 2.4' + test_done +} + +compare_refs() { + git --git-dir="$1/.git" rev-parse --verify $2 >expect && + git --git-dir="$3/.git" rev-parse --verify $4 >actual && + test_cmp expect actual +} -test_expect_success PYTHON_24 'setup repository' ' +test_expect_success 'setup repository' ' git init --bare server/.git && git clone server public && (cd public && @@ -27,54 +37,99 @@ test_expect_success PYTHON_24 'setup repository' ' git push origin master) ' -test_expect_success PYTHON_24 'cloning from local repo' ' +test_expect_success 'cloning from local repo' ' git clone "testgit::${PWD}/server" localclone && test_cmp public/file localclone/file ' -test_expect_success PYTHON_24 'cloning from remote repo' ' +test_expect_success 'cloning from remote repo' ' git clone "testgit::file://${PWD}/server" clone && test_cmp public/file clone/file ' -test_expect_success PYTHON_24 'create new commit on remote' ' +test_expect_success 'create new commit on remote' ' (cd public && echo content >>file && git commit -a -m two && git push) ' -test_expect_success PYTHON_24 'pulling from local repo' ' +test_expect_success 'pulling from local repo' ' (cd localclone && git pull) && test_cmp public/file localclone/file ' -test_expect_success PYTHON_24 'pulling from remote remote' ' +test_expect_success 'pulling from remote remote' ' (cd clone && git pull) && test_cmp public/file clone/file ' -test_expect_success PYTHON_24 'pushing to local repo' ' +test_expect_success 'pushing to local repo' ' (cd localclone && echo content >>file && git commit -a -m three && git push) && - HEAD=$(git --git-dir=localclone/.git rev-parse --verify HEAD) && - test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) + compare_refs localclone HEAD server HEAD ' -test_expect_success PYTHON_24 'synch with changes from localclone' ' +test_expect_success 'synch with changes from localclone' ' (cd clone && git pull) ' -test_expect_success PYTHON_24 'pushing remote local repo' ' +test_expect_success 'pushing remote local repo' ' (cd clone && echo content >>file && git commit -a -m four && git push) && - HEAD=$(git --git-dir=clone/.git rev-parse --verify HEAD) && - test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) + compare_refs clone HEAD server HEAD +' + +test_expect_success 'fetch new branch' ' + (cd public && + git checkout -b new && + echo content >>file && + git commit -a -m five && + git push origin new + ) && + (cd localclone && + git fetch origin new + ) && + compare_refs public HEAD localclone FETCH_HEAD +' + +test_expect_success 'fetch multiple branches' ' + (cd localclone && + git fetch + ) && + compare_refs server master localclone refs/remotes/origin/master && + compare_refs server new localclone refs/remotes/origin/new +' + +test_expect_success 'push when remote has extra refs' ' + (cd clone && + echo content >>file && + git commit -a -m six && + git push + ) && + compare_refs clone master server master +' + +test_expect_success 'push new branch by name' ' + (cd clone && + git checkout -b new-name && + echo content >>file && + git commit -a -m seven && + git push origin new-name + ) && + compare_refs clone HEAD server refs/heads/new-name +' + +test_expect_failure 'push new branch with old:new refspec' ' + (cd clone && + git push origin new-name:new-refspec + ) && + compare_refs clone HEAD server refs/heads/new-refspec ' test_done diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh new file mode 100755 index 0000000000..b10685af4e --- /dev/null +++ b/t/t6000-rev-list-misc.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +test_description='miscellaneous rev-list tests' + +. ./test-lib.sh + +test_expect_success setup ' + echo content1 >wanted_file && + echo content2 >unwanted_file && + git add wanted_file unwanted_file && + git commit -m one +' + +test_expect_success 'rev-list --objects heeds pathspecs' ' + git rev-list --objects HEAD -- wanted_file >output && + grep wanted_file output && + ! grep unwanted_file output +' + +test_expect_success 'rev-list --objects with pathspecs and deeper paths' ' + mkdir foo && + >foo/file && + git add foo/file && + git commit -m two && + + git rev-list --objects HEAD -- foo >output && + grep foo/file output && + + git rev-list --objects HEAD -- foo/file >output && + grep foo/file output && + ! grep unwanted_file output +' + +test_expect_success 'rev-list --objects with pathspecs and copied files' ' + git checkout --orphan junio-testcase && + git rm -rf . && + + mkdir two && + echo frotz >one && + cp one two/three && + git add one two/three && + test_tick && + git commit -m that && + + ONE=$(git rev-parse HEAD:one) + git rev-list --objects HEAD two >output && + grep "$ONE two/three" output && + ! grep one output +' + +test_done diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh index 5dabf1c5e3..3e8c42ee0b 100755 --- a/t/t6004-rev-list-path-optim.sh +++ b/t/t6004-rev-list-path-optim.sh @@ -1,51 +1,96 @@ #!/bin/sh -test_description='git rev-list trivial path optimization test' +test_description='git rev-list trivial path optimization test + + d/z1 + b0 b1 + o------------------------*----o master + / / + o---------o----o----o----o side + a0 c0 c1 a1 c2 + d/f0 d/f1 + d/z0 + +' . ./test-lib.sh test_expect_success setup ' -echo Hello > a && -git add a && -git commit -m "Initial commit" a && -initial=$(git rev-parse --verify HEAD) + echo Hello >a && + mkdir d && + echo World >d/f && + echo World >d/z && + git add a d && + test_tick && + git commit -m "Initial commit" && + git rev-parse --verify HEAD && + git tag initial ' test_expect_success path-optimization ' - commit=$(echo "Unchanged tree" | git commit-tree "HEAD^{tree}" -p HEAD) && - test $(git rev-list $commit | wc -l) = 2 && - test $(git rev-list $commit -- . | wc -l) = 1 + test_tick && + commit=$(echo "Unchanged tree" | git commit-tree "HEAD^{tree}" -p HEAD) && + test $(git rev-list $commit | wc -l) = 2 && + test $(git rev-list $commit -- . | wc -l) = 1 ' test_expect_success 'further setup' ' git checkout -b side && echo Irrelevant >c && - git add c && + echo Irrelevant >d/f && + git add c d/f && + test_tick && git commit -m "Side makes an irrelevant commit" && + git tag side_c0 && echo "More Irrelevancy" >c && git add c && + test_tick && git commit -m "Side makes another irrelevant commit" && echo Bye >a && git add a && + test_tick && git commit -m "Side touches a" && - side=$(git rev-parse --verify HEAD) && + git tag side_a1 && echo "Yet more Irrelevancy" >c && git add c && + test_tick && git commit -m "Side makes yet another irrelevant commit" && git checkout master && echo Another >b && - git add b && + echo Munged >d/z && + git add b d/z && + test_tick && git commit -m "Master touches b" && + git tag master_b0 && git merge side && echo Touched >b && git add b && + test_tick && git commit -m "Master touches b again" ' test_expect_success 'path optimization 2' ' - ( echo "$side"; echo "$initial" ) >expected && + git rev-parse side_a1 initial >expected && git rev-list HEAD -- a >actual && test_cmp expected actual ' +test_expect_success 'pathspec with leading path' ' + git rev-parse master^ master_b0 side_c0 initial >expected && + git rev-list HEAD -- d >actual && + test_cmp expected actual +' + +test_expect_success 'pathspec with glob (1)' ' + git rev-parse master^ master_b0 side_c0 initial >expected && + git rev-list HEAD -- "d/*" >actual && + test_cmp expected actual +' + +test_expect_success 'pathspec with glob (2)' ' + git rev-parse side_c0 initial >expected && + git rev-list HEAD -- "d/[a-m]*" >actual && + test_cmp expected actual +' + test_done diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index b565638e92..28d4f6b259 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -4,13 +4,14 @@ test_description='test git rev-list --cherry-pick -- file' . ./test-lib.sh -# A---B +# A---B---D---F # \ # \ -# C +# C---E # # B changes a file foo.c, adding a line of text. C changes foo.c as # well as bar.c, but the change in foo.c was identical to change B. +# D and C change bar in the same way, E and F differently. test_expect_success setup ' echo Hallo > foo && @@ -25,11 +26,26 @@ test_expect_success setup ' test_tick && git commit -m "C" && git tag C && + echo Dello > bar && + git add bar && + test_tick && + git commit -m "E" && + git tag E && git checkout master && git checkout branch foo && test_tick && git commit -m "B" && - git tag B + git tag B && + echo Cello > bar && + git add bar && + test_tick && + git commit -m "D" && + git tag D && + echo Nello > bar && + git add bar && + test_tick && + git commit -m "F" && + git tag F ' cat >expect <<EOF @@ -53,8 +69,119 @@ test_expect_success '--cherry-pick foo comes up empty' ' test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)" ' +cat >expect <<EOF +>tags/C +EOF + test_expect_success '--cherry-pick bar does not come up empty' ' - ! test -z "$(git rev-list --left-right --cherry-pick B...C -- bar)" + git rev-list --left-right --cherry-pick B...C -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +test_expect_success 'bar does not come up empty' ' + git rev-list --left-right B...C -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF +<tags/F +>tags/E +EOF + +test_expect_success '--cherry-pick bar does not come up empty (II)' ' + git rev-list --left-right --cherry-pick F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF ++tags/F +=tags/D ++tags/E +=tags/C +EOF + +test_expect_success '--cherry-mark' ' + git rev-list --cherry-mark F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF +<tags/F +=tags/D +>tags/E +=tags/C +EOF + +test_expect_success '--cherry-mark --left-right' ' + git rev-list --cherry-mark --left-right F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF +tags/E +EOF + +test_expect_success '--cherry-pick --right-only' ' + git rev-list --cherry-pick --right-only F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +test_expect_success '--cherry-pick --left-only' ' + git rev-list --cherry-pick --left-only E...F -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF ++tags/E +=tags/C +EOF + +test_expect_success '--cherry' ' + git rev-list --cherry F...E -- bar > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +cat >expect <<EOF +1 1 +EOF + +test_expect_success '--cherry --count' ' + git rev-list --cherry --count F...E -- bar > actual && + test_cmp actual expect +' + +cat >expect <<EOF +2 2 +EOF + +test_expect_success '--cherry-mark --count' ' + git rev-list --cherry-mark --count F...E -- bar > actual && + test_cmp actual expect +' + +cat >expect <<EOF +1 1 2 +EOF + +test_expect_success '--cherry-mark --left-right --count' ' + git rev-list --cherry-mark --left-right --count F...E -- bar > actual && + test_cmp actual expect ' test_expect_success '--cherry-pick with independent, but identical branches' ' @@ -75,11 +202,8 @@ cat >expect <<EOF 1 2 EOF -# Insert an extra commit to break the symmetry test_expect_success '--count --left-right' ' - git checkout branch && - test_commit D && - git rev-list --count --left-right B...D > actual && + git rev-list --count --left-right C...D > actual && test_cmp expect actual ' diff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh index 52f7b277ce..30507407ff 100755 --- a/t/t6009-rev-list-parent.sh +++ b/t/t6009-rev-list-parent.sh @@ -1,14 +1,15 @@ #!/bin/sh -test_description='properly cull all ancestors' +test_description='ancestor culling and limiting by parent number' . ./test-lib.sh -commit () { - test_tick && - echo $1 >file && - git commit -a -m $1 && - git tag $1 +check_revlist () { + rev_list_args="$1" && + shift && + git rev-parse "$@" >expect && + git rev-list $rev_list_args --all >actual && + test_cmp expect actual } test_expect_success setup ' @@ -16,13 +17,13 @@ test_expect_success setup ' touch file && git add file && - commit one && + test_commit one && test_tick=$(($test_tick - 2400)) && - commit two && - commit three && - commit four && + test_commit two && + test_commit three && + test_commit four && git log --pretty=oneline --abbrev-commit ' @@ -35,4 +36,101 @@ test_expect_success 'one is ancestor of others and should not be shown' ' ' +test_expect_success 'setup roots, merges and octopuses' ' + + git checkout --orphan newroot && + test_commit five && + git checkout -b sidebranch two && + test_commit six && + git checkout -b anotherbranch three && + test_commit seven && + git checkout -b yetanotherbranch four && + test_commit eight && + git checkout master && + test_merge normalmerge newroot && + test_tick && + git merge -m tripus sidebranch anotherbranch && + git tag tripus && + git checkout -b tetrabranch normalmerge && + test_tick && + git merge -m tetrapus sidebranch anotherbranch yetanotherbranch && + git tag tetrapus && + git checkout master +' + +test_expect_success 'rev-list roots' ' + + check_revlist "--max-parents=0" one five +' + +test_expect_success 'rev-list no merges' ' + + check_revlist "--max-parents=1" one eight seven six five four three two && + check_revlist "--no-merges" one eight seven six five four three two +' + +test_expect_success 'rev-list no octopuses' ' + + check_revlist "--max-parents=2" one normalmerge eight seven six five four three two +' + +test_expect_success 'rev-list no roots' ' + + check_revlist "--min-parents=1" tetrapus tripus normalmerge eight seven six four three two +' + +test_expect_success 'rev-list merges' ' + + check_revlist "--min-parents=2" tetrapus tripus normalmerge && + check_revlist "--merges" tetrapus tripus normalmerge +' + +test_expect_success 'rev-list octopus' ' + + check_revlist "--min-parents=3" tetrapus tripus +' + +test_expect_success 'rev-list ordinary commits' ' + + check_revlist "--min-parents=1 --max-parents=1" eight seven six four three two +' + +test_expect_success 'rev-list --merges --no-merges yields empty set' ' + + check_revlist "--min-parents=2 --no-merges" && + check_revlist "--merges --no-merges" && + check_revlist "--no-merges --merges" +' + +test_expect_success 'rev-list override and infinities' ' + + check_revlist "--min-parents=2 --max-parents=1 --max-parents=3" tripus normalmerge && + check_revlist "--min-parents=1 --min-parents=2 --max-parents=7" tetrapus tripus normalmerge && + check_revlist "--min-parents=2 --max-parents=8" tetrapus tripus normalmerge && + check_revlist "--min-parents=2 --max-parents=-1" tetrapus tripus normalmerge && + check_revlist "--min-parents=2 --no-max-parents" tetrapus tripus normalmerge && + check_revlist "--max-parents=0 --min-parents=1 --no-min-parents" one five +' + +test_expect_success 'dodecapus' ' + + roots= && + for i in 1 2 3 4 5 6 7 8 9 10 11 + do + git checkout -b root$i five && + test_commit $i && + roots="$roots root$i" || + return + done && + git checkout master && + test_tick && + git merge -m dodecapus $roots && + git tag dodecapus && + + check_revlist "--min-parents=4" dodecapus tetrapus && + check_revlist "--min-parents=8" dodecapus && + check_revlist "--min-parents=12" dodecapus && + check_revlist "--min-parents=13" && + check_revlist "--min-parents=4 --max-parents=11" tetrapus +' test_done diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh index 082032edc3..f80bba871c 100755 --- a/t/t6010-merge-base.sh +++ b/t/t6010-merge-base.sh @@ -8,38 +8,38 @@ test_description='Merge base and parent list computation. . ./test-lib.sh -test_expect_success 'setup' ' - T=$(git write-tree) && +M=1130000000 +Z=+0000 - M=1130000000 && - Z=+0000 && +GIT_COMMITTER_EMAIL=git@comm.iter.xz +GIT_COMMITTER_NAME='C O Mmiter' +GIT_AUTHOR_NAME='A U Thor' +GIT_AUTHOR_EMAIL=git@au.thor.xz +export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL - GIT_COMMITTER_EMAIL=git@comm.iter.xz && - GIT_COMMITTER_NAME="C O Mmiter" && - GIT_AUTHOR_NAME="A U Thor" && - GIT_AUTHOR_EMAIL=git@au.thor.xz && - export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL && +doit () { + OFFSET=$1 && + NAME=$2 && + shift 2 && - doit() { - OFFSET=$1 && - NAME=$2 && - shift 2 && + PARENTS= && + for P + do + PARENTS="${PARENTS}-p $P " + done && - PARENTS= && - for P - do - PARENTS="${PARENTS}-p $P " - done && + GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" && + GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE && + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE && - GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" && - GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE && - export GIT_COMMITTER_DATE GIT_AUTHOR_DATE && + commit=$(echo $NAME | git commit-tree $T $PARENTS) && - commit=$(echo $NAME | git commit-tree $T $PARENTS) && + echo $commit >.git/refs/tags/$NAME && + echo $commit +} - echo $commit >.git/refs/tags/$NAME && - echo $commit - } +test_expect_success 'setup' ' + T=$(git mktree </dev/null) ' test_expect_success 'set up G and H' ' diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh index f1c32dba42..667b37564e 100755 --- a/t/t6017-rev-list-stdin.sh +++ b/t/t6017-rev-list-stdin.sh @@ -58,4 +58,21 @@ check side-3 ^side-4 -- file-3 check side-3 ^side-2 check side-3 ^side-2 -- file-1 +test_expect_success 'not only --stdin' ' + cat >expect <<-EOF && + 7 + + file-1 + file-2 + EOF + cat >input <<-EOF && + ^master^ + -- + file-2 + EOF + git log --pretty=tformat:%s --name-only --stdin master -- file-1 \ + <input >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index fb8291c812..f00cebff3e 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -69,6 +69,18 @@ test_expect_success 'rev-parse --glob=heads/subspace' ' ' +test_expect_failure 'rev-parse accepts --glob as detached option' ' + + compare rev-parse "subspace/one subspace/two" "--glob heads/subspace" + +' + +test_expect_failure 'rev-parse is not confused by option-like glob' ' + + compare rev-parse "master" "--glob --symbolic master" + +' + test_expect_success 'rev-parse --branches=subspace/*' ' compare rev-parse "subspace/one subspace/two" "--branches=subspace/*" @@ -129,6 +141,12 @@ test_expect_success 'rev-list --glob refs/heads/subspace/*' ' ' +test_expect_success 'rev-list not confused by option-like --glob arg' ' + + compare rev-list "master" "--glob -0 master" + +' + test_expect_success 'rev-list --glob=heads/subspace/*' ' compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/*" @@ -213,4 +231,36 @@ test_expect_success 'rev-list --remotes=foo' ' ' +test_expect_success 'shortlog accepts --glob/--tags/--remotes' ' + + compare shortlog "subspace/one subspace/two" --branches=subspace && + compare shortlog \ + "master subspace-x someref other/three subspace/one subspace/two" \ + --branches && + compare shortlog master "--glob=heads/someref/* master" && + compare shortlog "subspace/one subspace/two other/three" \ + "--glob=heads/subspace/* --glob=heads/other/*" && + compare shortlog \ + "master other/three someref subspace-x subspace/one subspace/two" \ + "--glob=heads/*" && + compare shortlog foo/bar --tags=foo && + compare shortlog foo/bar --tags && + compare shortlog foo/baz --remotes=foo + +' + +test_expect_failure 'shortlog accepts --glob as detached option' ' + + compare shortlog \ + "master other/three someref subspace-x subspace/one subspace/two" \ + "--glob heads/*" + +' + +test_expect_failure 'shortlog --glob is not confused by option-like argument' ' + + compare shortlog master "--glob -e master" + +' + test_done diff --git a/t/t6019-rev-list-ancestry-path.sh b/t/t6019-rev-list-ancestry-path.sh index 76410293b3..39b4cb0ecd 100755 --- a/t/t6019-rev-list-ancestry-path.sh +++ b/t/t6019-rev-list-ancestry-path.sh @@ -70,4 +70,42 @@ test_expect_success 'rev-list --ancestry-patch D..M -- M.t' ' test_cmp expect actual ' +# b---bc +# / \ / +# a X +# \ / \ +# c---cb +# +# All refnames prefixed with 'x' to avoid confusion with the tags +# generated by test_commit on case-insensitive systems. +test_expect_success 'setup criss-cross' ' + mkdir criss-cross && + (cd criss-cross && + git init && + test_commit A && + git checkout -b xb master && + test_commit B && + git checkout -b xc master && + test_commit C && + git checkout -b xbc xb -- && + git merge xc && + git checkout -b xcb xc -- && + git merge xb && + git checkout master) +' + +# no commits in bc descend from cb +test_expect_success 'criss-cross: rev-list --ancestry-path cb..bc' ' + (cd criss-cross && + git rev-list --ancestry-path xcb..xbc > actual && + test -z "$(cat actual)") +' + +# no commits in repository descend from cb +test_expect_success 'criss-cross: rev-list --ancestry-path --all ^cb' ' + (cd criss-cross && + git rev-list --ancestry-path --all ^xcb > actual && + test -z "$(cat actual)") +' + test_done diff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh index eec8f4e3ed..27c3d73961 100755 --- a/t/t6020-merge-df.sh +++ b/t/t6020-merge-df.sh @@ -59,15 +59,19 @@ test_expect_success 'setup modify/delete + directory/file conflict' ' git add letters && git commit -m initial && + # Throw in letters.txt for sorting order fun + # ("letters.txt" sorts between "letters" and "letters/file") echo i >>letters && - git add letters && + echo "version 2" >letters.txt && + git add letters letters.txt && git commit -m modified && git checkout -b delete HEAD^ && git rm letters && mkdir letters && >letters/file && - git add letters && + echo "version 1" >letters.txt && + git add letters letters.txt && git commit -m deleted ' @@ -75,25 +79,31 @@ test_expect_success 'modify/delete + directory/file conflict' ' git checkout delete^0 && test_must_fail git merge modify && - test 3 = $(git ls-files -s | wc -l) && - test 2 = $(git ls-files -u | wc -l) && - test 1 = $(git ls-files -o | wc -l) && + test 5 -eq $(git ls-files -s | wc -l) && + test 4 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && test -f letters/file && + test -f letters.txt && test -f letters~modify ' test_expect_success 'modify/delete + directory/file conflict; other way' ' + # Yes, we really need the double reset since "letters" appears as + # both a file and a directory. + git reset --hard && git reset --hard && git clean -f && git checkout modify^0 && + test_must_fail git merge delete && - test 3 = $(git ls-files -s | wc -l) && - test 2 = $(git ls-files -u | wc -l) && - test 1 = $(git ls-files -o | wc -l) && + test 5 -eq $(git ls-files -s | wc -l) && + test 4 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && test -f letters/file && + test -f letters.txt && test -f letters~HEAD ' diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index 1ed259d864..9d8584e957 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -252,6 +252,7 @@ test_expect_success 'setup for rename + d/f conflicts' ' git reset --hard && git checkout --orphan dir-in-way && git rm -rf . && + git clean -fdqx && mkdir sub && mkdir dir && @@ -302,11 +303,11 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' git checkout -q renamed-file-has-no-conflicts^0 && test_must_fail git merge --strategy=recursive dir-in-way >output && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~HEAD instead" output && - test 2 -eq "$(git ls-files -u | wc -l)" && + test 3 -eq "$(git ls-files -u | wc -l)" && test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" && test_must_fail git diff --quiet && @@ -324,11 +325,11 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors && ! grep "error: refusing to lose untracked file at" errors && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~renamed-file-has-no-conflicts instead" output && - test 2 -eq "$(git ls-files -u | wc -l)" && + test 3 -eq "$(git ls-files -u | wc -l)" && test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" && test_must_fail git diff --quiet && @@ -350,11 +351,11 @@ cat >expected <<\EOF && 8 9 10 -<<<<<<< HEAD +<<<<<<< HEAD:dir 12 ======= 11 ->>>>>>> dir-not-in-way +>>>>>>> dir-not-in-way:sub/file EOF test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' ' @@ -404,11 +405,11 @@ cat >expected <<\EOF && 8 9 10 -<<<<<<< HEAD +<<<<<<< HEAD:sub/file 11 ======= 12 ->>>>>>> renamed-file-has-conflicts +>>>>>>> renamed-file-has-conflicts:dir EOF test_expect_success 'Same as previous, but merged other way' ' @@ -609,4 +610,278 @@ test_expect_success 'check handling of differently renamed file with D/F conflic ! test -f original ' +test_expect_success 'setup avoid unnecessary update, normal rename' ' + git reset --hard && + git checkout --orphan avoid-unnecessary-update-1 && + git rm -rf . && + git clean -fdqx && + + printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >original && + git add -A && + git commit -m "Common commmit" && + + git mv original rename && + echo 11 >>rename && + git add -u && + git commit -m "Renamed and modified" && + + git checkout -b merge-branch-1 HEAD~1 && + echo "random content" >random-file && + git add -A && + git commit -m "Random, unrelated changes" +' + +test_expect_success 'avoid unnecessary update, normal rename' ' + git checkout -q avoid-unnecessary-update-1^0 && + test-chmtime =1000000000 rename && + test-chmtime -v +0 rename >expect && + git merge merge-branch-1 && + test-chmtime -v +0 rename >actual && + test_cmp expect actual # "rename" should have stayed intact +' + +test_expect_success 'setup to test avoiding unnecessary update, with D/F conflict' ' + git reset --hard && + git checkout --orphan avoid-unnecessary-update-2 && + git rm -rf . && + git clean -fdqx && + + mkdir df && + printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" >df/file && + git add -A && + git commit -m "Common commmit" && + + git mv df/file temp && + rm -rf df && + git mv temp df && + echo 11 >>df && + git add -u && + git commit -m "Renamed and modified" && + + git checkout -b merge-branch-2 HEAD~1 && + >unrelated-change && + git add unrelated-change && + git commit -m "Only unrelated changes" +' + +test_expect_success 'avoid unnecessary update, with D/F conflict' ' + git checkout -q avoid-unnecessary-update-2^0 && + test-chmtime =1000000000 df && + test-chmtime -v +0 df >expect && + git merge merge-branch-2 && + test-chmtime -v +0 df >actual && + test_cmp expect actual # "df" should have stayed intact +' + +test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + >irrelevant && + mkdir df && + >df/file && + git add -A && + git commit -mA && + + git checkout -b side + git rm -rf df && + git commit -mB && + + git checkout master && + git rm -rf df && + echo bla >df && + git add -A && + git commit -m "Add a newfile" +' + +test_expect_success 'avoid unnecessary update, dir->(file,nothing)' ' + git checkout -q master^0 && + test-chmtime =1000000000 df && + test-chmtime -v +0 df >expect && + git merge side && + test-chmtime -v +0 df >actual && + test_cmp expect actual # "df" should have stayed intact +' + +test_expect_success 'setup avoid unnecessary update, modify/delete' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + >irrelevant && + >file && + git add -A && + git commit -mA && + + git checkout -b side + git rm -f file && + git commit -m "Delete file" && + + git checkout master && + echo bla >file && + git add -A && + git commit -m "Modify file" +' + +test_expect_success 'avoid unnecessary update, modify/delete' ' + git checkout -q master^0 && + test-chmtime =1000000000 file && + test-chmtime -v +0 file >expect && + test_must_fail git merge side && + test-chmtime -v +0 file >actual && + test_cmp expect actual # "file" should have stayed intact +' + +test_expect_success 'setup avoid unnecessary update, rename/add-dest' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n7\n8\n" >file && + git add -A && + git commit -mA && + + git checkout -b side + cp file newfile && + git add -A && + git commit -m "Add file copy" && + + git checkout master && + git mv file newfile && + git commit -m "Rename file" +' + +test_expect_success 'avoid unnecessary update, rename/add-dest' ' + git checkout -q master^0 && + test-chmtime =1000000000 newfile && + test-chmtime -v +0 newfile >expect && + git merge side && + test-chmtime -v +0 newfile >actual && + test_cmp expect actual # "file" should have stayed intact +' + +test_expect_success 'setup merge of rename + small change' ' + git reset --hard && + git checkout --orphan rename-plus-small-change && + git rm -rf . && + git clean -fdqx && + + echo ORIGINAL >file && + git add file && + + test_tick && + git commit -m Initial && + git checkout -b rename_branch && + git mv file renamed_file && + git commit -m Rename && + git checkout rename-plus-small-change && + echo NEW-VERSION >file && + git commit -a -m Reformat +' + +test_expect_success 'merge rename + small change' ' + git merge rename_branch && + + test 1 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + test $(git rev-parse HEAD:renamed_file) = $(git rev-parse HEAD~1:file) +' + +test_expect_success 'setup for use of extended merge markers' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file && + git add original_file && + git commit -mA && + + git checkout -b rename && + echo 9 >>original_file && + git add original_file && + git mv original_file renamed_file && + git commit -mB && + + git checkout master && + echo 8.5 >>original_file && + git add original_file && + git commit -mC +' + +cat >expected <<\EOF && +1 +2 +3 +4 +5 +6 +7 +8 +<<<<<<< HEAD:renamed_file +9 +======= +8.5 +>>>>>>> master^0:original_file +EOF + +test_expect_success 'merge master into rename has correct extended markers' ' + git checkout rename^0 && + test_must_fail git merge -s recursive master^0 && + test_cmp expected renamed_file +' + +cat >expected <<\EOF && +1 +2 +3 +4 +5 +6 +7 +8 +<<<<<<< HEAD:original_file +8.5 +======= +9 +>>>>>>> rename^0:renamed_file +EOF + +test_expect_success 'merge rename into master has correct extended markers' ' + git reset --hard && + git checkout master^0 && + test_must_fail git merge -s recursive rename^0 && + test_cmp expected renamed_file +' + +test_expect_success 'setup spurious "refusing to lose untracked" message' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + > irrelevant_file && + printf "1\n2\n3\n4\n5\n6\n7\n8\n" >original_file && + git add irrelevant_file original_file && + git commit -mA && + + git checkout -b rename && + git mv original_file renamed_file && + git commit -mB && + + git checkout master && + git rm original_file && + git commit -mC +' + +test_expect_success 'no spurious "refusing to lose untracked" message' ' + git checkout master^0 && + test_must_fail git merge rename^0 2>errors.txt && + ! grep "refusing to lose untracked file" errors.txt +' + test_done diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index d9f343942c..432f086c06 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -154,7 +154,7 @@ test_expect_success "expected conflict markers" "test_cmp expect out" test_expect_success 'binary files cannot be merged' ' test_must_fail git merge-file -p \ - orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err && + orig.txt "$TEST_DIRECTORY"/test-binary-1.png new1.txt 2> merge.err && grep "Cannot merge binary files" merge.err ' diff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh index b519626ca0..07735410b9 100755 --- a/t/t6027-merge-binary.sh +++ b/t/t6027-merge-binary.sh @@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files' test_expect_success setup ' - cat "$TEST_DIRECTORY"/test4012.png >m && + cat "$TEST_DIRECTORY"/test-binary-1.png >m && git add m && git ls-files -s | sed -e "s/ 0 / 1 /" >E1 && test_tick && diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index b5063b6fe6..c6f1f9f8ab 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -126,6 +126,18 @@ test_expect_success 'bisect reset removes packed refs' ' test -z "$(git for-each-ref "refs/heads/bisect")" ' +test_expect_success 'bisect reset removes bisect state after --no-checkout' ' + git bisect reset && + git bisect start --no-checkout && + git bisect good $HASH1 && + git bisect bad $HASH3 && + git bisect next && + git bisect reset && + test -z "$(git for-each-ref "refs/bisect/*")" && + test -z "$(git for-each-ref "refs/heads/bisect")" && + test -z "$(git for-each-ref "BISECT_HEAD")" +' + test_expect_success 'bisect start: back in good branch' ' git branch > branch.output && grep "* other" branch.output > /dev/null && @@ -138,15 +150,23 @@ test_expect_success 'bisect start: back in good branch' ' grep "* other" branch.output > /dev/null ' -test_expect_success 'bisect start: no ".git/BISECT_START" if junk rev' ' - git bisect start $HASH4 $HASH1 -- && - git bisect good && +test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' ' + git bisect reset && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && grep "* other" branch.output > /dev/null && test_must_fail test -e .git/BISECT_START ' +test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' ' + git bisect start $HASH4 $HASH1 -- && + git bisect good && + cp .git/BISECT_START saved && + test_must_fail git bisect start $HASH4 foo -- && + git branch > branch.output && + grep "* (no branch)" branch.output > /dev/null && + test_cmp saved .git/BISECT_START +' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' git bisect start $HASH4 $HASH1 -- && git bisect good && @@ -572,6 +592,155 @@ test_expect_success 'erroring out when using bad path parameters' ' grep "bad path parameters" error.txt ' +test_expect_success 'test bisection on bare repo - --no-checkout specified' ' + git clone --bare . bare.nocheckout && + ( + cd bare.nocheckout && + git bisect start --no-checkout && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect run eval \ + "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \ + >../nocheckout.log && + git bisect reset + ) && + grep "$HASH3 is the first bad commit" nocheckout.log +' + + +test_expect_success 'test bisection on bare repo - --no-checkout defaulted' ' + git clone --bare . bare.defaulted && + ( + cd bare.defaulted && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect run eval \ + "test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \ + >../defaulted.log && + git bisect reset + ) && + grep "$HASH3 is the first bad commit" defaulted.log +' + # +# This creates a broken branch which cannot be checked out because +# the tree created has been deleted. # +# H1-H2-H3-H4-H5-H6-H7 <--other +# \ +# S5-S6'-S7'-S8'-S9 <--broken +# +# Commits marked with ' have a missing tree. +# +test_expect_success 'broken branch creation' ' + git bisect reset && + git checkout -b broken $HASH4 && + git tag BROKEN_HASH4 $HASH4 && + add_line_into_file "5(broken): first line on a broken branch" hello2 && + git tag BROKEN_HASH5 && + mkdir missing && + :> missing/MISSING && + git add missing/MISSING && + git commit -m "6(broken): Added file that will be deleted" + git tag BROKEN_HASH6 && + add_line_into_file "7(broken): second line on a broken branch" hello2 && + git tag BROKEN_HASH7 && + add_line_into_file "8(broken): third line on a broken branch" hello2 && + git tag BROKEN_HASH8 && + git rm missing/MISSING && + git commit -m "9(broken): Remove missing file" + git tag BROKEN_HASH9 && + rm .git/objects/39/f7e61a724187ab767d2e08442d9b6b9dab587d +' + +echo "" > expected.ok +cat > expected.missing-tree.default <<EOF +fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d +EOF + +test_expect_success 'bisect fails if tree is broken on start commit' ' + git bisect reset && + test_must_fail git bisect start BROKEN_HASH7 BROKEN_HASH4 2>error.txt && + test_cmp expected.missing-tree.default error.txt +' + +test_expect_success 'bisect fails if tree is broken on trial commit' ' + git bisect reset && + test_must_fail git bisect start BROKEN_HASH9 BROKEN_HASH4 2>error.txt && + git reset --hard broken && + git checkout broken && + test_cmp expected.missing-tree.default error.txt +' + +check_same() +{ + echo "Checking $1 is the same as $2" && + git rev-parse "$1" > expected.same && + git rev-parse "$2" > expected.actual && + test_cmp expected.same expected.actual +} + +test_expect_success 'bisect: --no-checkout - start commit bad' ' + git bisect reset && + git bisect start BROKEN_HASH7 BROKEN_HASH4 --no-checkout && + check_same BROKEN_HASH6 BISECT_HEAD && + git bisect reset +' + +test_expect_success 'bisect: --no-checkout - trial commit bad' ' + git bisect reset && + git bisect start broken BROKEN_HASH4 --no-checkout && + check_same BROKEN_HASH6 BISECT_HEAD && + git bisect reset +' + +test_expect_success 'bisect: --no-checkout - target before breakage' ' + git bisect reset && + git bisect start broken BROKEN_HASH4 --no-checkout && + check_same BROKEN_HASH6 BISECT_HEAD && + git bisect bad BISECT_HEAD && + check_same BROKEN_HASH5 BISECT_HEAD && + git bisect bad BISECT_HEAD && + check_same BROKEN_HASH5 bisect/bad && + git bisect reset +' + +test_expect_success 'bisect: --no-checkout - target in breakage' ' + git bisect reset && + git bisect start broken BROKEN_HASH4 --no-checkout && + check_same BROKEN_HASH6 BISECT_HEAD && + git bisect bad BISECT_HEAD && + check_same BROKEN_HASH5 BISECT_HEAD && + git bisect good BISECT_HEAD && + check_same BROKEN_HASH6 bisect/bad && + git bisect reset +' + +test_expect_success 'bisect: --no-checkout - target after breakage' ' + git bisect reset && + git bisect start broken BROKEN_HASH4 --no-checkout && + check_same BROKEN_HASH6 BISECT_HEAD && + git bisect good BISECT_HEAD && + check_same BROKEN_HASH8 BISECT_HEAD && + git bisect good BISECT_HEAD && + check_same BROKEN_HASH9 bisect/bad && + git bisect reset +' + +test_expect_success 'bisect: demonstrate identification of damage boundary' " + git bisect reset && + git checkout broken && + git bisect start broken master --no-checkout && + git bisect run \"\$SHELL_PATH\" -c ' + GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) && + git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ && + git pack-objects --stdout >/dev/null < tmp.\$\$ + rc=\$? + rm -f tmp.\$\$ + test \$rc = 0' && + check_same BROKEN_HASH6 bisect/bad && + git bisect reset +" + test_done diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh index 92e02d5d77..2599ae50eb 100755 --- a/t/t6035-merge-dir-to-symlink.sh +++ b/t/t6035-merge-dir-to-symlink.sh @@ -17,13 +17,21 @@ test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' git commit -m "dir to symlink" ' -test_expect_success SYMLINKS 'keep a/b-2/c/d across checkout' ' +test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' ' git checkout HEAD^0 && git reset --hard master && git rm --cached a/b && git commit -m "untracked symlink remains" && - git checkout start^0 && - test -f a/b-2/c/d + test_must_fail git checkout start^0 +' + +test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' ' + git checkout HEAD^0 && + git reset --hard master && + git rm --cached a/b && + git commit -m "untracked symlink remains" && + git checkout -f start^0 && + test -f a/b-2/c/d ' test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' ' diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh index 871577d90c..dfee7d159b 100755 --- a/t/t6036-recursive-corner-cases.sh +++ b/t/t6036-recursive-corner-cases.sh @@ -1,9 +1,15 @@ #!/bin/sh -test_description='recursive merge corner cases' +test_description='recursive merge corner cases involving criss-cross merges' . ./test-lib.sh +get_clean_checkout () { + git reset --hard && + git clean -fdqx && + git checkout "$1" +} + # # L1 L2 # o---o @@ -51,23 +57,15 @@ test_expect_success 'merge simple rename+criss-cross with no modifications' ' test_must_fail git merge -s recursive R2^0 && - test 5 = $(git ls-files -s | wc -l) && - test 3 = $(git ls-files -u | wc -l) && - test 0 = $(git ls-files -o | wc -l) && + test 2 = $(git ls-files -s | wc -l) && + test 2 = $(git ls-files -u | wc -l) && + test 2 = $(git ls-files -o | wc -l) && - test $(git rev-parse :0:one) = $(git rev-parse L2:one) && - test $(git rev-parse :0:two) = $(git rev-parse R2:two) && test $(git rev-parse :2:three) = $(git rev-parse L2:three) && test $(git rev-parse :3:three) = $(git rev-parse R2:three) && - cp two merged && - >empty && - test_must_fail git merge-file \ - -L "Temporary merge branch 2" \ - -L "" \ - -L "Temporary merge branch 1" \ - merged empty one && - test $(git rev-parse :1:three) = $(git hash-object merged) + test $(git rev-parse L2:three) = $(git hash-object three~HEAD) && + test $(git rev-parse R2:three) = $(git hash-object three~R2^0) ' # @@ -126,24 +124,15 @@ test_expect_success 'merge criss-cross + rename merges with basic modification' test_must_fail git merge -s recursive R2^0 && - test 5 = $(git ls-files -s | wc -l) && - test 3 = $(git ls-files -u | wc -l) && - test 0 = $(git ls-files -o | wc -l) && + test 2 = $(git ls-files -s | wc -l) && + test 2 = $(git ls-files -u | wc -l) && + test 2 = $(git ls-files -o | wc -l) && - test $(git rev-parse :0:one) = $(git rev-parse L2:one) && - test $(git rev-parse :0:two) = $(git rev-parse R2:two) && test $(git rev-parse :2:three) = $(git rev-parse L2:three) && test $(git rev-parse :3:three) = $(git rev-parse R2:three) && - head -n 10 two >merged && - cp one merge-me && - >empty && - test_must_fail git merge-file \ - -L "Temporary merge branch 2" \ - -L "" \ - -L "Temporary merge branch 1" \ - merged empty merge-me && - test $(git rev-parse :1:three) = $(git hash-object merged) + test $(git rev-parse L2:three) = $(git hash-object three~HEAD) && + test $(git rev-parse R2:three) = $(git hash-object three~R2^0) ' # @@ -231,4 +220,557 @@ test_expect_success 'git detects differently handled merges conflict' ' test $(git rev-parse :1:new_a) = $(git hash-object merged) ' +# +# criss-cross + modify/delete: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: file with contents 'A\n' +# Commit B: file with contents 'B\n' +# Commit C: file not present +# Commit D: file with contents 'B\n' +# Commit E: file not present +# +# Merging commits D & E should result in modify/delete conflict. + +test_expect_success 'setup criss-cross + modify/delete resolved differently' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + echo A >file && + git add file && + test_tick && + git commit -m A && + + git branch B && + git checkout -b C && + git rm file && + test_tick && + git commit -m C && + + git checkout B && + echo B >file && + git add file && + test_tick && + git commit -m B && + + git checkout B^0 && + test_must_fail git merge C && + echo B >file && + git add file && + test_tick && + git commit -m D && + git tag D && + + git checkout C^0 && + test_must_fail git merge B && + git rm file && + test_tick && + git commit -m E && + git tag E +' + +test_expect_success 'git detects conflict merging criss-cross+modify/delete' ' + git checkout D^0 && + + test_must_fail git merge -s recursive E^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + + test $(git rev-parse :1:file) = $(git rev-parse master:file) && + test $(git rev-parse :2:file) = $(git rev-parse B:file) +' + +test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' ' + git reset --hard && + git checkout E^0 && + + test_must_fail git merge -s recursive D^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + + test $(git rev-parse :1:file) = $(git rev-parse master:file) && + test $(git rev-parse :3:file) = $(git rev-parse B:file) +' + +# +# criss-cross + modify/modify with very contrived file contents: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: file with contents 'A\n' +# Commit B: file with contents 'B\n' +# Commit C: file with contents 'C\n' +# Commit D: file with contents 'D\n' +# Commit E: file with contents: +# <<<<<<< Temporary merge branch 1 +# C +# ======= +# B +# >>>>>>> Temporary merge branch 2 +# +# Now, when we merge commits D & E, does git detect the conflict? + +test_expect_success 'setup differently handled merges of content conflict' ' + git clean -fdqx && + rm -rf .git && + git init && + + echo A >file && + git add file && + test_tick && + git commit -m A && + + git branch B && + git checkout -b C && + echo C >file && + git add file && + test_tick && + git commit -m C && + + git checkout B && + echo B >file && + git add file && + test_tick && + git commit -m B && + + git checkout B^0 && + test_must_fail git merge C && + echo D >file && + git add file && + test_tick && + git commit -m D && + git tag D && + + git checkout C^0 && + test_must_fail git merge B && + cat <<EOF >file && +<<<<<<< Temporary merge branch 1 +C +======= +B +>>>>>>> Temporary merge branch 2 +EOF + git add file && + test_tick && + git commit -m E && + git tag E +' + +test_expect_failure 'git detects conflict w/ criss-cross+contrived resolution' ' + git checkout D^0 && + + test_must_fail git merge -s recursive E^0 && + + test 3 -eq $(git ls-files -s | wc -l) && + test 3 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :2:file) = $(git rev-parse D:file) && + test $(git rev-parse :3:file) = $(git rev-parse E:file) +' + +# +# criss-cross + d/f conflict via add/add: +# Commit A: Neither file 'a' nor directory 'a/' exist. +# Commit B: Introduce 'a' +# Commit C: Introduce 'a/file' +# Commit D: Merge B & C, keeping 'a' and deleting 'a/' +# +# Two different later cases: +# Commit E1: Merge B & C, deleting 'a' but keeping 'a/file' +# Commit E2: Merge B & C, deleting 'a' but keeping a slightly modified 'a/file' +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E1 or E2 +# +# Merging D & E1 requires we first create a virtual merge base X from +# merging A & B in memory. Now, if X could keep both 'a' and 'a/file' in +# the index, then the merge of D & E1 could be resolved cleanly with both +# 'a' and 'a/file' removed. Since git does not currently allow creating +# such a tree, the best we can do is have X contain both 'a~<unique>' and +# 'a/file' resulting in the merge of D and E1 having a rename/delete +# conflict for 'a'. (Although this merge appears to be unsolvable with git +# currently, git could do a lot better than it currently does with these +# d/f conflicts, which is the purpose of this test.) +# +# Merge of D & E2 has similar issues for path 'a', but should always result +# in a modify/delete conflict for path 'a/file'. +# +# We run each merge in both directions, to check for directional issues +# with D/F conflict handling. +# + +test_expect_success 'setup differently handled merges of directory/file conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + >ignore-me && + git add ignore-me && + test_tick && + git commit -m A && + git tag A && + + git branch B && + git checkout -b C && + mkdir a && + echo 10 >a/file && + git add a/file && + test_tick && + git commit -m C && + + git checkout B && + echo 5 >a && + git add a && + test_tick && + git commit -m B && + + git checkout B^0 && + test_must_fail git merge C && + git clean -f && + rm -rf a/ && + echo 5 >a && + git add a && + test_tick && + git commit -m D && + git tag D && + + git checkout C^0 && + test_must_fail git merge B && + git clean -f && + git rm --cached a && + echo 10 >a/file && + git add a/file && + test_tick && + git commit -m E1 && + git tag E1 && + + git checkout C^0 && + test_must_fail git merge B && + git clean -f && + git rm --cached a && + printf "10\n11\n" >a/file && + git add a/file && + test_tick && + git commit -m E2 && + git tag E2 +' + +test_expect_success 'merge of D & E1 fails but has appropriate contents' ' + get_clean_checkout D^0 && + + test_must_fail git merge -s recursive E1^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 1 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) && + test $(git rev-parse :2:a) = $(git rev-parse B:a) +' + +test_expect_success 'merge of E1 & D fails but has appropriate contents' ' + get_clean_checkout E1^0 && + + test_must_fail git merge -s recursive D^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 1 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) && + test $(git rev-parse :3:a) = $(git rev-parse B:a) +' + +test_expect_success 'merge of D & E2 fails but has appropriate contents' ' + get_clean_checkout D^0 && + + test_must_fail git merge -s recursive E2^0 && + + test 4 -eq $(git ls-files -s | wc -l) && + test 3 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :2:a) = $(git rev-parse B:a) && + test $(git rev-parse :3:a/file) = $(git rev-parse E2:a/file) && + test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) && + test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) && + + test -f a~HEAD +' + +test_expect_success 'merge of E2 & D fails but has appropriate contents' ' + get_clean_checkout E2^0 && + + test_must_fail git merge -s recursive D^0 && + + test 4 -eq $(git ls-files -s | wc -l) && + test 3 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :3:a) = $(git rev-parse B:a) && + test $(git rev-parse :2:a/file) = $(git rev-parse E2:a/file) && + test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) + test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) && + + test -f a~D^0 +' + +# +# criss-cross with rename/rename(1to2)/modify followed by +# rename/rename(2to1)/modify: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: new file: a +# Commit B: rename a->b, modifying by adding a line +# Commit C: rename a->c +# Commit D: merge B&C, resolving conflict by keeping contents in newname +# Commit E: merge B&C, resolving conflict similar to D but adding another line +# +# There is a conflict merging B & C, but one of filename not of file +# content. Whoever created D and E chose specific resolutions for that +# conflict resolution. Now, since: (1) there is no content conflict +# merging B & C, (2) D does not modify that merged content further, and (3) +# both D & E resolve the name conflict in the same way, the modification to +# newname in E should not cause any conflicts when it is merged with D. +# (Note that this can be accomplished by having the virtual merge base have +# the merged contents of b and c stored in a file named a, which seems like +# the most logical choice anyway.) +# +# Comment from Junio: I do not necessarily agree with the choice "a", but +# it feels sound to say "B and C do not agree what the final pathname +# should be, but we know this content was derived from the common A:a so we +# use one path whose name is arbitrary in the virtual merge base X between +# D and E" and then further let the rename detection to notice that that +# arbitrary path gets renamed between X-D to "newname" and X-E also to +# "newname" to resolve it as both sides renaming it to the same new +# name. It is akin to what we do at the content level, i.e. "B and C do not +# agree what the final contents should be, so we leave the conflict marker +# but that may cancel out at the final merge stage". + +test_expect_success 'setup rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' ' + git reset --hard && + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n" >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + echo 7 >>b && + git add -u && + git commit -m B && + + git checkout -b C A && + git mv a c && + git commit -m C && + + git checkout -q B^0 && + git merge --no-commit -s ours C^0 && + git mv b newname && + git commit -m "Merge commit C^0 into HEAD" && + git tag D && + + git checkout -q C^0 && + git merge --no-commit -s ours B^0 && + git mv c newname && + printf "7\n8\n" >>newname && + git add -u && + git commit -m "Merge commit B^0 into HEAD" && + git tag E +' + +test_expect_success 'handle rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' ' + git checkout D^0 && + + git merge -s recursive E^0 && + + test 1 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse HEAD:newname) = $(git rev-parse E:newname) +' + +# +# criss-cross with rename/rename(1to2)/add-source + resolvable modify/modify: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: new file: a +# Commit B: rename a->b +# Commit C: rename a->c, add different a +# Commit D: merge B&C, keeping b&c and (new) a modified at beginning +# Commit E: merge B&C, keeping b&c and (new) a modified at end +# +# Merging commits D & E should result in no conflict; doing so correctly +# requires getting the virtual merge base (from merging B&C) right, handling +# renaming carefully (both in the virtual merge base and later), and getting +# content merge handled. + +test_expect_success 'setup criss-cross + rename/rename/add + modify/modify' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "lots\nof\nwords\nand\ncontent\n" >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + git commit -m B && + + git checkout -b C A && + git mv a c && + printf "2\n3\n4\n5\n6\n7\n" >a && + git add a && + git commit -m C && + + git checkout B^0 && + git merge --no-commit -s ours C^0 && + git checkout C -- a c && + mv a old_a && + echo 1 >a && + cat old_a >>a && + rm old_a && + git add -u && + git commit -m "Merge commit C^0 into HEAD" && + git tag D && + + git checkout C^0 && + git merge --no-commit -s ours B^0 && + git checkout B -- b && + echo 8 >>a && + git add -u && + git commit -m "Merge commit B^0 into HEAD" && + git tag E +' + +test_expect_failure 'detect rename/rename/add-source for virtual merge-base' ' + git checkout D^0 && + + git merge -s recursive E^0 && + + test 3 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse HEAD:b) = $(git rev-parse A:a) && + test $(git rev-parse HEAD:c) = $(git rev-parse A:a) && + test "$(cat a)" = "$(printf "1\n2\n3\n4\n5\n6\n7\n8\n")" +' + +# +# criss-cross with rename/rename(1to2)/add-dest + simple modify: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: new file: a +# Commit B: rename a->b, add c +# Commit C: rename a->c +# Commit D: merge B&C, keeping A:a and B:c +# Commit E: merge B&C, keeping A:a and slightly modified c from B +# +# Merging commits D & E should result in no conflict. The virtual merge +# base of B & C needs to not delete B:c for that to work, though... + +test_expect_success 'setup criss-cross+rename/rename/add-dest + simple modify' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + printf "1\n2\n3\n4\n5\n6\n7\n" >c && + git add c && + git commit -m B && + + git checkout -b C A && + git mv a c && + git commit -m C && + + git checkout B^0 && + git merge --no-commit -s ours C^0 && + git mv b a && + git commit -m "D is like B but renames b back to a" && + git tag D && + + git checkout B^0 && + git merge --no-commit -s ours C^0 && + git mv b a && + echo 8 >>c && + git add c && + git commit -m "E like D but has mod in c" && + git tag E +' + +test_expect_success 'virtual merge base handles rename/rename(1to2)/add-dest' ' + git checkout D^0 && + + git merge -s recursive E^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse HEAD:a) = $(git rev-parse A:a) && + test $(git rev-parse HEAD:c) = $(git rev-parse E:c) +' + test_done diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index 1e0447f615..19272bc551 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -48,7 +48,23 @@ test_expect_success 'branch -v' ' git branch -v ) | sed -n -e "$script" >actual && - test_cmp expect actual + test_i18ncmp expect actual +' + +cat >expect <<\EOF +b1 origin/master: ahead 1, behind 1 +b2 origin/master: ahead 1, behind 1 +b3 origin/master: behind 1 +b4 origin/master: ahead 2 +EOF + +test_expect_success 'branch -vv' ' + ( + cd test && + git branch -vv + ) | + sed -n -e "$script" >actual && + test_i18ncmp expect actual ' test_expect_success 'checkout' ' @@ -74,20 +90,20 @@ test_expect_success 'status' ' grep "have 1 and 1 different" actual ' -test_expect_success 'status when tracking lightweight tags' ' +test_expect_success 'fail to track lightweight tags' ' git checkout master && git tag light && - git branch --track lighttrack light >actual && - grep "set up to track" actual && - git checkout lighttrack + test_must_fail git branch --track lighttrack light >actual && + test_must_fail grep "set up to track" actual && + test_must_fail git checkout lighttrack ' -test_expect_success 'status when tracking annotated tags' ' +test_expect_success 'fail to track annotated tags' ' git checkout master && git tag -m heavy heavy && - git branch --track heavytrack heavy >actual && - grep "set up to track" actual && - git checkout heavytrack + test_must_fail git branch --track heavytrack heavy >actual && + test_must_fail grep "set up to track" actual && + test_must_fail git checkout heavytrack ' test_expect_success 'setup tracking with branch --set-upstream on existing branch' ' @@ -110,4 +126,18 @@ test_expect_success '--set-upstream does not change branch' ' grep -q "^refs/heads/master$" actual && cmp expect2 actual2 ' + +test_expect_success '--set-upstream @{-1}' ' + git checkout from-master && + git checkout from-master2 && + git config branch.from-master2.merge > expect2 && + git branch --set-upstream @{-1} follower && + git config branch.from-master.merge > actual && + git config branch.from-master2.merge > actual2 && + git branch --set-upstream from-master follower && + git config branch.from-master.merge > expect && + test_cmp expect2 actual2 && + test_cmp expect actual +' + test_done diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh new file mode 100755 index 0000000000..32591f9413 --- /dev/null +++ b/t/t6042-merge-rename-corner-cases.sh @@ -0,0 +1,578 @@ +#!/bin/sh + +test_description="recursive merge corner cases w/ renames but not criss-crosses" +# t6036 has corner cases that involve both criss-cross merges and renames + +. ./test-lib.sh + +test_expect_success 'setup rename/delete + untracked file' ' + echo "A pretty inscription" >ring && + git add ring && + test_tick && + git commit -m beginning && + + git branch people && + git checkout -b rename-the-ring && + git mv ring one-ring-to-rule-them-all && + test_tick && + git commit -m fullname && + + git checkout people && + git rm ring && + echo gollum >owner && + git add owner && + test_tick && + git commit -m track-people-instead-of-objects && + echo "Myyy PRECIOUSSS" >ring +' + +test_expect_success "Does git preserve Gollum's precious artifact?" ' + test_must_fail git merge -s recursive rename-the-ring && + + # Make sure git did not delete an untracked file + test -f ring +' + +# Testcase setup for rename/modify/add-source: +# Commit A: new file: a +# Commit B: modify a slightly +# Commit C: rename a->b, add completely different a +# +# We should be able to merge B & C cleanly + +test_expect_success 'setup rename/modify/add-source conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n7\n" >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + echo 8 >>a && + git add a && + git commit -m B && + + git checkout -b C A && + git mv a b && + echo something completely different >a && + git add a && + git commit -m C +' + +test_expect_failure 'rename/modify/add-source conflict resolvable' ' + git checkout B^0 && + + git merge -s recursive C^0 && + + test $(git rev-parse B:a) = $(git rev-parse b) && + test $(git rev-parse C:a) = $(git rev-parse a) +' + +test_expect_success 'setup resolvable conflict missed if rename missed' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n" >a && + echo foo >b && + git add a b && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a c && + echo "Completely different content" >a && + git add a && + git commit -m B && + + git checkout -b C A && + echo 6 >>a && + git add a && + git commit -m C +' + +test_expect_failure 'conflict caused if rename not detected' ' + git checkout -q C^0 && + git merge -s recursive B^0 && + + test 3 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test 6 -eq $(wc -l < c) && + test $(git rev-parse HEAD:a) = $(git rev-parse B:a) && + test $(git rev-parse HEAD:b) = $(git rev-parse A:b) +' + +test_expect_success 'setup conflict resolved wrong if rename missed' ' + git reset --hard && + git clean -f && + + git checkout -b D A && + echo 7 >>a && + git add a && + git mv a c && + echo "Completely different content" >a && + git add a && + git commit -m D && + + git checkout -b E A && + git rm a && + echo "Completely different content" >>a && + git add a && + git commit -m E +' + +test_expect_failure 'missed conflict if rename not detected' ' + git checkout -q E^0 && + test_must_fail git merge -s recursive D^0 +' + +# Tests for undetected rename/add-source causing a file to erroneously be +# deleted (and for mishandled rename/rename(1to1) causing the same issue). +# +# This test uses a rename/rename(1to1)+add-source conflict (1to1 means the +# same file is renamed on both sides to the same thing; it should trigger +# the 1to2 logic, which it would do if the add-source didn't cause issues +# for git's rename detection): +# Commit A: new file: a +# Commit B: rename a->b +# Commit C: rename a->b, add unrelated a + +test_expect_success 'setup undetected rename/add-source causes data loss' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n" >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + git commit -m B && + + git checkout -b C A && + git mv a b && + echo foobar >a && + git add a && + git commit -m C +' + +test_expect_failure 'detect rename/add-source and preserve all data' ' + git checkout B^0 && + + git merge -s recursive C^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test -f a && + test -f b && + + test $(git rev-parse HEAD:b) = $(git rev-parse A:a) && + test $(git rev-parse HEAD:a) = $(git rev-parse C:a) +' + +test_expect_failure 'detect rename/add-source and preserve all data, merge other way' ' + git checkout C^0 && + + git merge -s recursive B^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test -f a && + test -f b && + + test $(git rev-parse HEAD:b) = $(git rev-parse A:a) && + test $(git rev-parse HEAD:a) = $(git rev-parse C:a) +' + +test_expect_success 'setup content merge + rename/directory conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n" >file && + git add file && + test_tick && + git commit -m base && + git tag base && + + git checkout -b right && + echo 7 >>file && + mkdir newfile && + echo junk >newfile/realfile && + git add file newfile/realfile && + test_tick && + git commit -m right && + + git checkout -b left-conflict base && + echo 8 >>file && + git add file && + git mv file newfile && + test_tick && + git commit -m left && + + git checkout -b left-clean base && + echo 0 >newfile && + cat file >>newfile && + git add newfile && + git rm file && + test_tick && + git commit -m left +' + +test_expect_success 'rename/directory conflict + clean content merge' ' + git reset --hard && + git reset --hard && + git clean -fdqx && + + git checkout left-clean^0 && + + test_must_fail git merge -s recursive right^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 1 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && + + echo 0 >expect && + git cat-file -p base:file >>expect && + echo 7 >>expect && + test_cmp expect newfile~HEAD && + + test $(git rev-parse :2:newfile) = $(git hash-object expect) && + + test -f newfile/realfile && + test -f newfile~HEAD +' + +test_expect_success 'rename/directory conflict + content merge conflict' ' + git reset --hard && + git reset --hard && + git clean -fdqx && + + git checkout left-conflict^0 && + + test_must_fail git merge -s recursive right^0 && + + test 4 -eq $(git ls-files -s | wc -l) && + test 3 -eq $(git ls-files -u | wc -l) && + test 1 -eq $(git ls-files -o | wc -l) && + + git cat-file -p left-conflict:newfile >left && + git cat-file -p base:file >base && + git cat-file -p right:file >right && + test_must_fail git merge-file \ + -L "HEAD:newfile" \ + -L "" \ + -L "right^0:file" \ + left base right && + test_cmp left newfile~HEAD && + + test $(git rev-parse :1:newfile) = $(git rev-parse base:file) && + test $(git rev-parse :2:newfile) = $(git rev-parse left-conflict:newfile) && + test $(git rev-parse :3:newfile) = $(git rev-parse right:file) && + + test -f newfile/realfile && + test -f newfile~HEAD +' + +test_expect_success 'setup content merge + rename/directory conflict w/ disappearing dir' ' + git reset --hard && + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + mkdir sub && + printf "1\n2\n3\n4\n5\n6\n" >sub/file && + git add sub/file && + test_tick && + git commit -m base && + git tag base && + + git checkout -b right && + echo 7 >>sub/file && + git add sub/file && + test_tick && + git commit -m right && + + git checkout -b left base && + echo 0 >newfile && + cat sub/file >>newfile && + git rm sub/file && + mv newfile sub && + git add sub && + test_tick && + git commit -m left +' + +test_expect_success 'disappearing dir in rename/directory conflict handled' ' + git reset --hard && + git clean -fdqx && + + git checkout left^0 && + + git merge -s recursive right^0 && + + test 1 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + echo 0 >expect && + git cat-file -p base:sub/file >>expect && + echo 7 >>expect && + test_cmp expect sub && + + test -f sub +' + +# Test for all kinds of things that can go wrong with rename/rename (2to1): +# Commit A: new files: a & b +# Commit B: rename a->c, modify b +# Commit C: rename b->c, modify a +# +# Merging of B & C should NOT be clean. Questions: +# * Both a & b should be removed by the merge; are they? +# * The two c's should contain modifications to a & b; do they? +# * The index should contain two files, both for c; does it? +# * The working copy should have two files, both of form c~<unique>; does it? +# * Nothing else should be present. Is anything? + +test_expect_success 'setup rename/rename (2to1) + modify/modify' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n" >a && + printf "5\n4\n3\n2\n1\n" >b && + git add a b && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a c && + echo 0 >>b && + git add b && + git commit -m B && + + git checkout -b C A && + git mv b c && + echo 6 >>a && + git add a && + git commit -m C +' + +test_expect_success 'handle rename/rename (2to1) conflict correctly' ' + git checkout B^0 && + + test_must_fail git merge -s recursive C^0 >out && + grep "CONFLICT (rename/rename)" out && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + test 2 -eq $(git ls-files -u c | wc -l) && + test 3 -eq $(git ls-files -o | wc -l) && + + test ! -f a && + test ! -f b && + test -f c~HEAD && + test -f c~C^0 && + + test $(git hash-object c~HEAD) = $(git rev-parse C:a) && + test $(git hash-object c~C^0) = $(git rev-parse B:b) +' + +# Testcase setup for simple rename/rename (1to2) conflict: +# Commit A: new file: a +# Commit B: rename a->b +# Commit C: rename a->c +test_expect_success 'setup simple rename/rename (1to2) conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + echo stuff >a && + git add a && + test_tick && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + test_tick && + git commit -m B && + + git checkout -b C A && + git mv a c && + test_tick && + git commit -m C +' + +test_expect_success 'merge has correct working tree contents' ' + git checkout C^0 && + + test_must_fail git merge -s recursive B^0 && + + test 3 -eq $(git ls-files -s | wc -l) && + test 3 -eq $(git ls-files -u | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :1:a) = $(git rev-parse A:a) && + test $(git rev-parse :3:b) = $(git rev-parse A:a) && + test $(git rev-parse :2:c) = $(git rev-parse A:a) && + + test ! -f a && + test $(git hash-object b) = $(git rev-parse A:a) && + test $(git hash-object c) = $(git rev-parse A:a) +' + +# Testcase setup for rename/rename(1to2)/add-source conflict: +# Commit A: new file: a +# Commit B: rename a->b +# Commit C: rename a->c, add completely different a +# +# Merging of B & C should NOT be clean; there's a rename/rename conflict + +test_expect_success 'setup rename/rename(1to2)/add-source conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + printf "1\n2\n3\n4\n5\n6\n7\n" >a && + git add a && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a b && + git commit -m B && + + git checkout -b C A && + git mv a c && + echo something completely different >a && + git add a && + git commit -m C +' + +test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' ' + git checkout B^0 && + + test_must_fail git merge -s recursive C^0 && + + test 4 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse 3:a) = $(git rev-parse C:a) && + test $(git rev-parse 1:a) = $(git rev-parse A:a) && + test $(git rev-parse 2:b) = $(git rev-parse B:b) && + test $(git rev-parse 3:c) = $(git rev-parse C:c) && + + test -f a && + test -f b && + test -f c +' + +test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + >a && + git add a && + test_tick && + git commit -m base && + git tag A && + + git checkout -b B A && + git mv a b && + test_tick && + git commit -m one && + + git checkout -b C A && + git mv a b && + echo important-info >a && + git add a && + test_tick && + git commit -m two +' + +test_expect_failure 'rename/rename/add-source still tracks new a file' ' + git checkout C^0 && + git merge -s recursive B^0 && + + test 2 -eq $(git ls-files -s | wc -l) && + test 0 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse HEAD:a) = $(git rev-parse C:a) && + test $(git rev-parse HEAD:b) = $(git rev-parse A:a) +' + +test_expect_success 'setup rename/rename(1to2)/add-dest conflict' ' + git rm -rf . && + git clean -fdqx && + rm -rf .git && + git init && + + echo stuff >a && + git add a && + test_tick && + git commit -m base && + git tag A && + + git checkout -b B A && + git mv a b && + echo precious-data >c && + git add c && + test_tick && + git commit -m one && + + git checkout -b C A && + git mv a c && + echo important-info >b && + git add b && + test_tick && + git commit -m two +' + +test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' ' + git checkout C^0 && + test_must_fail git merge -s recursive B^0 && + + test 5 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u b | wc -l) && + test 2 -eq $(git ls-files -u c | wc -l) && + test 4 -eq $(git ls-files -o | wc -l) && + + test $(git rev-parse :1:a) = $(git rev-parse A:a) && + test $(git rev-parse :2:b) = $(git rev-parse C:b) && + test $(git rev-parse :3:b) = $(git rev-parse B:b) && + test $(git rev-parse :2:c) = $(git rev-parse C:c) && + test $(git rev-parse :3:c) = $(git rev-parse B:c) && + + test $(git hash-object c~HEAD) = $(git rev-parse C:c) && + test $(git hash-object c~B\^0) = $(git rev-parse B:c) && + test $(git hash-object b~HEAD) = $(git rev-parse C:b) && + test $(git hash-object b~B\^0) = $(git rev-parse B:b) && + + test ! -f b && + test ! -f c +' + +test_done diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index ae2194e07d..5c87f28e4e 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -236,6 +236,20 @@ test_expect_success 'index-pack and replacements' ' git index-pack test-*.pack ' -# -# +test_expect_success 'not just commits' ' + echo replaced >file && + git add file && + REPLACED=$(git rev-parse :file) && + mv file file.replaced && + + echo original >file && + git add file && + ORIGINAL=$(git rev-parse :file) && + git update-ref refs/replace/$ORIGINAL $REPLACED && + mv file file.original && + + git checkout file && + test_cmp file.replaced file +' + test_done diff --git a/t/t6060-merge-index.sh b/t/t6060-merge-index.sh new file mode 100755 index 0000000000..debadbd299 --- /dev/null +++ b/t/t6060-merge-index.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +test_description='basic git merge-index / git-merge-one-file tests' +. ./test-lib.sh + +test_expect_success 'setup diverging branches' ' + for i in 1 2 3 4 5 6 7 8 9 10; do + echo $i + done >file && + git add file && + git commit -m base && + git tag base && + sed s/2/two/ <file >tmp && + mv tmp file && + git commit -a -m two && + git tag two && + git checkout -b other HEAD^ && + sed s/10/ten/ <file >tmp && + mv tmp file && + git commit -a -m ten && + git tag ten +' + +cat >expect-merged <<'EOF' +1 +two +3 +4 +5 +6 +7 +8 +9 +ten +EOF + +test_expect_success 'read-tree does not resolve content merge' ' + git read-tree -i -m base ten two && + echo file >expect && + git diff-files --name-only --diff-filter=U >unmerged && + test_cmp expect unmerged +' + +test_expect_success 'git merge-index git-merge-one-file resolves' ' + git merge-index git-merge-one-file -a && + git diff-files --name-only --diff-filter=U >unmerged && + >expect && + test_cmp expect unmerged && + test_cmp expect-merged file && + git cat-file blob :file >file-index && + test_cmp expect-merged file-index +' + +test_expect_success 'setup bare merge' ' + git clone --bare . bare.git && + (cd bare.git && + GIT_INDEX_FILE=$PWD/merge.index && + export GIT_INDEX_FILE && + git read-tree -i -m base ten two + ) +' + +test_expect_success 'merge-one-file fails without a work tree' ' + (cd bare.git && + GIT_INDEX_FILE=$PWD/merge.index && + export GIT_INDEX_FILE && + test_must_fail git merge-index git-merge-one-file -a + ) +' + +test_expect_success 'merge-one-file respects GIT_WORK_TREE' ' + (cd bare.git && + mkdir work && + GIT_WORK_TREE=$PWD/work && + export GIT_WORK_TREE && + GIT_INDEX_FILE=$PWD/merge.index && + export GIT_INDEX_FILE && + git merge-index git-merge-one-file -a && + git cat-file blob :file >work/file-index + ) && + test_cmp expect-merged bare.git/work/file && + test_cmp expect-merged bare.git/work/file-index +' + +test_expect_success 'merge-one-file respects core.worktree' ' + mkdir subdir && + git clone . subdir/child && + (cd subdir && + GIT_DIR=$PWD/child/.git && + export GIT_DIR && + git config core.worktree "$PWD/child" && + git read-tree -i -m base ten two && + git merge-index git-merge-one-file -a && + git cat-file blob :file >file-index + ) && + test_cmp expect-merged subdir/child/file && + test_cmp expect-merged subdir/file-index +' + +test_done diff --git a/t/t6110-rev-list-sparse.sh b/t/t6110-rev-list-sparse.sh new file mode 100755 index 0000000000..656ac7fe9d --- /dev/null +++ b/t/t6110-rev-list-sparse.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='operations that cull histories in unusual ways' +. ./test-lib.sh + +test_expect_success setup ' + test_commit A && + test_commit B && + test_commit C && + git checkout -b side HEAD^ && + test_commit D && + test_commit E && + git merge master +' + +test_expect_success 'rev-list --first-parent --boundary' ' + git rev-list --first-parent --boundary HEAD^.. +' + +test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 876d1ab743..f67aa6ff6a 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -124,7 +124,7 @@ warning: tag 'A' is really 'Q' here EOF check_describe A-* HEAD test_expect_success 'warning was displayed for Q' ' - test_cmp err.expect err.actual + test_i18ncmp err.expect err.actual ' test_expect_success 'rename tag Q back to A' ' mv .git/refs/tags/Q .git/refs/tags/A diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 7dc8a510c7..172178490a 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -6,6 +6,7 @@ test_description='for-each-ref test' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh # Mon Jul 3 15:18:43 2006 +0000 datestamp=1151939923 @@ -37,11 +38,13 @@ test_atom() { case "$1" in head) ref=refs/heads/master ;; tag) ref=refs/tags/testtag ;; + *) ref=$1 ;; esac printf '%s\n' "$3" >expected - test_expect_${4:-success} "basic atom: $1 $2" " + test_expect_${4:-success} $PREREQ "basic atom: $1 $2" " git for-each-ref --format='%($2)' $ref >actual && - test_cmp expected actual + sanitize_pgp <actual >actual.clean && + test_cmp expected actual.clean " } @@ -71,7 +74,10 @@ 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 contents:subject 'Initial' test_atom head body '' +test_atom head contents:body '' +test_atom head contents:signature '' test_atom head contents 'Initial ' @@ -101,7 +107,10 @@ 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 contents:subject 'Tagging at 1151939927' test_atom tag body '' +test_atom tag contents:body '' +test_atom tag contents:signature '' test_atom tag contents 'Tagging at 1151939927 ' @@ -359,4 +368,92 @@ test_expect_success 'an unusual tag with an incomplete line' ' ' +test_expect_success 'create tag with subject and body content' ' + cat >>msg <<-\EOF && + the subject line + + first body line + second body line + EOF + git tag -F msg subject-body +' +test_atom refs/tags/subject-body subject 'the subject line' +test_atom refs/tags/subject-body body 'first body line +second body line +' +test_atom refs/tags/subject-body contents 'the subject line + +first body line +second body line +' + +test_expect_success 'create tag with multiline subject' ' + cat >msg <<-\EOF && + first subject line + second subject line + + first body line + second body line + EOF + git tag -F msg multiline +' +test_atom refs/tags/multiline subject 'first subject line second subject line' +test_atom refs/tags/multiline contents:subject 'first subject line second subject line' +test_atom refs/tags/multiline body 'first body line +second body line +' +test_atom refs/tags/multiline contents:body 'first body line +second body line +' +test_atom refs/tags/multiline contents:signature '' +test_atom refs/tags/multiline contents 'first subject line +second subject line + +first body line +second body line +' + +test_expect_success GPG 'create signed tags' ' + git tag -s -m "" signed-empty && + git tag -s -m "subject line" signed-short && + cat >msg <<-\EOF && + subject line + + body contents + EOF + git tag -s -F msg signed-long +' + +sig='-----BEGIN PGP SIGNATURE----- +-----END PGP SIGNATURE----- +' + +PREREQ=GPG +test_atom refs/tags/signed-empty subject '' +test_atom refs/tags/signed-empty contents:subject '' +test_atom refs/tags/signed-empty body "$sig" +test_atom refs/tags/signed-empty contents:body '' +test_atom refs/tags/signed-empty contents:signature "$sig" +test_atom refs/tags/signed-empty contents "$sig" + +test_atom refs/tags/signed-short subject 'subject line' +test_atom refs/tags/signed-short contents:subject 'subject line' +test_atom refs/tags/signed-short body "$sig" +test_atom refs/tags/signed-short contents:body '' +test_atom refs/tags/signed-short contents:signature "$sig" +test_atom refs/tags/signed-short contents "subject line +$sig" + +test_atom refs/tags/signed-long subject 'subject line' +test_atom refs/tags/signed-long contents:subject 'subject line' +test_atom refs/tags/signed-long body "body contents +$sig" +test_atom refs/tags/signed-long contents:body 'body contents +' +test_atom refs/tags/signed-long contents:signature "$sig" +test_atom refs/tags/signed-long contents "subject line + +body contents +$sig" + test_done diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 3e7baaf89f..e93ac73829 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -8,6 +8,7 @@ test_description='git tag Tests for operations with tags.' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh # creating and listing lightweight tags: @@ -257,6 +258,11 @@ test_expect_success \ test_cmp expect actual ' +test_expect_success 'tag -l can accept multiple patterns' ' + git tag -l "v1*" "v0*" >actual && + test_cmp expect actual +' + # creating and verifying lightweight tags: test_expect_success \ @@ -580,24 +586,6 @@ test_expect_success \ test_cmp expect actual ' -# subsequent tests require gpg; check if it is available -gpg --version >/dev/null 2>/dev/null -if [ $? -eq 127 ]; then - say "# gpg not found - skipping tag signing and verification tests" -else - # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 - # the gpg version 1.0.6 didn't parse trust packets correctly, so for - # that version, creation of signed tags using the generated key fails. - case "$(gpg --version)" in - 'gpg (GnuPG) 1.0.6'*) - say "Skipping signed tag tests, because a bug in 1.0.6 version" - ;; - *) - test_set_prereq GPG - ;; - esac -fi - # trying to verify annotated non-signed tags: test_expect_success GPG \ @@ -620,16 +608,6 @@ test_expect_success GPG \ # creating and verifying signed tags: -# key generation info: gpg --homedir t/t7004 --gen-key -# Type DSA and Elgamal, size 2048 bits, no expiration date. -# Name and email: C O Mitter <committer@example.com> -# No password given, to enable non-interactive operation. - -cp -R "$TEST_DIRECTORY"/t7004 ./gpghome -chmod 0700 gpghome -GNUPGHOME="$(pwd)/gpghome" -export GNUPGHOME - get_tag_header signed-tag $commit commit $time >expect echo 'A signed tag message' >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect @@ -1120,12 +1098,11 @@ test_expect_success \ ! (GIT_EDITOR=cat git tag -a initial-comment > actual) ' -test_expect_success \ - 'message in editor has initial comment: first line' ' +test_expect_success 'message in editor has initial comment: first line' ' # check the first line --- should be empty echo >first.expect && sed -e 1q <actual >first.actual && - test_cmp first.expect first.actual + test_i18ncmp first.expect first.actual ' test_expect_success \ diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index ed7575d0fd..320e1d1dbe 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -13,7 +13,7 @@ cleanup_fail() { test_expect_success 'setup' ' sane_unset GIT_PAGER GIT_PAGER_IN_USE && - test_might_fail git config --unset core.pager && + test_unconfig core.pager && PAGER="cat >paginated.out" && export PAGER && @@ -94,21 +94,19 @@ test_expect_success TTY 'no pager with --no-pager' ' test_expect_success TTY 'configuration can disable pager' ' rm -f paginated.out && - test_might_fail git config --unset pager.grep && + test_unconfig 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_config pager.grep false && 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_config pager.config true && test_terminal git config --list && test -e paginated.out ' @@ -116,8 +114,7 @@ test_expect_success TTY 'git config uses a pager if configured to' ' 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" && + test_config pager.bundle true && git bundle create test.bundle --all && rm -f paginated.out subdir/paginated.out && @@ -150,7 +147,7 @@ test_expect_success 'tests can detect color' ' test_expect_success 'no color when stdout is a regular file' ' rm -f colorless.log && - git config color.ui auto || + test_config color.ui auto || cleanup_fail && git log >colorless.log && @@ -159,7 +156,7 @@ test_expect_success 'no color when stdout is a regular file' ' test_expect_success TTY 'color when writing to a pager' ' rm -f paginated.out && - git config color.ui auto || + test_config color.ui auto || cleanup_fail && ( @@ -170,9 +167,21 @@ test_expect_success TTY 'color when writing to a pager' ' colorful paginated.out ' +test_expect_success TTY 'colors are suppressed by color.pager' ' + rm -f paginated.out && + test_config color.ui auto && + test_config color.pager false && + ( + TERM=vt100 && + export TERM && + test_terminal git log + ) && + ! colorful paginated.out +' + test_expect_success 'color when writing to a file intended for a pager' ' rm -f colorful.log && - git config color.ui auto || + test_config color.ui auto || cleanup_fail && ( @@ -184,6 +193,17 @@ test_expect_success 'color when writing to a file intended for a pager' ' colorful colorful.log ' +test_expect_success TTY 'colors are sent to pager for external commands' ' + test_config alias.externallog "!git log" && + test_config color.ui auto && + ( + TERM=vt100 && + export TERM && + test_terminal git -p externallog + ) && + colorful paginated.out +' + # Use this helper to make it easy for the caller of your # terminal-using function to specify whether it should fail. # If you write @@ -221,7 +241,7 @@ test_default_pager() { $test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" " sane_unset PAGER GIT_PAGER && - test_might_fail git config --unset core.pager && + test_unconfig core.pager && rm -f default_pager_used || cleanup_fail && @@ -244,7 +264,7 @@ test_PAGER_overrides() { $test_expectation TTY "$cmd - PAGER overrides default pager" " sane_unset GIT_PAGER && - test_might_fail git config --unset core.pager && + test_unconfig core.pager && rm -f PAGER_used || cleanup_fail && @@ -277,7 +297,7 @@ test_core_pager() { PAGER=wc && export PAGER && - git config core.pager 'wc >core.pager_used' && + test_config core.pager 'wc >core.pager_used' && $full_command && ${if_local_config}test -e core.pager_used " @@ -307,7 +327,7 @@ test_pager_subdir_helper() { PAGER=wc && stampname=\$(pwd)/core.pager_used && export PAGER stampname && - git config core.pager 'wc >\"\$stampname\"' && + test_config core.pager 'wc >\"\$stampname\"' && mkdir sub && ( cd sub && @@ -324,7 +344,7 @@ test_GIT_PAGER_overrides() { rm -f GIT_PAGER_used || cleanup_fail && - git config core.pager wc && + test_config core.pager wc && GIT_PAGER='wc >GIT_PAGER_used' && export GIT_PAGER && $full_command && @@ -402,21 +422,21 @@ test_core_pager_subdir expect_success test_must_fail \ 'git -p apply </dev/null' test_expect_success TTY 'command-specific pager' ' - unset PAGER GIT_PAGER; + sane_unset PAGER GIT_PAGER && echo "foo:initial" >expect && >actual && - git config --unset core.pager && - git config pager.log "sed s/^/foo:/ >actual" && + test_unconfig core.pager && + test_config pager.log "sed s/^/foo:/ >actual" && test_terminal git log --format=%s -1 && test_cmp expect actual ' test_expect_success TTY 'command-specific pager overrides core.pager' ' - unset PAGER GIT_PAGER; + sane_unset PAGER GIT_PAGER && echo "foo:initial" >expect && >actual && - git config core.pager "exit 1" - git config pager.log "sed s/^/foo:/ >actual" && + test_config core.pager "exit 1" + test_config pager.log "sed s/^/foo:/ >actual" && test_terminal git log --format=%s -1 && test_cmp expect actual ' @@ -425,9 +445,45 @@ test_expect_success TTY 'command-specific pager overridden by environment' ' GIT_PAGER="sed s/^/foo:/ >actual" && export GIT_PAGER && >actual && echo "foo:initial" >expect && - git config pager.log "exit 1" && + test_config pager.log "exit 1" && test_terminal git log --format=%s -1 && test_cmp expect actual ' +test_expect_success 'setup external command' ' + cat >git-external <<-\EOF && + #!/bin/sh + git "$@" + EOF + chmod +x git-external +' + +test_expect_success TTY 'command-specific pager works for external commands' ' + sane_unset PAGER GIT_PAGER && + echo "foo:initial" >expect && + >actual && + test_config pager.external "sed s/^/foo:/ >actual" && + test_terminal git --exec-path="`pwd`" external log --format=%s -1 && + test_cmp expect actual +' + +test_expect_success TTY 'sub-commands of externals use their own pager' ' + sane_unset PAGER GIT_PAGER && + echo "foo:initial" >expect && + >actual && + test_config pager.log "sed s/^/foo:/ >actual" && + test_terminal git --exec-path=. external log --format=%s -1 && + test_cmp expect actual +' + +test_expect_success TTY 'external command pagers override sub-commands' ' + sane_unset PAGER GIT_PAGER && + >expect && + >actual && + test_config pager.external false && + test_config pager.log "sed s/^/log:/ >actual" && + test_terminal git --exec-path=. external log --format=%s -1 && + test_cmp expect actual +' + test_done diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh index e058d184d1..917a264eea 100755 --- a/t/t7008-grep-binary.sh +++ b/t/t7008-grep-binary.sh @@ -84,7 +84,7 @@ test_expect_success 'git grep -Fi Y<NUL>f a' " git grep -f f -Fi a " -test_expect_failure 'git grep -Fi Y<NUL>x a' " +test_expect_success 'git grep -Fi Y<NUL>x a' " printf 'YQx' | q_to_nul >f && test_must_fail git grep -f f -Fi a " @@ -94,7 +94,7 @@ test_expect_success 'git grep y<NUL>f a' " git grep -f f a " -test_expect_failure 'git grep y<NUL>x a' " +test_expect_success 'git grep y<NUL>x a' " printf 'yQx' | q_to_nul >f && test_must_fail git grep -f f a " diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh index bb4066f767..8f3b54d826 100755 --- a/t/t7011-skip-worktree-reading.sh +++ b/t/t7011-skip-worktree-reading.sh @@ -24,7 +24,7 @@ H sub/2 EOF NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -ZERO_SHA0=0000000000000000000000000000000000000000 + setup_absent() { test -f 1 && rm 1 git update-index --remove 1 && @@ -120,7 +120,7 @@ test_expect_success 'grep with skip-worktree file' ' test "$(git grep --no-ext-grep test)" = "1:test" ' -echo ":000000 100644 $ZERO_SHA0 $NULL_SHA1 A 1" > expected +echo ":000000 100644 $_z40 $NULL_SHA1 A 1" > expected test_expect_success 'diff-index does not examine skip-worktree absent entries' ' setup_absent && git diff-index HEAD -- 1 > result && diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh index 582d0b54f1..9ceaa4049f 100755 --- a/t/t7012-skip-worktree-writing.sh +++ b/t/t7012-skip-worktree-writing.sh @@ -54,7 +54,7 @@ test_expect_success 'read-tree removes worktree, dirty case' ' ' NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -ZERO_SHA0=0000000000000000000000000000000000000000 + setup_absent() { test -f 1 && rm 1 git update-index --remove 1 && @@ -127,13 +127,13 @@ EOF test_expect_success 'git-clean, absent case' ' setup_absent && git clean -n > result && - test_cmp expected result + test_i18ncmp expected result ' test_expect_success 'git-clean, dirty case' ' setup_dirty && git clean -n > result && - test_cmp expected result + test_i18ncmp expected result ' #TODO test_expect_failure 'git-apply adds file' false diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index fcac472598..b8cb4906aa 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -50,10 +50,72 @@ test_expect_success 'M/D conflict does not segfault' ' git commit -m delete && test_must_fail git merge master && test_must_fail git commit --dry-run >../actual && - test_cmp ../expect ../actual && + test_i18ncmp ../expect ../actual && git status >../actual && - test_cmp ../expect ../actual + test_i18ncmp ../expect ../actual ) ' +test_expect_success 'rename & unmerged setup' ' + git rm -f -r . && + cat "$TEST_DIRECTORY/README" >ONE && + git add ONE && + test_tick && + git commit -m "One commit with ONE" && + + echo Modified >TWO && + cat ONE >>TWO && + cat ONE >>THREE && + git add TWO THREE && + sha1=$(git rev-parse :ONE) && + git rm --cached ONE && + ( + echo "100644 $sha1 1 ONE" && + echo "100644 $sha1 2 ONE" && + echo "100644 $sha1 3 ONE" + ) | git update-index --index-info && + echo Further >>THREE +' + +test_expect_success 'rename & unmerged status' ' + git status -suno >actual && + cat >expect <<-EOF && + UU ONE + AM THREE + A TWO + EOF + test_cmp expect actual +' + +test_expect_success 'git diff-index --cached shows 2 added + 1 unmerged' ' + cat >expected <<-EOF && + U ONE + A THREE + A TWO + EOF + git diff-index --cached --name-status HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'git diff-index --cached -M shows 2 added + 1 unmerged' ' + cat >expected <<-EOF && + U ONE + A THREE + A TWO + EOF + git diff-index --cached --name-status HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' ' + cat >expected <<-EOF && + U ONE + C ONE THREE + C ONE TWO + EOF + git diff-index --cached -C --name-status HEAD | + sed "s/^C[0-9]*/C/g" >actual && + test_cmp expected actual +' + test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index b8cf2603a1..b096dc88c2 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -426,7 +426,22 @@ EOF test_expect_success '--mixed refreshes the index' ' echo 123 >> file2 && git reset --mixed HEAD > output && - test_cmp expect output + test_i18ncmp expect output +' + +test_expect_success 'resetting specific path that is unmerged' ' + git rm --cached file2 && + F1=$(git rev-parse HEAD:file1) && + F2=$(git rev-parse HEAD:file2) && + F3=$(git rev-parse HEAD:secondfile) && + { + echo "100644 $F1 1 file2" && + echo "100644 $F2 2 file2" && + echo "100644 $F3 3 file2" + } | git update-index --index-info && + git ls-files -u && + test_must_fail git reset HEAD file2 && + git diff-index --exit-code --cached HEAD ' test_expect_success 'disambiguation (1)' ' diff --git a/t/t7106-reset-sequence.sh b/t/t7106-reset-sequence.sh new file mode 100755 index 0000000000..4956caaf82 --- /dev/null +++ b/t/t7106-reset-sequence.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='Test interaction of reset --hard with sequencer + + + anotherpick: rewrites foo to d + + picked: rewrites foo to c + + unrelatedpick: rewrites unrelated to reallyunrelated + + base: rewrites foo to b + + initial: writes foo as a, unrelated as unrelated +' + +. ./test-lib.sh + +pristine_detach () { + git cherry-pick --reset && + git checkout -f "$1^0" && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x +} + +test_expect_success setup ' + echo unrelated >unrelated && + git add unrelated && + test_commit initial foo a && + test_commit base foo b && + test_commit unrelatedpick unrelated reallyunrelated && + test_commit picked foo c && + test_commit anotherpick foo d && + git config advice.detachedhead false + +' + +test_expect_success 'reset --hard cleans up sequencer state, providing one-level undo' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + test_path_is_dir .git/sequencer && + git reset --hard && + test_path_is_missing .git/sequencer && + test_path_is_dir .git/sequencer-old && + git reset --hard && + test_path_is_missing .git/sequencer-old +' + +test_done diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh index 70cdd8e618..a82a07a04a 100755 --- a/t/t7110-reset-merge.sh +++ b/t/t7110-reset-merge.sh @@ -237,7 +237,7 @@ test_expect_success '"reset --keep HEAD^" fails with pending merge' ' git reset --hard third && test_must_fail git merge branch1 && test_must_fail git reset --keep HEAD^ 2>err.log && - grep "middle of a merge" err.log + test_i18ngrep "middle of a merge" err.log ' # The next test will test the following: @@ -263,7 +263,7 @@ test_expect_success '"reset --keep HEAD" fails with pending merge' ' git reset --hard third && test_must_fail git merge branch1 && test_must_fail git reset --keep HEAD 2>err.log && - grep "middle of a merge" err.log + test_i18ngrep "middle of a merge" err.log ' test_expect_success '--merge is ok with added/deleted merge' ' @@ -289,7 +289,7 @@ test_expect_success '--keep fails with added/deleted merge' ' git diff --exit-code file3 && git diff --exit-code branch3 file3 && test_must_fail git reset --keep HEAD 2>err.log && - grep "middle of a merge" err.log + test_i18ngrep "middle of a merge" err.log ' test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 1337fa5a22..07fb53adcb 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -228,7 +228,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' ' git config advice.detachedHead false && git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && - grep "HEAD is now at 7329388" messages && + test_i18ngrep "HEAD is now at 7329388" messages && test 1 -eq $(wc -l <messages) && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && @@ -246,7 +246,7 @@ test_expect_success 'checkout to detach HEAD' ' git config advice.detachedHead true && git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && - grep "HEAD is now at 7329388" messages && + test_i18ngrep "HEAD is now at 7329388" messages && test 1 -lt $(wc -l <messages) && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && @@ -408,6 +408,15 @@ test_expect_success 'checkout w/--track from non-branch HEAD fails' ' test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)" ' +test_expect_success 'checkout w/--track from tag fails' ' + git checkout master^0 && + test_must_fail git symbolic-ref HEAD && + test_must_fail git checkout --track -b track frotz && + test_must_fail git rev-parse --verify track && + test_must_fail git symbolic-ref HEAD && + test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)" +' + test_expect_success 'detach a symbolic link HEAD' ' git checkout master && git config --bool core.prefersymlinkrefs yes && @@ -423,7 +432,6 @@ test_expect_success 'detach a symbolic link HEAD' ' test_expect_success \ 'checkout with --track fakes a sensible -b <name>' ' git update-ref refs/remotes/origin/koala/bear renamer && - git update-ref refs/new/koala/bear renamer && git checkout --track origin/koala/bear && test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && @@ -439,12 +447,6 @@ test_expect_success \ git checkout --track remotes/origin/koala/bear && test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && - test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && - - git checkout master && git branch -D koala/bear && - - git checkout --track refs/new/koala/bear && - test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" ' diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 02f67b73b7..800b5368a5 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -110,7 +110,7 @@ test_expect_success 'git clean with prefix' ' ' -test_expect_success 'git clean with relative prefix' ' +test_expect_success C_LOCALE_OUTPUT 'git clean with relative prefix' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && @@ -125,7 +125,7 @@ test_expect_success 'git clean with relative prefix' ' } ' -test_expect_success 'git clean with absolute path' ' +test_expect_success C_LOCALE_OUTPUT 'git clean with absolute path' ' mkdir -p build docs && touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && @@ -377,7 +377,7 @@ test_expect_success 'clean.requireForce and -f' ' ' -test_expect_success 'core.excludesfile' ' +test_expect_success C_LOCALE_OUTPUT 'core.excludesfile' ' echo excludes >excludes && echo included >included && @@ -453,4 +453,11 @@ test_expect_success 'git clean -e' ' ) ' +test_expect_success SANITY 'git clean -d with an unreadable empty directory' ' + mkdir foo && + chmod a= foo && + git clean -dfx foo && + ! test -d foo +' + test_done diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 874279e32d..695f7afdf3 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -47,8 +47,10 @@ test_expect_success 'setup - repository to add submodules to' ' ' # The 'submodule add' tests need some repository to add as a submodule. -# The trash directory is a good one as any. -submodurl=$TRASH_DIRECTORY +# The trash directory is a good one as any. We need to canonicalize +# the name, though, as some tests compare it to the absolute path git +# generates, which will expand symbolic links. +submodurl=$(pwd -P) listbranches() { git for-each-ref --format='%(refname)' 'refs/heads/*' @@ -75,7 +77,8 @@ test_expect_success 'submodule add' ' ( cd addtest && - git submodule add "$submodurl" submod && + git submodule add -q "$submodurl" submod >actual && + test ! -s actual && git submodule init ) && @@ -99,7 +102,7 @@ test_expect_success 'submodule add to .gitignored path fails' ' git add --force .gitignore && git commit -m"Ignore everything" && ! git submodule add "$submodurl" submod >actual 2>&1 && - test_cmp expect actual + test_i18ncmp expect actual ) ' @@ -273,7 +276,8 @@ test_expect_success 'update should work when path is an empty dir' ' echo "$rev1" >expect && mkdir init && - git submodule update && + git submodule update -q >update.out && + test ! -s update.out && inspect init && test_cmp expect head-sha1 @@ -357,11 +361,11 @@ test_expect_success 'update --init' ' git submodule update init > update.out && cat update.out && - grep "not initialized" update.out && - ! test -d init/.git && + test_i18ngrep "not initialized" update.out && + test_must_fail git rev-parse --resolve-git-dir init/.git && git submodule update --init init && - test -d init/.git + git rev-parse --resolve-git-dir init/.git ' test_expect_success 'do not add files from a submodule' ' @@ -446,6 +450,16 @@ test_expect_success 'add should fail when path is used by an existing directory' ) ' +test_expect_success 'use superproject as upstream when path is relative and no url is set there' ' + ( + cd addtest && + git submodule add ../repo relative && + test "$(git config -f .gitmodules submodule.relative.url)" = ../repo && + git submodule sync relative && + test "$(git config submodule.relative.url)" = "$submodurl/repo" + ) +' + test_expect_success 'set up for relative path tests' ' mkdir reltest && ( diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index 7d7fde057b..30b429e7dc 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -128,7 +128,7 @@ test_expect_success 'typechanged submodule(submodule->blob), --cached' " < Add foo5 EOF - test_cmp actual expected + test_i18ncmp actual expected " test_expect_success 'typechanged submodule(submodule->blob), --files' " @@ -138,7 +138,7 @@ test_expect_success 'typechanged submodule(submodule->blob), --files' " > Add foo5 EOF - test_cmp actual expected + test_i18ncmp actual expected " rm -rf sm1 && @@ -149,7 +149,7 @@ test_expect_success 'typechanged submodule(submodule->blob)' " * sm1 $head4(submodule)->$head5(blob): EOF - test_cmp actual expected + test_i18ncmp actual expected " rm -f sm1 && @@ -162,7 +162,7 @@ test_expect_success 'nonexistent commit' " Warn: sm1 doesn't contain commit $head4_full EOF - test_cmp actual expected + test_i18ncmp actual expected " commit_file @@ -173,7 +173,7 @@ test_expect_success 'typechanged submodule(blob->submodule)' " > Add foo7 EOF - test_cmp expected actual + test_i18ncmp expected actual " commit_file sm1 && @@ -228,7 +228,7 @@ EOF test_expect_success '--for-status' " git submodule summary --for-status HEAD^ >actual && - test_cmp actual - <<EOF + test_i18ncmp actual - <<EOF # Submodule changes to be committed: # # * sm1 $head6...0000000: diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index e5b19538b0..3620215c1f 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -25,7 +25,8 @@ test_expect_success setup ' git clone super super-clone && (cd super-clone && git submodule update --init) && git clone super empty-clone && - (cd empty-clone && git submodule init) + (cd empty-clone && git submodule init) && + git clone super top-only-clone ' test_expect_success 'change submodule' ' @@ -52,11 +53,12 @@ test_expect_success 'change submodule url' ' test_expect_success '"git submodule sync" should update submodule URLs' ' (cd super-clone && - git pull && + git pull --no-recurse-submodules && git submodule sync ) && - test -d "$(git config -f super-clone/submodule/.git/config \ - remote.origin.url)" && + test -d "$(cd super-clone/submodule && + git config remote.origin.url + )" && (cd super-clone/submodule && git checkout master && git pull @@ -66,7 +68,7 @@ test_expect_success '"git submodule sync" should update submodule URLs' ' ) ' -test_expect_success '"git submodule sync" should update submodule URLs if not yet cloned' ' +test_expect_success '"git submodule sync" should update known submodule URLs' ' (cd empty-clone && git pull && git submodule sync && @@ -74,4 +76,14 @@ test_expect_success '"git submodule sync" should update submodule URLs if not ye ) ' +test_expect_success '"git submodule sync" should not vivify uninteresting submodule' ' + (cd top-only-clone && + git pull && + git submodule sync && + test -z "$(git config submodule.submodule.url)" && + git submodule sync submodule && + test -z "$(git config submodule.submodule.url)" + ) +' + test_done diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh index 7e2e258950..0d5b42a25b 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -56,11 +56,11 @@ test_expect_success setup ' # History setup # -# b -# / \ -# a d -# \ / -# c +# b +# / \ +# init -- a d +# \ \ / +# g 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 @@ -76,6 +76,8 @@ test_expect_success 'setup for merge search' ' git add file-a && git commit -m "sub-a" && git branch sub-a) && + git commit --allow-empty -m init && + git branch init && git add sub && git commit -m "a" && git branch a && @@ -101,7 +103,13 @@ test_expect_success 'setup for merge search' ' git checkout -b sub-d sub-b && git merge sub-c) && git commit -a -m "d" && - git branch test b) + git branch test b && + + git checkout -b g init && + (cd sub && + git checkout -b sub-g sub-c) && + git add sub && + git commit -a -m "g") ' test_expect_success 'merge with one side as a fast-forward of the other' ' @@ -176,10 +184,99 @@ test_expect_success 'merging should fail for changes that are backwards' ' test_must_fail git merge f) ' + +# Check that the conflicting submodule is detected when it is +# in the common ancestor. status should be 'U00...00" +test_expect_success 'git submodule status should display the merge conflict properly with merge base' ' + (cd merge-search && + cat >.gitmodules <<EOF && +[submodule "sub"] + path = sub + url = $TRASH_DIRECTORY/sub +EOF + cat >expect <<EOF && +U0000000000000000000000000000000000000000 sub +EOF + git submodule status > actual && + test_cmp expect actual && + git reset --hard) +' + +# Check that the conflicting submodule is detected when it is +# not in the common ancestor. status should be 'U00...00" +test_expect_success 'git submodule status should display the merge conflict properly without merge-base' ' + (cd merge-search && + git checkout -b test-no-merge-base g && + test_must_fail git merge b && + cat >.gitmodules <<EOF && +[submodule "sub"] + path = sub + url = $TRASH_DIRECTORY/sub +EOF + cat >expect <<EOF && +U0000000000000000000000000000000000000000 sub +EOF + git submodule status > actual && + test_cmp expect actual && + git reset --hard) +' + + test_expect_success 'merging with a modify/modify conflict between merge bases' ' git reset --hard HEAD && git checkout -b test2 c && git merge d ' +# canonical criss-cross history in top and submodule +test_expect_success 'setup for recursive merge with submodule' ' + mkdir merge-recursive && + (cd merge-recursive && + git init && + mkdir sub && + (cd sub && + git init && + test_commit a && + git checkout -b sub-b master && + test_commit b && + git checkout -b sub-c master && + test_commit c && + git checkout -b sub-bc sub-b && + git merge sub-c && + git checkout -b sub-cb sub-c && + git merge sub-b && + git checkout master) && + git add sub && + git commit -m a && + git checkout -b top-b master && + (cd sub && git checkout sub-b) && + git add sub && + git commit -m b && + git checkout -b top-c master && + (cd sub && git checkout sub-c) && + git add sub && + git commit -m c && + git checkout -b top-bc top-b && + git merge -s ours --no-commit top-c && + (cd sub && git checkout sub-bc) && + git add sub && + git commit -m bc && + git checkout -b top-cb top-c && + git merge -s ours --no-commit top-b && + (cd sub && git checkout sub-cb) && + git add sub && + git commit -m cb) +' + +# merge should leave submodule unmerged in index +test_expect_success 'recursive merge with submodule' ' + (cd merge-recursive && + test_must_fail git merge top-bc && + echo "160000 $(git rev-parse top-cb:sub) 2 sub" > expect2 && + echo "160000 $(git rev-parse top-bc:sub) 3 sub" > expect3 && + git ls-files -u > actual && + grep "$(cat expect2)" actual > /dev/null && + grep "$(cat expect3)" actual > /dev/null) +' + test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index bfb4975e94..33b292b8a8 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -30,6 +30,7 @@ test_expect_success 'setup a submodule tree' ' git clone super submodule && git clone super rebasing && git clone super merging && + git clone super none && (cd super && git submodule add ../submodule submodule && test_tick && @@ -58,6 +59,11 @@ test_expect_success 'setup a submodule tree' ' test_tick && git commit -m "rebasing" ) + (cd super && + git submodule add ../none none && + test_tick && + git commit -m "none" + ) ' test_expect_success 'submodule update detaching the HEAD ' ' @@ -74,6 +80,49 @@ test_expect_success 'submodule update detaching the HEAD ' ' ) ' +apos="'"; +test_expect_success 'submodule update does not fetch already present commits' ' + (cd submodule && + echo line3 >> file && + git add file && + test_tick && + git commit -m "upstream line3" + ) && + (cd super/submodule && + head=$(git rev-parse --verify HEAD) && + echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected && + git reset --hard HEAD~1 + ) && + (cd super && + git submodule update > ../actual 2> ../actual.err + ) && + test_i18ncmp expected actual && + ! test -s actual.err +' + +test_expect_success 'submodule update should fail due to local changes' ' + (cd super/submodule && + git reset --hard HEAD~1 && + echo "local change" > file + ) && + (cd super && + (cd submodule && + compare_head + ) && + test_must_fail git submodule update submodule + ) +' +test_expect_success 'submodule update should throw away changes with --force ' ' + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --force submodule && + cd submodule && + ! compare_head + ) +' + test_expect_success 'submodule update --rebase staying on master' ' (cd super/submodule && git checkout master @@ -203,4 +252,363 @@ test_expect_success 'submodule init picks up merge' ' ) ' +test_expect_success 'submodule update --merge - ignores --merge for new submodules' ' + (cd super && + rm -rf submodule && + git submodule update submodule && + git status -s submodule >expect && + rm -rf submodule && + git submodule update --merge submodule && + git status -s submodule >actual && + test_cmp expect actual + ) +' + +test_expect_success 'submodule update --rebase - ignores --rebase for new submodules' ' + (cd super && + rm -rf submodule && + git submodule update submodule && + git status -s submodule >expect && + rm -rf submodule && + git submodule update --rebase submodule && + git status -s submodule >actual && + test_cmp expect actual + ) +' + +test_expect_success 'submodule update ignores update=merge config for new submodules' ' + (cd super && + rm -rf submodule && + git submodule update submodule && + git status -s submodule >expect && + rm -rf submodule && + git config submodule.submodule.update merge && + git submodule update submodule && + git status -s submodule >actual && + git config --unset submodule.submodule.update && + test_cmp expect actual + ) +' + +test_expect_success 'submodule update ignores update=rebase config for new submodules' ' + (cd super && + rm -rf submodule && + git submodule update submodule && + git status -s submodule >expect && + rm -rf submodule && + git config submodule.submodule.update rebase && + git submodule update submodule && + git status -s submodule >actual && + git config --unset submodule.submodule.update && + test_cmp expect actual + ) +' + +test_expect_success 'submodule init picks up update=none' ' + (cd super && + git config -f .gitmodules submodule.none.update none && + git submodule init none && + test "none" = "$(git config submodule.none.update)" + ) +' + +test_expect_success 'submodule update - update=none in .git/config' ' + (cd super && + git config submodule.submodule.update none && + (cd submodule && + git checkout master && + compare_head + ) && + git diff --raw | grep " submodule" && + git submodule update && + git diff --raw | grep " submodule" && + (cd submodule && + compare_head + ) && + git config --unset submodule.submodule.update && + git submodule update submodule + ) +' + +test_expect_success 'submodule update - update=none in .git/config but --checkout given' ' + (cd super && + git config submodule.submodule.update none && + (cd submodule && + git checkout master && + compare_head + ) && + git diff --raw | grep " submodule" && + git submodule update --checkout && + test_must_fail git diff --raw \| grep " submodule" && + (cd submodule && + test_must_fail compare_head + ) && + git config --unset submodule.submodule.update + ) +' + +test_expect_success 'submodule update --init skips submodule with update=none' ' + (cd super && + git add .gitmodules && + git commit -m ".gitmodules" + ) && + git clone super cloned && + (cd cloned && + git submodule update --init && + test -e submodule/.git && + test_must_fail test -e none/.git + ) +' + +test_expect_success 'submodule update continues after checkout error' ' + (cd super && + git reset --hard HEAD && + git submodule add ../submodule submodule2 && + git submodule init && + git commit -am "new_submodule" && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../expect + ) && + (cd submodule && + test_commit "update_submodule" file + ) && + (cd submodule2 && + test_commit "update_submodule2" file + ) && + git add submodule && + git add submodule2 && + git commit -m "two_new_submodule_commits" && + (cd submodule && + echo "" > file + ) && + git checkout HEAD^ && + test_must_fail git submodule update && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../actual + ) && + test_cmp expect actual + ) +' +test_expect_success 'submodule update continues after recursive checkout error' ' + (cd super && + git reset --hard HEAD && + git checkout master && + git submodule update && + (cd submodule && + git submodule add ../submodule subsubmodule && + git submodule init && + git commit -m "new_subsubmodule" + ) && + git add submodule && + git commit -m "update_submodule" && + (cd submodule && + (cd subsubmodule && + test_commit "update_subsubmodule" file + ) && + git add subsubmodule && + test_commit "update_submodule_again" file && + (cd subsubmodule && + test_commit "update_subsubmodule_again" file + ) && + test_commit "update_submodule_again_again" file + ) && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../expect && + test_commit "update_submodule2_again" file + ) && + git add submodule && + git add submodule2 && + git commit -m "new_commits" && + git checkout HEAD^ && + (cd submodule && + git checkout HEAD^ && + (cd subsubmodule && + echo "" > file + ) + ) && + test_must_fail git submodule update --recursive && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../actual + ) && + test_cmp expect actual + ) +' + +test_expect_success 'submodule update exit immediately in case of merge conflict' ' + (cd super && + git checkout master && + git reset --hard HEAD && + (cd submodule && + (cd subsubmodule && + git reset --hard HEAD + ) + ) && + git submodule update --recursive && + (cd submodule && + test_commit "update_submodule_2" file + ) && + (cd submodule2 && + test_commit "update_submodule2_2" file + ) && + git add submodule && + git add submodule2 && + git commit -m "two_new_submodule_commits" && + (cd submodule && + git checkout master && + test_commit "conflict" file && + echo "conflict" > file + ) && + git checkout HEAD^ && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../expect + ) && + git config submodule.submodule.update merge && + test_must_fail git submodule update && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../actual + ) && + test_cmp expect actual + ) +' + +test_expect_success 'submodule update exit immediately after recursive rebase error' ' + (cd super && + git checkout master && + git reset --hard HEAD && + (cd submodule && + git reset --hard HEAD && + git submodule update --recursive + ) && + (cd submodule && + test_commit "update_submodule_3" file + ) && + (cd submodule2 && + test_commit "update_submodule2_3" file + ) && + git add submodule && + git add submodule2 && + git commit -m "two_new_submodule_commits" && + (cd submodule && + git checkout master && + test_commit "conflict2" file && + echo "conflict" > file + ) && + git checkout HEAD^ && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../expect + ) && + git config submodule.submodule.update rebase && + test_must_fail git submodule update && + (cd submodule2 && + git rev-parse --max-count=1 HEAD > ../actual + ) && + test_cmp expect actual + ) +' + +test_expect_success 'add different submodules to the same path' ' + (cd super && + git submodule add ../submodule s1 && + test_must_fail git submodule add ../merging s1 + ) +' + +test_expect_success 'submodule add places git-dir in superprojects git-dir' ' + (cd super && + mkdir deeper && + git submodule add ../submodule deeper/submodule && + (cd deeper/submodule && + git log > ../../expected + ) && + (cd .git/modules/deeper/submodule && + git log > ../../../../actual + ) && + test_cmp actual expected + ) +' + +test_expect_success 'submodule update places git-dir in superprojects git-dir' ' + (cd super && + git commit -m "added submodule" + ) && + git clone super super2 && + (cd super2 && + git submodule init deeper/submodule && + git submodule update && + (cd deeper/submodule && + git log > ../../expected + ) && + (cd .git/modules/deeper/submodule && + git log > ../../../../actual + ) && + test_cmp actual expected + ) +' + +test_expect_success 'submodule add places git-dir in superprojects git-dir recursive' ' + (cd super2 && + (cd deeper/submodule && + git submodule add ../submodule subsubmodule && + (cd subsubmodule && + git log > ../../../expected + ) && + git commit -m "added subsubmodule" && + git push + ) && + (cd .git/modules/deeper/submodule/modules/subsubmodule && + git log > ../../../../../actual + ) && + git add deeper/submodule && + git commit -m "update submodule" && + git push && + test_cmp actual expected + ) +' + +test_expect_success 'submodule update places git-dir in superprojects git-dir recursive' ' + mkdir super_update_r && + (cd super_update_r && + git init --bare + ) && + mkdir subsuper_update_r && + (cd subsuper_update_r && + git init --bare + ) && + mkdir subsubsuper_update_r && + (cd subsubsuper_update_r && + git init --bare + ) && + git clone subsubsuper_update_r subsubsuper_update_r2 && + (cd subsubsuper_update_r2 && + test_commit "update_subsubsuper" file && + git push origin master + ) && + git clone subsuper_update_r subsuper_update_r2 && + (cd subsuper_update_r2 && + test_commit "update_subsuper" file && + git submodule add ../subsubsuper_update_r subsubmodule && + git commit -am "subsubmodule" && + git push origin master + ) && + git clone super_update_r super_update_r2 && + (cd super_update_r2 && + test_commit "update_super" file && + git submodule add ../subsuper_update_r submodule && + git commit -am "submodule" && + git push origin master + ) && + rm -rf super_update_r2 && + git clone super_update_r super_update_r2 && + (cd super_update_r2 && + git submodule update --init --recursive && + (cd submodule/subsubmodule && + git log > ../../expected + ) && + (cd .git/modules/submodule/modules/subsubmodule + git log > ../../../../../actual + ) + test_cmp actual expected + ) +' + test_done diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index d8ad25036f..9b69fe2e14 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -77,7 +77,7 @@ test_expect_success 'test basic "submodule foreach" usage' ' git config foo.bar zar && git submodule foreach "git config --file \"\$toplevel/.git/config\" foo.bar" ) && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'setup nested submodules' ' @@ -118,19 +118,19 @@ test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' ' git clone super clone2 && ( cd clone2 && - test ! -d sub1/.git && - test ! -d sub2/.git && - test ! -d sub3/.git && - test ! -d nested1/.git && + test_must_fail git rev-parse --resolve-git-dir sub1/.git && + test_must_fail git rev-parse --resolve-git-dir sub2/.git && + test_must_fail git rev-parse --resolve-git-dir sub3/.git && + test_must_fail git rev-parse --resolve-git-dir nested1/.git && git submodule update --init && - test -d sub1/.git && - test -d sub2/.git && - test -d sub3/.git && - test -d nested1/.git && - test ! -d nested1/nested2/.git && + git rev-parse --resolve-git-dir sub1/.git && + git rev-parse --resolve-git-dir sub2/.git && + git rev-parse --resolve-git-dir sub3/.git && + git rev-parse --resolve-git-dir nested1/.git && + test_must_fail git rev-parse --resolve-git-dir nested1/nested2/.git && git submodule foreach "git submodule update --init" && - test -d nested1/nested2/.git && - test ! -d nested1/nested2/nested3/.git + git rev-parse --resolve-git-dir nested1/nested1/nested2/.git + test_must_fail git rev-parse --resolve-git-dir nested1/nested2/nested3/.git ) ' @@ -138,8 +138,8 @@ test_expect_success 'use "foreach --recursive" to checkout all submodules' ' ( cd clone2 && git submodule foreach --recursive "git submodule update --init" && - test -d nested1/nested2/nested3/.git && - test -d nested1/nested2/nested3/submodule/.git + git rev-parse --resolve-git-dir nested1/nested2/nested3/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git ) ' @@ -158,7 +158,7 @@ test_expect_success 'test messages from "foreach --recursive"' ' cd clone2 && git submodule foreach --recursive "true" > ../actual ) && - test_cmp expect actual + test_i18ncmp expect actual ' cat > expect <<EOF @@ -183,18 +183,18 @@ test_expect_success 'use "update --recursive" to checkout all submodules' ' git clone super clone3 && ( cd clone3 && - test ! -d sub1/.git && - test ! -d sub2/.git && - test ! -d sub3/.git && - test ! -d nested1/.git && + test_must_fail git rev-parse --resolve-git-dir sub1/.git && + test_must_fail git rev-parse --resolve-git-dir sub2/.git && + test_must_fail git rev-parse --resolve-git-dir sub3/.git && + test_must_fail git rev-parse --resolve-git-dir nested1/.git && git submodule update --init --recursive && - test -d sub1/.git && - test -d sub2/.git && - test -d sub3/.git && - test -d nested1/.git && - test -d nested1/nested2/.git && - test -d nested1/nested2/nested3/.git && - test -d nested1/nested2/nested3/submodule/.git + git rev-parse --resolve-git-dir sub1/.git && + git rev-parse --resolve-git-dir sub2/.git && + git rev-parse --resolve-git-dir sub3/.git && + git rev-parse --resolve-git-dir nested1/.git && + git rev-parse --resolve-git-dir nested1/nested2/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git ) ' @@ -238,19 +238,26 @@ test_expect_success 'ensure "status --cached --recursive" preserves the --cached ) && git submodule status --cached --recursive -- nested1 > ../actual ) && + if test_have_prereq MINGW + then + dos2unix actual + fi && test_cmp expect actual ' test_expect_success 'use "git clone --recursive" to checkout all submodules' ' git clone --recursive super clone4 && - test -d clone4/.git && - test -d clone4/sub1/.git && - test -d clone4/sub2/.git && - test -d clone4/sub3/.git && - test -d clone4/nested1/.git && - test -d clone4/nested1/nested2/.git && - test -d clone4/nested1/nested2/nested3/.git && - test -d clone4/nested1/nested2/nested3/submodule/.git + ( + cd clone4 && + git rev-parse --resolve-git-dir .git && + git rev-parse --resolve-git-dir sub1/.git && + git rev-parse --resolve-git-dir sub2/.git && + git rev-parse --resolve-git-dir sub3/.git && + git rev-parse --resolve-git-dir nested1/.git && + git rev-parse --resolve-git-dir nested1/nested2/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git + ) ' test_expect_success 'test "update --recursive" with a flag with spaces' ' @@ -258,14 +265,14 @@ test_expect_success 'test "update --recursive" with a flag with spaces' ' git clone super clone5 && ( cd clone5 && - test ! -d nested1/.git && + test_must_fail git rev-parse --resolve-git-dir d nested1/.git && git submodule update --init --recursive --reference="$(dirname "$PWD")/common objects" && - test -d nested1/.git && - test -d nested1/nested2/.git && - test -d nested1/nested2/nested3/.git && - test -f nested1/.git/objects/info/alternates && - test -f nested1/nested2/.git/objects/info/alternates && - test -f nested1/nested2/nested3/.git/objects/info/alternates + git rev-parse --resolve-git-dir nested1/.git && + git rev-parse --resolve-git-dir nested1/nested2/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/.git && + test -f .git/modules/nested1/objects/info/alternates && + test -f .git/modules/nested1/modules/nested2/objects/info/alternates && + test -f .git/modules/nested1/modules/nested2/modules/nested3/objects/info/alternates ) ' @@ -273,19 +280,37 @@ test_expect_success 'use "update --recursive nested1" to checkout all submodules git clone super clone6 && ( cd clone6 && - test ! -d sub1/.git && - test ! -d sub2/.git && - test ! -d sub3/.git && - test ! -d nested1/.git && + test_must_fail git rev-parse --resolve-git-dir sub1/.git && + test_must_fail git rev-parse --resolve-git-dir sub2/.git && + test_must_fail git rev-parse --resolve-git-dir sub3/.git && + test_must_fail git rev-parse --resolve-git-dir nested1/.git && git submodule update --init --recursive -- nested1 && - test ! -d sub1/.git && - test ! -d sub2/.git && - test ! -d sub3/.git && - test -d nested1/.git && - test -d nested1/nested2/.git && - test -d nested1/nested2/nested3/.git && - test -d nested1/nested2/nested3/submodule/.git + test_must_fail git rev-parse --resolve-git-dir sub1/.git && + test_must_fail git rev-parse --resolve-git-dir sub2/.git && + test_must_fail git rev-parse --resolve-git-dir sub3/.git && + git rev-parse --resolve-git-dir nested1/.git && + git rev-parse --resolve-git-dir nested1/nested2/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/.git && + git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git ) ' +test_expect_success 'command passed to foreach retains notion of stdin' ' + ( + cd super && + git submodule foreach echo success >../expected && + yes | git submodule foreach "read y && test \"x\$y\" = xy && echo success" >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'command passed to foreach --recursive retains notion of stdin' ' + ( + cd clone2 && + git submodule foreach --recursive echo success >../expected && + yes | git submodule foreach --recursive "read y && test \"x\$y\" = xy && echo success" >../actual + ) && + test_cmp expected actual +' + test_done diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index cc16d3f05d..ab37c368d0 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -43,7 +43,7 @@ git commit -m B-super-added' cd "$base_dir" test_expect_success 'after add: existence of info/alternates' \ -'test `wc -l <super/sub/.git/objects/info/alternates` = 1' +'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1' cd "$base_dir" @@ -66,7 +66,7 @@ test_expect_success 'update with reference' \ cd "$base_dir" test_expect_success 'after update: existence of info/alternates' \ -'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1' +'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1' cd "$base_dir" diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index 162527c211..1c908f4d39 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -10,7 +10,12 @@ Tests for selected commit options.' . ./test-lib.sh commit_msg_is () { - test "`git log --pretty=format:%s%b -1`" = "$1" + expect=commit_msg_is.expect + actual=commit_msg_is.actual + + printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect && + printf "%s" "$1" >$actual && + test_i18ncmp $expect $actual } # A sanity check to see if commit is working at all. @@ -23,13 +28,21 @@ test_expect_success 'a basic commit in an empty tree should succeed' ' test_expect_success 'nonexistent template file should return error' ' echo changes >> foo && git add foo && - test_must_fail git commit --template "$PWD"/notexist + ( + GIT_EDITOR="echo hello >\"\$1\"" && + export GIT_EDITOR && + test_must_fail git commit --template "$PWD"/notexist + ) ' test_expect_success 'nonexistent template file in config should return error' ' git config commit.template "$PWD"/notexist && - test_must_fail git commit && - git config --unset commit.template + test_when_finished "git config --unset commit.template" && + ( + GIT_EDITOR="echo hello >\"\$1\"" && + export GIT_EDITOR && + test_must_fail git commit + ) ' # From now on we'll use a template file that exists. @@ -110,6 +123,20 @@ test_expect_success 'commit message from file should override template' ' commit_msg_is "standard input msg" ' +cat >"$TEMPLATE" <<\EOF + + +### template + +EOF +test_expect_success 'commit message from template with whitespace issue' ' + echo "content galore" >>foo && + git add foo && + GIT_EDITOR="$TEST_DIRECTORY"/t7500/add-whitespaced-content git commit \ + --template "$TEMPLATE" && + commit_msg_is "commit message" +' + test_expect_success 'using alternate GIT_INDEX_FILE (1)' ' cp .git/index saved-index && diff --git a/t/t7500/add-whitespaced-content b/t/t7500/add-whitespaced-content new file mode 100755 index 0000000000..ccf07c61a4 --- /dev/null +++ b/t/t7500/add-whitespaced-content @@ -0,0 +1,8 @@ +#!/bin/sh +sed -e 's/|$//' >>"$1" <<\EOF + + | +commit message | + +EOF +exit 0 diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 8980738c75..3ad04363b5 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -14,8 +14,12 @@ test_tick test_expect_success \ "initial status" \ "echo 'bongo bongo' >file && - git add file && \ - git status | grep 'Initial commit'" + git add file" + +test_expect_success "Constructing initial commit" ' + git status >actual && + test_i18ngrep "Initial commit" actual +' test_expect_success \ "fail initial amend" \ @@ -38,10 +42,13 @@ test_expect_success \ "echo King of the bongo >file && test_must_fail git commit -m foo -a file" -test_expect_success PERL \ - "using paths with --interactive" \ - "echo bong-o-bong >file && - ! (echo 7 | git commit -m foo --interactive file)" +test_expect_success PERL 'can use paths with --interactive' ' + echo bong-o-bong >file && + # 2: update, 1:st path, that is all, 7: quit + ( echo 2; echo 1; echo; echo 7 ) | + git commit -m foo --interactive file && + git reset --hard HEAD^ +' test_expect_success \ "using invalid commit with -C" \ @@ -127,6 +134,16 @@ test_expect_success PERL \ "interactive add" \ "echo 7 | git commit --interactive | grep 'What now'" +test_expect_success PERL \ + "commit --interactive doesn't change index if editor aborts" \ + "echo zoo >file && + test_must_fail git diff --exit-code >diff1 && + (echo u ; echo '*' ; echo q) | + (EDITOR=: && export EDITOR && + test_must_fail git commit --interactive) && + git diff >diff2 && + test_cmp diff1 diff2" + test_expect_success \ "showing committed revisions" \ "git rev-list HEAD >current" diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 50da034cd3..3f3adc31b9 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -22,7 +22,7 @@ check_summary_oneline() { SUMMARY_POSTFIX="$(git log -1 --pretty='format:%h')" echo "[$SUMMARY_PREFIX $SUMMARY_POSTFIX] $2" >exp && - test_cmp exp act + test_i18ncmp exp act } test_expect_success 'output summary format' ' @@ -32,7 +32,10 @@ test_expect_success 'output summary format' ' check_summary_oneline "root-commit" "initial" && echo change >>file1 && - git add file1 && + git add file1 +' + +test_expect_success 'output summary format: root-commit' ' check_summary_oneline "" "a change" ' @@ -215,19 +218,21 @@ test_expect_success 'cleanup commit messages (strip,-F)' ' ' -echo "sample - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit." >expect - test_expect_success 'cleanup commit messages (strip,-F,-e)' ' echo >>negative && { echo;echo sample;echo; } >text && git commit -e -F text -a && - head -n 4 .git/COMMIT_EDITMSG >actual && - test_cmp expect actual + head -n 4 .git/COMMIT_EDITMSG >actual +' + +echo "sample +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit." >expect + +test_expect_success 'cleanup commit messages (strip,-F,-e): output' ' + test_i18ncmp expect actual ' echo "# @@ -235,11 +240,10 @@ echo "# #" >> expect test_expect_success 'author different from committer' ' - echo >>negative && - git commit -e -m "sample" + test_might_fail git commit -e -m "sample" && head -n 7 .git/COMMIT_EDITMSG >actual && - test_cmp expect actual + test_i18ncmp expect actual ' mv expect expect.tmp @@ -258,8 +262,8 @@ test_expect_success 'committer is automatic' ' test_must_fail git commit -e -m "sample" ) && head -n 8 .git/COMMIT_EDITMSG | \ - sed "s/^# Committer: .*/# Committer:/" >actual && - test_cmp expect actual + sed "s/^# Committer: .*/# Committer:/" >actual + test_i18ncmp expect actual ' pwd=`pwd` @@ -362,9 +366,9 @@ try_commit () { GIT_EDITOR=.git/FAKE_EDITOR git commit -a $* $use_template && case "$use_template" in '') - ! grep "^## Custom template" .git/COMMIT_EDITMSG ;; + test_i18ngrep ! "^## Custom template" .git/COMMIT_EDITMSG ;; *) - grep "^## Custom template" .git/COMMIT_EDITMSG ;; + test_i18ngrep "^## Custom template" .git/COMMIT_EDITMSG ;; esac } @@ -373,67 +377,67 @@ try_commit_status_combo () { test_expect_success 'commit' ' clear_config commit.status && try_commit "" && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit' ' clear_config commit.status && try_commit "" && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status' ' clear_config commit.status && try_commit --status && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status' ' clear_config commit.status && try_commit --no-status && - ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit with commit.status = yes' ' clear_config commit.status && git config commit.status yes && try_commit "" && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit with commit.status = no' ' clear_config commit.status && git config commit.status no && try_commit "" && - ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status with commit.status = yes' ' clear_config commit.status && git config commit.status yes && try_commit --status && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status with commit.status = yes' ' clear_config commit.status && git config commit.status yes && try_commit --no-status && - ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status with commit.status = no' ' clear_config commit.status && git config commit.status no && try_commit --status && - grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status with commit.status = no' ' clear_config commit.status && git config commit.status no && try_commit --no-status && - ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' } diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh index 8528f64c8d..ee7f0cd459 100755 --- a/t/t7503-pre-commit-hook.sh +++ b/t/t7503-pre-commit-hook.sh @@ -84,5 +84,38 @@ test_expect_success POSIXPERM '--no-verify with non-executable hook' ' git commit --no-verify -m "more content" ' +chmod +x "$HOOK" + +# a hook that checks $GIT_PREFIX and succeeds inside the +# success/ subdirectory only +cat > "$HOOK" <<EOF +#!/bin/sh +test \$GIT_PREFIX = success/ +EOF + +test_expect_success 'with hook requiring GIT_PREFIX' ' + + echo "more content" >> file && + git add file && + mkdir success && + ( + cd success && + git commit -m "hook requires GIT_PREFIX = success/" + ) && + rmdir success +' + +test_expect_success 'with failing hook requiring GIT_PREFIX' ' + + echo "more content" >> file && + git add file && + mkdir fail && + ( + cd fail && + test_must_fail git commit -m "hook must fail" + ) && + rmdir fail && + git checkout -- file +' test_done diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index ff189624d4..5b4b694f18 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -132,6 +132,18 @@ test_expect_success 'with hook (-c)' ' ' +test_expect_success 'with hook (merge)' ' + + head=`git rev-parse HEAD` && + git checkout -b other HEAD@{1} && + echo "more" >> file && + git add file && + git commit -m other && + git checkout - && + git merge other && + test "`git log -1 --pretty=format:%s`" = merge +' + cat > "$HOOK" <<'EOF' #!/bin/sh exit 1 diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index 3d4f85d74f..d31b34da83 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -4,17 +4,21 @@ test_description='git status for submodule' . ./test-lib.sh -test_expect_success 'setup' ' - test_create_repo sub && +test_create_repo_with_commit () { + test_create_repo "$1" && ( - cd sub && + cd "$1" && : >bar && git add bar && git commit -m " Add bar" && : >foo && git add foo && git commit -m " Add foo" - ) && + ) +} + +test_expect_success 'setup' ' + test_create_repo_with_commit sub && echo output > .gitignore && git add sub .gitignore && git commit -m "Add submodule sub" @@ -22,19 +26,19 @@ test_expect_success 'setup' ' test_expect_success 'status clean' ' git status >output && - grep "nothing to commit" output + test_i18ngrep "nothing to commit" output ' test_expect_success 'commit --dry-run -a clean' ' test_must_fail git commit --dry-run -a >output && - grep "nothing to commit" output + test_i18ngrep "nothing to commit" output ' test_expect_success 'status with modified file in submodule' ' (cd sub && git reset --hard) && echo "changed" >sub/foo && git status >output && - grep "modified: sub (modified content)" output + test_i18ngrep "modified: sub (modified content)" output ' test_expect_success 'status with modified file in submodule (porcelain)' ' @@ -49,7 +53,7 @@ test_expect_success 'status with modified file in submodule (porcelain)' ' test_expect_success 'status with added file in submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - grep "modified: sub (modified content)" output + test_i18ngrep "modified: sub (modified content)" output ' test_expect_success 'status with added file in submodule (porcelain)' ' @@ -64,12 +68,12 @@ test_expect_success 'status with untracked file in submodule' ' (cd sub && git reset --hard) && echo "content" >sub/new-file && git status >output && - grep "modified: sub (untracked content)" output + test_i18ngrep "modified: sub (untracked content)" output ' test_expect_success 'status -uno with untracked file in submodule' ' git status -uno >output && - grep "^nothing to commit" output + test_i18ngrep "^nothing to commit" output ' test_expect_success 'status with untracked file in submodule (porcelain)' ' @@ -83,7 +87,7 @@ test_expect_success 'status with added and untracked file in submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && echo "content" >sub/new-file && git status >output && - grep "modified: sub (modified content, untracked content)" output + test_i18ngrep "modified: sub (modified content, untracked content)" output ' test_expect_success 'status with added and untracked file in submodule (porcelain)' ' @@ -101,7 +105,7 @@ test_expect_success 'status with modified file in modified submodule' ' (cd sub && echo "next change" >foo && git commit -m "next change" foo) && echo "changed" >sub/foo && git status >output && - grep "modified: sub (new commits, modified content)" output + test_i18ngrep "modified: sub (new commits, modified content)" output ' test_expect_success 'status with modified file in modified submodule (porcelain)' ' @@ -116,7 +120,7 @@ test_expect_success 'status with modified file in modified submodule (porcelain) test_expect_success 'status with added file in modified submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - grep "modified: sub (new commits, modified content)" output + test_i18ngrep "modified: sub (new commits, modified content)" output ' test_expect_success 'status with added file in modified submodule (porcelain)' ' @@ -131,7 +135,7 @@ test_expect_success 'status with untracked file in modified submodule' ' (cd sub && git reset --hard) && echo "content" >sub/new-file && git status >output && - grep "modified: sub (new commits, untracked content)" output + test_i18ngrep "modified: sub (new commits, untracked content)" output ' test_expect_success 'status with untracked file in modified submodule (porcelain)' ' @@ -145,7 +149,7 @@ test_expect_success 'status with added and untracked file in modified submodule' (cd sub && git reset --hard && echo >foo && git add foo) && echo "content" >sub/new-file && git status >output && - grep "modified: sub (new commits, modified content, untracked content)" output + test_i18ngrep "modified: sub (new commits, modified content, untracked content)" output ' test_expect_success 'status with added and untracked file in modified submodule (porcelain)' ' @@ -170,7 +174,7 @@ test_expect_success 'setup .git file for sub' ' test_expect_success 'status with added file in modified submodule with .git file' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - grep "modified: sub (new commits, modified content)" output + test_i18ngrep "modified: sub (new commits, modified content)" output ' test_expect_success 'rm submodule contents' ' @@ -179,12 +183,92 @@ test_expect_success 'rm submodule contents' ' test_expect_success 'status clean (empty submodule dir)' ' git status >output && - grep "nothing to commit" output + test_i18ngrep "nothing to commit" output ' test_expect_success 'status -a clean (empty submodule dir)' ' test_must_fail git commit --dry-run -a >output && - grep "nothing to commit" output + test_i18ngrep "nothing to commit" output +' + +cat >status_expect <<\EOF +AA .gitmodules +A sub1 +EOF + +test_expect_success 'status with merge conflict in .gitmodules' ' + git clone . super && + test_create_repo_with_commit sub1 && + test_tick && + test_create_repo_with_commit sub2 && + ( + cd super && + prev=$(git rev-parse HEAD) && + git checkout -b add_sub1 && + git submodule add ../sub1 && + git commit -m "add sub1" && + git checkout -b add_sub2 $prev && + git submodule add ../sub2 && + git commit -m "add sub2" && + git checkout -b merge_conflict_gitmodules && + test_must_fail git merge add_sub1 && + git status -s >../status_actual 2>&1 + ) && + test_cmp status_actual status_expect +' + +sha1_merge_sub1=$(cd sub1 && git rev-parse HEAD) +sha1_merge_sub2=$(cd sub2 && git rev-parse HEAD) +short_sha1_merge_sub1=$(cd sub1 && git rev-parse --short HEAD) +short_sha1_merge_sub2=$(cd sub2 && git rev-parse --short HEAD) +cat >diff_expect <<\EOF +diff --cc .gitmodules +index badaa4c,44f999a..0000000 +--- a/.gitmodules ++++ b/.gitmodules +@@@ -1,3 -1,3 +1,9 @@@ +++<<<<<<< HEAD + +[submodule "sub2"] + + path = sub2 + + url = ../sub2 +++======= ++ [submodule "sub1"] ++ path = sub1 ++ url = ../sub1 +++>>>>>>> add_sub1 +EOF + +cat >diff_submodule_expect <<\EOF +diff --cc .gitmodules +index badaa4c,44f999a..0000000 +--- a/.gitmodules ++++ b/.gitmodules +@@@ -1,3 -1,3 +1,9 @@@ +++<<<<<<< HEAD + +[submodule "sub2"] + + path = sub2 + + url = ../sub2 +++======= ++ [submodule "sub1"] ++ path = sub1 ++ url = ../sub1 +++>>>>>>> add_sub1 +EOF + +test_expect_success 'diff with merge conflict in .gitmodules' ' + ( + cd super && + git diff >../diff_actual 2>&1 + ) && + test_cmp diff_actual diff_expect +' + +test_expect_success 'diff --submodule with merge conflict in .gitmodules' ' + ( + cd super && + git diff --submodule >../diff_submodule_actual 2>&1 + ) && + test_cmp diff_submodule_actual diff_submodule_expect ' test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh index f1dc5c3b6a..905255adf0 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -16,7 +16,7 @@ test_expect_success 'status -h in broken repository' ' echo "[status] showuntrackedfiles = CORRUPT" >>.git/config && test_expect_code 129 git status -h >usage 2>&1 ) && - grep "[Uu]sage" broken/usage + test_i18ngrep "[Uu]sage" broken/usage ' test_expect_success 'commit -h in broken repository' ' @@ -28,7 +28,7 @@ test_expect_success 'commit -h in broken repository' ' echo "[status] showuntrackedfiles = CORRUPT" >>.git/config && test_expect_code 129 git commit -h >usage 2>&1 ) && - grep "[Uu]sage" broken/usage + test_i18ngrep "[Uu]sage" broken/usage ' test_expect_success 'setup' ' @@ -56,9 +56,7 @@ test_expect_success 'setup' ' ' test_expect_success 'status (1)' ' - - grep "use \"git rm --cached <file>\.\.\.\" to unstage" output - + test_i18ngrep "use \"git rm --cached <file>\.\.\.\" to unstage" output ' cat >expect <<\EOF @@ -86,10 +84,8 @@ cat >expect <<\EOF EOF test_expect_success 'status (2)' ' - git status >output && - test_cmp expect output - + test_i18ncmp expect output ' cat >expect <<\EOF @@ -109,17 +105,14 @@ cat >expect <<\EOF # untracked EOF -git config advice.statusHints false - test_expect_success 'status (advice.statusHints false)' ' - + test_when_finished "git config --unset advice.statusHints" && + git config advice.statusHints false && git status >output && - test_cmp expect output + test_i18ncmp expect output ' -git config --unset advice.statusHints - cat >expect <<\EOF M dir1/modified A dir2/added @@ -138,6 +131,127 @@ test_expect_success 'status -s' ' ' +test_expect_success 'status with gitignore' ' + { + echo ".gitignore" && + echo "expect" && + echo "output" && + echo "untracked" + } >.gitignore && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + ?? dir2/modified + EOF + git status -s >output && + test_cmp expect output && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + ?? dir2/modified + !! .gitignore + !! dir1/untracked + !! dir2/untracked + !! expect + !! output + !! untracked + EOF + git status -s --ignored >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 + # + # Changes not staged for commit: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: dir1/modified + # + # Untracked files: + # (use "git add <file>..." to include in what will be committed) + # + # dir2/modified + # Ignored files: + # (use "git add -f <file>..." to include in what will be committed) + # + # .gitignore + # dir1/untracked + # dir2/untracked + # expect + # output + # untracked + EOF + git status --ignored >output && + test_cmp expect output +' + +test_expect_success 'status with gitignore (nothing untracked)' ' + { + echo ".gitignore" && + echo "expect" && + echo "dir2/modified" && + echo "output" && + echo "untracked" + } >.gitignore && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + EOF + git status -s >output && + test_cmp expect output && + + cat >expect <<-\EOF && + M dir1/modified + A dir2/added + !! .gitignore + !! dir1/untracked + !! dir2/modified + !! dir2/untracked + !! expect + !! output + !! untracked + EOF + git status -s --ignored >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 + # + # Changes not staged for commit: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: dir1/modified + # + # Ignored files: + # (use "git add -f <file>..." to include in what will be committed) + # + # .gitignore + # dir1/untracked + # dir2/modified + # dir2/untracked + # expect + # output + # untracked + EOF + git status --ignored >output && + test_cmp expect output +' + +rm -f .gitignore + cat >expect <<\EOF ## master M dir1/modified @@ -157,6 +271,12 @@ test_expect_success 'status -s -b' ' ' +test_expect_success 'setup dir3' ' + mkdir dir3 && + : >dir3/untracked1 && + : >dir3/untracked2 +' + cat >expect <<EOF # On branch master # Changes to be committed: @@ -173,17 +293,15 @@ cat >expect <<EOF # 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_i18ncmp expect output ' test_expect_success 'status (status.showUntrackedFiles no)' ' git config status.showuntrackedfiles no + test_when_finished "git config --unset status.showuntrackedfiles" && git status >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -199,7 +317,7 @@ EOF git config advice.statusHints false test_expect_success 'status -uno (advice.statusHints false)' ' git status -uno >output && - test_cmp expect output + test_i18ncmp expect output ' git config --unset advice.statusHints @@ -208,7 +326,6 @@ cat >expect << EOF A dir2/added EOF test_expect_success 'status -s -uno' ' - git config --unset status.showuntrackedfiles git status -s -uno >output && test_cmp expect output ' @@ -245,13 +362,14 @@ cat >expect <<EOF EOF test_expect_success 'status -unormal' ' git status -unormal >output && - test_cmp expect output + test_i18ncmp expect output ' test_expect_success 'status (status.showUntrackedFiles normal)' ' git config status.showuntrackedfiles normal + test_when_finished "git config --unset status.showuntrackedfiles" && git status >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -266,7 +384,6 @@ A dir2/added ?? untracked EOF test_expect_success 'status -s -unormal' ' - git config --unset status.showuntrackedfiles git status -s -unormal >output && test_cmp expect output ' @@ -304,14 +421,18 @@ cat >expect <<EOF EOF test_expect_success 'status -uall' ' git status -uall >output && - test_cmp expect output + test_i18ncmp expect output ' + test_expect_success 'status (status.showUntrackedFiles all)' ' git config status.showuntrackedfiles all + test_when_finished "git config --unset status.showuntrackedfiles" && git status >output && - rm -rf dir3 && - git config --unset status.showuntrackedfiles && - test_cmp expect output + test_i18ncmp expect output +' + +test_expect_success 'teardown dir3' ' + rm -rf dir3 ' cat >expect <<EOF @@ -362,10 +483,8 @@ cat >expect <<\EOF EOF test_expect_success 'status with relative paths' ' - (cd dir1 && git status) >output && - test_cmp expect output - + test_i18ncmp expect output ' cat >expect <<\EOF @@ -435,20 +554,17 @@ cat >expect <<\EOF EOF test_expect_success 'status with color.ui' ' - git config color.ui always && + test_when_finished "git config --unset color.ui" && git status | test_decode_color >output && - test_cmp expect output - + test_i18ncmp expect output ' test_expect_success 'status with color.status' ' - - git config --unset color.ui && git config color.status always && + test_when_finished "git config --unset color.status" && git status | test_decode_color >output && - test_cmp expect output - + test_i18ncmp expect output ' cat >expect <<\EOF @@ -464,7 +580,6 @@ EOF test_expect_success 'status -s with color.ui' ' - git config --unset color.status && git config color.ui always && git status -s | test_decode_color >output && test_cmp expect output @@ -566,9 +681,10 @@ EOF test_expect_success 'status without relative paths' ' - git config status.relativePaths false + git config status.relativePaths false && + test_when_finished "git config --unset status.relativePaths" && (cd dir1 && git status) >output && - test_cmp expect output + test_i18ncmp expect output ' @@ -585,6 +701,8 @@ EOF test_expect_success 'status -s without relative paths' ' + git config status.relativePaths false && + test_when_finished "git config --unset status.relativePaths" && (cd dir1 && git status -s) >output && test_cmp expect output @@ -608,7 +726,7 @@ cat <<EOF >expect EOF test_expect_success 'dry-run of partial commit excluding new file in index' ' git commit --dry-run dir1/modified >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -657,13 +775,13 @@ cat >expect <<EOF EOF test_expect_success 'status submodule summary is disabled by default' ' git status >output && - test_cmp expect output + test_i18ncmp expect output ' # we expect the same as the previous test test_expect_success 'status --untracked-files=all does not show submodule' ' git status --untracked-files=all >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -722,7 +840,7 @@ EOF test_expect_success 'status submodule summary' ' git config status.submodulesummary 10 && git status >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -760,13 +878,13 @@ cat >expect <<EOF # untracked no changes added to commit (use "git add" and/or "git commit -a") EOF -test_expect_success 'status submodule summary (clean submodule)' ' +test_expect_success 'status submodule summary (clean submodule): commit' ' git commit -m "commit submodule" && git config status.submodulesummary 10 && test_must_fail git commit --dry-run >output && - test_cmp expect output && + test_i18ncmp expect output && git status >output && - test_cmp expect output + test_i18ncmp expect output ' cat >expect <<EOF @@ -783,6 +901,13 @@ test_expect_success 'status -s submodule summary (clean submodule)' ' test_cmp expect output ' +test_expect_success 'status -z implies porcelain' ' + git status --porcelain | + perl -pe "s/\012/\000/g" >expect && + git status -z >output && + test_cmp expect output +' + cat >expect <<EOF # On branch master # Changes to be committed: @@ -815,7 +940,7 @@ EOF test_expect_success 'commit --dry-run submodule summary (--amend)' ' git config status.submodulesummary 10 && git commit --dry-run --amend >output && - test_cmp expect output + test_i18ncmp expect output ' test_expect_success POSIXPERM,SANITY 'status succeeds in a read-only repository' ' @@ -868,19 +993,19 @@ cat > expect << EOF EOF test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' - echo modified > sm/untracked && - git status --ignore-submodules=untracked > output && - test_cmp expect output + echo modified sm/untracked && + git status --ignore-submodules=untracked >output && + test_i18ncmp 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 && + test_i18ncmp 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname && git config --unset diff.ignoreSubmodules ' @@ -890,15 +1015,15 @@ test_expect_success '.git/config ignore=untracked suppresses submodules with unt 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 status >output && + test_i18ncmp 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 + git status --ignore-submodules=dirty >output && + test_i18ncmp expect output ' test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' ' @@ -907,8 +1032,8 @@ test_expect_success '.gitmodules ignore=dirty suppresses submodules with untrack ! 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname && git config --unset diff.ignoreSubmodules ' @@ -918,23 +1043,23 @@ test_expect_success '.git/config ignore=dirty suppresses submodules with untrack 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 status >output && + test_i18ncmp 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 + echo modified >sm/foo && + git status --ignore-submodules=dirty >output && + test_i18ncmp 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -943,8 +1068,8 @@ test_expect_success '.git/config ignore=dirty suppresses submodules with modifie 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 status >output && + test_i18ncmp expect output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' @@ -983,14 +1108,14 @@ EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' git status --ignore-submodules=untracked > output && - test_cmp expect output + test_i18ncmp 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -999,8 +1124,8 @@ test_expect_success ".git/config ignore=untracked doesn't suppress submodules wi 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 status >output && + test_i18ncmp expect output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' @@ -1045,14 +1170,14 @@ EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' git status --ignore-submodules=untracked > output && - test_cmp expect output + test_i18ncmp 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -1061,21 +1186,21 @@ test_expect_success ".git/config ignore=untracked doesn't suppress submodule sum 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 status >output && + test_i18ncmp 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_i18ncmp 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 status >output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -1084,8 +1209,8 @@ test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary 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 status >output && + test_i18ncmp expect output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' @@ -1113,7 +1238,7 @@ EOF test_expect_success "--ignore-submodules=all suppresses submodule summary" ' git status --ignore-submodules=all > output && - test_cmp expect output + test_i18ncmp expect output ' test_expect_failure '.gitmodules ignore=all suppresses submodule summary' ' diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh index 77b6920029..b61fd3c3c4 100755 --- a/t/t7509-commit.sh +++ b/t/t7509-commit.sh @@ -157,4 +157,33 @@ test_expect_success '--reset-author should be rejected without -c/-C/--amend' ' test_must_fail git commit -a --reset-author -m done ' +test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' ' + echo "cherry-pick 1a" >>foo && + test_tick && + git commit -am "cherry-pick 1" --author="Cherry <cherry@pick.er>" && + git tag cherry-pick-head && + git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD && + echo "This is a MERGE_MSG" >.git/MERGE_MSG && + echo "cherry-pick 1b" >>foo && + test_tick && + git commit -a && + author_header cherry-pick-head >expect && + author_header HEAD >actual && + test_cmp expect actual && + + echo "This is a MERGE_MSG" >expect && + message_body HEAD >actual && + test_cmp expect actual +' + +test_expect_success '--reset-author with CHERRY_PICK_HEAD' ' + git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD && + echo "cherry-pick 2" >>foo && + test_tick && + git commit -am "cherry-pick 2" --reset-author && + echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect && + author_header HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7511-status-index.sh b/t/t7511-status-index.sh new file mode 100755 index 0000000000..bca359dc1e --- /dev/null +++ b/t/t7511-status-index.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='git status with certain file name lengths' + +. ./test-lib.sh + +files="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z" + +check() { + len=$1 + prefix=$2 + + for i in $files + do + : >$prefix$i + done + + test_expect_success "status, filename length $len" " + git add $prefix* && + git status + " + rm $prefix* .git/index +} + +check 1 +check 2 p +check 3 pr +check 4 pre +check 5 pref +check 6 prefi +check 7 prefix +check 8 prefix- +check 9 prefix-p +check 10 prefix-pr +check 11 prefix-pre +check 12 prefix-pref +check 13 prefix-prefi +check 14 prefix-prefix +check 15 prefix-prefix- +check 16 prefix-prefix-p +check 17 prefix-prefix-pr +check 18 prefix-prefix-pre +check 19 prefix-prefix-pref +check 20 prefix-prefix-prefi +check 21 prefix-prefix-prefix +check 22 prefix-prefix-prefix- +check 23 prefix-prefix-prefix-p +check 24 prefix-prefix-prefix-pr + +test_done diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index b147a1bd69..3008e4e121 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -28,80 +28,80 @@ Testing basic merge operations/option parsing. . ./test-lib.sh -test_expect_success 'set up test data and helpers' ' - printf "%s\n" 1 2 3 4 5 6 7 8 9 >file && - printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >file.1 && - printf "%s\n" 1 2 3 4 "5 X" 6 7 8 9 >file.5 && - printf "%s\n" 1 2 3 4 5 6 7 8 "9 X" >file.9 && - printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >result.1 && - printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 9 >result.1-5 && - printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 "9 X" >result.1-5-9 && - - create_merge_msgs() { - echo "Merge commit '\''c2'\''" >msg.1-5 && - echo "Merge commit '\''c2'\''; commit '\''c3'\''" >msg.1-5-9 && - { - echo "Squashed commit of the following:" && - echo && - git log --no-merges ^HEAD c1 - } >squash.1 && - { - echo "Squashed commit of the following:" && - echo && - git log --no-merges ^HEAD c2 - } >squash.1-5 && - { - echo "Squashed commit of the following:" && - echo && - git log --no-merges ^HEAD c2 c3 - } >squash.1-5-9 && - echo >msg.nolog && - { - echo "* commit '\''c3'\'':" && - echo " commit 3" && - echo - } >msg.log - } && - - verify_merge() { - test_cmp "$2" "$1" && - git update-index --refresh && - git diff --exit-code && - if test -n "$3" - then - git show -s --pretty=format:%s HEAD >msg.act && - test_cmp "$3" msg.act - fi - } && - - verify_head() { - echo "$1" >head.expected && - git rev-parse HEAD >head.actual && - test_cmp head.expected head.actual - } && - - verify_parents() { - printf "%s\n" "$@" >parents.expected && - >parents.actual && - i=1 && - while test $i -le $# - do - git rev-parse HEAD^$i >>parents.actual && - i=$(expr $i + 1) || - return 1 - done && - test_cmp parents.expected parents.actual - } && - - verify_mergeheads() { - printf "%s\n" "$@" >mergehead.expected && - test_cmp mergehead.expected .git/MERGE_HEAD - } && - - verify_no_mergehead() { - ! test -e .git/MERGE_HEAD - } -' +printf '%s\n' 1 2 3 4 5 6 7 8 9 >file +printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >file.1 +printf '%s\n' 1 2 3 4 '5 X' 6 7 8 9 >file.5 +printf '%s\n' 1 2 3 4 5 6 7 8 '9 X' >file.9 +printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >result.1 +printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5 +printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9 +>empty + +create_merge_msgs () { + echo "Merge commit 'c2'" >msg.1-5 && + echo "Merge commit 'c2'; commit 'c3'" >msg.1-5-9 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c1 + } >squash.1 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c2 + } >squash.1-5 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c2 c3 + } >squash.1-5-9 && + echo >msg.nolog && + { + echo "* commit 'c3':" && + echo " commit 3" && + echo + } >msg.log +} + +verify_merge () { + test_cmp "$2" "$1" && + git update-index --refresh && + git diff --exit-code && + if test -n "$3" + then + git show -s --pretty=format:%s HEAD >msg.act && + test_cmp "$3" msg.act + fi +} + +verify_head () { + echo "$1" >head.expected && + git rev-parse HEAD >head.actual && + test_cmp head.expected head.actual +} + +verify_parents () { + printf '%s\n' "$@" >parents.expected && + >parents.actual && + i=1 && + while test $i -le $# + do + git rev-parse HEAD^$i >>parents.actual && + i=$(expr $i + 1) || + return 1 + done && + test_must_fail git rev-parse --verify "HEAD^$i" && + test_cmp parents.expected parents.actual +} + +verify_mergeheads () { + printf '%s\n' "$@" >mergehead.expected && + test_cmp mergehead.expected .git/MERGE_HEAD +} + +verify_no_mergehead () { + ! test -e .git/MERGE_HEAD +} test_expect_success 'setup' ' git add file && @@ -225,12 +225,28 @@ test_expect_success 'merge c1 with c2 and c3' ' test_debug 'git log --graph --decorate --oneline --all' -test_expect_success 'failing merges with --ff-only' ' +test_expect_success 'merges with --ff-only' ' git reset --hard c1 && test_tick && test_must_fail git merge --ff-only c2 && test_must_fail git merge --ff-only c3 && - test_must_fail git merge --ff-only c2 c3 + test_must_fail git merge --ff-only c2 c3 && + git reset --hard c0 && + git merge c3 && + verify_head $c3 +' + +test_expect_success 'merges with merge.ff=only' ' + git reset --hard c1 && + test_tick && + test_when_finished "git config --unset merge.ff" && + git config merge.ff only && + test_must_fail git merge c2 && + test_must_fail git merge c3 && + test_must_fail git merge c2 c3 && + git reset --hard c0 && + git merge c3 && + verify_head $c3 ' test_expect_success 'merge c0 with c1 (no-commit)' ' @@ -324,6 +340,39 @@ test_expect_success 'merge c1 with c2 (no-commit in config)' ' test_debug 'git log --graph --decorate --oneline --all' +test_expect_success 'merge c1 with c2 (log in config)' ' + git config branch.master.mergeoptions "" && + git reset --hard c1 && + git merge --log c2 && + git show -s --pretty=tformat:%s%n%b >expect && + + git config branch.master.mergeoptions --log && + git reset --hard c1 && + git merge c2 && + git show -s --pretty=tformat:%s%n%b >actual && + + test_cmp expect actual +' + +test_expect_success 'merge c1 with c2 (log in config gets overridden)' ' + test_when_finished "git config --remove-section branch.master" && + test_when_finished "git config --remove-section merge" && + test_might_fail git config --remove-section branch.master && + test_might_fail git config --remove-section merge && + + git reset --hard c1 && + git merge c2 && + git show -s --pretty=tformat:%s%n%b >expect && + + git config branch.master.mergeoptions "--no-log" && + git config merge.log true && + git reset --hard c1 && + git merge c2 && + git show -s --pretty=tformat:%s%n%b >actual && + + test_cmp expect actual +' + test_expect_success 'merge c1 with c2 (squash in config)' ' git reset --hard c1 && git config branch.master.mergeoptions "--squash" && @@ -415,7 +464,41 @@ test_expect_success 'merge c0 with c1 (no-ff)' ' test_debug 'git log --graph --decorate --oneline --all' +test_expect_success 'merge c0 with c1 (merge.ff=false)' ' + git reset --hard c0 && + git config merge.ff false && + test_tick && + git merge c1 && + git config --remove-section merge && + verify_merge file result.1 && + verify_parents $c0 $c1 +' +test_debug 'git log --graph --decorate --oneline --all' + +test_expect_success 'combine branch.master.mergeoptions with merge.ff' ' + git reset --hard c0 && + git config branch.master.mergeoptions --ff && + git config merge.ff false && + test_tick && + git merge c1 && + git config --remove-section "branch.master" && + git config --remove-section "merge" && + verify_merge file result.1 && + verify_parents "$c0" +' + +test_expect_success 'tolerate unknown values for merge.ff' ' + git reset --hard c0 && + git config merge.ff something-new && + test_tick && + git merge c1 2>message && + git config --remove-section "merge" && + verify_head "$c1" && + test_cmp empty message +' + test_expect_success 'combining --squash and --no-ff is refused' ' + git reset --hard c0 && test_must_fail git merge --squash --no-ff c1 && test_must_fail git merge --no-ff --squash c1 ' @@ -498,7 +581,7 @@ test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'in-index merge' ' git reset --hard c0 && git merge --no-ff -s resolve c1 >out && - grep "Wonderful." out && + test_i18ngrep "Wonderful." out && verify_parents $c0 $c1 ' @@ -560,4 +643,27 @@ test_expect_success 'amending no-ff merge commit' ' test_debug 'git log --graph --decorate --oneline --all' +cat >editor <<\EOF +#!/bin/sh +# Add a new message string that was not in the template +( + echo "Merge work done on the side branch c1" + echo + cat <"$1" +) >"$1.tmp" && mv "$1.tmp" "$1" +# strip comments and blank lines from end of message +sed -e '/^#/d' < "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' > expected +EOF +chmod 755 editor + +test_expect_success 'merge --no-ff --edit' ' + git reset --hard c0 && + EDITOR=./editor git merge --no-ff --edit c1 && + verify_parents $c0 $c1 && + git cat-file commit HEAD >raw && + grep "work done on the side branch" raw && + sed "1,/^$/d" >actual raw && + test_cmp actual expected +' + test_done diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index 0a46795ae7..61f36baa1f 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -53,7 +53,7 @@ cat >expected <<\EOF Trying simple merge with c2 Trying simple merge with c3 Trying simple merge with c4 -Merge made by octopus. +Merge made by the 'octopus' strategy. c2.c | 1 + c3.c | 1 + c4.c | 1 + @@ -72,7 +72,7 @@ test_expect_success 'merge output uses pretty names' ' cat >expected <<\EOF Already up-to-date with c4 Trying simple merge with c5 -Merge made by octopus. +Merge made by the 'octopus' strategy. c5.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 c5.c @@ -86,7 +86,7 @@ test_expect_success 'merge up-to-date output uses pretty names' ' cat >expected <<\EOF Fast-forwarding to: c1 Trying simple merge with c2 -Merge made by octopus. +Merge made by the 'octopus' strategy. c1.c | 1 + c2.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 4d5ce4e682..aa74184c31 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -107,6 +107,7 @@ error: The following untracked working tree files would be overwritten by merge: sub sub2 Please move or remove them before you can merge. +Aborting EOF test_expect_success 'will not overwrite untracked file in leading path' ' @@ -122,7 +123,7 @@ test_expect_success 'will not overwrite untracked file in leading path' ' rm -f sub sub2 ' -test_expect_failure SYMLINKS 'will not overwrite untracked symlink in leading path' ' +test_expect_success SYMLINKS 'will not overwrite untracked symlink in leading path' ' git reset --hard c0 && rm -rf sub && mkdir sub2 && @@ -151,9 +152,33 @@ test_expect_success 'will not overwrite untracked file on unborn branch' ' git checkout --orphan new && cp important c0.c && test_must_fail git merge c0 2>out && - test_cmp out expect && + test_i18ncmp out expect +' + +test_expect_success 'will not overwrite untracked file on unborn branch .git/MERGE_HEAD sanity etc.' ' + test_when_finished "rm c0.c" && test_path_is_missing .git/MERGE_HEAD && test_cmp important c0.c ' +test_expect_success 'failed merge leaves unborn branch in the womb' ' + test_must_fail git rev-parse --verify HEAD +' + +test_expect_success 'set up unborn branch and content' ' + git symbolic-ref HEAD refs/heads/unborn && + rm -f .git/index && + echo foo > tracked-file && + git add tracked-file && + echo bar > untracked-file +' + +test_expect_success 'will not clobber WT/index when merging into unborn' ' + git merge master && + grep foo tracked-file && + git show :tracked-file >expect && + grep foo expect && + grep bar untracked-file +' + test_done diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh index c994836c53..0e4a682c64 100755 --- a/t/t7609-merge-co-error-msgs.sh +++ b/t/t7609-merge-co-error-msgs.sh @@ -32,6 +32,7 @@ error: The following untracked working tree files would be overwritten by merge: three two Please move or remove them before you can merge. +Aborting EOF test_expect_success 'untracked files overwritten by merge (fast and non-fast forward)' ' @@ -56,6 +57,7 @@ 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. +Aborting EOF test_expect_success 'untracked files or local changes ovewritten by merge' ' @@ -71,6 +73,7 @@ error: Your local changes to the following files would be overwritten by checkou rep/one rep/two Please, commit your changes or stash them before you can switch branches. +Aborting EOF test_expect_success 'cannot switch branches because of local changes' ' @@ -92,6 +95,7 @@ error: Your local changes to the following files would be overwritten by checkou rep/one rep/two Please, commit your changes or stash them before you can switch branches. +Aborting EOF test_expect_success 'not uptodate file porcelain checkout error' ' @@ -105,6 +109,7 @@ error: Updating the following directories would lose untracked files in it: rep rep2 +Aborting EOF test_expect_success 'not_uptodate_dir porcelain checkout error' ' diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index d78bdec330..4aab2a75b8 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -16,23 +16,60 @@ Testing basic merge tool invocation' test_expect_success 'setup' ' git config rerere.enabled true && echo master >file1 && + echo master spaced >"spaced name" && + echo master file11 >file11 && + echo master file12 >file12 && + echo master file13 >file13 && + echo master file14 >file14 && mkdir subdir && echo master sub >subdir/file3 && - git add file1 subdir/file3 && - git commit -m "added file1" && + test_create_repo submod && + ( + cd submod && + : >foo && + git add foo && + git commit -m "Add foo" + ) && + git submodule add git://example.com/submod submod && + git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod && + git commit -m "add initial versions" && git checkout -b branch1 master && + git submodule update -N && echo branch1 change >file1 && echo branch1 newfile >file2 && + echo branch1 spaced >"spaced name" && + echo branch1 change file11 >file11 && + echo branch1 change file13 >file13 && echo branch1 sub >subdir/file3 && - git add file1 file2 subdir/file3 && + ( + cd submod && + echo branch1 submodule >bar && + git add bar && + git commit -m "Add bar on branch1" && + git checkout -b submod-branch1 + ) && + git add file1 "spaced name" file11 file13 file2 subdir/file3 submod && + git rm file12 && git commit -m "branch1 changes" && git checkout master && + git submodule update -N && echo master updated >file1 && echo master new >file2 && + echo master updated spaced >"spaced name" && + echo master updated file12 >file12 && + echo master updated file14 >file14 && echo master new sub >subdir/file3 && - git add file1 file2 subdir/file3 && + ( + cd submod && + echo master submodule >bar && + git add bar && + git commit -m "Add bar on master" && + git checkout -b submod-master + ) && + git add file1 "spaced name" file12 file14 file2 subdir/file3 submod && + git rm file11 && git commit -m "master updates" && git config merge.tool mytool && @@ -42,13 +79,18 @@ test_expect_success 'setup' ' test_expect_success 'custom mergetool' ' git checkout -b test1 branch1 && + git submodule update -N && test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file1 >/dev/null 2>&1 ) && - ( yes "" | git mergetool file2 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file1 ) && + ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) && ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod >/dev/null 2>&1 ) && test "$(cat file1)" = "master updated" && test "$(cat file2)" = "master new" && test "$(cat subdir/file3)" = "master new sub" && + test "$(cat submod/bar)" = "branch1 submodule" && git commit -m "branch1 resolved with mergetool" ' @@ -58,10 +100,16 @@ test_expect_success 'mergetool crlf' ' test_must_fail git merge master >/dev/null 2>&1 && ( yes "" | git mergetool file1 >/dev/null 2>&1 ) && ( yes "" | git mergetool file2 >/dev/null 2>&1 ) && + ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) && ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && + ( yes "r" | git mergetool submod >/dev/null 2>&1 ) && test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" && test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" && test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && git commit -m "branch1 resolved with mergetool - autocrlf" && git config core.autocrlf false && git reset --hard @@ -69,6 +117,7 @@ test_expect_success 'mergetool crlf' ' test_expect_success 'mergetool in subdir' ' git checkout -b test3 branch1 && + git submodule update -N && ( cd subdir && test_must_fail git merge master >/dev/null 2>&1 && @@ -81,17 +130,25 @@ 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 ) && + ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) && + ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) && test "$(cat ../file1)" = "master updated" && test "$(cat ../file2)" = "master new" && + test "$(cat ../submod/bar)" = "branch1 submodule" && git commit -m "branch1 resolved with mergetool - subdir" ) ' test_expect_success 'mergetool skips autoresolved' ' git checkout -b test4 branch1 && + git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && + ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod >/dev/null 2>&1 ) && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git reset --hard @@ -102,13 +159,290 @@ 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 && + ( yes "r" | git mergetool ../submod ) && + ( yes "d" "d" | 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 && + ( cd .. && git submodule update -N ) && + test "$(cat ../submod/bar)" = "master submodule" && git commit -m "branch2 resolved by mergetool from subdir" ) ' +test_expect_success 'mergetool skips resolved paths when rerere is active' ' + git config rerere.enabled true && + rm -rf .git/rr-cache && + git checkout -b test5 branch1 + git submodule update -N && + test_must_fail git merge master >/dev/null 2>&1 && + ( yes "l" | git mergetool --no-prompt submod >/dev/null 2>&1 ) && + ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) && + git submodule update -N && + output="$(yes "n" | git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git reset --hard +' + +test_expect_success 'mergetool takes partial path' ' + git config rerere.enabled false && + git checkout -b test12 branch1 && + git submodule update -N && + test_must_fail git merge master && + + #shouldnt need these lines + #( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && + #( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && + #( yes "l" | git mergetool submod >/dev/null 2>&1 ) && + #( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) && + + ( yes "" | git mergetool subdir ) && + + test "$(cat subdir/file3)" = "master new sub" && + git reset --hard +' + +test_expect_success 'deleted vs modified submodule' ' + git checkout -b test6 branch1 && + git submodule update -N && + mv submod submod-movedaside && + git rm submod && + git commit -m "Submodule deleted from branch" && + git checkout -b test6.a test6 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "r" | git mergetool submod ) && + rmdir submod && mv submod-movedaside submod && + test "$(cat submod/bar)" = "branch1 submodule" && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping module" && + + mv submod submod-movedaside && + git checkout -b test6.b test6 && + git submodule update -N && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod ) && + test ! -e submod && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by deleting module" && + + mv submod-movedaside submod && + git checkout -b test6.c master && + git submodule update -N && + test_must_fail git merge test6 && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "r" | git mergetool submod ) && + test ! -e submod && + test -d submod.orig && + git submodule update -N && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by deleting module" && + mv submod.orig submod && + + git checkout -b test6.d master && + git submodule update -N && + test_must_fail git merge test6 && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod ) && + test "$(cat submod/bar)" = "master submodule" && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping module" && + git reset --hard HEAD +' + +test_expect_success 'file vs modified submodule' ' + git checkout -b test7 branch1 && + git submodule update -N && + mv submod submod-movedaside && + git rm submod && + echo not a submodule >submod && + git add submod && + git commit -m "Submodule path becomes file" && + git checkout -b test7.a branch1 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "r" | git mergetool submod ) && + rmdir submod && mv submod-movedaside submod && + test "$(cat submod/bar)" = "branch1 submodule" && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping module" && + + mv submod submod-movedaside && + git checkout -b test7.b test7 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod ) && + git submodule update -N && + test "$(cat submod)" = "not a submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping file" && + + git checkout -b test7.c master && + rmdir submod && mv submod-movedaside submod && + test ! -e submod.orig && + git submodule update -N && + test_must_fail git merge test7 && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "r" | git mergetool submod ) && + test -d submod.orig && + git submodule update -N && + test "$(cat submod)" = "not a submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping file" && + + git checkout -b test7.d master && + rmdir submod && mv submod.orig submod && + git submodule update -N && + test_must_fail git merge test7 && + test -n "$(git ls-files -u)" && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && + ( yes "l" | git mergetool submod ) && + test "$(cat submod/bar)" = "master submodule" && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git commit -m "Merge resolved by keeping module" +' + +test_expect_success 'submodule in subdirectory' ' + git checkout -b test10 branch1 && + git submodule update -N && + ( + cd subdir && + test_create_repo subdir_module && + ( + cd subdir_module && + : >file15 && + git add file15 && + git commit -m "add initial versions" + ) + ) && + git submodule add git://example.com/subsubmodule subdir/subdir_module && + git add subdir/subdir_module && + git commit -m "add submodule in subdirectory" && + + git checkout -b test10.a test10 && + git submodule update -N && + ( + cd subdir/subdir_module && + git checkout -b super10.a && + echo test10.a >file15 && + git add file15 && + git commit -m "on branch 10.a" + ) && + git add subdir/subdir_module && + git commit -m "change submodule in subdirectory on test10.a" && + + git checkout -b test10.b test10 && + git submodule update -N && + ( + cd subdir/subdir_module && + git checkout -b super10.b && + echo test10.b >file15 && + git add file15 && + git commit -m "on branch 10.b" + ) && + git add subdir/subdir_module && + git commit -m "change submodule in subdirectory on test10.b" && + + test_must_fail git merge test10.a >/dev/null 2>&1 && + ( + cd subdir && + ( yes "l" | git mergetool subdir_module ) + ) && + test "$(cat subdir/subdir_module/file15)" = "test10.b" && + git submodule update -N && + test "$(cat subdir/subdir_module/file15)" = "test10.b" && + git reset --hard && + git submodule update -N && + + test_must_fail git merge test10.a >/dev/null 2>&1 && + ( yes "r" | git mergetool subdir/subdir_module ) && + test "$(cat subdir/subdir_module/file15)" = "test10.b" && + git submodule update -N && + test "$(cat subdir/subdir_module/file15)" = "test10.a" && + git commit -m "branch1 resolved with mergetool" && + rm -rf subdir/subdir_module +' + +test_expect_success 'directory vs modified submodule' ' + git checkout -b test11 branch1 && + mv submod submod-movedaside && + git rm submod && + mkdir submod && + echo not a submodule >submod/file16 && + git add submod/file16 && + git commit -m "Submodule path becomes directory" && + + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + ( yes "l" | git mergetool submod ) && + test "$(cat submod/file16)" = "not a submodule" && + rm -rf submod.orig && + + git reset --hard >/dev/null 2>&1 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + test ! -e submod.orig && + ( yes "r" | git mergetool submod ) && + test -d submod.orig && + test "$(cat submod.orig/file16)" = "not a submodule" && + rm -r submod.orig && + mv submod-movedaside/.git submod && + ( cd submod && git clean -f && git reset --hard ) && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside && + + git checkout -b test11.c master && + git submodule update -N && + test_must_fail git merge test11 && + test -n "$(git ls-files -u)" && + ( yes "l" | git mergetool submod ) && + git submodule update -N && + test "$(cat submod/bar)" = "master submodule" && + + git reset --hard >/dev/null 2>&1 && + git submodule update -N && + test_must_fail git merge test11 && + test -n "$(git ls-files -u)" && + test ! -e submod.orig && + ( yes "r" | git mergetool submod ) && + test "$(cat submod/file16)" = "not a submodule" && + + git reset --hard master >/dev/null 2>&1 && + ( cd submod && git clean -f && git reset --hard ) && + git submodule update -N +' + test_done diff --git a/t/t7611-merge-abort.sh b/t/t7611-merge-abort.sh index 61890bc892..7b4798e8e4 100755 --- a/t/t7611-merge-abort.sh +++ b/t/t7611-merge-abort.sh @@ -47,7 +47,10 @@ pre_merge_head="$(git rev-parse HEAD)" test_expect_success 'fails without MERGE_HEAD (unstarted merge)' ' test_must_fail git merge --abort 2>output && - grep -q MERGE_HEAD output && + test_i18ngrep MERGE_HEAD output +' + +test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' ' test ! -f .git/MERGE_HEAD && test "$pre_merge_head" = "$(git rev-parse HEAD)" ' @@ -58,7 +61,10 @@ test_expect_success 'fails without MERGE_HEAD (completed merge)' ' # Merge successfully completed post_merge_head="$(git rev-parse HEAD)" && test_must_fail git merge --abort 2>output && - grep -q MERGE_HEAD output && + test_i18ngrep MERGE_HEAD output +' + +test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' ' test ! -f .git/MERGE_HEAD && test "$post_merge_head" = "$(git rev-parse HEAD)" ' diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 4048d106d4..4fb4c9384a 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -10,9 +10,6 @@ Testing basic diff tool invocation . ./test-lib.sh -LF=' -' - remove_config_vars() { # Unset all config variables used by git-difftool @@ -41,7 +38,17 @@ restore_test_defaults() prompt_given() { prompt="$1" - test "$prompt" = "Hit return to launch 'test-tool': branch" + test "$prompt" = "Launch 'test-tool' [Y/n]: branch" +} + +stdin_contains() +{ + grep >/dev/null "$1" +} + +stdin_doesnot_contain() +{ + ! stdin_contains "$1" } # Create a file on master and change it on branch @@ -268,4 +275,35 @@ test_expect_success PERL 'difftool --extcmd cat arg2' ' test "$diff" = branch ' +# Create a second file on master and a different version on branch +test_expect_success PERL 'setup with 2 files different' ' + echo m2 >file2 && + git add file2 && + git commit -m "added file2" && + + git checkout branch && + echo br2 >file2 && + git add file2 && + git commit -a -m "branch changed file2" && + git checkout master +' + +test_expect_success PERL 'say no to the first file' ' + diff=$( (echo n; echo) | git difftool -x cat branch ) && + + echo "$diff" | stdin_contains m2 && + echo "$diff" | stdin_contains br2 && + echo "$diff" | stdin_doesnot_contain master && + echo "$diff" | stdin_doesnot_contain branch +' + +test_expect_success PERL 'say no to the second file' ' + diff=$( (echo; echo n) | git difftool -x cat branch ) && + + echo "$diff" | stdin_contains master && + echo "$diff" | stdin_contains branch && + echo "$diff" | stdin_doesnot_contain m2 && + echo "$diff" | stdin_doesnot_contain br2 +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index c8777589ca..81263b7851 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -26,6 +26,17 @@ test_expect_success setup ' echo foo mmap bar_mmap echo foo_mmap bar mmap baz } >file && + { + echo Hello world + echo HeLLo world + echo Hello_world + echo HeLLo_world + } >hello_world && + { + echo "a+b*c" + echo "a+bc" + echo "abc" + } >ab && echo vvv >v && echo ww w >w && echo x x xx x >x && @@ -59,7 +70,29 @@ do echo ${HC}file:4:foo mmap bar_mmap echo ${HC}file:5:foo_mmap bar mmap baz } >expected && - git grep -n -w -e mmap $H >actual && + git -c grep.linenumber=false grep -n -w -e mmap $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L" ' + { + echo ${HC}file:1:foo mmap bar + echo ${HC}file:3:foo_mmap bar mmap + echo ${HC}file:4:foo mmap bar_mmap + echo ${HC}file:5:foo_mmap bar mmap baz + } >expected && + git -c grep.linenumber=true grep -w -e mmap $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L" ' + { + echo ${HC}file:foo mmap bar + echo ${HC}file:foo_mmap bar mmap + echo ${HC}file:foo mmap bar_mmap + echo ${HC}file:foo_mmap bar mmap baz + } >expected && + git -c grep.linenumber=true grep --no-line-number -w -e mmap $H >actual && test_cmp expected actual ' @@ -182,6 +215,34 @@ do test_cmp expected actual ' + test_expect_success "grep --max-depth 0 -- . t $L" ' + { + echo ${HC}t/v:1:vvv + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth 0 -n -e vvv $H -- . t >actual && + test_cmp expected actual + ' + + test_expect_success "grep --max-depth 0 -- t . $L" ' + { + echo ${HC}t/v:1:vvv + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth 0 -n -e vvv $H -- t . >actual && + test_cmp expected actual + ' + test_expect_success "grep $L with grep.extendedRegexp=false" ' + echo "ab:a+bc" >expected && + git -c grep.extendedRegexp=false grep "a+b*c" ab >actual && + test_cmp expected actual + ' + + test_expect_success "grep $L with grep.extendedRegexp=true" ' + echo "ab:abc" >expected && + git -c grep.extendedRegexp=true grep "a+b*c" ab >actual && + test_cmp expected actual + ' done cat >expected <<EOF @@ -285,6 +346,11 @@ test_expect_success 'grep -f, ignore empty lines' ' test_cmp expected actual ' +test_expect_success 'grep -f, ignore empty lines, read patterns from stdin' ' + git grep -f - <patterns >actual && + test_cmp expected actual +' + cat >expected <<EOF y:y yy -- @@ -443,6 +509,20 @@ test_expect_success 'grep -p -B5' ' test_cmp expected actual ' +cat >expected <<EOF +hello.c=int main(int argc, const char **argv) +hello.c-{ +hello.c- printf("Hello world.\n"); +hello.c: return 0; +hello.c- /* char ?? */ +hello.c-} +EOF + +test_expect_success 'grep -W' ' + git grep -W return >actual && + test_cmp expected actual +' + test_expect_success 'grep from a subdirectory to search wider area (1)' ' mkdir -p s && ( @@ -474,7 +554,6 @@ test_expect_success 'outside of git repository' ' mkdir -p non/git/sub && echo hello >non/git/file1 && echo world >non/git/sub/file2 && - echo ".*o*" >non/git/.gitignore && { echo file1:hello && echo sub/file2:world @@ -491,6 +570,23 @@ test_expect_success 'outside of git repository' ' test_must_fail git grep o && git grep --no-index o >../../actual.sub && test_cmp ../../expect.sub ../../actual.sub + ) && + + echo ".*o*" >non/git/.gitignore && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non/git" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_must_fail git grep o && + git grep --no-index --exclude-standard o >../actual.full && + test_cmp ../expect.full ../actual.full && + + { + echo ".gitignore:.*o*" + cat ../expect.full + } >../expect.with.ignored && + git grep --no-index --no-exclude o >../actual.full && + test_cmp ../expect.with.ignored ../actual.full ) ' @@ -503,6 +599,10 @@ test_expect_success 'inside git repository but with --no-index' ' { echo file1:hello && echo sub/file2:world + } >is/expect.unignored && + { + echo ".gitignore:.*o*" && + cat is/expect.unignored } >is/expect.full && : >is/expect.empty && echo file2:world >is/expect.sub && @@ -511,12 +611,24 @@ test_expect_success 'inside git repository but with --no-index' ' git init && test_must_fail git grep o >../actual.full && test_cmp ../expect.empty ../actual.full && + + git grep --untracked o >../actual.unignored && + test_cmp ../expect.unignored ../actual.unignored && + git grep --no-index o >../actual.full && test_cmp ../expect.full ../actual.full && + + git grep --no-index --exclude-standard o >../actual.unignored && + test_cmp ../expect.unignored ../actual.unignored && + cd sub && test_must_fail git grep o >../../actual.sub && test_cmp ../../expect.empty ../../actual.sub && + git grep --no-index o >../../actual.sub && + test_cmp ../../expect.sub ../../actual.sub && + + git grep --untracked o >../../actual.sub && test_cmp ../../expect.sub ../../actual.sub ) ' @@ -554,4 +666,195 @@ test_expect_success 'grep -e -- -- path' ' test_cmp expected actual ' +cat >expected <<EOF +hello.c:int main(int argc, const char **argv) +hello.c: printf("Hello world.\n"); +EOF + +test_expect_success LIBPCRE 'grep --perl-regexp pattern' ' + git grep --perl-regexp "\p{Ps}.*?\p{Pe}" hello.c >actual && + test_cmp expected actual +' + +test_expect_success LIBPCRE 'grep -P pattern' ' + git grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual && + test_cmp expected actual +' + +test_expect_success 'grep pattern with grep.extendedRegexp=true' ' + >empty && + test_must_fail git -c grep.extendedregexp=true \ + grep "\p{Ps}.*?\p{Pe}" hello.c >actual && + test_cmp empty actual +' + +test_expect_success LIBPCRE 'grep -P pattern with grep.extendedRegexp=true' ' + git -c grep.extendedregexp=true \ + grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual && + test_cmp expected actual +' + +test_expect_success LIBPCRE 'grep -P -v pattern' ' + { + echo "ab:a+b*c" + echo "ab:a+bc" + } >expected && + git grep -P -v "abc" ab >actual && + test_cmp expected actual +' + +test_expect_success LIBPCRE 'grep -P -i pattern' ' + cat >expected <<-EOF && + hello.c: printf("Hello world.\n"); + EOF + git grep -P -i "PRINTF\([^\d]+\)" hello.c >actual && + test_cmp expected actual +' + +test_expect_success LIBPCRE 'grep -P -w pattern' ' + { + echo "hello_world:Hello world" + echo "hello_world:HeLLo world" + } >expected && + git grep -P -w "He((?i)ll)o" hello_world >actual && + test_cmp expected actual +' + +test_expect_success 'grep -G invalidpattern properly dies ' ' + test_must_fail git grep -G "a[" +' + +test_expect_success 'grep -E invalidpattern properly dies ' ' + test_must_fail git grep -E "a[" +' + +test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' ' + test_must_fail git grep -P "a[" +' + +test_expect_success 'grep -G -E -F pattern' ' + echo "ab:a+b*c" >expected && + git grep -G -E -F "a+b*c" ab >actual && + test_cmp expected actual +' + +test_expect_success 'grep -E -F -G pattern' ' + echo "ab:a+bc" >expected && + git grep -E -F -G "a+b*c" ab >actual && + test_cmp expected actual +' + +test_expect_success 'grep -F -G -E pattern' ' + echo "ab:abc" >expected && + git grep -F -G -E "a+b*c" ab >actual && + test_cmp expected actual +' + +test_expect_success 'grep -G -F -P -E pattern' ' + >empty && + test_must_fail git grep -G -F -P -E "a\x{2b}b\x{2a}c" ab >actual && + test_cmp empty actual +' + +test_expect_success LIBPCRE 'grep -G -F -E -P pattern' ' + echo "ab:a+b*c" >expected && + git grep -G -F -E -P "a\x{2b}b\x{2a}c" ab >actual && + test_cmp expected actual +' + +test_config() { + git config "$1" "$2" && + test_when_finished "git config --unset $1" +} + +cat >expected <<EOF +hello.c<RED>:<RESET>int main(int argc, const char **argv) +hello.c<RED>-<RESET>{ +<RED>--<RESET> +hello.c<RED>:<RESET> /* char ?? */ +hello.c<RED>-<RESET>} +<RED>--<RESET> +hello_world<RED>:<RESET>Hello_world +hello_world<RED>-<RESET>HeLLo_world +EOF + +test_expect_success 'grep --color, separator' ' + test_config color.grep.context normal && + test_config color.grep.filename normal && + test_config color.grep.function normal && + test_config color.grep.linenumber normal && + test_config color.grep.match normal && + test_config color.grep.selected normal && + test_config color.grep.separator red && + + git grep --color=always -A1 -e char -e lo_w hello.c hello_world | + test_decode_color >actual && + test_cmp expected actual +' + +cat >expected <<EOF +hello.c:int main(int argc, const char **argv) +hello.c: /* char ?? */ + +hello_world:Hello_world +EOF + +test_expect_success 'grep --break' ' + git grep --break -e char -e lo_w hello.c hello_world >actual && + test_cmp expected actual +' + +cat >expected <<EOF +hello.c:int main(int argc, const char **argv) +hello.c-{ +-- +hello.c: /* char ?? */ +hello.c-} + +hello_world:Hello_world +hello_world-HeLLo_world +EOF + +test_expect_success 'grep --break with context' ' + git grep --break -A1 -e char -e lo_w hello.c hello_world >actual && + test_cmp expected actual +' + +cat >expected <<EOF +hello.c +int main(int argc, const char **argv) + /* char ?? */ +hello_world +Hello_world +EOF + +test_expect_success 'grep --heading' ' + git grep --heading -e char -e lo_w hello.c hello_world >actual && + test_cmp expected actual +' + +cat >expected <<EOF +<BOLD;GREEN>hello.c<RESET> +2:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv) +6: /* <BLACK;BYELLOW>char<RESET> ?? */ + +<BOLD;GREEN>hello_world<RESET> +3:Hel<BLACK;BYELLOW>lo_w<RESET>orld +EOF + +test_expect_success 'mimic ack-grep --group' ' + test_config color.grep.context normal && + test_config color.grep.filename "bold green" && + test_config color.grep.function normal && + test_config color.grep.linenumber normal && + test_config color.grep.match "black yellow" && + test_config color.grep.selected normal && + test_config color.grep.separator normal && + + git grep --break --heading -n --color \ + -e char -e lo_w hello.c hello_world | + test_decode_color >actual && + test_cmp expected actual +' + test_done diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh index 568a6f2b69..a8957782cf 100755 --- a/t/t7811-grep-open.sh +++ b/t/t7811-grep-open.sh @@ -63,7 +63,7 @@ test_expect_success SIMPLEPAGER 'git grep -O' ' test_expect_success 'git grep -O --cached' ' test_must_fail git grep --cached -O GREP_PATTERN >out 2>msg && - grep open-files-in-pager msg + test_i18ngrep open-files-in-pager msg ' test_expect_success 'git grep -O --no-index' ' diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh index 45cb60ea4b..41962f04a7 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -6,10 +6,11 @@ test_description='git annotate' PROG='git annotate' . "$TEST_DIRECTORY"/annotate-tests.sh -test_expect_success \ - 'Annotating an old revision works' \ - '[ $(git annotate file master | awk "{print \$3}" | grep -c "^A$") -eq 2 ] && \ - [ $(git annotate file master | awk "{print \$3}" | grep -c "^B$") -eq 2 ]' - +test_expect_success 'Annotating an old revision works' ' + git annotate file master >result && + awk "{ print \$3; }" <result >authors && + test 2 = $(grep A <authors | wc -l) && + test 2 = $(grep B <authors | wc -l) +' test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index d3a51e1269..e2896cffc1 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -8,7 +8,7 @@ PROG='git blame -c' PROG='git blame -c -e' test_expect_success 'Blame --show-email works' ' - check_count "<A@test.git>" 1 "<B@test.git>" 1 "<B1@test.git>" 1 "<B2@test.git>" 1 "<author@example.com>" 1 "<C@test.git>" 1 "<D@test.git>" 1 + check_count "<A@test.git>" 1 "<B@test.git>" 1 "<B1@test.git>" 1 "<B2@test.git>" 1 "<author@example.com>" 1 "<C@test.git>" 1 "<D@test.git>" 1 "<E at test dot git>" 1 ' test_done diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh index ea64cd8d0f..32ec82ad67 100755 --- a/t/t8006-blame-textconv.sh +++ b/t/t8006-blame-textconv.sh @@ -25,7 +25,8 @@ test_expect_success 'setup ' ' echo "bin: test 1 version 2" >one.bin && echo "bin: test number 2 version 2" >>two.bin && if test_have_prereq SYMLINKS; then - ln -sf two.bin symlink.bin + rm symlink.bin && + ln -s two.bin symlink.bin fi && GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00" ' diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh new file mode 100755 index 0000000000..d15f8b3d47 --- /dev/null +++ b/t/t8008-blame-formats.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='blame output in various formats on a simple case' +. ./test-lib.sh + +test_expect_success 'setup' ' + echo a >file && + git add file + test_tick && + git commit -m one && + echo b >>file && + echo c >>file && + echo d >>file && + test_tick && + git commit -a -m two +' + +cat >expect <<'EOF' +^baf5e0b (A U Thor 2005-04-07 15:13:13 -0700 1) a +8825379d (A U Thor 2005-04-07 15:14:13 -0700 2) b +8825379d (A U Thor 2005-04-07 15:14:13 -0700 3) c +8825379d (A U Thor 2005-04-07 15:14:13 -0700 4) d +EOF +test_expect_success 'normal blame output' ' + git blame file >actual && + test_cmp expect actual +' + +ID1=baf5e0b3869e0b2b2beb395a3720c7b51eac94fc +COMMIT1='author A U Thor +author-mail <author@example.com> +author-time 1112911993 +author-tz -0700 +committer C O Mitter +committer-mail <committer@example.com> +committer-time 1112911993 +committer-tz -0700 +summary one +boundary +filename file' +ID2=8825379dfb8a1267b58e8e5bcf69eec838f685ec +COMMIT2='author A U Thor +author-mail <author@example.com> +author-time 1112912053 +author-tz -0700 +committer C O Mitter +committer-mail <committer@example.com> +committer-time 1112912053 +committer-tz -0700 +summary two +previous baf5e0b3869e0b2b2beb395a3720c7b51eac94fc file +filename file' + +cat >expect <<EOF +$ID1 1 1 1 +$COMMIT1 + a +$ID2 2 2 3 +$COMMIT2 + b +$ID2 3 3 + c +$ID2 4 4 + d +EOF +test_expect_success 'blame --porcelain output' ' + git blame --porcelain file >actual && + test_cmp expect actual +' + +cat >expect <<EOF +$ID1 1 1 1 +$COMMIT1 + a +$ID2 2 2 3 +$COMMIT2 + b +$ID2 3 3 +$COMMIT2 + c +$ID2 4 4 +$COMMIT2 + d +EOF +test_expect_success 'blame --line-porcelain output' ' + git blame --line-porcelain file >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 579ddb7572..8c12c65c72 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -23,6 +23,7 @@ test_expect_success $PREREQ \ echo do echo " echo \"!\$a!\"" echo "done >commandline\$output" + test_have_prereq MINGW && echo "dos2unix commandline\$output" echo "cat > msgtxt\$output" ) >fake.sendmail && chmod +x ./fake.sendmail && @@ -1168,4 +1169,32 @@ test_expect_success $PREREQ '--force sends cover letter template anyway' ' test -n "$(ls msgtxt*)" ' +test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' ' + clean_fake_sendmail && + echo "alias sbd somebody@example.org" >.mailrc && + git config --replace-all sendemail.aliasesfile "$(pwd)/.mailrc" && + git config sendemail.aliasfiletype mailrc && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=sbd \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/0001-*.patch \ + 2>errors >out && + grep "^!somebody@example\.org!$" commandline1 +' + +test_expect_success $PREREQ 'sendemail.aliasfile=~/.mailrc' ' + clean_fake_sendmail && + echo "alias sbd someone@example.org" >~/.mailrc && + git config --replace-all sendemail.aliasesfile "~/.mailrc" && + git config sendemail.aliasfiletype mailrc && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=sbd \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/0001-*.patch \ + 2>errors >out && + grep "^!someone@example\.org!$" commandline1 +' + test_done diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh index 88a9751dd3..6f6175a8f7 100755 --- a/t/t9010-svn-fe.sh +++ b/t/t9010-svn-fe.sh @@ -9,6 +9,30 @@ reinit_git () { git init } +properties () { + while test "$#" -ne 0 + do + property="$1" && + value="$2" && + printf "%s\n" "K ${#property}" && + printf "%s\n" "$property" && + printf "%s\n" "V ${#value}" && + printf "%s\n" "$value" && + shift 2 || + return 1 + done +} + +text_no_props () { + text="$1 +" && + printf "%s\n" "Prop-content-length: 10" && + printf "%s\n" "Text-content-length: ${#text}" && + printf "%s\n" "Content-length: $((${#text} + 10))" && + printf "%s\n" "" "PROPS-END" && + printf "%s\n" "$text" +} + >empty test_expect_success 'empty dump' ' @@ -18,13 +42,794 @@ test_expect_success 'empty dump' ' git fast-import <stream ' -test_expect_success 'v3 dumps not supported' ' +test_expect_success 'v4 dumps not supported' ' reinit_git && - echo "SVN-fs-dump-format-version: 3" >input && - test_must_fail test-svn-fe input >stream && + echo "SVN-fs-dump-format-version: 4" >v4.dump && + test_must_fail test-svn-fe v4.dump >stream && test_cmp empty stream ' +test_expect_failure 'empty revision' ' + reinit_git && + printf "rev <nobody, nobody@local>: %s\n" "" "" >expect && + cat >emptyrev.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 0 + Content-length: 0 + + Revision-number: 2 + Prop-content-length: 0 + Content-length: 0 + + EOF + test-svn-fe emptyrev.dump >stream && + git fast-import <stream && + git log -p --format="rev <%an, %ae>: %s" HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'empty properties' ' + reinit_git && + printf "rev <nobody, nobody@local>: %s\n" "" "" >expect && + cat >emptyprop.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + EOF + test-svn-fe emptyprop.dump >stream && + git fast-import <stream && + git log -p --format="rev <%an, %ae>: %s" HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'author name and commit message' ' + reinit_git && + echo "<author@example.com, author@example.com@local>" >expect.author && + cat >message <<-\EOF && + A concise summary of the change + + A detailed description of the change, why it is needed, what + was broken and why applying this is the best course of action. + + * file.c + Details pertaining to an individual file. + EOF + { + properties \ + svn:author author@example.com \ + svn:log "$(cat message)" && + echo PROPS-END + } >props && + { + echo "SVN-fs-dump-format-version: 3" && + echo && + echo "Revision-number: 1" && + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props + } >log.dump && + test-svn-fe log.dump >stream && + git fast-import <stream && + git log -p --format="%B" HEAD >actual.log && + git log --format="<%an, %ae>" >actual.author && + test_cmp message actual.log && + test_cmp expect.author actual.author +' + +test_expect_success 'unsupported properties are ignored' ' + reinit_git && + echo author >expect && + cat >extraprop.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 56 + Content-length: 56 + + K 8 + nonsense + V 1 + y + K 10 + svn:author + V 6 + author + PROPS-END + EOF + test-svn-fe extraprop.dump >stream && + git fast-import <stream && + git log -p --format=%an HEAD >actual && + test_cmp expect actual +' + +test_expect_failure 'timestamp and empty file' ' + echo author@example.com >expect.author && + echo 1999-01-01 >expect.date && + echo file >expect.files && + reinit_git && + { + properties \ + svn:author author@example.com \ + svn:date "1999-01-01T00:01:002.000000Z" \ + svn:log "add empty file" && + echo PROPS-END + } >props && + { + cat <<-EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + EOF + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props && + cat <<-\EOF + + Node-path: empty-file + Node-kind: file + Node-action: add + Content-length: 0 + + EOF + } >emptyfile.dump && + test-svn-fe emptyfile.dump >stream && + git fast-import <stream && + git log --format=%an HEAD >actual.author && + git log --date=short --format=%ad HEAD >actual.date && + git ls-tree -r --name-only HEAD >actual.files && + test_cmp expect.author actual.author && + test_cmp expect.date actual.date && + test_cmp expect.files actual.files && + git checkout HEAD empty-file && + test_cmp empty file +' + +test_expect_success 'directory with files' ' + reinit_git && + printf "%s\n" directory/file1 directory/file2 >expect.files && + echo hi >hi && + echo hello >hello && + { + properties \ + svn:author author@example.com \ + svn:date "1999-02-01T00:01:002.000000Z" \ + svn:log "add directory with some files in it" && + echo PROPS-END + } >props && + { + cat <<-EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + EOF + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props && + cat <<-\EOF && + + Node-path: directory + Node-kind: dir + Node-action: add + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: directory/file1 + Node-kind: file + Node-action: add + EOF + text_no_props hello && + cat <<-\EOF && + Node-path: directory/file2 + Node-kind: file + Node-action: add + EOF + text_no_props hi + } >directory.dump && + test-svn-fe directory.dump >stream && + git fast-import <stream && + + git ls-tree -r --name-only HEAD >actual.files && + git checkout HEAD directory && + test_cmp expect.files actual.files && + test_cmp hello directory/file1 && + test_cmp hi directory/file2 +' + +test_expect_success 'node without action' ' + cat >inaction.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: directory + Node-kind: dir + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + EOF + test_must_fail test-svn-fe inaction.dump +' + +test_expect_success 'action: add node without text' ' + cat >textless.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: textless + Node-kind: file + Node-action: add + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + EOF + test_must_fail test-svn-fe textless.dump +' + +test_expect_failure 'change file mode but keep old content' ' + reinit_git && + cat >expect <<-\EOF && + OBJID + :120000 100644 OBJID OBJID T greeting + OBJID + :100644 120000 OBJID OBJID T greeting + OBJID + :000000 100644 OBJID OBJID A greeting + EOF + echo "link hello" >expect.blob && + echo hello >hello && + cat >filemode.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: add + Prop-content-length: 10 + Text-content-length: 11 + Content-length: 21 + + PROPS-END + link hello + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: change + Prop-content-length: 33 + Content-length: 33 + + K 11 + svn:special + V 1 + * + PROPS-END + + Revision-number: 3 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: change + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + EOF + test-svn-fe filemode.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + git show HEAD:greeting >actual.blob && + git show HEAD^:greeting >actual.target && + test_cmp expect actual && + test_cmp expect.blob actual.blob && + test_cmp hello actual.target +' + +test_expect_success 'NUL in property value' ' + reinit_git && + echo "commit message" >expect.message && + { + properties \ + unimportant "something with a NUL (Q)" \ + svn:log "commit message"&& + echo PROPS-END + } | + q_to_nul >props && + { + cat <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + EOF + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props + } >nulprop.dump && + test-svn-fe nulprop.dump >stream && + git fast-import <stream && + git diff-tree --always -s --format=%s HEAD >actual.message && + test_cmp expect.message actual.message +' + +test_expect_success 'NUL in log message, file content, and property name' ' + # Caveat: svnadmin 1.6.16 (r1073529) truncates at \0 in the + # svn:specialQnotreally example. + reinit_git && + cat >expect <<-\EOF && + OBJID + :100644 100644 OBJID OBJID M greeting + OBJID + :000000 100644 OBJID OBJID A greeting + EOF + printf "\n%s\n" "something with an ASCII NUL (Q)" >expect.message && + printf "%s\n" "helQo" >expect.hello1 && + printf "%s\n" "link hello" >expect.hello2 && + { + properties svn:log "something with an ASCII NUL (Q)" && + echo PROPS-END + } | + q_to_nul >props && + { + q_to_nul <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: add + Prop-content-length: 10 + Text-content-length: 6 + Content-length: 16 + + PROPS-END + helQo + + Revision-number: 2 + EOF + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props && + q_to_nul <<-\EOF + + Node-path: greeting + Node-kind: file + Node-action: change + Prop-content-length: 43 + Text-content-length: 11 + Content-length: 54 + + K 21 + svn:specialQnotreally + V 1 + * + PROPS-END + link hello + EOF + } >8bitclean.dump && + test-svn-fe 8bitclean.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + { + git cat-file commit HEAD | nul_to_q && + echo + } | + sed -ne "/^\$/,\$ p" >actual.message && + git cat-file blob HEAD^:greeting | nul_to_q >actual.hello1 && + git cat-file blob HEAD:greeting | nul_to_q >actual.hello2 && + test_cmp expect actual && + test_cmp expect.message actual.message && + test_cmp expect.hello1 actual.hello1 && + test_cmp expect.hello2 actual.hello2 +' + +test_expect_success 'change file mode and reiterate content' ' + reinit_git && + cat >expect <<-\EOF && + OBJID + :120000 100644 OBJID OBJID T greeting + OBJID + :100644 120000 OBJID OBJID T greeting + OBJID + :000000 100644 OBJID OBJID A greeting + EOF + echo "link hello" >expect.blob && + echo hello >hello && + cat >filemode.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: add + Prop-content-length: 10 + Text-content-length: 11 + Content-length: 21 + + PROPS-END + link hello + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: change + Prop-content-length: 33 + Text-content-length: 11 + Content-length: 44 + + K 11 + svn:special + V 1 + * + PROPS-END + link hello + + Revision-number: 3 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: change + Prop-content-length: 10 + Text-content-length: 11 + Content-length: 21 + + PROPS-END + link hello + EOF + test-svn-fe filemode.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + git show HEAD:greeting >actual.blob && + git show HEAD^:greeting >actual.target && + test_cmp expect actual && + test_cmp expect.blob actual.blob && + test_cmp hello actual.target +' + +test_expect_success 'deltas not supported' ' + { + # (old) h + (inline) ello + (old) \n + printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" | + q_to_nul + } >delta && + { + properties \ + svn:author author@example.com \ + svn:date "1999-01-05T00:01:002.000000Z" \ + svn:log "add greeting" && + echo PROPS-END + } >props && + { + properties \ + svn:author author@example.com \ + svn:date "1999-01-06T00:01:002.000000Z" \ + svn:log "change it" && + echo PROPS-END + } >props2 && + { + echo SVN-fs-dump-format-version: 3 && + echo && + echo Revision-number: 1 && + echo Prop-content-length: $(wc -c <props) && + echo Content-length: $(wc -c <props) && + echo && + cat props && + cat <<-\EOF && + + Node-path: hello + Node-kind: file + Node-action: add + Prop-content-length: 10 + Text-content-length: 3 + Content-length: 13 + + PROPS-END + hi + + EOF + echo Revision-number: 2 && + echo Prop-content-length: $(wc -c <props2) && + echo Content-length: $(wc -c <props2) && + echo && + cat props2 && + cat <<-\EOF && + + Node-path: hello + Node-kind: file + Node-action: change + Text-delta: true + Prop-content-length: 10 + EOF + echo Text-content-length: $(wc -c <delta) && + echo Content-length: $((10 + $(wc -c <delta))) && + echo && + echo PROPS-END && + cat delta + } >delta.dump && + test_must_fail test-svn-fe delta.dump +' + +test_expect_success 'property deltas supported' ' + reinit_git && + cat >expect <<-\EOF && + OBJID + :100755 100644 OBJID OBJID M script.sh + EOF + { + properties \ + svn:author author@example.com \ + svn:date "1999-03-06T00:01:002.000000Z" \ + svn:log "make an executable, or chmod -x it" && + echo PROPS-END + } >revprops && + { + echo SVN-fs-dump-format-version: 3 && + echo && + echo Revision-number: 1 && + echo Prop-content-length: $(wc -c <revprops) && + echo Content-length: $(wc -c <revprops) && + echo && + cat revprops && + echo && + cat <<-\EOF && + Node-path: script.sh + Node-kind: file + Node-action: add + Text-content-length: 0 + Prop-content-length: 39 + Content-length: 39 + + K 14 + svn:executable + V 4 + true + PROPS-END + + EOF + echo Revision-number: 2 && + echo Prop-content-length: $(wc -c <revprops) && + echo Content-length: $(wc -c <revprops) && + echo && + cat revprops && + echo && + cat <<-\EOF + Node-path: script.sh + Node-kind: file + Node-action: change + Prop-delta: true + Prop-content-length: 30 + Content-length: 30 + + D 14 + svn:executable + PROPS-END + EOF + } >propdelta.dump && + test-svn-fe propdelta.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + test_cmp expect actual +' + +test_expect_success 'properties on /' ' + reinit_git && + cat <<-\EOF >expect && + OBJID + OBJID + :000000 100644 OBJID OBJID A greeting + EOF + sed -e "s/X$//" <<-\EOF >changeroot.dump && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: greeting + Node-kind: file + Node-action: add + Text-content-length: 0 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: X + Node-kind: dir + Node-action: change + Prop-delta: true + Prop-content-length: 43 + Content-length: 43 + + K 10 + svn:ignore + V 11 + build-area + + PROPS-END + EOF + test-svn-fe changeroot.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --root --always --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + test_cmp expect actual +' + +test_expect_success 'deltas for typechange' ' + reinit_git && + cat >expect <<-\EOF && + OBJID + :120000 100644 OBJID OBJID T test-file + OBJID + :100755 120000 OBJID OBJID T test-file + OBJID + :000000 100755 OBJID OBJID A test-file + EOF + cat >deleteprop.dump <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: test-file + Node-kind: file + Node-action: add + Prop-delta: true + Prop-content-length: 35 + Text-content-length: 17 + Content-length: 52 + + K 14 + svn:executable + V 0 + + PROPS-END + link testing 123 + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: test-file + Node-kind: file + Node-action: change + Prop-delta: true + Prop-content-length: 53 + Text-content-length: 17 + Content-length: 70 + + K 11 + svn:special + V 1 + * + D 14 + svn:executable + PROPS-END + link testing 231 + + Revision-number: 3 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: test-file + Node-kind: file + Node-action: change + Prop-delta: true + Prop-content-length: 27 + Text-content-length: 17 + Content-length: 44 + + D 11 + svn:special + PROPS-END + link testing 321 + EOF + test-svn-fe deleteprop.dump >stream && + git fast-import <stream && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + test_cmp expect actual +' + + test_expect_success 'set up svn repo' ' svnconf=$PWD/svnconf && mkdir -p "$svnconf" && diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh index 5d477e4bda..cf4c05261b 100755 --- a/t/t9116-git-svn-log.sh +++ b/t/t9116-git-svn-log.sh @@ -60,6 +60,21 @@ test_expect_success 'test ascending revision range' " git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 - " +test_expect_success 'test ascending revision range with --show-commit' " + git reset --hard trunk && + git svn log --show-commit -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 - + " + +test_expect_success 'test ascending revision range with --show-commit (sha1)' " + git svn find-rev r1 >expected-range-r1-r2-r4-sha1 && + git svn find-rev r2 >>expected-range-r1-r2-r4-sha1 && + git svn find-rev r4 >>expected-range-r1-r2-r4-sha1 && + git reset --hard trunk && + git svn log --show-commit -r 1:4 | grep '^r[0-9]' | cut -d'|' -f2 >out && + git rev-parse \$(cat out) >actual && + test_cmp expected-range-r1-r2-r4-sha1 actual + " + printf 'r4 \nr2 \nr1 \n' > expected-range-r4-r2-r1 test_expect_success 'test descending revision range' " diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh index ec0a106614..b324c491c5 100755 --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@ -96,7 +96,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' ' rm -r "$GIT_DIR" && test x = x"$(git config svn.authorsfile)" && test_config="$HOME"/.gitconfig && - unset GIT_CONFIG_NOGLOBAL && unset GIT_DIR && unset GIT_CONFIG && git config --global \ diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh index 158c8e33ef..6d3130e618 100755 --- a/t/t9146-git-svn-empty-dirs.sh +++ b/t/t9146-git-svn-empty-dirs.sh @@ -28,6 +28,23 @@ test_expect_success 'empty directories exist' ' ) ' +test_expect_success 'option automkdirs set to false' ' + ( + git svn init "$svnrepo" cloned-no-mkdirs && + cd cloned-no-mkdirs && + git config svn-remote.svn.automkdirs false && + git svn fetch && + for i in a b c d d/e d/e/f "weird file name" + do + if test -d "$i" + then + echo >&2 "$i exists" + exit 1 + fi + done + ) +' + test_expect_success 'more emptiness' ' svn_cmd mkdir -m "bang bang" "$svnrepo"/"! !" ' diff --git a/t/t9158-git-svn-mergeinfo.sh b/t/t9158-git-svn-mergeinfo.sh index 3ab43902b3..8c9539e1b4 100755 --- a/t/t9158-git-svn-mergeinfo.sh +++ b/t/t9158-git-svn-mergeinfo.sh @@ -38,4 +38,17 @@ test_expect_success 'verify svn:mergeinfo' ' test "$mergeinfo" = "/branches/foo:1-10" ' +test_expect_success 'change svn:mergeinfo multiline' ' + touch baz && + git add baz && + git commit -m "baz" && + git svn dcommit --mergeinfo="/branches/bar:1-10 /branches/other:3-5,8,10-11" +' + +test_expect_success 'verify svn:mergeinfo multiline' ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/trunk) + test "$mergeinfo" = "/branches/bar:1-10 +/branches/other:3-5,8,10-11" +' + test_done diff --git a/t/t9159-git-svn-no-parent-mergeinfo.sh b/t/t9159-git-svn-no-parent-mergeinfo.sh new file mode 100755 index 0000000000..69e4815781 --- /dev/null +++ b/t/t9159-git-svn-no-parent-mergeinfo.sh @@ -0,0 +1,41 @@ +#!/bin/sh +test_description='git svn handling of root commits in merge ranges' +. ./lib-git-svn.sh + +svn_ver="$(svn --version --quiet)" +case $svn_ver in +0.* | 1.[0-4].*) + skip_all="skipping git-svn test - SVN too old ($svn_ver)" + test_done + ;; +esac + +test_expect_success 'test handling of root commits in merge ranges' ' + mkdir -p init/trunk init/branches init/tags && + echo "r1" > init/trunk/file.txt && + svn_cmd import -m "initial import" init "$svnrepo" && + svn_cmd co "$svnrepo" tmp && + ( + cd tmp && + echo "r2" > trunk/file.txt && + svn_cmd commit -m "Modify file.txt on trunk" && + svn_cmd cp trunk@1 branches/a && + svn_cmd commit -m "Create branch a from trunk r1" && + svn_cmd propset svn:mergeinfo /trunk:1-2 branches/a && + svn_cmd commit -m "Fake merge of trunk r2 into branch a" && + mkdir branches/b && + echo "r5" > branches/b/file2.txt && + svn_cmd add branches/b && + svn_cmd commit -m "Create branch b from thin air" && + echo "r6" > branches/b/file2.txt && + svn_cmd commit -m "Modify file2.txt on branch b" && + svn_cmd cp branches/b@5 branches/c && + svn_cmd commit -m "Create branch c from branch b r5" && + svn_cmd propset svn:mergeinfo /branches/b:5-6 branches/c && + svn_cmd commit -m "Fake merge of branch b r6 into branch c" + ) && + git svn init -s "$svnrepo" && + git svn fetch + ' + +test_done diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh new file mode 100755 index 0000000000..b4a4434604 --- /dev/null +++ b/t/t9160-git-svn-preserve-empty-dirs.sh @@ -0,0 +1,153 @@ +#!/bin/sh +# +# Copyright (c) 2011 Ray Chen +# + +test_description='git svn test (option --preserve-empty-dirs) + +This test uses git to clone a Subversion repository that contains empty +directories, and checks that corresponding directories are created in the +local Git repository with placeholder files.' + +. ./lib-git-svn.sh + +say 'define NO_SVN_TESTS to skip git svn tests' +GIT_REPO=git-svn-repo + +test_expect_success 'initialize source svn repo containing empty dirs' ' + svn_cmd mkdir -m x "$svnrepo"/trunk && + svn_cmd co "$svnrepo"/trunk "$SVN_TREE" && + ( + cd "$SVN_TREE" && + mkdir -p 1 2 3/a 3/b 4 5 6 && + echo "First non-empty file" > 2/file1.txt && + echo "Second non-empty file" > 2/file2.txt && + echo "Third non-empty file" > 3/a/file1.txt && + echo "Fourth non-empty file" > 3/b/file1.txt && + svn_cmd add 1 2 3 4 5 6 && + svn_cmd commit -m "initial commit" && + + mkdir 4/a && + svn_cmd add 4/a && + svn_cmd commit -m "nested empty directory" && + mkdir 4/a/b && + svn_cmd add 4/a/b && + svn_cmd commit -m "deeply nested empty directory" && + mkdir 4/a/b/c && + svn_cmd add 4/a/b/c && + svn_cmd commit -m "really deeply nested empty directory" && + echo "Kill the placeholder file" > 4/a/b/c/foo && + svn_cmd add 4/a/b/c/foo && + svn_cmd commit -m "Regular file to remove placeholder" && + + svn_cmd del 2/file2.txt && + svn_cmd del 3/b && + svn_cmd commit -m "delete non-last entry in directory" && + + svn_cmd del 2/file1.txt && + svn_cmd del 3/a && + svn_cmd commit -m "delete last entry in directory" && + + echo "Conflict file" > 5/.placeholder && + mkdir 6/.placeholder && + svn_cmd add 5/.placeholder 6/.placeholder && + svn_cmd commit -m "Placeholder Namespace conflict" + ) && + rm -rf "$SVN_TREE" +' + +test_expect_success 'clone svn repo with --preserve-empty-dirs' ' + git svn clone "$svnrepo"/trunk --preserve-empty-dirs "$GIT_REPO" +' + +# "$GIT_REPO"/1 should only contain the placeholder file. +test_expect_success 'directory empty from inception' ' + test -f "$GIT_REPO"/1/.gitignore && + test $(find "$GIT_REPO"/1 -type f | wc -l) = "1" +' + +# "$GIT_REPO"/2 and "$GIT_REPO"/3 should only contain the placeholder file. +test_expect_success 'directory empty from subsequent svn commit' ' + test -f "$GIT_REPO"/2/.gitignore && + test $(find "$GIT_REPO"/2 -type f | wc -l) = "1" && + test -f "$GIT_REPO"/3/.gitignore && + test $(find "$GIT_REPO"/3 -type f | wc -l) = "1" +' + +# No placeholder files should exist in "$GIT_REPO"/4, even though one was +# generated for every sub-directory at some point in the repo's history. +test_expect_success 'add entry to previously empty directory' ' + test $(find "$GIT_REPO"/4 -type f | wc -l) = "1" && + test -f "$GIT_REPO"/4/a/b/c/foo +' + +# The HEAD~2 commit should not have introduced .gitignore placeholder files. +test_expect_success 'remove non-last entry from directory' ' + ( + cd "$GIT_REPO" && + git checkout HEAD~2 + ) && + test_must_fail test -f "$GIT_REPO"/2/.gitignore && + test_must_fail test -f "$GIT_REPO"/3/.gitignore +' + +# After re-cloning the repository with --placeholder-file specified, there +# should be 5 files named ".placeholder" in the local Git repo. +test_expect_success 'clone svn repo with --placeholder-file specified' ' + rm -rf "$GIT_REPO" && + git svn clone "$svnrepo"/trunk --preserve-empty-dirs \ + --placeholder-file=.placeholder "$GIT_REPO" && + find "$GIT_REPO" -type f -name ".placeholder" && + test $(find "$GIT_REPO" -type f -name ".placeholder" | wc -l) = "5" +' + +# "$GIT_REPO"/5/.placeholder should be a file, and non-empty. +test_expect_success 'placeholder namespace conflict with file' ' + test -s "$GIT_REPO"/5/.placeholder +' + +# "$GIT_REPO"/6/.placeholder should be a directory, and the "$GIT_REPO"/6 tree +# should only contain one file: the placeholder. +test_expect_success 'placeholder namespace conflict with directory' ' + test -d "$GIT_REPO"/6/.placeholder && + test -f "$GIT_REPO"/6/.placeholder/.placeholder && + test $(find "$GIT_REPO"/6 -type f | wc -l) = "1" +' + +# Prepare a second set of svn commits to test persistence during rebase. +test_expect_success 'second set of svn commits and rebase' ' + svn_cmd co "$svnrepo"/trunk "$SVN_TREE" && + ( + cd "$SVN_TREE" && + mkdir -p 7 && + echo "This should remove placeholder" > 1/file1.txt && + echo "This should not remove placeholder" > 5/file1.txt && + svn_cmd add 7 1/file1.txt 5/file1.txt && + svn_cmd commit -m "subsequent svn commit for persistence tests" + ) && + rm -rf "$SVN_TREE" && + ( + cd "$GIT_REPO" && + git svn rebase + ) +' + +# Check that --preserve-empty-dirs and --placeholder-file flag state +# stays persistent over multiple invocations. +test_expect_success 'flag persistence during subsqeuent rebase' ' + test -f "$GIT_REPO"/7/.placeholder && + test $(find "$GIT_REPO"/7 -type f | wc -l) = "1" +' + +# Check that placeholder files are properly removed when unnecessary, +# even across multiple invocations. +test_expect_success 'placeholder list persistence during subsqeuent rebase' ' + test -f "$GIT_REPO"/1/file1.txt && + test $(find "$GIT_REPO"/1 -type f | wc -l) = "1" && + + test -f "$GIT_REPO"/5/file1.txt && + test -f "$GIT_REPO"/5/.placeholder && + test $(find "$GIT_REPO"/5 -type f | wc -l) = "2" +' + +test_done diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh new file mode 100755 index 0000000000..6ef0c0bde3 --- /dev/null +++ b/t/t9161-git-svn-mergeinfo-push.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# +# Portions copyright (c) 2007, 2009 Sam Vilain +# Portions copyright (c) 2011 Bryan Jacobs +# + +test_description='git-svn svn mergeinfo propagation' + +. ./lib-git-svn.sh + +test_expect_success 'load svn dump' " + svnadmin load -q '$rawsvnrepo' \ + < '$TEST_DIRECTORY/t9161/branches.dump' && + git svn init --minimize-url -R svnmerge \ + -T trunk -b branches '$svnrepo' && + git svn fetch --all + " + +test_expect_success 'propagate merge information' ' + git config svn.pushmergeinfo yes && + git checkout svnb1 && + git merge --no-ff svnb2 && + git svn dcommit + ' + +test_expect_success 'check svn:mergeinfo' ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) + test "$mergeinfo" = "/branches/svnb2:3,8" + ' + +test_expect_success 'merge another branch' ' + git merge --no-ff svnb3 && + git svn dcommit + ' + +test_expect_success 'check primary parent mergeinfo respected' ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) + test "$mergeinfo" = "/branches/svnb2:3,8 +/branches/svnb3:4,9" + ' + +test_expect_success 'merge existing merge' ' + git merge --no-ff svnb4 && + git svn dcommit + ' + +test_expect_success "check both parents' mergeinfo respected" ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) + test "$mergeinfo" = "/branches/svnb2:3,8 +/branches/svnb3:4,9 +/branches/svnb4:5-6,10-12 +/branches/svnb5:6,11" + ' + +test_expect_success 'make further commits to branch' ' + git checkout svnb2 && + touch newb2file && + git add newb2file && + git commit -m "later b2 commit" && + touch newb2file-2 && + git add newb2file-2 && + git commit -m "later b2 commit 2" && + git svn dcommit + ' + +test_expect_success 'second forward merge' ' + git checkout svnb1 && + git merge --no-ff svnb2 && + git svn dcommit + ' + +test_expect_success 'check new mergeinfo added' ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1) + test "$mergeinfo" = "/branches/svnb2:3,8,16-17 +/branches/svnb3:4,9 +/branches/svnb4:5-6,10-12 +/branches/svnb5:6,11" + ' + +test_expect_success 'reintegration merge' ' + git checkout svnb4 && + git merge --no-ff svnb1 && + git svn dcommit + ' + +test_expect_success 'check reintegration mergeinfo' ' + mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb4) + test "$mergeinfo" = "/branches/svnb1:2-4,7-9,13-18 +/branches/svnb2:3,8,16-17 +/branches/svnb3:4,9 +/branches/svnb4:5-6,10-12 +/branches/svnb5:6,11" + ' + +test_expect_success 'dcommit a merge at the top of a stack' ' + git checkout svnb1 && + touch anotherfile && + git add anotherfile && + git commit -m "a commit" && + git merge svnb4 && + git svn dcommit + ' + +test_done diff --git a/t/t9161/branches.dump b/t/t9161/branches.dump new file mode 100644 index 0000000000..e61c3e7236 --- /dev/null +++ b/t/t9161/branches.dump @@ -0,0 +1,374 @@ +SVN-fs-dump-format-version: 2 + +UUID: 1ef08553-f2d1-45df-b38c-19af6b7c926d + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2011-09-02T16:08:02.941384Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 114 +Content-length: 114 + +K 7 +svn:log +V 12 +Base commit + +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:08:27.205062Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 19 +Create branch svnb1 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:09:43.628137Z +PROPS-END + +Node-path: branches/svnb1 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 3 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 19 +Create branch svnb2 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:09:46.339930Z +PROPS-END + +Node-path: branches/svnb2 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 4 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 19 +Create branch svnb3 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:09:49.394515Z +PROPS-END + +Node-path: branches/svnb3 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 5 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 19 +Create branch svnb4 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:09:54.114607Z +PROPS-END + +Node-path: branches/svnb4 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 6 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 19 +Create branch svnb5 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:09:58.602623Z +PROPS-END + +Node-path: branches/svnb5 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 7 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +b1 commit +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:10:20.292369Z +PROPS-END + +Node-path: branches/svnb1/b1file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + +Revision-number: 8 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +b2 commit +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:10:38.429199Z +PROPS-END + +Node-path: branches/svnb2/b2file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + +Revision-number: 9 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +b3 commit +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:10:52.843023Z +PROPS-END + +Node-path: branches/svnb3/b3file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + +Revision-number: 10 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +b4 commit +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:11:17.489870Z +PROPS-END + +Node-path: branches/svnb4/b4file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + +Revision-number: 11 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +b5 commit +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:11:32.277404Z +PROPS-END + +Node-path: branches/svnb5/b5file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + +Revision-number: 12 +Prop-content-length: 192 +Content-length: 192 + +K 7 +svn:log +V 90 +Merge remote-tracking branch 'svnb5' into HEAD + +* svnb5: + b5 commit + Create branch svnb5 +K 10 +svn:author +V 7 +bjacobs +K 8 +svn:date +V 27 +2011-09-02T16:11:54.274722Z +PROPS-END + +Node-path: branches/svnb4 +Node-kind: dir +Node-action: change +Prop-content-length: 56 +Content-length: 56 + +K 13 +svn:mergeinfo +V 21 +/branches/svnb5:6,11 + +PROPS-END + + +Node-path: branches/svnb4/b5file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Content-length: 10 + +PROPS-END + + diff --git a/t/t9162-git-svn-dcommit-interactive.sh b/t/t9162-git-svn-dcommit-interactive.sh new file mode 100755 index 0000000000..e38d9fa37b --- /dev/null +++ b/t/t9162-git-svn-dcommit-interactive.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Copyright (c) 2011 Frédéric Heitzmann + +test_description='git svn dcommit --interactive series' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' ' + svn_cmd mkdir -m"mkdir test-interactive" "$svnrepo/test-interactive" && + git svn clone "$svnrepo/test-interactive" test-interactive && + cd test-interactive && + touch foo && git add foo && git commit -m"foo: first commit" && + git svn dcommit + ' + +test_expect_success 'answers: y [\n] yes' ' + ( + echo "change #1" >> foo && git commit -a -m"change #1" && + echo "change #2" >> foo && git commit -a -m"change #2" && + echo "change #3" >> foo && git commit -a -m"change #3" && + ( echo "y + +y" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) && + test $(git rev-parse HEAD) = $(git rev-parse remotes/git-svn) + ) + ' + +test_expect_success 'answers: yes yes no' ' + ( + echo "change #1" >> foo && git commit -a -m"change #1" && + echo "change #2" >> foo && git commit -a -m"change #2" && + echo "change #3" >> foo && git commit -a -m"change #3" && + ( echo "yes +yes +no" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) && + test $(git rev-parse HEAD^^^) = $(git rev-parse remotes/git-svn) && + git reset --hard remotes/git-svn + ) + ' + +test_expect_success 'answers: yes quit' ' + ( + echo "change #1" >> foo && git commit -a -m"change #1" && + echo "change #2" >> foo && git commit -a -m"change #2" && + echo "change #3" >> foo && git commit -a -m"change #3" && + ( echo "yes +quit" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) && + test $(git rev-parse HEAD^^^) = $(git rev-parse remotes/git-svn) && + git reset --hard remotes/git-svn + ) + ' + +test_expect_success 'answers: all' ' + ( + echo "change #1" >> foo && git commit -a -m"change #1" && + echo "change #2" >> foo && git commit -a -m"change #2" && + echo "change #3" >> foo && git commit -a -m"change #3" && + ( echo "all" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) && + test $(git rev-parse HEAD) = $(git rev-parse remotes/git-svn) && + git reset --hard remotes/git-svn + ) + ' + +test_done diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index e5da65b99f..41db05cb4a 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -50,8 +50,8 @@ test_expect_success \ 'mkdir A B C D E F && echo hello1 >A/newfile1.txt && echo hello2 >B/newfile2.txt && - cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png && - cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png && + cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png && git add A/newfile1.txt && git add B/newfile2.txt && git add C/newfile3.png && @@ -76,8 +76,8 @@ test_expect_success \ rm -f B/newfile2.txt && rm -f C/newfile3.png && echo Hello5 >E/newfile5.txt && - cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png && - cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png && + cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png && git add E/newfile5.txt && git add F/newfile6.png && git commit -a -m "Test: Remove, add and update" && @@ -165,7 +165,7 @@ test_expect_success \ 'mkdir "G g" && echo ok then >"G g/with spaces.txt" && git add "G g/with spaces.txt" && \ - cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \ + cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "With spaces" && id=$(git rev-list --max-count=1 HEAD) && @@ -177,7 +177,7 @@ test_expect_success \ test_expect_success \ 'Update file with spaces in file name' \ 'echo Ok then >>"G g/with spaces.txt" && - cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \ + cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "Update with spaces" && id=$(git rev-list --max-count=1 HEAD) && @@ -202,7 +202,7 @@ test_expect_success \ 'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö && echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && - cp "$TEST_DIRECTORY"/test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && + cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && git commit -a -m "Går det så går det" && \ id=$(git rev-list --max-count=1 HEAD) && diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 986bc14d58..438aaf6b14 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -42,6 +42,14 @@ echo "$@"' >empty +test_expect_success 'setup: have pipes?' ' + rm -f frob && + if mkfifo frob + then + test_set_prereq PIPE + fi +' + ### ### series A ### @@ -86,6 +94,12 @@ data <<EOF An annotated tag without a tagger EOF +tag series-A-blob +from :3 +data <<EOF +An annotated tag that annotates a blob. +EOF + INPUT_END test_expect_success \ 'A: create pack from stdin' \ @@ -144,6 +158,18 @@ test_expect_success 'A: verify tag/series-A' ' ' cat >expect <<EOF +object $(git rev-parse refs/heads/master:file3) +type blob +tag series-A-blob + +An annotated tag that annotates a blob. +EOF +test_expect_success 'A: verify tag/series-A-blob' ' + git cat-file tag tags/series-A-blob >actual && + test_cmp expect actual +' + +cat >expect <<EOF :2 `git rev-parse --verify master:file2` :3 `git rev-parse --verify master:file3` :4 `git rev-parse --verify master:file4` @@ -162,6 +188,55 @@ test_expect_success \ test_cmp expect marks.new' test_tick +new_blob=$(echo testing | git hash-object --stdin) +cat >input <<INPUT_END +tag series-A-blob-2 +from $(git rev-parse refs/heads/master:file3) +data <<EOF +Tag blob by sha1. +EOF + +blob +mark :6 +data <<EOF +testing +EOF + +commit refs/heads/new_blob +committer <> 0 +0000 +data 0 +M 644 :6 new_blob +#pretend we got sha1 from fast-import +ls "new_blob" + +tag series-A-blob-3 +from $new_blob +data <<EOF +Tag new_blob. +EOF +INPUT_END + +cat >expect <<EOF +object $(git rev-parse refs/heads/master:file3) +type blob +tag series-A-blob-2 + +Tag blob by sha1. +object $new_blob +type blob +tag series-A-blob-3 + +Tag new_blob. +EOF + +test_expect_success \ + 'A: tag blob by sha1' \ + 'git fast-import <input && + git cat-file tag tags/series-A-blob-2 >actual && + git cat-file tag tags/series-A-blob-3 >>actual && + test_cmp expect actual' + +test_tick cat >input <<INPUT_END commit refs/heads/verify--import-marks committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -316,6 +391,105 @@ test_expect_success \ test `git rev-parse master` = `git rev-parse TEMP_TAG^`' rm -f .git/TEMP_TAG +git gc 2>/dev/null >/dev/null +git prune 2>/dev/null >/dev/null + +cat >input <<INPUT_END +commit refs/heads/empty-committer-1 +committer <> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: accept empty committer' ' + git fast-import <input && + out=$(git fsck) && + echo "$out" && + test -z "$out" +' +git update-ref -d refs/heads/empty-committer-1 || true + +git gc 2>/dev/null >/dev/null +git prune 2>/dev/null >/dev/null + +cat >input <<INPUT_END +commit refs/heads/empty-committer-2 +committer <a@b.com> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: accept and fixup committer with no name' ' + git fast-import <input && + out=$(git fsck) && + echo "$out" && + test -z "$out" +' +git update-ref -d refs/heads/empty-committer-2 || true + +git gc 2>/dev/null >/dev/null +git prune 2>/dev/null >/dev/null + +cat >input <<INPUT_END +commit refs/heads/invalid-committer +committer Name email> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: fail on invalid committer (1)' ' + test_must_fail git fast-import <input +' +git update-ref -d refs/heads/invalid-committer || true + +cat >input <<INPUT_END +commit refs/heads/invalid-committer +committer Name <e<mail> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: fail on invalid committer (2)' ' + test_must_fail git fast-import <input +' +git update-ref -d refs/heads/invalid-committer || true + +cat >input <<INPUT_END +commit refs/heads/invalid-committer +committer Name <email>> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: fail on invalid committer (3)' ' + test_must_fail git fast-import <input +' +git update-ref -d refs/heads/invalid-committer || true + +cat >input <<INPUT_END +commit refs/heads/invalid-committer +committer Name <email $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: fail on invalid committer (4)' ' + test_must_fail git fast-import <input +' +git update-ref -d refs/heads/invalid-committer || true + +cat >input <<INPUT_END +commit refs/heads/invalid-committer +committer Name<email> $GIT_COMMITTER_DATE +data <<COMMIT +empty commit +COMMIT +INPUT_END +test_expect_success 'B: fail on invalid committer (5)' ' + test_must_fail git fast-import <input +' +git update-ref -d refs/heads/invalid-committer || true + ### ### series C ### @@ -646,6 +820,18 @@ test_expect_success \ 'test 1 = `git rev-list J | wc -l` && test 0 = `git ls-tree J | wc -l`' +cat >input <<INPUT_END +reset refs/heads/J2 + +tag wrong_tag +from refs/heads/J2 +data <<EOF +Tag branch that was reset. +EOF +INPUT_END +test_expect_success \ + 'J: tag must fail on empty branch' \ + 'test_must_fail git fast-import <input' ### ### series K ### @@ -726,6 +912,47 @@ test_expect_success \ git diff-tree --abbrev --raw L^ L >output && test_cmp expect output' +cat >input <<INPUT_END +blob +mark :1 +data <<EOF +the data +EOF + +commit refs/heads/L2 +committer C O Mitter <committer@example.com> 1112912473 -0700 +data <<COMMIT +init L2 +COMMIT +M 644 :1 a/b/c +M 644 :1 a/b/d +M 644 :1 a/e/f + +commit refs/heads/L2 +committer C O Mitter <committer@example.com> 1112912473 -0700 +data <<COMMIT +update L2 +COMMIT +C a g +C a/e g/b +M 644 :1 g/b/h +INPUT_END + +cat <<EOF >expect +g/b/f +g/b/h +EOF + +test_expect_success \ + 'L: nested tree copy does not corrupt deltas' \ + 'git fast-import <input && + git ls-tree L2 g/b/ >tmp && + cat tmp | cut -f 2 >actual && + test_cmp expect actual && + git fsck `git rev-parse L2`' + +git update-ref -d refs/heads/L2 + ### ### series M ### @@ -898,6 +1125,77 @@ test_expect_success \ git diff-tree -C --find-copies-harder -r N4^ N4 >actual && compare_diff_raw expect actual' +test_expect_success PIPE 'N: read and copy directory' ' + cat >expect <<-\EOF + :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf + :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf + EOF + git update-ref -d refs/heads/N4 && + rm -f backflow && + mkfifo backflow && + ( + exec <backflow && + cat <<-EOF && + commit refs/heads/N4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy by tree hash, part 2 + COMMIT + + from refs/heads/branch^0 + ls "file2" + EOF + read mode type tree filename && + echo "M 040000 $tree file3" + ) | + git fast-import --cat-blob-fd=3 3>backflow && + git diff-tree -C --find-copies-harder -r N4^ N4 >actual && + compare_diff_raw expect actual +' + +test_expect_success PIPE 'N: empty directory reads as missing' ' + cat <<-\EOF >expect && + OBJNAME + :000000 100644 OBJNAME OBJNAME A unrelated + EOF + echo "missing src" >expect.response && + git update-ref -d refs/heads/read-empty && + rm -f backflow && + mkfifo backflow && + ( + exec <backflow && + cat <<-EOF && + commit refs/heads/read-empty + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + read "empty" (missing) directory + COMMIT + + M 100644 inline src/greeting + data <<BLOB + hello + BLOB + C src/greeting dst1/non-greeting + C src/greeting unrelated + # leave behind "empty" src directory + D src/greeting + ls "src" + EOF + read -r line && + printf "%s\n" "$line" >response && + cat <<-\EOF + D dst1 + D dst2 + EOF + ) | + git fast-import --cat-blob-fd=3 3>backflow && + test_cmp expect.response response && + git rev-list read-empty | + git diff-tree -r --root --stdin | + sed "s/$_x40/OBJNAME/g" >actual && + test_cmp expect actual +' + test_expect_success \ 'N: copy root directory by tree hash' \ 'cat >expect <<-\EOF && @@ -1689,6 +1987,23 @@ test_expect_success \ 'Q: verify second note for second commit' \ 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual' +cat >input <<EOF +reset refs/heads/Q0 + +commit refs/heads/note-Q0 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +Note for an empty branch. +COMMIT + +N inline refs/heads/Q0 +data <<NOTE +some note +NOTE +EOF +test_expect_success \ + 'Q: deny note on empty branch' \ + 'test_must_fail git fast-import <input' ### ### series R (feature and option) ### @@ -1748,6 +2063,108 @@ test_expect_success \ 'cat input | git fast-import --export-marks=other.marks && grep :1 other.marks' +test_expect_success 'R: catch typo in marks file name' ' + test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null && + echo "feature import-marks=nonexistent.marks" | + test_must_fail git fast-import +' + +test_expect_success 'R: import and output marks can be the same file' ' + rm -f io.marks && + blob=$(echo hi | git hash-object --stdin) && + cat >expect <<-EOF && + :1 $blob + :2 $blob + EOF + git fast-import --export-marks=io.marks <<-\EOF && + blob + mark :1 + data 3 + hi + + EOF + git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF && + blob + mark :2 + data 3 + hi + + EOF + test_cmp expect io.marks +' + +test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' ' + rm -f io.marks && + test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF + blob + mark :1 + data 3 + hi + + EOF +' + +test_expect_success 'R: --import-marks-if-exists' ' + rm -f io.marks && + blob=$(echo hi | git hash-object --stdin) && + echo ":1 $blob" >expect && + git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF && + blob + mark :1 + data 3 + hi + + EOF + test_cmp expect io.marks +' + +test_expect_success 'R: feature import-marks-if-exists' ' + rm -f io.marks && + >expect && + + git fast-import --export-marks=io.marks <<-\EOF && + feature import-marks-if-exists=not_io.marks + EOF + test_cmp expect io.marks && + + blob=$(echo hi | git hash-object --stdin) && + + echo ":1 $blob" >io.marks && + echo ":1 $blob" >expect && + echo ":2 $blob" >>expect && + + git fast-import --export-marks=io.marks <<-\EOF && + feature import-marks-if-exists=io.marks + blob + mark :2 + data 3 + hi + + EOF + test_cmp expect io.marks && + + echo ":3 $blob" >>expect && + + git fast-import --import-marks=io.marks \ + --export-marks=io.marks <<-\EOF && + feature import-marks-if-exists=not_io.marks + blob + mark :3 + data 3 + hi + + EOF + test_cmp expect io.marks && + + >expect && + + git fast-import --import-marks-if-exists=not_io.marks \ + --export-marks=io.marks <<-\EOF + feature import-marks-if-exists=io.marks + EOF + test_cmp expect io.marks +' + cat >input << EOF feature import-marks=marks.out feature export-marks=marks.new @@ -1759,7 +2176,7 @@ test_expect_success \ test_cmp marks.out marks.new' cat >input <<EOF -feature import-marks=nonexistant.marks +feature import-marks=nonexistent.marks feature export-marks=marks.new EOF @@ -1770,7 +2187,7 @@ test_expect_success \ cat >input <<EOF -feature import-marks=nonexistant.marks +feature import-marks=nonexistent.marks feature export-marks=combined.marks EOF @@ -1806,6 +2223,11 @@ test_expect_success 'R: feature no-relative-marks should be honoured' ' test_cmp marks.new non-relative.out ' +test_expect_success 'R: feature ls supported' ' + echo "feature ls" | + git fast-import +' + test_expect_success 'R: feature cat-blob supported' ' echo "feature cat-blob" | git fast-import @@ -1815,7 +2237,7 @@ test_expect_success 'R: cat-blob-fd must be a nonnegative integer' ' test_must_fail git fast-import --cat-blob-fd=-1 </dev/null ' -test_expect_success 'R: print old blob' ' +test_expect_success NOT_MINGW 'R: print old blob' ' blob=$(echo "yes it can" | git hash-object -w --stdin) && cat >expect <<-EOF && ${blob} blob 11 @@ -1827,7 +2249,7 @@ test_expect_success 'R: print old blob' ' test_cmp expect actual ' -test_expect_success 'R: in-stream cat-blob-fd not respected' ' +test_expect_success NOT_MINGW 'R: in-stream cat-blob-fd not respected' ' echo hello >greeting && blob=$(git hash-object -w greeting) && cat >expect <<-EOF && @@ -1848,7 +2270,7 @@ test_expect_success 'R: in-stream cat-blob-fd not respected' ' test_cmp expect actual.1 ' -test_expect_success 'R: print new blob' ' +test_expect_success NOT_MINGW 'R: print new blob' ' blob=$(echo "yep yep yep" | git hash-object --stdin) && cat >expect <<-EOF && ${blob} blob 12 @@ -1866,7 +2288,7 @@ test_expect_success 'R: print new blob' ' test_cmp expect actual ' -test_expect_success 'R: print new blob by sha1' ' +test_expect_success NOT_MINGW 'R: print new blob by sha1' ' blob=$(echo "a new blob named by sha1" | git hash-object --stdin) && cat >expect <<-EOF && ${blob} blob 25 @@ -1931,14 +2353,6 @@ test_expect_success 'R: print two blobs to stdout' ' test_cmp expect actual ' -test_expect_success 'setup: have pipes?' ' - rm -f frob && - if mkfifo frob - then - test_set_prereq PIPE - fi -' - test_expect_success PIPE 'R: copy using cat-file' ' expect_id=$(git hash-object big) && expect_len=$(wc -c <big) && @@ -2066,6 +2480,48 @@ test_expect_success 'R: quiet option results in no stats being output' ' test_cmp empty output ' +test_expect_success 'R: feature done means terminating "done" is mandatory' ' + echo feature done | test_must_fail git fast-import && + test_must_fail git fast-import --done </dev/null +' + +test_expect_success 'R: terminating "done" with trailing gibberish is ok' ' + git fast-import <<-\EOF && + feature done + done + trailing gibberish + EOF + git fast-import <<-\EOF + done + more trailing gibberish + EOF +' + +test_expect_success 'R: terminating "done" within commit' ' + cat >expect <<-\EOF && + OBJID + :000000 100644 OBJID OBJID A hello.c + :000000 100644 OBJID OBJID A hello2.c + EOF + git fast-import <<-EOF && + commit refs/heads/done-ends + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<EOT + Commit terminated by "done" command + EOT + M 100644 inline hello.c + data <<EOT + Hello, world. + EOT + C hello.c hello2.c + done + EOF + git rev-list done-ends | + git diff-tree -r --stdin --root --always | + sed -e "s/$_x40/OBJID/g" >actual && + test_cmp expect actual +' + cat >input <<EOF option git non-existing-option EOF diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index 7cf8cd8a2f..463254c727 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -120,6 +120,7 @@ test_expect_success 'add notes with simple M command' ' test_tick cat >input <<INPUT_END +feature notes commit refs/notes/test committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE data <<COMMIT diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index f823c05305..950d0ff498 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -228,7 +228,7 @@ test_expect_success 'fast-export -C -C | fast-import' ' mkdir new && git --git-dir=new/.git init && git fast-export -C -C --signed-tags=strip --all > output && - grep "^C \"file6\" \"file7\"\$" output && + grep "^C file6 file7\$" output && cat output | (cd new && git fast-import && @@ -414,4 +414,30 @@ test_expect_success SYMLINKS 'directory becomes symlink' ' (cd result && git show master:foo) ' +test_expect_success 'fast-export quotes pathnames' ' + git init crazy-paths && + (cd crazy-paths && + blob=`echo foo | git hash-object -w --stdin` && + git update-index --add \ + --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \ + --cacheinfo 100644 $blob "path with \"quote\"" \ + --cacheinfo 100644 $blob "path with \\backslash" \ + --cacheinfo 100644 $blob "path with space" && + git commit -m addition && + git ls-files -z -s | perl -0pe "s{\\t}{$&subdir/}" >index && + git read-tree --empty && + git update-index -z --index-info <index && + git commit -m rename && + git read-tree --empty && + git commit -m deletion && + git fast-export HEAD >export.out && + git rev-list HEAD >expect && + git init result && + cd result && + git fast-import <../export.out && + git rev-list HEAD >actual && + test_cmp ../expect actual + ) +' + test_done diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 21cd286bb7..53297156a3 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -18,42 +18,34 @@ or warnings to log.' test_expect_success \ 'no commits: projects_list (implicit)' \ 'gitweb_run' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: projects_index' \ 'gitweb_run "a=project_index"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git summary (implicit)' \ 'gitweb_run "p=.git"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git commit (implicit HEAD)' \ 'gitweb_run "p=.git;a=commit"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git commitdiff (implicit HEAD)' \ 'gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git tree (implicit HEAD)' \ 'gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git heads' \ 'gitweb_run "p=.git;a=heads"' -test_debug 'cat gitweb.log' test_expect_success \ 'no commits: .git tags' \ 'gitweb_run "p=.git;a=tags"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- @@ -69,52 +61,42 @@ test_expect_success \ test_expect_success \ 'projects_list (implicit)' \ 'gitweb_run' -test_debug 'cat gitweb.log' test_expect_success \ 'projects_index' \ 'gitweb_run "a=project_index"' -test_debug 'cat gitweb.log' test_expect_success \ '.git summary (implicit)' \ 'gitweb_run "p=.git"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commit (implicit HEAD)' \ 'gitweb_run "p=.git;a=commit"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commitdiff (implicit HEAD, root commit)' \ 'gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commitdiff_plain (implicit HEAD, root commit)' \ 'gitweb_run "p=.git;a=commitdiff_plain"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commit (HEAD)' \ 'gitweb_run "p=.git;a=commit;h=HEAD"' -test_debug 'cat gitweb.log' test_expect_success \ '.git tree (implicit HEAD)' \ 'gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' test_expect_success \ '.git blob (file)' \ 'gitweb_run "p=.git;a=blob;f=file"' -test_debug 'cat gitweb.log' test_expect_success \ '.git blob_plain (file)' \ 'gitweb_run "p=.git;a=blob_plain;f=file"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # nonexistent objects @@ -122,37 +104,30 @@ test_debug 'cat gitweb.log' test_expect_success \ '.git commit (non-existent)' \ 'gitweb_run "p=.git;a=commit;h=non-existent"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commitdiff (non-existent)' \ 'gitweb_run "p=.git;a=commitdiff;h=non-existent"' -test_debug 'cat gitweb.log' test_expect_success \ '.git commitdiff (non-existent vs HEAD)' \ 'gitweb_run "p=.git;a=commitdiff;hp=non-existent;h=HEAD"' -test_debug 'cat gitweb.log' test_expect_success \ '.git tree (0000000000000000000000000000000000000000)' \ 'gitweb_run "p=.git;a=tree;h=0000000000000000000000000000000000000000"' -test_debug 'cat gitweb.log' test_expect_success \ '.git tag (0000000000000000000000000000000000000000)' \ 'gitweb_run "p=.git;a=tag;h=0000000000000000000000000000000000000000"' -test_debug 'cat gitweb.log' test_expect_success \ '.git blob (non-existent)' \ 'gitweb_run "p=.git;a=blob;f=non-existent"' -test_debug 'cat gitweb.log' test_expect_success \ '.git blob_plain (non-existent)' \ 'gitweb_run "p=.git;a=blob_plain;f=non-existent"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- @@ -161,7 +136,6 @@ test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): root' \ 'gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): file added' \ @@ -169,21 +143,18 @@ test_expect_success \ git add new_file && git commit -a -m "File added." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): mode change' \ 'test_chmod +x new_file && git commit -a -m "Mode changed." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): file renamed' \ 'git mv new_file renamed_file && git commit -a -m "File renamed." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success SYMLINKS \ 'commitdiff(0): file to symlink' \ @@ -191,7 +162,6 @@ test_expect_success SYMLINKS \ ln -s file renamed_file && git commit -a -m "File to symlink." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): file deleted' \ @@ -199,7 +169,6 @@ test_expect_success \ rm -f renamed_file && git commit -a -m "File removed." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): file copied / new file' \ @@ -207,7 +176,6 @@ test_expect_success \ git add file2 && git commit -a -m "File copied." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): mode change and modified' \ @@ -215,7 +183,6 @@ test_expect_success \ test_chmod +x file2 && git commit -a -m "Mode change and modification." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): renamed and modified' \ @@ -233,7 +200,6 @@ EOF echo "Propter nomen suum." >> file3 && git commit -a -m "File rename and modification." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): renamed, mode change and modified' \ @@ -242,7 +208,6 @@ test_expect_success \ test_chmod +x file2 && git commit -a -m "File rename, mode change and modification." && gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # commitdiff testing (taken from t4114-apply-typechange.sh) @@ -279,42 +244,34 @@ test_expect_success SYMLINKS 'setup typechange commits' ' test_expect_success \ 'commitdiff(2): file renamed from foo to foo/baz' \ 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-baz-renamed-from-foo"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): file renamed from foo/baz to foo' \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-baz-renamed-from-foo;h=initial"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): directory becomes file' \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=initial"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): file becomes directory' \ 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-becomes-a-directory"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): file becomes symlink' \ 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-symlinked-to-bar"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): symlink becomes file' \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-back-to-file"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): symlink becomes directory' \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-becomes-a-directory"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(2): directory becomes symlink' \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=foo-symlinked-to-bar"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # commit, commitdiff: merge, large @@ -330,12 +287,10 @@ test_expect_success \ test_expect_success \ 'commit(0): merge commit' \ 'gitweb_run "p=.git;a=commit"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): merge commit' \ 'gitweb_run "p=.git;a=commitdiff"' -test_debug 'cat gitweb.log' test_expect_success \ 'Prepare large commit' \ @@ -371,12 +326,10 @@ test_expect_success \ test_expect_success \ 'commit(1): large commit' \ 'gitweb_run "p=.git;a=commit;h=b"' -test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(1): large commit' \ 'gitweb_run "p=.git;a=commitdiff;h=b"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # tags testing @@ -394,17 +347,14 @@ test_expect_success \ git tag lightweight/tag-tree HEAD^{tree} && git tag lightweight/tag-blob HEAD:file && gitweb_run "p=.git;a=tags"' -test_debug 'cat gitweb.log' test_expect_success \ 'tag: Tag to commit object' \ 'gitweb_run "p=.git;a=tag;h=tag-commit"' -test_debug 'cat gitweb.log' test_expect_success \ 'tag: on lightweight tag (invalid)' \ 'gitweb_run "p=.git;a=tag;h=lightweight/tag-commit"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # logs @@ -412,22 +362,18 @@ test_debug 'cat gitweb.log' test_expect_success \ 'logs: log (implicit HEAD)' \ 'gitweb_run "p=.git;a=log"' -test_debug 'cat gitweb.log' test_expect_success \ 'logs: shortlog (implicit HEAD)' \ 'gitweb_run "p=.git;a=shortlog"' -test_debug 'cat gitweb.log' test_expect_success \ 'logs: history (implicit HEAD, file)' \ 'gitweb_run "p=.git;a=history;f=file"' -test_debug 'cat gitweb.log' test_expect_success \ 'logs: history (implicit HEAD, non-existent file)' \ 'gitweb_run "p=.git;a=history;f=non-existent"' -test_debug 'cat gitweb.log' test_expect_success \ 'logs: history (implicit HEAD, deleted file)' \ @@ -438,55 +384,45 @@ test_expect_success \ git rm deleted_file && git commit -m "Delete file" && gitweb_run "p=.git;a=history;f=deleted_file"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # path_info links test_expect_success \ 'path_info: project' \ 'gitweb_run "" "/.git"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch' \ 'gitweb_run "" "/.git/b"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch:file' \ 'gitweb_run "" "/.git/master:file"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch:dir/' \ 'gitweb_run "" "/.git/master:foo/"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch:file (non-existent)' \ 'gitweb_run "" "/.git/master:non-existent"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch:dir/ (non-existent)' \ 'gitweb_run "" "/.git/master:non-existent/"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/branch:/file' \ 'gitweb_run "" "/.git/master:/file"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/:/file (implicit HEAD)' \ 'gitweb_run "" "/.git/:/file"' -test_debug 'cat gitweb.log' test_expect_success \ 'path_info: project/:/ (implicit HEAD, top tree)' \ 'gitweb_run "" "/.git/:/"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- @@ -495,17 +431,14 @@ test_debug 'cat gitweb.log' test_expect_success \ 'feeds: OPML' \ 'gitweb_run "a=opml"' -test_debug 'cat gitweb.log' test_expect_success \ 'feed: RSS' \ 'gitweb_run "p=.git;a=rss"' -test_debug 'cat gitweb.log' test_expect_success \ 'feed: Atom' \ 'gitweb_run "p=.git;a=atom"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # encoding/decoding @@ -513,27 +446,28 @@ test_debug 'cat gitweb.log' test_expect_success \ 'encode(commit): utf8' \ '. "$TEST_DIRECTORY"/t3901-utf8.txt && + test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" && + test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" && echo "UTF-8" >> file && git add file && git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt && gitweb_run "p=.git;a=commit"' -test_debug 'cat gitweb.log' test_expect_success \ 'encode(commit): iso-8859-1' \ '. "$TEST_DIRECTORY"/t3901-8859-1.txt && + test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" && + test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" && echo "ISO-8859-1" >> file && git add file && git config i18n.commitencoding ISO-8859-1 && + test_when_finished "git config --unset i18n.commitencoding" && git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt && - git config --unset i18n.commitencoding && gitweb_run "p=.git;a=commit"' -test_debug 'cat gitweb.log' test_expect_success \ 'encode(log): utf-8 and iso-8859-1' \ 'gitweb_run "p=.git;a=log"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # extra options @@ -541,27 +475,22 @@ test_debug 'cat gitweb.log' test_expect_success \ 'opt: log --no-merges' \ 'gitweb_run "p=.git;a=log;opt=--no-merges"' -test_debug 'cat gitweb.log' test_expect_success \ 'opt: atom --no-merges' \ 'gitweb_run "p=.git;a=log;opt=--no-merges"' -test_debug 'cat gitweb.log' test_expect_success \ 'opt: "file" history --no-merges' \ 'gitweb_run "p=.git;a=history;f=file;opt=--no-merges"' -test_debug 'cat gitweb.log' test_expect_success \ 'opt: log --no-such-option (invalid option)' \ 'gitweb_run "p=.git;a=log;opt=--no-such-option"' -test_debug 'cat gitweb.log' test_expect_success \ 'opt: tree --no-merges (invalid option for action)' \ 'gitweb_run "p=.git;a=tree;opt=--no-merges"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # testing config_to_multi / cloneurl @@ -569,14 +498,12 @@ test_debug 'cat gitweb.log' test_expect_success \ 'URL: no project URLs, no base URL' \ 'gitweb_run "p=.git;a=summary"' -test_debug 'cat gitweb.log' test_expect_success \ 'URL: project URLs via gitweb.url' \ 'git config --add gitweb.url git://example.com/git/trash.git && git config --add gitweb.url http://example.com/git/trash.git && gitweb_run "p=.git;a=summary"' -test_debug 'cat gitweb.log' cat >.git/cloneurl <<\EOF git://example.com/git/trash.git @@ -586,7 +513,6 @@ EOF test_expect_success \ 'URL: project URLs via cloneurl file' \ 'gitweb_run "p=.git;a=summary"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # gitweb config and repo config @@ -604,12 +530,10 @@ EOF test_expect_success \ 'config override: projects list (implicit)' \ 'gitweb_run' -test_debug 'cat gitweb.log' test_expect_success \ 'config override: tree view, features not overridden in repo config' \ 'gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' test_expect_success \ 'config override: tree view, features disabled in repo config' \ @@ -617,14 +541,12 @@ test_expect_success \ git config gitweb.snapshot none && git config gitweb.avatar gravatar && gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' test_expect_success \ 'config override: tree view, features enabled in repo config (1)' \ 'git config gitweb.blame yes && git config gitweb.snapshot "zip,tgz, tbz2" && gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' cat >.git/config <<\EOF # testing noval and alternate separator @@ -635,7 +557,6 @@ EOF test_expect_success \ 'config override: tree view, features enabled in repo config (2)' \ 'gitweb_run "p=.git;a=tree"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # non-ASCII in README.html @@ -645,7 +566,6 @@ test_expect_success \ 'echo "<b>UTF-8 example:</b><br />" > .git/README.html && cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html && gitweb_run "p=.git;a=summary"' -test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # syntax highlighting @@ -666,7 +586,6 @@ test_expect_success HIGHLIGHT \ 'syntax highlighting (no highlight, unknown syntax)' \ 'git config gitweb.highlight yes && gitweb_run "p=.git;a=blob;f=file"' -test_debug 'cat gitweb.log' test_expect_success HIGHLIGHT \ 'syntax highlighting (highlighted, shell script)' \ @@ -675,6 +594,70 @@ test_expect_success HIGHLIGHT \ git add test.sh && git commit -m "Add test.sh" && gitweb_run "p=.git;a=blob;f=test.sh"' -test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# forks of projects + +cat >>gitweb_config.perl <<\EOF && +$feature{'forks'}{'default'} = [1]; +EOF + +test_expect_success \ + 'forks: prepare' \ + 'git init --bare foo.git && + git --git-dir=foo.git --work-tree=. add file && + git --git-dir=foo.git --work-tree=. commit -m "Initial commit" && + echo "foo" > foo.git/description && + mkdir -p foo && + (cd foo && + git clone --shared --bare ../foo.git foo-forked.git && + echo "fork of foo" > foo-forked.git/description)' + +test_expect_success \ + 'forks: projects list' \ + 'gitweb_run' + +test_expect_success \ + 'forks: forks action' \ + 'gitweb_run "p=foo.git;a=forks"' + +# ---------------------------------------------------------------------- +# content tags (tag cloud) + +cat >>gitweb_config.perl <<-\EOF && +# we don't test _setting_ content tags, so any true value is good +$feature{'ctags'}{'default'} = ['ctags_script.cgi']; +EOF + +test_expect_success \ + 'ctags: tag cloud in projects list' \ + 'mkdir .git/ctags && + echo "2" > .git/ctags/foo && + echo "1" > .git/ctags/bar && + gitweb_run' + +test_expect_success \ + 'ctags: search projects by existing tag' \ + 'gitweb_run "by_tag=foo"' + +test_expect_success \ + 'ctags: search projects by non existent tag' \ + 'gitweb_run "by_tag=non-existent"' + +test_expect_success \ + 'ctags: malformed tag weights' \ + 'mkdir -p .git/ctags && + echo "not-a-number" > .git/ctags/nan && + echo "not-a-number-2" > .git/ctags/nan2 && + echo "0.1" >.git/ctags/floating-point && + gitweb_run' + +# ---------------------------------------------------------------------- +# categories + +test_expect_success \ + 'categories: projects list, only default category' \ + 'echo "\$projects_list_group_categories = 1;" >>gitweb_config.perl && + gitweb_run' test_done diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh index 18825aff89..26102ee9b0 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -126,7 +126,6 @@ test_expect_success 'load checking: load too high (default action)' ' grep "Status: 503 Service Unavailable" gitweb.headers && grep "503 - The load average on the server is too high" gitweb.body ' -test_debug 'cat gitweb.log' # just in case test_debug 'cat gitweb.headers' # turn off load checking diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh index dd83890001..731e64c3ad 100755 --- a/t/t9502-gitweb-standalone-parse-output.sh +++ b/t/t9502-gitweb-standalone-parse-output.sh @@ -112,4 +112,78 @@ test_expect_success 'snapshot: hierarchical branch name (xx/test)' ' ' test_debug 'cat gitweb.headers' +# ---------------------------------------------------------------------- +# forks of projects + +test_expect_success 'forks: setup' ' + git init --bare foo.git && + echo file > file && + git --git-dir=foo.git --work-tree=. add file && + git --git-dir=foo.git --work-tree=. commit -m "Initial commit" && + echo "foo" > foo.git/description && + git clone --bare foo.git foo.bar.git && + echo "foo.bar" > foo.bar.git/description && + git clone --bare foo.git foo_baz.git && + echo "foo_baz" > foo_baz.git/description && + rm -fr foo && + mkdir -p foo && + ( + cd foo && + git clone --shared --bare ../foo.git foo-forked.git && + echo "fork of foo" > foo-forked.git/description + ) +' + +test_expect_success 'forks: not skipped unless "forks" feature enabled' ' + gitweb_run "a=project_list" && + grep -q ">\\.git<" gitweb.body && + grep -q ">foo\\.git<" gitweb.body && + grep -q ">foo_baz\\.git<" gitweb.body && + grep -q ">foo\\.bar\\.git<" gitweb.body && + grep -q ">foo_baz\\.git<" gitweb.body && + grep -q ">foo/foo-forked\\.git<" gitweb.body && + grep -q ">fork of .*<" gitweb.body +' + +cat >>gitweb_config.perl <<\EOF && +$feature{'forks'}{'default'} = [1]; +EOF + +test_expect_success 'forks: forks skipped if "forks" feature enabled' ' + gitweb_run "a=project_list" && + grep -q ">\\.git<" gitweb.body && + grep -q ">foo\\.git<" gitweb.body && + grep -q ">foo_baz\\.git<" gitweb.body && + grep -q ">foo\\.bar\\.git<" gitweb.body && + grep -q ">foo_baz\\.git<" gitweb.body && + grep -v ">foo/foo-forked\\.git<" gitweb.body && + grep -v ">fork of .*<" gitweb.body +' + +test_expect_success 'forks: "forks" action for forked repository' ' + gitweb_run "p=foo.git;a=forks" && + grep -q ">foo/foo-forked\\.git<" gitweb.body && + grep -q ">fork of foo<" gitweb.body +' + +test_expect_success 'forks: can access forked repository' ' + gitweb_run "p=foo/foo-forked.git;a=summary" && + grep -q "200 OK" gitweb.headers && + grep -q ">fork of foo<" gitweb.body +' + +test_expect_success 'forks: project_index lists all projects (incl. forks)' ' + cat >expected <<-\EOF + .git + foo.bar.git + foo.git + foo/foo-forked.git + foo_baz.git + EOF + gitweb_run "a=project_index" && + sed -e "s/ .*//" <gitweb.body | sort >actual && + test_cmp expected actual +' + + test_done diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh index 3787186703..435d896476 100755 --- a/t/t9700-perl-git.sh +++ b/t/t9700-perl-git.sh @@ -43,7 +43,11 @@ test_expect_success \ git config --add test.booltrue true && git config --add test.boolfalse no && git config --add test.boolother other && - git config --add test.int 2k + git config --add test.int 2k && + git config --add test.path "~/foo" && + git config --add test.pathexpanded "$HOME/foo" && + git config --add test.pathmulti foo && + git config --add test.pathmulti bar ' # The external test will outputs its own plan diff --git a/t/t9700/test.pl b/t/t9700/test.pl index c15ca2d647..3b9b48408a 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -33,6 +33,10 @@ 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"); +is($r->config_path("test.path"), $r->config("test.pathexpanded"), + "config_path: ~/foo expansion"); +is_deeply([$r->config_path("test.pathmulti")], ["foo", "bar"], + "config_path: multiple values"); 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 @@ -113,6 +117,16 @@ like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash'); my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.'); isnt($last_commit, $dir_commit, 'log . does not show last commit'); +# commands outside working tree +chdir($abs_repo_dir . '/..'); +my $r3 = Git->repository(Directory => $abs_repo_dir); +my $tmpfile3 = "$abs_repo_dir/file3.tmp"; +open TEMPFILE3, "+>$tmpfile3" or die "Can't open $tmpfile3: $!"; +is($r3->cat_blob($file1hash, \*TEMPFILE3), 15, "cat_blob(outside): size"); +close TEMPFILE3; +unlink $tmpfile3; +chdir($abs_repo_dir); + printf "1..%d\n", Test::More->builder->current_test; my $is_passing = eval { Test::More->is_passing }; diff --git a/t/t9800-git-p4.sh b/t/t9800-git-p4.sh new file mode 100755 index 0000000000..272de3fea3 --- /dev/null +++ b/t/t9800-git-p4.sh @@ -0,0 +1,404 @@ +#!/bin/sh + +test_description='git-p4 tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'add p4 files' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "file1" && + echo file2 >file2 && + p4 add file2 && + p4 submit -d "file2" + ) +' + +test_expect_success 'basic git-p4 clone' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline >lines && + test_line_count = 1 lines + ) +' + +test_expect_success 'git-p4 clone @all' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline >lines && + test_line_count = 2 lines + ) +' + +test_expect_success 'git-p4 sync uninitialized repo' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_must_fail "$GITP4" sync + ) +' + +# +# Create a git repo by hand. Add a commit so that HEAD is valid. +# Test imports a new p4 repository into a new git branch. +# +test_expect_success 'git-p4 sync new branch' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all && + git log --oneline p4/depot >lines && + test_line_count = 2 lines + ) +' + +test_expect_success 'exit when p4 fails to produce marshaled output' ' + badp4dir="$TRASH_DIRECTORY/badp4dir" && + mkdir "$badp4dir" && + test_when_finished "rm \"$badp4dir/p4\" && rmdir \"$badp4dir\"" && + cat >"$badp4dir"/p4 <<-EOF && + #!$SHELL_PATH + exit 1 + EOF + chmod 755 "$badp4dir"/p4 && + PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? && + test $retval -eq 1 && + test_must_fail grep -q Traceback errs +' + +test_expect_success 'add p4 files with wildcards in the names' ' + ( + cd "$cli" && + echo file-wild-hash >file-wild#hash && + echo file-wild-star >file-wild\*star && + echo file-wild-at >file-wild@at && + echo file-wild-percent >file-wild%percent && + p4 add -f file-wild* && + p4 submit -d "file wildcards" + ) +' + +test_expect_success 'wildcard files git-p4 clone' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + test -f file-wild#hash && + test -f file-wild\*star && + test -f file-wild@at && + test -f file-wild%percent + ) +' + +test_expect_success 'clone bare' ' + "$GITP4" clone --dest="$git" --bare //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + test ! -d .git && + bare=`git config --get core.bare` && + test "$bare" = true + ) +' + +p4_add_user() { + name=$1 fullname=$2 && + p4 user -f -i <<-EOF && + User: $name + Email: $name@localhost + FullName: $fullname + EOF + p4 passwd -P secret $name +} + +p4_grant_admin() { + name=$1 && + { + p4 protect -o && + echo " admin user $name * //depot/..." + } | p4 protect -i +} + +p4_check_commit_author() { + file=$1 user=$2 && + p4 changes -m 1 //depot/$file | grep -q $user +} + +make_change_by_user() { + file=$1 name=$2 email=$3 && + echo "username: a change by $name" >>"$file" && + git add "$file" && + git commit --author "$name <$email>" -m "a change by $name" +} + +# Test username support, submitting as user 'alice' +test_expect_success 'preserve users' ' + p4_add_user alice Alice && + p4_add_user bob Bob && + p4_grant_admin alice && + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + echo "username: a change by alice" >>file1 && + echo "username: a change by bob" >>file2 && + git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 && + git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 && + git config git-p4.skipSubmitEditCheck true && + P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user && + p4_check_commit_author file1 alice && + p4_check_commit_author file2 bob + ) +' + +# Test username support, submitting as bob, who lacks admin rights. Should +# not submit change to p4 (git diff should show deltas). +test_expect_success 'refuse to preserve users without perms' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo "username-noperms: a change by alice" >>file1 && + git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 && + P4EDITOR=touch P4USER=bob P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user && + test_must_fail git diff --exit-code HEAD..p4/master + ) +' + +# What happens with unknown author? Without allowMissingP4Users it should fail. +test_expect_success 'preserve user where author is unknown to p4' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo "username-bob: a change by bob" >>file1 && + git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 && + echo "username-unknown: a change by charlie" >>file1 && + git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 && + P4EDITOR=touch P4USER=alice P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user && + test_must_fail git diff --exit-code HEAD..p4/master && + + echo "$0: repeat with allowMissingP4Users enabled" && + git config git-p4.allowMissingP4Users true && + git config git-p4.preserveUser true && + P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit && + git diff --exit-code HEAD..p4/master && + p4_check_commit_author file1 alice + ) +' + +# If we're *not* using --preserve-user, git-p4 should warn if we're submitting +# changes that are not all ours. +# Test: user in p4 and user unknown to p4. +# Test: warning disabled and user is the same. +test_expect_success 'not preserving user with mixed authorship' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + p4_add_user derek Derek && + + make_change_by_user usernamefile3 Derek derek@localhost && + P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\ + grep "git author derek@localhost does not match" && + + make_change_by_user usernamefile3 Charlie charlie@localhost && + P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\ + grep "git author charlie@localhost does not match" && + + make_change_by_user usernamefile3 alice alice@localhost && + P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" |\ + test_must_fail grep "git author.*does not match" && + + git config git-p4.skipUserNameCheck true && + make_change_by_user usernamefile3 Charlie charlie@localhost && + P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\ + test_must_fail grep "git author.*does not match" && + + p4_check_commit_author usernamefile3 alice + ) +' + +marshal_dump() { + what=$1 + "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]' +} + +# Sleep a bit so that the top-most p4 change did not happen "now". Then +# import the repo and make sure that the initial import has the same time +# as the top-most change. +test_expect_success 'initial import time from top change time' ' + p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) && + p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) && + sleep 3 && + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + gittime=$(git show -s --raw --pretty=format:%at HEAD) && + echo $p4time $gittime && + test $p4time = $gittime + ) +' + +# Rename a file and confirm that rename is not detected in P4. +# Rename the new file again with detectRenames option enabled and confirm that +# this is detected in P4. +# Rename the new file again adding an extra line, configure a big threshold in +# detectRenames and confirm that rename is not detected in P4. +# Repeat, this time with a smaller threshold and confirm that the rename is +# detected in P4. +test_expect_success 'detect renames' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + + git mv file1 file4 && + git commit -a -m "Rename file1 to file4" && + git diff-tree -r -M HEAD && + "$GITP4" submit && + p4 filelog //depot/file4 && + p4 filelog //depot/file4 | test_must_fail grep -q "branch from" && + + git mv file4 file5 && + git commit -a -m "Rename file4 to file5" && + git diff-tree -r -M HEAD && + git config git-p4.detectRenames true && + "$GITP4" submit && + p4 filelog //depot/file5 && + p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && + + git mv file5 file6 && + echo update >>file6 && + git add file6 && + git commit -a -m "Rename file5 to file6 with changes" && + git diff-tree -r -M HEAD && + level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && + test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && + git config git-p4.detectRenames $(($level + 2)) && + "$GITP4" submit && + p4 filelog //depot/file6 && + p4 filelog //depot/file6 | test_must_fail grep -q "branch from" && + + git mv file6 file7 && + echo update >>file7 && + git add file7 && + git commit -a -m "Rename file6 to file7 with changes" && + git diff-tree -r -M HEAD && + level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && + test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && + git config git-p4.detectRenames $(($level - 2)) && + "$GITP4" submit && + p4 filelog //depot/file7 && + p4 filelog //depot/file7 | grep -q "branch from //depot/file6" + ) +' + +# Copy a file and confirm that copy is not detected in P4. +# Copy a file with detectCopies option enabled and confirm that copy is not +# detected in P4. +# Modify and copy a file with detectCopies option enabled and confirm that copy +# is detected in P4. +# Copy a file with detectCopies and detectCopiesHarder options enabled and +# confirm that copy is detected in P4. +# Modify and copy a file, configure a bigger threshold in detectCopies and +# confirm that copy is not detected in P4. +# Modify and copy a file, configure a smaller threshold in detectCopies and +# confirm that copy is detected in P4. +test_expect_success 'detect copies' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + + cp file2 file8 && + git add file8 && + git commit -a -m "Copy file2 to file8" && + git diff-tree -r -C HEAD && + "$GITP4" submit && + p4 filelog //depot/file8 && + p4 filelog //depot/file8 | test_must_fail grep -q "branch from" && + + cp file2 file9 && + git add file9 && + git commit -a -m "Copy file2 to file9" && + git diff-tree -r -C HEAD && + git config git-p4.detectCopies true && + "$GITP4" submit && + p4 filelog //depot/file9 && + p4 filelog //depot/file9 | test_must_fail grep -q "branch from" && + + echo "file2" >>file2 && + cp file2 file10 && + git add file2 file10 && + git commit -a -m "Modify and copy file2 to file10" && + git diff-tree -r -C HEAD && + "$GITP4" submit && + p4 filelog //depot/file10 && + p4 filelog //depot/file10 | grep -q "branch from //depot/file" && + + cp file2 file11 && + git add file11 && + git commit -a -m "Copy file2 to file11" && + git diff-tree -r -C --find-copies-harder HEAD && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopiesHarder true && + "$GITP4" submit && + p4 filelog //depot/file11 && + p4 filelog //depot/file11 | grep -q "branch from //depot/file" && + + cp file2 file12 && + echo "some text" >>file12 && + git add file12 && + git commit -a -m "Copy file2 to file12 with changes" && + git diff-tree -r -C --find-copies-harder HEAD && + level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && + test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopies $(($level + 2)) && + "$GITP4" submit && + p4 filelog //depot/file12 && + p4 filelog //depot/file12 | test_must_fail grep -q "branch from" && + + cp file2 file13 && + echo "different text" >>file13 && + git add file13 && + git commit -a -m "Copy file2 to file13 with changes" && + git diff-tree -r -C --find-copies-harder HEAD && + level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && + test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopies $(($level - 2)) && + "$GITP4" submit && + p4 filelog //depot/file13 && + p4 filelog //depot/file13 | grep -q "branch from //depot/file" + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh new file mode 100755 index 0000000000..a25f18d36a --- /dev/null +++ b/t/t9801-git-p4-branch.sh @@ -0,0 +1,233 @@ +#!/bin/sh + +test_description='git-p4 p4 branching tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# +# 1: //depot/main/f1 +# 2: //depot/main/f2 +# 3: integrate //depot/main/... -> //depot/branch1/... +# 4: //depot/main/f4 +# 5: //depot/branch1/f5 +# .: named branch branch2 +# 6: integrate -b branch2 +# 7: //depot/branch2/f7 +# 8: //depot/main/f8 +# +test_expect_success 'basic p4 branches' ' + ( + cd "$cli" && + mkdir -p main && + + echo f1 >main/f1 && + p4 add main/f1 && + p4 submit -d "main/f1" && + + echo f2 >main/f2 && + p4 add main/f2 && + p4 submit -d "main/f2" && + + p4 integrate //depot/main/... //depot/branch1/... && + p4 submit -d "integrate main to branch1" && + + echo f4 >main/f4 && + p4 add main/f4 && + p4 submit -d "main/f4" && + + echo f5 >branch1/f5 && + p4 add branch1/f5 && + p4 submit -d "branch1/f5" && + + p4 branch -i <<-EOF && + Branch: branch2 + View: //depot/main/... //depot/branch2/... + EOF + + p4 integrate -b branch2 && + p4 submit -d "integrate main to branch2" && + + echo f7 >branch2/f7 && + p4 add branch2/f7 && + p4 submit -d "branch2/f7" && + + echo f8 >main/f8 && + p4 add main/f8 && + p4 submit -d "main/f8" + ) +' + +test_expect_success 'import main, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/main@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 4 wc + ) +' + +test_expect_success 'import branch1, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/branch1@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'import branch2, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/branch2@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'import depot, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 8 wc + ) +' + +test_expect_success 'import depot, branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" --detect-branches //depot@all && + ( + cd "$git" && + + git log --oneline --graph --decorate --all && + + # 4 main commits + git rev-list master >wc && + test_line_count = 4 wc && + + # 3 main, 1 integrate, 1 on branch2 + git rev-list p4/depot/branch2 >wc && + test_line_count = 5 wc && + + # no branch1, since no p4 branch created for it + test_must_fail git show-ref p4/depot/branch1 + ) +' + +test_expect_success 'import depot, branch detection, branchList branch definition' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + "$GITP4" clone --dest=. --detect-branches //depot@all && + + git log --oneline --graph --decorate --all && + + # 4 main commits + git rev-list master >wc && + test_line_count = 4 wc && + + # 3 main, 1 integrate, 1 on branch2 + git rev-list p4/depot/branch2 >wc && + test_line_count = 5 wc && + + # 2 main, 1 integrate, 1 on branch1 + git rev-list p4/depot/branch1 >wc && + test_line_count = 4 wc + ) +' + +test_expect_success 'restart p4d' ' + kill_p4d && + start_p4d +' + +# +# 1: //depot/branch1/file1 +# //depot/branch1/file2 +# 2: integrate //depot/branch1/... -> //depot/branch2/... +# 3: //depot/branch1/file3 +# 4: //depot/branch1/file2 (edit) +# 5: integrate //depot/branch1/... -> //depot/branch3/... +# +## Create a simple branch structure in P4 depot. +test_expect_success 'add simple p4 branches' ' + ( + cd "$cli" && + mkdir branch1 && + cd branch1 && + echo file1 >file1 && + echo file2 >file2 && + p4 add file1 file2 && + p4 submit -d "branch1" && + p4 integrate //depot/branch1/... //depot/branch2/... && + p4 submit -d "branch2" && + echo file3 >file3 && + p4 add file3 && + p4 submit -d "add file3 in branch1" && + p4 open file2 && + echo update >>file2 && + p4 submit -d "update file2 in branch1" && + p4 integrate //depot/branch1/... //depot/branch3/... && + p4 submit -d "branch3" + ) +' + +# Configure branches through git-config and clone them. +# All files are tested to make sure branches were cloned correctly. +# Finally, make an update to branch1 on P4 side to check if it is imported +# correctly by git-p4. +test_expect_success 'git-p4 clone simple branches' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList branch1:branch2 && + git config --add git-p4.branchList branch1:branch3 && + "$GITP4" clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test -f file1 && + test -f file2 && + test -f file3 && + grep -q update file2 && + git reset --hard p4/depot/branch2 && + test -f file1 && + test -f file2 && + test ! -f file3 && + test_must_fail grep -q update file2 && + git reset --hard p4/depot/branch3 && + test -f file1 && + test -f file2 && + test -f file3 && + grep -q update file2 && + cd "$cli" && + cd branch1 && + p4 edit file2 && + echo file2_ >>file2 && + p4 submit -d "update file2 in branch3" && + cd "$git" && + git reset --hard p4/depot/branch1 && + "$GITP4" rebase && + grep -q file2_ file2 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh new file mode 100755 index 0000000000..3b358ef8d8 --- /dev/null +++ b/t/t9802-git-p4-filetype.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +test_description='git-p4 p4 filetype tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'utf-16 file create' ' + ( + cd "$cli" && + + # p4 saves this verbatim + printf "three\nline\ntext\n" >f-ascii && + p4 add -t text f-ascii && + + # p4 adds \377\376 header + cp f-ascii f-ascii-as-utf16 && + p4 add -t utf16 f-ascii-as-utf16 && + + # p4 saves this exactly as iconv produced it + printf "three\nline\ntext\n" | iconv -f ascii -t utf-16 >f-utf16 && + p4 add -t utf16 f-utf16 && + + # this also is unchanged + cp f-utf16 f-utf16-as-text && + p4 add -t text f-utf16-as-text && + + p4 submit -d "f files" && + + # force update of client files + p4 sync -f + ) +' + +test_expect_success 'utf-16 file test' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + + test_cmp "$cli/f-ascii" f-ascii && + test_cmp "$cli/f-ascii-as-utf16" f-ascii-as-utf16 && + test_cmp "$cli/f-utf16" f-utf16 && + test_cmp "$cli/f-utf16-as-text" f-utf16-as-text + ) +' + +test_expect_success 'keyword file create' ' + ( + cd "$cli" && + + printf "id\n\$Id\$\n\$Author\$\ntext\n" >k-text-k && + p4 add -t text+k k-text-k && + + cp k-text-k k-text-ko && + p4 add -t text+ko k-text-ko && + + cat k-text-k | iconv -f ascii -t utf-16 >k-utf16-k && + p4 add -t utf16+k k-utf16-k && + + cp k-utf16-k k-utf16-ko && + p4 add -t utf16+ko k-utf16-ko && + + p4 submit -d "k files" && + p4 sync -f + ) +' + +build_smush() { + cat >k_smush.py <<-\EOF && + import re, sys + sys.stdout.write(re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$', r'$\1$', sys.stdin.read())) + EOF + cat >ko_smush.py <<-\EOF + import re, sys + sys.stdout.write(re.sub(r'(?i)\$(Id|Header):[^$]*\$', r'$\1$', sys.stdin.read())) + EOF +} + +test_expect_success 'keyword file test' ' + build_smush && + test_when_finished rm -f k_smush.py ko_smush.py && + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + + # text, ensure unexpanded + "$PYTHON_PATH" "$TRASH_DIRECTORY/k_smush.py" <"$cli/k-text-k" >cli-k-text-k-smush && + test_cmp cli-k-text-k-smush k-text-k && + "$PYTHON_PATH" "$TRASH_DIRECTORY/ko_smush.py" <"$cli/k-text-ko" >cli-k-text-ko-smush && + test_cmp cli-k-text-ko-smush k-text-ko && + + # utf16, even though p4 expands keywords, git-p4 does not + # try to undo that + test_cmp "$cli/k-utf16-k" k-utf16-k && + test_cmp "$cli/k-utf16-ko" k-utf16-ko + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9803-git-shell-metachars.sh b/t/t9803-git-shell-metachars.sh new file mode 100755 index 0000000000..db04375a13 --- /dev/null +++ b/t/t9803-git-shell-metachars.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +test_description='git-p4 transparency to shell metachars in filenames' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'init depot' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "file1" + ) +' + +test_expect_success 'shell metachars in filenames' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo f1 >foo\$bar && + git add foo\$bar && + echo f2 >"file with spaces" && + git add "file with spaces" && + git commit -m "add files" && + P4EDITOR=touch "$GITP4" submit + ) && + ( + cd "$cli" && + p4 sync ... && + test -e "file with spaces" && + test -e "foo\$bar" + ) +' + +test_expect_success 'deleting with shell metachars' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + git rm foo\$bar && + git rm file\ with\ spaces && + git commit -m "remove files" && + P4EDITOR=touch "$GITP4" submit + ) && + ( + cd "$cli" && + p4 sync ... && + test ! -e "file with spaces" && + test ! -e foo\$bar + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9901-git-web--browse.sh b/t/t9901-git-web--browse.sh new file mode 100755 index 0000000000..b0a6bad8dd --- /dev/null +++ b/t/t9901-git-web--browse.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# + +test_description='git web--browse basic tests + +This test checks that git web--browse can handle various valid URLs.' + +. ./test-lib.sh + +test_web_browse () { + # browser=$1 url=$2 + git web--browse --browser="$1" "$2" >actual && + tr -d '\015' <actual >text && + test_cmp expect text +} + +test_expect_success \ + 'URL with an ampersand in it' ' + echo http://example.com/foo\&bar >expect && + git config browser.custom.cmd echo && + test_web_browse custom http://example.com/foo\&bar +' + +test_expect_success \ + 'URL with a semi-colon in it' ' + echo http://example.com/foo\;bar >expect && + git config browser.custom.cmd echo && + test_web_browse custom http://example.com/foo\;bar +' + +test_expect_success \ + 'URL with a hash in it' ' + echo http://example.com/foo#bar >expect && + git config browser.custom.cmd echo && + test_web_browse custom http://example.com/foo#bar +' + +test_expect_success \ + 'browser paths are properly quoted' ' + echo fake: http://example.com/foo >expect && + cat >"fake browser" <<-\EOF && + #!/bin/sh + echo fake: "$@" + EOF + chmod +x "fake browser" && + git config browser.w3m.path "`pwd`/fake browser" && + test_web_browse w3m http://example.com/foo +' + +test_expect_success \ + 'browser command allows arbitrary shell code' ' + echo "arg: http://example.com/foo" >expect && + git config browser.custom.cmd " + f() { + for i in \"\$@\"; do + echo arg: \$i + done + } + f" && + test_web_browse custom http://example.com/foo +' + +test_done diff --git a/t/test4012.png b/t/test-binary-1.png Binary files differindex 7b181d15ce..7b181d15ce 100644 --- a/t/test4012.png +++ b/t/test-binary-1.png diff --git a/t/test9200b.png b/t/test-binary-2.png Binary files differindex ac22ccbd3e..ac22ccbd3e 100644 --- a/t/test9200b.png +++ b/t/test-binary-2.png diff --git a/t/test-lib.sh b/t/test-lib.sh index 0fdc541a7c..bdd9513b84 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -43,36 +43,25 @@ TERM=dumb export LANG LC_ALL PAGER TERM TZ EDITOR=: unset VISUAL -unset GIT_EDITOR -unset AUTHOR_DATE -unset AUTHOR_EMAIL -unset AUTHOR_NAME -unset COMMIT_AUTHOR_EMAIL -unset COMMIT_AUTHOR_NAME unset EMAIL -unset GIT_ALTERNATE_OBJECT_DIRECTORIES -unset GIT_AUTHOR_DATE +unset $(perl -e ' + my @env = keys %ENV; + my $ok = join("|", qw( + TRACE + DEBUG + USE_LOOKUP + TEST + .*_TEST + PROVE + VALGRIND + )); + my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); + print join("\n", @vars); +') GIT_AUTHOR_EMAIL=author@example.com GIT_AUTHOR_NAME='A U Thor' -unset GIT_COMMITTER_DATE GIT_COMMITTER_EMAIL=committer@example.com GIT_COMMITTER_NAME='C O Mitter' -unset GIT_DIFF_OPTS -unset GIT_DIR -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 -unset GIT_NOTES_REF -unset GIT_NOTES_DISPLAY_REF -unset GIT_NOTES_REWRITE_REF -unset GIT_NOTES_REWRITE_MODE -unset GIT_REFLOG_ACTION -unset GIT_CHERRY_PICK_HELP -unset GIT_QUIET GIT_MERGE_VERBOSITY=5 export GIT_MERGE_VERBOSITY export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME @@ -100,6 +89,13 @@ esac _x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' _x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05" +# Zero SHA-1 +_z40=0000000000000000000000000000000000000000 + +# Line feed +LF=' +' + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... @@ -365,6 +361,24 @@ test_chmod () { git update-index --add "--chmod=$@" } +# Unset a configuration variable, but don't fail if it doesn't exist. +test_unconfig () { + git config --unset-all "$@" + config_status=$? + case "$config_status" in + 5) # ok, nothing to unset + config_status=0 + ;; + esac + return $config_status +} + +# Set git config, automatically unsetting it after the test is over. +test_config () { + test_when_finished "test_unconfig '$1'" && + git config "$@" +} + # Use test_set_prereq to tell that a particular prerequisite is available. # The prerequisite can later be checked for in two ways: # @@ -452,15 +466,26 @@ test_debug () { test "$debug" = "" || eval "$1" } +test_eval_ () { + # This is a separate function because some tests use + # "return" to end a test_expect_success block early. + eval >&3 2>&4 "$*" +} + test_run_ () { test_cleanup=: - eval >&3 2>&4 "$1" + expecting_failure=$2 + test_eval_ "$1" eval_ret=$? - eval >&3 2>&4 "$test_cleanup" + + if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure" + then + test_eval_ "$test_cleanup" + fi if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then echo "" fi - return 0 + return "$eval_ret" } test_skip () { @@ -505,8 +530,7 @@ test_expect_failure () { if ! test_skip "$@" then say >&3 "checking known breakage: $2" - test_run_ "$2" - if [ "$?" = 0 -a "$eval_ret" = 0 ] + if test_run_ "$2" expecting_failure then test_known_broken_ok_ "$1" else @@ -524,8 +548,7 @@ test_expect_success () { if ! test_skip "$@" then say >&3 "expecting success: $2" - test_run_ "$2" - if [ "$?" = 0 -a "$eval_ret" = 0 ] + if test_run_ "$2" then test_ok_ "$1" else @@ -586,7 +609,7 @@ test_external () { test_external_without_stderr () { # The temporary file has no (and must have no) security # implications. - tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi + tmp=${TMPDIR:-/tmp} stderr="$tmp/git-external-stderr.$$.tmp" test_external "$@" 4> "$stderr" [ -f "$stderr" ] || error "Internal error: $stderr disappeared." @@ -739,12 +762,11 @@ test_expect_code () { exit_code=$? if test $exit_code = $want_code then - echo >&2 "test_expect_code: command exited with $exit_code: $*" return 0 - else - echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*" - return 1 fi + + echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*" + return 1 } # test_cmp is a helper function to compare actual and expected output. @@ -783,6 +805,9 @@ test_cmp() { # # except that the greeting and config --unset must both succeed for # the test to pass. +# +# Note that under --immediate mode, no clean-up is done to help diagnose +# what went wrong. test_when_finished () { test_cleanup="{ $* @@ -812,12 +837,14 @@ test_done () { mkdir -p "$test_results_dir" test_results_path="$test_results_dir/${0%.sh}-$$.counts" - 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 + cat >>"$test_results_path" <<-EOF + total $test_count + success $test_success + fixed $test_fixed + broken $test_broken + failed $test_failure + + EOF fi if test "$test_fixed" != 0 @@ -891,8 +918,13 @@ then } make_valgrind_symlink () { - # handle only executables - test -x "$1" || return + # handle only executables, unless they are shell libraries that + # need to be in the exec-path. We will just use "#!" as a + # guess for a shell-script, since we have no idea what the user + # may have configured as the shell path. + test -x "$1" || + test "#!" = "$(head -c 2 <"$1")" || + return; base=$(basename "$1") symlink_target=$GIT_BUILD_DIR/$base @@ -918,6 +950,8 @@ then do make_valgrind_symlink $file done + # special-case the mergetools loadables + make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools" OLDIFS=$IFS IFS=: for path in $PATH @@ -954,8 +988,8 @@ fi GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt unset GIT_CONFIG GIT_CONFIG_NOSYSTEM=1 -GIT_CONFIG_NOGLOBAL=1 -export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL +GIT_ATTR_NOSYSTEM=1 +export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS @@ -1004,14 +1038,14 @@ rm -fr "$test" || { exit 1 } +HOME="$TRASH_DIRECTORY" +export HOME + test_create_repo "$test" # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses like git equals our $PWD (for pathname comparisons). cd -P "$test" || exit 1 -HOME=$(pwd) -export HOME - this_test=${0##*/} this_test=${this_test%%-*} for skp in $GIT_SKIP_TESTS @@ -1078,6 +1112,42 @@ esac test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PYTHON" && test_set_prereq PYTHON +test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE + +# Can we rely on git's output in the C locale? +if test -n "$GETTEXT_POISON" +then + GIT_GETTEXT_POISON=YesPlease + export GIT_GETTEXT_POISON +else + test_set_prereq C_LOCALE_OUTPUT +fi + +# Use this instead of test_cmp to compare files that contain expected and +# actual output from git commands that can be translated. When running +# under GETTEXT_POISON this pretends that the command produced expected +# results. +test_i18ncmp () { + test -n "$GETTEXT_POISON" || test_cmp "$@" +} + +# Use this instead of "grep expected-string actual" to see if the +# output from a git command that can be translated either contains an +# expected string, or does not contain an unwanted one. When running +# under GETTEXT_POISON this pretends that the command produced expected +# results. +test_i18ngrep () { + if test -n "$GETTEXT_POISON" + then + : # pretend success + elif test "x!" = "x$1" + then + shift + ! grep "$@" + else + grep "$@" + fi +} # test whether the filesystem supports symbolic links ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS diff --git a/t/test9200a.png b/t/test9200a.png Binary files differdeleted file mode 100644 index 7b181d15ce..0000000000 --- a/t/test9200a.png +++ /dev/null diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp index 9e013fa3b2..0a6724fcc4 100644 --- a/t/valgrind/default.supp +++ b/t/valgrind/default.supp @@ -43,3 +43,9 @@ fun:write_buffer fun:write_loose_object } + +{ + ignore-sse-strlen-invalid-read-size + Memcheck:Addr4 + fun:copy_ref +} |