diff options
Diffstat (limited to 't')
432 files changed, 21691 insertions, 3839 deletions
diff --git a/t/Makefile b/t/Makefile index 9046ec9816..88e289fc8b 100644 --- a/t/Makefile +++ b/t/Makefile @@ -17,9 +17,9 @@ DEFAULT_TEST_TARGET ?= test # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) -TSVN = $(wildcard t91[0-9][0-9]-*.sh) -TGITWEB = $(wildcard t95[0-9][0-9]-*.sh) +T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) +TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh)) +TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh)) all: $(DEFAULT_TEST_TARGET) @@ -28,7 +28,7 @@ test: pre-clean $(TEST_LINT) prove: pre-clean $(TEST_LINT) @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS) - $(MAKE) clean + $(MAKE) clean-except-prove-cache $(T): @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) @@ -36,9 +36,11 @@ $(T): pre-clean: $(RM) -r test-results -clean: +clean-except-prove-cache: $(RM) -r 'trash directory'.* test-results $(RM) -r valgrind/bin + +clean: clean-except-prove-cache $(RM) .prove test-lint: test-lint-duplicates test-lint-executable @@ -73,6 +75,9 @@ gitweb-test: valgrind: $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind" +perf: + $(MAKE) -C perf/ all + # Smoke testing targets -include ../GIT-VERSION-FILE uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo unknown') @@ -111,4 +116,4 @@ smoke_report: smoke http://smoke.git.nix.is/app/projects/process_add_report/1 \ | grep -v ^Redirecting -.PHONY: pre-clean $(T) aggregate-results clean valgrind smoke smoke_report +.PHONY: pre-clean $(T) aggregate-results clean valgrind perf @@ -307,6 +307,25 @@ Don't: Use test_done instead if you need to stop the tests early (see "Skipping tests" below). + - use '! git cmd' when you want to make sure the git command exits + with failure in a controlled way by calling "die()". Instead, + use 'test_must_fail git cmd'. This will signal a failure if git + dies in an unexpected way (e.g. segfault). + + - use perl without spelling it as "$PERL_PATH". This is to help our + friends on Windows where the platform Perl often adds CR before + the end of line, and they bundle Git with a version of Perl that + does not do so, whose path is specified with $PERL_PATH. + + - use sh without spelling it as "$SHELL_PATH", when the script can + be misinterpreted by broken platform shell (e.g. Solaris). + + - chdir around in tests. It is not sufficient to chdir to + somewhere and then chdir back to the original location later in + the test, as any intermediate step can fail and abort the test, + causing the next test to start in an unexpected directory. Do so + inside a subshell if necessary. + - Break the TAP output The raw output from your test may be interpreted by a TAP harness. TAP @@ -342,9 +361,9 @@ 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.: - test_expect_success PERL 'I need Perl' " - '$PERL_PATH' -e 'hlagh() if unf_unf()' - " + test_expect_success PERL 'I need Perl' ' + "$PERL_PATH" -e "hlagh() if unf_unf()" + ' The advantage of skipping tests like this is that platforms that don't have the PERL and other optional dependencies get an indication of how @@ -548,6 +567,19 @@ library for your script to use. ... ' + - test_pause + + This command is useful for writing and debugging tests and must be + removed before submitting. It halts the execution of the test and + spawns a shell in the trash directory. Exit the shell to continue + the test. Example: + + test_expect_success 'test' ' + git do-something >actual && + test_pause && + test_cmp expected actual + ' + Prerequisites ------------- @@ -658,76 +690,3 @@ Then, at the top-level: That'll generate a detailed cover report in the "cover_db_html" directory, which you can then copy to a webserver, or inspect locally in a browser. - -Smoke testing -------------- - -The Git test suite has support for smoke testing. Smoke testing is -when you submit the results of a test run to a central server for -analysis and aggregation. - -Running a smoke tester is an easy and valuable way of contributing to -Git development, particularly if you have access to an uncommon OS on -obscure hardware. - -After building Git you can generate a smoke report like this in the -"t" directory: - - make clean smoke - -You can also pass arguments via the environment. This should make it -faster: - - GIT_TEST_OPTS='--root=/dev/shm' TEST_JOBS=10 make clean smoke - -The "smoke" target will run the Git test suite with Perl's -"TAP::Harness" module, and package up the results in a .tar.gz archive -with "TAP::Harness::Archive". The former is included with Perl v5.10.1 -or later, but you'll need to install the latter from the CPAN. See the -"Test coverage" section above for how you might do that. - -Once the "smoke" target finishes you'll see a message like this: - - TAP Archive created at <path to git>/t/test-results/git-smoke.tar.gz - -To upload the smoke report you need to have curl(1) installed, then -do: - - make smoke_report - -To upload the report anonymously. Hopefully that'll return something -like "Reported #7 added.". - -If you're going to be uploading reports frequently please request a -user account by E-Mailing gitsmoke@v.nix.is. Once you have a username -and password you'll be able to do: - - SMOKE_USERNAME=<username> SMOKE_PASSWORD=<password> make smoke_report - -You can also add an additional comment to attach to the report, and/or -a comma separated list of tags: - - SMOKE_USERNAME=<username> SMOKE_PASSWORD=<password> \ - SMOKE_COMMENT=<comment> SMOKE_TAGS=<tags> \ - make smoke_report - -Once the report is uploaded it'll be made available at -http://smoke.git.nix.is, here's an overview of Recent Smoke Reports -for Git: - - http://smoke.git.nix.is/app/projects/smoke_reports/1 - -The reports will also be mirrored to GitHub every few hours: - - http://github.com/gitsmoke/smoke-reports - -The Smolder SQLite database is also mirrored and made available for -download: - - http://github.com/gitsmoke/smoke-database - -Note that the database includes hashed (with crypt()) user passwords -and E-Mail addresses. Don't use a valuable password for the smoke -service if you have an account, or an E-Mail address you don't want to -be publicly known. The user accounts are just meant to be convenient -labels, they're not meant to be secure. 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/gitweb-lib.sh b/t/gitweb-lib.sh index 143eb1f240..ae2dc4604f 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'; @@ -68,7 +69,7 @@ gitweb_run () { # written to web server logs, so we are not interested in that: # we are interested only in properly formatted errors/warnings rm -f gitweb.log && - perl -- "$SCRIPT_NAME" \ + "$PERL_PATH" -- "$SCRIPT_NAME" \ >gitweb.output 2>gitweb.log && perl -w -e ' open O, ">gitweb.headers"; @@ -107,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/harness b/t/harness deleted file mode 100755 index f5c02f49b7..0000000000 --- a/t/harness +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Getopt::Long (); -use TAP::Harness::Archive; - -Getopt::Long::Parser->new( - config => [ qw/ pass_through / ], -)->getoptions( - 'jobs:1' => \(my $jobs = $ENV{TEST_JOBS}), - 'archive=s' => \my $archive, -) or die "$0: Couldn't getoptions()"; - -TAP::Harness::Archive->new({ - jobs => $jobs, - archive => $archive, - ($ENV{GIT_TEST_OPTS} - ? (test_args => [ split /\s+/, $ENV{GIT_TEST_OPTS} ]) - : ()), - extra_properties => {}, -})->runtests(@ARGV); diff --git a/t/lib-credential.sh b/t/lib-credential.sh new file mode 100755 index 0000000000..4a37cd79e5 --- /dev/null +++ b/t/lib-credential.sh @@ -0,0 +1,254 @@ +#!/bin/sh + +# Try a set of credential helpers; the expected stdin, +# stdout and stderr should be provided on stdin, +# separated by "--". +check() { + read_chunk >stdin && + read_chunk >expect-stdout && + read_chunk >expect-stderr && + test-credential "$@" <stdin >stdout 2>stderr && + test_cmp expect-stdout stdout && + test_cmp expect-stderr stderr +} + +read_chunk() { + while read line; do + case "$line" in + --) break ;; + *) echo "$line" ;; + esac + done +} + +# Clear any residual data from previous tests. We only +# need this when testing third-party helpers which read and +# write outside of our trash-directory sandbox. +# +# Don't bother checking for success here, as it is +# outside the scope of tests and represents a best effort to +# clean up after ourselves. +helper_test_clean() { + reject $1 https example.com store-user + reject $1 https example.com user1 + reject $1 https example.com user2 + reject $1 http path.tld user + reject $1 https timeout.tld user +} + +reject() { + ( + echo protocol=$2 + echo host=$3 + echo username=$4 + ) | test-credential reject $1 +} + +helper_test() { + HELPER=$1 + + test_expect_success "helper ($HELPER) has no existing data" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com'\'': + askpass: Password for '\''https://askpass-username@example.com'\'': + EOF + ' + + test_expect_success "helper ($HELPER) stores password" ' + check approve $HELPER <<-\EOF + protocol=https + host=example.com + username=store-user + password=store-pass + EOF + ' + + test_expect_success "helper ($HELPER) can retrieve password" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + -- + username=store-user + password=store-pass + -- + EOF + ' + + test_expect_success "helper ($HELPER) requires matching protocol" ' + check fill $HELPER <<-\EOF + protocol=http + host=example.com + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''http://example.com'\'': + askpass: Password for '\''http://askpass-username@example.com'\'': + EOF + ' + + test_expect_success "helper ($HELPER) requires matching host" ' + check fill $HELPER <<-\EOF + protocol=https + host=other.tld + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://other.tld'\'': + askpass: Password for '\''https://askpass-username@other.tld'\'': + EOF + ' + + test_expect_success "helper ($HELPER) requires matching username" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=other + -- + username=other + password=askpass-password + -- + askpass: Password for '\''https://other@example.com'\'': + EOF + ' + + test_expect_success "helper ($HELPER) requires matching path" ' + test_config credential.usehttppath true && + check approve $HELPER <<-\EOF && + protocol=http + host=path.tld + path=foo.git + username=user + password=pass + EOF + check fill $HELPER <<-\EOF + protocol=http + host=path.tld + path=bar.git + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''http://path.tld/bar.git'\'': + askpass: Password for '\''http://askpass-username@path.tld/bar.git'\'': + EOF + ' + + test_expect_success "helper ($HELPER) can forget host" ' + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com'\'': + askpass: Password for '\''https://askpass-username@example.com'\'': + EOF + ' + + test_expect_success "helper ($HELPER) can store multiple users" ' + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user1 + password=pass1 + EOF + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user2 + password=pass2 + EOF + check fill $HELPER <<-\EOF && + protocol=https + host=example.com + username=user1 + -- + username=user1 + password=pass1 + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user2 + -- + username=user2 + password=pass2 + EOF + ' + + test_expect_success "helper ($HELPER) can forget user" ' + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + username=user1 + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user1 + -- + username=user1 + password=askpass-password + -- + askpass: Password for '\''https://user1@example.com'\'': + EOF + ' + + test_expect_success "helper ($HELPER) remembers other user" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user2 + -- + username=user2 + password=pass2 + EOF + ' +} + +helper_test_timeout() { + HELPER="$*" + + test_expect_success "helper ($HELPER) times out" ' + check approve "$HELPER" <<-\EOF && + protocol=https + host=timeout.tld + username=user + password=pass + EOF + sleep 2 && + check fill "$HELPER" <<-\EOF + protocol=https + host=timeout.tld + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://timeout.tld'\'': + askpass: Password for '\''https://askpass-username@timeout.tld'\'': + EOF + ' +} + +cat >askpass <<\EOF +#!/bin/sh +echo >&2 askpass: $* +what=`echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z` +echo "askpass-$what" +EOF +chmod +x askpass +GIT_ASKPASS="$PWD/askpass" +export GIT_ASKPASS 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-gettext.sh b/t/lib-gettext.sh new file mode 100644 index 0000000000..0f76f6cdc0 --- /dev/null +++ b/t/lib-gettext.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +. ./test-lib.sh + +GIT_TEXTDOMAINDIR="$GIT_BUILD_DIR/po/build/locale" +GIT_PO_PATH="$GIT_BUILD_DIR/po" +export GIT_TEXTDOMAINDIR GIT_PO_PATH + +. "$GIT_BUILD_DIR"/git-sh-i18n + +if test_have_prereq GETTEXT && ! test_have_prereq GETTEXT_POISON +then + # is_IS.UTF-8 on Solaris and FreeBSD, is_IS.utf8 on Debian + is_IS_locale=$(locale -a | sed -n '/^is_IS\.[uU][tT][fF]-*8$/{ + p + q + }') + # is_IS.ISO8859-1 on Solaris and FreeBSD, is_IS.iso88591 on Debian + is_IS_iso_locale=$(locale -a | sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{ + p + q + }') + + # Export them as an environment variable so the t0202/test.pl Perl + # test can use it too + export is_IS_locale is_IS_iso_locale + + if test -n "$is_IS_locale" && + test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough" + then + # Some of the tests need the reference Icelandic locale + test_set_prereq GETTEXT_LOCALE + + # Exporting for t0202/test.pl + GETTEXT_LOCALE=1 + export GETTEXT_LOCALE + say "# lib-gettext: Found '$is_IS_locale' as an is_IS UTF-8 locale" + else + say "# lib-gettext: No is_IS UTF-8 locale available" + fi + + if test -n "$is_IS_iso_locale" && + test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough" + then + # Some of the tests need the reference Icelandic locale + test_set_prereq GETTEXT_ISO_LOCALE + + say "# lib-gettext: Found '$is_IS_iso_locale' as an is_IS ISO-8859-1 locale" + else + say "# lib-gettext: No is_IS ISO-8859-1 locale available" + fi +fi diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh new file mode 100644 index 0000000000..87f0ad8f41 --- /dev/null +++ b/t/lib-git-daemon.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +if test -z "$GIT_TEST_GIT_DAEMON" +then + skip_all="git-daemon testing disabled (define GIT_TEST_GIT_DAEMON to enable)" + test_done +fi + +LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-'8121'} + +GIT_DAEMON_PID= +GIT_DAEMON_DOCUMENT_ROOT_PATH="$PWD"/repo +GIT_DAEMON_URL=git://127.0.0.1:$LIB_GIT_DAEMON_PORT + +start_git_daemon() { + if test -n "$GIT_DAEMON_PID" + then + error "start_git_daemon already called" + fi + + mkdir -p "$GIT_DAEMON_DOCUMENT_ROOT_PATH" + + trap 'code=$?; stop_git_daemon; (exit $code); die' EXIT + + say >&3 "Starting git daemon ..." + mkfifo git_daemon_output + git daemon --listen=127.0.0.1 --port="$LIB_GIT_DAEMON_PORT" \ + --reuseaddr --verbose \ + --base-path="$GIT_DAEMON_DOCUMENT_ROOT_PATH" \ + "$@" "$GIT_DAEMON_DOCUMENT_ROOT_PATH" \ + >&3 2>git_daemon_output & + GIT_DAEMON_PID=$! + { + read line <&7 + echo >&4 "$line" + cat <&7 >&4 & + } 7<git_daemon_output && + + # Check expected output + if test x"$(expr "$line" : "\[[0-9]*\] \(.*\)")" != x"Ready to rumble" + then + kill "$GIT_DAEMON_PID" + wait "$GIT_DAEMON_PID" + trap 'die' EXIT + error "git daemon failed to start" + fi +} + +stop_git_daemon() { + if test -z "$GIT_DAEMON_PID" + then + return + fi + + trap 'die' EXIT + + # kill git-daemon child of git + say >&3 "Stopping git daemon ..." + kill "$GIT_DAEMON_PID" + wait "$GIT_DAEMON_PID" >&3 2>&4 + ret=$? + # expect exit with status 143 = 128+15 for signal TERM=15 + if test $ret -ne 143 + then + error "git daemon exited with status: $ret" + fi + GIT_DAEMON_PID= + rm -f git_daemon_output +} diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh new file mode 100644 index 0000000000..121e38002b --- /dev/null +++ b/t/lib-git-p4.sh @@ -0,0 +1,73 @@ +# +# 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 +} + +# 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 +export P4EDITOR=: + +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 b8996a373a..094d490893 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,6 +160,6 @@ test_http_push_nonff() { ' test_expect_success 'non-fast-forward push shows help message' ' - test_i18ngrep "To prevent you from losing history, non-fast-forward updates were rejected" output + test_i18ngrep "Updates were rejected because" output ' } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 0a4cdfa93e..de3762e247 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -52,8 +52,15 @@ Alias /auth/ www/auth/ <Location /smart_noexport/> SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} </Location> +<Location /smart_custom_env/> + SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} + SetEnv GIT_HTTP_EXPORT_ALL + SetEnv GIT_COMMITTER_NAME "Custom User" + SetEnv GIT_COMMITTER_EMAIL custom@example.com +</Location> ScriptAlias /smart/ ${GIT_EXEC_PATH}/git-http-backend/ ScriptAlias /smart_noexport/ ${GIT_EXEC_PATH}/git-http-backend/ +ScriptAlias /smart_custom_env/ ${GIT_EXEC_PATH}/git-http-backend/ <Directory ${GIT_EXEC_PATH}> Options None </Directory> @@ -92,6 +99,9 @@ SSLEngine On <Location /dumb/> Dav on </Location> + <Location /auth/dumb> + Dav on + </Location> </IfDefine> <IfDefine SVN> diff --git a/t/perf/.gitignore b/t/perf/.gitignore new file mode 100644 index 0000000000..50f5cc1ed9 --- /dev/null +++ b/t/perf/.gitignore @@ -0,0 +1,2 @@ +build/ +test-results/ diff --git a/t/perf/Makefile b/t/perf/Makefile new file mode 100644 index 0000000000..8c47155a7c --- /dev/null +++ b/t/perf/Makefile @@ -0,0 +1,15 @@ +-include ../../config.mak +export GIT_TEST_OPTIONS + +all: perf + +perf: pre-clean + ./run + +pre-clean: + rm -rf test-results + +clean: + rm -rf build "trash directory".* test-results + +.PHONY: all perf pre-clean clean diff --git a/t/perf/README b/t/perf/README new file mode 100644 index 0000000000..b2dbad4d50 --- /dev/null +++ b/t/perf/README @@ -0,0 +1,146 @@ +Git performance tests +===================== + +This directory holds performance testing scripts for git tools. The +first part of this document describes the various ways in which you +can run them. + +When fixing the tools or adding enhancements, you are strongly +encouraged to add tests in this directory to cover what you are +trying to fix or enhance. The later part of this short document +describes how your test scripts should be organized. + + +Running Tests +------------- + +The easiest way to run tests is to say "make". This runs all +the tests on the current git repository. + + === Running 2 tests in this tree === + [...] + Test this tree + --------------------------------------------------------- + 0001.1: rev-list --all 0.54(0.51+0.02) + 0001.2: rev-list --all --objects 6.14(5.99+0.11) + 7810.1: grep worktree, cheap regex 0.16(0.16+0.35) + 7810.2: grep worktree, expensive regex 7.90(29.75+0.37) + 7810.3: grep --cached, cheap regex 3.07(3.02+0.25) + 7810.4: grep --cached, expensive regex 9.39(30.57+0.24) + +You can compare multiple repositories and even git revisions with the +'run' script: + + $ ./run . origin/next /path/to/git-tree p0001-rev-list.sh + +where . stands for the current git tree. The full invocation is + + ./run [<revision|directory>...] [--] [<test-script>...] + +A '.' argument is implied if you do not pass any other +revisions/directories. + +You can also manually test this or another git build tree, and then +call the aggregation script to summarize the results: + + $ ./p0001-rev-list.sh + [...] + $ GIT_BUILD_DIR=/path/to/other/git ./p0001-rev-list.sh + [...] + $ ./aggregate.perl . /path/to/other/git ./p0001-rev-list.sh + +aggregate.perl has the same invocation as 'run', it just does not run +anything beforehand. + +You can set the following variables (also in your config.mak): + + GIT_PERF_REPEAT_COUNT + Number of times a test should be repeated for best-of-N + measurements. Defaults to 5. + + GIT_PERF_MAKE_OPTS + Options to use when automatically building a git tree for + performance testing. E.g., -j6 would be useful. + + GIT_PERF_REPO + GIT_PERF_LARGE_REPO + Repositories to copy for the performance tests. The normal + repo should be at least git.git size. The large repo should + probably be about linux-2.6.git size for optimal results. + Both default to the git.git you are running from. + +You can also pass the options taken by ordinary git tests; the most +useful one is: + +--root=<directory>:: + Create "trash" directories used to store all temporary data during + testing under <directory>, instead of the t/ directory. + Using this option with a RAM-based filesystem (such as tmpfs) + can massively speed up the test suite. + + +Naming Tests +------------ + +The performance test files are named as: + + pNNNN-commandname-details.sh + +where N is a decimal digit. The same conventions for choosing NNNN as +for normal tests apply. + + +Writing Tests +------------- + +The perf script starts much like a normal test script, except it +sources perf-lib.sh: + + #!/bin/sh + # + # Copyright (c) 2005 Junio C Hamano + # + + test_description='xxx performance test' + . ./perf-lib.sh + +After that you will want to use some of the following: + + test_perf_default_repo # sets up a "normal" repository + test_perf_large_repo # sets up a "large" repository + + test_perf_default_repo sub # ditto, in a subdir "sub" + + test_checkout_worktree # if you need the worktree too + +At least one of the first two is required! + +You can use test_expect_success as usual. For actual performance +tests, use + + test_perf 'descriptive string' ' + command1 && + command2 + ' + +test_perf spawns a subshell, for lack of better options. This means +that + +* you _must_ export all variables that you need in the subshell + +* you _must_ flag all variables that you want to persist from the + subshell with 'test_export': + + test_perf 'descriptive string' ' + foo=$(git rev-parse HEAD) && + test_export foo + ' + + The so-exported variables are automatically marked for export in the + shell executing the perf test. For your convenience, test_export is + the same as export in the main shell. + + This feature relies on a bit of magic using 'set' and 'source'. + While we have tried to make sure that it can cope with embedded + whitespace and other special characters, it will not work with + multi-line data. diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl new file mode 100755 index 0000000000..15f7fc1b80 --- /dev/null +++ b/t/perf/aggregate.perl @@ -0,0 +1,166 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Git; + +sub get_times { + my $name = shift; + open my $fh, "<", $name or return undef; + my $line = <$fh>; + return undef if not defined $line; + close $fh or die "cannot close $name: $!"; + $line =~ /^(?:(\d+):)?(\d+):(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) (\d+(?:\.\d+)?)$/ + or die "bad input line: $line"; + my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3; + return ($rt, $4, $5); +} + +sub format_times { + my ($r, $u, $s, $firstr) = @_; + if (!defined $r) { + return "<missing>"; + } + my $out = sprintf "%.2f(%.2f+%.2f)", $r, $u, $s; + if (defined $firstr) { + if ($firstr > 0) { + $out .= sprintf " %+.1f%%", 100.0*($r-$firstr)/$firstr; + } elsif ($r == 0) { + $out .= " ="; + } else { + $out .= " +inf"; + } + } + return $out; +} + +my (@dirs, %dirnames, %dirabbrevs, %prefixes, @tests); +while (scalar @ARGV) { + my $arg = $ARGV[0]; + my $dir; + last if -f $arg or $arg eq "--"; + if (! -d $arg) { + my $rev = Git::command_oneline(qw(rev-parse --verify), $arg); + $dir = "build/".$rev; + } else { + $arg =~ s{/*$}{}; + $dir = $arg; + $dirabbrevs{$dir} = $dir; + } + push @dirs, $dir; + $dirnames{$dir} = $arg; + my $prefix = $dir; + $prefix =~ tr/^a-zA-Z0-9/_/c; + $prefixes{$dir} = $prefix . '.'; + shift @ARGV; +} + +if (not @dirs) { + @dirs = ('.'); +} +$dirnames{'.'} = $dirabbrevs{'.'} = "this tree"; +$prefixes{'.'} = ''; + +shift @ARGV if scalar @ARGV and $ARGV[0] eq "--"; + +@tests = @ARGV; +if (not @tests) { + @tests = glob "p????-*.sh"; +} + +my @subtests; +my %shorttests; +for my $t (@tests) { + $t =~ s{(?:.*/)?(p(\d+)-[^/]+)\.sh$}{$1} or die "bad test name: $t"; + my $n = $2; + my $fname = "test-results/$t.subtests"; + open my $fp, "<", $fname or die "cannot open $fname: $!"; + for (<$fp>) { + chomp; + /^(\d+)$/ or die "malformed subtest line: $_"; + push @subtests, "$t.$1"; + $shorttests{"$t.$1"} = "$n.$1"; + } + close $fp or die "cannot close $fname: $!"; +} + +sub read_descr { + my $name = shift; + open my $fh, "<", $name or return "<error reading description>"; + my $line = <$fh>; + close $fh or die "cannot close $name"; + chomp $line; + return $line; +} + +my %descrs; +my $descrlen = 4; # "Test" +for my $t (@subtests) { + $descrs{$t} = $shorttests{$t}.": ".read_descr("test-results/$t.descr"); + $descrlen = length $descrs{$t} if length $descrs{$t}>$descrlen; +} + +sub have_duplicate { + my %seen; + for (@_) { + return 1 if exists $seen{$_}; + $seen{$_} = 1; + } + return 0; +} +sub have_slash { + for (@_) { + return 1 if m{/}; + } + return 0; +} + +my %newdirabbrevs = %dirabbrevs; +while (!have_duplicate(values %newdirabbrevs)) { + %dirabbrevs = %newdirabbrevs; + last if !have_slash(values %dirabbrevs); + %newdirabbrevs = %dirabbrevs; + for (values %newdirabbrevs) { + s{^[^/]*/}{}; + } +} + +my %times; +my @colwidth = ((0)x@dirs); +for my $i (0..$#dirs) { + my $d = $dirs[$i]; + my $w = length (exists $dirabbrevs{$d} ? $dirabbrevs{$d} : $dirnames{$d}); + $colwidth[$i] = $w if $w > $colwidth[$i]; +} +for my $t (@subtests) { + my $firstr; + for my $i (0..$#dirs) { + my $d = $dirs[$i]; + $times{$prefixes{$d}.$t} = [get_times("test-results/$prefixes{$d}$t.times")]; + my ($r,$u,$s) = @{$times{$prefixes{$d}.$t}}; + my $w = length format_times($r,$u,$s,$firstr); + $colwidth[$i] = $w if $w > $colwidth[$i]; + $firstr = $r unless defined $firstr; + } +} +my $totalwidth = 3*@dirs+$descrlen; +$totalwidth += $_ for (@colwidth); + +printf "%-${descrlen}s", "Test"; +for my $i (0..$#dirs) { + my $d = $dirs[$i]; + printf " %-$colwidth[$i]s", (exists $dirabbrevs{$d} ? $dirabbrevs{$d} : $dirnames{$d}); +} +print "\n"; +print "-"x$totalwidth, "\n"; +for my $t (@subtests) { + printf "%-${descrlen}s", $descrs{$t}; + my $firstr; + for my $i (0..$#dirs) { + my $d = $dirs[$i]; + my ($r,$u,$s) = @{$times{$prefixes{$d}.$t}}; + printf " %-$colwidth[$i]s", format_times($r,$u,$s,$firstr); + $firstr = $r unless defined $firstr; + } + print "\n"; +} diff --git a/t/perf/min_time.perl b/t/perf/min_time.perl new file mode 100755 index 0000000000..c1a2717e07 --- /dev/null +++ b/t/perf/min_time.perl @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +my $minrt = 1e100; +my $min; + +while (<>) { + # [h:]m:s.xx U.xx S.xx + /^(?:(\d+):)?(\d+):(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) (\d+(?:\.\d+)?)$/ + or die "bad input line: $_"; + my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3; + if ($rt < $minrt) { + $min = $_; + $minrt = $rt; + } +} + +if (!defined $min) { + die "no input found"; +} + +print $min; diff --git a/t/perf/p0000-perf-lib-sanity.sh b/t/perf/p0000-perf-lib-sanity.sh new file mode 100755 index 0000000000..cf8e1efce7 --- /dev/null +++ b/t/perf/p0000-perf-lib-sanity.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='Tests whether perf-lib facilities work' +. ./perf-lib.sh + +test_perf_default_repo + +test_perf 'test_perf_default_repo works' ' + foo=$(git rev-parse HEAD) && + test_export foo +' + +test_checkout_worktree + +test_perf 'test_checkout_worktree works' ' + wt=$(find . | wc -l) && + idx=$(git ls-files | wc -l) && + test $wt -gt $idx +' + +baz=baz +test_export baz + +test_expect_success 'test_export works' ' + echo "$foo" && + test "$foo" = "$(git rev-parse HEAD)" && + echo "$baz" && + test "$baz" = baz +' + +test_perf 'export a weird var' ' + bar="weird # variable" && + test_export bar +' + +test_expect_success 'test_export works with weird vars' ' + echo "$bar" && + test "$bar" = "weird # variable" +' + +test_perf 'important variables available in subshells' ' + test -n "$HOME" && + test -n "$TEST_DIRECTORY" && + test -n "$TRASH_DIRECTORY" && + test -n "$GIT_BUILD_DIR" +' + +test_perf 'test-lib-functions correctly loaded in subshells' ' + : >a && + test_path_is_file a && + : >b && + test_cmp a b +' + +test_done diff --git a/t/perf/p0001-rev-list.sh b/t/perf/p0001-rev-list.sh new file mode 100755 index 0000000000..4f71a63b0a --- /dev/null +++ b/t/perf/p0001-rev-list.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +test_description="Tests history walking performance" + +. ./perf-lib.sh + +test_perf_default_repo + +test_perf 'rev-list --all' ' + git rev-list --all >/dev/null +' + +test_perf 'rev-list --all --objects' ' + git rev-list --all --objects >/dev/null +' + +test_done diff --git a/t/perf/p4000-diff-algorithms.sh b/t/perf/p4000-diff-algorithms.sh new file mode 100755 index 0000000000..7e00c9da47 --- /dev/null +++ b/t/perf/p4000-diff-algorithms.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +test_description="Tests diff generation performance" + +. ./perf-lib.sh + +test_perf_default_repo + +test_perf 'log -3000 (baseline)' ' + git log -3000 >/dev/null +' + +test_perf 'log --raw -3000 (tree-only)' ' + git log --raw -3000 >/dev/null +' + +test_perf 'log -p -3000 (Myers)' ' + git log -p -3000 >/dev/null +' + +test_perf 'log -p -3000 --histogram' ' + git log -p -3000 --histogram >/dev/null +' + +test_perf 'log -p -3000 --patience' ' + git log -p -3000 --patience >/dev/null +' + +test_done diff --git a/t/perf/p5302-pack-index.sh b/t/perf/p5302-pack-index.sh new file mode 100755 index 0000000000..6cb5b0d55b --- /dev/null +++ b/t/perf/p5302-pack-index.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +test_description="Tests index-pack performance" + +. ./perf-lib.sh + +test_perf_large_repo + +test_expect_success 'repack' ' + git repack -ad && + PACK=`ls .git/objects/pack/*.pack | head -n1` && + test -f "$PACK" && + export PACK +' + +test_perf 'index-pack 0 threads' ' + GIT_DIR=t1 git index-pack --threads=1 --stdin < $PACK +' + +test_perf 'index-pack 1 thread ' ' + GIT_DIR=t2 GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK +' + +test_perf 'index-pack 2 threads' ' + GIT_DIR=t3 git index-pack --threads=2 --stdin < $PACK +' + +test_perf 'index-pack 4 threads' ' + GIT_DIR=t4 git index-pack --threads=4 --stdin < $PACK +' + +test_perf 'index-pack 8 threads' ' + GIT_DIR=t5 git index-pack --threads=8 --stdin < $PACK +' + +test_perf 'index-pack default number of threads' ' + GIT_DIR=t6 git index-pack --stdin < $PACK +' + +test_done diff --git a/t/perf/p7810-grep.sh b/t/perf/p7810-grep.sh new file mode 100755 index 0000000000..9f4ade639f --- /dev/null +++ b/t/perf/p7810-grep.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description="git-grep performance in various modes" + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +test_perf 'grep worktree, cheap regex' ' + git grep some_nonexistent_string || : +' +test_perf 'grep worktree, expensive regex' ' + git grep "^.* *some_nonexistent_string$" || : +' +test_perf 'grep --cached, cheap regex' ' + git grep --cached some_nonexistent_string || : +' +test_perf 'grep --cached, expensive regex' ' + git grep --cached "^.* *some_nonexistent_string$" || : +' + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh new file mode 100644 index 0000000000..5580c22812 --- /dev/null +++ b/t/perf/perf-lib.sh @@ -0,0 +1,202 @@ +#!/bin/sh +# +# Copyright (c) 2011 Thomas Rast +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/ . + +# do the --tee work early; it otherwise confuses our careful +# GIT_BUILD_DIR mangling +case "$GIT_TEST_TEE_STARTED, $* " in +done,*) + # do not redirect again + ;; +*' --tee '*|*' --va'*) + mkdir -p test-results + BASE=test-results/$(basename "$0" .sh) + (GIT_TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1; + echo $? > $BASE.exit) | tee $BASE.out + test "$(cat $BASE.exit)" = 0 + exit + ;; +esac + +TEST_DIRECTORY=$(pwd)/.. +TEST_OUTPUT_DIRECTORY=$(pwd) +if test -z "$GIT_TEST_INSTALLED"; then + perf_results_prefix= +else + perf_results_prefix=$(printf "%s" "${GIT_TEST_INSTALLED%/bin-wrappers}" | tr -c "[a-zA-Z0-9]" "[_*]")"." + # make the tested dir absolute + GIT_TEST_INSTALLED=$(cd "$GIT_TEST_INSTALLED" && pwd) +fi + +TEST_NO_CREATE_REPO=t + +. ../test-lib.sh + +# Variables from test-lib that are normally internal to the tests; we +# need to export them for test_perf subshells +export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP + +perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results +mkdir -p "$perf_results_dir" +rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests + +if test -z "$GIT_PERF_REPEAT_COUNT"; then + GIT_PERF_REPEAT_COUNT=3 +fi +die_if_build_dir_not_repo () { + if ! ( cd "$TEST_DIRECTORY/.." && + git rev-parse --build-dir >/dev/null 2>&1 ); then + error "No $1 defined, and your build directory is not a repo" + fi +} + +if test -z "$GIT_PERF_REPO"; then + die_if_build_dir_not_repo '$GIT_PERF_REPO' + GIT_PERF_REPO=$TEST_DIRECTORY/.. +fi +if test -z "$GIT_PERF_LARGE_REPO"; then + die_if_build_dir_not_repo '$GIT_PERF_LARGE_REPO' + GIT_PERF_LARGE_REPO=$TEST_DIRECTORY/.. +fi + +test_perf_create_repo_from () { + test "$#" = 2 || + error "bug in the test script: not 2 parameters to test-create-repo" + repo="$1" + source="$2" + source_git=$source/$(cd "$source" && git rev-parse --git-dir) + mkdir -p "$repo/.git" + ( + cd "$repo/.git" && + { cp -Rl "$source_git/objects" . 2>/dev/null || + cp -R "$source_git/objects" .; } && + for stuff in "$source_git"/*; do + case "$stuff" in + */objects|*/hooks|*/config) + ;; + *) + cp -R "$stuff" . || break + ;; + esac + done && + cd .. && + git init -q && + mv .git/hooks .git/hooks-disabled 2>/dev/null + ) || error "failed to copy repository '$source' to '$repo'" +} + +# call at least one of these to establish an appropriately-sized repository +test_perf_default_repo () { + test_perf_create_repo_from "${1:-$TRASH_DIRECTORY}" "$GIT_PERF_REPO" +} +test_perf_large_repo () { + if test "$GIT_PERF_LARGE_REPO" = "$GIT_BUILD_DIR"; then + echo "warning: \$GIT_PERF_LARGE_REPO is \$GIT_BUILD_DIR." >&2 + echo "warning: This will work, but may not be a sufficiently large repo" >&2 + echo "warning: for representative measurements." >&2 + fi + test_perf_create_repo_from "${1:-$TRASH_DIRECTORY}" "$GIT_PERF_LARGE_REPO" +} +test_checkout_worktree () { + git checkout-index -u -a || + error "git checkout-index failed" +} + +# Performance tests should never fail. If they do, stop immediately +immediate=t + +test_run_perf_ () { + test_cleanup=: + test_export_="test_cleanup" + export test_cleanup test_export_ + /usr/bin/time -f "%E %U %S" -o test_time.$i "$SHELL" -c ' +. '"$TEST_DIRECTORY"/test-lib-functions.sh' +test_export () { + [ $# != 0 ] || return 0 + test_export_="$test_export_\\|$1" + shift + test_export "$@" +} +'"$1"' +ret=$? +set | sed -n "s'"/'/'\\\\''/g"';s/^\\($test_export_\\)/export '"'&'"'/p" >test_vars +exit $ret' >&3 2>&4 + eval_ret=$? + + if test $eval_ret = 0 || test -n "$expecting_failure" + then + test_eval_ "$test_cleanup" + . ./test_vars || error "failed to load updated environment" + fi + if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then + echo "" + fi + return "$eval_ret" +} + + +test_perf () { + test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= + test "$#" = 2 || + error "bug in the test script: not 2 or 3 parameters to test-expect-success" + export test_prereq + if ! test_skip "$@" + then + base=$(basename "$0" .sh) + echo "$test_count" >>"$perf_results_dir"/$base.subtests + echo "$1" >"$perf_results_dir"/$base.$test_count.descr + if test -z "$verbose"; then + echo -n "perf $test_count - $1:" + else + echo "perf $test_count - $1:" + fi + for i in $(seq 1 $GIT_PERF_REPEAT_COUNT); do + say >&3 "running: $2" + if test_run_perf_ "$2" + then + if test -z "$verbose"; then + echo -n " $i" + else + echo "* timing run $i/$GIT_PERF_REPEAT_COUNT:" + fi + else + test -z "$verbose" && echo + test_failure_ "$@" + break + fi + done + if test -z "$verbose"; then + echo " ok" + else + test_ok_ "$1" + fi + base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" .sh)"."$test_count" + "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times + fi + echo >&3 "" +} + +# We extend test_done to print timings at the end (./run disables this +# and does it after running everything) +test_at_end_hook_ () { + if test -z "$GIT_PERF_AGGREGATING_LATER"; then + ( cd "$TEST_DIRECTORY"/perf && ./aggregate.perl $(basename "$0") ) + fi +} + +test_export () { + export "$@" +} diff --git a/t/perf/run b/t/perf/run new file mode 100755 index 0000000000..cfd70129bb --- /dev/null +++ b/t/perf/run @@ -0,0 +1,82 @@ +#!/bin/sh + +case "$1" in + --help) + echo "usage: $0 [other_git_tree...] [--] [test_scripts]" + exit 0 + ;; +esac + +die () { + echo >&2 "error: $*" + exit 1 +} + +run_one_dir () { + if test $# -eq 0; then + set -- p????-*.sh + fi + echo "=== Running $# tests in ${GIT_TEST_INSTALLED:-this tree} ===" + for t in "$@"; do + ./$t $GIT_TEST_OPTS + done +} + +unpack_git_rev () { + rev=$1 + mkdir -p build/$rev + (cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) | + (cd build/$rev && tar x) +} +build_git_rev () { + rev=$1 + cp ../../config.mak build/$rev/config.mak + (cd build/$rev && make $GIT_PERF_MAKE_OPTS) || + die "failed to build revision '$mydir'" +} + +run_dirs_helper () { + mydir=${1%/} + shift + while test $# -gt 0 -a "$1" != -- -a ! -f "$1"; do + shift + done + if test $# -gt 0 -a "$1" = --; then + shift + fi + if [ ! -d "$mydir" ]; then + rev=$(git rev-parse --verify "$mydir" 2>/dev/null) || + die "'$mydir' is neither a directory nor a valid revision" + if [ ! -d build/$rev ]; then + unpack_git_rev $rev + fi + build_git_rev $rev + mydir=build/$rev + fi + if test "$mydir" = .; then + unset GIT_TEST_INSTALLED + else + GIT_TEST_INSTALLED="$mydir/bin-wrappers" + export GIT_TEST_INSTALLED + fi + run_one_dir "$@" +} + +run_dirs () { + while test $# -gt 0 -a "$1" != -- -a ! -f "$1"; do + run_dirs_helper "$@" + shift + done +} + +GIT_PERF_AGGREGATING_LATER=t +export GIT_PERF_AGGREGATING_LATER + +cd "$(dirname $0)" +. ../../GIT-BUILD-OPTIONS + +if test $# = 0 -o "$1" = -- -o -f "$1"; then + set -- . "$@" +fi +run_dirs "$@" +./aggregate.perl "$@" diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index f4e8f43bae..ccb5435b2a 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -34,69 +34,69 @@ fi # git init has been done in an empty repository. # make sure it is empty. -find .git/objects -type f -print >should-be-empty -test_expect_success \ - '.git/objects should be empty after git init in an empty repo.' \ - 'cmp -s /dev/null should-be-empty' +test_expect_success '.git/objects should be empty after git init in an empty repo' ' + find .git/objects -type f -print >should-be-empty && + test_line_count = 0 should-be-empty +' # also it should have 2 subdirectories; no fan-out anymore, pack, and info. # 3 is counting "objects" itself -find .git/objects -type d -print >full-of-directories -test_expect_success \ - '.git/objects should have 3 subdirectories.' \ - 'test $(wc -l < full-of-directories) = 3' +test_expect_success '.git/objects should have 3 subdirectories' ' + find .git/objects -type d -print >full-of-directories && + test_line_count = 3 full-of-directories +' ################################################################ # Test harness test_expect_success 'success is reported like this' ' - : + : ' test_expect_failure 'pretend we have a known breakage' ' - false + false ' test_expect_success 'pretend we have fixed a known breakage (run in sub test-lib)' " - mkdir passing-todo && - (cd passing-todo && - cat >passing-todo.sh <<EOF && -#!$SHELL_PATH - -test_description='A passing TODO test - -This is run in a sub test-lib so that we do not get incorrect passing -metrics -' - -# Point to the t/test-lib.sh, which isn't in ../ as usual -TEST_DIRECTORY=\"$TEST_DIRECTORY\" -. \"\$TEST_DIRECTORY\"/test-lib.sh - -test_expect_failure 'pretend we have fixed a known breakage' ' - : -' - -test_done -EOF - chmod +x passing-todo.sh && - ./passing-todo.sh >out 2>err && - ! test -s err && -sed -e 's/^> //' >expect <<EOF && -> ok 1 - pretend we have fixed a known breakage # TODO known breakage -> # fixed 1 known breakage(s) -> # passed all 1 test(s) -> 1..1 -EOF - test_cmp expect out) + mkdir passing-todo && + (cd passing-todo && + cat >passing-todo.sh <<-EOF && + #!$SHELL_PATH + + test_description='A passing TODO test + + This is run in a sub test-lib so that we do not get incorrect + passing metrics + ' + + # Point to the t/test-lib.sh, which isn't in ../ as usual + TEST_DIRECTORY=\"$TEST_DIRECTORY\" + . \"\$TEST_DIRECTORY\"/test-lib.sh + + test_expect_failure 'pretend we have fixed a known breakage' ' + : + ' + + test_done + EOF + chmod +x passing-todo.sh && + ./passing-todo.sh >out 2>err && + ! test -s err && + sed -e 's/^> //' >expect <<-\\EOF && + > ok 1 - pretend we have fixed a known breakage # TODO known breakage + > # fixed 1 known breakage(s) + > # passed all 1 test(s) + > 1..1 + EOF + test_cmp expect out) " test_set_prereq HAVEIT haveit=no test_expect_success HAVEIT 'test runs if prerequisite is satisfied' ' - test_have_prereq HAVEIT && - haveit=yes + test_have_prereq HAVEIT && + haveit=yes ' donthaveit=yes test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' ' - donthaveit=no + donthaveit=no ' if test $haveit$donthaveit != yesyes then @@ -107,17 +107,17 @@ fi test_set_prereq HAVETHIS haveit=no test_expect_success HAVETHIS,HAVEIT 'test runs if prerequisites are satisfied' ' - test_have_prereq HAVEIT && - test_have_prereq HAVETHIS && - haveit=yes + test_have_prereq HAVEIT && + test_have_prereq HAVETHIS && + haveit=yes ' donthaveit=yes test_expect_success HAVEIT,DONTHAVEIT 'unmet prerequisites causes test to be skipped' ' - donthaveit=no + donthaveit=no ' donthaveiteither=yes test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' ' - donthaveiteither=no + donthaveiteither=no ' if test $haveit$donthaveit$donthaveiteither != yesyesyes then @@ -127,7 +127,7 @@ fi clean=no test_expect_success 'tests clean up after themselves' ' - test_when_finished clean=yes + test_when_finished clean=yes ' if test $clean != yes @@ -137,106 +137,100 @@ then fi test_expect_success 'tests clean up even on failures' " - mkdir failing-cleanup && - (cd failing-cleanup && - cat >failing-cleanup.sh <<EOF && -#!$SHELL_PATH - -test_description='Failing tests with cleanup commands' - -# Point to the t/test-lib.sh, which isn't in ../ as usual -TEST_DIRECTORY=\"$TEST_DIRECTORY\" -. \"\$TEST_DIRECTORY\"/test-lib.sh - -test_expect_success 'tests clean up even after a failure' ' - touch clean-after-failure && - test_when_finished rm clean-after-failure && - (exit 1) -' - -test_expect_success 'failure to clean up causes the test to fail' ' - test_when_finished \"(exit 2)\" -' - -test_done -EOF - chmod +x failing-cleanup.sh && - test_must_fail ./failing-cleanup.sh >out 2>err && - ! test -s err && - ! test -f \"trash directory.failing-cleanup/clean-after-failure\" && -sed -e 's/Z$//' -e 's/^> //' >expect <<\EOF && -> not ok - 1 tests clean up even after a failure -> # Z -> # touch clean-after-failure && -> # test_when_finished rm clean-after-failure && -> # (exit 1) -> # Z -> not ok - 2 failure to clean up causes the test to fail -> # Z -> # test_when_finished \"(exit 2)\" -> # Z -> # failed 2 among 2 test(s) -> 1..2 -EOF - test_cmp expect out) + mkdir failing-cleanup && + ( + cd failing-cleanup && + + cat >failing-cleanup.sh <<-EOF && + #!$SHELL_PATH + + test_description='Failing tests with cleanup commands' + + # Point to the t/test-lib.sh, which isn't in ../ as usual + TEST_DIRECTORY=\"$TEST_DIRECTORY\" + . \"\$TEST_DIRECTORY\"/test-lib.sh + + test_expect_success 'tests clean up even after a failure' ' + touch clean-after-failure && + test_when_finished rm clean-after-failure && + (exit 1) + ' + test_expect_success 'failure to clean up causes the test to fail' ' + test_when_finished \"(exit 2)\" + ' + test_done + + EOF + + chmod +x failing-cleanup.sh && + test_must_fail ./failing-cleanup.sh >out 2>err && + ! test -s err && + ! test -f \"trash directory.failing-cleanup/clean-after-failure\" && + sed -e 's/Z$//' -e 's/^> //' >expect <<-\\EOF && + > not ok - 1 tests clean up even after a failure + > # Z + > # touch clean-after-failure && + > # test_when_finished rm clean-after-failure && + > # (exit 1) + > # Z + > not ok - 2 failure to clean up causes the test to fail + > # Z + > # test_when_finished \"(exit 2)\" + > # Z + > # failed 2 among 2 test(s) + > 1..2 + EOF + test_cmp expect out + ) " ################################################################ # Basics of the basics # updating a new file without --add should fail. -test_expect_success 'git update-index without --add should fail adding.' ' - test_must_fail git update-index should-be-empty +test_expect_success 'git update-index without --add should fail adding' ' + test_must_fail git update-index should-be-empty ' # and with --add it should succeed, even if it is empty (it used to fail). -test_expect_success \ - 'git update-index with --add should succeed.' \ - 'git update-index --add should-be-empty' +test_expect_success 'git update-index with --add should succeed' ' + git update-index --add should-be-empty +' -test_expect_success \ - 'writing tree out with git write-tree' \ - 'tree=$(git write-tree)' +test_expect_success 'writing tree out with git write-tree' ' + tree=$(git write-tree) +' # we know the shape and contents of the tree and know the object ID for it. -test_expect_success \ - 'validate object ID of a known tree.' \ - 'test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a' +test_expect_success 'validate object ID of a known tree' ' + test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a + ' # Removing paths. -rm -f should-be-empty full-of-directories -test_expect_success 'git update-index without --remove should fail removing.' ' - test_must_fail git update-index should-be-empty +test_expect_success 'git update-index without --remove should fail removing' ' + rm -f should-be-empty full-of-directories && + test_must_fail git update-index should-be-empty ' -test_expect_success \ - 'git update-index with --remove should be able to remove.' \ - 'git update-index --remove should-be-empty' +test_expect_success 'git update-index with --remove should be able to remove' ' + git update-index --remove should-be-empty +' # Empty tree can be written with recent write-tree. -test_expect_success \ - 'git write-tree should be able to write an empty tree.' \ - 'tree=$(git write-tree)' +test_expect_success 'git write-tree should be able to write an empty tree' ' + tree=$(git write-tree) +' -test_expect_success \ - 'validate object ID of a known tree.' \ - 'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904' +test_expect_success 'validate object ID of a known tree' ' + test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +' # Various types of objects + # Some filesystems do not support symblic links; on such systems # some expected values are different -mkdir path2 path3 path3/subp3 -paths='path0 path2/file2 path3/file3 path3/subp3/file3' -for p in $paths -do - echo "hello $p" >$p -done if test_have_prereq SYMLINKS then - for p in $paths - do - ln -s "hello $p" ${p}sym - done expectfilter=cat expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3 @@ -248,135 +242,154 @@ else expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f fi -test_expect_success \ - 'adding various types of objects with git update-index --add.' \ - 'find path* ! -type d -print | xargs git update-index --add' + +test_expect_success 'adding various types of objects with git update-index --add' ' + mkdir path2 path3 path3/subp3 && + paths="path0 path2/file2 path3/file3 path3/subp3/file3" && + ( + for p in $paths + do + echo "hello $p" >$p || exit 1 + if test_have_prereq SYMLINKS + then + ln -s "hello $p" ${p}sym || exit 1 + fi + done + ) && + find path* ! -type d -print | xargs git update-index --add +' # Show them and see that matches what we expect. -test_expect_success \ - 'showing stage with git ls-files --stage' \ - 'git ls-files --stage >current' - -$expectfilter >expected <<\EOF -100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 -120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym -100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 -120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym -100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3 -120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym -100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3 -120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym -EOF -test_expect_success \ - 'validate git ls-files output for a known tree.' \ - 'test_cmp expected current' - -test_expect_success \ - 'writing tree out with git write-tree.' \ - 'tree=$(git write-tree)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$tree" = "$expectedtree"' - -test_expect_success \ - 'showing tree with git ls-tree' \ - 'git ls-tree $tree >current' -cat >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 -040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 -EOF -test_expect_success SYMLINKS \ - 'git ls-tree output for a known tree.' \ - 'test_cmp expected current' +test_expect_success 'showing stage with git ls-files --stage' ' + git ls-files --stage >current +' + +test_expect_success 'validate git ls-files output for a known tree' ' + $expectfilter >expected <<-\EOF && + 100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 + 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym + 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 + 120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym + 100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3 + 120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym + 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3 + 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym + EOF + test_cmp expected current +' + +test_expect_success 'writing tree out with git write-tree' ' + tree=$(git write-tree) +' + +test_expect_success 'validate object ID for a known tree' ' + test "$tree" = "$expectedtree" +' + +test_expect_success 'showing tree with git ls-tree' ' + git ls-tree $tree >current +' + +test_expect_success SYMLINKS 'git ls-tree output for a known tree' ' + cat >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 + 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 + EOF + test_cmp expected current +' # This changed in ls-tree pathspec change -- recursive does # not show tree nodes anymore. -test_expect_success \ - 'showing tree with git ls-tree -r' \ - 'git ls-tree -r $tree >current' -$expectfilter >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 -120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym -100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 -120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym -100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 -120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym -EOF -test_expect_success \ - 'git ls-tree -r output for a known tree.' \ - 'test_cmp expected current' +test_expect_success 'showing tree with git ls-tree -r' ' + git ls-tree -r $tree >current +' + +test_expect_success 'git ls-tree -r output for a known tree' ' + $expectfilter >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 + 120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym + 100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 + 120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym + 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 + 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym + EOF + test_cmp expected current +' # But with -r -t we can have both. -test_expect_success \ - 'showing tree with git ls-tree -r -t' \ - 'git ls-tree -r -t $tree >current' -cat >expected <<\EOF -100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 -120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 -100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 -120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym -040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 -100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 -120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym -040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 -100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 -120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym -EOF -test_expect_success SYMLINKS \ - 'git ls-tree -r output for a known tree.' \ - 'test_cmp expected current' - -test_expect_success \ - 'writing partial tree out with git write-tree --prefix.' \ - 'ptree=$(git write-tree --prefix=path3)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$ptree" = "$expectedptree1"' - -test_expect_success \ - 'writing partial tree out with git write-tree --prefix.' \ - 'ptree=$(git write-tree --prefix=path3/subp3)' -test_expect_success \ - 'validate object ID for a known tree.' \ - 'test "$ptree" = "$expectedptree2"' - -cat >badobjects <<EOF -100644 blob 1000000000000000000000000000000000000000 dir/file1 -100644 blob 2000000000000000000000000000000000000000 dir/file2 -100644 blob 3000000000000000000000000000000000000000 dir/file3 -100644 blob 4000000000000000000000000000000000000000 dir/file4 -100644 blob 5000000000000000000000000000000000000000 dir/file5 -EOF +test_expect_success 'showing tree with git ls-tree -r -t' ' + git ls-tree -r -t $tree >current +' -rm .git/index -test_expect_success \ - 'put invalid objects into the index.' \ - 'git update-index --index-info < badobjects' +test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' ' + cat >expected <<-\EOF && + 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 + 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym + 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 + 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 + 120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym + 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 + 100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 + 120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym + 040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 + 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 + 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym + EOF + test_cmp expected current +' -test_expect_success 'writing this tree without --missing-ok.' ' - test_must_fail git write-tree +test_expect_success 'writing partial tree out with git write-tree --prefix' ' + ptree=$(git write-tree --prefix=path3) ' -test_expect_success \ - 'writing this tree with --missing-ok.' \ - 'git write-tree --missing-ok' +test_expect_success 'validate object ID for a known tree' ' + test "$ptree" = "$expectedptree1" +' + +test_expect_success 'writing partial tree out with git write-tree --prefix' ' + ptree=$(git write-tree --prefix=path3/subp3) +' + +test_expect_success 'validate object ID for a known tree' ' + test "$ptree" = "$expectedptree2" +' + +test_expect_success 'put invalid objects into the index' ' + rm -f .git/index && + cat >badobjects <<-\EOF && + 100644 blob 1000000000000000000000000000000000000000 dir/file1 + 100644 blob 2000000000000000000000000000000000000000 dir/file2 + 100644 blob 3000000000000000000000000000000000000000 dir/file3 + 100644 blob 4000000000000000000000000000000000000000 dir/file4 + 100644 blob 5000000000000000000000000000000000000000 dir/file5 + EOF + git update-index --index-info <badobjects +' + +test_expect_success 'writing this tree without --missing-ok' ' + test_must_fail git write-tree +' + +test_expect_success 'writing this tree with --missing-ok' ' + git write-tree --missing-ok +' ################################################################ -rm .git/index -test_expect_success \ - 'git read-tree followed by write-tree should be idempotent.' \ - 'git read-tree $tree && - test -f .git/index && - newtree=$(git write-tree) && - test "$newtree" = "$tree"' - -$expectfilter >expected <<\EOF +test_expect_success 'git read-tree followed by write-tree should be idempotent' ' + rm -f .git/index + git read-tree $tree && + test -f .git/index && + newtree=$(git write-tree) && + test "$newtree" = "$tree" +' + +test_expect_success 'validate git diff-files output for a know cache/work tree state' ' + $expectfilter >expected <<\EOF && :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2 @@ -386,45 +399,47 @@ $expectfilter >expected <<\EOF :100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M path3/subp3/file3 :120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M path3/subp3/file3sym EOF -test_expect_success \ - 'validate git diff-files output for a know cache/work tree state.' \ - 'git diff-files >current && test_cmp current expected >/dev/null' + git diff-files >current && + test_cmp current expected +' -test_expect_success \ - 'git update-index --refresh should succeed.' \ - 'git update-index --refresh' +test_expect_success 'git update-index --refresh should succeed' ' + git update-index --refresh +' -test_expect_success \ - 'no diff after checkout and git update-index --refresh.' \ - 'git diff-files >current && cmp -s current /dev/null' +test_expect_success 'no diff after checkout and git update-index --refresh' ' + git diff-files >current && + cmp -s current /dev/null +' ################################################################ P=$expectedtree -test_expect_success \ - 'git commit-tree records the correct tree in a commit.' \ - 'commit0=$(echo NO | git commit-tree $P) && - tree=$(git show --pretty=raw $commit0 | - sed -n -e "s/^tree //p" -e "/^author /q") && - test "z$tree" = "z$P"' - -test_expect_success \ - 'git commit-tree records the correct parent in a commit.' \ - 'commit1=$(echo NO | git commit-tree $P -p $commit0) && - parent=$(git show --pretty=raw $commit1 | - sed -n -e "s/^parent //p" -e "/^author /q") && - test "z$commit0" = "z$parent"' - -test_expect_success \ - 'git commit-tree omits duplicated parent in a commit.' \ - 'commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) && - parent=$(git show --pretty=raw $commit2 | - sed -n -e "s/^parent //p" -e "/^author /q" | - sort -u) && - test "z$commit0" = "z$parent" && - numparent=$(git show --pretty=raw $commit2 | - sed -n -e "s/^parent //p" -e "/^author /q" | - wc -l) && - test $numparent = 1' + +test_expect_success 'git commit-tree records the correct tree in a commit' ' + commit0=$(echo NO | git commit-tree $P) && + tree=$(git show --pretty=raw $commit0 | + sed -n -e "s/^tree //p" -e "/^author /q") && + test "z$tree" = "z$P" +' + +test_expect_success 'git commit-tree records the correct parent in a commit' ' + commit1=$(echo NO | git commit-tree $P -p $commit0) && + parent=$(git show --pretty=raw $commit1 | + sed -n -e "s/^parent //p" -e "/^author /q") && + test "z$commit0" = "z$parent" +' + +test_expect_success 'git commit-tree omits duplicated parent in a commit' ' + commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) && + parent=$(git show --pretty=raw $commit2 | + sed -n -e "s/^parent //p" -e "/^author /q" | + sort -u) && + test "z$commit0" = "z$parent" && + numparent=$(git show --pretty=raw $commit2 | + sed -n -e "s/^parent //p" -e "/^author /q" | + wc -l) && + test $numparent = 1 +' test_expect_success 'update-index D/F conflict' ' mv path0 tmp && diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index ebbc7554a7..51f3045ba4 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,57 +83,135 @@ 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 'prefixes are not confused with leading directories' ' + attr_check a_plus/g unspecified && + cat >expect <<-\EOF && + a/g: test: a/g + a_plus/g: test: unspecified + EOF + git check-attr test a/g a_plus/g >actual && + test_cmp expect actual +' + test_expect_success 'core.attributesfile' ' attr_check global unspecified && git config core.attributesfile "$HOME/global-gitattributes" && 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 +221,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 +240,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 f87abb5a06..1d29810a7a 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -40,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..e50f0f742f 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 @@ -136,4 +153,41 @@ test_expect_success 'filter shell-escaped filenames' ' : ' +test_expect_success 'required filter success' ' + git config filter.required.smudge cat && + git config filter.required.clean cat && + git config filter.required.required true && + + echo "*.r filter=required" >.gitattributes && + + echo test >test.r && + git add test.r && + rm -f test.r && + git checkout -- test.r +' + +test_expect_success 'required filter smudge failure' ' + git config filter.failsmudge.smudge false && + git config filter.failsmudge.clean cat && + git config filter.failsmudge.required true && + + echo "*.fs filter=failsmudge" >.gitattributes && + + echo test >test.fs && + git add test.fs && + rm -f test.fs && + test_must_fail git checkout -- test.fs +' + +test_expect_success 'required filter clean failure' ' + git config filter.failclean.smudge cat && + git config filter.failclean.clean false && + git config filter.failclean.required true && + + echo "*.fc filter=failclean" >.gitattributes && + + echo test >test.fc && + test_must_fail git add test.fc +' + test_done diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh index aaed725402..f9bbb91f64 100755 --- a/t/t0023-crlf-am.sh +++ b/t/t0023-crlf-am.sh @@ -11,7 +11,7 @@ Date: Thu, 23 Aug 2007 13:00:00 +0200 Subject: test1 --- - foo | 1 + + foo | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 foo diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ae266147b6..e3f354a45e 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -10,7 +10,10 @@ test_description='our own option parser' cat > expect << EOF usage: test-parse-options <options> - -b, --boolean get a boolean + --yes get a boolean + -D, --no-doubt begins with 'no-' + -B, --no-fear be brave + -b, --boolean increment by one -4, --or4 bitwise-or boolean with ...0100 --neg-or4 same as --no-or4 @@ -28,6 +31,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 @@ -52,6 +56,59 @@ test_expect_success 'test help' ' mv expect expect.err +cat >expect.template <<EOF +boolean: 0 +integer: 0 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +check() { + what="$1" && + shift && + expect="$1" && + shift && + sed "s/^$what .*/$what $expect/" <expect.template >expect && + test-parse-options $* >output 2>output.err && + test ! -s output.err && + test_cmp expect output +} + +check_unknown() { + case "$1" in + --*) + echo error: unknown option \`${1#--}\' >expect ;; + -*) + echo error: unknown switch \`${1#-}\' >expect ;; + esac && + cat expect.err >>expect && + test_must_fail test-parse-options $* >output 2>output.err && + test ! -s output && + test_cmp expect output.err +} + +test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes' +test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt' +test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D' +test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear' +test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B' + +test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes' +test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB' + +test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes' +test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt' + +test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear' +test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear' + +test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt' + cat > expect << EOF boolean: 2 integer: 1729 @@ -86,7 +143,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 ' @@ -179,6 +236,16 @@ test_expect_success 'detect possible typos' ' test_cmp typo.err output.err ' +cat > typo.err << EOF +error: did you mean \`--ambiguous\` (with two dashes ?) +EOF + +test_expect_success 'detect possible typos' ' + test_must_fail test-parse-options -ambiguous > output 2> output.err && + test ! -s output && + test_cmp typo.err output.err +' + cat > expect <<EOF boolean: 0 integer: 0 @@ -295,7 +362,7 @@ test_expect_success 'OPT_NEGBIT() works' ' test_cmp expect output ' -test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' ' +test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' ' test-parse-options + + + + + + > output 2> output.err && test ! -s output.err && test_cmp expect output @@ -337,4 +404,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 8d4938f019..17e969df60 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -34,4 +34,17 @@ test_expect_success POSIXPERM 'run_command reports EACCES' ' grep "fatal: cannot exec.*hello.sh" err ' +test_expect_success POSIXPERM 'unreadable directory in PATH' ' + mkdir local-command && + test_when_finished "chmod u+rwx local-command && rm -fr local-command" && + git config alias.nitfol "!echo frotz" && + chmod a-rx local-command && + ( + PATH=./local-command:$PATH && + git nitfol >actual + ) && + echo frotz >expect && + test_cmp expect actual +' + test_done diff --git a/t/t0062-revision-walking.sh b/t/t0062-revision-walking.sh new file mode 100755 index 0000000000..3d98eb847f --- /dev/null +++ b/t/t0062-revision-walking.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (c) 2012 Heiko Voigt +# + +test_description='Test revision walking api' + +. ./test-lib.sh + +cat >run_twice_expected <<-EOF +1st + > add b + > add a +2nd + > add b + > add a +EOF + +test_expect_success 'setup' ' + echo a > a && + git add a && + git commit -m "add a" && + echo b > b && + git add b && + git commit -m "add b" +' + +test_expect_success 'revision walking can be done twice' ' + test-revision-walking run-twice > run_twice_actual + test_cmp run_twice_expected run_twice_actual +' + +test_done diff --git a/t/t0080-vcs-svn.sh b/t/t0080-vcs-svn.sh deleted file mode 100755 index 99a314b080..0000000000 --- a/t/t0080-vcs-svn.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/sh - -test_description='check infrastructure for svn importer' - -. ./test-lib.sh -uint32_max=4294967295 - -test_expect_success 'obj pool: store data' ' - cat <<-\EOF >expected && - 0 - 1 - EOF - - test-obj-pool <<-\EOF >actual && - alloc one 16 - set one 13 - test one 13 - reset one - EOF - test_cmp expected actual -' - -test_expect_success 'obj pool: NULL is offset ~0' ' - echo "$uint32_max" >expected && - echo null one | test-obj-pool >actual && - test_cmp expected actual -' - -test_expect_success 'obj pool: out-of-bounds access' ' - cat <<-EOF >expected && - 0 - 0 - $uint32_max - $uint32_max - 16 - 20 - $uint32_max - EOF - - test-obj-pool <<-\EOF >actual && - alloc one 16 - alloc two 16 - offset one 20 - offset two 20 - alloc one 5 - offset one 20 - free one 1 - offset one 20 - reset one - reset two - EOF - test_cmp expected actual -' - -test_expect_success 'obj pool: high-water mark' ' - cat <<-\EOF >expected && - 0 - 0 - 10 - 20 - 20 - 20 - EOF - - test-obj-pool <<-\EOF >actual && - alloc one 10 - committed one - alloc one 10 - commit one - committed one - alloc one 10 - free one 20 - committed one - reset one - EOF - test_cmp expected actual -' - -test_expect_success 'string pool' ' - echo a does not equal b >expected.differ && - echo a equals a >expected.match && - echo equals equals equals >expected.matchmore && - - test-string-pool "a,--b" >actual.differ && - test-string-pool "a,a" >actual.match && - test-string-pool "equals-equals" >actual.matchmore && - test_must_fail test-string-pool a,a,a && - test_must_fail test-string-pool a && - - test_cmp expected.differ actual.differ && - test_cmp expected.match actual.match && - test_cmp expected.matchmore actual.matchmore -' - -test_expect_success 'treap sort' ' - cat <<-\EOF >unsorted && - 68 - 12 - 13 - 13 - 68 - 13 - 13 - 21 - 10 - 11 - 12 - 13 - 13 - EOF - sort unsorted >expected && - - test-treap <unsorted >actual && - test_cmp expected actual -' - -test_done diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh new file mode 100755 index 0000000000..6c33e28ee8 --- /dev/null +++ b/t/t0090-cache-tree.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +test_description="Test whether cache-tree is properly updated + +Tests whether various commands properly update and/or rewrite the +cache-tree extension. +" + . ./test-lib.sh + +cmp_cache_tree () { + test-dump-cache-tree >actual && + sed "s/$_x40/SHA/" <actual >filtered && + test_cmp "$1" filtered +} + +# We don't bother with actually checking the SHA1: +# test-dump-cache-tree already verifies that all existing data is +# correct. +test_shallow_cache_tree () { + printf "SHA (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >expect && + cmp_cache_tree expect +} + +test_invalid_cache_tree () { + echo "invalid (0 subtrees)" >expect && + printf "SHA #(ref) (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >>expect && + cmp_cache_tree expect +} + +test_no_cache_tree () { + : >expect && + cmp_cache_tree expect +} + +test_expect_failure 'initial commit has cache-tree' ' + test_commit foo && + test_shallow_cache_tree +' + +test_expect_success 'read-tree HEAD establishes cache-tree' ' + git read-tree HEAD && + test_shallow_cache_tree +' + +test_expect_success 'git-add invalidates cache-tree' ' + test_when_finished "git reset --hard; git read-tree HEAD" && + echo "I changed this file" > foo && + git add foo && + test_invalid_cache_tree +' + +test_expect_success 'update-index invalidates cache-tree' ' + test_when_finished "git reset --hard; git read-tree HEAD" && + echo "I changed this file" > foo && + git update-index --add foo && + test_invalid_cache_tree +' + +test_expect_success 'write-tree establishes cache-tree' ' + test-scrap-cache-tree && + git write-tree && + test_shallow_cache_tree +' + +test_expect_success 'test-scrap-cache-tree works' ' + git read-tree HEAD && + test-scrap-cache-tree && + test_no_cache_tree +' + +test_expect_success 'second commit has cache-tree' ' + test_commit bar && + test_shallow_cache_tree +' + +test_expect_success 'reset --hard gives cache-tree' ' + test-scrap-cache-tree && + git reset --hard && + test_shallow_cache_tree +' + +test_expect_success 'reset --hard without index gives cache-tree' ' + rm -f .git/index && + git reset --hard && + test_shallow_cache_tree +' + +test_expect_failure 'checkout gives cache-tree' ' + git checkout HEAD^ && + test_shallow_cache_tree +' + +test_done diff --git a/t/t0200-gettext-basic.sh b/t/t0200-gettext-basic.sh new file mode 100755 index 0000000000..8853d8afb9 --- /dev/null +++ b/t/t0200-gettext-basic.sh @@ -0,0 +1,108 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description='Gettext support for Git' + +. ./lib-gettext.sh + +test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" ' + test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME" +' + +test_expect_success 'sanity: $TEXTDOMAIN is git' ' + test $TEXTDOMAIN = "git" +' + +test_expect_success 'xgettext sanity: Perl _() strings are not extracted' ' + ! grep "A Perl string xgettext will not get" "$GIT_PO_PATH"/is.po +' + +test_expect_success 'xgettext sanity: Comment extraction with --add-comments' ' + grep "TRANSLATORS: This is a test" "$TEST_DIRECTORY"/t0200/* | wc -l >expect && + grep "TRANSLATORS: This is a test" "$GIT_PO_PATH"/is.po | wc -l >actual && + test_cmp expect actual +' + +test_expect_success 'xgettext sanity: Comment extraction with --add-comments stops at statements' ' + ! grep "This is a phony" "$GIT_PO_PATH"/is.po && + ! grep "the above comment" "$GIT_PO_PATH"/is.po +' + +test_expect_success GETTEXT 'sanity: $TEXTDOMAINDIR exists without NO_GETTEXT=YesPlease' ' + test -d "$TEXTDOMAINDIR" && + test "$TEXTDOMAINDIR" = "$GIT_TEXTDOMAINDIR" +' + +test_expect_success GETTEXT 'sanity: Icelandic locale was compiled' ' + test -f "$TEXTDOMAINDIR/is/LC_MESSAGES/git.mo" +' + +# TODO: When we have more locales, generalize this to test them +# all. Maybe we'll need a dir->locale map for that. +test_expect_success GETTEXT_LOCALE 'sanity: gettext("") metadata is OK' ' + # Return value may be non-zero + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >zero-expect && + grep "Project-Id-Version: Git" zero-expect && + grep "Git Mailing List <git@vger.kernel.org>" zero-expect && + grep "Content-Type: text/plain; charset=UTF-8" zero-expect && + grep "Content-Transfer-Encoding: 8bit" zero-expect +' + +test_expect_success GETTEXT_LOCALE 'sanity: gettext(unknown) is passed through' ' + printf "This is not a translation string" >expect && + gettext "This is not a translation string" >actual && + eval_gettext "This is not a translation string" >actual && + test_cmp expect actual +' + +# xgettext from C +test_expect_success GETTEXT_LOCALE 'xgettext: C extraction of _() and N_() strings' ' + printf "TILRAUN: C tilraunastrengur" >expect && + printf "\n" >>expect && + printf "Sjá '\''git help SKIPUN'\'' til að sjá hjálp fyrir tiltekna skipun." >>expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string" >actual && + printf "\n" >>actual && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "See '\''git help COMMAND'\'' for more information on a specific command." >>actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_LOCALE 'xgettext: C extraction with %s' ' + printf "TILRAUN: C tilraunastrengur %%s" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A C test string %s" >actual && + test_cmp expect actual +' + +# xgettext from Shell +test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction' ' + printf "TILRAUN: Skeljartilraunastrengur" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Shell test string" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_LOCALE 'xgettext: Shell extraction with $variable' ' + printf "TILRAUN: Skeljartilraunastrengur með breytunni a var i able" >x-expect && + LANGUAGE=is LC_ALL="$is_IS_locale" variable="a var i able" eval_gettext "TEST: A Shell test \$variable" >x-actual && + test_cmp x-expect x-actual +' + +# xgettext from Perl +test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction' ' + printf "TILRAUN: Perl tilraunastrengur" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test string" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_LOCALE 'xgettext: Perl extraction with %s' ' + printf "TILRAUN: Perl tilraunastrengur með breytunni %%s" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: A Perl test variable %s" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_LOCALE 'sanity: Some gettext("") data for real locale' ' + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "" >real-locale && + test -s real-locale +' + +test_done diff --git a/t/t0200/test.c b/t/t0200/test.c new file mode 100644 index 0000000000..584d45cf36 --- /dev/null +++ b/t/t0200/test.c @@ -0,0 +1,23 @@ +/* This is a phony C program that's only here to test xgettext message extraction */ + +const char help[] = + /* TRANSLATORS: This is a test. You don't need to translate it. */ + N_("See 'git help COMMAND' for more information on a specific command."); + +int main(void) +{ + /* TRANSLATORS: This is a test. You don't need to translate it. */ + puts(_("TEST: A C test string")); + + /* TRANSLATORS: This is a test. You don't need to translate it. */ + printf(_("TEST: A C test string %s"), "variable"); + + /* TRANSLATORS: This is a test. You don't need to translate it. */ + printf(_("TEST: Hello World!")); + + /* TRANSLATORS: This is a test. You don't need to translate it. */ + printf(_("TEST: Old English Runes")); + + /* TRANSLATORS: This is a test. You don't need to translate it. */ + printf(_("TEST: ‘single’ and “double†quotes")); +} diff --git a/t/t0200/test.perl b/t/t0200/test.perl new file mode 100644 index 0000000000..36fba341ba --- /dev/null +++ b/t/t0200/test.perl @@ -0,0 +1,14 @@ +# This is a phony Perl program that's only here to test xgettext +# message extraction + +# so the above comment won't be folded into the next one by xgettext +1; + +# TRANSLATORS: This is a test. You don't need to translate it. +print __("TEST: A Perl test string"); + +# TRANSLATORS: This is a test. You don't need to translate it. +printf __("TEST: A Perl test variable %s"), "moo"; + +# TRANSLATORS: If you see this, Git has a bug +print _"TEST: A Perl string xgettext will not get"; diff --git a/t/t0200/test.sh b/t/t0200/test.sh new file mode 100644 index 0000000000..022d607f4c --- /dev/null +++ b/t/t0200/test.sh @@ -0,0 +1,14 @@ +# This is a phony Shell program that's only here to test xgettext +# message extraction + +# so the above comment won't be folded into the next one by xgettext +echo + +# TRANSLATORS: This is a test. You don't need to translate it. +gettext "TEST: A Shell test string" + +# TRANSLATORS: This is a test. You don't need to translate it. +eval_gettext "TEST: A Shell test \$variable" + +# TRANSLATORS: If you see this, Git has a bug +_("TEST: A Shell string xgettext won't get") diff --git a/t/t0201-gettext-fallbacks.sh b/t/t0201-gettext-fallbacks.sh index 54d98b9b10..52b1c27c2c 100755 --- a/t/t0201-gettext-fallbacks.sh +++ b/t/t0201-gettext-fallbacks.sh @@ -5,8 +5,24 @@ test_description='Gettext Shell fallbacks' -. ./test-lib.sh -. "$GIT_BUILD_DIR"/git-sh-i18n +GIT_INTERNAL_GETTEXT_TEST_FALLBACKS=YesPlease +export GIT_INTERNAL_GETTEXT_TEST_FALLBACKS + +. ./lib-gettext.sh + +test_expect_success "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" ' + test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME" +' + +test_expect_success 'sanity: $GIT_INTERNAL_GETTEXT_TEST_FALLBACKS is set' ' + test -n "$GIT_INTERNAL_GETTEXT_TEST_FALLBACKS" +' + +test_expect_success C_LOCALE_OUTPUT 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is fallthrough' ' + echo fallthrough >expect && + echo $GIT_INTERNAL_GETTEXT_SH_SCHEME >actual && + test_cmp expect actual +' test_expect_success 'gettext: our gettext() fallback has pass-through semantics' ' printf "test" >expect && diff --git a/t/t0202-gettext-perl.sh b/t/t0202-gettext-perl.sh new file mode 100755 index 0000000000..428ebb0080 --- /dev/null +++ b/t/t0202-gettext-perl.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description='Perl gettext interface (Git::I18N)' + +. ./lib-gettext.sh + +if ! test_have_prereq PERL; then + skip_all='skipping perl interface tests, perl not available' + test_done +fi + +"$PERL_PATH" -MTest::More -e 0 2>/dev/null || { + skip_all="Perl Test::More unavailable, skipping test" + test_done +} + +# The external test will outputs its own plan +test_external_has_tap=1 + +test_external_without_stderr \ + 'Perl Git::I18N API' \ + "$PERL_PATH" "$TEST_DIRECTORY"/t0202/test.pl + +test_done diff --git a/t/t0202/test.pl b/t/t0202/test.pl new file mode 100644 index 0000000000..2c10cb4693 --- /dev/null +++ b/t/t0202/test.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl +use 5.008; +use lib (split(/:/, $ENV{GITPERLLIB})); +use strict; +use warnings; +use POSIX qw(:locale_h); +use Test::More tests => 8; +use Git::I18N; + +my $has_gettext_library = $Git::I18N::__HAS_LIBRARY; + +ok(1, "Testing Git::I18N with " . + ($has_gettext_library + ? (defined $Locale::Messages::VERSION + ? "Locale::Messages version $Locale::Messages::VERSION" + # Versions of Locale::Messages before 1.17 didn't have a + # $VERSION variable. + : "Locale::Messages version <1.17") + : "NO Perl gettext library")); +ok(1, "Git::I18N is located at $INC{'Git/I18N.pm'}"); + +{ + my $exports = @Git::I18N::EXPORT; + ok($exports, "sanity: Git::I18N has $exports export(s)"); +} +is_deeply(\@Git::I18N::EXPORT, \@Git::I18N::EXPORT_OK, "sanity: Git::I18N exports everything by default"); + +# prototypes +{ + # Add prototypes here when modifying the public interface to add + # more gettext wrapper functions. + my %prototypes = (qw( + __ $ + )); + while (my ($sub, $proto) = each %prototypes) { + is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype"); + } +} + +# Test basic passthrough in the C locale +{ + local $ENV{LANGUAGE} = 'C'; + local $ENV{LC_ALL} = 'C'; + local $ENV{LANG} = 'C'; + + my ($got, $expect) = (('TEST: A Perl test string') x 2); + + is(__($got), $expect, "Passing a string through __() in the C locale works"); +} + +# Test a basic message on different locales +SKIP: { + unless ($ENV{GETTEXT_LOCALE}) { + # Can't reliably test __() with a non-C locales because the + # required locales may not be installed on the system. + # + # We test for these anyway as part of the shell + # tests. Skipping these here will eliminate failures on odd + # platforms with incomplete locale data. + + skip "GETTEXT_LOCALE must be set by lib-gettext.sh for exhaustive Git::I18N tests", 2; + } + + # The is_IS UTF-8 locale passed from lib-gettext.sh + my $is_IS_locale = $ENV{is_IS_locale}; + + my $test = sub { + my ($got, $expect, $msg, $locale) = @_; + # Maybe this system doesn't have the locale we're trying to + # test. + my $locale_ok = setlocale(LC_ALL, $locale); + is(__($got), $expect, "$msg a gettext library + <$locale> locale <$got> turns into <$expect>"); + }; + + my $env_C = sub { + $ENV{LANGUAGE} = 'C'; + $ENV{LC_ALL} = 'C'; + }; + + my $env_is = sub { + $ENV{LANGUAGE} = 'is'; + $ENV{LC_ALL} = $is_IS_locale; + }; + + # Translation's the same as the original + my ($got, $expect) = (('TEST: A Perl test string') x 2); + + if ($has_gettext_library) { + { + local %ENV; $env_C->(); + $test->($got, $expect, "With", 'C'); + } + + { + my ($got, $expect) = ($got, 'TILRAUN: Perl tilraunastrengur'); + local %ENV; $env_is->(); + $test->($got, $expect, "With", $is_IS_locale); + } + } else { + { + local %ENV; $env_C->(); + $test->($got, $expect, "Without", 'C'); + } + + { + local %ENV; $env_is->(); + $test->($got, $expect, "Without", 'is'); + } + } +} diff --git a/t/t0203-gettext-setlocale-sanity.sh b/t/t0203-gettext-setlocale-sanity.sh new file mode 100755 index 0000000000..a212460081 --- /dev/null +++ b/t/t0203-gettext-setlocale-sanity.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description="The Git C functions aren't broken by setlocale(3)" + +. ./lib-gettext.sh + +test_expect_success 'git show a ISO-8859-1 commit under C locale' ' + . "$TEST_DIRECTORY"/t3901-8859-1.txt && + test_commit "iso-c-commit" iso-under-c && + git show >out 2>err && + ! test -s err && + grep -q "iso-c-commit" out +' + +test_expect_success GETTEXT_LOCALE 'git show a ISO-8859-1 commit under a UTF-8 locale' ' + . "$TEST_DIRECTORY"/t3901-8859-1.txt && + test_commit "iso-utf8-commit" iso-under-utf8 && + LANGUAGE=is LC_ALL="$is_IS_locale" git show >out 2>err && + ! test -s err && + grep -q "iso-utf8-commit" out +' + +test_done diff --git a/t/t0204-gettext-reencode-sanity.sh b/t/t0204-gettext-reencode-sanity.sh new file mode 100755 index 0000000000..8437e51eb5 --- /dev/null +++ b/t/t0204-gettext-reencode-sanity.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description="Gettext reencoding of our *.po/*.mo files works" + +. ./lib-gettext.sh + +# The constants used in a tricky observation for undefined behaviour +RUNES="TILRAUN: ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛠᚻᛖ ᛒᚢᛞᛖ áš©áš¾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ áš¹á›áš¦ ᚦᚪ ᚹᛖᛥᚫ" +PUNTS="TILRAUN: ?? ???? ??? ?? ???? ?? ??? ????? ??????????? ??? ?? ????" +MSGKEY="TEST: Old English Runes" + +test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Icelandic' ' + printf "TILRAUN: Halló Heimur!" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: Hello World!" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_LOCALE 'gettext: Emitting UTF-8 from our UTF-8 *.mo files / Runes' ' + printf "%s" "$RUNES" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "$MSGKEY" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_ISO_LOCALE 'gettext: Emitting ISO-8859-1 from our UTF-8 *.mo files / Icelandic' ' + printf "TILRAUN: Halló Heimur!" | iconv -f UTF-8 -t ISO8859-1 >expect && + LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: Hello World!" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_ISO_LOCALE 'gettext: impossible ISO-8859-1 output' ' + LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "$MSGKEY" >runes && + case "$(cat runes)" in + "$MSGKEY") + say "Your system gives back the key to message catalog" + ;; + "$PUNTS") + say "Your system replaces an impossible character with ?" + ;; + "$RUNES") + say "Your system gives back the raw message for an impossible request" + ;; + *) + say "We never saw the error behaviour your system exhibits" + false + ;; + esac +' + +test_expect_success GETTEXT_LOCALE 'gettext: Fetching a UTF-8 msgid -> UTF-8' ' + printf "TILRAUN: ‚einfaldar‘ og „tvöfaldar“ gæsalappir" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" gettext "TEST: ‘single’ and “double†quotes" >actual && + test_cmp expect actual +' + +# How these quotes get transliterated depends on the gettext implementation: +# +# Debian: ,einfaldar' og ,,tvöfaldar" [GNU libintl] +# FreeBSD: `einfaldar` og "tvöfaldar" [GNU libintl] +# Solaris: ?einfaldar? og ?tvöfaldar? [Solaris libintl] +# +# Just make sure the contents are transliterated, and don't use grep -q +# so that these differences are emitted under --verbose for curious +# eyes. +test_expect_success GETTEXT_ISO_LOCALE 'gettext: Fetching a UTF-8 msgid -> ISO-8859-1' ' + LANGUAGE=is LC_ALL="$is_IS_iso_locale" gettext "TEST: ‘single’ and “double†quotes" >actual && + grep "einfaldar" actual && + grep "$(echo tvöfaldar | iconv -f UTF-8 -t ISO8859-1)" actual +' + +test_expect_success GETTEXT_LOCALE 'gettext.c: git init UTF-8 -> UTF-8' ' + printf "Bjó til tóma Git lind" >expect && + LANGUAGE=is LC_ALL="$is_IS_locale" git init repo >actual && + test_when_finished "rm -rf repo" && + grep "^$(cat expect) " actual +' + +test_expect_success GETTEXT_ISO_LOCALE 'gettext.c: git init UTF-8 -> ISO-8859-1' ' + printf "Bjó til tóma Git lind" >expect && + LANGUAGE=is LC_ALL="$is_IS_iso_locale" git init repo >actual && + test_when_finished "rm -rf repo" && + grep "^$(cat expect | iconv -f UTF-8 -t ISO8859-1) " actual +' + +test_done diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh new file mode 100755 index 0000000000..2361590d54 --- /dev/null +++ b/t/t0205-gettext-poison.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +test_description='Gettext Shell poison' + +. ./lib-gettext.sh + +test_expect_success GETTEXT_POISON "sanity: \$GIT_INTERNAL_GETTEXT_SH_SCHEME is set (to $GIT_INTERNAL_GETTEXT_SH_SCHEME)" ' + test -n "$GIT_INTERNAL_GETTEXT_SH_SCHEME" +' + +test_expect_success GETTEXT_POISON 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' ' + test "$GIT_INTERNAL_GETTEXT_SH_SCHEME" = "poison" +' + +test_expect_success GETTEXT_POISON 'gettext: our gettext() fallback has poison semantics' ' + printf "# GETTEXT POISON #" >expect && + gettext "test" >actual && + test_cmp expect actual && + printf "# GETTEXT POISON #" >expect && + gettext "test more words" >actual && + test_cmp expect actual +' + +test_expect_success GETTEXT_POISON 'eval_gettext: our eval_gettext() fallback has poison semantics' ' + printf "# GETTEXT POISON #" >expect && + eval_gettext "test" >actual && + test_cmp expect actual && + printf "# GETTEXT POISON #" >expect && + eval_gettext "test more words" >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh new file mode 100755 index 0000000000..20e28e34e7 --- /dev/null +++ b/t/t0300-credentials.sh @@ -0,0 +1,278 @@ +#!/bin/sh + +test_description='basic credential helper tests' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential.sh + +test_expect_success 'setup helper scripts' ' + cat >dump <<-\EOF && + whoami=`echo $0 | sed s/.*git-credential-//` + echo >&2 "$whoami: $*" + OIFS=$IFS + IFS== + while read key value; do + echo >&2 "$whoami: $key=$value" + eval "$key=$value" + done + IFS=$OIFS + EOF + + write_script git-credential-useless <<-\EOF && + . ./dump + exit 0 + EOF + + write_script git-credential-verbatim <<-\EOF && + user=$1; shift + pass=$1; shift + . ./dump + test -z "$user" || echo username=$user + test -z "$pass" || echo password=$pass + EOF + + PATH="$PWD:$PATH" +' + +test_expect_success 'credential_fill invokes helper' ' + check fill "verbatim foo bar" <<-\EOF + -- + username=foo + password=bar + -- + verbatim: get + EOF +' + +test_expect_success 'credential_fill invokes multiple helpers' ' + check fill useless "verbatim foo bar" <<-\EOF + -- + username=foo + password=bar + -- + useless: get + verbatim: get + EOF +' + +test_expect_success 'credential_fill stops when we get a full response' ' + check fill "verbatim one two" "verbatim three four" <<-\EOF + -- + username=one + password=two + -- + verbatim: get + EOF +' + +test_expect_success 'credential_fill continues through partial response' ' + check fill "verbatim one \"\"" "verbatim two three" <<-\EOF + -- + username=two + password=three + -- + verbatim: get + verbatim: get + verbatim: username=one + EOF +' + +test_expect_success 'credential_fill passes along metadata' ' + check fill "verbatim one two" <<-\EOF + protocol=ftp + host=example.com + path=foo.git + -- + username=one + password=two + -- + verbatim: get + verbatim: protocol=ftp + verbatim: host=example.com + verbatim: path=foo.git + EOF +' + +test_expect_success 'credential_approve calls all helpers' ' + check approve useless "verbatim one two" <<-\EOF + username=foo + password=bar + -- + -- + useless: store + useless: username=foo + useless: password=bar + verbatim: store + verbatim: username=foo + verbatim: password=bar + EOF +' + +test_expect_success 'do not bother storing password-less credential' ' + check approve useless <<-\EOF + username=foo + -- + -- + EOF +' + + +test_expect_success 'credential_reject calls all helpers' ' + check reject useless "verbatim one two" <<-\EOF + username=foo + password=bar + -- + -- + useless: erase + useless: username=foo + useless: password=bar + verbatim: erase + verbatim: username=foo + verbatim: password=bar + EOF +' + +test_expect_success 'usernames can be preserved' ' + check fill "verbatim \"\" three" <<-\EOF + username=one + -- + username=one + password=three + -- + verbatim: get + verbatim: username=one + EOF +' + +test_expect_success 'usernames can be overridden' ' + check fill "verbatim two three" <<-\EOF + username=one + -- + username=two + password=three + -- + verbatim: get + verbatim: username=one + EOF +' + +test_expect_success 'do not bother completing already-full credential' ' + check fill "verbatim three four" <<-\EOF + username=one + password=two + -- + username=one + password=two + -- + EOF +' + +# We can't test the basic terminal password prompt here because +# getpass() tries too hard to find the real terminal. But if our +# askpass helper is run, we know the internal getpass is working. +test_expect_success 'empty helper list falls back to internal getpass' ' + check fill <<-\EOF + -- + username=askpass-username + password=askpass-password + -- + askpass: Username: + askpass: Password: + EOF +' + +test_expect_success 'internal getpass does not ask for known username' ' + check fill <<-\EOF + username=foo + -- + username=foo + password=askpass-password + -- + askpass: Password: + EOF +' + +HELPER="!f() { + cat >/dev/null + echo username=foo + echo password=bar + }; f" +test_expect_success 'respect configured credentials' ' + test_config credential.helper "$HELPER" && + check fill <<-\EOF + -- + username=foo + password=bar + -- + EOF +' + +test_expect_success 'match configured credential' ' + test_config credential.https://example.com.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=example.com + path=repo.git + -- + username=foo + password=bar + -- + EOF +' + +test_expect_success 'do not match configured credential' ' + test_config credential.https://foo.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=bar + -- + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://bar'\'': + askpass: Password for '\''https://askpass-username@bar'\'': + EOF +' + +test_expect_success 'pull username from config' ' + test_config credential.https://example.com.username foo && + check fill <<-\EOF + protocol=https + host=example.com + -- + username=foo + password=askpass-password + -- + askpass: Password for '\''https://foo@example.com'\'': + EOF +' + +test_expect_success 'http paths can be part of context' ' + check fill "verbatim foo bar" <<-\EOF && + protocol=https + host=example.com + path=foo.git + -- + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF + test_config credential.https://example.com.useHttpPath true && + check fill "verbatim foo bar" <<-\EOF + protocol=https + host=example.com + path=foo.git + -- + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: path=foo.git + EOF +' + +test_done diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh new file mode 100755 index 0000000000..82c8411210 --- /dev/null +++ b/t/t0301-credential-cache.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description='credential-cache tests' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential.sh + +test -z "$NO_UNIX_SOCKETS" || { + skip_all='skipping credential-cache tests, unix sockets not available' + test_done +} + +# don't leave a stale daemon running +trap 'code=$?; git credential-cache exit; (exit $code); die' EXIT + +helper_test cache +helper_test_timeout cache --timeout=1 + +# we can't rely on our "trap" above working after test_done, +# as test_done will delete the trash directory containing +# our socket, leaving us with no way to access the daemon. +git credential-cache exit + +test_done diff --git a/t/t0302-credential-store.sh b/t/t0302-credential-store.sh new file mode 100755 index 0000000000..f61b40c69b --- /dev/null +++ b/t/t0302-credential-store.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +test_description='credential-store tests' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential.sh + +helper_test store + +test_done diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh new file mode 100755 index 0000000000..f028fd1418 --- /dev/null +++ b/t/t0303-credential-external.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='external credential helper tests + +This is a tool for authors of external helper tools to sanity-check +their helpers. If you have written the "git-credential-foo" helper, +you check it with: + + make GIT_TEST_CREDENTIAL_HELPER=foo t0303-credential-external.sh + +This assumes that your helper is capable of both storing and +retrieving credentials (some helpers may be read-only, and they will +fail these tests). + +Please note that the individual tests do not verify all of the +preconditions themselves, but rather build on each other. A failing +test means that tests later in the sequence can return false "OK" +results. + +If your helper supports time-based expiration with a configurable +timeout, you can test that feature with: + + make GIT_TEST_CREDENTIAL_HELPER=foo \ + GIT_TEST_CREDENTIAL_HELPER_TIMEOUT="foo --timeout=1" \ + t0303-credential-external.sh + +If your helper requires additional setup before the tests are started, +you can set GIT_TEST_CREDENTIAL_HELPER_SETUP to a sequence of shell +commands. +' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential.sh + +if test -z "$GIT_TEST_CREDENTIAL_HELPER"; then + skip_all="used to test external credential helpers" + test_done +fi + +test -z "$GIT_TEST_CREDENTIAL_HELPER_SETUP" || + eval "$GIT_TEST_CREDENTIAL_HELPER_SETUP" + +# clean before the test in case there is cruft left +# over from a previous run that would impact results +helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER" + +helper_test "$GIT_TEST_CREDENTIAL_HELPER" + +if test -z "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT"; then + say "# skipping timeout tests (GIT_TEST_CREDENTIAL_HELPER_TIMEOUT not set)" +else + helper_test_timeout "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT" +fi + +# clean afterwards so that we are good citizens +# and don't leave cruft in the helper's storage, which +# might be long-term system storage +helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER" + +test_done diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index 6d52b824b1..f83df8eb8b 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -189,7 +189,7 @@ for args in "-w --stdin-paths" "--stdin-paths -w"; do done test_expect_success 'corrupt tree' ' - echo abc >malformed-tree + echo abc >malformed-tree && test_must_fail git hash-object -t tree malformed-tree ' diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index b946f87686..df573c4978 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -42,13 +42,13 @@ test_expect_success 'ls-tree piped to mktree (2)' ' ' test_expect_success 'ls-tree output in wrong order given to mktree (1)' ' - perl -e "print reverse <>" <top | + "$PERL_PATH" -e "print reverse <>" <top | git mktree >actual && test_cmp tree actual ' test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' - perl -e "print reverse <>" <top.withsub | + "$PERL_PATH" -e "print reverse <>" <top.withsub | git mktree >actual && test_cmp tree.withsub actual ' diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 018c3546b6..5c0053a20b 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -234,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/t1013-loose-object-format.sh b/t/t1013-loose-object-format.sh new file mode 100755 index 0000000000..fbf5f2fc00 --- /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 f6a44c9ee0..e23ac0e69d 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -17,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 && @@ -120,7 +118,7 @@ test_expect_success 'alias expansion' ' ) ' -test_expect_success '!alias expansion' ' +test_expect_success NOT_MINGW '!alias expansion' ' pwd >expect && ( git config alias.test !pwd && @@ -140,6 +138,22 @@ test_expect_success 'GIT_PREFIX for !alias' ' 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/t1050-large.sh b/t/t1050-large.sh index deba111bd7..55ed955cef 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -6,22 +6,144 @@ 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 + # clone does not allow us to pass core.bigfilethreshold to + # new repos, so set core.bigfilethreshold globally + git config --global core.bigfilethreshold 200k && + echo X | dd of=large1 bs=1k seek=2000 && + echo X | dd of=large2 bs=1k seek=2000 && + echo X | dd of=large3 bs=1k seek=2000 && + echo Y | dd of=huge bs=1k seek=2500 && + GIT_ALLOC_LIMIT=1500 && + export GIT_ALLOC_LIMIT ' -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 'add a large file or two' ' + git add large1 huge large2 && + # make sure we got a single packfile and no loose objects + bad= count=0 idx= && + for p in .git/objects/pack/pack-*.pack + do + count=$(( $count + 1 )) + if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx" + then + continue + fi + bad=t + done && + test -z "$bad" && + test $count = 1 && + cnt=$(git show-index <"$idx" | wc -l) && + test $cnt = 2 && + for l in .git/objects/??/?????????????????????????????????????? + do + test -f "$l" || continue + bad=t + done && + test -z "$bad" && + + # attempt to add another copy of the same + git add large3 && + bad= count=0 && + for p in .git/objects/pack/pack-*.pack + do + count=$(( $count + 1 )) + if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx" + then + continue + fi + bad=t + done && + test -z "$bad" && + test $count = 1 ' test_expect_success 'checkout a large file' ' - large=$(git rev-parse :large) && - git update-index --add --cacheinfo 100644 $large another && + large1=$(git rev-parse :large1) && + git update-index --add --cacheinfo 100644 $large1 another && git checkout another && - cmp large another ;# this must not be test_cmp + cmp large1 another ;# this must not be test_cmp +' + +test_expect_success 'packsize limit' ' + test_create_repo mid && + ( + cd mid && + git config core.bigfilethreshold 64k && + git config pack.packsizelimit 256k && + + # mid1 and mid2 will fit within 256k limit but + # appending mid3 will bust the limit and will + # result in a separate packfile. + test-genrandom "a" $(( 66 * 1024 )) >mid1 && + test-genrandom "b" $(( 80 * 1024 )) >mid2 && + test-genrandom "c" $(( 128 * 1024 )) >mid3 && + git add mid1 mid2 mid3 && + + count=0 + for pi in .git/objects/pack/pack-*.idx + do + test -f "$pi" && count=$(( $count + 1 )) + done && + test $count = 2 && + + ( + git hash-object --stdin <mid1 + git hash-object --stdin <mid2 + git hash-object --stdin <mid3 + ) | + sort >expect && + + for pi in .git/objects/pack/pack-*.idx + do + git show-index <"$pi" + done | + sed -e "s/^[0-9]* \([0-9a-f]*\) .*/\1/" | + sort >actual && + + test_cmp expect actual + ) +' + +test_expect_success 'diff --raw' ' + git commit -q -m initial && + echo modified >>large1 && + git add large1 && + git commit -q -m modified && + git diff --raw HEAD^ +' + +test_expect_success 'hash-object' ' + git hash-object large1 +' + +test_expect_success 'cat-file a large file' ' + git cat-file blob :large1 >/dev/null +' + +test_expect_success 'cat-file a large file from a tag' ' + git tag -m largefile largefiletag :large1 && + git cat-file blob largefiletag >/dev/null +' + +test_expect_success 'git-show a large file' ' + git show :large1 >/dev/null + +' + +test_expect_success 'repack' ' + git repack -ad +' + +test_expect_success 'tar achiving' ' + git archive --format=tar HEAD >/dev/null +' + +test_expect_success 'zip achiving, store only' ' + git archive --format=zip -0 HEAD >/dev/null +' + +test_expect_success 'zip achiving, deflate' ' + git archive --format=zip HEAD >/dev/null ' test_done diff --git a/t/t1051-large-conversion.sh b/t/t1051-large-conversion.sh new file mode 100755 index 0000000000..8b7640b3ba --- /dev/null +++ b/t/t1051-large-conversion.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +test_description='test conversion filters on large files' +. ./test-lib.sh + +set_attr() { + test_when_finished 'rm -f .gitattributes' && + echo "* $*" >.gitattributes +} + +check_input() { + git read-tree --empty && + git add small large && + git cat-file blob :small >small.index && + git cat-file blob :large | head -n 1 >large.index && + test_cmp small.index large.index +} + +check_output() { + rm -f small large && + git checkout small large && + head -n 1 large >large.head && + test_cmp small large.head +} + +test_expect_success 'setup input tests' ' + printf "\$Id: foo\$\\r\\n" >small && + cat small small >large && + git config core.bigfilethreshold 20 && + git config filter.test.clean "sed s/.*/CLEAN/" +' + +test_expect_success 'autocrlf=true converts on input' ' + test_config core.autocrlf true && + check_input +' + +test_expect_success 'eol=crlf converts on input' ' + set_attr eol=crlf && + check_input +' + +test_expect_success 'ident converts on input' ' + set_attr ident && + check_input +' + +test_expect_success 'user-defined filters convert on input' ' + set_attr filter=test && + check_input +' + +test_expect_success 'setup output tests' ' + echo "\$Id\$" >small && + cat small small >large && + git add small large && + git config core.bigfilethreshold 7 && + git config filter.test.smudge "sed s/.*/SMUDGE/" +' + +test_expect_success 'autocrlf=true converts on output' ' + test_config core.autocrlf true && + check_output +' + +test_expect_success 'eol=crlf converts on output' ' + set_attr eol=crlf && + check_output +' + +test_expect_success 'user-defined filters convert on output' ' + set_attr filter=test && + check_output +' + +test_expect_success 'ident converts on output' ' + set_attr ident && + rm -f small large && + git checkout small large && + sed -n "s/Id: .*/Id: SHA/p" <small >small.clean && + head -n 1 large >large.head && + sed -n "s/Id: .*/Id: SHA/p" <large.head >large.clean && + test_cmp small.clean large.clean +' + +test_done diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index c4414ff576..a3b77239f4 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -7,6 +7,9 @@ test_description='git commit-tree options test This test checks that git commit-tree can create a specific commit object by defining all environment variables that it understands. + +Also make sure that command line parser understands the normal +"flags first and then non flag arguments" command line. ' . ./test-lib.sh @@ -42,4 +45,18 @@ test_expect_success \ 'compare commit' \ 'test_cmp expected commit' + +test_expect_success 'flags and then non flags' ' + echo comment text | + git commit-tree $(cat treeid) >commitid && + echo comment text | + git commit-tree $(cat treeid) -p $(cat commitid) >childid-1 && + echo comment text | + git commit-tree -p $(cat commitid) $(cat treeid) >childid-2 && + test_cmp childid-1 childid-2 && + git commit-tree $(cat treeid) -m foo >childid-3 && + git commit-tree -m foo $(cat treeid) >childid-4 && + test_cmp childid-3 childid-4 +' + test_done diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index 5e29e13782..397ccb6909 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -154,9 +154,9 @@ test_expect_success 'git show-branch' ' cat > resolve.expect << EOF Updating VARIABLE..VARIABLE FASTFORWARD (no commit created; -m option ignored) - example | 1 + - hello | 1 + - 2 files changed, 2 insertions(+), 0 deletions(-) + example | 1 + + hello | 1 + + 2 files changed, 2 insertions(+) EOF test_expect_success 'git resolve' ' diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 3db56267ee..a477453e2e 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' @@ -410,14 +451,20 @@ test_expect_success 'refer config from subdirectory' ' mkdir x && ( cd x && - echo strasse >expect + echo strasse >expect && git config --get --file ../other-config ein.bahn >actual && test_cmp expect actual ) ' -GIT_CONFIG=other-config git config anwohner.park ausweis +test_expect_success 'refer config from subdirectory via GIT_CONFIG' ' + ( + cd x && + GIT_CONFIG=../other-config git config --get ein.bahn >actual && + test_cmp expect actual + ) +' cat > expect << EOF [ein] @@ -426,7 +473,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 @@ -500,6 +550,14 @@ EOF test_expect_success "rename succeeded" "test_cmp expect .git/config" +test_expect_success 'renaming empty section name is rejected' ' + test_must_fail git config --rename-section branch.zwei "" +' + +test_expect_success 'renaming to bogus section is rejected' ' + test_must_fail git config --rename-section branch.zwei "bogus name" +' + cat >> .git/config << EOF [branch "zwei"] a = 1 [branch "vier"] EOF @@ -516,8 +574,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 +584,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 +657,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 +671,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 +682,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 +691,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 +710,7 @@ cat >expect <<\EOF EOF test_expect_success 'get --bool-or-int' ' + rm -f .git/config && ( echo "[bool]" echo true1 @@ -676,7 +730,6 @@ test_expect_success 'get --bool-or-int' ' ' -rm .git/config cat >expect <<\EOF [bool] true1 = true @@ -690,6 +743,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 +754,6 @@ test_expect_success 'set --bool-or-int' ' test_cmp expect .git/config ' -rm .git/config - cat >expect <<\EOF [path] home = ~/ @@ -710,6 +762,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 +803,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 +810,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 +842,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 +866,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" && @@ -904,4 +958,70 @@ test_expect_success 'git -c works with aliases of builtins' ' 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_expect_success 'git config --edit works' ' + git config -f tmp test.value no && + echo test.value=yes >expect && + GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit && + git config -f tmp --list >actual && + test_cmp expect actual +' + +test_expect_success 'git config --edit respects core.editor' ' + git config -f tmp test.value no && + echo test.value=yes >expect && + test_config core.editor "echo [test]value=yes >" && + git config -f tmp --edit && + git config -f tmp --list >actual && + test_cmp expect actual +' + +# malformed configuration files +test_expect_success 'barf on syntax error' ' + cat >.git/config <<-\EOF && + # broken section line + [section] + key garbage + EOF + test_must_fail git config --get section.key >actual 2>error && + grep " line 3 " error +' + +test_expect_success 'barf on incomplete section header' ' + cat >.git/config <<-\EOF && + # broken section line + [section + key = value + EOF + test_must_fail git config --get section.key >actual 2>error && + grep " line 2 " error +' + +test_expect_success 'barf on incomplete string' ' + cat >.git/config <<-\EOF && + # broken section line + [section] + key = "value string + EOF + test_must_fail git config --get section.key >actual 2>error && + grep " line 3 " error +' + 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/t1305-config-include.sh b/t/t1305-config-include.sh new file mode 100755 index 0000000000..a70707620f --- /dev/null +++ b/t/t1305-config-include.sh @@ -0,0 +1,142 @@ +#!/bin/sh + +test_description='test config file include directives' +. ./test-lib.sh + +test_expect_success 'include file by absolute path' ' + echo "[test]one = 1" >one && + echo "[include]path = \"$(pwd)/one\"" >.gitconfig && + echo 1 >expect && + git config test.one >actual && + test_cmp expect actual +' + +test_expect_success 'include file by relative path' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + echo 1 >expect && + git config test.one >actual && + test_cmp expect actual +' + +test_expect_success 'chained relative paths' ' + mkdir subdir && + echo "[test]three = 3" >subdir/three && + echo "[include]path = three" >subdir/two && + echo "[include]path = subdir/two" >.gitconfig && + echo 3 >expect && + git config test.three >actual && + test_cmp expect actual +' + +test_expect_success 'include paths get tilde-expansion' ' + echo "[test]one = 1" >one && + echo "[include]path = ~/one" >.gitconfig && + echo 1 >expect && + git config test.one >actual && + test_cmp expect actual +' + +test_expect_success 'include options can still be examined' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + echo one >expect && + git config include.path >actual && + test_cmp expect actual +' + +test_expect_success 'listing includes option and expansion' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + cat >expect <<-\EOF && + include.path=one + test.one=1 + EOF + git config --list >actual.full && + grep -v ^core actual.full >actual && + test_cmp expect actual +' + +test_expect_success 'single file lookup does not expand includes by default' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + test_must_fail git config -f .gitconfig test.one && + test_must_fail git config --global test.one && + echo 1 >expect && + git config --includes -f .gitconfig test.one >actual && + test_cmp expect actual +' + +test_expect_success 'single file list does not expand includes by default' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + echo "include.path=one" >expect && + git config -f .gitconfig --list >actual && + test_cmp expect actual +' + +test_expect_success 'writing config file does not expand includes' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + git config test.two 2 && + echo 2 >expect && + git config --no-includes test.two >actual && + test_cmp expect actual && + test_must_fail git config --no-includes test.one +' + +test_expect_success 'config modification does not affect includes' ' + echo "[test]one = 1" >one && + echo "[include]path = one" >.gitconfig && + git config test.one 2 && + echo 1 >expect && + git config -f one test.one >actual && + test_cmp expect actual && + cat >expect <<-\EOF && + 1 + 2 + EOF + git config --get-all test.one >actual && + test_cmp expect actual +' + +test_expect_success 'missing include files are ignored' ' + cat >.gitconfig <<-\EOF && + [include]path = foo + [test]value = yes + EOF + echo yes >expect && + git config test.value >actual && + test_cmp expect actual +' + +test_expect_success 'absolute includes from command line work' ' + echo "[test]one = 1" >one && + echo 1 >expect && + git -c include.path="$PWD/one" config test.one >actual && + test_cmp expect actual +' + +test_expect_success 'relative includes from command line fail' ' + echo "[test]one = 1" >one && + test_must_fail git -c include.path=one config test.one +' + +test_expect_success 'include cycles are detected' ' + cat >.gitconfig <<-\EOF && + [test]value = gitconfig + [include]path = cycle + EOF + cat >cycle <<-\EOF && + [test]value = cycle + [include]path = .gitconfig + EOF + cat >expect <<-\EOF && + gitconfig + cycle + EOF + test_must_fail git config --get-all test.value 2>stderr && + grep "exceeded maximum include depth" stderr +' + +test_done 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/t1410-reflog.sh b/t/t1410-reflog.sh index 252fc82837..236b13a3ab 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -100,8 +100,7 @@ test_expect_success setup ' check_fsck && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 4 + test_line_count = 4 .git/logs/refs/heads/master ' test_expect_success rewind ' @@ -117,8 +116,7 @@ test_expect_success rewind ' check_have A B C D E F G H I J K L && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 5 + test_line_count = 5 .git/logs/refs/heads/master ' test_expect_success 'corrupt and check' ' @@ -136,8 +134,7 @@ test_expect_success 'reflog expire --dry-run should not touch reflog' ' --stale-fix \ --all && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 5 && + test_line_count = 5 .git/logs/refs/heads/master && check_fsck "missing blob $F" ' @@ -150,8 +147,7 @@ test_expect_success 'reflog expire' ' --stale-fix \ --all && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 2 && + test_line_count = 2 .git/logs/refs/heads/master && check_fsck "dangling commit $K" ' @@ -217,9 +213,7 @@ test_expect_success 'delete' ' test_expect_success 'rewind2' ' test_tick && git reset --hard HEAD~2 && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 4 - + test_line_count = 4 .git/logs/refs/heads/master ' test_expect_success '--expire=never' ' @@ -228,9 +222,7 @@ test_expect_success '--expire=never' ' --expire=never \ --expire-unreachable=never \ --all && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 4 - + test_line_count = 4 .git/logs/refs/heads/master ' test_expect_success 'gc.reflogexpire=never' ' @@ -238,8 +230,7 @@ test_expect_success 'gc.reflogexpire=never' ' git config gc.reflogexpire never && git config gc.reflogexpireunreachable never && git reflog expire --verbose --all && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 4 + test_line_count = 4 .git/logs/refs/heads/master ' test_expect_success 'gc.reflogexpire=false' ' @@ -247,8 +238,7 @@ test_expect_success 'gc.reflogexpire=false' ' git config gc.reflogexpire false && git config gc.reflogexpireunreachable false && git reflog expire --verbose --all && - loglen=$(wc -l <.git/logs/refs/heads/master) && - test $loglen = 4 && + test_line_count = 4 .git/logs/refs/heads/master && git config --unset gc.reflogexpire && git config --unset gc.reflogexpireunreachable diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh index caa687b5b4..9a105fe21f 100755 --- a/t/t1411-reflog-show.sh +++ b/t/t1411-reflog-show.sh @@ -65,20 +65,73 @@ test_expect_success 'using @{now} syntax shows reflog date (oneline)' ' ' cat >expect <<'EOF' -Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>) +HEAD@{Thu Apr 7 15:13:13 2005 -0700} +EOF +test_expect_success 'using @{now} syntax shows reflog date (format=%gd)' ' + git log -g -1 --format=%gd HEAD@{now} >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 EOF test_expect_success 'using --date= shows reflog date (multiline)' ' - git log -g -1 --date=raw >tmp && + git log -g -1 --date=default >tmp && grep ^Reflog <tmp >actual && test_cmp expect actual ' cat >expect <<'EOF' -e46513e HEAD@{1112911993 -0700}: commit (initial): one +e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one EOF test_expect_success 'using --date= shows reflog date (oneline)' ' - git log -g -1 --oneline --date=raw >actual && + git log -g -1 --oneline --date=default >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +HEAD@{1112911993 -0700} +EOF +test_expect_success 'using --date= shows reflog date (format=%gd)' ' + git log -g -1 --format=%gd --date=raw >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Reflog: HEAD@{0} (C O Mitter <committer@example.com>) +Reflog message: commit (initial): one +EOF +test_expect_success 'log.date does not invoke "--date" magic (multiline)' ' + test_config log.date raw && + git log -g -1 >tmp && + grep ^Reflog <tmp >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{0}: commit (initial): one +EOF +test_expect_success 'log.date does not invoke "--date" magic (oneline)' ' + test_config log.date raw && + git log -g -1 --oneline >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +HEAD@{0} +EOF +test_expect_success 'log.date does not invoke "--date" magic (format=%gd)' ' + test_config log.date raw && + git log -g -1 --format=%gd >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +HEAD@{0} +EOF +test_expect_success '--date magic does not override explicit @{0} syntax' ' + git log -g -1 --format=%gd --date=raw HEAD@{0} >actual && test_cmp expect actual ' diff --git a/t/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index 7f519e5ebe..3acd895afb 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -20,11 +20,11 @@ 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 + cat >expect <<-\EOF && + 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..5b79c51b8c 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -27,12 +27,8 @@ test_expect_success 'loose objects borrowed from alternate are not missing' ' git init && echo ../../../.git/objects >.git/objects/info/alternates && test_commit C fileC one && - git fsck >../out 2>&1 + git fsck --no-dangling >../actual 2>&1 ) && - { - grep -v dangling out >actual || - : - } && test_cmp empty actual ' @@ -110,6 +106,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 @@ -155,4 +187,30 @@ test_expect_success 'cleaned up' ' test_cmp empty actual ' +test_expect_success 'rev-list --verify-objects' ' + git rev-list --verify-objects --all >/dev/null 2>out && + test_cmp empty out +' + +test_expect_success 'rev-list --verify-objects with bad sha1' ' + sha=$(echo blob | git hash-object -w --stdin) && + old=$(echo $sha | sed "s+^..+&/+") && + new=$(dirname $old)/ffffffffffffffffffffffffffffffffffffff && + sha="$(dirname $new)$(basename $new)" && + mv .git/objects/$old .git/objects/$new && + test_when_finished "remove_object $sha" && + git update-index --add --cacheinfo 100644 $sha foo && + test_when_finished "git read-tree -u --reset HEAD" && + tree=$(git write-tree) && + test_when_finished "remove_object $tree" && + cmt=$(echo bogus | git commit-tree $tree) && + test_when_finished "remove_object $cmt" && + git update-ref refs/heads/bogus $cmt && + test_when_finished "git update-ref -d refs/heads/bogus" && + + test_might_fail git rev-list --verify-objects refs/heads/bogus >/dev/null 2>out && + cat out && + grep -q "error: sha1 mismatch 63ffffffffffffffffffffffffffffffffffffff" out +' + test_done diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index 63849836c8..8f36aa9fc4 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -48,7 +48,7 @@ test_expect_success 'setup: helper for testing rev-parse' ' ' test_expect_success 'setup: core.worktree = relative path' ' - unset GIT_WORK_TREE; + sane_unset GIT_WORK_TREE && GIT_DIR=repo.git && GIT_CONFIG="$(pwd)"/$GIT_DIR/config && export GIT_DIR GIT_CONFIG && @@ -68,7 +68,7 @@ test_expect_success 'inside work tree' ' ) ' -test_expect_failure 'empty prefix is actually written out' ' +test_expect_success 'empty prefix is actually written out' ' echo >expected && ( cd work && @@ -89,7 +89,7 @@ test_expect_success 'subdir of work tree' ' ' test_expect_success 'setup: core.worktree = absolute path' ' - unset GIT_WORK_TREE; + sane_unset GIT_WORK_TREE && GIT_DIR=$(pwd)/repo.git && GIT_CONFIG=$GIT_DIR/config && export GIT_DIR GIT_CONFIG && @@ -334,7 +334,7 @@ test_expect_success 'absolute pathspec should fail gracefully' ' ' test_expect_success 'make_relative_path handles double slashes in GIT_DIR' ' - >dummy_file + >dummy_file && echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file && git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file ' diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 0843a1c13b..c5cb77a0e1 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -171,4 +171,15 @@ test_expect_success 'relative path when startup_info is NULL' ' grep "BUG: startup_info struct is not initialized." error ' +test_expect_success '<commit>:file correctly diagnosed after a pathname' ' + test_must_fail git rev-parse file.txt HEAD:file.txt 1>actual 2>error && + test_i18ngrep ! "exists on disk" error && + test_i18ngrep "no such path in the working tree" error && + cat >expect <<-\EOF && + file.txt + HEAD:file.txt + EOF + test_cmp expect actual +' + test_done diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index a4555510c3..d6e576192f 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -15,10 +15,18 @@ test_expect_success 'setup' ' test_commit 3 && (cd clone && test_commit 4 && - git branch --track my-side origin/side) - + git branch --track my-side origin/side && + git branch --track local-master master && + git remote add -t master master-only .. && + git fetch master-only && + git branch bad-upstream && + git config branch.bad-upstream.remote master-only && + git config branch.bad-upstream.merge refs/heads/side + ) ' +sq="'" + full_name () { (cd clone && git rev-parse --symbolic-full-name "$@") @@ -29,6 +37,11 @@ commit_subject () { git show -s --pretty=format:%s "$@") } +error_message () { + (cd clone && + test_must_fail git rev-parse --verify "$@") +} + test_expect_success '@{upstream} resolves to correct full name' ' test refs/remotes/origin/master = "$(full_name @{upstream})" ' @@ -78,7 +91,6 @@ test_expect_success 'checkout -b new my-side@{u} forks from the same' ' test_expect_success 'merge my-side@{u} records the correct name' ' ( - sq="'\''" && cd clone || exit git checkout master || exit git branch -D new ;# can fail but is ok @@ -107,6 +119,69 @@ test_expect_success 'checkout other@{u}' ' test_cmp expect actual ' +test_expect_success 'branch@{u} works when tracking a local branch' ' + test refs/heads/master = "$(full_name local-master@{u})" +' + +test_expect_success 'branch@{u} error message when no upstream' ' + cat >expect <<-EOF && + error: No upstream configured for branch ${sq}non-tracking${sq} + fatal: Needed a single revision + EOF + error_message non-tracking@{u} 2>actual && + test_i18ncmp expect actual +' + +test_expect_success '@{u} error message when no upstream' ' + cat >expect <<-EOF && + error: No upstream configured for branch ${sq}master${sq} + fatal: Needed a single revision + EOF + test_must_fail git rev-parse --verify @{u} 2>actual && + test_i18ncmp expect actual +' + +test_expect_success 'branch@{u} error message with misspelt branch' ' + cat >expect <<-EOF && + error: No such branch: ${sq}no-such-branch${sq} + fatal: Needed a single revision + EOF + error_message no-such-branch@{u} 2>actual && + test_i18ncmp expect actual +' + +test_expect_success '@{u} error message when not on a branch' ' + cat >expect <<-EOF && + error: HEAD does not point to a branch + fatal: Needed a single revision + EOF + git checkout HEAD^0 && + test_must_fail git rev-parse --verify @{u} 2>actual && + test_i18ncmp expect actual +' + +test_expect_success 'branch@{u} error message if upstream branch not fetched' ' + cat >expect <<-EOF && + error: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch + fatal: Needed a single revision + EOF + error_message bad-upstream@{u} 2>actual && + test_i18ncmp expect actual +' + +test_expect_success 'pull works when tracking a local branch' ' +( + cd clone && + git checkout local-master && + git pull +) +' + +# makes sense if the previous one succeeded +test_expect_success '@{u} works when tracking a local branch' ' + test refs/heads/master = "$(full_name @{u})" +' + cat >expect <<EOF commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 Reflog: master@{0} (C O Mitter <committer@example.com>) diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh index ec50a9ad70..80aedfca8c 100755 --- a/t/t1510-repo-setup.sh +++ b/t/t1510-repo-setup.sh @@ -603,7 +603,7 @@ test_expect_success '#22a: core.worktree = GIT_DIR = .git dir' ' # like case #6. setup_repo 22a "$here/22a/.git" "" unset && - setup_repo 22ab . "" unset + setup_repo 22ab . "" unset && mkdir -p 22a/.git/sub 22a/sub && mkdir -p 22ab/.git/sub 22ab/sub && try_case 22a/.git unset . \ @@ -742,7 +742,7 @@ test_expect_success '#28: core.worktree and core.bare conflict (gitfile case)' ' # Case #29: GIT_WORK_TREE(+core.worktree) overrides core.bare (gitfile case). test_expect_success '#29: setup' ' setup_repo 29 non-existent gitfile true && - mkdir -p 29/sub/sub 29/wt/sub + mkdir -p 29/sub/sub 29/wt/sub && ( cd 29 && GIT_WORK_TREE="$here/29" && diff --git a/t/t1511-rev-parse-caret.sh b/t/t1511-rev-parse-caret.sh index e043cb7c64..eaefc777bd 100755 --- a/t/t1511-rev-parse-caret.sh +++ b/t/t1511-rev-parse-caret.sh @@ -6,7 +6,7 @@ test_description='tests for ref^{stuff}' test_expect_success 'setup' ' echo blob >a-blob && - git tag -a -m blob blob-tag `git hash-object -w a-blob` + git tag -a -m blob blob-tag `git hash-object -w a-blob` && mkdir a-tree && echo moreblobs >a-tree/another-blob && git add . && diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index 36cca14d95..0f4b2896af 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -40,7 +40,7 @@ test_expect_success \ rm -f path* .merge_* out .git/index && git read-tree $t1 && git checkout-index --temp -- path1 >out && -test $(wc -l <out) = 1 && +test_line_count = 1 out && test $(cut "-d " -f2 out) = path1 && p=$(cut "-d " -f1 out) && test -f $p && @@ -51,7 +51,7 @@ test_expect_success \ rm -f path* .merge_* out .git/index && git read-tree $t1 && git checkout-index -a --temp >out && -test $(wc -l <out) = 5 && +test_line_count = 5 out && for f in path0 path1 path3 path4 asubdir/path5 do test $(grep $f out | cut "-d " -f2) = $f && @@ -69,7 +69,7 @@ test_expect_success \ 'checkout one stage 2 to temporary file' ' rm -f path* .merge_* out && git checkout-index --stage=2 --temp -- path1 >out && -test $(wc -l <out) = 1 && +test_line_count = 1 out && test $(cut "-d " -f2 out) = path1 && p=$(cut "-d " -f1 out) && test -f $p && @@ -79,7 +79,7 @@ test_expect_success \ 'checkout all stage 2 to temporary files' ' rm -f path* .merge_* out && git checkout-index --all --stage=2 --temp >out && -test $(wc -l <out) = 3 && +test_line_count = 3 out && for f in path1 path2 path4 do test $(grep $f out | cut "-d " -f2) = $f && @@ -92,13 +92,13 @@ test_expect_success \ 'checkout all stages/one file to nothing' ' rm -f path* .merge_* out && git checkout-index --stage=all --temp -- path0 >out && -test $(wc -l <out) = 0' +test_line_count = 0 out' test_expect_success \ 'checkout all stages/one file to temporary files' ' rm -f path* .merge_* out && git checkout-index --stage=all --temp -- path1 >out && -test $(wc -l <out) = 1 && +test_line_count = 1 out && test $(cut "-d " -f2 out) = path1 && cut "-d " -f1 out | (read s1 s2 s3 && test -f $s1 && @@ -112,7 +112,7 @@ test_expect_success \ 'checkout some stages/one file to temporary files' ' rm -f path* .merge_* out && git checkout-index --stage=all --temp -- path2 >out && -test $(wc -l <out) = 1 && +test_line_count = 1 out && test $(cut "-d " -f2 out) = path2 && cut "-d " -f1 out | (read s1 s2 s3 && test $s1 = . && @@ -125,7 +125,7 @@ test_expect_success \ 'checkout all stages/all files to temporary files' ' rm -f path* .merge_* out && git checkout-index -a --stage=all --temp >out && -test $(wc -l <out) = 5' +test_line_count = 5 out' test_expect_success \ '-- path0: no entry' ' @@ -185,7 +185,7 @@ test_expect_success \ 'checkout --temp within subdir' ' (cd asubdir && git checkout-index -a --stage=all >out && - test $(wc -l <out) = 1 && + test_line_count = 1 out && test $(grep path5 out | cut "-d " -f2) = path5 && grep path5 out | cut "-d " -f1 | (read s1 s2 s3 && test -f ../$s1 && @@ -203,7 +203,7 @@ t4=$(git write-tree) && rm -f .git/index && git read-tree $t4 && git checkout-index --temp -a >out && -test $(wc -l <out) = 1 && +test_line_count = 1 out && test $(cut "-d " -f2 out) = a && p=$(cut "-d " -f1 out) && test -f $p && diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh index c551d39a66..37bdcedcc9 100755 --- a/t/t2015-checkout-unborn.sh +++ b/t/t2015-checkout-unborn.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='checkout from unborn branch protects contents' +test_description='checkout from unborn branch' . ./test-lib.sh test_expect_success 'setup' ' @@ -37,4 +37,24 @@ test_expect_success 'checkout from unborn merges identical index contents' ' git checkout -b new origin ' +test_expect_success 'checking out another branch from unborn state' ' + git checkout --orphan newroot && + git checkout -b anothername && + test_must_fail git show-ref --verify refs/heads/newroot && + git symbolic-ref HEAD >actual && + echo refs/heads/anothername >expect && + test_cmp expect actual +' + +test_expect_success 'checking out in a newly created repo' ' + test_create_repo empty && + ( + cd empty && + git symbolic-ref HEAD >expect && + test_must_fail git checkout && + git symbolic-ref HEAD >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh index 0e3b8582f2..655f278c5f 100755 --- a/t/t2017-checkout-orphan.sh +++ b/t/t2017-checkout-orphan.sh @@ -116,4 +116,10 @@ test_expect_success '--orphan refuses to switch if a merge is needed' ' git reset --hard ' +test_expect_success 'cannot --detach on an unborn branch' ' + git checkout master && + git checkout --orphan new && + test_must_fail git checkout --detach +' + test_done diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index fa69016381..2741262369 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,24 @@ 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 works' ' + git checkout branch1 && + git checkout -B branch1-scratch && + + setup_dirty_mergeable && + git checkout -B branch1-scratch initial && + test_dirty_mergeable +' + test_done diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 068fba4c8e..81005373d7 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -11,14 +11,13 @@ 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 "you are leaving $2 behind" "$1" && test_i18ngrep ! "$PREV_HEAD_DESC" "$1" } check_no_orphan_warning() { - test_i18ngrep ! "$ORPHAN_WARNING" "$1" && + test_i18ngrep ! "you are leaving .* commit.*behind" "$1" && test_i18ngrep "$PREV_HEAD_DESC" "$1" } @@ -110,12 +109,24 @@ test_expect_success 'checkout warns on orphan commits' ' git checkout --detach two && echo content >orphan && git add orphan && - git commit -a -m orphan && + git commit -a -m orphan1 && + echo new content >orphan && + git commit -a -m orphan2 && + orphan2=$(git rev-parse HEAD) && git checkout master 2>stderr ' test_expect_success 'checkout warns on orphan commits: output' ' - check_orphan_warning stderr + check_orphan_warning stderr "2 commits" +' + +test_expect_success 'checkout warns orphaning 1 of 2 commits' ' + git checkout "$orphan2" && + git checkout HEAD^ 2>stderr +' + +test_expect_success 'checkout warns orphaning 1 of 2 commits: output' ' + check_orphan_warning stderr "1 commit" ' test_expect_success 'checkout does not warn leaving ref tip' ' @@ -148,7 +159,7 @@ test_expect_success 'tracking count is accurate after orphan check' ' git config branch.child.merge refs/heads/master && git checkout child^ && git checkout child >stdout && - test_cmp expect stdout + test_i18ncmp expect stdout ' 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/t2023-checkout-m.sh b/t/t2023-checkout-m.sh new file mode 100755 index 0000000000..7e18985134 --- /dev/null +++ b/t/t2023-checkout-m.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='checkout -m -- <conflicted path> + +Ensures that checkout -m on a resolved file restores the conflicted file' + +. ./test-lib.sh + +test_expect_success setup ' + test_tick && + test_commit both.txt both.txt initial && + git branch topic && + test_commit modified_in_master both.txt in_master && + test_commit added_in_master each.txt in_master && + git checkout topic && + test_commit modified_in_topic both.txt in_topic && + test_commit added_in_topic each.txt in_topic +' + +test_expect_success 'git merge master' ' + test_must_fail git merge master +' + +clean_branchnames () { + # Remove branch names after conflict lines + sed 's/^\([<>]\{5,\}\) .*$/\1/' +} + +test_expect_success '-m restores 2-way conflicted+resolved file' ' + cp each.txt each.txt.conflicted && + echo resolved >each.txt && + git add each.txt && + git checkout -m -- each.txt && + clean_branchnames <each.txt >each.txt.cleaned && + clean_branchnames <each.txt.conflicted >each.txt.conflicted.cleaned && + test_cmp each.txt.conflicted.cleaned each.txt.cleaned +' + +test_expect_success '-m restores 3-way conflicted+resolved file' ' + cp both.txt both.txt.conflicted && + echo resolved >both.txt && + git add both.txt && + git checkout -m -- both.txt && + clean_branchnames <both.txt >both.txt.cleaned && + clean_branchnames <both.txt.conflicted >both.txt.conflicted.cleaned && + test_cmp both.txt.conflicted.cleaned both.txt.cleaned +' + +test_done diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index cb7effe0a3..f2620650ce 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -113,7 +113,7 @@ test_expect_success 'unmerge with plumbing' ' prime_resolve_undo && git update-index --unresolve fi/le && git ls-files -u >actual && - test $(wc -l <actual) = 3 + test_line_count = 3 actual ' test_expect_success 'rerere and rerere forget' ' diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index 58a329961e..ec35409f9c 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -32,7 +32,7 @@ test_expect_success 'intent to add does not clobber existing paths' ' ! grep "$empty" actual ' -test_expect_success 'cannot commit with i-t-a entry' ' +test_expect_success 'i-t-a entry is simply ignored' ' test_tick && git commit -a -m initial && git reset --hard && @@ -41,12 +41,14 @@ test_expect_success 'cannot commit with i-t-a entry' ' echo frotz >nitfol && git add rezrov && git add -N nitfol && - test_must_fail git commit + git commit -m second && + test $(git ls-tree HEAD -- nitfol | wc -l) = 0 && + test $(git diff --name-only HEAD -- nitfol | wc -l) = 1 ' test_expect_success 'can commit with an unrelated i-t-a entry in index' ' git reset --hard && - echo xyzzy >rezrov && + echo bozbar >rezrov && echo frotz >nitfol && git add rezrov && git add -N nitfol && 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/t3006-ls-files-long.sh b/t/t3006-ls-files-long.sh new file mode 100755 index 0000000000..202ad658b8 --- /dev/null +++ b/t/t3006-ls-files-long.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +test_description='overly long paths' +. ./test-lib.sh + +test_expect_success setup ' + p=filefilefilefilefilefilefilefile && + p=$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p && + p=$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p$p && + + path_a=${p}_a && + path_z=${p}_z && + + blob_a=$(echo frotz | git hash-object -w --stdin) && + blob_z=$(echo nitfol | git hash-object -w --stdin) && + + pat="100644 %s 0\t%s\n" +' + +test_expect_success 'overly-long path by itself is not a problem' ' + printf "$pat" "$blob_a" "$path_a" | + git update-index --add --index-info && + echo "$path_a" >expect && + git ls-files >actual && + test_cmp expect actual +' + +test_expect_success 'overly-long path does not replace another by mistake' ' + printf "$pat" "$blob_a" "$path_a" "$blob_z" "$path_z" | + git update-index --add --index-info && + ( + echo "$path_a" + echo "$path_z" + ) >expect && + git ls-files >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 0c02d56952..a5e3da7e41 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 ' @@ -284,17 +285,7 @@ test_expect_success 'merge-recursive simple' ' rm -fr [abcd] && git checkout -f "$c2" && - git merge-recursive "$c0" -- "$c2" "$c1" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c2" "$c1" ' test_expect_success 'merge-recursive result' ' @@ -333,17 +324,7 @@ test_expect_success 'merge-recursive remove conflict' ' rm -fr [abcd] && git checkout -f "$c1" && - git merge-recursive "$c0" -- "$c1" "$c5" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c5" ' test_expect_success 'merge-recursive remove conflict' ' @@ -387,17 +368,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c1" && - git merge-recursive "$c0" -- "$c1" "$c4" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c4" ' test_expect_success 'merge-recursive d/f conflict result' ' @@ -421,17 +392,7 @@ test_expect_success 'merge-recursive d/f conflict the other way' ' git reset --hard && git checkout -f "$c4" && - git merge-recursive "$c0" -- "$c4" "$c1" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c4" "$c1" ' test_expect_success 'merge-recursive d/f conflict result the other way' ' @@ -455,17 +416,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c1" && - git merge-recursive "$c0" -- "$c1" "$c6" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c1" "$c6" ' test_expect_success 'merge-recursive d/f conflict result' ' @@ -489,17 +440,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c6" && - git merge-recursive "$c0" -- "$c6" "$c1" - status=$? - case "$status" in - 1) - : happy - ;; - *) - echo >&2 "why status $status!!!" - false - ;; - esac + test_expect_code 1 git merge-recursive "$c0" -- "$c6" "$c1" ' test_expect_success 'merge-recursive d/f conflict result' ' @@ -630,16 +571,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/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh index f6973e96a5..0a4ff6d824 100755 --- a/t/t3040-subprojects-basic.sh +++ b/t/t3040-subprojects-basic.sh @@ -3,81 +3,81 @@ test_description='Basic subproject functionality' . ./test-lib.sh -test_expect_success 'Super project creation' \ - ': >Makefile && - git add Makefile && - git commit -m "Superproject created"' - - -cat >expected <<EOF -:000000 160000 00000... A sub1 -:000000 160000 00000... A sub2 -EOF -test_expect_success 'create subprojects' \ - 'mkdir sub1 && - ( cd sub1 && git init && : >Makefile && git add * && - git commit -q -m "subproject 1" ) && - mkdir sub2 && - ( cd sub2 && git init && : >Makefile && git add * && - git commit -q -m "subproject 2" ) && - git update-index --add sub1 && - git add sub2 && - git commit -q -m "subprojects added" && - git diff-tree --abbrev=5 HEAD^ HEAD |cut -d" " -f-3,5- >current && - test_cmp expected current' - -git branch save HEAD - -test_expect_success 'check if fsck ignores the subprojects' \ - 'git fsck --full' - -test_expect_success 'check if commit in a subproject detected' \ - '( cd sub1 && - echo "all:" >>Makefile && - echo " true" >>Makefile && - git commit -q -a -m "make all" ) && { - git diff-files --exit-code - test $? = 1 - }' - -test_expect_success 'check if a changed subproject HEAD can be committed' \ - 'git commit -q -a -m "sub1 changed" && { - git diff-tree --exit-code HEAD^ HEAD - test $? = 1 - }' - -test_expect_success 'check if diff-index works for subproject elements' \ - 'git diff-index --exit-code --cached save -- sub1 - test $? = 1' - -test_expect_success 'check if diff-tree works for subproject elements' \ - 'git diff-tree --exit-code HEAD^ HEAD -- sub1 - test $? = 1' - -test_expect_success 'check if git diff works for subproject elements' \ - 'git diff --exit-code HEAD^ HEAD - test $? = 1' - -test_expect_success 'check if clone works' \ - 'git ls-files -s >expected && - git clone -l -s . cloned && - ( cd cloned && git ls-files -s ) >current && - test_cmp expected current' - -test_expect_success 'removing and adding subproject' \ - 'git update-index --force-remove -- sub2 && - mv sub2 sub3 && - git add sub3 && - git commit -q -m "renaming a subproject" && { - git diff -M --name-status --exit-code HEAD^ HEAD - test $? = 1 - }' +test_expect_success 'setup: create superproject' ' + : >Makefile && + git add Makefile && + git commit -m "Superproject created" +' + +test_expect_success 'setup: create subprojects' ' + mkdir sub1 && + ( cd sub1 && git init && : >Makefile && git add * && + git commit -q -m "subproject 1" ) && + mkdir sub2 && + ( cd sub2 && git init && : >Makefile && git add * && + git commit -q -m "subproject 2" ) && + git update-index --add sub1 && + git add sub2 && + git commit -q -m "subprojects added" && + git diff-tree --abbrev=5 HEAD^ HEAD |cut -d" " -f-3,5- >current && + git branch save HEAD && + cat >expected <<-\EOF && + :000000 160000 00000... A sub1 + :000000 160000 00000... A sub2 + EOF + test_cmp expected current +' + +test_expect_success 'check if fsck ignores the subprojects' ' + git fsck --full +' + +test_expect_success 'check if commit in a subproject detected' ' + ( cd sub1 && + echo "all:" >>Makefile && + echo " true" >>Makefile && + git commit -q -a -m "make all" ) && + test_expect_code 1 git diff-files --exit-code +' + +test_expect_success 'check if a changed subproject HEAD can be committed' ' + git commit -q -a -m "sub1 changed" && + test_expect_code 1 git diff-tree --exit-code HEAD^ HEAD +' + +test_expect_success 'check if diff-index works for subproject elements' ' + test_expect_code 1 git diff-index --exit-code --cached save -- sub1 +' + +test_expect_success 'check if diff-tree works for subproject elements' ' + test_expect_code 1 git diff-tree --exit-code HEAD^ HEAD -- sub1 +' + +test_expect_success 'check if git diff works for subproject elements' ' + test_expect_code 1 git diff --exit-code HEAD^ HEAD +' + +test_expect_success 'check if clone works' ' + git ls-files -s >expected && + git clone -l -s . cloned && + ( cd cloned && git ls-files -s ) >current && + test_cmp expected current +' + +test_expect_success 'removing and adding subproject' ' + git update-index --force-remove -- sub2 && + mv sub2 sub3 && + git add sub3 && + git commit -q -m "renaming a subproject" && + test_expect_code 1 git diff -M --name-status --exit-code HEAD^ HEAD +' # the index must contain the object name the HEAD of the # subproject sub1 was at the point "save" -test_expect_success 'checkout in superproject' \ - 'git checkout save && - git diff-index --exit-code --raw --cached save -- sub1' +test_expect_success 'checkout in superproject' ' + git checkout save && + git diff-index --exit-code --raw --cached save -- sub1 +' # just interesting what happened... # git diff --name-status -M save master 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 9e69c8c926..a17f8b2a40 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -3,11 +3,8 @@ # Copyright (c) 2005 Amos Waterland # -test_description='git branch --foo should not create bogus branch +test_description='git branch assorted tests' -This test runs git branch --help and checks that the argument is properly -handled. Specifically, that a bogus branch is not created. -' . ./test-lib.sh test_expect_success \ @@ -22,8 +19,8 @@ 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_might_fail git branch --help </dev/null >/dev/null 2>/dev/null && + test_path_is_missing .git/refs/heads/--help ' test_expect_success 'branch -h in broken repository' ' @@ -39,11 +36,11 @@ 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 $_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master @@ -52,15 +49,15 @@ 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' \ @@ -75,16 +72,21 @@ test_expect_success \ git branch l' test_expect_success \ + 'git branch -m dumps usage' \ + 'test_expect_code 129 git branch -m 2>err && + grep "[Uu]sage: git branch" err' + +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' + git branch -m n/n 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 +100,143 @@ 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 -M master should work when master is checked out' ' + git checkout master && + git branch -M master +' + +test_expect_success 'git branch -M master master should work when master is checked out' ' + git checkout master && + git branch -M master master +' + +test_expect_success 'git branch -M master2 master2 should work when master is checked out' ' + git checkout master && + git branch master2 && + git branch -M master2 master2 +' + +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 +' + +test_expect_success 'git branch --column' ' + COLUMNS=81 git branch --column=column >actual && + cat >expected <<\EOF && + a/b/c bam foo l * master n o/p r + abc bar j/k m/m master2 o/o q +EOF + test_cmp expected actual +' + +test_expect_success 'git branch --column with an extremely long branch name' ' + long=this/is/a/part/of/long/branch/name && + long=z$long/$long/$long/$long && + test_when_finished "git branch -d $long" && + git branch $long && + COLUMNS=80 git branch --column=column >actual && + cat >expected <<EOF && + a/b/c + abc + bam + bar + foo + j/k + l + m/m +* master + master2 + n + o/o + o/p + q + r + $long +EOF + test_cmp expected actual +' + +test_expect_success 'git branch with column.*' ' + git config column.ui column && + git config column.branch "dense" && + COLUMNS=80 git branch >actual && + git config --unset column.branch && + git config --unset column.ui && + cat >expected <<\EOF && + a/b/c bam foo l * master n o/p r + abc bar j/k m/m master2 o/o q +EOF + test_cmp expected actual +' + +test_expect_success 'git branch --column -v should fail' ' + test_must_fail git branch --column -v +' + +test_expect_success 'git branch -v with column.ui ignored' ' + git config column.ui column && + COLUMNS=80 git branch -v | cut -c -10 | sed "s/ *$//" >actual && + git config --unset column.ui && + cat >expected <<\EOF && + a/b/c + abc + bam + bar + foo + j/k + l + m/m +* master + master2 + n + o/o + o/p + q + r +EOF + test_cmp expected actual +' + mv .git/config .git/config-saved test_expect_success 'git branch -m q q2 without config should succeed' ' @@ -112,12 +251,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 +267,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 \ @@ -238,8 +377,8 @@ 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' ' @@ -542,4 +681,57 @@ 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_expect_success 'use --edit-description' ' + write_script editor <<-\EOF && + echo "New contents" >"$1" + EOF + EDITOR=./editor git branch --edit-description && + write_script editor <<-\EOF && + git stripspace -s <"$1" >"EDITOR_OUTPUT" + EOF + EDITOR=./editor git branch --edit-description && + echo "New contents" >expect && + test_cmp EDITOR_OUTPUT expect +' + +test_expect_success 'detect typo in branch name when using --edit-description' ' + write_script editor <<-\EOF && + echo "New contents" >"$1" + EOF + ( + EDITOR=./editor && + export EDITOR && + test_must_fail git branch --edit-description no-such-branch + ) +' + +test_expect_success 'refuse --edit-description on unborn branch for now' ' + write_script editor <<-\EOF && + echo "New contents" >"$1" + EOF + git checkout --orphan unborn && + ( + EDITOR=./editor && + export EDITOR && + test_must_fail git branch --edit-description + ) +' + +test_expect_success '--merged catches invalid object names' ' + test_must_fail git branch --merged 0000000000000000000000000000000000000000 +' + test_done diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 6b7c118e4f..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 diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index 5e29a05259..1f35e55ee3 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -15,184 +15,204 @@ p0='no-funny' p1='tabs ," (dq) and spaces' p2='just space' -cat >"$p0" <<\EOF -1. A quick brown fox jumps over the lazy cat, oops dog. -2. A quick brown fox jumps over the lazy cat, oops dog. -3. A quick brown fox jumps over the lazy cat, oops dog. -EOF - -cat 2>/dev/null >"$p1" "$p0" -echo 'Foo Bar Baz' >"$p2" +test_expect_success 'setup' ' + cat >"$p0" <<-\EOF && + 1. A quick brown fox jumps over the lazy cat, oops dog. + 2. A quick brown fox jumps over the lazy cat, oops dog. + 3. A quick brown fox jumps over the lazy cat, oops dog. + EOF + + { cat "$p0" >"$p1" || :; } && + { echo "Foo Bar Baz" >"$p2" || :; } && + + if test -f "$p1" && cmp "$p0" "$p1" + then + test_set_prereq TABS_IN_FILENAMES + fi +' -if test -f "$p1" && cmp "$p0" "$p1" +if ! test_have_prereq TABS_IN_FILENAMES then - test_set_prereq TABS_IN_FILENAMES -else # since FAT/NTFS does not allow tabs in filenames, skip this test - say 'Your filesystem does not allow tabs in filenames' + skip_all='Your filesystem does not allow tabs in filenames' + test_done fi -test_expect_success TABS_IN_FILENAMES 'setup expect' " -echo 'just space -no-funny' >expected -" +test_expect_success 'setup: populate index and tree' ' + git update-index --add "$p0" "$p2" && + t0=$(git write-tree) +' -test_expect_success TABS_IN_FILENAMES 'git ls-files no-funny' \ - 'git update-index --add "$p0" "$p2" && +test_expect_success 'ls-files prints space in filename verbatim' ' + printf "%s\n" "just space" no-funny >expected && git ls-files >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -t0=`git write-tree` && -echo "$t0" >t0 && + test_cmp expected current +' -cat > expected <<\EOF -just space -no-funny -"tabs\t,\" (dq) and spaces" -EOF +test_expect_success 'setup: add funny filename' ' + git update-index --add "$p1" && + t1=$(git write-tree) ' -test_expect_success TABS_IN_FILENAMES 'git ls-files with-funny' \ - 'git update-index --add "$p1" && +test_expect_success 'ls-files quotes funny filename' ' + cat >expected <<-\EOF && + just space + no-funny + "tabs\t,\" (dq) and spaces" + EOF git ls-files >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' " -echo 'just space -no-funny -tabs ,\" (dq) and spaces' >expected -" - -test_expect_success TABS_IN_FILENAMES 'git ls-files -z with-funny' \ - 'git ls-files -z | perl -pe y/\\000/\\012/ >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -t1=`git write-tree` && -echo "$t1" >t1 && - -cat > expected <<\EOF -just space -no-funny -"tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git ls-tree with funny' \ - 'git ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat > expected <<\EOF -A "tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-index with-funny' \ - 'git diff-index --name-status $t0 >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree with-funny' \ - 'git diff-tree --name-status $t0 $t1 >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' " -echo 'A -tabs ,\" (dq) and spaces' >expected -" - -test_expect_success TABS_IN_FILENAMES 'git diff-index -z with-funny' \ - 'git diff-index -z --name-status $t0 | perl -pe y/\\000/\\012/ >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree -z with-funny' \ - 'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\000/\\012/ >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat > expected <<\EOF -CNUM no-funny "tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree -C with-funny' \ - 'git diff-tree -C --find-copies-harder --name-status \ - $t0 $t1 | sed -e 's/^C[0-9]*/CNUM/' >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat > expected <<\EOF -RNUM no-funny "tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ - 'git update-index --force-remove "$p0" && - git diff-index -M --name-status \ - $t0 | sed -e 's/^R[0-9]*/RNUM/' >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat > expected <<\EOF -diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" -similarity index NUM% -rename from no-funny -rename to "tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ - 'git diff-index -M -p $t0 | - sed -e "s/index [0-9]*%/index NUM%/" >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -chmod +x "$p1" && -cat > expected <<\EOF -diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" -old mode 100644 -new mode 100755 -similarity index NUM% -rename from no-funny -rename to "tabs\t,\" (dq) and spaces" -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ - 'git diff-index -M -p $t0 | - sed -e "s/index [0-9]*%/index NUM%/" >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat >expected <<\EOF - "tabs\t,\" (dq) and spaces" - 1 files changed, 0 insertions(+), 0 deletions(-) -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree rename with-funny applied' \ - 'git diff-index -M -p $t0 | - git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'setup expect' ' -cat > expected <<\EOF - no-funny - "tabs\t,\" (dq) and spaces" - 2 files changed, 3 insertions(+), 3 deletions(-) -EOF -' - -test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny applied' \ - 'git diff-index -p $t0 | - git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - test_cmp expected current' - -test_expect_success TABS_IN_FILENAMES 'git apply non-git diff' \ - 'git diff-index -p $t0 | - sed -ne "/^[-+@]/p" | - git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - test_cmp expected current' + test_cmp expected current +' + +test_expect_success 'ls-files -z does not quote funny filename' ' + cat >expected <<-\EOF && + just space + no-funny + tabs ," (dq) and spaces + EOF + git ls-files -z >ls-files.z && + "$PERL_PATH" -pe "y/\000/\012/" <ls-files.z >current && + test_cmp expected current +' + +test_expect_success 'ls-tree quotes funny filename' ' + cat >expected <<-\EOF && + just space + no-funny + "tabs\t,\" (dq) and spaces" + EOF + git ls-tree -r $t1 >ls-tree && + sed -e "s/^[^ ]* //" <ls-tree >current && + test_cmp expected current +' + +test_expect_success 'diff-index --name-status quotes funny filename' ' + cat >expected <<-\EOF && + A "tabs\t,\" (dq) and spaces" + EOF + git diff-index --name-status $t0 >current && + test_cmp expected current +' + +test_expect_success 'diff-tree --name-status quotes funny filename' ' + cat >expected <<-\EOF && + A "tabs\t,\" (dq) and spaces" + EOF + git diff-tree --name-status $t0 $t1 >current && + test_cmp expected current +' + +test_expect_success 'diff-index -z does not quote funny filename' ' + cat >expected <<-\EOF && + A + tabs ," (dq) and spaces + EOF + git diff-index -z --name-status $t0 >diff-index.z && + "$PERL_PATH" -pe "y/\000/\012/" <diff-index.z >current && + test_cmp expected current +' + +test_expect_success 'diff-tree -z does not quote funny filename' ' + cat >expected <<-\EOF && + A + tabs ," (dq) and spaces + EOF + git diff-tree -z --name-status $t0 $t1 >diff-tree.z && + "$PERL_PATH" -pe y/\\000/\\012/ <diff-tree.z >current && + test_cmp expected current +' + +test_expect_success 'diff-tree --find-copies-harder quotes funny filename' ' + cat >expected <<-\EOF && + CNUM no-funny "tabs\t,\" (dq) and spaces" + EOF + git diff-tree -C --find-copies-harder --name-status $t0 $t1 >out && + sed -e "s/^C[0-9]*/CNUM/" <out >current && + test_cmp expected current +' + +test_expect_success 'setup: remove unfunny index entry' ' + git update-index --force-remove "$p0" +' + +test_expect_success 'diff-tree -M quotes funny filename' ' + cat >expected <<-\EOF && + RNUM no-funny "tabs\t,\" (dq) and spaces" + EOF + git diff-index -M --name-status $t0 >out && + sed -e "s/^R[0-9]*/RNUM/" <out >current && + test_cmp expected current +' + +test_expect_success 'diff-index -M -p quotes funny filename' ' + cat >expected <<-\EOF && + diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" + similarity index NUM% + rename from no-funny + rename to "tabs\t,\" (dq) and spaces" + EOF + git diff-index -M -p $t0 >diff && + sed -e "s/index [0-9]*%/index NUM%/" <diff >current && + test_cmp expected current +' + +test_expect_success 'setup: mode change' ' + chmod +x "$p1" +' + +test_expect_success 'diff-index -M -p with mode change quotes funny filename' ' + cat >expected <<-\EOF && + diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" + old mode 100644 + new mode 100755 + similarity index NUM% + rename from no-funny + rename to "tabs\t,\" (dq) and spaces" + EOF + git diff-index -M -p $t0 >diff && + sed -e "s/index [0-9]*%/index NUM%/" <diff >current && + test_cmp expected current +' + +test_expect_success 'diffstat for rename quotes funny filename' ' + cat >expected <<-\EOF && + "tabs\t,\" (dq) and spaces" + 1 file changed, 0 insertions(+), 0 deletions(-) + EOF + git diff-index -M -p $t0 >diff && + git apply --stat <diff >diffstat && + sed -e "s/|.*//" -e "s/ *\$//" <diffstat >current && + test_i18ncmp expected current +' + +test_expect_success 'numstat for rename quotes funny filename' ' + cat >expected <<-\EOF && + 0 0 "tabs\t,\" (dq) and spaces" + EOF + git diff-index -M -p $t0 >diff && + git apply --numstat <diff >current && + test_cmp expected current +' + +test_expect_success 'numstat without -M quotes funny filename' ' + cat >expected <<-\EOF && + 0 3 no-funny + 3 0 "tabs\t,\" (dq) and spaces" + EOF + git diff-index -p $t0 >diff && + git apply --numstat <diff >current && + test_cmp expected current +' + +test_expect_success 'numstat for non-git rename diff quotes funny filename' ' + cat >expected <<-\EOF && + 0 3 no-funny + 3 0 "tabs\t,\" (dq) and spaces" + EOF + git diff-index -p $t0 >git-diff && + sed -ne "/^[-+@]/p" <git-diff >diff && + git apply --numstat <diff >current && + test_cmp expected current +' test_done 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/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index 4ec4d11450..195bb97f85 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -324,7 +324,7 @@ y and z notes on 4th commit EOF git notes merge --commit && # No .git/NOTES_MERGE_* files left - test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && + test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && test_cmp /dev/null output && # Merge commit has pre-merge y and pre-merge z as parents test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" && @@ -386,10 +386,10 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol test_expect_success 'abort notes merge' ' git notes merge --abort && # No .git/NOTES_MERGE_* files left - test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && + test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && test_cmp /dev/null output && # m has not moved (still == y) - test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)" + test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)" && # Verify that other notes refs has not changed (w, x, y and z) verify_notes w && verify_notes x && @@ -453,7 +453,7 @@ EOF # Finalize merge git notes merge --commit && # No .git/NOTES_MERGE_* files left - test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && + test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && test_cmp /dev/null output && # Merge commit has pre-merge y and pre-merge z as parents test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" && @@ -525,9 +525,9 @@ EOF test -f .git/NOTES_MERGE_WORKTREE/$commit_sha3 && test -f .git/NOTES_MERGE_WORKTREE/$commit_sha4 && # Refs are unchanged - test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" - test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" - test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" + test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" && + test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && + test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && # Mention refs/notes/m, and its current and expected value in output grep -q "refs/notes/m" output && grep -q "$(git rev-parse refs/notes/m)" output && @@ -542,10 +542,10 @@ EOF test_expect_success 'resolve situation by aborting the notes merge' ' git notes merge --abort && # No .git/NOTES_MERGE_* files left - test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && + test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && test_cmp /dev/null output && # m has not moved (still == w) - test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" + test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" && # Verify that other notes refs has not changed (w, x, y and z) verify_notes w && verify_notes x && @@ -553,4 +553,23 @@ test_expect_success 'resolve situation by aborting the notes merge' ' verify_notes z ' +cat >expect_notes <<EOF +foo +bar +EOF + +test_expect_success 'switch cwd before committing notes merge' ' + git notes add -m foo HEAD && + git notes --ref=other add -m bar HEAD && + test_must_fail git notes merge refs/notes/other && + ( + cd .git/NOTES_MERGE_WORKTREE && + echo "foo" > $(git rev-parse HEAD) && + echo "bar" >> $(git rev-parse HEAD) && + git notes merge --commit + ) && + git notes show HEAD > actual_notes && + test_cmp expect_notes actual_notes +' + test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 6eaecec906..7788ae02ad 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -160,20 +160,18 @@ rm -f B 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_must_fail git rebase ' 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_must_fail git rebase ' 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 config branch.default.remote . && + git config branch.default.merge refs/heads/master && git rebase && test "$(git rev-parse default~1)" = "$(git rev-parse master)" ' @@ -218,4 +216,27 @@ test_expect_success 'rebase -m can copy notes' ' test "a note" = "$(git notes show HEAD)" ' +test_expect_success 'rebase commit with an ancient timestamp' ' + git reset --hard && + + >old.one && git add old.one && test_tick && + git commit --date="@12345 +0400" -m "Old one" && + >old.two && git add old.two && test_tick && + git commit --date="@23456 +0500" -m "Old two" && + >old.three && git add old.three && test_tick && + git commit --date="@34567 +0600" -m "Old three" && + + git cat-file commit HEAD^^ >actual && + grep "author .* 12345 +0400$" actual && + git cat-file commit HEAD^ >actual && + grep "author .* 23456 +0500$" actual && + git cat-file commit HEAD >actual && + grep "author .* 34567 +0600$" actual && + + git rebase --onto HEAD^^ HEAD^ && + + git cat-file commit HEAD >actual && + grep "author .* 34567 +0600$" actual +' + test_done diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh index aea6685984..7f8693b928 100755 --- a/t/t3401-rebase-partial.sh +++ b/t/t3401-rebase-partial.sh @@ -11,51 +11,43 @@ local branch. ' . ./test-lib.sh -test_expect_success \ - 'prepare repository with topic branch' \ - 'echo First > A && - git update-index --add A && - git commit -m "Add A." && - - git checkout -b my-topic-branch && - - echo Second > B && - git update-index --add B && - git commit -m "Add B." && - - echo AnotherSecond > C && - git update-index --add C && - git commit -m "Add C." && - - git checkout -f master && +test_expect_success 'prepare repository with topic branch' ' + test_commit A && + git checkout -b my-topic-branch && + test_commit B && + test_commit C && + git checkout -f master && + test_commit A2 A.t +' - echo Third >> A && - git update-index A && - git commit -m "Modify A." +test_expect_success 'pick top patch from topic branch into master' ' + git cherry-pick C && + git checkout -f my-topic-branch ' -test_expect_success \ - 'pick top patch from topic branch into master' \ - 'git cherry-pick my-topic-branch^0 && - git checkout -f my-topic-branch && - git branch master-merge master && - git branch my-topic-branch-merge my-topic-branch +test_debug ' + git cherry master && + git format-patch -k --stdout --full-index master >/dev/null && + gitk --all & sleep 1 ' -test_debug \ - 'git cherry master && - git format-patch -k --stdout --full-index master >/dev/null && - gitk --all & sleep 1 +test_expect_success 'rebase topic branch against new master and check git am did not get halted' ' + git rebase master && + test_path_is_missing .git/rebase-apply ' -test_expect_success \ - 'rebase topic branch against new master and check git am did not get halted' \ - 'git rebase master && test ! -d .git/rebase-apply' +test_expect_success 'rebase --merge topic branch that was partially merged upstream' ' + git reset --hard C && + git rebase --merge master && + test_path_is_missing .git/rebase-merge +' -test_expect_success \ - 'rebase --merge topic branch that was partially merged upstream' \ - 'git checkout -f my-topic-branch-merge && - git rebase --merge master-merge && - test ! -d .git/rebase-merge' +test_expect_success 'rebase ignores empty commit' ' + git reset --hard A && + git commit --allow-empty -m empty && + test_commit D && + git rebase C && + test $(git log --format=%s C..) = "D" +' test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 47c8371c7e..025c1c610e 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -247,6 +247,7 @@ test_expect_success '-p handles "no changes" gracefully' ' ' test_expect_failure 'exchange two commits with -p' ' + git checkout H && FAKE_LINES="2 1" git rebase -i -p HEAD~2 && test H = $(git cat-file commit HEAD^ | sed -ne \$p) && test G = $(git cat-file commit HEAD | sed -ne \$p) @@ -295,7 +296,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 && @@ -323,7 +324,7 @@ test_expect_success 'verbose flag is heeded, even after --continue' ' echo resolved > file1 && git add file1 && git rebase --continue > output && - grep "^ file1 | 2 +-$" output + grep "^ file1 | 2 +-$" output ' test_expect_success 'multi-squash only fires up editor once' ' @@ -527,6 +528,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) && @@ -610,8 +625,38 @@ test_expect_success 'submodule rebase -i' ' FAKE_LINES="1 squash 2 3" git rebase -i A ' +test_expect_success 'submodule conflict setup' ' + git tag submodule-base && + git checkout HEAD^ && + ( + cd sub && git checkout HEAD^ && echo 4 >elif && + git add elif && git commit -m "submodule conflict" + ) && + git add sub && + test_tick && + git commit -m "Conflict in submodule" && + git tag submodule-topic +' + +test_expect_success 'rebase -i continue with only submodule staged' ' + test_must_fail git rebase -i submodule-base && + git add sub && + git rebase --continue && + test $(git rev-parse submodule-base) != $(git rev-parse HEAD) +' + +test_expect_success 'rebase -i continue with unstaged submodule' ' + git checkout submodule-topic && + git reset --hard && + test_must_fail git rebase -i submodule-base && + git reset && + git rebase --continue && + test $(git rev-parse submodule-base) = $(git rev-parse HEAD) +' + test_expect_success 'avoid unnecessary reset' ' git checkout master && + git reset --hard && test-chmtime =123456789 file3 && git update-index --refresh && HEAD=$(git rev-parse HEAD) && diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index fe5f936988..6898377910 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -62,4 +62,9 @@ test_expect_success 'rebase -n overrides config rebase.stat config' ' ! grep "^ fileX | *1 +$" diffstat.txt ' +test_expect_success 'rebase --onto outputs the invalid ref' ' + test_must_fail git rebase --onto invalid-ref HEAD HEAD 2>err && + grep "invalid-ref" err +' + test_done diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh index 08201e2331..6de4e2263f 100755 --- a/t/t3409-rebase-preserve-merges.sh +++ b/t/t3409-rebase-preserve-merges.sh @@ -37,7 +37,15 @@ export GIT_AUTHOR_EMAIL # \ # B2 <-- origin/topic # -# In all cases, 'topic' is rebased onto '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 && @@ -57,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" && @@ -123,4 +138,15 @@ test_expect_success 'rebase -p preserves no-ff merges' ' ) ' +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..dc81bf27eb 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 @@ -56,6 +56,7 @@ test_expect_success 'squash F1 into D1' ' # And rebase G1..M1 onto E2 test_expect_success 'rebase two levels of merge' ' + git checkout A1 && test_commit G1 && test_commit H1 && test_commit I1 && diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index b38be8e937..a1e86c4097 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -33,7 +33,7 @@ test_auto_fixup () { test_tick && git rebase $2 -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) && + test_line_count = 3 actual && git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) @@ -62,7 +62,7 @@ test_auto_squash () { test_tick && git rebase $2 -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) && + test_line_count = 3 actual && git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 2 = $(git cat-file commit HEAD^ | grep first | wc -l) @@ -90,7 +90,7 @@ test_expect_success 'misspelled auto squash' ' test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && - test 4 = $(wc -l <actual) && + test_line_count = 4 actual && git diff --exit-code final-missquash && test 0 = $(git rev-list final-missquash...HEAD | wc -l) ' @@ -109,7 +109,7 @@ test_expect_success 'auto squash that matches 2 commits' ' test_tick && git rebase --autosquash -i HEAD~4 && git log --oneline >actual && - test 4 = $(wc -l <actual) && + test_line_count = 4 actual && git diff --exit-code final-multisquash && test 1 = "$(git cat-file blob HEAD^^:file1)" && test 2 = $(git cat-file commit HEAD^^ | grep first | wc -l) && @@ -130,7 +130,7 @@ test_expect_success 'auto squash that matches a commit after the squash' ' test_tick && git rebase --autosquash -i HEAD~4 && git log --oneline >actual && - test 5 = $(wc -l <actual) && + test_line_count = 5 actual && git diff --exit-code final-presquash && test 0 = "$(git cat-file blob HEAD^^:file1)" && test 1 = "$(git cat-file blob HEAD^:file1)" && @@ -147,7 +147,7 @@ test_expect_success 'auto squash that matches a sha1' ' test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) && + test_line_count = 3 actual && git diff --exit-code final-shasquash && test 1 = "$(git cat-file blob HEAD^:file1)" && test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l) @@ -163,7 +163,7 @@ test_expect_success 'auto squash that matches longer sha1' ' test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) && + test_line_count = 3 actual && git diff --exit-code final-longshasquash && test 1 = "$(git cat-file blob HEAD^:file1)" && test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l) @@ -179,7 +179,7 @@ test_auto_commit_flags () { test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) && + test_line_count = 3 actual && git diff --exit-code final-commit-$1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test $2 = $(git cat-file commit HEAD^ | grep first | wc -l) diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 1e855cdae5..2680375628 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -51,7 +51,7 @@ test_expect_success 'rebase --continue remembers merge strategy and options' ' 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 + cat >test-bin/git-merge-funny <<-EOF && #!$SHELL_PATH case "\$1" in --opt) ;; *) exit 2 ;; esac shift && @@ -77,7 +77,7 @@ test_expect_success 'rebase --continue remembers merge strategy and options' ' 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 + git checkout master && test_commit "commit-new-file-F3" F3 3 && git config rerere.enabled true && test_must_fail git rebase -m master topic && diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh index bd8efaf005..e70ac10a0c 100755 --- a/t/t3419-rebase-patch-id.sh +++ b/t/t3419-rebase-patch-id.sh @@ -39,7 +39,7 @@ run() } test_expect_success 'setup' ' - git commit --allow-empty -m initial + git commit --allow-empty -m initial && git tag root ' diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh index 0ab52da902..e37547f41a 100755 --- a/t/t3502-cherry-pick-merge.sh +++ b/t/t3502-cherry-pick-merge.sh @@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' ' git reset --hard && git checkout a^0 && - test_must_fail git cherry-pick -m 1 b && + test_expect_code 128 git cherry-pick -m 1 b && git diff --exit-code a -- ' diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh index 9aefe3a1be..e27f39d1e5 100755 --- a/t/t3503-cherry-pick-root.sh +++ b/t/t3503-cherry-pick-root.sh @@ -16,12 +16,20 @@ 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 && echo first >expect && test_cmp expect file1 @@ -50,4 +58,21 @@ test_expect_success 'revert a root commit with an external strategy' ' ' +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^^^ + +' + test_done diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh index c10b28cf57..5a1340cee6 100755 --- a/t/t3505-cherry-pick-empty.sh +++ b/t/t3505-cherry-pick-empty.sh @@ -18,7 +18,12 @@ test_expect_success setup ' echo third >> file1 && git add file1 && test_tick && - git commit --allow-empty-message -m "" + git commit --allow-empty-message -m "" && + + git checkout master && + git checkout -b empty-branch2 && + test_tick && + git commit --allow-empty -m "empty" ' @@ -48,4 +53,52 @@ test_expect_success 'index lockfile was removed' ' ' +test_expect_success 'cherry pick an empty non-ff commit without --allow-empty' ' + git checkout master && + echo fourth >>file2 && + git add file2 && + git commit -m "fourth" && + test_must_fail git cherry-pick empty-branch2 +' + +test_expect_success 'cherry pick an empty non-ff commit with --allow-empty' ' + git checkout master && + git cherry-pick --allow-empty empty-branch2 +' + +test_expect_success 'cherry pick with --keep-redundant-commits' ' + git checkout master && + git cherry-pick --keep-redundant-commits HEAD^ +' + +test_expect_success 'cherry-pick a commit that becomes no-op (prep)' ' + git checkout master && + git branch fork && + echo foo >file2 && + git add file2 && + test_tick && + git commit -m "add file2 on master" && + + git checkout fork && + echo foo >file2 && + git add file2 && + test_tick && + git commit -m "add file2 on the side" +' + +test_expect_success 'cherry-pick a no-op without --keep-redundant' ' + git reset --hard && + git checkout fork^0 && + test_must_fail git cherry-pick master +' + +test_expect_success 'cherry-pick a no-op with --keep-redundant' ' + git reset --hard && + git checkout fork^0 && + git cherry-pick --keep-redundant-commits master && + git show -s --format='%s' >actual && + echo "add file2 on master" >expect && + test_cmp expect actual +' + test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 212ec54aaf..0c81b3c427 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -59,6 +59,20 @@ test_expect_success 'advice from failed cherry-pick' " test_i18ncmp expected actual " +test_expect_success 'advice from failed cherry-pick --no-commit' " + 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>' + EOF + test_must_fail git cherry-pick --no-commit picked 2>actual && + + test_i18ncmp expected actual +" + test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' ' pristine_detach initial && test_must_fail git cherry-pick picked && @@ -77,6 +91,21 @@ test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' ' test_must_fail git rev-parse --verify CHERRY_PICK_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 && ( @@ -238,6 +267,60 @@ test_expect_success 'revert also handles conflicts sanely' ' test_cmp expected actual ' +test_expect_success 'failed revert sets REVERT_HEAD' ' + pristine_detach initial && + test_must_fail git revert picked && + test_cmp_rev picked REVERT_HEAD +' + +test_expect_success 'successful revert does not set REVERT_HEAD' ' + pristine_detach base && + git revert base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && + test_must_fail git rev-parse --verify REVERT_HEAD +' + +test_expect_success 'revert --no-commit sets REVERT_HEAD' ' + pristine_detach base && + git revert --no-commit base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && + test_cmp_rev base REVERT_HEAD +' + +test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' ' + pristine_detach base && + echo foo > foo && + test_must_fail git revert base && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && + test_must_fail git rev-parse --verify REVERT_HEAD +' + +test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' ' + pristine_detach initial && + ( + GIT_CHERRY_PICK_HELP="and then do something else" && + GIT_REVERT_HELP="and then do something else, again" && + export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP && + test_must_fail git revert picked + ) && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && + test_cmp_rev picked REVERT_HEAD +' + +test_expect_success 'git reset clears REVERT_HEAD' ' + pristine_detach initial && + test_must_fail git revert picked && + git reset && + test_must_fail git rev-parse --verify REVERT_HEAD +' + +test_expect_success 'failed commit does not clear REVERT_HEAD' ' + pristine_detach initial && + test_must_fail git revert picked && + test_must_fail git commit && + test_cmp_rev picked REVERT_HEAD +' + test_expect_success 'revert conflict, diff3 -m style' ' pristine_detach initial && git config merge.conflictstyle diff3 && diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh index 8e09fd0319..75f7ff4f2f 100755 --- a/t/t3508-cherry-pick-many-commits.sh +++ b/t/t3508-cherry-pick-many-commits.sh @@ -35,55 +35,69 @@ test_expect_success setup ' ' test_expect_success 'cherry-pick first..fourth works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick first..fourth && + git diff --quiet other && + git diff --quiet HEAD other && + check_head_differs_from fourth +' + +test_expect_success 'output to keep user entertained during multi-pick' ' cat <<-\EOF >expected && [master OBJID] second Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) [master OBJID] third Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) [master OBJID] fourth Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) EOF git checkout -f master && git reset --hard first && test_tick && git cherry-pick first..fourth >actual && + sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy && + test_line_count -ge 3 actual.fuzzy && + test_i18ncmp expected actual.fuzzy +' + +test_expect_success 'cherry-pick --strategy resolve first..fourth works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick --strategy resolve first..fourth && git diff --quiet other && git diff --quiet HEAD other && - - sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy && - test_cmp expected actual.fuzzy && check_head_differs_from fourth ' -test_expect_success 'cherry-pick --strategy resolve first..fourth works' ' +test_expect_success 'output during multi-pick indicates merge strategy' ' cat <<-\EOF >expected && Trying simple merge. [master OBJID] second Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) Trying simple merge. [master OBJID] third Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) Trying simple merge. [master OBJID] fourth Author: A U Thor <author@example.com> - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) EOF git checkout -f master && git reset --hard first && test_tick && git cherry-pick --strategy resolve first..fourth >actual && - git diff --quiet other && - git diff --quiet HEAD other && sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy && - test_cmp expected actual.fuzzy && - check_head_differs_from fourth + test_i18ncmp expected actual.fuzzy ' test_expect_success 'cherry-pick --ff first..fourth works' ' diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh new file mode 100755 index 0000000000..f4e6450d6a --- /dev/null +++ b/t/t3510-cherry-pick-sequence.sh @@ -0,0 +1,520 @@ +#!/bin/sh + +test_description='Test cherry-pick continuation features + + + conflicting: rewrites unrelated to conflicting + + yetanotherpick: rewrites foo to e + + 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 + +# Repeat first match 10 times +_r10='\1\1\1\1\1\1\1\1\1\1' + +pristine_detach () { + git cherry-pick --quit && + git checkout -f "$1^0" && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x +} + +test_cmp_rev () { + git rev-parse --verify "$1" >expect.rev && + git rev-parse --verify "$2" >actual.rev && + test_cmp expect.rev actual.rev +} + +test_expect_success setup ' + git config advice.detachedhead false && + 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 && + test_commit yetanotherpick foo e && + pristine_detach initial && + test_commit conflicting unrelated +' + +test_expect_success 'cherry-pick persists data on failure' ' + pristine_detach initial && + test_expect_code 1 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 mid-cherry-pick-sequence' ' + pristine_detach initial && + test_must_fail git cherry-pick base..anotherpick && + test_cmp_rev picked CHERRY_PICK_HEAD && + # "oops, I forgot that these patches rely on the change from base" + git checkout HEAD foo && + git cherry-pick base && + git cherry-pick picked && + git cherry-pick --continue && + git diff --exit-code anotherpick +' + +test_expect_success 'cherry-pick persists opts correctly' ' + pristine_detach initial && + test_expect_code 128 git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours initial..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 '--quit does not complain when no cherry-pick is in progress' ' + pristine_detach initial && + git cherry-pick --quit +' + +test_expect_success '--abort requires cherry-pick in progress' ' + pristine_detach initial && + test_must_fail git cherry-pick --abort +' + +test_expect_success '--quit cleans up sequencer state' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..picked && + git cherry-pick --quit && + test_path_is_missing .git/sequencer +' + +test_expect_success '--quit keeps HEAD and conflicted index intact' ' + pristine_detach initial && + cat >expect <<-\EOF && + OBJID + :100644 100644 OBJID OBJID M unrelated + OBJID + :000000 100644 OBJID OBJID A foo + :000000 100644 OBJID OBJID A unrelated + EOF + test_expect_code 1 git cherry-pick base..picked && + git cherry-pick --quit && + test_path_is_missing .git/sequencer && + test_must_fail git update-index --refresh && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + test_cmp expect actual +' + +test_expect_success '--abort to cancel multiple cherry-pick' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + git cherry-pick --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev initial HEAD && + git update-index --refresh && + git diff-index --exit-code HEAD +' + +test_expect_success '--abort to cancel single cherry-pick' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick picked && + git cherry-pick --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev initial HEAD && + git update-index --refresh && + git diff-index --exit-code HEAD +' + +test_expect_success 'cherry-pick --abort to cancel multiple revert' ' + pristine_detach anotherpick && + test_expect_code 1 git revert base..picked && + git cherry-pick --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev anotherpick HEAD && + git update-index --refresh && + git diff-index --exit-code HEAD +' + +test_expect_success 'revert --abort works, too' ' + pristine_detach anotherpick && + test_expect_code 1 git revert base..picked && + git revert --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev anotherpick HEAD +' + +test_expect_success '--abort to cancel single revert' ' + pristine_detach anotherpick && + test_expect_code 1 git revert picked && + git revert --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev anotherpick HEAD && + git update-index --refresh && + git diff-index --exit-code HEAD +' + +test_expect_success '--abort keeps unrelated change, easy case' ' + pristine_detach unrelatedpick && + echo changed >expect && + test_expect_code 1 git cherry-pick picked..yetanotherpick && + echo changed >unrelated && + git cherry-pick --abort && + test_cmp expect unrelated +' + +test_expect_success '--abort refuses to clobber unrelated change, harder case' ' + pristine_detach initial && + echo changed >expect && + test_expect_code 1 git cherry-pick base..anotherpick && + echo changed >unrelated && + test_must_fail git cherry-pick --abort && + test_cmp expect unrelated && + git rev-list HEAD >log && + test_line_count = 2 log && + test_must_fail git update-index --refresh && + + git checkout unrelated && + git cherry-pick --abort && + test_cmp_rev initial HEAD +' + +test_expect_success 'cherry-pick still writes sequencer state when one commit is left' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..picked && + test_path_is_dir .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 '--abort after last commit in sequence' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..picked && + git cherry-pick --abort && + test_path_is_missing .git/sequencer && + test_cmp_rev initial HEAD && + git update-index --refresh && + git diff-index --exit-code HEAD +' + +test_expect_success 'cherry-pick does not implicitly stomp an existing operation' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + test-chmtime -v +0 .git/sequencer >expect && + test_expect_code 128 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_expect_code 128 git cherry-pick --continue +' + +test_expect_success '--continue complains when there are unresolved conflicts' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + test_expect_code 128 git cherry-pick --continue +' + +test_expect_success '--continue of single cherry-pick' ' + pristine_detach initial && + echo c >expect && + test_must_fail git cherry-pick picked && + echo c >foo && + git add foo && + git cherry-pick --continue && + + test_cmp expect foo && + test_cmp_rev initial HEAD^ && + git diff --exit-code HEAD && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD +' + +test_expect_success '--continue of single revert' ' + pristine_detach initial && + echo resolved >expect && + echo "Revert \"picked\"" >expect.msg && + test_must_fail git revert picked && + echo resolved >foo && + git add foo && + git cherry-pick --continue && + + git diff --exit-code HEAD && + test_cmp expect foo && + test_cmp_rev initial HEAD^ && + git diff-tree -s --pretty=tformat:%s HEAD >msg && + test_cmp expect.msg msg && + test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && + test_must_fail git rev-parse --verify REVERT_HEAD +' + +test_expect_success '--continue after resolving conflicts' ' + pristine_detach initial && + echo d >expect && + cat >expect.log <<-\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_must_fail git cherry-pick base..anotherpick && + echo c >foo && + git add foo && + git cherry-pick --continue && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual.log && + test_cmp expect foo && + test_cmp expect.log actual.log +' + +test_expect_success '--continue after resolving conflicts and committing' ' + pristine_detach initial && + test_expect_code 1 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 asks for help after resolving patch to nil' ' + pristine_detach conflicting && + test_must_fail git cherry-pick initial..picked && + + test_cmp_rev unrelatedpick CHERRY_PICK_HEAD && + git checkout HEAD -- unrelated && + test_must_fail git cherry-pick --continue 2>msg && + test_i18ngrep "The previous cherry-pick is now empty" msg +' + +test_expect_success 'follow advice and skip nil patch' ' + pristine_detach conflicting && + test_must_fail git cherry-pick initial..picked && + + git checkout HEAD -- unrelated && + test_must_fail git cherry-pick --continue && + git reset && + git cherry-pick --continue && + + git rev-list initial..HEAD >commits && + test_line_count = 3 commits +' + +test_expect_success '--continue respects opts' ' + pristine_detach initial && + test_expect_code 1 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 '--continue of single-pick respects -x' ' + pristine_detach initial && + test_must_fail git cherry-pick -x picked && + echo c >foo && + git add foo && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + git cat-file commit HEAD >msg && + grep "cherry picked from" msg +' + +test_expect_success '--continue respects -x in first commit in multi-pick' ' + pristine_detach initial && + test_must_fail git cherry-pick -x picked anotherpick && + echo c >foo && + git add foo && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + git cat-file commit HEAD^ >msg && + picked=$(git rev-parse --verify picked) && + grep "cherry picked from.*$picked" msg +' + +test_expect_success '--signoff is not automatically propagated to resolved conflict' ' + pristine_detach initial && + test_expect_code 1 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 '--signoff dropped for implicit commit of resolution, multi-pick case' ' + pristine_detach initial && + test_must_fail git cherry-pick -s picked anotherpick && + echo c >foo && + git add foo && + git cherry-pick --continue && + + git diff --exit-code HEAD && + test_cmp_rev initial HEAD^^ && + git cat-file commit HEAD^ >msg && + ! grep Signed-off-by: msg +' + +test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' ' + pristine_detach initial && + test_must_fail git cherry-pick -s picked && + echo c >foo && + git add foo && + git cherry-pick --continue && + + git diff --exit-code HEAD && + test_cmp_rev initial HEAD^ && + git cat-file commit HEAD >msg && + ! grep Signed-off-by: msg +' + +test_expect_success 'malformed instruction sheet 1' ' + pristine_detach initial && + test_expect_code 1 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_expect_code 128 git cherry-pick --continue +' + +test_expect_success 'malformed instruction sheet 2' ' + pristine_detach initial && + test_expect_code 1 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_expect_code 128 git cherry-pick --continue +' + +test_expect_success 'empty commit set' ' + pristine_detach initial && + test_expect_code 128 git cherry-pick base..base +' + +test_expect_success 'malformed instruction sheet 3' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + echo "resolved" >foo && + git add foo && + git commit && + sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet && + cp new_sheet .git/sequencer/todo && + test_expect_code 128 git cherry-pick --continue +' + +test_expect_success 'instruction sheet, fat-fingers version' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + echo "c" >foo && + git add foo && + git commit && + sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet && + cp new_sheet .git/sequencer/todo && + git cherry-pick --continue +' + +test_expect_success 'commit descriptions in insn sheet are optional' ' + pristine_detach initial && + test_expect_code 1 git cherry-pick base..anotherpick && + echo "c" >foo && + git add foo && + git commit && + cut -d" " -f1,2 .git/sequencer/todo >new_sheet && + cp new_sheet .git/sequencer/todo && + git cherry-pick --continue && + test_path_is_missing .git/sequencer && + git rev-list HEAD >commits && + test_line_count = 4 commits +' + +test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 575d9508a0..874b3a6444 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -179,6 +179,21 @@ test_expect_success 'git add --refresh' ' test -z "`git diff-index HEAD -- foo`" ' +test_expect_success 'git add --refresh with pathspec' ' + git reset --hard && + echo >foo && echo >bar && echo >baz && + git add foo bar baz && H=$(git rev-parse :foo) && git rm -f foo && + echo "100644 $H 3 foo" | git update-index --index-info && + test-chmtime -60 bar baz && + >expect && + git add --refresh bar >actual && + test_cmp expect actual && + + git diff-files --name-only >actual && + ! grep bar actual&& + grep baz actual +' + test_expect_success POSIXPERM,SANITY 'git add should fail atomically upon an unreadable file' ' git reset --hard && date >foo1 && diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 9e236f9cc0..098a6ae4a0 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -330,4 +330,30 @@ test_expect_success PERL 'split hunk "add -p (edit)"' ' ! grep "^+15" actual ' +test_expect_success 'patch mode ignores unmerged entries' ' + git reset --hard && + test_commit conflict && + test_commit non-conflict && + git checkout -b side && + test_commit side conflict.t && + git checkout master && + test_commit master conflict.t && + test_must_fail git merge side && + echo changed >non-conflict.t && + echo y | git add -p >output && + ! grep a/conflict.t output && + cat >expected <<-\EOF && + * Unmerged path conflict.t + diff --git a/non-conflict.t b/non-conflict.t + index f766221..5ea2ed4 100644 + --- a/non-conflict.t + +++ b/non-conflict.t + @@ -1 +1 @@ + -non-conflict + +changed + EOF + git diff --cached >diff && + test_cmp expected diff +' + test_done diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index c06a5ee766..37ddabba2d 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -34,6 +34,12 @@ test_expect_success 'no encoding header for base case' ' test z = "z$E" ' +test_expect_failure 'UTF-16 refused because of NULs' ' + echo UTF-16 >F && + git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt +' + + for H in ISO8859-1 eucJP ISO-2022-JP do test_expect_success "$H setup" ' @@ -147,19 +153,19 @@ 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" && git config --unset-all i18n.commitencoding && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && - test 3 = $(wc -l <actual) + test_line_count = 3 actual ' } 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 7197aae1ed..cd042633ba 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -432,7 +432,7 @@ test_expect_success 'stash branch - stashes on stack, stash-like argument' ' test $(git ls-files --modified | wc -l) -eq 1 ' -test_expect_success 'stash show - stashes on stack, stash-like argument' ' +test_expect_success 'stash show format defaults to --stat' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && @@ -443,10 +443,25 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' ' STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && - file | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + file | 1 + + 1 file changed, 1 insertion(+) EOF git stash show ${STASH_ID} >actual && + test_i18ncmp expected actual +' + +test_expect_success 'stash show - stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + git stash && + test_when_finished "git stash drop" && + echo bar >> file && + STASH_ID=$(git stash create) && + git reset --hard && + echo "1 0 file" >expected && + git stash show --numstat ${STASH_ID} >actual && test_cmp expected actual ' @@ -480,11 +495,8 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' ' echo foo >> file && STASH_ID=$(git stash create) && git reset --hard && - cat >expected <<-EOF && - file | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - EOF - git stash show ${STASH_ID} >actual && + echo "1 0 file" >expected && + git stash show --numstat ${STASH_ID} >actual && test_cmp expected actual ' @@ -542,7 +554,7 @@ test_expect_success 'ref with non-existent reflog' ' 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 && @@ -601,4 +613,28 @@ test_expect_success 'stash apply shows status same as git status (relative to cu test_cmp expect actual ' +cat > expect << EOF +diff --git a/HEAD b/HEAD +new file mode 100644 +index 0000000..fe0cbee +--- /dev/null ++++ b/HEAD +@@ -0,0 +1 @@ ++file-not-a-ref +EOF + +test_expect_success 'stash where working directory contains "HEAD" file' ' + git stash clear && + git reset --hard && + echo file-not-a-ref > HEAD && + git add HEAD && + test_tick && + git stash && + git diff-files --quiet && + git diff-index --cached --quiet HEAD && + test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" && + git diff stash^..stash > output && + test_cmp output expect +' + test_done diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index 781fd71681..70655c1848 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -7,7 +7,8 @@ test_expect_success PERL 'setup' ' mkdir dir && echo parent > dir/foo && echo dummy > bar && - git add bar dir/foo && + echo committed > HEAD && + git add bar dir/foo HEAD && git commit -m initial && test_tick && test_commit second dir/foo head && @@ -17,47 +18,57 @@ test_expect_success PERL 'setup' ' save_head ' -# note: bar sorts before dir, so the first 'n' is always to skip 'bar' +# note: order of files with unstaged changes: HEAD bar dir/foo test_expect_success PERL 'saying "n" does nothing' ' + set_state HEAD HEADfile_work HEADfile_index && set_state dir/foo work index && - (echo n; echo n) | test_must_fail git stash save -p && - verify_state dir/foo work index && - verify_saved_state bar + (echo n; echo n; echo n) | test_must_fail git stash save -p && + verify_state HEAD HEADfile_work HEADfile_index && + verify_saved_state bar && + verify_state dir/foo work index ' test_expect_success PERL 'git stash -p' ' - (echo n; echo y) | git stash save -p && - verify_state dir/foo head index && + (echo y; echo n; echo y) | git stash save -p && + verify_state HEAD committed HEADfile_index && verify_saved_state bar && + verify_state dir/foo head index && git reset --hard && git stash apply && - verify_state dir/foo work head && - verify_state bar dummy dummy + verify_state HEAD HEADfile_work committed && + verify_state bar dummy dummy && + verify_state dir/foo work head ' test_expect_success PERL 'git stash -p --no-keep-index' ' - set_state dir/foo work index && + set_state HEAD HEADfile_work HEADfile_index && set_state bar bar_work bar_index && - (echo n; echo y) | git stash save -p --no-keep-index && - verify_state dir/foo head head && + set_state dir/foo work index && + (echo y; echo n; echo y) | git stash save -p --no-keep-index && + verify_state HEAD committed committed && verify_state bar bar_work dummy && + verify_state dir/foo head head && git reset --hard && git stash apply --index && - verify_state dir/foo work index && - verify_state bar dummy bar_index + verify_state HEAD HEADfile_work HEADfile_index && + verify_state bar dummy bar_index && + verify_state dir/foo work index ' test_expect_success PERL 'git stash --no-keep-index -p' ' - set_state dir/foo work index && + set_state HEAD HEADfile_work HEADfile_index && set_state bar bar_work bar_index && - (echo n; echo y) | git stash save --no-keep-index -p && + set_state dir/foo work index && + (echo y; echo n; echo y) | git stash save --no-keep-index -p && + verify_state HEAD committed committed && 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 + verify_state HEAD HEADfile_work HEADfile_index && + verify_state bar dummy bar_index && + verify_state dir/foo work index ' test_expect_success PERL 'none of this moved HEAD' ' diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh new file mode 100755 index 0000000000..a5e7e6b2ba --- /dev/null +++ b/t/t3905-stash-include-untracked.sh @@ -0,0 +1,188 @@ +#!/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 && + echo 1 > HEAD && + 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/HEAD b/HEAD +new file mode 100644 +index 0000000..d00491f +--- /dev/null ++++ b/HEAD +@@ -0,0 +1 @@ ++1 +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 +HEAD +file2 +untracked +EOF + +test_expect_success 'stash save --include-untracked stashed the untracked files' ' + test_path_is_missing file2 && + test_path_is_missing untracked && + test_path_is_missing HEAD && + git diff HEAD stash^3 -- HEAD 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 +?? HEAD +?? 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 + +# Must direct output somewhere where it won't be considered an untracked file +test_expect_success 'stash save --include-untracked -q is quiet' ' + echo 1 > file5 && + git stash save --include-untracked --quiet > .git/stash-output.out 2>&1 && + test_line_count = 0 .git/stash-output.out && + rm -f .git/stash-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_path_is_missing 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_path_is_missing file4 +' + +test_expect_success 'stash save --all does not respect .gitignore' ' + git stash -a && + test_path_is_missing ignored && + test_path_is_missing ignored.d && + test_path_is_missing .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/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index ff8c2f7532..7a3e1f9a24 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -8,23 +8,52 @@ test_description='Test mode change diffs. ' . ./test-lib.sh -test_expect_success \ - 'setup' \ - 'echo frotz >rezrov && - git update-index --add rezrov && - tree=`git write-tree` && - echo $tree' - -test_expect_success \ - 'chmod' \ - 'test_chmod +x rezrov && - git diff-index $tree >current' - -sed -e 's/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' <current >check -echo ":100644 100755 X X M rezrov" >expected - -test_expect_success \ - 'verify' \ - 'test_cmp expected check' +sed_script='s/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' + +test_expect_success 'setup' ' + echo frotz >rezrov && + git update-index --add rezrov && + tree=`git write-tree` && + echo $tree +' + +test_expect_success 'chmod' ' + test_chmod +x rezrov && + git diff-index $tree >current && + sed -e "$sed_script" <current >check && + echo ":100644 100755 X X M rezrov" >expected && + test_cmp expected check +' + +test_expect_success 'prepare binary file' ' + git commit -m rezrov && + printf "\00\01\02\03\04\05\06" >binbin && + git add binbin && + git commit -m binbin +' + +test_expect_success '--stat output after text chmod' ' + test_chmod -x rezrov && + echo " 0 files changed" >expect && + git diff HEAD --stat >actual && + test_cmp expect actual +' + +test_expect_success '--shortstat output after text chmod' ' + git diff HEAD --shortstat >actual && + test_cmp expect actual +' + +test_expect_success '--stat output after binary chmod' ' + test_chmod +x binbin && + echo " 0 files changed" >expect && + git diff HEAD --stat >actual && + test_cmp expect actual +' + +test_expect_success '--shortstat output after binary chmod' ' + git diff HEAD --shortstat >actual && + test_cmp expect actual +' test_done diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index fbc8cd8f05..af5134b70c 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -48,6 +48,14 @@ test_expect_success \ compare_diff_raw current expected' cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + '"*file1" should show path1/file1' \ + 'git diff-index --cached $tree -- "*file1" >current && + compare_diff_raw current expected' + +cat >expected <<\EOF :100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M file0 EOF test_expect_success \ diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index 408a19c4c2..f0d5041c11 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,85 +9,110 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -cat > expected << EOF -diff --git a/frotz b/frotz -new file mode 120000 -index 0000000..7c465af ---- /dev/null -+++ b/frotz -@@ -0,0 +1 @@ -+xyzzy -\ No newline at end of file -EOF - -test_expect_success SYMLINKS \ - 'diff new symlink' \ - 'ln -s xyzzy frotz && - git update-index && - tree=$(git write-tree) && - git update-index --add frotz && - GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current && - compare_diff_patch current expected' - -test_expect_success SYMLINKS \ - 'diff unchanged symlink' \ - 'tree=$(git write-tree) && - git update-index frotz && - test -z "$(git diff-index --name-only $tree)"' - -cat > expected << EOF -diff --git a/frotz b/frotz -deleted file mode 120000 -index 7c465af..0000000 ---- a/frotz -+++ /dev/null -@@ -1 +0,0 @@ --xyzzy -\ No newline at end of file -EOF +test_expect_success SYMLINKS 'diff new symlink and file' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + new file mode 120000 + index 0000000..7c465af + --- /dev/null + +++ b/frotz + @@ -0,0 +1 @@ + +xyzzy + \ No newline at end of file + diff --git a/nitfol b/nitfol + new file mode 100644 + index 0000000..7c465af + --- /dev/null + +++ b/nitfol + @@ -0,0 +1 @@ + +xyzzy + EOF + ln -s xyzzy frotz && + echo xyzzy >nitfol && + git update-index && + tree=$(git write-tree) && + git update-index --add frotz nitfol && + GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff removed symlink' \ - 'mv frotz frotz2 && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff unchanged symlink and file' ' + tree=$(git write-tree) && + git update-index frotz nitfol && + test -z "$(git diff-index --name-only $tree)" +' -cat > expected << EOF -diff --git a/frotz b/frotz -EOF +test_expect_success SYMLINKS 'diff removed symlink and file' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + deleted file mode 120000 + index 7c465af..0000000 + --- a/frotz + +++ /dev/null + @@ -1 +0,0 @@ + -xyzzy + \ No newline at end of file + diff --git a/nitfol b/nitfol + deleted file mode 100644 + index 7c465af..0000000 + --- a/nitfol + +++ /dev/null + @@ -1 +0,0 @@ + -xyzzy + EOF + mv frotz frotz2 && + mv nitfol nitfol2 && + git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff identical, but newly created symlink' \ - 'ln -s xyzzy frotz && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' ' + >expected && + rm -f frotz nitfol && + echo xyzzy >nitfol && + test-chmtime +10 nitfol && + ln -s xyzzy frotz && + git diff-index -M -p $tree >current && + compare_diff_patch expected current && -cat > expected << EOF -diff --git a/frotz b/frotz -index 7c465af..df1db54 120000 ---- a/frotz -+++ b/frotz -@@ -1 +1 @@ --xyzzy -\ No newline at end of file -+yxyyz -\ No newline at end of file -EOF + >expected && + git diff-index -M -p -w $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff different symlink' \ - 'rm frotz && - ln -s yxyyz frotz && - git diff-index -M -p $tree > current && - compare_diff_patch current expected' +test_expect_success SYMLINKS 'diff different symlink and file' ' + cat >expected <<-\EOF && + diff --git a/frotz b/frotz + index 7c465af..df1db54 120000 + --- a/frotz + +++ b/frotz + @@ -1 +1 @@ + -xyzzy + \ No newline at end of file + +yxyyz + \ No newline at end of file + diff --git a/nitfol b/nitfol + index 7c465af..df1db54 100644 + --- a/nitfol + +++ b/nitfol + @@ -1 +1 @@ + -xyzzy + +yxyyz + EOF + rm -f frotz && + ln -s yxyyz frotz && + echo yxyyz >nitfol && + git diff-index -M -p $tree >current && + compare_diff_patch expected current +' -test_expect_success SYMLINKS \ - 'diff symlinks with non-existing targets' \ - 'ln -s narf pinky && - ln -s take\ over brain && - test_must_fail git diff --no-index pinky brain > output 2> output.err && - grep narf output && - ! grep error output.err' +test_expect_success SYMLINKS 'diff symlinks with non-existing targets' ' + ln -s narf pinky && + ln -s take\ over brain && + test_must_fail git diff --no-index pinky brain >output 2>output.err && + grep narf output && + ! test -s output.err +' test_expect_success SYMLINKS 'setup symlinks with attributes' ' echo "*.bin diff=bin" >>.gitattributes && @@ -96,19 +121,19 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' ' git add -N file.bin link.bin ' -cat >expect <<'EOF' -diff --git a/file.bin b/file.bin -index e69de29..d95f3ad 100644 -Binary files a/file.bin and b/file.bin differ -diff --git a/link.bin b/link.bin -index e69de29..dce41ec 120000 ---- a/link.bin -+++ b/link.bin -@@ -0,0 +1 @@ -+file.bin -\ No newline at end of file -EOF test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' ' + cat >expect <<-\EOF && + diff --git a/file.bin b/file.bin + index e69de29..d95f3ad 100644 + Binary files a/file.bin and b/file.bin differ + diff --git a/link.bin b/link.bin + index e69de29..dce41ec 120000 + --- a/link.bin + +++ b/link.bin + @@ -0,0 +1 @@ + +file.bin + \ No newline at end of file + EOF git config diff.bin.binary true && git diff file.bin link.bin >actual && test_cmp expect actual diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 05ec062832..6cebb3951b 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -8,11 +8,18 @@ test_description='Binary diff and apply . ./test-lib.sh +cat >expect.binary-numstat <<\EOF +1 1 a +- - b +1 1 c +- - d +EOF + 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' @@ -23,13 +30,35 @@ cat > expected <<\EOF d | Bin 4 files changed, 2 insertions(+), 2 deletions(-) EOF -test_expect_success 'diff without --binary' \ - 'git diff | git apply --stat --summary >current && - test_cmp expected current' +test_expect_success '"apply --stat" output for binary file change' ' + git diff >diff && + git apply --stat --summary <diff >current && + test_i18ncmp expected current +' + +test_expect_success 'diff --shortstat output for binary file change' ' + echo " 4 files changed, 2 insertions(+), 2 deletions(-)" >expected && + git diff --shortstat >current && + test_i18ncmp expected current +' + +test_expect_success 'diff --shortstat output for binary file change only' ' + echo " 1 file changed, 0 insertions(+), 0 deletions(-)" >expected && + git diff --shortstat -- b >current && + test_i18ncmp expected current +' -test_expect_success 'diff with --binary' \ - 'git diff --binary | git apply --stat --summary >current && - test_cmp expected current' +test_expect_success 'apply --numstat notices binary file change' ' + git diff >diff && + git apply --numstat <diff >current && + test_cmp expect.binary-numstat current +' + +test_expect_success 'apply --numstat understands diff --binary format' ' + git diff --binary >diff && + git apply --numstat <diff >current && + test_cmp expect.binary-numstat current +' # apply needs to be able to skip the binary material correctly # in order to report the line number of a corrupt patch. @@ -90,4 +119,23 @@ test_expect_success 'diff --no-index with binary creation' ' test_cmp expected actual ' +cat >expect <<EOF + binfile | Bin 0 -> 1026 bytes + textfile | 10000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF + +test_expect_success 'diff --stat with binary files and big change count' ' + echo X | dd of=binfile bs=1k seek=1 && + git add binfile && + i=0 && + while test $i -lt 10000; do + echo $i && + i=$(($i + 1)) + done >textfile && + git add textfile && + git diff --cached --stat binfile textfile >output && + grep " | " output >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 93a6f20871..e77c09c37e 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -128,7 +128,12 @@ do } >"$actual" && if test -f "$expect" then - test_cmp "$expect" "$actual" && + case $cmd in + *format-patch* | *-stat*) + test_i18ncmp "$expect" "$actual";; + *) + test_cmp "$expect" "$actual";; + esac && rm -f "$actual" else # this is to help developing new tests. diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master index 3a9f78a09d..9951e3677d 100644 --- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master +++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master @@ -1,8 +1,8 @@ $ git diff-tree --cc --patch-with-stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side index a61ad8cb13..cec33fa3f0 100644 --- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side +++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side @@ -1,9 +1,9 @@ $ git diff-tree --cc --patch-with-stat --summary side c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master index 49f23b9215..db3c0a7b2c 100644 --- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master +++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master @@ -1,8 +1,8 @@ $ git diff-tree --cc --patch-with-stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c diff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master index cc6eb3b3d5..d019867dd9 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master +++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master @@ -1,6 +1,6 @@ $ git diff-tree --cc --stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) $ diff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side index 50362be7bf..12b2eee17e 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side +++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side @@ -1,8 +1,8 @@ $ git diff-tree --cc --stat --summary side c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 $ diff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_master index fae7f33255..40b91796b3 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_master +++ b/t/t4013/diff.diff-tree_--cc_--stat_master @@ -1,6 +1,6 @@ $ git diff-tree --cc --stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) $ diff --git a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial index d5c333a378..817ed06f82 100644 --- a/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial +++ b/t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial @@ -1,9 +1,9 @@ $ git diff-tree --pretty=oneline --root --patch-with-stat initial 444ac553ac7612cc88969031b02b3767fb8a353a Initial - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) diff --git a/dir/sub b/dir/sub new file mode 100644 diff --git a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side index 4d30e7eddc..fe3f6b7c7e 100644 --- a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side +++ b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial index 7dfa6af3c9..06eb77e386 100644 --- a/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial +++ b/t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) diff --git a/dir/sub b/dir/sub new file mode 100644 diff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial index 43bfce253e..680eab5f27 100644 --- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial +++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial index 9154aa4d47..9722d1b3a7 100644 --- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial +++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial @@ -5,8 +5,8 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) $ diff --git a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial index 1562b62708..ad69ffe647 100644 --- a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial +++ b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial @@ -1,9 +1,9 @@ $ git diff-tree --root --patch-with-stat initial 444ac553ac7612cc88969031b02b3767fb8a353a - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) diff --git a/dir/sub b/dir/sub new file mode 100644 diff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_master index ac9f641fb4..81c3021541 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master +++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_master @@ -1,6 +1,6 @@ $ git diff-tree -c --stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) $ diff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_side b/t/t4013/diff.diff-tree_-c_--stat_--summary_side index 2afcca11f4..e8dc12bfbf 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_--summary_side +++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_side @@ -1,8 +1,8 @@ $ git diff-tree -c --stat --summary side c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 $ diff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_master index c2fe6a98c5..89d59b1548 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_master +++ b/t/t4013/diff.diff-tree_-c_--stat_master @@ -1,6 +1,6 @@ $ git diff-tree -c --stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) $ diff --git a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side index 9ed317a198..be8d1ea1bd 100644 --- a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side +++ b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side @@ -1,8 +1,8 @@ $ git diff --patch-with-stat -r initial..side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.diff_--patch-with-stat_initial..side b/t/t4013/diff.diff_--patch-with-stat_initial..side index 8b50629e66..5424e6d566 100644 --- a/t/t4013/diff.diff_--patch-with-stat_initial..side +++ b/t/t4013/diff.diff_--patch-with-stat_initial..side @@ -1,8 +1,8 @@ $ git diff --patch-with-stat initial..side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.diff_--stat_initial..side b/t/t4013/diff.diff_--stat_initial..side index 0517b5d631..b7741e2b83 100644 --- a/t/t4013/diff.diff_--stat_initial..side +++ b/t/t4013/diff.diff_--stat_initial..side @@ -1,6 +1,6 @@ $ git diff --stat initial..side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) $ diff --git a/t/t4013/diff.diff_-r_--stat_initial..side b/t/t4013/diff.diff_-r_--stat_initial..side index 245220d3f9..5d514f55b9 100644 --- a/t/t4013/diff.diff_-r_--stat_initial..side +++ b/t/t4013/diff.diff_-r_--stat_initial..side @@ -1,6 +1,6 @@ $ git diff -r --stat initial..side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) $ diff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side index 52116d3ead..547ca065a5 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side @@ -12,10 +12,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master index ce49bd676e..52fedc179e 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -121,10 +121,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ index 5f1b23863b..1c3cde251b 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side index 4a2364abc2..4717bd8313 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side @@ -12,10 +12,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master index 43b81eba54..02c4db7ec5 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -121,10 +121,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master index ca3f60bf0e..c7677c5951 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -121,10 +121,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master index 08f23014bc..5b3e34e2c0 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -121,10 +121,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ index 07f1230d31..d13f8a8128 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ index 29e00ab8af..caec5537de 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ @@ -14,9 +14,9 @@ Content-Transfer-Encoding: 8bit This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side index 67633d424a..d3a6762130 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side @@ -12,10 +12,10 @@ Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 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 3b4e113012..244d964fc6 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^ @@ -10,10 +10,10 @@ A U Thor (2): Second Third - dir/sub | 4 ++++ - file0 | 3 +++ - file1 | 3 +++ - file2 | 3 --- + dir/sub | 4 ++++ + file0 | 3 +++ + file1 | 3 +++ + file2 | 3 --- 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 file1 delete mode 100644 file2 @@ -28,9 +28,9 @@ Subject: [DIFFERENT_PREFIX 1/2] Second This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -73,9 +73,9 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000 Subject: [DIFFERENT_PREFIX 2/2] Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master index f7752ebbea..bfc287a147 100644 --- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master +++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master @@ -6,9 +6,9 @@ Subject: [PATCH] Second This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -51,9 +51,9 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000 Subject: [PATCH] Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -85,10 +85,10 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000 Subject: [PATCH] Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master index 8e67dbf76f..568f6f584e 100644 --- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master +++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master @@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -51,9 +51,9 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000 Subject: [PATCH 2/3] Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -85,10 +85,10 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000 Subject: [PATCH 3/3] Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master index 7b89978e32..5f0352f9f7 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--stdout_initial..master @@ -6,9 +6,9 @@ Subject: [PATCH 1/3] Second This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -51,9 +51,9 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000 Subject: [PATCH 2/3] Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -85,10 +85,10 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000 Subject: [PATCH 3/3] Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^ index b7f9725dc4..2ae454d807 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--stdout_initial..master^ @@ -6,9 +6,9 @@ Subject: [PATCH 1/2] Second This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -51,9 +51,9 @@ Date: Mon, 26 Jun 2006 00:02:00 +0000 Subject: [PATCH 2/2] Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.format-patch_--stdout_initial..side b/t/t4013/diff.format-patch_--stdout_initial..side index e765088475..a7d52fbeea 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--stdout_initial..side @@ -5,10 +5,10 @@ Date: Mon, 26 Jun 2006 00:03:00 +0000 Subject: [PATCH] Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ index bd7f5c0f70..a18f1472a9 100644 --- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ @@ -12,8 +12,8 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -31,8 +31,8 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -53,8 +53,8 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master index 14595a614c..ae425c4672 100644 --- a/t/t4013/diff.log_--patch-with-stat_master +++ b/t/t4013/diff.log_--patch-with-stat_master @@ -12,10 +12,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -54,9 +54,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -86,9 +86,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ index 5a4e72765d..d5207cadf4 100644 --- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ @@ -12,8 +12,8 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -31,8 +31,8 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -53,8 +53,8 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master index df0aaa9f2c..0fc1e8cd71 100644 --- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master @@ -6,9 +6,9 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c @@ -44,10 +44,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -87,9 +87,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -120,9 +120,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -162,10 +162,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master index c11b5f2c7f..dffc09dde9 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master @@ -12,10 +12,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -55,9 +55,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -88,9 +88,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -130,10 +130,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master index 5f0c98f9ce..55aa98012d 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_master @@ -12,10 +12,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -54,9 +54,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -86,9 +86,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dir/sub b/dir/sub @@ -127,10 +127,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) diff --git a/dir/sub b/dir/sub new file mode 100644 diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master index e62c368dc6..019d85f7de 100644 --- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master @@ -6,9 +6,9 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --combined dir/sub index cead32e,7289e35..992913c @@ -44,10 +44,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -87,9 +87,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -120,9 +120,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -162,10 +162,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.show_--patch-with-stat_--summary_side b/t/t4013/diff.show_--patch-with-stat_--summary_side index 377f2b7b7a..95a474ef1d 100644 --- a/t/t4013/diff.show_--patch-with-stat_--summary_side +++ b/t/t4013/diff.show_--patch-with-stat_--summary_side @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.show_--patch-with-stat_side b/t/t4013/diff.show_--patch-with-stat_side index fb14c530d2..974e99be82 100644 --- a/t/t4013/diff.show_--patch-with-stat_side +++ b/t/t4013/diff.show_--patch-with-stat_side @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.show_--stat_--summary_side b/t/t4013/diff.show_--stat_--summary_side index 5bd5977628..a71492f9bf 100644 --- a/t/t4013/diff.show_--stat_--summary_side +++ b/t/t4013/diff.show_--stat_--summary_side @@ -5,9 +5,9 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 $ diff --git a/t/t4013/diff.show_--stat_side b/t/t4013/diff.show_--stat_side index 3b22327e48..9be712458f 100644 --- a/t/t4013/diff.show_--stat_side +++ b/t/t4013/diff.show_--stat_side @@ -5,8 +5,8 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) $ diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ index 6a467cccc1..c8b6af2f43 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ +++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ @@ -5,8 +5,8 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -24,8 +24,8 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -46,8 +46,8 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_master index 1e1bbe1963..1ac431ba92 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_master +++ b/t/t4013/diff.whatchanged_--patch-with-stat_master @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -47,9 +47,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -79,9 +79,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dir/sub b/dir/sub diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ index 13789f169b..b30c28588f 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ +++ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ @@ -5,8 +5,8 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -24,8 +24,8 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -46,8 +46,8 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master index e96ff1fb8c..30aae7817b 100644 --- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master @@ -6,9 +6,9 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c @@ -44,10 +44,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -87,9 +87,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -120,9 +120,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -162,10 +162,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master index 0291153587..db90e51525 100644 --- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -48,9 +48,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -81,9 +81,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -123,10 +123,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master index 9b0349cd55..9a6cc92ce7 100644 --- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master +++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master @@ -5,10 +5,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -47,9 +47,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -79,9 +79,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dir/sub b/dir/sub @@ -120,10 +120,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) diff --git a/dir/sub b/dir/sub new file mode 100644 diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master index c0aff68ef6..d1d32bd34c 100644 --- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master @@ -6,9 +6,9 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' - dir/sub | 2 ++ - file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + 2 files changed, 5 insertions(+) diff --combined dir/sub index cead32e,7289e35..992913c @@ -44,10 +44,10 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- - dir/sub | 2 ++ - file0 | 3 +++ - file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -87,9 +87,9 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- - dir/sub | 2 ++ - file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -120,9 +120,9 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 --- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 @@ -162,10 +162,10 @@ Date: Mon Jun 26 00:00:00 2006 +0000 Initial --- - dir/sub | 2 ++ - file0 | 3 +++ - file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 +++ + 3 files changed, 8 insertions(+) create mode 100644 dir/sub create mode 100644 file0 create mode 100644 file2 diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 92248d24c4..959aa26ef5 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 ' @@ -231,7 +243,7 @@ check_threading () { (git format-patch --stdout "$@"; echo $? > status.out) | # Prints everything between the Message-ID and In-Reply-To, # and replaces all Message-ID-lookalikes by a sequence number - perl -ne ' + "$PERL_PATH" -ne ' if (/^(message-id|references|in-reply-to)/i) { $printing = 1; } elsif (/^\S/) { @@ -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 @@ -505,11 +518,6 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' ' ' cat > expect << EOF ---- - file | 16 ++++++++++++++++ - 1 files changed, 16 insertions(+), 0 deletions(-) - -diff --git a/file b/file index 40f36c6..2dc5c23 100644 --- a/file +++ b/file @@ -524,7 +532,9 @@ EOF test_expect_success 'format-patch respects -U' ' git format-patch -U4 -2 && - sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output && + sed -e "1,/^diff/d" -e "/^+5/q" \ + <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \ + >output && test_cmp expect output ' @@ -657,6 +667,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 +684,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 ' @@ -869,4 +883,12 @@ test_expect_success 'empty subject prefix does not have extra space' ' 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/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 9059bcd69e..cc3db1304e 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -103,7 +103,7 @@ test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expe git diff -w -b --ignore-space-at-eol > out test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out' -tr 'Q' '\015' << EOF > expect +tr 'Q_' '\015 ' << EOF > expect diff --git a/x b/x index d99af23..8b32fb5 100644 --- a/x @@ -111,19 +111,19 @@ index d99af23..8b32fb5 100644 @@ -1,6 +1,6 @@ -whitespace at beginning + whitespace at beginning - whitespace change + whitespace change -whitespace in the middle +white space in the middle - whitespace at end + whitespace at end__ unchanged line - CR at endQ + CR at end EOF git diff -b > out test_expect_success 'another test, with -b' 'test_cmp expect out' git diff -b --ignore-space-at-eol > out test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out' -tr 'Q' '\015' << EOF > expect +tr 'Q_' '\015 ' << EOF > expect diff --git a/x b/x index d99af23..8b32fb5 100644 --- a/x @@ -135,9 +135,9 @@ index d99af23..8b32fb5 100644 + whitespace at beginning +whitespace change +white space in the middle - whitespace at end + whitespace at end__ unchanged line - CR at endQ + CR at end EOF git diff --ignore-space-at-eol > out test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out' diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index ab0c2f0574..97b81778cb 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -57,22 +57,33 @@ test_expect_success TABS_IN_FILENAMES 'git diff --summary -M HEAD' ' test_cmp expect actual ' -test_expect_success TABS_IN_FILENAMES 'setup expected files' ' -cat >expect <<\EOF - pathname.1 => "Rpathname\twith HT.0" | 0 - pathname.3 => "Rpathname\nwith LF.0" | 0 - "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 - pathname.2 => Rpathname with SP.0 | 0 - "pathname\twith HT.2" => Rpathname with SP.1 | 0 - pathname.0 => Rpathname.0 | 0 - "pathname\twith HT.0" => Rpathname.1 | 0 - 7 files changed, 0 insertions(+), 0 deletions(-) -EOF +test_expect_success TABS_IN_FILENAMES 'git diff --numstat -M HEAD' ' + cat >expect <<-\EOF && + 0 0 pathname.1 => "Rpathname\twith HT.0" + 0 0 pathname.3 => "Rpathname\nwith LF.0" + 0 0 "pathname\twith HT.3" => "Rpathname\nwith LF.1" + 0 0 pathname.2 => Rpathname with SP.0 + 0 0 "pathname\twith HT.2" => Rpathname with SP.1 + 0 0 pathname.0 => Rpathname.0 + 0 0 "pathname\twith HT.0" => Rpathname.1 + EOF + git diff --numstat -M HEAD >actual && + test_cmp expect actual ' test_expect_success TABS_IN_FILENAMES 'git diff --stat -M HEAD' ' + cat >expect <<-\EOF && + pathname.1 => "Rpathname\twith HT.0" | 0 + pathname.3 => "Rpathname\nwith LF.0" | 0 + "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 + pathname.2 => Rpathname with SP.0 | 0 + "pathname\twith HT.2" => Rpathname with SP.1 | 0 + pathname.0 => Rpathname.0 | 0 + "pathname\twith HT.0" => Rpathname.1 | 0 + 7 files changed, 0 insertions(+), 0 deletions(-) + EOF git diff --stat -M HEAD >actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_done diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index b68c56b68c..4bd2a1c838 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -105,7 +105,7 @@ test_expect_funcname () { grep "^@@.*@@ $1" diff } -for p in bibtex cpp csharp fortran html java objc pascal perl php python ruby tex +for p in bibtex cpp csharp fortran html java matlab objc pascal perl php python ruby tex do test_expect_success "builtin $p pattern compiles" ' echo "*.java diff=$p" >.gitattributes && diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 083f62d1d6..2e7d73f090 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -48,7 +48,53 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' ' ' +test_expect_success SYMLINKS 'typechange diff' ' + rm -f file && + ln -s elif file && + GIT_EXTERNAL_DIFF=echo git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z120000 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } && + GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff >actual && + git diff >expect && + test_cmp expect actual +' + +test_expect_success 'diff.external' ' + git reset --hard && + echo third >file && + test_config diff.external echo && + git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } +' + +test_expect_success 'diff.external should apply only to diff' ' + test_config diff.external echo && + git log -p -1 HEAD | + grep "^diff --git a/file b/file" +' + +test_expect_success 'diff.external and --no-ext-diff' ' + test_config diff.external echo && + git diff --no-ext-diff | + grep "^diff --git a/file b/file" +' + test_expect_success 'diff attribute' ' + git reset --hard && + echo third >file && git config diff.parrot.command echo && @@ -113,12 +159,25 @@ test_expect_success 'diff attribute and --no-ext-diff' ' ' +test_expect_success 'GIT_EXTERNAL_DIFF trumps diff.external' ' + >.gitattributes && + test_config diff.external "echo ext-global" && + GIT_EXTERNAL_DIFF="echo ext-env" git diff | grep ext-env +' + +test_expect_success 'attributes trump GIT_EXTERNAL_DIFF and diff.external' ' + test_config diff.foo.command "echo ext-attribute" && + test_config diff.external "echo ext-global" && + echo "file diff=foo" >.gitattributes && + GIT_EXTERNAL_DIFF="echo ext-env" git diff | grep ext-attribute +' + test_expect_success 'no diff with -diff' ' echo >.gitattributes "file -diff" && git diff | grep Binary ' -echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file +echo NULZbetweenZwords | "$PERL_PATH" -pe 'y/Z/\000/' > file test_expect_success 'force diff with "diff"' ' echo >.gitattributes "file diff" && diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh index 3ccc237a8d..36e2f075c9 100755 --- a/t/t4029-diff-trailing-space.sh +++ b/t/t4029-diff-trailing-space.sh @@ -27,7 +27,7 @@ test_expect_success \ git config --bool diff.suppressBlankEmpty true && git diff f > actual && test_cmp exp actual && - perl -i.bak -p -e "s/^\$/ /" exp && + "$PERL_PATH" -i.bak -p -e "s/^\$/ /" exp && git config --bool diff.suppressBlankEmpty false && git diff f > actual && test_cmp exp actual && diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 88c5619ae7..eebb1eed8b 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -21,7 +21,7 @@ EOF cat >hexdump <<'EOF' #!/bin/sh -perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" +"$PERL_PATH" -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" EOF chmod +x hexdump @@ -85,13 +85,17 @@ test_expect_success 'status -v produces text' ' ' cat >expect.stat <<'EOF' - file | Bin 2 -> 4 bytes - 1 files changed, 0 insertions(+), 0 deletions(-) + file | Bin 2 -> 4 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) EOF test_expect_success 'diffstat does not run textconv' ' echo file diff=fail >.gitattributes && git diff --stat HEAD^ HEAD >actual && - test_cmp expect.stat actual + test_i18ncmp expect.stat actual && + + head -n1 <expect.stat >expect.line1 && + head -n1 <actual >actual.line1 && + test_cmp expect.line1 actual.line1 ' # restore working setup echo file diff=foo >.gitattributes diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh index 7d7470f21b..eacc6694f7 100755 --- a/t/t4031-diff-rewrite-binary.sh +++ b/t/t4031-diff-rewrite-binary.sh @@ -44,17 +44,23 @@ test_expect_success 'rewrite diff can show binary patch' ' grep "GIT binary patch" diff ' -test_expect_success 'rewrite diff --stat shows binary changes' ' +test_expect_success 'rewrite diff --numstat shows binary changes' ' + git diff -B --numstat --summary >diff && + grep -e "- - " diff && + grep " rewrite file" diff +' + +test_expect_success 'diff --stat counts binary rewrite as 0 lines' ' git diff -B --stat --summary >diff && grep "Bin" diff && - grep "0 insertions.*0 deletions" diff && + test_i18ngrep "0 insertions.*0 deletions" diff && grep " rewrite file" diff ' { echo "#!$SHELL_PATH" cat <<'EOF' -perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" +"$PERL_PATH" -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" EOF } >dump chmod +x dump 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 c374aa4c1c..30d42cb3bf 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -3,6 +3,7 @@ test_description='word diff colors' . ./test-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh cat >pre.simple <<-\EOF h(4) @@ -293,12 +294,17 @@ test_expect_success '--word-diff=none' ' word_diff --word-diff=plain --word-diff=none ' +test_expect_success 'unset default driver' ' + test_unconfig diff.wordregex +' + 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 matlab test_language_driver objc test_language_driver pascal test_language_driver perl @@ -333,4 +339,49 @@ test_expect_success 'word-diff with diff.sbe' ' word_diff --word-diff=plain ' +test_expect_success 'word-diff with no newline at EOF' ' + cat >expect <<-\EOF && + diff --git a/pre b/post + index 7bf316e..3dd0303 100644 + --- a/pre + +++ b/post + @@ -1 +1 @@ + a a [-a-]{+ab+} a a + EOF + printf "%s" "a a a a a" >pre && + printf "%s" "a a ab a a" >post && + word_diff --word-diff=plain +' + +test_expect_success 'setup history with two files' ' + echo "a b; c" >a.tex && + echo "a b; c" >z.txt && + git add a.tex z.txt && + git commit -minitial && + + # modify both + echo "a bx; c" >a.tex && + echo "a bx; c" >z.txt && + git commit -mmodified -a +' + +test_expect_success 'wordRegex for the first file does not apply to the second' ' + echo "*.tex diff=tex" >.gitattributes && + git config diff.tex.wordRegex "[a-z]+|." && + cat >expect <<-\EOF && + diff --git a/a.tex b/a.tex + --- a/a.tex + +++ b/a.tex + @@ -1 +1 @@ + a [-b-]{+bx+}; c + diff --git a/z.txt b/z.txt + --- a/z.txt + +++ b/z.txt + @@ -1 +1 @@ + a [-b;-]{+bx;+} c + EOF + git diff --word-diff HEAD~ >actual && + compare_diff_patch expect actual +' + test_done diff --git a/t/t4034/matlab/expect b/t/t4034/matlab/expect new file mode 100644 index 0000000000..72cf3e93a2 --- /dev/null +++ b/t/t4034/matlab/expect @@ -0,0 +1,14 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index dc204db..70e05f0 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,9 +1,9 @@<RESET> +(<RED>1<RESET><GREEN>0<RESET>) (<RED>-1e10<RESET><GREEN>-0e10<RESET>) '<RED>b<RESET><GREEN>y<RESET>'; +[<RED>a<RESET><GREEN>x<RESET>] {<RED>a<RESET><GREEN>x<RESET>} <RED>a<RESET><GREEN>x<RESET>.<RED>b<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 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>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>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><GREEN>y<RESET>; +<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<RESET><GREEN>y<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>b<RESET><GREEN>y<RESET>; diff --git a/t/t4034/matlab/post b/t/t4034/matlab/post new file mode 100644 index 0000000000..70e05f0753 --- /dev/null +++ b/t/t4034/matlab/post @@ -0,0 +1,9 @@ +(0) (-0e10) 'y'; +[x] {x} x.y; +~x; +x*y x.*y x/y x./y x^y x.^y x.\y 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; diff --git a/t/t4034/matlab/pre b/t/t4034/matlab/pre new file mode 100644 index 0000000000..dc204db486 --- /dev/null +++ b/t/t4034/matlab/pre @@ -0,0 +1,9 @@ +(1) (-1e10) 'b'; +[a] {a} a.b; +~a; +a*b a.*b a/b a./b a^b a.^b a.\b 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; diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh index e747e84227..231412d100 100755 --- a/t/t4035-diff-quiet.sh +++ b/t/t4035-diff-quiet.sh @@ -10,71 +10,142 @@ test_expect_success 'setup' ' git commit -m first && echo 2 >b && git add . && - git commit -a -m second + git commit -a -m second && + mkdir -p test-outside/repo && ( + cd test-outside/repo && + git init && + echo "1 1" >a && + git add . && + git commit -m 1 + ) && + mkdir -p test-outside/non/git && ( + cd test-outside/non/git && + echo "1 1" >a && + echo "1 1" >matching-file && + echo "1 1 " >trailing-space && + echo "1 1" >extra-space && + echo "2" >never-match + ) ' test_expect_success 'git diff-tree HEAD^ HEAD' ' git diff-tree --quiet HEAD^ HEAD >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt ' test_expect_success 'git diff-tree HEAD^ HEAD -- a' ' git diff-tree --quiet HEAD^ HEAD -- a >cnt - test $? = 0 && test $(wc -l <cnt) = 0 + test $? = 0 && test_line_count = 0 cnt ' test_expect_success 'git diff-tree HEAD^ HEAD -- b' ' git diff-tree --quiet HEAD^ HEAD -- b >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt ' # this diff outputs one line: sha1 of the given head test_expect_success 'echo HEAD | git diff-tree --stdin' ' echo $(git rev-parse HEAD) | git diff-tree --quiet --stdin >cnt - test $? = 1 && test $(wc -l <cnt) = 1 + test $? = 1 && test_line_count = 1 cnt ' test_expect_success 'git diff-tree HEAD HEAD' ' git diff-tree --quiet HEAD HEAD >cnt - test $? = 0 && test $(wc -l <cnt) = 0 + test $? = 0 && test_line_count = 0 cnt ' test_expect_success 'git diff-files' ' git diff-files --quiet >cnt - test $? = 0 && test $(wc -l <cnt) = 0 + test $? = 0 && test_line_count = 0 cnt ' test_expect_success 'git diff-index --cached HEAD' ' git diff-index --quiet --cached HEAD >cnt - test $? = 0 && test $(wc -l <cnt) = 0 + test $? = 0 && test_line_count = 0 cnt ' test_expect_success 'git diff-index --cached HEAD^' ' git diff-index --quiet --cached HEAD^ >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt ' test_expect_success 'git diff-index --cached HEAD^' ' echo text >>b && echo 3 >c && git add . && { git diff-index --quiet --cached HEAD^ >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt } ' test_expect_success 'git diff-tree -Stext HEAD^ HEAD -- b' ' git commit -m "text in b" && { git diff-tree --quiet -Stext HEAD^ HEAD -- b >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt } ' test_expect_success 'git diff-tree -Snot-found HEAD^ HEAD -- b' ' git diff-tree --quiet -Snot-found HEAD^ HEAD -- b >cnt - test $? = 0 && test $(wc -l <cnt) = 0 + test $? = 0 && test_line_count = 0 cnt ' test_expect_success 'git diff-files' ' echo 3 >>c && { git diff-files --quiet >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt } ' test_expect_success 'git diff-index --cached HEAD' ' git update-index c && { git diff-index --quiet --cached HEAD >cnt - test $? = 1 && test $(wc -l <cnt) = 0 + test $? = 1 && test_line_count = 0 cnt } ' +test_expect_success 'git diff, one file outside repo' ' + ( + cd test-outside/repo && + test_expect_code 0 git diff --quiet a ../non/git/matching-file && + test_expect_code 1 git diff --quiet a ../non/git/extra-space + ) +' + +test_expect_success 'git diff, both files outside repo' ' + ( + GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" && + export GIT_CEILING_DIRECTORIES && + cd test-outside/non/git && + test_expect_code 0 git diff --quiet a matching-file && + test_expect_code 1 git diff --quiet a extra-space + ) +' + +test_expect_success 'git diff --ignore-space-at-eol, one file outside repo' ' + ( + cd test-outside/repo && + test_expect_code 0 git diff --quiet --ignore-space-at-eol a ../non/git/trailing-space && + test_expect_code 1 git diff --quiet --ignore-space-at-eol a ../non/git/extra-space + ) +' + +test_expect_success 'git diff --ignore-space-at-eol, both files outside repo' ' + ( + GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" && + export GIT_CEILING_DIRECTORIES && + cd test-outside/non/git && + test_expect_code 0 git diff --quiet --ignore-space-at-eol a trailing-space && + test_expect_code 1 git diff --quiet --ignore-space-at-eol a extra-space + ) +' + +test_expect_success 'git diff --ignore-all-space, one file outside repo' ' + ( + cd test-outside/repo && + test_expect_code 0 git diff --quiet --ignore-all-space a ../non/git/trailing-space && + test_expect_code 0 git diff --quiet --ignore-all-space a ../non/git/extra-space && + test_expect_code 1 git diff --quiet --ignore-all-space a ../non/git/never-match + ) +' + +test_expect_success 'git diff --ignore-all-space, both files outside repo' ' + ( + GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/test-outside" && + export GIT_CEILING_DIRECTORIES && + cd test-outside/non/git && + test_expect_code 0 git diff --quiet --ignore-all-space a trailing-space && + test_expect_code 0 git diff --quiet --ignore-all-space a extra-space && + test_expect_code 1 git diff --quiet --ignore-all-space a never-match + ) +' + test_done diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index bf9a7526bd..6c01d0c056 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -458,4 +458,38 @@ EOF test_cmp expected actual ' +test_expect_success 'diff --submodule with objects referenced by alternates' ' + mkdir sub_alt && + (cd sub_alt && + git init && + echo a >a && + git add a && + git commit -m a + ) && + mkdir super && + (cd super && + git clone -s ../sub_alt sub && + git init && + git add sub && + git commit -m "sub a" + ) && + (cd sub_alt && + sha1_before=$(git rev-parse --short HEAD) + echo b >b && + git add b && + git commit -m b + sha1_after=$(git rev-parse --short HEAD) + echo "Submodule sub $sha1_before..$sha1_after: + > b" >../expected + ) && + (cd super && + (cd sub && + git fetch && + git checkout origin/master + ) && + git diff --submodule > ../actual + ) + test_cmp expected actual +' + test_done diff --git a/t/t4043-diff-rename-binary.sh b/t/t4043-diff-rename-binary.sh index 06012811a1..2a2cf91352 100755 --- a/t/t4043-diff-rename-binary.sh +++ b/t/t4043-diff-rename-binary.sh @@ -23,9 +23,8 @@ test_expect_success 'move the files into a "sub" directory' ' ' cat > expected <<\EOF - bar => sub/bar | Bin 5 -> 5 bytes - foo => sub/foo | 0 - 2 files changed, 0 insertions(+), 0 deletions(-) +- - bar => sub/bar +0 0 foo => sub/foo diff --git a/bar b/sub/bar similarity index 100% @@ -38,7 +37,8 @@ rename to sub/foo EOF test_expect_success 'git show -C -C report renames' ' - git show -C -C --raw --binary --stat | tail -n 12 > current && + git show -C -C --raw --binary --numstat >patch-with-stat && + tail -n 11 patch-with-stat >current && test_cmp expected current ' diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index 8a3c63b9e2..3950f5034d 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -29,15 +29,27 @@ test_expect_success "-p $*" " " } +check_numstat() { +expect=$1; shift +cat >expected <<EOF +1 0 $expect +EOF +test_expect_success "--numstat $*" " + echo '1 0 $expect' >expected && + git diff --numstat $* HEAD^ >actual && + test_cmp expected actual +" +} + check_stat() { expect=$1; shift cat >expected <<EOF - $expect | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + $expect | 1 + + 1 file changed, 1 insertion(+) EOF test_expect_success "--stat $*" " git diff --stat $* HEAD^ >actual && - test_cmp expected actual + test_i18ncmp expected actual " } @@ -52,7 +64,7 @@ test_expect_success "--raw $*" " " } -for type in diff stat raw; do +for type in diff numstat stat raw; do check_$type file2 --relative=subdir/ check_$type file2 --relative=subdir check_$type dir/file2 --relative=sub diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh index 29e80a58cd..ed7e093366 100755 --- a/t/t4047-diff-dirstat.sh +++ b/t/t4047-diff-dirstat.sh @@ -252,50 +252,47 @@ EOF ' 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(-) +1 1 changed/text +10 0 dst/copy/changed/text +10 0 dst/copy/rearranged/text +10 0 dst/copy/unchanged/text +10 0 dst/move/changed/text +10 0 dst/move/rearranged/text +10 0 dst/move/unchanged/text +1 1 rearranged/text +0 10 src/move/changed/text +0 10 src/move/rearranged/text +0 10 src/move/unchanged/text 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(-) +1 1 changed/text +10 0 dst/copy/changed/text +10 0 dst/copy/rearranged/text +10 0 dst/copy/unchanged/text +1 1 {src => dst}/move/changed/text +1 1 {src => dst}/move/rearranged/text +0 0 {src => dst}/move/unchanged/text +1 1 rearranged/text 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 && +1 1 changed/text +1 1 {src => dst}/copy/changed/text +1 1 {src => dst}/copy/rearranged/text +0 0 {src => dst}/copy/unchanged/text +1 1 {src => dst}/move/changed/text +1 1 {src => dst}/move/rearranged/text +0 0 {src => dst}/move/unchanged/text +1 1 rearranged/text +EOF + +test_expect_success 'sanity check setup (--numstat)' ' + git diff --numstat HEAD^..HEAD >actual_diff_stat && test_cmp expect_diff_stat actual_diff_stat && - git diff --stat -M HEAD^..HEAD >actual_diff_stat_M && + git diff --numstat -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 && + git diff --numstat -C -C HEAD^..HEAD >actual_diff_stat_CC && test_cmp expect_diff_stat_CC actual_diff_stat_CC ' 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..b41eb61ca8 --- /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(+) + EOF + git diff --stat --stat-count=2 >actual && + test_i18ncmp 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/t4052-stat-output.sh b/t/t4052-stat-output.sh new file mode 100755 index 0000000000..b68afefa3c --- /dev/null +++ b/t/t4052-stat-output.sh @@ -0,0 +1,336 @@ +#!/bin/sh +# +# Copyright (c) 2012 Zbigniew Jędrzejewski-Szmek +# + +test_description='test --stat output of various commands' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-terminal.sh + +# 120 character name +name=aaaaaaaaaa +name=$name$name$name$name$name$name$name$name$name$name$name$name +test_expect_success 'preparation' ' + >"$name" && + git add "$name" && + git commit -m message && + echo a >"$name" && + git commit -m message "$name" +' + +while read cmd args +do + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd: small change with long name gives more space to the name" ' + git $cmd $args >output && + grep " | " output >actual && + test_cmp expect actual + ' + + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" ' + git $cmd $args --stat=40 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-width=width with long name" ' + git $cmd $args --stat-width=40 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + cat >expect <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + EOF + test_expect_success "$cmd --stat=...,name-width with long name" ' + git $cmd $args --stat=60,30 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-name-width with long name" ' + git $cmd $args --stat-name-width=30 >output && + grep " | " output >actual && + test_cmp expect actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + + +test_expect_success 'preparation for big change tests' ' + >abcd && + git add abcd && + git commit -m message && + i=0 && + while test $i -lt 1000 + do + echo $i && i=$(($i + 1)) + done >abcd && + git commit -m message abcd +' + +cat >expect80 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +cat >expect80-graph <<'EOF' +| abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +cat >expect200 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +cat >expect200-graph <<'EOF' +| abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +while read verb expect cmd args +do + test_expect_success "$cmd $verb COLUMNS (big change)" ' + COLUMNS=200 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --graph $verb COLUMNS (big change)" ' + COLUMNS=200 git $cmd $args --graph >output + grep " | " output >actual && + test_cmp "$expect-graph" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect200 diff HEAD^ HEAD --stat +respects expect200 show --stat +respects expect200 log -1 --stat +EOF + +cat >expect40 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++ +EOF +cat >expect40-graph <<'EOF' +| abcd | 1000 ++++++++++++++++++++++++ +EOF +while read verb expect cmd args +do + test_expect_success "$cmd $verb not enough COLUMNS (big change)" ' + COLUMNS=40 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --graph $verb not enough COLUMNS (big change)" ' + COLUMNS=40 git $cmd $args --graph >output + grep " | " output >actual && + test_cmp "$expect-graph" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect40 diff HEAD^ HEAD --stat +respects expect40 show --stat +respects expect40 log -1 --stat +EOF + +cat >expect40 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++ +EOF +cat >expect40-graph <<'EOF' +| abcd | 1000 ++++++++++++++++++++++++++ +EOF +while read verb expect cmd args +do + test_expect_success "$cmd $verb statGraphWidth config" ' + git -c diff.statGraphWidth=26 $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --graph $verb statGraphWidth config" ' + git -c diff.statGraphWidth=26 $cmd $args --graph >output + grep " | " output >actual && + test_cmp "$expect-graph" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect40 diff HEAD^ HEAD --stat +respects expect40 show --stat +respects expect40 log -1 --stat +EOF + + +cat >expect <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++ +EOF +cat >expect-graph <<'EOF' +| abcd | 1000 ++++++++++++++++++++++++++ +EOF +while read cmd args +do + test_expect_success "$cmd --stat=width with big change" ' + git $cmd $args --stat=40 >output + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-width=width with big change" ' + git $cmd $args --stat-width=40 >output + grep " | " output >actual && + test_cmp expect actual + ' + + test_expect_success "$cmd --stat-graph-width with big change" ' + git $cmd $args --stat-graph-width=26 >output + grep " | " output >actual && + test_cmp expect actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --stat-width=width --graph with big change" ' + git $cmd $args --stat-width=40 --graph >output + grep " | " output >actual && + test_cmp expect-graph actual + ' + + test_expect_success "$cmd --stat-graph-width --graph with big change" ' + git $cmd $args --stat-graph-width=26 --graph >output + grep " | " output >actual && + test_cmp expect-graph actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + +test_expect_success 'preparation for long filename tests' ' + cp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + git add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + git commit -m message +' + +cat >expect <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++ +EOF +cat >expect-graph <<'EOF' +| ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++ +EOF +while read cmd args +do + test_expect_success "$cmd --stat=width with big change is more balanced" ' + git $cmd $args --stat-width=60 >output && + grep " | " output >actual && + test_cmp expect actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --stat=width --graph with big change is balanced" ' + git $cmd $args --stat-width=60 --graph >output && + grep " | " output >actual && + test_cmp expect-graph actual + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + +cat >expect80 <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ +EOF +cat >expect80-graph <<'EOF' +| ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ +EOF +cat >expect200 <<'EOF' + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +cat >expect200-graph <<'EOF' +| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +while read verb expect cmd args +do + test_expect_success "$cmd $verb COLUMNS (long filename)" ' + COLUMNS=200 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' + + test "$cmd" != diff || continue + + test_expect_success "$cmd --graph $verb COLUMNS (long filename)" ' + COLUMNS=200 git $cmd $args --graph >output + grep " | " output >actual && + test_cmp "$expect-graph" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect200 diff HEAD^ HEAD --stat +respects expect200 show --stat +respects expect200 log -1 --stat +EOF + +cat >expect1 <<'EOF' + ...aaaaaaa | 1000 ++++++ +EOF +cat >expect1-graph <<'EOF' +| ...aaaaaaa | 1000 ++++++ +EOF +while read verb expect cmd args +do + test_expect_success COLUMNS_CAN_BE_1 \ + "$cmd $verb prefix greater than COLUMNS (big change)" ' + COLUMNS=1 git $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" actual + ' + + test "$cmd" != diff || continue + + test_expect_success COLUMNS_CAN_BE_1 \ + "$cmd --graph $verb prefix greater than COLUMNS (big change)" ' + COLUMNS=1 git $cmd $args --graph >output + grep " | " output >actual && + test_cmp "$expect-graph" actual + ' +done <<\EOF +ignores expect80 format-patch -1 --stdout +respects expect1 diff HEAD^ HEAD --stat +respects expect1 show --stat +respects expect1 log -1 --stat +EOF + +cat >expect <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +test_expect_success 'merge --stat respects COLUMNS (big change)' ' + git checkout -b branch HEAD^^ && + COLUMNS=100 git merge --stat --no-ff master^ >output && + grep " | " output >actual + test_cmp expect actual +' + +cat >expect <<'EOF' + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++ +EOF +test_expect_success 'merge --stat respects COLUMNS (long filename)' ' + COLUMNS=100 git merge --stat --no-ff master >output && + grep " | " output >actual + test_cmp expect actual +' + +test_done diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh new file mode 100755 index 0000000000..979e98398b --- /dev/null +++ b/t/t4053-diff-no-index.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='diff --no-index' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir a && + mkdir b && + echo 1 >a/1 && + echo 2 >a/2 && + git init repo && + echo 1 >repo/a && + mkdir -p non/git && + echo 1 >non/git/a && + echo 1 >non/git/b +' + +test_expect_success 'git diff --no-index directories' ' + git diff --no-index a b >cnt + test $? = 1 && test_line_count = 14 cnt +' + +test_expect_success 'git diff --no-index relative path outside repo' ' + ( + cd repo && + test_expect_code 0 git diff --no-index a ../non/git/a && + test_expect_code 0 git diff --no-index ../non/git/a ../non/git/b + ) +' + +test_done diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 9b433de836..744b8e51be 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -17,13 +17,13 @@ do test_expect_success "$title" ' git apply --stat --summary \ <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current && - test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current + test_i18ncmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current ' test_expect_success "$title with recount" ' sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" | git apply --recount --stat --summary >current && - test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current + test_i18ncmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current ' done <<\EOF rename diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect index eef7f2e65c..55a55c3cc7 100644 --- a/t/t4100/t-apply-8.expect +++ b/t/t4100/t-apply-8.expect @@ -1,2 +1,2 @@ t/t4100-apply-stat.sh | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect index eef7f2e65c..55a55c3cc7 100644 --- a/t/t4100/t-apply-9.expect +++ b/t/t4100/t-apply-9.expect @@ -1,2 +1,2 @@ t/t4100-apply-stat.sh | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index dbbf56cba9..99627bc6d6 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -25,10 +25,10 @@ test_expect_success 'setup' " git commit -m 'Initial Version' 2>/dev/null && git checkout -b binary && - perl -pe 'y/x/\000/' <file1 >file3 && + "$PERL_PATH" -pe 'y/x/\000/' <file1 >file3 && cat file3 >file4 && git add file2 && - perl -pe 'y/\000/v/' <file3 >file1 && + "$PERL_PATH" -pe 'y/\000/v/' <file3 >file1 && rm -f file2 && git update-index --add --remove file1 file2 file3 file4 && git commit -m 'Second Version' && diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh index 2298ece801..fca815392e 100755 --- a/t/t4116-apply-reverse.sh +++ b/t/t4116-apply-reverse.sh @@ -12,14 +12,14 @@ test_description='git apply in reverse test_expect_success setup ' for i in a b c d e f g h i j k l m n; do echo $i; done >file1 && - perl -pe "y/ijk/\\000\\001\\002/" <file1 >file2 && + "$PERL_PATH" -pe "y/ijk/\\000\\001\\002/" <file1 >file2 && git add file1 file2 && git commit -m initial && git tag initial && for i in a b c g h i J K L m o n p q; do echo $i; done >file1 && - perl -pe "y/mon/\\000\\001\\002/" <file1 >file2 && + "$PERL_PATH" -pe "y/mon/\\000\\001\\002/" <file1 >file2 && git commit -a -m second && git tag second && diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh index 94373ca9a0..b1361ce546 100755 --- a/t/t4131-apply-fake-ancestor.sh +++ b/t/t4131-apply-fake-ancestor.sh @@ -11,7 +11,7 @@ test_expect_success 'setup' ' test_commit 1 && test_commit 2 && mkdir sub && - test_commit 3 sub/3 && + test_commit 3 sub/3.t && test_commit 4 ' diff --git a/t/t4136-apply-check.sh b/t/t4136-apply-check.sh new file mode 100755 index 0000000000..a321f7c245 --- /dev/null +++ b/t/t4136-apply-check.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='git apply should exit non-zero with unrecognized input.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit 1 +' + +test_expect_success 'apply --check exits non-zero with unrecognized input' ' + test_must_fail git apply --check - <<-\EOF + I am not a patch + I look nothing like a patch + git apply must fail + EOF +' + +test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 850fc96d1f..cdafd7e7c1 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 && @@ -116,6 +123,7 @@ test_expect_success setup ' git commit -m "added another file" && git format-patch --stdout master >lorem-move.patch && + git format-patch --no-prefix --stdout master >lorem-zero.patch && git checkout -b rename && git mv file renamed && @@ -129,7 +137,7 @@ test_expect_success setup ' git format-patch -M --stdout lorem^ >rename-add.patch && # reset time - unset test_tick && + sane_unset test_tick && test_tick ' @@ -167,6 +175,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" && @@ -219,7 +238,7 @@ test_expect_success 'am stays in branch' ' test_expect_success 'am --signoff does not add Signed-off-by: line if already there' ' git format-patch --stdout HEAD^ >patch3 && - sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4 && + sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 && rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && @@ -241,7 +260,17 @@ test_expect_success 'am --keep really keeps the subject' ' git am --keep patch4 && ! test -d .git/rebase-apply && git cat-file commit HEAD >actual && - grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual + grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual +' + +test_expect_success 'am --keep-non-patch really keeps the non-patch part' ' + rm -fr .git/rebase-apply && + git reset --hard && + git checkout HEAD^ && + git am --keep-non-patch patch4 && + ! test -d .git/rebase-apply && + git cat-file commit HEAD >actual && + grep "^\[foo\] third" actual ' test_expect_success 'am -3 falls back to 3-way merge' ' @@ -258,6 +287,20 @@ test_expect_success 'am -3 falls back to 3-way merge' ' git diff --exit-code lorem ' +test_expect_success 'am -3 -p0 can read --no-prefix patch' ' + rm -fr .git/rebase-apply && + git reset --hard && + git checkout -b lorem3 master2 && + sed -n -e "3,\$p" msg >file && + head -n 9 msg >>file && + git add file && + test_tick && + git commit -m "copied stuff" && + git am -3 -p0 lorem-zero.patch && + ! test -d .git/rebase-apply && + git diff --exit-code lorem +' + test_expect_success 'am can rename a file' ' grep "^rename from" rename.patch && rm -fr .git/rebase-apply && @@ -465,7 +508,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' ' @@ -477,4 +520,14 @@ test_expect_success 'am -q is quiet' ' ! test -s output.out ' +test_expect_success 'am empty-file does not infloop' ' + rm -fr .git/rebase-apply && + git reset --hard && + touch empty-file && + test_tick && + test_must_fail git am empty-file 2>actual && + echo Patch format detection failed. >expected && + test_i18ncmp expected actual +' + test_done 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/t4200-rerere.sh b/t/t4200-rerere.sh index 36255d608a..3ab670d36a 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -78,7 +78,7 @@ test_expect_success 'activate rerere, old style (conflicting merge)' ' test_might_fail git config --unset rerere.enabled && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$("$PERL_PATH" -pe "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 && grep "^=======\$" $rr/preimage && ! test -f $rr/postimage && @@ -91,7 +91,7 @@ test_expect_success 'rerere.enabled works, too' ' git reset --hard && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$("$PERL_PATH" -pe "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 && grep ^=======$ $rr/preimage ' @@ -101,7 +101,7 @@ test_expect_success 'set up rr-cache' ' git config rerere.enabled true && git reset --hard && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$("$PERL_PATH" -pe "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 ' @@ -185,7 +185,7 @@ test_expect_success 'rerere updates postimage timestamp' ' test_expect_success 'rerere clear' ' rm $rr/postimage && - echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR && + echo "$sha1 a1" | "$PERL_PATH" -pe "y/\012/\000/" >.git/MERGE_RR && git rerere clear && ! test -d $rr ' diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 983e34bec6..71be59d446 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -346,11 +346,11 @@ test_expect_success 'set up more tangled history' ' ' cat > expect <<\EOF -* Merge commit 'reach' +* Merge tag 'reach' |\ | \ | \ -*-. \ Merge commit 'octopus-a'; commit 'octopus-b' +*-. \ Merge tags 'octopus-a' and 'octopus-b' |\ \ \ * | | | seventh | | * | octopus-b @@ -516,4 +516,294 @@ test_expect_success 'show added path under "--follow -M"' ' ) ' +cat >expect <<\EOF +* commit COMMIT_OBJECT_NAME +|\ Merge: MERGE_PARENTS +| | Author: A U Thor <author@example.com> +| | +| | Merge HEADS DESCRIPTION +| | +| * commit COMMIT_OBJECT_NAME +| | Author: A U Thor <author@example.com> +| | +| | reach +| | --- +| | reach.t | 1 + +| | 1 file changed, 1 insertion(+) +| | +| | diff --git a/reach.t b/reach.t +| | new file mode 100644 +| | index 0000000..10c9591 +| | --- /dev/null +| | +++ b/reach.t +| | @@ -0,0 +1 @@ +| | +reach +| | +| \ +*-. \ commit COMMIT_OBJECT_NAME +|\ \ \ Merge: MERGE_PARENTS +| | | | Author: A U Thor <author@example.com> +| | | | +| | | | Merge HEADS DESCRIPTION +| | | | +| | * | commit COMMIT_OBJECT_NAME +| | |/ Author: A U Thor <author@example.com> +| | | +| | | octopus-b +| | | --- +| | | octopus-b.t | 1 + +| | | 1 file changed, 1 insertion(+) +| | | +| | | diff --git a/octopus-b.t b/octopus-b.t +| | | new file mode 100644 +| | | index 0000000..d5fcad0 +| | | --- /dev/null +| | | +++ b/octopus-b.t +| | | @@ -0,0 +1 @@ +| | | +octopus-b +| | | +| * | commit COMMIT_OBJECT_NAME +| |/ Author: A U Thor <author@example.com> +| | +| | octopus-a +| | --- +| | octopus-a.t | 1 + +| | 1 file changed, 1 insertion(+) +| | +| | diff --git a/octopus-a.t b/octopus-a.t +| | new file mode 100644 +| | index 0000000..11ee015 +| | --- /dev/null +| | +++ b/octopus-a.t +| | @@ -0,0 +1 @@ +| | +octopus-a +| | +* | commit COMMIT_OBJECT_NAME +|/ Author: A U Thor <author@example.com> +| +| seventh +| --- +| seventh.t | 1 + +| 1 file changed, 1 insertion(+) +| +| diff --git a/seventh.t b/seventh.t +| new file mode 100644 +| index 0000000..9744ffc +| --- /dev/null +| +++ b/seventh.t +| @@ -0,0 +1 @@ +| +seventh +| +* commit COMMIT_OBJECT_NAME +|\ Merge: MERGE_PARENTS +| | Author: A U Thor <author@example.com> +| | +| | Merge branch 'tangle' +| | +| * commit COMMIT_OBJECT_NAME +| |\ Merge: MERGE_PARENTS +| | | Author: A U Thor <author@example.com> +| | | +| | | Merge branch 'side' (early part) into tangle +| | | +| * | commit COMMIT_OBJECT_NAME +| |\ \ Merge: MERGE_PARENTS +| | | | Author: A U Thor <author@example.com> +| | | | +| | | | Merge branch 'master' (early part) into tangle +| | | | +| * | | commit COMMIT_OBJECT_NAME +| | | | Author: A U Thor <author@example.com> +| | | | +| | | | tangle-a +| | | | --- +| | | | tangle-a | 1 + +| | | | 1 file changed, 1 insertion(+) +| | | | +| | | | diff --git a/tangle-a b/tangle-a +| | | | new file mode 100644 +| | | | index 0000000..7898192 +| | | | --- /dev/null +| | | | +++ b/tangle-a +| | | | @@ -0,0 +1 @@ +| | | | +a +| | | | +* | | | commit COMMIT_OBJECT_NAME +|\ \ \ \ Merge: MERGE_PARENTS +| | | | | Author: A U Thor <author@example.com> +| | | | | +| | | | | Merge branch 'side' +| | | | | +| * | | | commit COMMIT_OBJECT_NAME +| | |_|/ Author: A U Thor <author@example.com> +| |/| | +| | | | side-2 +| | | | --- +| | | | 2 | 1 + +| | | | 1 file changed, 1 insertion(+) +| | | | +| | | | diff --git a/2 b/2 +| | | | new file mode 100644 +| | | | index 0000000..0cfbf08 +| | | | --- /dev/null +| | | | +++ b/2 +| | | | @@ -0,0 +1 @@ +| | | | +2 +| | | | +| * | | commit COMMIT_OBJECT_NAME +| | | | Author: A U Thor <author@example.com> +| | | | +| | | | side-1 +| | | | --- +| | | | 1 | 1 + +| | | | 1 file changed, 1 insertion(+) +| | | | +| | | | diff --git a/1 b/1 +| | | | new file mode 100644 +| | | | index 0000000..d00491f +| | | | --- /dev/null +| | | | +++ b/1 +| | | | @@ -0,0 +1 @@ +| | | | +1 +| | | | +* | | | commit COMMIT_OBJECT_NAME +| | | | Author: A U Thor <author@example.com> +| | | | +| | | | Second +| | | | --- +| | | | one | 1 + +| | | | 1 file changed, 1 insertion(+) +| | | | +| | | | diff --git a/one b/one +| | | | new file mode 100644 +| | | | index 0000000..9a33383 +| | | | --- /dev/null +| | | | +++ b/one +| | | | @@ -0,0 +1 @@ +| | | | +case +| | | | +* | | | commit COMMIT_OBJECT_NAME +| |_|/ Author: A U Thor <author@example.com> +|/| | +| | | sixth +| | | --- +| | | a/two | 1 - +| | | 1 file changed, 1 deletion(-) +| | | +| | | diff --git a/a/two b/a/two +| | | deleted file mode 100644 +| | | index 9245af5..0000000 +| | | --- a/a/two +| | | +++ /dev/null +| | | @@ -1 +0,0 @@ +| | | -ni +| | | +* | | commit COMMIT_OBJECT_NAME +| | | Author: A U Thor <author@example.com> +| | | +| | | fifth +| | | --- +| | | a/two | 1 + +| | | 1 file changed, 1 insertion(+) +| | | +| | | diff --git a/a/two b/a/two +| | | new file mode 100644 +| | | index 0000000..9245af5 +| | | --- /dev/null +| | | +++ b/a/two +| | | @@ -0,0 +1 @@ +| | | +ni +| | | +* | | commit COMMIT_OBJECT_NAME +|/ / Author: A U Thor <author@example.com> +| | +| | fourth +| | --- +| | ein | 1 + +| | 1 file changed, 1 insertion(+) +| | +| | diff --git a/ein b/ein +| | new file mode 100644 +| | index 0000000..9d7e69f +| | --- /dev/null +| | +++ b/ein +| | @@ -0,0 +1 @@ +| | +ichi +| | +* | commit COMMIT_OBJECT_NAME +|/ Author: A U Thor <author@example.com> +| +| third +| --- +| ichi | 1 + +| one | 1 - +| 2 files changed, 1 insertion(+), 1 deletion(-) +| +| diff --git a/ichi b/ichi +| new file mode 100644 +| index 0000000..9d7e69f +| --- /dev/null +| +++ b/ichi +| @@ -0,0 +1 @@ +| +ichi +| diff --git a/one b/one +| deleted file mode 100644 +| index 9d7e69f..0000000 +| --- a/one +| +++ /dev/null +| @@ -1 +0,0 @@ +| -ichi +| +* commit COMMIT_OBJECT_NAME +| Author: A U Thor <author@example.com> +| +| second +| --- +| one | 2 +- +| 1 file changed, 1 insertion(+), 1 deletion(-) +| +| diff --git a/one b/one +| index 5626abf..9d7e69f 100644 +| --- a/one +| +++ b/one +| @@ -1 +1 @@ +| -one +| +ichi +| +* commit COMMIT_OBJECT_NAME + Author: A U Thor <author@example.com> + + initial + --- + one | 1 + + 1 file changed, 1 insertion(+) + + diff --git a/one b/one + new file mode 100644 + index 0000000..5626abf + --- /dev/null + +++ b/one + @@ -0,0 +1 @@ + +one +EOF + +sanitize_output () { + sed -e 's/ *$//' \ + -e 's/commit [0-9a-f]*$/commit COMMIT_OBJECT_NAME/' \ + -e 's/Merge: [ 0-9a-f]*$/Merge: MERGE_PARENTS/' \ + -e 's/Merge tag.*/Merge HEADS DESCRIPTION/' \ + -e 's/Merge commit.*/Merge HEADS DESCRIPTION/' \ + -e 's/, 0 deletions(-)//' \ + -e 's/, 0 insertions(+)//' \ + -e 's/ 1 files changed, / 1 file changed, /' \ + -e 's/, 1 deletions(-)/, 1 deletion(-)/' \ + -e 's/, 1 insertions(+)/, 1 insertion(+)/' +} + +test_expect_success 'log --graph with diff and stats' ' + git log --graph --pretty=short --stat -p >actual && + sanitize_output >actual.sanitized <actual && + test_cmp expect actual.sanitized +' + test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index 2ae9faa8b3..4afd77815f 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -71,4 +71,32 @@ test_expect_success 'alias loop' ' test_must_fail git log --pretty=test-foo ' +test_expect_success 'NUL separation' ' + printf "add bar\0initial" >expected && + git log -z --pretty="format:%s" >actual && + test_cmp expected actual +' + +test_expect_success 'NUL termination' ' + printf "add bar\0initial\0" >expected && + git log -z --pretty="tformat:%s" >actual && + test_cmp expected actual +' + +test_expect_success 'NUL separation with --stat' ' + stat0_part=$(git diff --stat HEAD^ HEAD) && + stat1_part=$(git diff --stat --root HEAD^) && + printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n" >expected && + git log -z --stat --pretty="format:%s" >actual && + test_cmp expected actual +' + +test_expect_failure 'NUL termination with --stat' ' + stat0_part=$(git diff --stat HEAD^ HEAD) && + stat1_part=$(git diff --stat --root HEAD^) && + printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n\0" >expected && + git log -z --stat --pretty="tformat:%s" >actual && + test_cmp expected actual +' + test_done diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh new file mode 100755 index 0000000000..eed727341d --- /dev/null +++ b/t/t4209-log-pickaxe.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +test_description='log --grep/--author/--regexp-ignore-case/-S/-G' +. ./test-lib.sh + +test_expect_success setup ' + >file && + git add file && + test_tick && + git commit -m initial && + + echo Picked >file && + test_tick && + git commit -a --author="Another Person <another@example.com>" -m second +' + +test_expect_success 'log --grep' ' + git log --grep=initial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --grep --regexp-ignore-case' ' + git log --regexp-ignore-case --grep=InItial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --grep -i' ' + git log -i --grep=InItial --format=%H >actual && + git rev-parse --verify HEAD^ >expect && + test_cmp expect actual +' + +test_expect_success 'log --author --regexp-ignore-case' ' + git log --regexp-ignore-case --author=person --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log --author -i' ' + git log -i --author=person --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G (nomatch)' ' + git log -Gpicked --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G (match)' ' + git log -GPicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G --regexp-ignore-case (nomatch)' ' + git log --regexp-ignore-case -Gpickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G -i (nomatch)' ' + git log -i -Gpickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -G --regexp-ignore-case (match)' ' + git log --regexp-ignore-case -Gpicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -G -i (match)' ' + git log -i -Gpicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S (nomatch)' ' + git log -Spicked --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -S (match)' ' + git log -SPicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S --regexp-ignore-case (match)' ' + git log --regexp-ignore-case -Spicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S -i (match)' ' + git log -i -Spicked --format=%H >actual && + git rev-parse --verify HEAD >expect && + test_cmp expect actual +' + +test_expect_success 'log -S --regexp-ignore-case (nomatch)' ' + git log --regexp-ignore-case -Spickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log -S -i (nomatch)' ' + git log -i -Spickle --format=%H >actual && + >expect && + test_cmp expect actual +' + +test_done diff --git a/t/t4253-am-keep-cr-dos.sh b/t/t4253-am-keep-cr-dos.sh index 735e55d77c..553fe3e88e 100755 --- a/t/t4253-am-keep-cr-dos.sh +++ b/t/t4253-am-keep-cr-dos.sh @@ -62,7 +62,7 @@ test_expect_success 'am with dos files config am.keepcr' ' git diff --exit-code master ' -test_expect_success 'am with dos files config am.keepcr overriden by --no-keep-cr' ' +test_expect_success 'am with dos files config am.keepcr overridden by --no-keep-cr' ' git config am.keepcr 1 && git checkout -b dosfiles-conf-keepcr-override initial && git format-patch -k initial..master && @@ -83,7 +83,7 @@ test_expect_success 'am with dos files with --keep-cr continue' ' git diff --exit-code master ' -test_expect_success 'am with unix files config am.keepcr overriden by --no-keep-cr' ' +test_expect_success 'am with unix files config am.keepcr overridden by --no-keep-cr' ' git config am.keepcr 1 && git checkout -b unixfiles-conf-keepcr-override initial && cp -f file1 file && 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..ecf00edab2 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -26,9 +26,31 @@ commit id embedding: . ./test-lib.sh UNZIP=${UNZIP:-unzip} +GZIP=${GZIP:-gzip} +GUNZIP=${GUNZIP:-gzip -d} SUBSTFORMAT=%H%n +check_zip() { + zipfile=$1.zip + listfile=$1.lst + dir=$1 + dir_with_prefix=$dir/$2 + + test_expect_success UNZIP " extract ZIP archive" " + (mkdir $dir && cd $dir && $UNZIP ../$zipfile) + " + + test_expect_success UNZIP " validate filenames" " + (cd ${dir_with_prefix}a && find .) | sort >$listfile && + test_cmp a.lst $listfile + " + + test_expect_success UNZIP " validate file contents" " + diff -r a ${dir_with_prefix}a + " +} + test_expect_success \ 'populate workdir' \ 'mkdir a b c && @@ -82,6 +104,12 @@ test_expect_success \ 'git archive vs. git tar-tree' \ 'test_cmp b.tar b2.tar' +test_expect_success 'git archive on large files' ' + test_config core.bigfilethreshold 1 && + git archive HEAD >b3.tar && + test_cmp b.tar b3.tar +' + test_expect_success \ 'git archive in a bare repo' \ '(cd bare.git && git archive HEAD) >b3.tar' @@ -94,7 +122,7 @@ test_expect_success 'git archive with --output' \ 'git archive --output=b4.tar HEAD && test_cmp b.tar b4.tar' -test_expect_success NOT_MINGW 'git archive --remote' \ +test_expect_success 'git archive --remote' \ 'git archive --remote=. HEAD >b5.tar && test_cmp b.tar b5.tar' @@ -173,10 +201,19 @@ test_expect_success \ test_cmp a/substfile2 g/prefix/a/substfile2 ' +$UNZIP -v >/dev/null 2>&1 +if [ $? -eq 127 ]; then + say "Skipping ZIP tests, because unzip was not found" +else + test_set_prereq UNZIP +fi + test_expect_success \ 'git archive --format=zip' \ 'git archive --format=zip HEAD >d.zip' +check_zip d + test_expect_success \ 'git archive --format=zip in a bare repo' \ '(cd bare.git && git archive --format=zip HEAD) >d1.zip' @@ -199,47 +236,38 @@ test_expect_success 'git archive with --output, override inferred format' ' test_cmp b.tar d4.zip ' -$UNZIP -v >/dev/null 2>&1 -if [ $? -eq 127 ]; then - say "Skipping ZIP tests, because unzip was not found" -else - test_set_prereq UNZIP -fi - -test_expect_success UNZIP \ - 'extract ZIP archive' \ - '(mkdir d && cd d && $UNZIP ../d.zip)' - -test_expect_success UNZIP \ - 'validate filenames' \ - '(cd d/a && find .) | sort >d.lst && - test_cmp a.lst d.lst' - -test_expect_success UNZIP \ - 'validate file contents' \ - 'diff -r a d/a' - test_expect_success \ 'git archive --format=zip with prefix' \ 'git archive --format=zip --prefix=prefix/ HEAD >e.zip' -test_expect_success UNZIP \ - 'extract ZIP archive with prefix' \ - '(mkdir e && cd e && $UNZIP ../e.zip)' +check_zip e prefix/ -test_expect_success UNZIP \ - 'validate filenames with prefix' \ - '(cd e/prefix/a && find .) | sort >e.lst && - test_cmp a.lst e.lst' +test_expect_success 'git archive -0 --format=zip on large files' ' + test_config core.bigfilethreshold 1 && + git archive -0 --format=zip HEAD >large.zip +' -test_expect_success UNZIP \ - 'validate file contents with prefix' \ - 'diff -r a e/prefix/a' +check_zip large + +test_expect_success 'git archive --format=zip on large files' ' + test_config core.bigfilethreshold 1 && + git archive --format=zip HEAD >large-compressed.zip +' + +check_zip large-compressed test_expect_success \ 'git archive --list outside of a git repo' \ 'GIT_DIR=some/non-existing/directory git archive --list' +test_expect_success 'clients cannot access unreachable commits' ' + test_commit unreachable && + sha1=`git rev-parse HEAD` && + git reset --hard HEAD^ && + git archive $sha1 >remote.tar && + test_must_fail git archive --remote=. $sha1 >remote.tar +' + test_expect_success 'git-archive --prefix=olde-' ' git archive --prefix=olde- >h.tar HEAD && ( @@ -252,4 +280,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 '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 '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 '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 '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/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index ebc36c1758..81904d9ec8 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -65,7 +65,7 @@ test_expect_success 'respect NULs' ' git mailsplit -d3 -o. "$TEST_DIRECTORY"/t5100/nul-plain && test_cmp "$TEST_DIRECTORY"/t5100/nul-plain 001 && (cat 001 | git mailinfo msg patch) && - test 4 = $(wc -l < patch) + test_line_count = 4 patch ' diff --git a/t/t5100/patch0001 b/t/t5100/patch0001 index 8ce155167d..02c97746d6 100644 --- a/t/t5100/patch0001 +++ b/t/t5100/patch0001 @@ -1,5 +1,5 @@ --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo diff --git a/t/t5100/patch0002 b/t/t5100/patch0002 index 8ce155167d..02c97746d6 100644 --- a/t/t5100/patch0002 +++ b/t/t5100/patch0002 @@ -1,5 +1,5 @@ --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo diff --git a/t/t5100/patch0003 b/t/t5100/patch0003 index 8ce155167d..02c97746d6 100644 --- a/t/t5100/patch0003 +++ b/t/t5100/patch0003 @@ -1,5 +1,5 @@ --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo diff --git a/t/t5100/patch0005 b/t/t5100/patch0005 index 7d24b24af8..ab7a38373b 100644 --- a/t/t5100/patch0005 +++ b/t/t5100/patch0005 @@ -1,7 +1,7 @@ --- - Documentation/git-cvsimport-script.txt | 9 ++++++++- - git-cvsimport-script | 4 ++-- + Documentation/git-cvsimport-script.txt | 9 ++++++++- + git-cvsimport-script | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) 50452f9c0c2df1f04d83a26266ba704b13861632 diff --git a/t/t5100/patch0006 b/t/t5100/patch0006 index 8ce155167d..02c97746d6 100644 --- a/t/t5100/patch0006 +++ b/t/t5100/patch0006 @@ -1,5 +1,5 @@ --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo diff --git a/t/t5100/patch0010 b/t/t5100/patch0010 index f055481d56..436821c97a 100644 --- a/t/t5100/patch0010 +++ b/t/t5100/patch0010 @@ -1,5 +1,5 @@ --- - builtin-mailinfo.c | 2 +- + builtin-mailinfo.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c diff --git a/t/t5100/patch0011 b/t/t5100/patch0011 index 8841d3c139..0988713761 100644 --- a/t/t5100/patch0011 +++ b/t/t5100/patch0011 @@ -1,5 +1,5 @@ --- - builtin-mailinfo.c | 4 ++-- + builtin-mailinfo.c | 4 ++-- diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 3e5fe51..aabfe5c 100644 diff --git a/t/t5100/patch0014 b/t/t5100/patch0014 index 124efd234f..3f3825f9f2 100644 --- a/t/t5100/patch0014 +++ b/t/t5100/patch0014 @@ -1,5 +1,5 @@ --- - builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c diff --git a/t/t5100/patch0014--scissors b/t/t5100/patch0014--scissors index 124efd234f..3f3825f9f2 100644 --- a/t/t5100/patch0014--scissors +++ b/t/t5100/patch0014--scissors @@ -1,5 +1,5 @@ --- - builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox index de1031241d..34a09a0fc1 100644 --- a/t/t5100/sample.mbox +++ b/t/t5100/sample.mbox @@ -12,7 +12,7 @@ Subject: [PATCH] a commit. Here is a patch from A U Thor. --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo @@ -52,7 +52,7 @@ two truly blank and another full of spaces in between. Hope this helps. --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo @@ -83,7 +83,7 @@ Message-Id: <nitpicker.12121212@example.net> Hopefully this would fix the problem stated there. --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo @@ -249,8 +249,8 @@ actual flags. Signed-off-by: David K=E5gedal <davidk@lysator.liu.se> --- - Documentation/git-cvsimport-script.txt | 9 ++++++++- - git-cvsimport-script | 4 ++-- + Documentation/git-cvsimport-script.txt | 9 ++++++++- + git-cvsimport-script | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) 50452f9c0c2df1f04d83a26266ba704b13861632 @@ -379,7 +379,7 @@ Subject: [PATCH] a commit. Here is a patch from A U Thor. --- - foo | 2 +- + foo | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/foo b/foo @@ -449,7 +449,7 @@ memcmp("Subject: ", header[i], 7) will never match. Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- - builtin-mailinfo.c | 2 +- + builtin-mailinfo.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c @@ -482,7 +482,7 @@ Content-Transfer-Encoding: quoted-printable Here comes a commit log message, and its second line is here. --- - builtin-mailinfo.c | 4 ++-- + builtin-mailinfo.c | 4 ++-- diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 3e5fe51..aabfe5c 100644 @@ -587,7 +587,7 @@ everything before it in the message body. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- - builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index 9cc0a42ea9..432f98c357 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -67,9 +67,11 @@ test_expect_success 'setup: two scripts for reading pull requests' ' cat <<-\EOT >read-request.sed && #!/bin/sed -nf + # Note that a request could ask for "tag $tagname" / in the git repository at:$/!d n /^$/ n + s/ tag \([^ ]*\)$/ tag--\1/ s/^[ ]*\(.*\) \([^ ]*\)/please pull\ \1\ \2/p @@ -86,13 +88,14 @@ test_expect_success 'setup: two scripts for reading pull requests' ' s/$downstream_url_for_sed/URL/g s/for-upstream/BRANCH/g s/mnemonic.txt/FILENAME/g + s/^version [0-9]/VERSION/ /^ FILENAME | *[0-9]* [-+]*\$/ b diffstat /^AUTHOR ([0-9]*):\$/ b shortlog p b : diffstat n - / [0-9]* files changed/ { + / [0-9]* files* changed/ { a\\ DIFFSTAT b @@ -176,10 +179,7 @@ test_expect_success 'request names an appropriate branch' ' read repository && read branch } <digest && - { - test "$branch" = master || - test "$branch" = for-upstream - } + test "$branch" = tags/full ' @@ -193,8 +193,17 @@ test_expect_success 'pull request format' ' SUBJECT (DATE) are available in the git repository at: + URL BRANCH + for you to fetch changes up to OBJECT_NAME: + + SUBJECT (DATE) + + ---------------------------------------------------------------- + VERSION + + ---------------------------------------------------------------- SHORTLOG DIFFSTAT @@ -207,7 +216,7 @@ test_expect_success 'pull request format' ' git request-pull initial "$downstream_url" >../request ) && <request sed -nf fuzz.sed >request.fuzzy && - test_cmp expect request.fuzzy + test_i18ncmp expect request.fuzzy ' diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 602806d09c..4fd69a19eb 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -13,9 +13,9 @@ TRASH=`pwd` test_expect_success \ 'setup' \ 'rm -f .git/index* && - perl -e "print \"a\" x 4096;" > a && - perl -e "print \"b\" x 4096;" > b && - perl -e "print \"c\" x 4096;" > c && + "$PERL_PATH" -e "print \"a\" x 4096;" > a && + "$PERL_PATH" -e "print \"b\" x 4096;" > b && + "$PERL_PATH" -e "print \"c\" x 4096;" > c && test-genrandom "seed a" 2097152 > a_big && test-genrandom "seed b" 2097152 > b_big && git update-index --add a a_big b b_big c && @@ -38,6 +38,10 @@ test_expect_success \ 'pack without delta' \ 'packname_1=$(git pack-objects --window=0 test-1 <obj-list)' +test_expect_success \ + 'pack-objects with bogus arguments' \ + 'test_must_fail git pack-objects --window=0 test-1 blah blah <obj-list' + rm -fr .git2 mkdir .git2 @@ -125,7 +129,7 @@ test_expect_success \ cd "$TRASH" test_expect_success 'compare delta flavors' ' - perl -e '\'' + "$PERL_PATH" -e '\'' defined($_ = -s $_) or die for @ARGV; exit 1 if $ARGV[0] <= $ARGV[1]; '\'' test-2-$packname_2.pack test-3-$packname_3.pack diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index b34ea93a80..fe82025d4a 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -65,6 +65,18 @@ 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 \ + 'pack-objects --index-version=2, is not accepted' \ + 'test_must_fail git pack-objects --index-version=2, test-3 <obj-list' + 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 +105,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 +230,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/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 5f6cd4f333..5b1250f0d2 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -98,7 +98,7 @@ test_expect_success \ 'create_new_pack && git prune-packed && chmod +w ${pack}.pack && - perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && + "$PERL_PATH" -i.bak -pe "s/ base /abcdef/" ${pack}.pack && test_must_fail git cat-file blob $blob_1 > /dev/null && test_must_fail git cat-file blob $blob_2 > /dev/null && test_must_fail git cat-file blob $blob_3 > /dev/null' @@ -155,7 +155,7 @@ test_expect_success \ 'create_new_pack && git prune-packed && chmod +w ${pack}.pack && - perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && + "$PERL_PATH" -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && git cat-file blob $blob_1 > /dev/null && test_must_fail git cat-file blob $blob_2 > /dev/null && test_must_fail git cat-file blob $blob_3 > /dev/null' 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/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index bafcca765e..e80a2af348 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -97,7 +97,7 @@ test_expect_success 'setup' ' git symbolic-ref HEAD refs/heads/B ' -pull_to_client 1st "B A" $((11*3)) +pull_to_client 1st "refs/heads/B refs/heads/A" $((11*3)) test_expect_success 'post 1st pull setup' ' add A11 $A10 && @@ -110,12 +110,28 @@ test_expect_success 'post 1st pull setup' ' done ' -pull_to_client 2nd "B" $((64*3)) +pull_to_client 2nd "refs/heads/B" $((64*3)) -pull_to_client 3rd "A" $((1*3)) +pull_to_client 3rd "refs/heads/A" $((1*3)) + +test_expect_success 'single branch clone' ' + git clone --single-branch "file://$(pwd)/." singlebranch +' + +test_expect_success 'single branch object count' ' + GIT_DIR=singlebranch/.git git count-objects -v | + grep "^in-pack:" > count.singlebranch && + echo "in-pack: 198" >expected && + test_cmp expected count.singlebranch +' + +test_expect_success 'single given branch clone' ' + git clone --single-branch --branch A "file://$(pwd)/." branch-a && + test_must_fail git --git-dir=branch-a/.git rev-parse origin/B +' test_expect_success 'clone shallow' ' - git clone --depth 2 "file://$(pwd)/." shallow + git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow ' test_expect_success 'clone shallow object count' ' @@ -248,4 +264,137 @@ test_expect_success 'clone shallow object count' ' grep "^count: 52" count.shallow ' +test_expect_success 'clone shallow without --no-single-branch' ' + git clone --depth 1 "file://$(pwd)/." shallow2 +' + +test_expect_success 'clone shallow object count' ' + ( + cd shallow2 && + git count-objects -v + ) > count.shallow2 && + grep "^in-pack: 6" count.shallow2 +' + +test_expect_success 'clone shallow with --branch' ' + git clone --depth 1 --branch A "file://$(pwd)/." shallow3 +' + +test_expect_success 'clone shallow object count' ' + echo "in-pack: 6" > count3.expected && + GIT_DIR=shallow3/.git git count-objects -v | + grep "^in-pack" > count3.actual && + test_cmp count3.expected count3.actual +' + +test_expect_success 'clone shallow with detached HEAD' ' + git checkout HEAD^ && + git clone --depth 1 "file://$(pwd)/." shallow5 && + git checkout - && + GIT_DIR=shallow5/.git git rev-parse HEAD >actual && + git rev-parse HEAD^ >expected && + test_cmp expected actual +' + +test_expect_success 'shallow clone pulling tags' ' + git tag -a -m A TAGA1 A && + git tag -a -m B TAGB1 B && + git tag TAGA2 A && + git tag TAGB2 B && + git clone --depth 1 "file://$(pwd)/." shallow6 && + + cat >taglist.expected <<\EOF && +TAGB1 +TAGB2 +EOF + GIT_DIR=shallow6/.git git tag -l >taglist.actual && + test_cmp taglist.expected taglist.actual && + + echo "in-pack: 7" > count6.expected && + GIT_DIR=shallow6/.git git count-objects -v | + grep "^in-pack" > count6.actual && + test_cmp count6.expected count6.actual +' + +test_expect_success 'shallow cloning single tag' ' + git clone --depth 1 --branch=TAGB1 "file://$(pwd)/." shallow7 && + cat >taglist.expected <<\EOF && +TAGB1 +TAGB2 +EOF + GIT_DIR=shallow7/.git git tag -l >taglist.actual && + test_cmp taglist.expected taglist.actual && + + echo "in-pack: 7" > count7.expected && + GIT_DIR=shallow7/.git git count-objects -v | + grep "^in-pack" > count7.actual && + test_cmp count7.expected count7.actual +' + +test_expect_success 'setup tests for the --stdin parameter' ' + for head in C D E F + do + add $head + done && + for head in A B C D E F + do + git tag $head $head + done && + cat >input <<-\EOF + refs/heads/C + refs/heads/A + refs/heads/D + refs/tags/C + refs/heads/B + refs/tags/A + refs/heads/E + refs/tags/B + refs/tags/E + refs/tags/D + EOF + sort <input >expect && + ( + echo refs/heads/E && + echo refs/tags/E && + cat input + ) >input.dup +' + +test_expect_success 'fetch refs from cmdline' ' + ( + cd client && + git fetch-pack --no-progress .. $(cat ../input) + ) >output && + cut -d " " -f 2 <output | sort >actual && + test_cmp expect actual +' + +test_expect_success 'fetch refs from stdin' ' + ( + cd client && + git fetch-pack --stdin --no-progress .. <../input + ) >output && + cut -d " " -f 2 <output | sort >actual && + test_cmp expect actual +' + +test_expect_success 'fetch mixed refs from cmdline and stdin' ' + ( + cd client && + tail -n +5 ../input | + git fetch-pack --stdin --no-progress .. $(head -n 4 ../input) + ) >output && + cut -d " " -f 2 <output | sort >actual && + test_cmp expect actual +' + +test_expect_success 'test duplicate refs from stdin' ' + ( + cd client && + test_must_fail git fetch-pack --stdin --no-progress .. <../input.dup + ) >output && + cut -d " " -f 2 <output | sort >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5501-fetch-push-alternates.sh b/t/t5501-fetch-push-alternates.sh index b5ced8483a..1bc57ac03f 100755 --- a/t/t5501-fetch-push-alternates.sh +++ b/t/t5501-fetch-push-alternates.sh @@ -28,7 +28,7 @@ test_expect_success setup ' done ) && ( - git clone --reference=original "file:///$(pwd)/original" one && + git clone --reference=original "file://$(pwd)/original" one && cd one && echo Z >count && git add count && diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh new file mode 100755 index 0000000000..35ec294d9a --- /dev/null +++ b/t/t5504-fetch-receive-strict.sh @@ -0,0 +1,118 @@ +#!/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 + ) +' + +cat >exp <<EOF +To dst +! refs/heads/master:refs/heads/test [remote rejected] (missing necessary objects) +EOF + +test_expect_success 'push without strict' ' + rm -rf dst && + git init dst && + ( + cd dst && + git config fetch.fsckobjects false && + git config transfer.fsckobjects false + ) && + test_must_fail git push --porcelain dst master:refs/heads/test >act && + test_cmp exp act +' + +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 + ) && + test_must_fail git push --porcelain dst master:refs/heads/test >act && + test_cmp exp act +' + +cat >exp <<EOF +To dst +! refs/heads/master:refs/heads/test [remote rejected] (n/a (unpacker error)) +EOF + +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 --porcelain dst master:refs/heads/test >act && + test_cmp exp act +' + +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 --porcelain dst master:refs/heads/test >act && + test_cmp exp act +' + +test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 0d0222ea2a..e8af615e6d 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -631,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/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..d7a19a1829 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -14,6 +14,14 @@ test_bundle_object_count () { test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l) } +convert_bundle_to_pack () { + while read x && test -n "$x" + do + :; + done + cat +} + test_expect_success setup ' echo >file original && git add file && @@ -70,12 +78,62 @@ test_expect_success "fetch test for-merge" ' master_in_two=`cd ../two && git rev-parse master` && one_in_two=`cd ../two && git rev-parse one` && { - echo "$master_in_two not-for-merge" echo "$one_in_two " + echo "$master_in_two not-for-merge" } >expected && 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" && @@ -104,6 +162,36 @@ test_expect_success 'fetch following tags' ' ' +test_expect_success 'fetch uses remote ref names to describe new refs' ' + cd "$D" && + git init descriptive && + ( + cd descriptive && + git config remote.o.url .. && + git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" && + git config --add remote.o.fetch "refs/others/*:refs/heads/*" && + git fetch o + ) && + git tag -a -m "Descriptive tag" descriptive-tag && + git branch descriptive-branch && + git checkout descriptive-branch && + echo "Nuts" >crazy && + git add crazy && + git commit -a -m "descriptive commit" && + git update-ref refs/others/crazy HEAD && + ( + cd descriptive && + git fetch o 2>actual && + grep " -> refs/crazyheads/descriptive-branch$" actual | + test_i18ngrep "new branch" && + grep " -> descriptive-tag$" actual | + test_i18ngrep "new tag" && + grep " -> crazy$" actual | + test_i18ngrep "new ref" + ) && + git checkout master +' + test_expect_success 'fetch must not resolve short tag name' ' cd "$D" && @@ -116,7 +204,7 @@ test_expect_success 'fetch must not resolve short tag name' ' ' -test_expect_success 'fetch must not resolve short remote name' ' +test_expect_success 'fetch can now resolve short remote name' ' cd "$D" && git update-ref refs/remotes/six/HEAD HEAD && @@ -125,8 +213,7 @@ test_expect_success 'fetch must not resolve short remote name' ' cd six && git init && - test_must_fail git fetch .. six:six - + git fetch .. six:six ' test_expect_success 'create bundle 1' ' @@ -157,13 +244,7 @@ test_expect_success 'unbundle 1' ' test_expect_success 'bundle 1 has only 3 files ' ' cd "$D" && - ( - while read x && test -n "$x" - do - :; - done - cat - ) <bundle1 >bundle.pack && + convert_bundle_to_pack <bundle1 >bundle.pack && git index-pack bundle.pack && test_bundle_object_count bundle.pack 3 ' @@ -180,13 +261,7 @@ test_expect_success 'bundle does not prerequisite objects' ' git add file2 && git commit -m add.file2 file2 && git bundle create bundle3 -1 HEAD && - ( - while read x && test -n "$x" - do - :; - done - cat - ) <bundle3 >bundle.pack && + convert_bundle_to_pack <bundle3 >bundle.pack && git index-pack bundle.pack && test_bundle_object_count bundle.pack 3 ' @@ -384,14 +459,31 @@ test_expect_success 'fetch --dry-run' ' ' test_expect_success "should be able to fetch with duplicate refspecs" ' - mkdir dups && - cd dups && - git init && - git config branch.master.remote three && - git config remote.three.url ../three/.git && - git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && - git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && - git fetch three + mkdir dups && + ( + cd dups && + git init && + git config branch.master.remote three && + git config remote.three.url ../three/.git && + git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git fetch three + ) +' + +test_expect_success 'all boundary commits are excluded' ' + test_commit base && + test_commit oneside && + git checkout HEAD^ && + test_commit otherside && + git checkout master && + test_tick && + git merge otherside && + ad=$(git log --no-walk --format=%ad HEAD) && + git bundle create twoside-boundary.bdl master --since="$ad" && + convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack && + pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) && + test_bundle_object_count .git/objects/pack/pack-${pack##pack }.pack 3 ' test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 5c546c99a5..6764d511ce 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -5,7 +5,6 @@ test_description='git ls-remote' . ./test-lib.sh test_expect_success setup ' - >file && git add file && test_tick && @@ -18,45 +17,33 @@ test_expect_success setup ' ) >expected.all && git remote add self "$(pwd)/.git" - ' test_expect_success 'ls-remote --tags .git' ' - git ls-remote --tags .git >actual && test_cmp expected.tag actual - ' test_expect_success 'ls-remote .git' ' - git ls-remote .git >actual && test_cmp expected.all actual - ' test_expect_success 'ls-remote --tags self' ' - git ls-remote --tags self >actual && test_cmp expected.tag actual - ' test_expect_success 'ls-remote self' ' - git ls-remote self >actual && test_cmp expected.all actual - ' test_expect_success 'dies when no remote specified and no default remotes found' ' - test_must_fail git ls-remote - ' test_expect_success 'use "origin" when no remote specified' ' - URL="$(pwd)/.git" && echo "From $URL" >exp_err && @@ -65,18 +52,14 @@ test_expect_success 'use "origin" when no remote specified' ' test_cmp exp_err actual_err && test_cmp expected.all actual - ' test_expect_success 'suppress "From <url>" with -q' ' - git ls-remote -q 2>actual_err && test_must_fail test_cmp exp_err actual_err - ' test_expect_success 'use branch.<name>.remote if possible' ' - # # Test that we are indeed using branch.<name>.remote, not "origin", even # though the "origin" remote has been set. @@ -99,14 +82,13 @@ test_expect_success 'use branch.<name>.remote if possible' ' git ls-remote 2>actual_err >actual && test_cmp exp_err actual_err && test_cmp exp actual - ' -cat >exp <<EOF -fatal: 'refs*master' does not appear to be a git repository -fatal: The remote end hung up unexpectedly -EOF test_expect_success 'confuses pattern as remote when no remote specified' ' + cat >exp <<-\EOF && + fatal: '\''refs*master'\'' does not appear to be a git repository + fatal: The remote end hung up unexpectedly + EOF # # Do not expect "git ls-remote <pattern>" to work; ls-remote, correctly, # confuses <pattern> for <remote>. Although ugly, this behaviour is akin @@ -120,7 +102,6 @@ test_expect_success 'confuses pattern as remote when no remote specified' ' # role as a pattern. test_must_fail git ls-remote refs*master >actual 2>&1 && test_cmp exp actual - ' test_expect_success 'die with non-2 for wrong repository even with --exit-code' ' diff --git a/t/t5515/fetch.br-branches-default b/t/t5515/fetch.br-branches-default index 2e0414f6c3..a1bc3d53a6 100644 --- a/t/t5515/fetch.br-branches-default +++ b/t/t5515/fetch.br-branches-default @@ -1,8 +1,8 @@ # br-branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge index ca2cc1d1b4..12ab08e8ac 100644 --- a/t/t5515/fetch.br-branches-default-merge +++ b/t/t5515/fetch.br-branches-default-merge @@ -1,9 +1,9 @@ # br-branches-default-merge -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default index 7d947cd80f..54427522dd 100644 --- a/t/t5515/fetch.br-branches-default-merge_branches-default +++ b/t/t5515/fetch.br-branches-default-merge_branches-default @@ -1,9 +1,9 @@ # br-branches-default-merge branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus index ec39c54b7e..498a761aae 100644 --- a/t/t5515/fetch.br-branches-default-octopus +++ b/t/t5515/fetch.br-branches-default-octopus @@ -1,10 +1,10 @@ # br-branches-default-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default index 6bf42e24b6..0857f134e1 100644 --- a/t/t5515/fetch.br-branches-default-octopus_branches-default +++ b/t/t5515/fetch.br-branches-default-octopus_branches-default @@ -1,10 +1,10 @@ # br-branches-default-octopus branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-default_branches-default b/t/t5515/fetch.br-branches-default_branches-default index 4a2bf3c95c..8cbd718936 100644 --- a/t/t5515/fetch.br-branches-default_branches-default +++ b/t/t5515/fetch.br-branches-default_branches-default @@ -1,8 +1,8 @@ # br-branches-default branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one b/t/t5515/fetch.br-branches-one index 12ac8d20fb..c98f670526 100644 --- a/t/t5515/fetch.br-branches-one +++ b/t/t5515/fetch.br-branches-one @@ -1,8 +1,8 @@ # br-branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge index b4b3b35ce0..54a77420d5 100644 --- a/t/t5515/fetch.br-branches-one-merge +++ b/t/t5515/fetch.br-branches-one-merge @@ -1,9 +1,9 @@ # br-branches-one-merge -8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one index 2ecef384eb..b4d1bb0b0b 100644 --- a/t/t5515/fetch.br-branches-one-merge_branches-one +++ b/t/t5515/fetch.br-branches-one-merge_branches-one @@ -1,9 +1,9 @@ # br-branches-one-merge branches-one -8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus b/t/t5515/fetch.br-branches-one-octopus index 96e3029416..97c4b544b8 100644 --- a/t/t5515/fetch.br-branches-one-octopus +++ b/t/t5515/fetch.br-branches-one-octopus @@ -1,9 +1,9 @@ # br-branches-one-octopus 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus_branches-one b/t/t5515/fetch.br-branches-one-octopus_branches-one index 55e0bad621..df705f74c7 100644 --- a/t/t5515/fetch.br-branches-one-octopus_branches-one +++ b/t/t5515/fetch.br-branches-one-octopus_branches-one @@ -1,9 +1,9 @@ # br-branches-one-octopus branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-branches-one_branches-one b/t/t5515/fetch.br-branches-one_branches-one index 281fa09d48..96890e5bd9 100644 --- a/t/t5515/fetch.br-branches-one_branches-one +++ b/t/t5515/fetch.br-branches-one_branches-one @@ -1,8 +1,8 @@ # br-branches-one branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit b/t/t5515/fetch.br-config-explicit index e2fa9c8654..68fc927263 100644 --- a/t/t5515/fetch.br-config-explicit +++ b/t/t5515/fetch.br-config-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit-merge b/t/t5515/fetch.br-config-explicit-merge index ec1a7231aa..5ce764a06e 100644 --- a/t/t5515/fetch.br-config-explicit-merge +++ b/t/t5515/fetch.br-config-explicit-merge @@ -1,11 +1,11 @@ # br-config-explicit-merge +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit-merge_config-explicit b/t/t5515/fetch.br-config-explicit-merge_config-explicit index 54f689151f..b1152b76dc 100644 --- a/t/t5515/fetch.br-config-explicit-merge_config-explicit +++ b/t/t5515/fetch.br-config-explicit-merge_config-explicit @@ -1,11 +1,11 @@ # br-config-explicit-merge config-explicit +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit-octopus b/t/t5515/fetch.br-config-explicit-octopus index 7011dfc181..110577bb67 100644 --- a/t/t5515/fetch.br-config-explicit-octopus +++ b/t/t5515/fetch.br-config-explicit-octopus @@ -1,11 +1,11 @@ # br-config-explicit-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit-octopus_config-explicit b/t/t5515/fetch.br-config-explicit-octopus_config-explicit index bdad51f871..a29dd8baba 100644 --- a/t/t5515/fetch.br-config-explicit-octopus_config-explicit +++ b/t/t5515/fetch.br-config-explicit-octopus_config-explicit @@ -1,11 +1,11 @@ # br-config-explicit-octopus config-explicit -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-explicit_config-explicit b/t/t5515/fetch.br-config-explicit_config-explicit index 1b237dde6e..b19b0162e1 100644 --- a/t/t5515/fetch.br-config-explicit_config-explicit +++ b/t/t5515/fetch.br-config-explicit_config-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob b/t/t5515/fetch.br-config-glob index e75ec2f72b..946d70ca07 100644 --- a/t/t5515/fetch.br-config-glob +++ b/t/t5515/fetch.br-config-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob-merge b/t/t5515/fetch.br-config-glob-merge index ce8f739a0d..89f2596cb9 100644 --- a/t/t5515/fetch.br-config-glob-merge +++ b/t/t5515/fetch.br-config-glob-merge @@ -1,11 +1,11 @@ # br-config-glob-merge +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob-merge_config-glob b/t/t5515/fetch.br-config-glob-merge_config-glob index 5817bed8f8..2ba4832160 100644 --- a/t/t5515/fetch.br-config-glob-merge_config-glob +++ b/t/t5515/fetch.br-config-glob-merge_config-glob @@ -1,11 +1,11 @@ # br-config-glob-merge config-glob +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus b/t/t5515/fetch.br-config-glob-octopus index 938e532db2..64994df7e2 100644 --- a/t/t5515/fetch.br-config-glob-octopus +++ b/t/t5515/fetch.br-config-glob-octopus @@ -1,11 +1,11 @@ # br-config-glob-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus_config-glob b/t/t5515/fetch.br-config-glob-octopus_config-glob index c9225bf6ff..681a725adc 100644 --- a/t/t5515/fetch.br-config-glob-octopus_config-glob +++ b/t/t5515/fetch.br-config-glob-octopus_config-glob @@ -1,11 +1,11 @@ # br-config-glob-octopus config-glob -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-config-glob_config-glob b/t/t5515/fetch.br-config-glob_config-glob index a6c20f92ce..19daf0cb77 100644 --- a/t/t5515/fetch.br-config-glob_config-glob +++ b/t/t5515/fetch.br-config-glob_config-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit b/t/t5515/fetch.br-remote-explicit index 83534d2ec8..ab44bc5519 100644 --- a/t/t5515/fetch.br-remote-explicit +++ b/t/t5515/fetch.br-remote-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit-merge b/t/t5515/fetch.br-remote-explicit-merge index a9064dd65a..d018b3515f 100644 --- a/t/t5515/fetch.br-remote-explicit-merge +++ b/t/t5515/fetch.br-remote-explicit-merge @@ -1,11 +1,11 @@ # br-remote-explicit-merge +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit index 732a37e4d3..0d3d780dd0 100644 --- a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit +++ b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit @@ -1,11 +1,11 @@ # br-remote-explicit-merge remote-explicit +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit-octopus b/t/t5515/fetch.br-remote-explicit-octopus index ecf020d929..6f843044ed 100644 --- a/t/t5515/fetch.br-remote-explicit-octopus +++ b/t/t5515/fetch.br-remote-explicit-octopus @@ -1,11 +1,11 @@ # br-remote-explicit-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit index af77531011..3546a83713 100644 --- a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit +++ b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit @@ -1,11 +1,11 @@ # br-remote-explicit-octopus remote-explicit -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-explicit_remote-explicit b/t/t5515/fetch.br-remote-explicit_remote-explicit index 51fae567c8..01e014e6a0 100644 --- a/t/t5515/fetch.br-remote-explicit_remote-explicit +++ b/t/t5515/fetch.br-remote-explicit_remote-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob b/t/t5515/fetch.br-remote-glob index 94e6ad31e3..09bfcee00f 100644 --- a/t/t5515/fetch.br-remote-glob +++ b/t/t5515/fetch.br-remote-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob-merge b/t/t5515/fetch.br-remote-glob-merge index 09362e25af..7e1a433a64 100644 --- a/t/t5515/fetch.br-remote-glob-merge +++ b/t/t5515/fetch.br-remote-glob-merge @@ -1,11 +1,11 @@ # br-remote-glob-merge +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob-merge_remote-glob b/t/t5515/fetch.br-remote-glob-merge_remote-glob index e2eabec62e..53571bb4ec 100644 --- a/t/t5515/fetch.br-remote-glob-merge_remote-glob +++ b/t/t5515/fetch.br-remote-glob-merge_remote-glob @@ -1,11 +1,11 @@ # br-remote-glob-merge remote-glob +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus b/t/t5515/fetch.br-remote-glob-octopus index b08e046195..c7c8b6d7f4 100644 --- a/t/t5515/fetch.br-remote-glob-octopus +++ b/t/t5515/fetch.br-remote-glob-octopus @@ -1,11 +1,11 @@ # br-remote-glob-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus_remote-glob b/t/t5515/fetch.br-remote-glob-octopus_remote-glob index d4d547c847..36076fba0c 100644 --- a/t/t5515/fetch.br-remote-glob-octopus_remote-glob +++ b/t/t5515/fetch.br-remote-glob-octopus_remote-glob @@ -1,11 +1,11 @@ # br-remote-glob-octopus remote-glob -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-remote-glob_remote-glob b/t/t5515/fetch.br-remote-glob_remote-glob index 646dbc8770..20ba5cb172 100644 --- a/t/t5515/fetch.br-remote-glob_remote-glob +++ b/t/t5515/fetch.br-remote-glob_remote-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig b/t/t5515/fetch.br-unconfig index 65ce6d99e2..887ccfc41f 100644 --- a/t/t5515/fetch.br-unconfig +++ b/t/t5515/fetch.br-unconfig @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git index 8258c80868..1669cc4af0 100644 --- a/t/t5515/fetch.br-unconfig_--tags_.._.git +++ b/t/t5515/fetch.br-unconfig_--tags_.._.git @@ -1,7 +1,7 @@ # br-unconfig --tags ../.git -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file index f02bab2fb4..74115361ba 100644 --- a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file +++ b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file @@ -2,7 +2,7 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 tag 'tag-one' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file index 85de41109e..7726983818 100644 --- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file +++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file @@ -1,7 +1,7 @@ # br-unconfig ../.git tag tag-one-tree tag tag-three-file 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three index 0da2337f1b..7b3750ce5c 100644 --- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three +++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three @@ -1,7 +1,7 @@ # br-unconfig ../.git tag tag-one tag tag-three 8e32a6d901327a23ef831511badce7bf3bf46689 tag 'tag-one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b tag 'tag-three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 tag 'tag-three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_branches-default b/t/t5515/fetch.br-unconfig_branches-default index fc7041eefc..da30e3c62c 100644 --- a/t/t5515/fetch.br-unconfig_branches-default +++ b/t/t5515/fetch.br-unconfig_branches-default @@ -1,8 +1,8 @@ # br-unconfig branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_branches-one b/t/t5515/fetch.br-unconfig_branches-one index e94cde745b..e4614314c5 100644 --- a/t/t5515/fetch.br-unconfig_branches-one +++ b/t/t5515/fetch.br-unconfig_branches-one @@ -1,8 +1,8 @@ # br-unconfig branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_config-explicit b/t/t5515/fetch.br-unconfig_config-explicit index 01a283e70d..ed323c9871 100644 --- a/t/t5515/fetch.br-unconfig_config-explicit +++ b/t/t5515/fetch.br-unconfig_config-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_config-glob b/t/t5515/fetch.br-unconfig_config-glob index 3a556c5e96..2372ed03c5 100644 --- a/t/t5515/fetch.br-unconfig_config-glob +++ b/t/t5515/fetch.br-unconfig_config-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_remote-explicit b/t/t5515/fetch.br-unconfig_remote-explicit index db216dfa56..6318dd11b4 100644 --- a/t/t5515/fetch.br-unconfig_remote-explicit +++ b/t/t5515/fetch.br-unconfig_remote-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.br-unconfig_remote-glob b/t/t5515/fetch.br-unconfig_remote-glob index aee65c204d..1d9afad7d8 100644 --- a/t/t5515/fetch.br-unconfig_remote-glob +++ b/t/t5515/fetch.br-unconfig_remote-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master b/t/t5515/fetch.master index 950fd078db..9b29d67200 100644 --- a/t/t5515/fetch.master +++ b/t/t5515/fetch.master @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git index 0e59950c7b..8a7493537b 100644 --- a/t/t5515/fetch.master_--tags_.._.git +++ b/t/t5515/fetch.master_--tags_.._.git @@ -1,7 +1,7 @@ # master --tags ../.git -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file index 82868524ca..0672d1292f 100644 --- a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file +++ b/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file @@ -2,7 +2,7 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 tag 'tag-one' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file index 2e133eff29..0fd737cf81 100644 --- a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file +++ b/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file @@ -1,7 +1,7 @@ # master ../.git tag tag-one-tree tag tag-three-file 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three index 92b18b40cc..e488986653 100644 --- a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three +++ b/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three @@ -1,7 +1,7 @@ # master ../.git tag tag-one tag tag-three 8e32a6d901327a23ef831511badce7bf3bf46689 tag 'tag-one' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b tag 'tag-three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 tag 'tag-three' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_branches-default b/t/t5515/fetch.master_branches-default index 603d6d2331..2eedd3bfa4 100644 --- a/t/t5515/fetch.master_branches-default +++ b/t/t5515/fetch.master_branches-default @@ -1,8 +1,8 @@ # master branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_branches-one b/t/t5515/fetch.master_branches-one index fe9bb0b798..901ce21d33 100644 --- a/t/t5515/fetch.master_branches-one +++ b/t/t5515/fetch.master_branches-one @@ -1,8 +1,8 @@ # master branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.master_config-explicit index 4be97c7575..251c826aa9 100644 --- a/t/t5515/fetch.master_config-explicit +++ b/t/t5515/fetch.master_config-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_config-glob b/t/t5515/fetch.master_config-glob index cb0726ff8d..27c158e332 100644 --- a/t/t5515/fetch.master_config-glob +++ b/t/t5515/fetch.master_config-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_remote-explicit b/t/t5515/fetch.master_remote-explicit index 44a1ca8429..b3cfe6b98b 100644 --- a/t/t5515/fetch.master_remote-explicit +++ b/t/t5515/fetch.master_remote-explicit @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5515/fetch.master_remote-glob b/t/t5515/fetch.master_remote-glob index 724e8db0a5..118befd1e4 100644 --- a/t/t5515/fetch.master_remote-glob +++ b/t/t5515/fetch.master_remote-glob @@ -3,9 +3,9 @@ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ -754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ -0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge tag 'tag-three' of ../ +c61a82b60967180544e3c19f819ddbd0c9f89899 not-for-merge tag 'tag-three' of ../ 0e3b14047d3ee365f4f2a1b673db059c3972589c not-for-merge tag 'tag-three-file' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge tag 'tag-two' of ../ +525b7fb068d59950d185a8779dc957c77eed73ba not-for-merge tag 'tag-two' of ../ diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 3abb2907ea..b5417cc951 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" @@ -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) && @@ -782,4 +979,20 @@ test_expect_success 'push --porcelain --dry-run rejected' ' test_cmp .git/foo .git/bar ' +test_expect_success 'push --prune' ' + mk_test heads/master heads/second heads/foo heads/bar && + git push --prune testrepo && + check_push_result $the_commit heads/master && + check_push_result $the_first_commit heads/second && + ! check_push_result $the_first_commit heads/foo heads/bar +' + +test_expect_success 'push --prune refspec' ' + mk_test tmp/master tmp/second tmp/foo tmp/bar && + git push --prune testrepo "refs/heads/*:refs/tmp/*" && + check_push_result $the_commit tmp/master && + check_push_result $the_first_commit tmp/second && + ! check_push_result $the_first_commit tmp/foo tmp/bar +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 0e5eb678ce..35304b41e9 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -94,16 +94,35 @@ test_expect_success '--rebase' ' test $(git rev-parse HEAD^) = $(git rev-parse copy) && test new = $(git show HEAD:file2) ' +test_expect_success 'pull.rebase' ' + git reset --hard before-rebase && + git config --bool pull.rebase true && + test_when_finished "git config --unset pull.rebase" && + git pull . copy && + test $(git rev-parse HEAD^) = $(git rev-parse copy) && + test new = $(git show HEAD:file2) +' test_expect_success 'branch.to-rebase.rebase' ' git reset --hard before-rebase && - git config branch.to-rebase.rebase 1 && + git config --bool branch.to-rebase.rebase true && + test_when_finished "git config --unset branch.to-rebase.rebase" && git pull . copy && - git config branch.to-rebase.rebase 0 && test $(git rev-parse HEAD^) = $(git rev-parse copy) && test new = $(git show HEAD:file2) ' +test_expect_success 'branch.to-rebase.rebase should override pull.rebase' ' + git reset --hard before-rebase && + git config --bool pull.rebase true && + test_when_finished "git config --unset pull.rebase" && + git config --bool branch.to-rebase.rebase false && + test_when_finished "git config --unset branch.to-rebase.rebase" && + git pull . copy && + test $(git rev-parse HEAD^) != $(git rev-parse copy) && + test new = $(git show HEAD:file2) +' + test_expect_success '--rebase with rebased upstream' ' git remote add -f me . && diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh index c229fe68f1..3683df13a6 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -101,11 +101,19 @@ test_expect_success TTY 'push -q suppresses progress' ' ! grep "Writing objects" err ' -test_expect_failure TTY 'push --no-progress suppresses progress' ' +test_expect_success TTY 'push --no-progress suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u --no-progress upstream master >out 2>err && + ! grep "Unpacking objects" err && ! grep "Writing objects" err ' +test_expect_success TTY 'quiet push' ' + ensure_fresh_upstream && + + test_terminal git push --quiet --no-progress upstream master 2>&1 | tee output && + test_cmp /dev/null output +' + test_done diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index a1fddd4d15..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" ' @@ -277,12 +277,12 @@ test_expect_success "Recursion picks up all submodules when necessary" ' ( cd submodule && ( - cd deepsubmodule && + cd subdir/deepsubmodule && git fetch && git checkout -q FETCH_HEAD ) && head1=$(git rev-parse --short HEAD^) && - git add deepsubmodule && + git add subdir/deepsubmodule && git commit -m "new deepsubmodule" head2=$(git rev-parse --short HEAD) && echo "From $pwd/submodule" > ../expect.err.sub && @@ -309,12 +309,12 @@ test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no ne ( cd submodule && ( - cd deepsubmodule && + cd subdir/deepsubmodule && git fetch && git checkout -q FETCH_HEAD ) && head1=$(git rev-parse --short HEAD^) && - git add deepsubmodule && + git add subdir/deepsubmodule && git commit -m "new deepsubmodule" head2=$(git rev-parse --short HEAD) && echo "From $pwd/submodule" > ../expect.err.sub && @@ -345,13 +345,13 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess git config fetch.recurseSubmodules false && ( cd submodule && - git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false + 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.deepsubmodule.fetchRecursive + git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive ) ) && test_i18ncmp expect.out actual.out && diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh new file mode 100755 index 0000000000..edea9f957e --- /dev/null +++ b/t/t5527-fetch-odd-refs.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +test_description='test fetching of oddly-named refs' +. ./test-lib.sh + +# afterwards we will have: +# HEAD - two +# refs/for/refs/heads/master - one +# refs/heads/master - three +test_expect_success 'setup repo with odd suffix ref' ' + echo content >file && + git add . && + git commit -m one && + git update-ref refs/for/refs/heads/master HEAD && + echo content >>file && + git commit -a -m two && + echo content >>file && + git commit -a -m three && + git checkout HEAD^ +' + +test_expect_success 'suffix ref is ignored during fetch' ' + git clone --bare file://"$PWD" suffix && + echo three >expect && + git --git-dir=suffix log -1 --format=%s refs/heads/master >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh new file mode 100755 index 0000000000..4736da8f36 --- /dev/null +++ b/t/t5528-push-default.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +test_description='check various push.default settings' +. ./test-lib.sh + +test_expect_success 'setup bare remotes' ' + git init --bare repo1 && + git remote add parent1 repo1 && + git init --bare repo2 && + git remote add parent2 repo2 && + test_commit one && + git push parent1 HEAD && + git push parent2 HEAD +' + +# $1 = local revision +# $2 = remote revision (tested to be equal to the local one) +check_pushed_commit () { + git log -1 --format='%h %s' "$1" >expect && + git --git-dir=repo1 log -1 --format='%h %s' "$2" >actual && + test_cmp expect actual +} + +# $1 = push.default value +# $2 = expected target branch for the push +test_push_success () { + git -c push.default="$1" push && + check_pushed_commit HEAD "$2" +} + +# $1 = push.default value +# check that push fails and does not modify any remote branch +test_push_failure () { + git --git-dir=repo1 log --no-walk --format='%h %s' --all >expect && + test_must_fail git -c push.default="$1" push && + git --git-dir=repo1 log --no-walk --format='%h %s' --all >actual && + test_cmp expect actual +} + +test_expect_success '"upstream" pushes to configured upstream' ' + git checkout master && + test_config branch.master.remote parent1 && + test_config branch.master.merge refs/heads/foo && + test_commit two && + test_push_success upstream foo +' + +test_expect_success '"upstream" does not push on unconfigured remote' ' + git checkout master && + test_unconfig branch.master.remote && + test_config push.default upstream && + test_commit three && + test_push_failure upstream +' + +test_expect_success '"upstream" does not push on unconfigured branch' ' + git checkout master && + test_config branch.master.remote parent1 && + test_unconfig branch.master.merge && + test_config push.default upstream + test_commit four && + test_push_failure upstream +' + +test_expect_success '"upstream" does not push when remotes do not match' ' + git checkout master && + test_config branch.master.remote parent1 && + test_config branch.master.merge refs/heads/foo && + test_config push.default upstream && + test_commit five && + test_must_fail git push parent2 +' + +test_expect_success 'push from/to new branch with upstream, matching and simple' ' + git checkout -b new-branch && + test_push_failure simple && + test_push_failure matching && + test_push_failure upstream +' + +test_expect_success 'push from/to new branch with current creates remote branch' ' + test_config branch.new-branch.remote repo1 && + git checkout new-branch && + test_push_success current new-branch +' + +test_expect_success 'push to existing branch, with no upstream configured' ' + test_config branch.master.remote repo1 && + git checkout master && + test_push_failure simple && + test_push_failure upstream +' + +test_expect_success 'push to existing branch, upstream configured with same name' ' + test_config branch.master.remote repo1 && + test_config branch.master.merge refs/heads/master && + git checkout master && + test_commit six && + test_push_success upstream master && + test_commit seven && + test_push_success simple master +' + +test_expect_success 'push to existing branch, upstream configured with different name' ' + test_config branch.master.remote repo1 && + test_config branch.master.merge refs/heads/other-name && + git checkout master && + test_commit eight && + test_push_success upstream other-name && + test_commit nine && + test_push_failure simple && + git --git-dir=repo1 log -1 --format="%h %s" "other-name" >expect-other-name && + test_push_success current master && + git --git-dir=repo1 log -1 --format="%h %s" "other-name" >actual-other-name && + test_cmp expect-other-name actual-other-name +' + +test_done diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index faa2e96337..1947c28c64 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -32,4 +32,185 @@ 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_expect_success 'push unpushed submodules when not needed' ' + ( + cd work && + ( + cd gar/bage && + git checkout master && + >junk5 && + git add junk5 && + git commit -m "Fifth junk" && + git push && + git rev-parse origin/master >../../../expected + ) && + git checkout master && + git add gar/bage && + git commit -m "Fifth commit for gar/bage" && + git push --recurse-submodules=on-demand ../pub.git master + ) && + ( + cd submodule.git && + git rev-parse master >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'push unpushed submodules when not needed 2' ' + ( + cd submodule.git && + git rev-parse master >../expected + ) && + ( + cd work && + ( + cd gar/bage && + >junk6 && + git add junk6 && + git commit -m "Sixth junk" + ) && + >junk2 && + git add junk2 && + git commit -m "Second junk for work" && + git push --recurse-submodules=on-demand ../pub.git master + ) && + ( + cd submodule.git && + git rev-parse master >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'push unpushed submodules recursively' ' + ( + cd work && + ( + cd gar/bage && + git checkout master && + > junk7 && + git add junk7 && + git commit -m "Seventh junk" && + git rev-parse master >../../../expected + ) && + git checkout master && + git add gar/bage && + git commit -m "Seventh commit for gar/bage" && + git push --recurse-submodules=on-demand ../pub.git master + ) && + ( + cd submodule.git && + git rev-parse master >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'push unpushable submodule recursively fails' ' + ( + cd work && + ( + cd gar/bage && + git rev-parse origin/master >../../../expected && + git checkout master~0 && + > junk8 && + git add junk8 && + git commit -m "Eighth junk" + ) && + git add gar/bage && + git commit -m "Eighth commit for gar/bage" && + test_must_fail git push --recurse-submodules=on-demand ../pub.git master + ) && + ( + cd submodule.git && + git rev-parse master >../actual + ) && + test_cmp expected actual +' + test_done diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh index 62f2460047..5531bd1af4 100755 --- a/t/t5532-fetch-proxy.sh +++ b/t/t5532-fetch-proxy.sh @@ -15,7 +15,7 @@ test_expect_success 'setup remote repo' ' cat >proxy <<'EOF' #!/bin/sh echo >&2 "proxying for $*" -cmd=`perl -e ' +cmd=`"$PERL_PATH" -e ' read(STDIN, $buf, 4); my $n = hex($buf) - 4; read(STDIN, $buf, $n); diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index a266ca5636..1eea647656 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -40,6 +40,22 @@ test_expect_success 'setup remote repository' ' mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" ' +test_expect_success 'create password-protected repository' ' + mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb" && + cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ + "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" +' + +test_expect_success 'setup askpass helper' ' + cat >askpass <<-\EOF && + #!/bin/sh + echo user@host + EOF + chmod +x askpass && + GIT_ASKPASS="$PWD/askpass" && + export GIT_ASKPASS +' + test_expect_success 'clone remote repository' ' cd "$ROOT_PATH" && git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone @@ -132,14 +148,36 @@ 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] " ' test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ "$ROOT_PATH"/test_repo_clone master +test_expect_success 'push to password-protected repository (user in URL)' ' + test_commit pw-user && + git push "$HTTPD_URL_USER/auth/dumb/test_repo.git" HEAD && + git rev-parse --verify HEAD >expect && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \ + rev-parse --verify HEAD >actual && + test_cmp expect actual +' + +test_expect_failure 'push to password-protected repository (no user in URL)' ' + test_commit pw-nouser && + git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD && + git rev-parse --verify HEAD >expect && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \ + rev-parse --verify HEAD >actual && + test_cmp expect actual +' + stop_httpd test_done diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh index a73c82635f..312e484090 100755 --- a/t/t5541-http-push.sh +++ b/t/t5541-http-push.sh @@ -14,6 +14,7 @@ fi ROOT_PATH="$PWD" LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'} . "$TEST_DIRECTORY"/lib-httpd.sh +. "$TEST_DIRECTORY"/lib-terminal.sh start_httpd test_expect_success 'setup remote repository' ' @@ -29,6 +30,7 @@ test_expect_success 'setup remote repository' ' git clone --bare test_repo test_repo.git && cd test_repo.git && git config http.receivepack true && + git config core.logallrefupdates true && ORIG_HEAD=$(git rev-parse --verify HEAD) && cd - && mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" @@ -95,6 +97,32 @@ test_expect_success 'create and delete remote branch' ' test_must_fail git show-ref --verify refs/remotes/origin/dev ' +cat >"$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" <<EOF +#!/bin/sh +exit 1 +EOF +chmod a+x "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" + +cat >exp <<EOF +remote: error: hook declined to update refs/heads/dev2 +To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git + ! [remote rejected] dev2 -> dev2 (hook declined) +error: failed to push some refs to 'http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git' +EOF + +test_expect_success 'rejected update prints status' ' + cd "$ROOT_PATH"/test_repo_clone && + git checkout -b dev2 && + : >path4 && + git add path4 && + test_tick && + git commit -m dev2 && + test_must_fail git push origin dev2 2>act && + sed -e "/^remote: /s/ *$//" <act >cmp && + test_cmp exp cmp +' +rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" + cat >exp <<EOF GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 @@ -106,6 +134,8 @@ GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 +GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 +POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 EOF test_expect_success 'used receive-pack service' ' sed -e " @@ -138,7 +168,7 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he ' 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" \ + test_i18ngrep "Updates were rejected because" \ output ' @@ -154,5 +184,87 @@ test_expect_success 'push (chunked)' ' test $HEAD = $(git rev-parse --verify HEAD)) ' +test_expect_success 'push --all can push to empty repo' ' + d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git && + git init --bare "$d" && + git --git-dir="$d" config http.receivepack true && + git push --all "$HTTPD_URL"/smart/empty-all.git +' + +test_expect_success 'push --mirror can push to empty repo' ' + d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git && + git init --bare "$d" && + git --git-dir="$d" config http.receivepack true && + git push --mirror "$HTTPD_URL"/smart/empty-mirror.git +' + +test_expect_success 'push --all to repo with alternates' ' + s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git && + d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git && + git clone --bare --shared "$s" "$d" && + git --git-dir="$d" config http.receivepack true && + git --git-dir="$d" repack -adl && + git push --all "$HTTPD_URL"/smart/alternates-all.git +' + +test_expect_success 'push --mirror to repo with alternates' ' + s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git && + d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git && + git clone --bare --shared "$s" "$d" && + git --git-dir="$d" config http.receivepack true && + git --git-dir="$d" repack -adl && + git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git +' + +test_expect_success TTY 'push shows progress when stderr is a tty' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit noisy && + test_terminal git push >output 2>&1 && + grep "^Writing objects" output +' + +test_expect_success TTY 'push --quiet silences status and progress' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit quiet && + test_terminal git push --quiet >output 2>&1 && + test_cmp /dev/null output +' + +test_expect_success TTY 'push --no-progress silences progress but not status' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit no-progress && + test_terminal git push --no-progress >output 2>&1 && + grep "^To http" output && + ! grep "^Writing objects" +' + +test_expect_success 'push --progress shows progress to non-tty' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit progress && + git push --progress >output 2>&1 && + grep "^To http" output && + grep "^Writing objects" output +' + +test_expect_success 'http push gives sane defaults to reflog' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit reflog-test && + git push "$HTTPD_URL"/smart/test_repo.git && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ + log -g -1 --format="%gn <%ge>" >actual && + echo "anonymous <anonymous@http.127.0.0.1>" >expect && + test_cmp expect actual +' + +test_expect_success 'http push respects GIT_COMMITTER_* in reflog' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit custom-reflog-test && + git push "$HTTPD_URL"/smart_custom_env/test_repo.git && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ + log -g -1 --format="%gn <%ge>" >actual && + echo "Custom User <custom@example.com>" >expect && + test_cmp expect actual +' + stop_httpd test_done diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index a1883ca6b6..b06f817af3 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -8,22 +8,27 @@ 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' ' - echo content >file && + echo content1 >file && git add file && git commit -m one + echo content2 >file && + git add file && + git commit -m two ' -test_expect_success 'create http-accessible bare repository' ' - mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && +test_expect_success 'create http-accessible bare repository with loose objects' ' + cp -a .git "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && - git --bare init && + git config core.bare true && + mkdir -p hooks && echo "exec git update-server-info" >hooks/post-update && - chmod +x hooks/post-update + chmod +x hooks/post-update && + hooks/post-update ) && git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && git push public master:master @@ -35,11 +40,98 @@ 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 +' + +expect_askpass() { + dest=$HTTPD_DEST + { + case "$1" in + none) + ;; + pass) + echo "askpass: Password for 'http://$2@$dest': " + ;; + both) + echo "askpass: Username for 'http://$dest': " + echo "askpass: Password for 'http://$2@$dest': " + ;; + *) + false + ;; + esac + } >askpass-expect && + test_cmp askpass-expect askpass-query +} + +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 && + expect_askpass both wrong +' + +test_expect_success 'http auth can use user/pass in URL' ' + >askpass-query && + echo wrong >askpass-response && + git clone "$HTTPD_URL_USER_PASS/auth/repo.git" clone-auth-none && + expect_askpass none +' + +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 && + expect_askpass pass user@host +' + +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 && + expect_askpass both user@host +' + +test_expect_success 'http auth respects credential helper config' ' + test_config_global credential.helper "!f() { + cat >/dev/null + echo username=user@host + echo password=user@host + }; f" && + >askpass-query && + echo wrong >askpass-response && + git clone "$HTTPD_URL/auth/repo.git" clone-auth-helper && + expect_askpass none +' + +test_expect_success 'http auth can get username from config' ' + test_config_global "credential.$HTTPD_URL.username" user@host && + >askpass-query && + echo user@host >askpass-response && + git clone "$HTTPD_URL/auth/repo.git" clone-auth-user && + expect_askpass pass user@host +' + +test_expect_success 'configured username does not override URL' ' + test_config_global "credential.$HTTPD_URL.username" wrong && + >askpass-query && + echo user@host >askpass-response && + git clone "$HTTPD_URL_USER/auth/repo.git" clone-auth-user2 && + expect_askpass pass user@host ' test_expect_success 'fetch changes via http' ' @@ -75,8 +167,7 @@ test_expect_success 'http remote detects correct HEAD' ' test_expect_success 'fetch packed objects' ' cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git && (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git && - git --bare repack && - git --bare prune-packed + git --bare repack -a -d ) && git clone $HTTPD_URL/dumb/repo_pack.git ' diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh index 26d355725f..fadf2f258e 100755 --- a/t/t5551-http-fetch.sh +++ b/t/t5551-http-fetch.sh @@ -109,5 +109,36 @@ test_expect_success 'follow redirects (302)' ' git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t ' +test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE + +test_expect_success EXPENSIVE 'create 50,000 tags in the repo' ' + ( + cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + for i in `seq 50000` + do + echo "commit refs/heads/too-many-refs" + echo "mark :$i" + echo "committer git <git@example.com> $i +0000" + echo "data 0" + echo "M 644 inline bla.txt" + echo "data 4" + echo "bla" + # make every commit dangling by always + # rewinding the branch after each commit + echo "reset refs/heads/too-many-refs" + echo "from :1" + done | git fast-import --export-marks=marks && + + # now assign tags to all the dangling commits we created above + tag=$("$PERL_PATH" -e "print \"bla\" x 30") && + sed -e "s/^:\(.\+\) \(.\+\)$/\2 refs\/tags\/$tag-\1/" <marks >>packed-refs + ) +' + +test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' ' + git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err && + test_line_count = 0 err +' + stop_httpd test_done diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh index 0ad7ce07c4..ef98d95e00 100755 --- a/t/t5560-http-backend-noserver.sh +++ b/t/t5560-http-backend-noserver.sh @@ -17,7 +17,7 @@ run_backend() { GET() { REQUEST_METHOD="GET" && export REQUEST_METHOD && run_backend "/repo.git/$1" && - unset REQUEST_METHOD && + sane_unset REQUEST_METHOD && if ! grep "Status" act.out >act then printf "Status: 200 OK\r\n" >act @@ -30,8 +30,8 @@ POST() { REQUEST_METHOD="POST" && export REQUEST_METHOD && CONTENT_TYPE="application/x-$1-request" && export CONTENT_TYPE && run_backend "/repo.git/$1" "$2" && - unset REQUEST_METHOD && - unset CONTENT_TYPE && + sane_unset REQUEST_METHOD && + sane_unset CONTENT_TYPE && if ! grep "Status" act.out >act then printf "Status: 200 OK\r\n" >act diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh new file mode 100755 index 0000000000..a3a4e47e1d --- /dev/null +++ b/t/t5570-git-daemon.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +test_description='test fetching over git protocol' +. ./test-lib.sh + +LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-5570} +. "$TEST_DIRECTORY"/lib-git-daemon.sh +start_git_daemon + +test_expect_success 'setup repository' ' + echo content >file && + git add file && + git commit -m one +' + +test_expect_success 'create git-accessible bare repository' ' + mkdir "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" && + (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" && + git --bare init && + : >git-daemon-export-ok + ) && + git remote add public "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" && + git push public master:master +' + +test_expect_success 'clone git repository' ' + git clone "$GIT_DAEMON_URL/repo.git" clone && + test_cmp file clone/file +' + +test_expect_success 'fetch changes via git protocol' ' + echo content >>file && + git commit -a -m two && + git push public && + (cd clone && git pull) && + test_cmp file clone/file +' + +test_expect_failure 'remote detects correct HEAD' ' + git push public master:other && + (cd clone && + git remote set-head -d origin && + git remote set-head -a origin && + git symbolic-ref refs/remotes/origin/HEAD > output && + echo refs/remotes/origin/master > expect && + test_cmp expect output + ) +' + +test_expect_success 'prepare pack objects' ' + cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git && + (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git && + git --bare repack -a -d + ) +' + +test_expect_success 'fetch notices corrupt pack' ' + cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git && + (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git && + p=`ls objects/pack/pack-*.pack` && + chmod u+w $p && + printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc + ) && + mkdir repo_bad1.git && + (cd repo_bad1.git && + git --bare init && + test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad1.git" && + test 0 = `ls objects/pack/pack-*.pack | wc -l` + ) +' + +test_expect_success 'fetch notices corrupt idx' ' + cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && + (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && + p=`ls objects/pack/pack-*.idx` && + chmod u+w $p && + printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc + ) && + mkdir repo_bad2.git && + (cd repo_bad2.git && + git --bare init && + test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad2.git" && + test 0 = `ls objects/pack | wc -l` + ) +' + +test_remote_error() +{ + do_export=YesPlease + while test $# -gt 0 + do + case $1 in + -x) + shift + chmod -x "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" + ;; + -n) + shift + do_export= + ;; + *) + break + esac + done + + msg=$1 + shift + cmd=$1 + shift + repo=$1 + shift || error "invalid number of arguments" + + if test -x "$GIT_DAEMON_DOCUMENT_ROOT_PATH/$repo" + then + if test -n "$do_export" + then + : >"$GIT_DAEMON_DOCUMENT_ROOT_PATH/$repo/git-daemon-export-ok" + else + rm -f "$GIT_DAEMON_DOCUMENT_ROOT_PATH/$repo/git-daemon-export-ok" + fi + fi + + test_must_fail git "$cmd" "$GIT_DAEMON_URL/$repo" "$@" 2>output && + echo "fatal: remote error: $msg: /$repo" >expect && + test_cmp expect output + ret=$? + chmod +x "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" + (exit $ret) +} + +msg="access denied or repository not exported" +test_expect_success 'clone non-existent' "test_remote_error '$msg' clone nowhere.git " +test_expect_success 'push disabled' "test_remote_error '$msg' push repo.git master" +test_expect_success 'read access denied' "test_remote_error -x '$msg' fetch repo.git " +test_expect_success 'not exported' "test_remote_error -n '$msg' fetch repo.git " + +stop_git_daemon +start_git_daemon --informative-errors + +test_expect_success 'clone non-existent' "test_remote_error 'no such repository' clone nowhere.git " +test_expect_success 'push disabled' "test_remote_error 'service not enabled' push repo.git master" +test_expect_success 'read access denied' "test_remote_error -x 'no such repository' fetch repo.git " +test_expect_success 'not exported' "test_remote_error -n 'repository not exported' fetch repo.git " + +stop_git_daemon +test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 151ea531bd..67869b4813 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -9,10 +9,13 @@ test_expect_success setup ' rm -fr .git && test_create_repo src && ( - cd src - >file - git add file - git commit -m initial + cd src && + >file && + git add file && + git commit -m initial && + echo 1 >file && + git add file && + git commit -m updated ) ' @@ -88,6 +91,26 @@ test_expect_success 'clone --mirror' ' ' +test_expect_success 'clone --mirror with detached HEAD' ' + + ( cd src && git checkout HEAD^ && git rev-parse HEAD >../expected ) && + git clone --mirror src mirror.detached && + ( cd src && git checkout - ) && + GIT_DIR=mirror.detached git rev-parse HEAD >actual && + test_cmp expected actual + +' + +test_expect_success 'clone --bare with detached HEAD' ' + + ( cd src && git checkout HEAD^ && git rev-parse HEAD >../expected ) && + git clone --bare src bare.detached && + ( cd src && git checkout - ) && + GIT_DIR=bare.detached git rev-parse HEAD >actual && + test_cmp expected actual + +' + test_expect_success 'clone --bare names the local repository <name>.git' ' git clone --bare src && @@ -202,9 +225,59 @@ test_expect_success 'clone separate gitdir: output' ' 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_expect_success 'clone checking out a tag' ' + git clone --branch=some-tag src dst.tag && + GIT_DIR=src/.git git rev-parse some-tag >expected && + test_cmp expected dst.tag/.git/HEAD && + GIT_DIR=dst.tag/.git git config remote.origin.fetch >fetch.actual && + echo "+refs/heads/*:refs/remotes/origin/*" >fetch.expected && + test_cmp fetch.expected fetch.actual +' + test_done diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index 895f5595ae..c47d450cc3 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -34,7 +34,7 @@ test_expect_success 'cloning with reference (-l -s)' \ cd "$base_dir" test_expect_success 'existence of info/alternates' \ -'test `wc -l <C/.git/objects/info/alternates` = 2' +'test_line_count = 2 C/.git/objects/info/alternates' cd "$base_dir" @@ -52,18 +52,18 @@ test_cmp expected current' cd "$base_dir" -rm -f "$U" +rm -f "$U.D" test_expect_success 'cloning with reference (no -l -s)' \ -'GIT_DEBUG_SEND_PACK=3 git clone --reference B "file://$(pwd)/A" D 3>"$U"' +'GIT_DEBUG_SEND_PACK=3 git clone --reference B "file://$(pwd)/A" D 3>"$U.D"' test_expect_success 'fetched no objects' \ -'! grep "^want" "$U"' +'! grep "^want" "$U.D"' cd "$base_dir" test_expect_success 'existence of info/alternates' \ -'test `wc -l <D/.git/objects/info/alternates` = 1' +'test_line_count = 1 D/.git/objects/info/alternates' cd "$base_dir" @@ -146,4 +146,39 @@ test_expect_success 'cloning with reference being subset of source (-l -s)' \ cd "$base_dir" +test_expect_success 'clone with reference from a tagged repository' ' + ( + cd A && git tag -a -m 'tagged' HEAD + ) && + git clone --reference=A A I +' + +test_expect_success 'prepare branched repository' ' + git clone A J && + ( + cd J && + git checkout -b other master^ && + echo other >otherfile && + git add otherfile && + git commit -m other && + git checkout master + ) +' + +rm -f "$U.K" + +test_expect_success 'fetch with incomplete alternates' ' + git init K && + echo "$base_dir/A/.git/objects" >K/.git/objects/info/alternates && + ( + cd K && + git remote add J "file://$base_dir/J" && + GIT_DEBUG_SEND_PACK=3 git fetch J 3>"$U.K" + ) && + master_object=$(cd A && git for-each-ref --format="%(objectname)" refs/heads/master) && + ! grep "^want $master_object" "$U.K" && + tag_object=$(cd A && git for-each-ref --format="%(objectname)" refs/tags/HEAD) && + ! grep "^want $tag_object" "$U.K" +' + test_done diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh index 6972258b27..c6feca44e3 100755 --- a/t/t5701-clone-local.sh +++ b/t/t5701-clone-local.sh @@ -3,7 +3,10 @@ test_description='test local clone' . ./test-lib.sh -D=`pwd` +repo_is_hardlinked() { + find "$1/objects" -type f -links 1 >output && + test_line_count = 0 output +} test_expect_success 'preparing origin repository' ' : >file && git add . && git commit -m1 && @@ -19,105 +22,72 @@ test_expect_success 'preparing origin repository' ' ' test_expect_success 'local clone without .git suffix' ' - cd "$D" && git clone -l -s a b && - cd b && + (cd b && test "$(GIT_CONFIG=.git/config git config --bool core.bare)" = false && - git fetch + git fetch) ' test_expect_success 'local clone with .git suffix' ' - cd "$D" && git clone -l -s a.git c && - cd c && - git fetch + (cd c && git fetch) ' test_expect_success 'local clone from x' ' - cd "$D" && git clone -l -s x y && - cd y && - git fetch + (cd y && git fetch) ' test_expect_success 'local clone from x.git that does not exist' ' - cd "$D" && - if git clone -l -s x.git z - then - echo "Oops, should have failed" - false - else - echo happy - fi + test_must_fail git clone -l -s x.git z ' test_expect_success 'With -no-hardlinks, local will make a copy' ' - cd "$D" && git clone --bare --no-hardlinks x w && - cd w && - linked=$(find objects -type f ! -links 1 | wc -l) && - test 0 = $linked + ! repo_is_hardlinked w ' test_expect_success 'Even without -l, local will make a hardlink' ' - cd "$D" && rm -fr w && git clone -l --bare x w && - cd w && - copied=$(find objects -type f -links 1 | wc -l) && - test 0 = $copied + repo_is_hardlinked w ' test_expect_success 'local clone of repo with nonexistent ref in HEAD' ' - cd "$D" && echo "ref: refs/heads/nonexistent" > a.git/HEAD && git clone a d && - cd d && + (cd d && git fetch && - test ! -e .git/refs/remotes/origin/HEAD' + test ! -e .git/refs/remotes/origin/HEAD) +' test_expect_success 'bundle clone without .bundle suffix' ' - cd "$D" && git clone dir/b3 && - cd b3 && - git fetch + (cd b3 && git fetch) ' test_expect_success 'bundle clone with .bundle suffix' ' - cd "$D" && git clone b1.bundle && - cd b1 && - git fetch + (cd b1 && git fetch) ' test_expect_success 'bundle clone from b4' ' - cd "$D" && git clone b4 bdl && - cd bdl && - git fetch + (cd bdl && git fetch) ' test_expect_success 'bundle clone from b4.bundle that does not exist' ' - cd "$D" && - if git clone b4.bundle bb - then - echo "Oops, should have failed" - false - else - echo happy - fi + test_must_fail git clone b4.bundle bb ' test_expect_success 'bundle clone with nonexistent HEAD' ' - cd "$D" && git clone b2.bundle b2 && - cd b2 && + (cd b2 && git fetch && - test ! -e .git/refs/heads/master + test_must_fail git rev-parse --verify refs/heads/master) ' test_expect_success 'clone empty repository' ' - cd "$D" && mkdir empty && (cd empty && git init && @@ -135,7 +105,6 @@ test_expect_success 'clone empty repository' ' ' test_expect_success 'clone empty repository, and then push should not segfault.' ' - cd "$D" && rm -fr empty/ empty-clone/ && mkdir empty && (cd empty && git init) && @@ -145,13 +114,11 @@ test_expect_success 'clone empty repository, and then push should not segfault.' ' 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 diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh index 728ccd88c3..9e43731fe5 100755 --- a/t/t5704-bundle.sh +++ b/t/t5704-bundle.sh @@ -4,53 +4,58 @@ test_description='some bundle related tests' . ./test-lib.sh test_expect_success 'setup' ' - - : > file && - git add file && - test_tick && - git commit -m initial && + test_commit initial && test_tick && git tag -m tag tag && - : > file2 && - git add file2 && - : > file3 && - test_tick && - git commit -m second && - git add file3 && - test_tick && - git commit -m third - + test_commit second && + test_commit third && + git tag -d initial && + git tag -d second && + git tag -d third ' test_expect_success 'tags can be excluded by rev-list options' ' - git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 && git ls-remote bundle > output && ! grep tag output - ' test_expect_success 'die if bundle file cannot be created' ' - mkdir adir && test_must_fail git bundle create adir --all - ' test_expect_failure 'bundle --stdin' ' - echo master | git bundle create stdin-bundle.bdl --stdin && git ls-remote stdin-bundle.bdl >output && grep master output - ' test_expect_failure 'bundle --stdin <rev-list options>' ' - echo master | git bundle create hybrid-bundle.bdl --stdin tag && git ls-remote hybrid-bundle.bdl >output && grep master output +' + +test_expect_success 'empty bundle file is rejected' ' + : >empty-bundle && + test_must_fail git fetch empty-bundle +' +# This triggers a bug in older versions where the resulting line (with +# --pretty=oneline) was longer than a 1024-char buffer. +test_expect_success 'ridiculously long subject in boundary' ' + : >file4 && + test_tick && + git add file4 && + printf "%01200d\n" 0 | git commit -F - && + test_commit fifth && + git bundle create long-subject-bundle.bdl HEAD^..HEAD && + git bundle list-heads long-subject-bundle.bdl >heads && + test -s heads && + git fetch long-subject-bundle.bdl && + sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary && + grep "^-[0-9a-f]\\{40\\} " boundary ' test_done diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh index f3f9a76056..56be67e07e 100755 --- a/t/t5706-clone-branch.sh +++ b/t/t5706-clone-branch.sh @@ -57,12 +57,8 @@ test_expect_success 'clone -b does not munge remotes/origin/HEAD' ' ) ' -test_expect_success 'clone -b with bogus branch chooses HEAD' ' - git clone -b bogus parent clone-bogus && - (cd clone-bogus && - check_HEAD master && - check_file one - ) +test_expect_success 'clone -b with bogus branch' ' + test_must_fail git clone -b bogus parent clone-bogus ' 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/t5710-info-alternate.sh b/t/t5710-info-alternate.sh index ef7127c1b3..aa045295de 100755 --- a/t/t5710-info-alternate.sh +++ b/t/t5710-info-alternate.sh @@ -18,7 +18,7 @@ reachable_via() { test_valid_repo() { git fsck --full > fsck.log && - test `wc -l < fsck.log` = 0 + test_line_count = 0 fsck.log } base_dir=`pwd` diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh index 1fb6380fce..5702334510 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 +} -test_expect_success PYTHON_24 'setup repository' ' +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 'setup repository' ' git init --bare server/.git && git clone server public && (cd public && @@ -27,54 +37,112 @@ 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 +' + +# Generally, skip this test. It demonstrates a now-fixed race in +# git-remote-testgit, but is too slow to leave in for general use. +: test_expect_success 'racily pushing to local repo' ' + test_when_finished "rm -rf server2 localclone2" && + cp -a server server2 && + git clone "testgit::${PWD}/server2" localclone2 && + (cd localclone2 && + echo content >>file && + git commit -a -m three && + GIT_REMOTE_TESTGIT_SLEEPY=2 git push) && + compare_refs localclone2 HEAD server2 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/t5900-repo-selection.sh b/t/t5900-repo-selection.sh new file mode 100755 index 0000000000..3d5b418bb4 --- /dev/null +++ b/t/t5900-repo-selection.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +test_description='selecting remote repo in ambiguous cases' +. ./test-lib.sh + +reset() { + rm -rf foo foo.git fetch clone +} + +make_tree() { + git init "$1" && + (cd "$1" && test_commit "$1") +} + +make_bare() { + git init --bare "$1" && + (cd "$1" && + tree=`git hash-object -w -t tree /dev/null` && + commit=$(echo "$1" | git commit-tree $tree) && + git update-ref HEAD $commit + ) +} + +get() { + git init --bare fetch && + (cd fetch && git fetch "../$1") && + git clone "$1" clone +} + +check() { + echo "$1" >expect && + (cd fetch && git log -1 --format=%s FETCH_HEAD) >actual.fetch && + (cd clone && git log -1 --format=%s HEAD) >actual.clone && + test_cmp expect actual.fetch && + test_cmp expect actual.clone +} + +test_expect_success 'find .git dir in worktree' ' + reset && + make_tree foo && + get foo && + check foo +' + +test_expect_success 'automagically add .git suffix' ' + reset && + make_bare foo.git && + get foo && + check foo.git +' + +test_expect_success 'automagically add .git suffix to worktree' ' + reset && + make_tree foo.git && + get foo && + check foo.git +' + +test_expect_success 'prefer worktree foo over bare foo.git' ' + reset && + make_tree foo && + make_bare foo.git && + get foo && + check foo +' + +test_expect_success 'prefer bare foo over bare foo.git' ' + reset && + make_bare foo && + make_bare foo.git && + get foo && + check foo +' + +test_expect_success 'disambiguate with full foo.git' ' + reset && + make_bare foo && + make_bare foo.git && + get foo.git && + check foo.git +' + +test_expect_success 'we are not fooled by non-git foo directory' ' + reset && + make_bare foo.git && + mkdir foo && + get foo && + check foo.git +' + +test_expect_success 'prefer inner .git over outer bare' ' + reset && + make_tree foo && + make_bare foo.git && + mv foo/.git foo.git && + get foo.git && + check foo +' + +test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index d918cc02d0..f94f0c48e6 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -188,23 +188,23 @@ test_expect_success 'empty email' ' test_expect_success 'del LF before empty (1)' ' git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual && - test $(wc -l <actual) = 2 + test_line_count = 2 actual ' test_expect_success 'del LF before empty (2)' ' git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD >actual && - test $(wc -l <actual) = 6 && + test_line_count = 6 actual && grep "^$" actual ' test_expect_success 'add LF before non-empty (1)' ' git show -s --pretty=format:"%s%+b%nThanks%n" HEAD^^ >actual && - test $(wc -l <actual) = 2 + test_line_count = 2 actual ' test_expect_success 'add LF before non-empty (2)' ' git show -s --pretty=format:"%s%+b%nThanks%n" HEAD >actual && - test $(wc -l <actual) = 6 && + test_line_count = 6 actual && grep "^$" actual ' @@ -267,13 +267,27 @@ test_expect_success '%gd shortens ref name' ' test_cmp expect.gd-short actual.gd-short ' +test_expect_success 'reflog identity' ' + echo "C O Mitter:committer@example.com" >expect && + git log -g -1 --format="%gn:%ge" >actual && + test_cmp expect actual +' + test_expect_success 'oneline with empty message' ' git commit -m "dummy" --allow-empty && git commit -m "dummy" --allow-empty && git filter-branch --msg-filter "sed -e s/dummy//" HEAD^^.. && git rev-list --oneline HEAD >test.txt && - test $(git rev-list --oneline HEAD | wc -l) -eq 5 && - test $(git rev-list --oneline --graph HEAD | wc -l) -eq 5 + test_line_count = 5 test.txt && + git rev-list --oneline --graph HEAD >testg.txt && + test_line_count = 5 testg.txt +' + +test_expect_success 'single-character name is parsed correctly' ' + git commit --author="a <a@example.com>" --allow-empty -m foo && + echo "a <a@example.com>" >expect && + git log -1 --format="%an <%ae>" >actual && + test_cmp expect actual ' test_done diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh index e51eb41f4b..bbb0581f88 100755 --- a/t/t6011-rev-list-with-bad-commit.sh +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -37,7 +37,7 @@ test_expect_success 'verify number of revisions' \ test_expect_success 'corrupt second commit object' \ ' - perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack && + "$PERL_PATH" -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack && test_must_fail git fsck --full ' diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh index af34a1e817..839ad97b79 100755 --- a/t/t6012-rev-list-simplify.sh +++ b/t/t6012-rev-list-simplify.sh @@ -86,5 +86,6 @@ check_result 'I H E C B A' --full-history --date-order -- file check_result 'I E C B A' --simplify-merges -- file check_result 'I B A' -- file check_result 'I B A' --topo-order -- file +check_result 'H' --first-parent -- another-file test_done diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh index 59fc2f06e0..892a537989 100755 --- a/t/t6013-rev-list-reverse-parents.sh +++ b/t/t6013-rev-list-reverse-parents.sh @@ -25,7 +25,7 @@ test_expect_success 'set up --reverse example' ' test_expect_success '--reverse --parents --full-history combines correctly' ' git rev-list --parents --full-history master -- foo | - perl -e "print reverse <>" > expected && + "$PERL_PATH" -e "print reverse <>" > expected && git rev-list --reverse --parents --full-history master -- foo \ > actual && test_cmp actual expected @@ -33,7 +33,7 @@ test_expect_success '--reverse --parents --full-history combines correctly' ' test_expect_success '--boundary does too' ' git rev-list --boundary --parents --full-history master ^root -- foo | - perl -e "print reverse <>" > expected && + "$PERL_PATH" -e "print reverse <>" > expected && git rev-list --boundary --reverse --parents --full-history \ master ^root -- foo > actual && test_cmp actual expected 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..1104249182 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,294 @@ 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_expect_success 'do not follow renames for empty files' ' + git checkout -f -b empty-base && + >empty1 && + git add empty1 && + git commit -m base && + echo content >empty1 && + git add empty1 && + git commit -m fill && + git checkout -b empty-topic HEAD^ && + git mv empty1 empty2 && + git commit -m rename && + test_must_fail git merge empty-base && + >expect && + test_cmp expect empty2 +' + 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/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh index a91644e3b2..c518e9c30c 100755 --- a/t/t6028-merge-up-to-date.sh +++ b/t/t6028-merge-up-to-date.sh @@ -16,7 +16,12 @@ test_expect_success setup ' test_tick && git commit -m second && git tag c1 && - git branch test + git branch test && + echo third >file && + git add file && + test_tick && + git commit -m third && + git tag c2 ' test_expect_success 'merge -s recursive up-to-date' ' @@ -74,4 +79,14 @@ test_expect_success 'merge -s subtree up-to-date' ' ' +test_expect_success 'merge fast-forward octopus' ' + + git reset --hard c0 && + test_tick && + git merge c1 c2 + expect=$(git rev-parse c2) && + current=$(git rev-parse HEAD) && + test "$expect" = "$current" +' + test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index b5063b6fe6..72e28ee535 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 && + test_i18ngrep "* (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 && @@ -460,7 +480,7 @@ test_expect_success 'many merge bases creation' ' git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" && B_HASH=$(git rev-parse --verify HEAD) && git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt && - test $(wc -l < merge_bases.txt) = "2" && + test_line_count = 2 merge_bases.txt && grep "$HASH5" merge_bases.txt && grep "$SIDE_HASH5" merge_bases.txt ' @@ -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/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh index fdb6c25371..15beecc3c6 100755 --- a/t/t6032-merge-large-rename.sh +++ b/t/t6032-merge-large-rename.sh @@ -95,9 +95,9 @@ test_expect_success 'setup large simple rename' ' ' test_expect_success 'massive simple rename does not spam added files' ' - unset GIT_MERGE_VERBOSITY && + sane_unset GIT_MERGE_VERBOSITY && git merge --no-stat simple-rename | grep -v Removing >output && - test 5 -gt "$(wc -l < output)" + test_line_count -lt 5 output ' test_done 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 a9b0ac1efc..ec2b516c3f 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -51,17 +51,33 @@ test_expect_success 'branch -v' ' 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' ' ( cd test && git checkout b1 ) >actual && - grep "have 1 and 1 different" actual + test_i18ngrep "have 1 and 1 different" actual ' test_expect_success 'checkout with local tracked branch' ' git checkout master && git checkout follower >actual && - grep "is ahead of" actual + test_i18ngrep "is ahead of" actual ' test_expect_success 'status' ' @@ -71,14 +87,14 @@ test_expect_success 'status' ' # reports nothing to commit test_must_fail git commit --dry-run ) >actual && - grep "have 1 and 1 different" actual + test_i18ngrep "have 1 and 1 different" actual ' test_expect_success 'fail to track lightweight tags' ' git checkout master && git tag light && test_must_fail git branch --track lighttrack light >actual && - test_must_fail grep "set up to track" actual && + test_i18ngrep ! "set up to track" actual && test_must_fail git checkout lighttrack ' @@ -86,7 +102,7 @@ test_expect_success 'fail to track annotated tags' ' git checkout master && git tag -m heavy heavy && test_must_fail git branch --track heavytrack heavy >actual && - test_must_fail grep "set up to track" actual && + test_i18ngrep ! "set up to track" actual && test_must_fail git checkout heavytrack ' @@ -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..466fa3804b --- /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_line_count = 6 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/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 9a16806921..992c2a0467 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -35,15 +35,18 @@ test_expect_success setup ' echo "l3" >two && test_tick && - git commit -a -m "Left #3" && + GIT_COMMITTER_NAME="Another Committer" \ + GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #3" && echo "l4" >two && test_tick && - git commit -a -m "Left #4" && + GIT_COMMITTER_NAME="Another Committer" \ + GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #4" && echo "l5" >two && test_tick && - git commit -a -m "Left #5" && + GIT_COMMITTER_NAME="Another Committer" \ + GIT_AUTHOR_NAME="Another Author" git commit -a -m "Left #5" && git tag tag-l5 && git checkout right && @@ -99,6 +102,8 @@ test_expect_success '[merge] summary/log configuration' ' cat >expected <<-EOF && Merge branch ${apos}left${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: Left #5 Left #4 @@ -144,6 +149,8 @@ test_expect_success 'merge.log=3 limits shortlog length' ' cat >expected <<-EOF && Merge branch ${apos}left${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: (5 commits) Left #5 Left #4 @@ -159,6 +166,8 @@ test_expect_success 'merge.log=5 shows all 5 commits' ' cat >expected <<-EOF && Merge branch ${apos}left${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: Left #5 Left #4 @@ -181,6 +190,8 @@ test_expect_success '--log=3 limits shortlog length' ' cat >expected <<-EOF && Merge branch ${apos}left${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: (5 commits) Left #5 Left #4 @@ -196,6 +207,8 @@ test_expect_success '--log=5 shows all 5 commits' ' cat >expected <<-EOF && Merge branch ${apos}left${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: Left #5 Left #4 @@ -225,6 +238,8 @@ test_expect_success 'fmt-merge-msg -m' ' cat >expected.log <<-EOF && Sync with left + # By Another Author (3) and A U Thor (2) + # Via Another Committer * ${apos}left${apos} of $(pwd): Left #5 Left #4 @@ -256,6 +271,8 @@ test_expect_success 'setup: expected shortlog for two branches' ' cat >expected <<-EOF Merge branches ${apos}left${apos} and ${apos}right${apos} + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: Left #5 Left #4 @@ -379,6 +396,8 @@ test_expect_success 'merge-msg two tags' ' Common #2 Common #1 + # By Another Author (3) and A U Thor (2) + # Via Another Committer * tag ${apos}tag-l5${apos}: Left #5 Left #4 @@ -407,6 +426,8 @@ test_expect_success 'merge-msg tag and branch' ' Common #2 Common #1 + # By Another Author (3) and A U Thor (2) + # Via Another Committer * left: Left #5 Left #4 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/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index e0227730de..4d13e10de1 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -5,7 +5,8 @@ test_description='git filter-branch' test_expect_success 'setup' ' test_commit A && - test_commit B && + GIT_COMMITTER_DATE="@0 +0000" GIT_AUTHOR_DATE="@0 +0000" && + test_commit --notick B && git checkout -b branch B && test_commit D && mkdir dir && diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 2ac1c66079..5189446534 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,55 @@ 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 +' + +test_expect_success 'listing tags in column' ' + COLUMNS=40 git tag -l --column=row >actual && + cat >expected <<\EOF && +a1 aa1 cba t210 t211 +v0.2.1 v1.0 v1.0.1 v1.1.3 +EOF + test_cmp expected actual +' + +test_expect_success 'listing tags in column with column.*' ' + git config column.tag row && + git config column.ui dense && + COLUMNS=40 git tag -l >actual && + git config --unset column.ui && + git config --unset column.tag && + cat >expected <<\EOF && +a1 aa1 cba t210 t211 +v0.2.1 v1.0 v1.0.1 v1.1.3 +EOF + test_cmp expected actual +' + +test_expect_success 'listing tag with -n --column should fail' ' + test_must_fail git tag --column -n +' + +test_expect_success 'listing tags -n in column with column.ui ignored' ' + git config column.ui "row dense" && + COLUMNS=40 git tag -l -n >actual && + git config --unset column.ui && + cat >expected <<\EOF && +a1 Foo +aa1 Foo +cba Foo +t210 Foo +t211 Foo +v0.2.1 Foo +v1.0 Foo +v1.0.1 Foo +v1.1.3 Foo +EOF + test_cmp expected actual +' + # creating and verifying lightweight tags: test_expect_success \ @@ -580,23 +630,18 @@ 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 +test_expect_success 'annotations for blobs are empty' ' + blob=$(git hash-object -w --stdin <<-\EOF + Blob paragraph 1. + + Blob paragraph 2. + EOF + ) && + git tag tag-blob $blob && + echo "tag-blob " >expect && + git tag -n1 -l tag-blob >actual && + test_cmp expect actual +' # trying to verify annotated non-signed tags: @@ -620,16 +665,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 @@ -1291,4 +1326,43 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -v -s ' +# check points-at + +test_expect_success '--points-at cannot be used in non-list mode' ' + test_must_fail git tag --points-at=v4.0 foo +' + +test_expect_success '--points-at finds lightweight tags' ' + echo v4.0 >expect && + git tag --points-at v4.0 >actual && + test_cmp expect actual +' + +test_expect_success '--points-at finds annotated tags of commits' ' + git tag -m "v4.0, annotated" annotated-v4.0 v4.0 && + echo annotated-v4.0 >expect && + git tag -l --points-at v4.0 "annotated*" >actual && + test_cmp expect actual +' + +test_expect_success '--points-at finds annotated tags of tags' ' + git tag -m "describing the v4.0 tag object" \ + annotated-again-v4.0 annotated-v4.0 && + cat >expect <<-\EOF && + annotated-again-v4.0 + annotated-v4.0 + EOF + git tag --points-at=annotated-v4.0 >actual && + test_cmp expect actual +' + +test_expect_success 'multiple --points-at are OR-ed together' ' + cat >expect <<-\EOF && + v2.0 + v3.0 + EOF + git tag --points-at=v2.0 --points-at=v3.0 >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index ed7575d0fd..ff2590849d 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -6,14 +6,9 @@ test_description='Test automatic use of a pager.' . "$TEST_DIRECTORY"/lib-pager.sh . "$TEST_DIRECTORY"/lib-terminal.sh -cleanup_fail() { - echo >&2 cleanup failed - (exit 1) -} - 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 && @@ -22,9 +17,7 @@ test_expect_success 'setup' ' ' test_expect_success TTY 'some commands use a pager' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && test_terminal git log && test -e paginated.out ' @@ -45,70 +38,56 @@ test_expect_failure TTY 'pager runs from subdir' ' ' test_expect_success TTY 'some commands do not use a pager' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && test_terminal git rev-list HEAD && ! test -e paginated.out ' test_expect_success 'no pager when stdout is a pipe' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && git log | cat && ! test -e paginated.out ' test_expect_success 'no pager when stdout is a regular file' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && git log >file && ! test -e paginated.out ' test_expect_success TTY 'git --paginate rev-list uses a pager' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && test_terminal git --paginate rev-list HEAD && test -e paginated.out ' test_expect_success 'no pager even with --paginate when stdout is a pipe' ' - rm -f file paginated.out || - cleanup_fail && - + rm -f file paginated.out && git --paginate log | cat && ! test -e paginated.out ' test_expect_success TTY 'no pager with --no-pager' ' - rm -f paginated.out || - cleanup_fail && - + rm -f paginated.out && test_terminal git --no-pager log && ! test -e paginated.out ' test_expect_success TTY 'configuration can disable pager' ' rm -f paginated.out && - test_might_fail git config --unset pager.grep && + test_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 +95,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 && @@ -139,9 +117,7 @@ colorful() { } test_expect_success 'tests can detect color' ' - rm -f colorful.log colorless.log || - cleanup_fail && - + rm -f colorful.log colorless.log && git log --no-color >colorless.log && git log --color >colorful.log && ! colorful colorless.log && @@ -150,18 +126,14 @@ 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 || - cleanup_fail && - + test_config color.ui auto && git log >colorless.log && ! colorful colorless.log ' test_expect_success TTY 'color when writing to a pager' ' rm -f paginated.out && - git config color.ui auto || - cleanup_fail && - + test_config color.ui auto && ( TERM=vt100 && export TERM && @@ -170,11 +142,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 || - cleanup_fail && - + test_config color.ui auto && ( TERM=vt100 && GIT_PAGER_IN_USE=true && @@ -184,6 +166,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,10 +214,8 @@ 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 && - rm -f default_pager_used || - cleanup_fail && - + test_unconfig core.pager && + rm -f default_pager_used && cat >\$less <<-\EOF && #!/bin/sh wc >default_pager_used @@ -244,10 +235,8 @@ test_PAGER_overrides() { $test_expectation TTY "$cmd - PAGER overrides default pager" " sane_unset GIT_PAGER && - test_might_fail git config --unset core.pager && - rm -f PAGER_used || - cleanup_fail && - + test_unconfig core.pager && + rm -f PAGER_used && PAGER='wc >PAGER_used' && export PAGER && $full_command && @@ -272,12 +261,10 @@ test_core_pager() { $test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" " sane_unset GIT_PAGER && - rm -f core.pager_used || - cleanup_fail && - + rm -f core.pager_used && 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 " @@ -301,13 +288,11 @@ test_pager_subdir_helper() { $test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" " sane_unset GIT_PAGER && rm -f core.pager_used && - rm -fr sub || - cleanup_fail && - + rm -fr sub && 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 && @@ -321,10 +306,8 @@ test_GIT_PAGER_overrides() { parse_args "$@" $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" " - rm -f GIT_PAGER_used || - cleanup_fail && - - git config core.pager wc && + rm -f GIT_PAGER_used && + test_config core.pager wc && GIT_PAGER='wc >GIT_PAGER_used' && export GIT_PAGER && $full_command && @@ -336,9 +319,7 @@ test_doesnt_paginate() { parse_args "$@" $test_expectation TTY "no pager for '$cmd'" " - rm -f GIT_PAGER_used || - cleanup_fail && - + rm -f GIT_PAGER_used && GIT_PAGER='wc >GIT_PAGER_used' && export GIT_PAGER && $full_command && @@ -402,21 +383,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 +406,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/t7007-show.sh b/t/t7007-show.sh index cce222f052..a40cd3630c 100755 --- a/t/t7007-show.sh +++ b/t/t7007-show.sh @@ -17,4 +17,95 @@ test_expect_success 'showing a tag that point at a missing object' ' test_must_fail git --no-pager show foo-tag ' +test_expect_success 'set up a bit of history' ' + test_commit main1 && + test_commit main2 && + test_commit main3 && + git tag -m "annotated tag" annotated && + git checkout -b side HEAD^^ && + test_commit side2 && + test_commit side3 +' + +test_expect_success 'showing two commits' ' + cat >expect <<-EOF && + commit $(git rev-parse main2) + commit $(git rev-parse main3) + EOF + git show main2 main3 >actual && + grep ^commit actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing a range walks (linear)' ' + cat >expect <<-EOF && + commit $(git rev-parse main3) + commit $(git rev-parse main2) + EOF + git show main1..main3 >actual && + grep ^commit actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing a range walks (Y shape, ^ first)' ' + cat >expect <<-EOF && + commit $(git rev-parse main3) + commit $(git rev-parse main2) + EOF + git show ^side3 main3 >actual && + grep ^commit actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing a range walks (Y shape, ^ last)' ' + cat >expect <<-EOF && + commit $(git rev-parse main3) + commit $(git rev-parse main2) + EOF + git show main3 ^side3 >actual && + grep ^commit actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing with -N walks' ' + cat >expect <<-EOF && + commit $(git rev-parse main3) + commit $(git rev-parse main2) + EOF + git show -2 main3 >actual && + grep ^commit actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing annotated tag' ' + cat >expect <<-EOF && + tag annotated + commit $(git rev-parse annotated^{commit}) + EOF + git show annotated >actual && + grep -E "^(commit|tag)" actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing annotated tag plus commit' ' + cat >expect <<-EOF && + tag annotated + commit $(git rev-parse annotated^{commit}) + commit $(git rev-parse side3) + EOF + git show annotated side3 >actual && + grep -E "^(commit|tag)" actual >actual.filtered && + test_cmp expect actual.filtered +' + +test_expect_success 'showing range' ' + cat >expect <<-EOF && + commit $(git rev-parse main3) + commit $(git rev-parse main2) + EOF + git show ^side3 annotated >actual && + grep -E "^(commit|tag)" actual >actual.filtered && + test_cmp expect actual.filtered +' + test_done diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh index e058d184d1..fd6410fc71 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,9 +94,33 @@ 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 " +test_expect_success 'grep respects binary diff attribute' ' + echo text >t && + git add t && + echo t:text >expect && + git grep text t >actual && + test_cmp expect actual && + echo "t -diff" >.gitattributes && + echo "Binary file t matches" >expect && + git grep text t >actual && + test_cmp expect actual +' + +test_expect_success 'grep respects not-binary diff attribute' ' + echo binQary | q_to_nul >b && + git add b && + echo "Binary file b matches" >expect && + git grep bin b >actual && + test_cmp expect actual && + echo "b diff" >.gitattributes && + echo "b:binQary" >expect && + git grep bin b | nul_to_q >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index f1cfc9ac95..b096dc88c2 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -429,6 +429,21 @@ test_expect_success '--mixed refreshes the index' ' 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)' ' git reset --hard && diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 07fb53adcb..be9672e5a0 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -229,7 +229,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && test_i18ngrep "HEAD is now at 7329388" messages && - test 1 -eq $(wc -l <messages) && + test_line_count = 1 messages && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && test "z$H" = "z$M" && @@ -247,7 +247,7 @@ test_expect_success 'checkout to detach HEAD' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && test_i18ngrep "HEAD is now at 7329388" messages && - test 1 -lt $(wc -l <messages) && + test_line_count -gt 1 messages && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && test "z$H" = "z$M" && diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 800b5368a5..ccfb54de7a 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -399,8 +399,8 @@ test_expect_success SANITY 'removal failure' ' ' test_expect_success 'nested git work tree' ' - rm -fr foo bar && - mkdir foo bar && + rm -fr foo bar baz && + mkdir -p foo bar baz/boo && ( cd foo && git init && @@ -412,15 +412,24 @@ test_expect_success 'nested git work tree' ' cd bar && >goodbye.people ) && + ( + cd baz/boo && + git init && + >deeper.world + git add . && + git commit -a -m deeply.nested + ) && git clean -f -d && test -f foo/.git/index && test -f foo/hello.world && + test -f baz/boo/.git/index && + test -f baz/boo/deeper.world && ! test -d bar ' test_expect_success 'force removal of nested git work tree' ' - rm -fr foo bar && - mkdir foo bar && + rm -fr foo bar baz && + mkdir -p foo bar baz/boo && ( cd foo && git init && @@ -432,9 +441,17 @@ test_expect_success 'force removal of nested git work tree' ' cd bar && >goodbye.people ) && + ( + cd baz/boo && + git init && + >deeper.world + git add . && + git commit -a -m deeply.nested + ) && git clean -f -f -d && ! test -d foo && - ! test -d bar + ! test -d bar && + ! test -d baz ' test_expect_success 'git clean -e' ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 874279e32d..81827e696f 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,17 @@ test_expect_success 'submodule add' ' ( cd addtest && - git submodule add "$submodurl" submod && + git submodule add -q "$submodurl" submod >actual && + test ! -s actual && + echo "gitdir: ../.git/modules/submod" >expect && + test_cmp expect submod/.git && + ( + cd submod && + git config core.worktree >actual && + echo "../../../submod" >expect && + test_cmp expect actual && + rm -f actual expect + ) && git submodule init ) && @@ -99,7 +111,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 ) ' @@ -222,7 +234,7 @@ EOF test_expect_success 'status should only print one line' ' git submodule status >lines && - test $(wc -l <lines) = 1 + test_line_count = 1 lines ' test_expect_success 'setup - fetch commit name from submodule' ' @@ -273,7 +285,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 +370,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 +459,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 && ( @@ -484,4 +507,17 @@ test_expect_success 'relative path works with user@host:path' ' ) ' +test_expect_success 'moving the superproject does not break submodules' ' + ( + cd addtest && + git submodule status >expect + ) + mv addtest addtest2 && + ( + cd addtest2 && + git submodule status >actual && + test_cmp expect actual + ) +' + test_done 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 d600583cef..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' ' @@ -55,8 +56,9 @@ test_expect_success '"git submodule sync" should update submodule URLs' ' 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 a8fb30b792..0d5b42a25b 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -228,4 +228,55 @@ test_expect_success 'merging with a modify/modify conflict between merge bases' 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 4f16fcce2b..ce61d4c0fa 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 ' ' @@ -90,7 +96,7 @@ test_expect_success 'submodule update does not fetch already present commits' ' (cd super && git submodule update > ../actual 2> ../actual.err ) && - test_cmp expected actual && + test_i18ncmp expected actual && ! test -s actual.err ' @@ -298,4 +304,349 @@ test_expect_success 'submodule update ignores update=rebase config for new submo ) ' +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_expect_success 'submodule add properly re-creates deeper level submodules' ' + (cd super && + git reset --hard master && + rm -rf deeper/ && + git submodule add ../submodule deeper/submodule + ) +' + +test_expect_success 'submodule update properly revives a moved submodule' ' + (cd super && + git commit -am "pre move" && + git status >expect&& + H=$(cd submodule2; git rev-parse HEAD) && + git rm --cached submodule2 && + rm -rf submodule2 && + mkdir -p "moved/sub module" && + git update-index --add --cacheinfo 160000 $H "moved/sub module" && + git config -f .gitmodules submodule.submodule2.path "moved/sub module" + git commit -am "post move" && + git submodule update && + git status >actual && + test_cmp expect actual + ) +' + +test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd' ' + mkdir -p linked/dir && + ln -s linked/dir linkto && + ( + cd linkto && + git clone "$TRASH_DIRECTORY"/super_update_r2 super && + ( + cd super && + git submodule update --init --recursive + ) + ) +' + test_done diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index e5be13c271..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 ) ' @@ -247,14 +247,17 @@ test_expect_success 'ensure "status --cached --recursive" preserves the --cached 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' ' @@ -262,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 ) ' @@ -277,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..b770b2f04d 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -28,7 +28,7 @@ git prune' cd "$base_dir" -test_expect_success 'preparing supermodule' \ +test_expect_success 'preparing superproject' \ 'test_create_repo super && cd super && echo file > file && git add file && @@ -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_line_count = 1 super/.git/modules/sub/objects/info/alternates' cd "$base_dir" @@ -55,7 +55,7 @@ diff expected current' cd "$base_dir" -test_expect_success 'cloning supermodule' \ +test_expect_success 'cloning superproject' \ 'git clone super super-clone' 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_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates' cd "$base_dir" diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 3ad04363b5..195e7477d8 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -8,39 +8,41 @@ test_description='git commit' . ./test-lib.sh +. "$TEST_DIRECTORY/diff-lib.sh" -test_tick +author='The Real Author <someguy@his.email.org>' -test_expect_success \ - "initial status" \ - "echo 'bongo bongo' >file && - git add file" +test_tick -test_expect_success "Constructing initial commit" ' +test_expect_success 'initial status' ' + echo bongo bongo >file && + git add file && git status >actual && test_i18ngrep "Initial commit" actual ' -test_expect_success \ - "fail initial amend" \ - "test_must_fail git commit --amend" +test_expect_success 'fail initial amend' ' + test_must_fail git commit --amend +' -test_expect_success \ - "initial commit" \ - "git commit -m initial" +test_expect_success 'setup: initial commit' ' + git commit -m initial +' -test_expect_success \ - "invalid options 1" \ - "test_must_fail git commit -m foo -m bar -F file" +test_expect_success '-m and -F do not mix' ' + git checkout HEAD file && echo >>file && git add file && + test_must_fail git commit -m foo -m bar -F file +' -test_expect_success \ - "invalid options 2" \ - "test_must_fail git commit -C HEAD -m illegal" +test_expect_success '-m and -C do not mix' ' + git checkout HEAD file && echo >>file && git add file && + test_must_fail git commit -C HEAD -m illegal +' -test_expect_success \ - "using paths with -a" \ - "echo King of the bongo >file && - test_must_fail git commit -m foo -a file" +test_expect_success 'paths and -a do not mix' ' + echo King of the bongo >file && + test_must_fail git commit -m foo -a file +' test_expect_success PERL 'can use paths with --interactive' ' echo bong-o-bong >file && @@ -50,139 +52,200 @@ test_expect_success PERL 'can use paths with --interactive' ' git reset --hard HEAD^ ' -test_expect_success \ - "using invalid commit with -C" \ - "test_must_fail git commit -C bogus" +test_expect_success 'using invalid commit with -C' ' + test_must_fail git commit -C bogus +' + +test_expect_success 'nothing to commit' ' + test_must_fail git commit -m initial +' + +test_expect_success 'setup: non-initial commit' ' + echo bongo bongo bongo >file && + git commit -m next -a +' + +test_expect_success 'commit message from non-existing file' ' + echo more bongo: bongo bongo bongo bongo >file && + test_must_fail git commit -F gah -a +' -test_expect_success \ - "testing nothing to commit" \ - "test_must_fail git commit -m initial" +test_expect_success 'empty commit message' ' + # Empty except stray tabs and spaces on a few lines. + sed -e "s/@//g" >msg <<-\EOF && + @ @ + @@ + @ @ + @Signed-off-by: hula@ + EOF + test_must_fail git commit -F msg -a +' -test_expect_success \ - "next commit" \ - "echo 'bongo bongo bongo' >file \ - git commit -m next -a" +test_expect_success 'template "emptyness" check does not kick in with -F' ' + git checkout HEAD file && echo >>file && git add file && + git commit -t file -F file +' -test_expect_success \ - "commit message from non-existing file" \ - "echo 'more bongo: bongo bongo bongo bongo' >file && \ - test_must_fail git commit -F gah -a" +test_expect_success 'template "emptyness" check' ' + git checkout HEAD file && echo >>file && git add file && + test_must_fail git commit -t file 2>err && + test_i18ngrep "did not edit" err +' -# Empty except stray tabs and spaces on a few lines. -sed -e 's/@$//' >msg <<EOF - @ +test_expect_success 'setup: commit message from file' ' + git checkout HEAD file && echo >>file && git add file && + echo this is the commit message, coming from a file >msg && + git commit -F msg -a +' - @ -Signed-off-by: hula -EOF -test_expect_success \ - "empty commit message" \ - "test_must_fail git commit -F msg -a" +test_expect_success 'amend commit' ' + cat >editor <<-\EOF && + #!/bin/sh + sed -e "s/a file/an amend commit/g" < "$1" > "$1-" + mv "$1-" "$1" + EOF + chmod 755 editor && + EDITOR=./editor git commit --amend +' -test_expect_success \ - "commit message from file" \ - "echo 'this is the commit message, coming from a file' >msg && \ - git commit -F msg -a" +test_expect_success 'amend --only ignores staged contents' ' + cp file file.expect && + echo changed >file && + git add file && + git commit --no-edit --amend --only && + git cat-file blob HEAD:file >file.actual && + test_cmp file.expect file.actual && + git diff --exit-code +' -cat >editor <<\EOF -#!/bin/sh -sed -e "s/a file/an amend commit/g" < "$1" > "$1-" -mv "$1-" "$1" -EOF -chmod 755 editor +test_expect_success 'set up editor' ' + cat >editor <<-\EOF && + #!/bin/sh + sed -e "s/unamended/amended/g" <"$1" >"$1-" + mv "$1-" "$1" + EOF + chmod 755 editor +' -test_expect_success \ - "amend commit" \ - "EDITOR=./editor git commit --amend" +test_expect_success 'amend without launching editor' ' + echo unamended >expect && + git commit --allow-empty -m "unamended" && + echo needs more bongo >file && + git add file && + EDITOR=./editor git commit --no-edit --amend && + git diff --exit-code HEAD -- file && + git diff-tree -s --format=%s HEAD >msg && + test_cmp expect msg +' -test_expect_success \ - "passing -m and -F" \ - "echo 'enough with the bongos' >file && \ - test_must_fail git commit -F msg -m amending ." +test_expect_success '--amend --edit' ' + echo amended >expect && + git commit --allow-empty -m "unamended" && + echo bongo again >file && + git add file && + EDITOR=./editor git commit --edit --amend && + git diff-tree -s --format=%s HEAD >msg && + test_cmp expect msg +' -test_expect_success \ - "using message from other commit" \ - "git commit -C HEAD^ ." +test_expect_success '--amend --edit of empty message' ' + cat >replace <<-\EOF && + #!/bin/sh + echo "amended" >"$1" + EOF + chmod 755 replace && + git commit --allow-empty --allow-empty-message -m "" && + echo more bongo >file && + git add file && + EDITOR=./replace git commit --edit --amend && + git diff-tree -s --format=%s HEAD >msg && + ./replace expect && + test_cmp expect msg +' -cat >editor <<\EOF -#!/bin/sh -sed -e "s/amend/older/g" < "$1" > "$1-" -mv "$1-" "$1" -EOF -chmod 755 editor - -test_expect_success \ - "editing message from other commit" \ - "echo 'hula hula' >file && \ - EDITOR=./editor git commit -c HEAD^ -a" - -test_expect_success \ - "message from stdin" \ - "echo 'silly new contents' >file && \ - echo commit message from stdin | git commit -F - -a" - -test_expect_success \ - "overriding author from command line" \ - "echo 'gak' >file && \ - git commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a >output 2>&1" - -test_expect_success \ - "commit --author output mentions author" \ - "grep Rubber.Duck output" - -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_expect_success '-m --edit' ' + echo amended >expect && + git commit --allow-empty -m buffer && + echo bongo bongo >file && + git add file && + EDITOR=./editor git commit -m unamended --edit && + git diff-tree -s --format=%s HEAD >msg && + test_cmp expect msg +' + +test_expect_success '-m and -F do not mix' ' + echo enough with the bongos >file && + test_must_fail git commit -F msg -m amending . +' + +test_expect_success 'using message from other commit' ' + git commit -C HEAD^ . +' + +test_expect_success 'editing message from other commit' ' + cat >editor <<-\EOF && + #!/bin/sh + sed -e "s/amend/older/g" < "$1" > "$1-" + mv "$1-" "$1" + EOF + chmod 755 editor && + echo hula hula >file && + EDITOR=./editor git commit -c HEAD^ -a +' + +test_expect_success 'message from stdin' ' + echo silly new contents >file && + echo commit message from stdin | + git commit -F - -a +' + +test_expect_success 'overriding author from command line' ' + echo gak >file && + git commit -m author \ + --author "Rubber Duck <rduck@convoy.org>" -a >output 2>&1 && + grep Rubber.Duck output +' + +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) && + (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" + compare_diff_patch diff1 diff2 +' -cat >editor <<\EOF -#!/bin/sh -sed -e "s/good/bad/g" < "$1" > "$1-" -mv "$1-" "$1" -EOF -chmod 755 editor - -cat >msg <<EOF -A good commit message. -EOF - -test_expect_success \ - 'editor not invoked if -F is given' ' - echo "moo" >file && - EDITOR=./editor git commit -a -F msg && - git show -s --pretty=format:"%s" | grep -q good && - echo "quack" >file && - echo "Another good message." | EDITOR=./editor git commit -a -F - && - git show -s --pretty=format:"%s" | grep -q good - ' -# We could just check the head sha1, but checking each commit makes it -# easier to isolate bugs. - -cat >expected <<\EOF -72c0dc9855b0c9dadcbfd5a31cab072e0cb774ca -9b88fc14ce6b32e3d9ee021531a54f18a5cf38a2 -3536bbb352c3a1ef9a420f5b4242d48578b92aa7 -d381ac431806e53f3dd7ac2f1ae0534f36d738b9 -4fd44095ad6334f3ef72e4c5ec8ddf108174b54a -402702b49136e7587daa9280e91e4bb7cb2179f7 -EOF - -test_expect_success \ - 'validate git rev-list output.' \ - 'test_cmp expected current' +test_expect_success 'editor not invoked if -F is given' ' + cat >editor <<-\EOF && + #!/bin/sh + sed -e s/good/bad/g <"$1" >"$1-" + mv "$1-" "$1" + EOF + chmod 755 editor && + + echo A good commit message. >msg && + echo moo >file && + + EDITOR=./editor git commit -a -F msg && + git show -s --pretty=format:%s >subject && + grep -q good subject && + + echo quack >file && + echo Another good message. | + EDITOR=./editor git commit -a -F - && + git show -s --pretty=format:%s >subject && + grep -q good subject +' test_expect_success 'partial commit that involves removal (1)' ' @@ -216,7 +279,6 @@ test_expect_success 'partial commit that involves removal (3)' ' ' -author="The Real Author <someguy@his.email.org>" test_expect_success 'amend commit to fix author' ' oldtick=$GIT_AUTHOR_DATE && @@ -345,7 +407,6 @@ test_expect_success 'multiple -m' ' ' -author="The Real Author <someguy@his.email.org>" test_expect_success 'amend commit to fix author' ' oldtick=$GIT_AUTHOR_DATE && @@ -372,15 +433,8 @@ test_expect_success 'git commit <file> with dirty index' ' test_expect_success 'same tree (single parent)' ' - git reset --hard - - if git commit -m empty - then - echo oops -- should have complained - false - else - : happy - fi + git reset --hard && + test_must_fail git commit -m empty ' @@ -458,4 +512,16 @@ test_expect_success 'amend can copy notes' ' ' +test_expect_success 'commit a file whose name is a dash' ' + git reset --hard && + for i in 1 2 3 4 5 + do + echo $i + done >./- && + git add ./- && + test_tick && + git commit -m "add dash" >output </dev/null && + test_i18ngrep " changed, 5 insertions" output +' + test_done diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 3f3adc31b9..181456aa9a 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -335,7 +335,7 @@ test_expect_success 'A single-liner subject with a token plus colon is not a foo git reset --hard && git commit -s -m "hello: kitty" --allow-empty && git cat-file commit HEAD | sed -e "1,/^$/d" >actual && - test $(wc -l <actual) = 3 + test_line_count = 3 actual ' diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh index 8528f64c8d..984889b39d 100755 --- a/t/t7503-pre-commit-hook.sh +++ b/t/t7503-pre-commit-hook.sh @@ -84,5 +84,56 @@ 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_expect_success 'check the author in hook' ' + write_script "$HOOK" <<-\EOF && + test "$GIT_AUTHOR_NAME" = "New Author" && + test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com" + EOF + test_must_fail git commit --allow-empty -m "by a.u.thor" && + ( + GIT_AUTHOR_NAME="New Author" && + GIT_AUTHOR_EMAIL="newauthor@example.com" && + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL && + git commit --allow-empty -m "by new.author via env" && + git show -s + ) && + git commit --author="New Author <newauthor@example.com>" \ + --allow-empty -m "by new.author via command line" && + git show -s +' test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 1fdfbd3865..c206f4777a 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -59,6 +59,30 @@ test_expect_success 'status (1)' ' test_i18ngrep "use \"git rm --cached <file>\.\.\.\" to unstage" output ' +test_expect_success 'status --column' ' + COLUMNS=50 git status --column="column dense" >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) +# +# dir1/untracked dir2/untracked untracked +# dir2/modified output +EOF + test_cmp expect output +' + cat >expect <<\EOF # On branch master # Changes to be committed: @@ -131,6 +155,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_i18ncmp 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_i18ncmp expect output +' + +rm -f .gitignore + cat >expect <<\EOF ## master M dir1/modified @@ -150,6 +295,15 @@ test_expect_success 'status -s -b' ' ' +test_expect_success 'status -s -z -b' ' + tr "\\n" Q <expect >expect.q && + mv expect.q expect && + git status -s -z -b >output && + nul_to_q <output >output.q && + mv output.q output && + test_cmp expect output +' + test_expect_success 'setup dir3' ' mkdir dir3 && : >dir3/untracked1 && @@ -526,9 +680,14 @@ test_expect_success 'status --porcelain ignores color.status' ' git config --unset color.status git config --unset color.ui -test_expect_success 'status --porcelain ignores -b' ' +test_expect_success 'status --porcelain respects -b' ' git status --porcelain -b >output && + { + echo "## master" && + cat expect + } >tmp && + mv tmp expect && test_cmp expect output ' @@ -782,7 +941,7 @@ test_expect_success 'status -s submodule summary (clean submodule)' ' test_expect_success 'status -z implies porcelain' ' git status --porcelain | - perl -pe "s/\012/\000/g" >expect && + "$PERL_PATH" -pe "s/\012/\000/g" >expect && git status -z >output && test_cmp expect output ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh new file mode 100755 index 0000000000..1d3c56fe61 --- /dev/null +++ b/t/t7510-signed-commit.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +test_description='signed commit tests' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" + +test_expect_success GPG 'create signed commits' ' + echo 1 >file && git add file && + test_tick && git commit -S -m initial && + git tag initial && + git branch side && + + echo 2 >file && test_tick && git commit -a -S -m second && + git tag second && + + git checkout side && + echo 3 >elif && git add elif && + test_tick && git commit -m "third on side" && + + git checkout master && + test_tick && git merge -S side && + git tag merge && + + echo 4 >file && test_tick && git commit -a -m "fourth unsigned" && + git tag fourth-unsigned && + + test_tick && git commit --amend -S -m "fourth signed" && + git tag fourth-signed +' + +test_expect_success GPG 'show signatures' ' + ( + for commit in initial second merge master + do + git show --pretty=short --show-signature $commit >actual && + grep "Good signature from" actual || exit 1 + ! grep "BAD signature from" actual || exit 1 + echo $commit OK + done + ) && + ( + for commit in merge^2 fourth-unsigned + do + git show --pretty=short --show-signature $commit >actual && + grep "Good signature from" actual && exit 1 + ! grep "BAD signature from" actual || exit 1 + echo $commit OK + done + ) +' + +test_expect_success GPG 'detect fudged signature' ' + git cat-file commit master >raw && + + sed -e "s/fourth signed/4th forged/" raw >forged1 && + git hash-object -w -t commit forged1 >forged1.commit && + git show --pretty=short --show-signature $(cat forged1.commit) >actual1 && + grep "BAD signature from" actual1 && + ! grep "Good signature from" actual1 +' + +test_expect_success GPG 'detect fudged signature with NUL' ' + git cat-file commit master >raw && + cat raw >forged2 && + echo Qwik | tr "Q" "\000" >>forged2 && + git hash-object -w -t commit forged2 >forged2.commit && + git show --pretty=short --show-signature $(cat forged2.commit) >actual2 && + grep "BAD signature from" actual2 && + ! grep "Good signature from" actual2 +' + +test_expect_success GPG 'amending already signed commit' ' + git checkout fourth-signed^0 && + git commit --amend -S --no-edit && + git show -s --show-signature HEAD >actual && + grep "Good signature from" actual && + ! grep "BAD signature from" actual +' + +test_done diff --git a/t/t7511-status-index.sh b/t/t7511-status-index.sh new file mode 100755 index 0000000000..b5fdc048a5 --- /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 px +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 87aac835a1..9e27bbf902 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -27,6 +27,7 @@ Testing basic merge operations/option parsing. ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh 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 @@ -38,8 +39,8 @@ 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 "Merge tag 'c2'" >msg.1-5 && + echo "Merge tags 'c2' and 'c3'" >msg.1-5-9 && { echo "Squashed commit of the following:" && echo && @@ -57,7 +58,7 @@ create_merge_msgs () { } >squash.1-5-9 && echo >msg.nolog && { - echo "* commit 'c3':" && + echo "* tag 'c3':" && echo " commit 3" && echo } >msg.log @@ -96,7 +97,11 @@ verify_parents () { verify_mergeheads () { printf '%s\n' "$@" >mergehead.expected && - test_cmp mergehead.expected .git/MERGE_HEAD + while read sha1 rest + do + git rev-parse $sha1 + done <.git/MERGE_HEAD >mergehead.actual && + test_cmp mergehead.expected mergehead.actual } verify_no_mergehead () { @@ -643,4 +648,51 @@ 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_expect_success GPG 'merge --ff-only tag' ' + git reset --hard c0 && + git commit --allow-empty -m "A newer commit" && + git tag -s -m "A newer commit" signed && + git reset --hard c0 && + + git merge --ff-only signed && + git rev-parse signed^0 >expect && + git rev-parse HEAD >actual && + test_cmp actual expect +' + +test_expect_success GPG 'merge --no-edit tag should skip editor' ' + git reset --hard c0 && + git commit --allow-empty -m "A newer commit" && + git tag -f -s -m "A newer commit" signed && + git reset --hard c0 && + + EDITOR=false git merge --no-edit signed && + git rev-parse signed^0 >expect && + git rev-parse HEAD^2 >actual && + test_cmp actual expect +' + test_done diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index 0a46795ae7..955f09f8e8 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -53,11 +53,11 @@ cat >expected <<\EOF Trying simple merge with c2 Trying simple merge with c3 Trying simple merge with c4 -Merge made by octopus. - c2.c | 1 + - c3.c | 1 + - c4.c | 1 + - 3 files changed, 3 insertions(+), 0 deletions(-) +Merge made by the 'octopus' strategy. + c2.c | 1 + + c3.c | 1 + + c4.c | 1 + + 3 files changed, 3 insertions(+) create mode 100644 c2.c create mode 100644 c3.c create mode 100644 c4.c @@ -66,30 +66,28 @@ EOF test_expect_success 'merge output uses pretty names' ' git reset --hard c1 && git merge c2 c3 c4 >actual && - test_cmp actual expected + test_i18ncmp expected actual ' cat >expected <<\EOF -Already up-to-date with c4 -Trying simple merge with c5 -Merge made by octopus. - c5.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) +Merge made by the 'recursive' strategy. + c5.c | 1 + + 1 file changed, 1 insertion(+) create mode 100644 c5.c EOF -test_expect_success 'merge up-to-date output uses pretty names' ' - git merge c4 c5 >actual && - test_cmp actual expected +test_expect_success 'merge reduces irrelevant remote heads' ' + GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual && + test_i18ncmp expected actual ' cat >expected <<\EOF Fast-forwarding to: c1 Trying simple merge with c2 -Merge made by octopus. - c1.c | 1 + - c2.c | 1 + - 2 files changed, 2 insertions(+), 0 deletions(-) +Merge made by the 'octopus' strategy. + c1.c | 1 + + c2.c | 1 + + 2 files changed, 2 insertions(+) create mode 100644 c1.c create mode 100644 c2.c EOF @@ -97,7 +95,7 @@ EOF test_expect_success 'merge fast-forward output uses pretty names' ' git reset --hard c0 && git merge c1 c2 >actual && - test_cmp actual expected + test_i18ncmp expected actual ' test_done diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh index 7e17eb490d..98948955ae 100755 --- a/t/t7603-merge-reduce-heads.sh +++ b/t/t7603-merge-reduce-heads.sh @@ -57,7 +57,36 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' ' test -f c2.c && test -f c3.c && test -f c4.c && - test -f c5.c + test -f c5.c && + git show --format=%s -s >actual && + ! grep c1 actual && + grep c2 actual && + grep c3 actual && + ! grep c4 actual && + grep c5 actual +' + +test_expect_success 'pull c2, c3, c4, c5 into c1' ' + git reset --hard c1 && + git pull . c2 c3 c4 c5 && + test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && + test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" && + test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" && + test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && + test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" && + git diff --exit-code && + test -f c0.c && + test -f c1.c && + test -f c2.c && + test -f c3.c && + test -f c4.c && + test -f c5.c && + git show --format=%s -s >actual && + ! grep c1 actual && + grep c2 actual && + grep c3 actual && + ! grep c4 actual && + grep c5 actual ' test_expect_success 'setup' ' @@ -113,4 +142,23 @@ test_expect_success 'verify merge result' ' test $(git rev-parse HEAD^1) = $(git rev-parse E2) && test $(git rev-parse HEAD^2) = $(git rev-parse I2) ' + +test_expect_success 'fast-forward to redundant refs' ' + git reset --hard c0 && + git merge c4 c5 +' + +test_expect_success 'verify merge result' ' + test $(git rev-parse HEAD) = $(git rev-parse c5) +' + +test_expect_success 'merge up-to-date redundant refs' ' + git reset --hard c5 && + git merge c0 c4 +' + +test_expect_success 'verify merge result' ' + test $(git rev-parse HEAD) = $(git rev-parse c5) +' + test_done diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh index 9114785ef7..89619cf446 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -11,7 +11,7 @@ create_merge_msgs() { cp exp.subject exp.log && echo >>exp.log "" && - echo >>exp.log "* commit 'c2':" && + echo >>exp.log "* tag 'c2':" && echo >>exp.log " c2" } diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 72a8731d5e..6547eb8f54 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -92,6 +92,15 @@ test_expect_success 'will not overwrite removed file with staged changes' ' test_cmp important c1.c ' +test_expect_failure 'will not overwrite unstaged changes in renamed file' ' + git reset --hard c1 && + git mv c1.c other.c && + git commit -m rename && + cp important other.c && + git merge c1a && + test_cmp important other.c +' + test_expect_success 'will not overwrite untracked subtree' ' git reset --hard c0 && rm -rf sub && @@ -107,6 +116,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' ' diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh index 9225fa6f02..8e7e0a5865 100755 --- a/t/t7608-merge-messages.sh +++ b/t/t7608-merge-messages.sh @@ -35,7 +35,7 @@ test_expect_success 'merge tag' ' git checkout master && test_commit master-3 && git merge tag-1 && - check_oneline "Merge commit Qtag-1Q" + check_oneline "Merge tag Qtag-1Q" ' test_expect_success 'ambiguous tag' ' @@ -44,7 +44,7 @@ test_expect_success 'ambiguous tag' ' git checkout master && test_commit master-4 && git merge ambiguous && - check_oneline "Merge commit QambiguousQ" + check_oneline "Merge tag QambiguousQ" ' test_expect_success 'remote-tracking branch' ' 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 cbc08e3276..f5e16fc7db 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -16,6 +16,7 @@ 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 && @@ -30,13 +31,15 @@ test_expect_success 'setup' ' git commit -m "Add foo" ) && git submodule add git://example.com/submod submod && - git add file1 file1[1-4] subdir/file3 .gitmodules 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 both added >both && echo branch1 change file11 >file11 && echo branch1 change file13 >file13 && echo branch1 sub >subdir/file3 && @@ -47,7 +50,8 @@ test_expect_success 'setup' ' git commit -m "Add bar on branch1" && git checkout -b submod-branch1 ) && - git add file1 file11 file13 file2 subdir/file3 submod && + git add file1 "spaced name" file11 file13 file2 subdir/file3 submod && + git add both && git rm file12 && git commit -m "branch1 changes" && @@ -55,6 +59,8 @@ test_expect_success 'setup' ' git submodule update -N && echo master updated >file1 && echo master new >file2 && + echo master updated spaced >"spaced name" && + echo master both added >both && echo master updated file12 >file12 && echo master updated file14 >file14 && echo master new sub >subdir/file3 && @@ -65,21 +71,25 @@ test_expect_success 'setup' ' git commit -m "Add bar on master" && git checkout -b submod-master ) && - git add file1 file12 file14 file2 subdir/file3 submod && + git add file1 "spaced name" file12 file14 file2 subdir/file3 submod && + git add both && git rm file11 && git commit -m "master updates" && git config merge.tool mytool && git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" && - git config mergetool.mytool.trustExitCode true + git config mergetool.mytool.trustExitCode true && + git config mergetool.mybase.cmd "cat \"\$BASE\" >\"\$MERGED\"" && + git config mergetool.mybase.trustExitCode true ' 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 both >/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 ) && @@ -97,6 +107,8 @@ 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 both >/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 ) && @@ -126,7 +138,8 @@ 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 "" | git mergetool ../both >/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 ) && @@ -180,6 +193,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' ' 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 && @@ -189,7 +220,8 @@ test_expect_success 'deleted vs modified submodule' ' git checkout -b test6.a test6 && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/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 && @@ -205,7 +237,8 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/dev/null 2>&1 ) && ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && ( yes "l" | git mergetool submod ) && test ! -e submod && @@ -218,7 +251,8 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test6 && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/dev/null 2>&1 ) && ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && ( yes "r" | git mergetool submod ) && test ! -e submod && @@ -233,7 +267,8 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test6 && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/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" && @@ -256,7 +291,8 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test7.a branch1 && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/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 && @@ -271,7 +307,8 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test7.b test7 && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/dev/null 2>&1 ) && ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && ( yes "l" | git mergetool submod ) && git submodule update -N && @@ -286,7 +323,8 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test7 && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both >/dev/null 2>&1 ) && ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && ( yes "r" | git mergetool submod ) && test -d submod.orig && @@ -301,7 +339,8 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test7 && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | git mergetool both>/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" && @@ -388,7 +427,7 @@ test_expect_success 'directory vs modified submodule' ' test "$(cat submod/file16)" = "not a submodule" && rm -rf submod.orig && - git reset --hard && + git reset --hard >/dev/null 2>&1 && test_must_fail git merge master && test -n "$(git ls-files -u)" && test ! -e submod.orig && @@ -400,7 +439,7 @@ test_expect_success 'directory vs modified submodule' ' ( cd submod && git clean -f && git reset --hard ) && git submodule update -N && test "$(cat submod/bar)" = "master submodule" && - git reset --hard && rm -rf submod-movedaside && + git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside && git checkout -b test11.c master && git submodule update -N && @@ -410,7 +449,7 @@ test_expect_success 'directory vs modified submodule' ' git submodule update -N && test "$(cat submod/bar)" = "master submodule" && - git reset --hard && + git reset --hard >/dev/null 2>&1 && git submodule update -N && test_must_fail git merge test11 && test -n "$(git ls-files -u)" && @@ -418,9 +457,18 @@ test_expect_success 'directory vs modified submodule' ' ( yes "r" | git mergetool submod ) && test "$(cat submod/file16)" = "not a submodule" && - git reset --hard master && + git reset --hard master >/dev/null 2>&1 && ( cd submod && git clean -f && git reset --hard ) && git submodule update -N ' +test_expect_success 'file with no base' ' + git checkout -b test13 branch1 && + test_must_fail git merge master && + git mergetool --no-prompt --tool mybase -- both && + >expected && + test_cmp both expected && + git reset --hard master >/dev/null 2>&1 +' + test_done diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index 200ab61278..b8d4cdea8c 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -95,4 +95,18 @@ test_expect_success 'unpacked objects receive timestamp of pack file' ' compare_mtimes < mtimes ' +test_expect_success 'do not bother loosening old objects' ' + obj1=$(echo one | git hash-object -w --stdin) && + obj2=$(echo two | git hash-object -w --stdin) && + pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) && + pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) && + git prune-packed && + git cat-file -p $obj1 && + git cat-file -p $obj2 && + test-chmtime =-86400 .git/objects/pack/pack-$pack2.pack && + git repack -A -d --unpack-unreachable=1.hour.ago && + git cat-file -p $obj1 && + test_must_fail git cat-file -p $obj2 +' + test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 4048d106d4..9c3e997b9d 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 @@ -76,6 +83,17 @@ test_expect_success PERL 'difftool ignores bad --tool values' ' test "$diff" = "" ' +test_expect_success PERL 'difftool forwards arguments to diff' ' + >for-diff && + git add for-diff && + echo changes>for-diff && + git add for-diff && + diff=$(git difftool --cached --no-prompt -- for-diff) && + test "$diff" = "" && + git reset -- for-diff && + rm for-diff +' + test_expect_success PERL 'difftool honors --gui' ' git config merge.tool bogus-tool && git config diff.tool bogus-tool && @@ -87,6 +105,19 @@ test_expect_success PERL 'difftool honors --gui' ' restore_test_defaults ' +test_expect_success PERL 'difftool --gui last setting wins' ' + git config diff.guitool bogus-tool && + git difftool --no-prompt --gui --no-gui && + + git config merge.tool bogus-tool && + git config diff.tool bogus-tool && + git config diff.guitool test-tool && + diff=$(git difftool --no-prompt --no-gui --gui branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + test_expect_success PERL 'difftool --gui works without configured diff.guitool' ' git config diff.tool test-tool && @@ -268,4 +299,79 @@ 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_expect_success PERL 'difftool --tool-help' ' + tool_help=$(git difftool --tool-help) && + echo "$tool_help" | stdin_contains tool +' + +test_expect_success PERL 'setup change in subdirectory' ' + git checkout master && + mkdir sub && + echo master >sub/sub && + git add sub/sub && + git commit -m "added sub/sub" && + echo test >>file && + echo test >>sub/sub && + git add . && + git commit -m "modified both" +' + +test_expect_success PERL 'difftool -d' ' + diff=$(git difftool -d --extcmd ls branch) && + echo "$diff" | stdin_contains sub && + echo "$diff" | stdin_contains file +' + +test_expect_success PERL 'difftool --dir-diff' ' + diff=$(git difftool --dir-diff --extcmd ls branch) && + echo "$diff" | stdin_contains sub && + echo "$diff" | stdin_contains file +' + +test_expect_success PERL 'difftool --dir-diff ignores --prompt' ' + diff=$(git difftool --dir-diff --prompt --extcmd ls branch) && + echo "$diff" | stdin_contains sub && + echo "$diff" | stdin_contains file +' + +test_expect_success PERL 'difftool --dir-diff from subdirectory' ' + ( + cd sub && + diff=$(git difftool --dir-diff --extcmd ls branch) && + echo "$diff" | stdin_contains sub && + echo "$diff" | stdin_contains file + ) +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 6379ad60bc..24e9b1974d 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -47,6 +47,13 @@ test_expect_success setup ' echo vvv >t/v && mkdir t/a && echo vvv >t/a/v && + { + echo "line without leading space1" + echo " line with leading space1" + echo " line with leading space2" + echo " line with leading space3" + echo "line without leading space2" + } >space && git add . && test_tick && git commit -m initial @@ -246,6 +253,28 @@ do done cat >expected <<EOF +file +EOF +test_expect_success 'grep -l -C' ' + git grep -l -C1 foo >actual && + test_cmp expected actual +' + +cat >expected <<EOF +file:5 +EOF +test_expect_success 'grep -l -C' ' + git grep -c -C1 foo >actual && + test_cmp expected actual +' + +test_expect_success 'grep -L -C' ' + git ls-files >expected && + git grep -L -C1 nonexistent_string >actual && + test_cmp expected actual +' + +cat >expected <<EOF file:foo mmap bar_mmap EOF @@ -322,6 +351,11 @@ test_expect_success 'grep -f, multiple patterns' ' test_cmp expected actual ' +test_expect_success 'grep, multiple patterns' ' + git grep "$(cat patterns)" >actual && + test_cmp expected actual +' + cat >expected <<EOF file:foo mmap bar file:foo_mmap bar @@ -509,6 +543,34 @@ 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 +' + +cat >expected <<EOF +hello.c= printf("Hello world.\n"); +hello.c: return 0; +hello.c- /* char ?? */ +EOF + +test_expect_success 'grep -W with userdiff' ' + test_when_finished "rm -f .gitattributes" && + git config diff.custom.xfuncname "(printf.*|})$" && + echo "hello.c diff=custom" >.gitattributes && + git grep -W return >actual && + test_cmp expected actual +' + test_expect_success 'grep from a subdirectory to search wider area (1)' ' mkdir -p s && ( @@ -540,7 +602,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 @@ -557,6 +618,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 ) ' @@ -569,6 +647,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 && @@ -577,12 +659,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 ) ' @@ -716,4 +810,115 @@ test_expect_success LIBPCRE 'grep -G -F -E -P pattern' ' 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 +' + +cat >expected <<EOF +space: line with leading space1 +space: line with leading space2 +space: line with leading space3 +EOF + +test_expect_success LIBPCRE 'grep -E "^ "' ' + git grep -E "^ " space >actual && + test_cmp expected actual +' + +test_expect_success LIBPCRE 'grep -P "^ "' ' + git grep -P "^ " space >actual && + test_cmp expected actual +' + test_done diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh index 32ec82ad67..bf6caa4dc3 100755 --- a/t/t8006-blame-textconv.sh +++ b/t/t8006-blame-textconv.sh @@ -10,11 +10,12 @@ find_blame() { cat >helper <<'EOF' #!/bin/sh grep -q '^bin: ' "$1" || { echo "E: $1 is not \"binary\" file" 1>&2; exit 1; } -sed 's/^bin: /converted: /' "$1" +"$PERL_PATH" -p -e 's/^bin: /converted: /' "$1" EOF chmod +x helper test_expect_success 'setup ' ' + echo "bin: test number 0" >zero.bin && echo "bin: test 1" >one.bin && echo "bin: test number 2" >two.bin && if test_have_prereq SYMLINKS; then @@ -43,6 +44,7 @@ test_expect_success 'no filter specified' ' test_expect_success 'setup textconv filters' ' echo "*.bin diff=test" >.gitattributes && + echo "zero.bin eol=crlf" >>.gitattributes && git config diff.test.textconv ./helper && git config diff.test.cachetextconv false ' @@ -74,6 +76,15 @@ test_expect_success 'blame --textconv going through revisions' ' test_cmp expected result ' +test_expect_success 'blame --textconv with local changes' ' + test_when_finished "git checkout zero.bin" && + printf "bin: updated number 0\015" >zero.bin && + git blame --textconv zero.bin >blame && + expect="(Not Committed Yet ....-..-.. ..:..:.. +0000 1)" && + expect="$expect converted: updated number 0" && + expr "$(find_blame <blame)" : "^$expect" +' + test_expect_success 'setup +cachetextconv' ' git config diff.test.cachetextconv true ' 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/t9002-column.sh b/t/t9002-column.sh new file mode 100755 index 0000000000..89983527b6 --- /dev/null +++ b/t/t9002-column.sh @@ -0,0 +1,180 @@ +#!/bin/sh + +test_description='git column' +. ./test-lib.sh + +test_expect_success 'setup' ' + cat >lista <<\EOF +one +two +three +four +five +six +seven +eight +nine +ten +eleven +EOF +' + +test_expect_success 'never' ' + git column --indent=Z --mode=never <lista >actual && + test_cmp lista actual +' + +test_expect_success 'always' ' + cat >expected <<\EOF && +Zone +Ztwo +Zthree +Zfour +Zfive +Zsix +Zseven +Zeight +Znine +Zten +Zeleven +EOF + git column --indent=Z --mode=plain <lista >actual && + test_cmp expected actual +' + +test_expect_success '80 columns' ' + cat >expected <<\EOF && +one two three four five six seven eight nine ten eleven +EOF + COLUMNS=80 git column --mode=column <lista >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +one +two +three +four +five +six +seven +eight +nine +ten +eleven +EOF + +test_expect_success COLUMNS_CAN_BE_1 'COLUMNS = 1' ' + COLUMNS=1 git column --mode=column <lista >actual && + test_cmp expected actual +' + +test_expect_success 'width = 1' ' + git column --mode=column --width=1 <lista >actual && + test_cmp expected actual +' + +COLUMNS=20 +export COLUMNS + +test_expect_success '20 columns' ' + cat >expected <<\EOF && +one seven +two eight +three nine +four ten +five eleven +six +EOF + git column --mode=column <lista >actual && + test_cmp expected actual +' + +test_expect_success '20 columns, nodense' ' + cat >expected <<\EOF && +one seven +two eight +three nine +four ten +five eleven +six +EOF + git column --mode=column,nodense < lista > actual && + test_cmp expected actual +' + +test_expect_success '20 columns, dense' ' + cat >expected <<\EOF && +one five nine +two six ten +three seven eleven +four eight +EOF + git column --mode=column,dense < lista > actual && + test_cmp expected actual +' + +test_expect_success '20 columns, padding 2' ' + cat >expected <<\EOF && +one seven +two eight +three nine +four ten +five eleven +six +EOF + git column --mode=column --padding 2 <lista >actual && + test_cmp expected actual +' + +test_expect_success '20 columns, indented' ' + cat >expected <<\EOF && + one seven + two eight + three nine + four ten + five eleven + six +EOF + git column --mode=column --indent=" " <lista >actual && + test_cmp expected actual +' + +test_expect_success '20 columns, row first' ' + cat >expected <<\EOF && +one two +three four +five six +seven eight +nine ten +eleven +EOF + git column --mode=row <lista >actual && + test_cmp expected actual +' + +test_expect_success '20 columns, row first, nodense' ' + cat >expected <<\EOF && +one two +three four +five six +seven eight +nine ten +eleven +EOF + git column --mode=row,nodense <lista >actual && + test_cmp expected actual +' + +test_expect_success '20 columns, row first, dense' ' + cat >expected <<\EOF && +one two three +four five six +seven eight nine +ten eleven +EOF + git column --mode=row,dense <lista >actual && + test_cmp expected actual +' + +test_done diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh index 6f6175a8f7..b7eed2489f 100755 --- a/t/t9010-svn-fe.sh +++ b/t/t9010-svn-fe.sh @@ -5,8 +5,27 @@ test_description='check svn dumpfile importer' . ./test-lib.sh reinit_git () { + if ! test_declared_prereq PIPE + then + echo >&4 "reinit_git: need to declare PIPE prerequisite" + return 127 + fi rm -fr .git && - git init + rm -f stream backflow && + git init && + mkfifo stream backflow +} + +try_dump () { + input=$1 && + maybe_fail_svnfe=${2:+test_$2} && + maybe_fail_fi=${3:+test_$3} && + + { + $maybe_fail_svnfe test-svn-fe "$input" >stream 3<backflow & + } && + $maybe_fail_fi git fast-import --cat-blob-fd=3 <stream 3>backflow && + wait $! } properties () { @@ -35,21 +54,27 @@ text_no_props () { >empty -test_expect_success 'empty dump' ' +test_expect_success 'setup: have pipes?' ' + rm -f frob && + if mkfifo frob + then + test_set_prereq PIPE + fi +' + +test_expect_success PIPE 'empty dump' ' reinit_git && echo "SVN-fs-dump-format-version: 2" >input && - test-svn-fe input >stream && - git fast-import <stream + try_dump input ' -test_expect_success 'v4 dumps not supported' ' +test_expect_success PIPE 'v4 dumps not supported' ' reinit_git && echo "SVN-fs-dump-format-version: 4" >v4.dump && - test_must_fail test-svn-fe v4.dump >stream && - test_cmp empty stream + try_dump v4.dump must_fail ' -test_expect_failure 'empty revision' ' +test_expect_failure PIPE 'empty revision' ' reinit_git && printf "rev <nobody, nobody@local>: %s\n" "" "" >expect && cat >emptyrev.dump <<-\EOF && @@ -64,13 +89,12 @@ test_expect_failure 'empty revision' ' Content-length: 0 EOF - test-svn-fe emptyrev.dump >stream && - git fast-import <stream && + try_dump emptyrev.dump && git log -p --format="rev <%an, %ae>: %s" HEAD >actual && test_cmp expect actual ' -test_expect_success 'empty properties' ' +test_expect_success PIPE 'empty properties' ' reinit_git && printf "rev <nobody, nobody@local>: %s\n" "" "" >expect && cat >emptyprop.dump <<-\EOF && @@ -88,13 +112,12 @@ test_expect_success 'empty properties' ' PROPS-END EOF - test-svn-fe emptyprop.dump >stream && - git fast-import <stream && + try_dump emptyprop.dump && git log -p --format="rev <%an, %ae>: %s" HEAD >actual && test_cmp expect actual ' -test_expect_success 'author name and commit message' ' +test_expect_success PIPE 'author name and commit message' ' reinit_git && echo "<author@example.com, author@example.com@local>" >expect.author && cat >message <<-\EOF && @@ -121,15 +144,14 @@ test_expect_success 'author name and commit message' ' echo && cat props } >log.dump && - test-svn-fe log.dump >stream && - git fast-import <stream && + try_dump log.dump && 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' ' +test_expect_success PIPE 'unsupported properties are ignored' ' reinit_git && echo author >expect && cat >extraprop.dump <<-\EOF && @@ -149,13 +171,12 @@ test_expect_success 'unsupported properties are ignored' ' author PROPS-END EOF - test-svn-fe extraprop.dump >stream && - git fast-import <stream && + try_dump extraprop.dump && git log -p --format=%an HEAD >actual && test_cmp expect actual ' -test_expect_failure 'timestamp and empty file' ' +test_expect_failure PIPE 'timestamp and empty file' ' echo author@example.com >expect.author && echo 1999-01-01 >expect.date && echo file >expect.files && @@ -186,8 +207,7 @@ test_expect_failure 'timestamp and empty file' ' EOF } >emptyfile.dump && - test-svn-fe emptyfile.dump >stream && - git fast-import <stream && + try_dump emptyfile.dump && 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 && @@ -198,7 +218,7 @@ test_expect_failure 'timestamp and empty file' ' test_cmp empty file ' -test_expect_success 'directory with files' ' +test_expect_success PIPE 'directory with files' ' reinit_git && printf "%s\n" directory/file1 directory/file2 >expect.files && echo hi >hi && @@ -242,8 +262,7 @@ test_expect_success 'directory with files' ' EOF text_no_props hi } >directory.dump && - test-svn-fe directory.dump >stream && - git fast-import <stream && + try_dump directory.dump && git ls-tree -r --name-only HEAD >actual.files && git checkout HEAD directory && @@ -252,7 +271,107 @@ test_expect_success 'directory with files' ' test_cmp hi directory/file2 ' -test_expect_success 'node without action' ' +test_expect_success PIPE 'branch name with backslash' ' + reinit_git && + sort <<-\EOF >expect.branch-files && + trunk/file1 + trunk/file2 + "branches/UpdateFOPto094\\/file1" + "branches/UpdateFOPto094\\/file2" + EOF + + echo hi >hi && + echo hello >hello && + { + properties \ + svn:author author@example.com \ + svn:date "1999-02-02T00:01:02.000000Z" \ + svn:log "add directory with some files in it" && + echo PROPS-END + } >props.setup && + { + properties \ + svn:author brancher@example.com \ + svn:date "2007-12-06T21:38:34.000000Z" \ + svn:log "Updating fop to .94 and adjust fo-stylesheets" && + echo PROPS-END + } >props.branch && + { + cat <<-EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + EOF + echo Prop-content-length: $(wc -c <props.setup) && + echo Content-length: $(wc -c <props.setup) && + echo && + cat props.setup && + cat <<-\EOF && + + Node-path: trunk + Node-kind: dir + Node-action: add + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: branches + Node-kind: dir + Node-action: add + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: trunk/file1 + Node-kind: file + Node-action: add + EOF + text_no_props hello && + cat <<-\EOF && + Node-path: trunk/file2 + Node-kind: file + Node-action: add + EOF + text_no_props hi && + cat <<-\EOF && + + Revision-number: 2 + EOF + echo Prop-content-length: $(wc -c <props.branch) && + echo Content-length: $(wc -c <props.branch) && + echo && + cat props.branch && + cat <<-\EOF + + Node-path: branches/UpdateFOPto094\ + Node-kind: dir + Node-action: add + Node-copyfrom-rev: 1 + Node-copyfrom-path: trunk + + Node-kind: dir + Node-action: add + Prop-content-length: 34 + Content-length: 34 + + K 13 + svn:mergeinfo + V 0 + + PROPS-END + EOF + } >branch.dump && + try_dump branch.dump && + + git ls-tree -r --name-only HEAD | + sort >actual.branch-files && + test_cmp expect.branch-files actual.branch-files +' + +test_expect_success PIPE 'node without action' ' + reinit_git && cat >inaction.dump <<-\EOF && SVN-fs-dump-format-version: 3 @@ -269,10 +388,11 @@ test_expect_success 'node without action' ' PROPS-END EOF - test_must_fail test-svn-fe inaction.dump + try_dump inaction.dump must_fail ' -test_expect_success 'action: add node without text' ' +test_expect_success PIPE 'action: add node without text' ' + reinit_git && cat >textless.dump <<-\EOF && SVN-fs-dump-format-version: 3 @@ -290,10 +410,10 @@ test_expect_success 'action: add node without text' ' PROPS-END EOF - test_must_fail test-svn-fe textless.dump + try_dump textless.dump must_fail ' -test_expect_failure 'change file mode but keep old content' ' +test_expect_failure PIPE 'change file mode but keep old content' ' reinit_git && cat >expect <<-\EOF && OBJID @@ -356,8 +476,7 @@ test_expect_failure 'change file mode but keep old content' ' PROPS-END EOF - test-svn-fe filemode.dump >stream && - git fast-import <stream && + try_dump filemode.dump && { git rev-list HEAD | git diff-tree --root --stdin | @@ -370,7 +489,7 @@ test_expect_failure 'change file mode but keep old content' ' test_cmp hello actual.target ' -test_expect_success 'NUL in property value' ' +test_expect_success PIPE 'NUL in property value' ' reinit_git && echo "commit message" >expect.message && { @@ -391,13 +510,12 @@ test_expect_success 'NUL in property value' ' echo && cat props } >nulprop.dump && - test-svn-fe nulprop.dump >stream && - git fast-import <stream && + try_dump nulprop.dump && 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' ' +test_expect_success PIPE '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 && @@ -458,8 +576,7 @@ test_expect_success 'NUL in log message, file content, and property name' ' link hello EOF } >8bitclean.dump && - test-svn-fe 8bitclean.dump >stream && - git fast-import <stream && + try_dump 8bitclean.dump && { git rev-list HEAD | git diff-tree --root --stdin | @@ -478,7 +595,7 @@ test_expect_success 'NUL in log message, file content, and property name' ' test_cmp expect.hello2 actual.hello2 ' -test_expect_success 'change file mode and reiterate content' ' +test_expect_success PIPE 'change file mode and reiterate content' ' reinit_git && cat >expect <<-\EOF && OBJID @@ -490,7 +607,7 @@ test_expect_success 'change file mode and reiterate content' ' EOF echo "link hello" >expect.blob && echo hello >hello && - cat >filemode.dump <<-\EOF && + cat >filemode2.dump <<-\EOF && SVN-fs-dump-format-version: 3 Revision-number: 1 @@ -545,8 +662,7 @@ test_expect_success 'change file mode and reiterate content' ' PROPS-END link hello EOF - test-svn-fe filemode.dump >stream && - git fast-import <stream && + try_dump filemode2.dump && { git rev-list HEAD | git diff-tree --root --stdin | @@ -559,7 +675,8 @@ test_expect_success 'change file mode and reiterate content' ' test_cmp hello actual.target ' -test_expect_success 'deltas not supported' ' +test_expect_success PIPE 'deltas supported' ' + reinit_git && { # (old) h + (inline) ello + (old) \n printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" | @@ -619,10 +736,10 @@ test_expect_success 'deltas not supported' ' echo PROPS-END && cat delta } >delta.dump && - test_must_fail test-svn-fe delta.dump + try_dump delta.dump ' -test_expect_success 'property deltas supported' ' +test_expect_success PIPE 'property deltas supported' ' reinit_git && cat >expect <<-\EOF && OBJID @@ -678,8 +795,7 @@ test_expect_success 'property deltas supported' ' PROPS-END EOF } >propdelta.dump && - test-svn-fe propdelta.dump >stream && - git fast-import <stream && + try_dump propdelta.dump && { git rev-list HEAD | git diff-tree --stdin | @@ -688,7 +804,7 @@ test_expect_success 'property deltas supported' ' test_cmp expect actual ' -test_expect_success 'properties on /' ' +test_expect_success PIPE 'properties on /' ' reinit_git && cat <<-\EOF >expect && OBJID @@ -733,8 +849,7 @@ test_expect_success 'properties on /' ' PROPS-END EOF - test-svn-fe changeroot.dump >stream && - git fast-import <stream && + try_dump changeroot.dump && { git rev-list HEAD | git diff-tree --root --always --stdin | @@ -743,7 +858,7 @@ test_expect_success 'properties on /' ' test_cmp expect actual ' -test_expect_success 'deltas for typechange' ' +test_expect_success PIPE 'deltas for typechange' ' reinit_git && cat >expect <<-\EOF && OBJID @@ -819,8 +934,7 @@ test_expect_success 'deltas for typechange' ' PROPS-END link testing 321 EOF - test-svn-fe deleteprop.dump >stream && - git fast-import <stream && + try_dump deleteprop.dump && { git rev-list HEAD | git diff-tree --root --stdin | @@ -829,6 +943,143 @@ test_expect_success 'deltas for typechange' ' test_cmp expect actual ' +test_expect_success PIPE 'deltas need not consume the whole preimage' ' + reinit_git && + cat >expect <<-\EOF && + OBJID + :120000 100644 OBJID OBJID T postimage + OBJID + :100644 120000 OBJID OBJID T postimage + OBJID + :000000 100644 OBJID OBJID A postimage + EOF + echo "first preimage" >expect.1 && + printf target >expect.2 && + printf lnk >expect.3 && + { + printf "SVNQ%b%b%b" "QQ\017\001\017" "\0217" "first preimage\n" | + q_to_nul + } >delta.1 && + { + properties svn:special "*" && + echo PROPS-END + } >symlink.props && + { + printf "SVNQ%b%b%b" "Q\002\013\004\012" "\0201\001\001\0211" "lnk target" | + q_to_nul + } >delta.2 && + { + printf "SVNQ%b%b" "Q\004\003\004Q" "\001Q\002\002" | + q_to_nul + } >delta.3 && + { + cat <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: postimage + Node-kind: file + Node-action: add + Text-delta: true + Prop-content-length: 10 + EOF + echo Text-content-length: $(wc -c <delta.1) && + echo Content-length: $((10 + $(wc -c <delta.1))) && + echo && + echo PROPS-END && + cat delta.1 && + cat <<-\EOF && + + Revision-number: 2 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: postimage + Node-kind: file + Node-action: change + Text-delta: true + EOF + echo Prop-content-length: $(wc -c <symlink.props) && + echo Text-content-length: $(wc -c <delta.2) && + echo Content-length: $(($(wc -c <symlink.props) + $(wc -c <delta.2))) && + echo && + cat symlink.props && + cat delta.2 && + cat <<-\EOF && + + Revision-number: 3 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: postimage + Node-kind: file + Node-action: change + Text-delta: true + Prop-content-length: 10 + EOF + echo Text-content-length: $(wc -c <delta.3) && + echo Content-length: $((10 + $(wc -c <delta.3))) && + echo && + echo PROPS-END && + cat delta.3 && + echo + } >deltapartial.dump && + try_dump deltapartial.dump && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$_x40/OBJID/g" + } >actual && + test_cmp expect actual && + git show HEAD:postimage >actual.3 && + git show HEAD^:postimage >actual.2 && + git show HEAD^^:postimage >actual.1 && + test_cmp expect.1 actual.1 && + test_cmp expect.2 actual.2 && + test_cmp expect.3 actual.3 +' + +test_expect_success PIPE 'no hang for delta trying to read past end of preimage' ' + reinit_git && + { + # COPY 1 + printf "SVNQ%b%b" "Q\001\001\002Q" "\001Q" | + q_to_nul + } >greedy.delta && + { + cat <<-\EOF && + SVN-fs-dump-format-version: 3 + + Revision-number: 1 + Prop-content-length: 10 + Content-length: 10 + + PROPS-END + + Node-path: bootstrap + Node-kind: file + Node-action: add + Text-delta: true + Prop-content-length: 10 + EOF + echo Text-content-length: $(wc -c <greedy.delta) && + echo Content-length: $((10 + $(wc -c <greedy.delta))) && + echo && + echo PROPS-END && + cat greedy.delta && + echo + } >greedydelta.dump && + try_dump greedydelta.dump must_fail might_fail +' test_expect_success 'set up svn repo' ' svnconf=$PWD/svnconf && @@ -844,12 +1095,12 @@ test_expect_success 'set up svn repo' ' fi ' -test_expect_success SVNREPO 't9135/svn.dump' ' - git init simple-git && - test-svn-fe "$TEST_DIRECTORY/t9135/svn.dump" >simple.fe && +test_expect_success SVNREPO,PIPE 't9135/svn.dump' ' + mkdir -p simple-git && ( cd simple-git && - git fast-import <../simple.fe + reinit_git && + try_dump "$TEST_DIRECTORY/t9135/svn.dump" ) && ( cd simple-svnco && diff --git a/t/t9011-svn-da.sh b/t/t9011-svn-da.sh new file mode 100755 index 0000000000..b38d16f9db --- /dev/null +++ b/t/t9011-svn-da.sh @@ -0,0 +1,248 @@ +#!/bin/sh + +test_description='test parsing of svndiff0 files + +Using the "test-svn-fe -d" helper, check that svn-fe correctly +interprets deltas using various facilities (some from the spec, +some only learned from practice). +' +. ./test-lib.sh + +>empty +printf foo >preimage + +test_expect_success 'reject empty delta' ' + test_must_fail test-svn-fe -d preimage empty 0 +' + +test_expect_success 'delta can empty file' ' + printf "SVNQ" | q_to_nul >clear.delta && + test-svn-fe -d preimage clear.delta 4 >actual && + test_cmp empty actual +' + +test_expect_success 'reject svndiff2' ' + printf "SVN\002" >bad.filetype && + test_must_fail test-svn-fe -d preimage bad.filetype 4 +' + +test_expect_success 'one-window empty delta' ' + printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && + test-svn-fe -d preimage clear.onewindow 9 >actual && + test_cmp empty actual +' + +test_expect_success 'reject incomplete window header' ' + printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && + printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow && + test_must_fail test-svn-fe -d preimage clear.onewindow 6 && + test_must_fail test-svn-fe -d preimage clear.partialwindow 6 +' + +test_expect_success 'reject declared delta longer than actual delta' ' + printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && + printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow && + test_must_fail test-svn-fe -d preimage clear.onewindow 14 && + test_must_fail test-svn-fe -d preimage clear.partialwindow 9 +' + +test_expect_success 'two-window empty delta' ' + printf "SVNQ%s%s" "QQQQQ" "QQQQQ" | q_to_nul >clear.twowindow && + test-svn-fe -d preimage clear.twowindow 14 >actual && + test_must_fail test-svn-fe -d preimage clear.twowindow 13 && + test_cmp empty actual +' + +test_expect_success 'noisy zeroes' ' + printf "SVNQ%s" \ + "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQQQQQ" | + tr R "\200" | + q_to_nul >clear.noisy && + len=$(wc -c <clear.noisy) && + test-svn-fe -d preimage clear.noisy $len && + test_cmp empty actual +' + +test_expect_success 'reject variable-length int in magic' ' + printf "SVNRQ" | tr R "\200" | q_to_nul >clear.badmagic && + test_must_fail test-svn-fe -d preimage clear.badmagic 5 +' + +test_expect_success 'reject truncated integer' ' + printf "SVNQ%s%s" "QQQQQ" "QQQQRRQ" | + tr R "\200" | + q_to_nul >clear.fullint && + printf "SVNQ%s%s" "QQQQQ" "QQQQRR" | + tr RT "\201" | + q_to_nul >clear.partialint && + test_must_fail test-svn-fe -d preimage clear.fullint 15 && + test-svn-fe -d preimage clear.fullint 16 && + test_must_fail test-svn-fe -d preimage clear.partialint 15 +' + +test_expect_success 'nonempty (but unused) preimage view' ' + printf "SVNQ%b" "Q\003QQQ" | q_to_nul >clear.readpreimage && + test-svn-fe -d preimage clear.readpreimage 9 >actual && + test_cmp empty actual +' + +test_expect_success 'preimage view: right endpoint cannot backtrack' ' + printf "SVNQ%b%b" "Q\003QQQ" "Q\002QQQ" | + q_to_nul >clear.backtrack && + test_must_fail test-svn-fe -d preimage clear.backtrack 14 +' + +test_expect_success 'preimage view: left endpoint can advance' ' + printf "SVNQ%b%b" "Q\003QQQ" "\001\002QQQ" | + q_to_nul >clear.preshrink && + printf "SVNQ%b%b" "Q\003QQQ" "\001\001QQQ" | + q_to_nul >clear.shrinkbacktrack && + test-svn-fe -d preimage clear.preshrink 14 >actual && + test_must_fail test-svn-fe -d preimage clear.shrinkbacktrack 14 && + test_cmp empty actual +' + +test_expect_success 'preimage view: offsets compared by value' ' + printf "SVNQ%b%b" "\001\001QQQ" "\0200Q\003QQQ" | + q_to_nul >clear.noisybacktrack && + printf "SVNQ%b%b" "\001\001QQQ" "\0200\001\002QQQ" | + q_to_nul >clear.noisyadvance && + test_must_fail test-svn-fe -d preimage clear.noisybacktrack 15 && + test-svn-fe -d preimage clear.noisyadvance 15 && + test_cmp empty actual +' + +test_expect_success 'preimage view: reject truncated preimage' ' + printf "SVNQ%b" "\010QQQQ" | q_to_nul >clear.lateemptyread && + printf "SVNQ%b" "\010\001QQQ" | q_to_nul >clear.latenonemptyread && + printf "SVNQ%b" "\001\010QQQ" | q_to_nul >clear.longread && + test_must_fail test-svn-fe -d preimage clear.lateemptyread 9 && + test_must_fail test-svn-fe -d preimage clear.latenonemptyread 9 && + test_must_fail test-svn-fe -d preimage clear.longread 9 +' + +test_expect_success 'forbid unconsumed inline data' ' + printf "SVNQ%b%s%b%s" "QQQQ\003" "bar" "QQQQ\001" "x" | + q_to_nul >inline.clear && + test_must_fail test-svn-fe -d preimage inline.clear 18 >actual +' + +test_expect_success 'reject truncated inline data' ' + printf "SVNQ%b%s" "QQQQ\003" "b" | q_to_nul >inline.trunc && + test_must_fail test-svn-fe -d preimage inline.trunc 10 +' + +test_expect_success 'reject truncated inline data (after instruction section)' ' + printf "SVNQ%b%b%s" "QQ\001\001\003" "\0201" "b" | q_to_nul >insn.trunc && + test_must_fail test-svn-fe -d preimage insn.trunc 11 +' + +test_expect_success 'copyfrom_data' ' + echo hi >expect && + printf "SVNQ%b%b%b" "QQ\003\001\003" "\0203" "hi\n" | q_to_nul >copydat && + test-svn-fe -d preimage copydat 13 >actual && + test_cmp expect actual +' + +test_expect_success 'multiple copyfrom_data' ' + echo hi >expect && + printf "SVNQ%b%b%b%b%b" "QQ\003\002\003" "\0201\0202" "hi\n" \ + "QQQ\002Q" "\0200Q" | q_to_nul >copy.multi && + len=$(wc -c <copy.multi) && + test-svn-fe -d preimage copy.multi $len >actual && + test_cmp expect actual +' + +test_expect_success 'incomplete multiple insn' ' + printf "SVNQ%b%b%b" "QQ\003\002\003" "\0203\0200" "hi\n" | + q_to_nul >copy.partial && + len=$(wc -c <copy.partial) && + test_must_fail test-svn-fe -d preimage copy.partial $len +' + +test_expect_success 'catch attempt to copy missing data' ' + printf "SVNQ%b%b%s%b%s" "QQ\002\002\001" "\0201\0201" "X" \ + "QQQQ\002" "YZ" | + q_to_nul >copy.incomplete && + len=$(wc -c <copy.incomplete) && + test_must_fail test-svn-fe -d preimage copy.incomplete $len +' + +test_expect_success 'copyfrom target to repeat data' ' + printf foofoo >expect && + printf "SVNQ%b%b%s" "QQ\006\004\003" "\0203\0100\003Q" "foo" | + q_to_nul >copytarget.repeat && + len=$(wc -c <copytarget.repeat) && + test-svn-fe -d preimage copytarget.repeat $len >actual && + test_cmp expect actual +' + +test_expect_success 'copyfrom target out of order' ' + printf foooof >expect && + printf "SVNQ%b%b%s" \ + "QQ\006\007\003" "\0203\0101\002\0101\001\0101Q" "foo" | + q_to_nul >copytarget.reverse && + len=$(wc -c <copytarget.reverse) && + test-svn-fe -d preimage copytarget.reverse $len >actual && + test_cmp expect actual +' + +test_expect_success 'catch copyfrom future' ' + printf "SVNQ%b%b%s" "QQ\004\004\003" "\0202\0101\002\0201" "XYZ" | + q_to_nul >copytarget.infuture && + len=$(wc -c <copytarget.infuture) && + test_must_fail test-svn-fe -d preimage copytarget.infuture $len +' + +test_expect_success 'copy to sustain' ' + printf XYXYXYXYXYXZ >expect && + printf "SVNQ%b%b%s" "QQ\014\004\003" "\0202\0111Q\0201" "XYZ" | + q_to_nul >copytarget.sustain && + len=$(wc -c <copytarget.sustain) && + test-svn-fe -d preimage copytarget.sustain $len >actual && + test_cmp expect actual +' + +test_expect_success 'catch copy that overflows' ' + printf "SVNQ%b%b%s" "QQ\003\003\001" "\0201\0177Q" X | + q_to_nul >copytarget.overflow && + len=$(wc -c <copytarget.overflow) && + test_must_fail test-svn-fe -d preimage copytarget.overflow $len +' + +test_expect_success 'copyfrom source' ' + printf foo >expect && + printf "SVNQ%b%b" "Q\003\003\002Q" "\003Q" | q_to_nul >copysource.all && + test-svn-fe -d preimage copysource.all 11 >actual && + test_cmp expect actual +' + +test_expect_success 'copy backwards' ' + printf oof >expect && + printf "SVNQ%b%b" "Q\003\003\006Q" "\001\002\001\001\001Q" | + q_to_nul >copysource.rev && + test-svn-fe -d preimage copysource.rev 15 >actual && + test_cmp expect actual +' + +test_expect_success 'offsets are relative to window' ' + printf fo >expect && + printf "SVNQ%b%b%b%b" "Q\003\001\002Q" "\001Q" \ + "\002\001\001\002Q" "\001Q" | + q_to_nul >copysource.two && + test-svn-fe -d preimage copysource.two 18 >actual && + test_cmp expect actual +' + +test_expect_success 'example from notes/svndiff' ' + printf aaaaccccdddddddd >expect && + printf aaaabbbbcccc >source && + printf "SVNQ%b%b%s" "Q\014\020\007\001" \ + "\004Q\004\010\0201\0107\010" d | + q_to_nul >delta.example && + len=$(wc -c <delta.example) && + test-svn-fe -d source delta.example $len >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index b041516a1d..749b75e8d4 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -65,7 +65,8 @@ test_expect_success "$name" " git update-index --add dir/file/file && git commit -m '$name' && test_must_fail git svn set-tree --find-copies-harder --rmdir \ - ${remotes_git_svn}..mybranch" || true + ${remotes_git_svn}..mybranch +" name='detect node change from directory to file #1' @@ -79,7 +80,8 @@ test_expect_success "$name" ' git update-index --add -- bar && git commit -m "$name" && test_must_fail git svn set-tree --find-copies-harder --rmdir \ - ${remotes_git_svn}..mybranch2' || true + ${remotes_git_svn}..mybranch2 +' name='detect node change from file to directory #2' @@ -92,9 +94,12 @@ test_expect_success "$name" ' echo yyy > bar/zzz/yyy && git update-index --add bar/zzz/yyy && git commit -m "$name" && - test_must_fail git svn set-tree --find-copies-harder --rmdir \ - ${remotes_git_svn}..mybranch3' || true - + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch3 && + svn_cmd up "$SVN_TREE" && + test -d "$SVN_TREE"/bar/zzz && + test -e "$SVN_TREE"/bar/zzz/yyy +' name='detect node change from directory to file #2' test_expect_success "$name" ' @@ -107,7 +112,8 @@ test_expect_success "$name" ' git update-index --add -- dir && git commit -m "$name" && test_must_fail git svn set-tree --find-copies-harder --rmdir \ - ${remotes_git_svn}..mybranch4' || true + ${remotes_git_svn}..mybranch4 +' name='remove executable bit from a file' @@ -134,10 +140,10 @@ test_expect_success "$name" ' test -x "$SVN_TREE"/exec.sh' -name='executable file becomes a symlink to bar/zzz (file)' +name='executable file becomes a symlink to file' test_expect_success "$name" ' rm exec.sh && - ln -s bar/zzz exec.sh && + ln -s file exec.sh && git update-index exec.sh && git commit -m "$name" && git svn set-tree --find-copies-harder --rmdir \ @@ -148,19 +154,19 @@ test_expect_success "$name" ' name='new symlink is added to a file that was also just made executable' test_expect_success "$name" ' - chmod +x bar/zzz && - ln -s bar/zzz exec-2.sh && - git update-index --add bar/zzz exec-2.sh && + chmod +x file && + ln -s file exec-2.sh && + git update-index --add file exec-2.sh && git commit -m "$name" && git svn set-tree --find-copies-harder --rmdir \ ${remotes_git_svn}..mybranch5 && svn_cmd up "$SVN_TREE" && - test -x "$SVN_TREE"/bar/zzz && + test -x "$SVN_TREE"/file && test -h "$SVN_TREE"/exec-2.sh' name='modify a symlink to become a file' test_expect_success "$name" ' - echo git help > help || true && + echo git help >help && rm exec-2.sh && cp help exec-2.sh && git update-index exec-2.sh && @@ -195,14 +201,15 @@ name='check imported tree checksums expected tree checksums' rm -f expected if test_have_prereq UTF8 then - echo tree bf522353586b1b883488f2bc73dab0d9f774b9a9 > expected + echo tree dc68b14b733e4ec85b04ab6f712340edc5dc936e > expected fi cat >> expected <<\EOF -tree 83654bb36f019ae4fe77a0171f81075972087624 -tree 031b8d557afc6fea52894eaebb45bec52f1ba6d1 -tree 0b094cbff17168f24c302e297f55bfac65eb8bd3 -tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e -tree 56a30b966619b863674f5978696f4a3594f2fca9 +tree c3322890dcf74901f32d216f05c5044f670ce632 +tree d3ccd5035feafd17b030c5732e7808cc49122853 +tree d03e1630363d4881e68929d532746b20b0986b83 +tree 149d63cd5878155c846e8c55d7d8487de283f89e +tree 312b76e4f64ce14893aeac8591eb3960b065e247 +tree 149d63cd5878155c846e8c55d7d8487de283f89e tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4 EOF diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh index 8cfdfe790f..9a40f1e199 100755 --- a/t/t9129-git-svn-i18n-commitencoding.sh +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -29,7 +29,7 @@ fi compare_svn_head_with () { # extract just the log message and strip out committer info. # don't use --limit here since svn 1.1.x doesn't have it, - LC_ALL="$a_utf8_locale" svn log `git svn info --url` | perl -w -e ' + LC_ALL="$a_utf8_locale" svn log `git svn info --url` | "$PERL_PATH" -w -e ' use bytes; $/ = ("-"x72) . "\n"; my @x = <STDIN>; diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh index b324c491c5..c3443ceb25 100755 --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@ -96,8 +96,8 @@ 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_DIR && - unset GIT_CONFIG && + sane_unset GIT_DIR && + sane_unset GIT_CONFIG && git config --global \ svn.authorsfile "$HOME"/svn-authors && test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" && diff --git a/t/t9137-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh index d60da63f7a..c17aa3186f 100755 --- a/t/t9137-git-svn-dcommit-clobber-series.sh +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -20,8 +20,8 @@ test_expect_success '(supposedly) non-conflicting change from SVN' ' test x"`sed -n -e 61p < file`" = x61 && svn_cmd co "$svnrepo" tmp && (cd tmp && - perl -i.bak -p -e "s/^58$/5588/" file && - perl -i.bak -p -e "s/^61$/6611/" file && + "$PERL_PATH" -i.bak -p -e "s/^58$/5588/" file && + "$PERL_PATH" -i.bak -p -e "s/^61$/6611/" file && poke file && test x"`sed -n -e 58p < file`" = x5588 && test x"`sed -n -e 61p < file`" = x6611 && @@ -40,8 +40,8 @@ test_expect_success 'some unrelated changes to git' " test_expect_success 'change file but in unrelated area' " test x\"\`sed -n -e 4p < file\`\" = x4 && test x\"\`sed -n -e 7p < file\`\" = x7 && - perl -i.bak -p -e 's/^4\$/4444/' file && - perl -i.bak -p -e 's/^7\$/7777/' file && + "$PERL_PATH" -i.bak -p -e 's/^4\$/4444/' file && + "$PERL_PATH" -i.bak -p -e 's/^7\$/7777/' file && test x\"\`sed -n -e 4p < file\`\" = x4444 && test x\"\`sed -n -e 7p < file\`\" = x7777 && git commit -m '4 => 4444, 7 => 7777' file && diff --git a/t/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..b59be9a894 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -19,9 +19,9 @@ then test_done fi -CVSROOT=$(pwd)/cvsroot -CVSWORK=$(pwd)/cvswork -GIT_DIR=$(pwd)/.git +CVSROOT=$PWD/cvsroot +CVSWORK=$PWD/cvswork +GIT_DIR=$PWD/.git export CVSROOT CVSWORK GIT_DIR rm -rf "$CVSROOT" "$CVSWORK" @@ -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) && @@ -321,7 +321,7 @@ test_expect_success 'use the same checkout for Git and CVS' ' (mkdir shared && cd shared && - unset GIT_DIR && + sane_unset GIT_DIR && cvs co . && git init && git add " space" && diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 2a53640c5b..2fcf269469 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -12,7 +12,7 @@ test_description='test git fast-import utility' # This could be written as "head -c $1", but IRIX "head" does not # support the -c option. head_c () { - perl -e ' + "$PERL_PATH" -e ' my $len = $ARGV[1]; while ($len > 0) { my $s; @@ -24,6 +24,13 @@ head_c () { ' - "$1" } +verify_packs () { + for p in .git/objects/pack/*.pack + do + git verify-pack "$@" "$p" || return + done +} + file2_data='file2 second line of EOF' @@ -94,14 +101,21 @@ 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' \ 'git fast-import --export-marks=marks.out <input && git whatchanged master' -test_expect_success \ - 'A: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'A: verify pack' ' + verify_packs +' cat >expect <<EOF author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -152,6 +166,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` @@ -170,6 +196,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 @@ -185,9 +260,11 @@ test_expect_success \ 'A: verify marks import does not crash' \ 'git fast-import --import-marks=marks.out <input && git whatchanged verify--import-marks' -test_expect_success \ - 'A: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'A: verify pack' ' + verify_packs +' + cat >expect <<EOF :000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A copy-of-file2 EOF @@ -324,6 +401,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 ### @@ -348,9 +524,11 @@ test_expect_success \ 'C: incremental import create pack from stdin' \ 'git fast-import <input && git whatchanged branch' -test_expect_success \ - 'C: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'C: verify pack' ' + verify_packs +' + test_expect_success \ 'C: validate reuse existing blob' \ 'test $newf = `git rev-parse --verify branch:file2/newf` && @@ -406,9 +584,10 @@ test_expect_success \ 'D: inline data in commit' \ 'git fast-import <input && git whatchanged branch' -test_expect_success \ - 'D: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'D: verify pack' ' + verify_packs +' cat >expect <<EOF :000000 100755 0000000000000000000000000000000000000000 35a59026a33beac1569b1c7f66f3090ce9c09afc A newdir/exec.sh @@ -452,9 +631,10 @@ test_expect_success 'E: rfc2822 date, --date-format=raw' ' test_expect_success \ 'E: rfc2822 date, --date-format=rfc2822' \ 'git fast-import --date-format=rfc2822 <input' -test_expect_success \ - 'E: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'E: verify pack' ' + verify_packs +' cat >expect <<EOF author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500 @@ -503,9 +683,10 @@ test_expect_success \ fi fi ' -test_expect_success \ - 'F: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'F: verify pack' ' + verify_packs +' cat >expect <<EOF tree `git rev-parse branch~1^{tree}` @@ -539,9 +720,11 @@ INPUT_END test_expect_success \ 'G: non-fast-forward update forced' \ 'git fast-import --force <input' -test_expect_success \ - 'G: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'G: verify pack' ' + verify_packs +' + test_expect_success \ 'G: branch changed, but logged' \ 'test $old_branch != `git rev-parse --verify branch^0` && @@ -576,9 +759,10 @@ test_expect_success \ 'H: deletall, add 1' \ 'git fast-import <input && git whatchanged H' -test_expect_success \ - 'H: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'H: verify pack' ' + verify_packs +' cat >expect <<EOF :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf @@ -654,6 +838,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 ### @@ -734,6 +930,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 ### @@ -1088,6 +1325,45 @@ test_expect_success \ INPUT_END' test_expect_success \ + 'N: reject foo/ syntax in copy source' \ + 'test_must_fail git fast-import <<-INPUT_END + commit refs/heads/N5C + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy with invalid syntax + COMMIT + + from refs/heads/branch^0 + C file2/ file3 + INPUT_END' + +test_expect_success \ + 'N: reject foo/ syntax in rename source' \ + 'test_must_fail git fast-import <<-INPUT_END + commit refs/heads/N5D + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + rename with invalid syntax + COMMIT + + from refs/heads/branch^0 + R file2/ file3 + INPUT_END' + +test_expect_success \ + 'N: reject foo/ syntax in ls argument' \ + 'test_must_fail git fast-import <<-INPUT_END + commit refs/heads/N5E + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy with invalid syntax + COMMIT + + from refs/heads/branch^0 + ls "file2/" + INPUT_END' + +test_expect_success \ 'N: copy to root by id and modify' \ 'echo "hello, world" >expect.foo && echo hello >expect.bar && @@ -1381,7 +1657,7 @@ M 160000 :6 sub INPUT_END test_expect_success \ - 'P: supermodule & submodule mix' \ + 'P: superproject & submodule mix' \ 'git fast-import <input && git checkout subuse1 && rm -rf sub && mkdir sub && (cd sub && @@ -1599,9 +1875,10 @@ test_expect_success \ 'Q: commit notes' \ 'git fast-import <input && git whatchanged notes-test' -test_expect_success \ - 'Q: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +test_expect_success 'Q: verify pack' ' + verify_packs +' commit1=$(git rev-parse notes-test~2) commit2=$(git rev-parse notes-test^) @@ -1768,6 +2045,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) ### @@ -1823,7 +2117,7 @@ test_expect_success \ grep :1 git.marks' test_expect_success \ - 'R: export-marks options can be overriden by commandline options' \ + 'R: export-marks options can be overridden by commandline options' \ 'cat input | git fast-import --export-marks=other.marks && grep :1 other.marks' @@ -1882,6 +2176,53 @@ test_expect_success 'R: --import-marks-if-exists' ' 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 @@ -1954,7 +2295,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 @@ -1966,7 +2307,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 && @@ -1987,7 +2328,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 @@ -2005,7 +2346,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 @@ -2197,6 +2538,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 @@ -2252,13 +2635,14 @@ test_expect_success \ 'R: blob bigger than threshold' \ 'test_create_repo R && git --git-dir=R/.git fast-import --big-file-threshold=1 <input' -test_expect_success \ - 'R: verify created pack' \ - ': >verify && - for p in R/.git/objects/pack/*.pack; - do - git verify-pack -v $p >>verify || exit; - done' + +test_expect_success 'R: verify created pack' ' + ( + cd R && + verify_packs -v > ../verify + ) +' + test_expect_success \ 'R: verify written objects' \ 'git --git-dir=R/.git cat-file blob big-file:big1 >actual && @@ -2271,4 +2655,291 @@ test_expect_success \ 'n=$(grep $a verify | wc -l) && test 1 = $n' +### +### series S +### +# +# Make sure missing spaces and EOLs after mark references +# cause errors. +# +# Setup: +# +# 1--2--4 +# \ / +# -3- +# +# commit marks: 301, 302, 303, 304 +# blob marks: 403, 404, resp. +# note mark: 202 +# +# The error message when a space is missing not at the +# end of the line is: +# +# Missing space after .. +# +# or when extra characters come after the mark at the end +# of the line: +# +# Garbage after .. +# +# or when the dataref is neither "inline " or a known SHA1, +# +# Invalid dataref .. +# +test_tick + +cat >input <<INPUT_END +commit refs/heads/S +mark :301 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit 1 +COMMIT +M 100644 inline hello.c +data <<BLOB +blob 1 +BLOB + +commit refs/heads/S +mark :302 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit 2 +COMMIT +from :301 +M 100644 inline hello.c +data <<BLOB +blob 2 +BLOB + +blob +mark :403 +data <<BLOB +blob 3 +BLOB + +blob +mark :202 +data <<BLOB +note 2 +BLOB +INPUT_END + +test_expect_success 'S: initialize for S tests' ' + git fast-import --export-marks=marks <input +' + +# +# filemodify, three datarefs +# +test_expect_success 'S: filemodify with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit N + COMMIT + M 100644 :403x hello.c + EOF + cat err && + test_i18ngrep "space after mark" err +' + +# inline is misspelled; fast-import thinks it is some unknown dataref +test_expect_success 'S: filemodify with garbage after inline must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit N + COMMIT + M 100644 inlineX hello.c + data <<BLOB + inline + BLOB + EOF + cat err && + test_i18ngrep "nvalid dataref" err +' + +test_expect_success 'S: filemodify with garbage after sha1 must fail' ' + sha1=$(grep :403 marks | cut -d\ -f2) && + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit N + COMMIT + M 100644 ${sha1}x hello.c + EOF + cat err && + test_i18ngrep "space after SHA1" err +' + +# +# notemodify, three ways to say dataref +# +test_expect_success 'S: notemodify with garabge after mark dataref must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit S note dataref markref + COMMIT + N :202x :302 + EOF + cat err && + test_i18ngrep "space after mark" err +' + +test_expect_success 'S: notemodify with garbage after inline dataref must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit S note dataref inline + COMMIT + N inlineX :302 + data <<BLOB + note blob + BLOB + EOF + cat err && + test_i18ngrep "nvalid dataref" err +' + +test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' ' + sha1=$(grep :202 marks | cut -d\ -f2) && + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit S note dataref sha1 + COMMIT + N ${sha1}x :302 + EOF + cat err && + test_i18ngrep "space after SHA1" err +' + +# +# notemodify, mark in committish +# +test_expect_success 'S: notemodify with garbarge after mark committish must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/Snotes + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit S note committish + COMMIT + N :202 :302x + EOF + cat err && + test_i18ngrep "after mark" err +' + +# +# from +# +test_expect_success 'S: from with garbage after mark must fail' ' + # no && + git fast-import --import-marks=marks --export-marks=marks <<-EOF 2>err + commit refs/heads/S2 + mark :303 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit 3 + COMMIT + from :301x + M 100644 :403 hello.c + EOF + + ret=$? && + echo returned $ret && + test $ret -ne 0 && # failed, but it created the commit + + # go create the commit, need it for merge test + git fast-import --import-marks=marks --export-marks=marks <<-EOF && + commit refs/heads/S2 + mark :303 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit 3 + COMMIT + from :301 + M 100644 :403 hello.c + EOF + + # now evaluate the error + cat err && + test_i18ngrep "after mark" err +' + + +# +# merge +# +test_expect_success 'S: merge with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + commit refs/heads/S + mark :304 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + merge 4 + COMMIT + from :302 + merge :303x + M 100644 :403 hello.c + EOF + cat err && + test_i18ngrep "after mark" err +' + +# +# tag, from markref +# +test_expect_success 'S: tag with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + tag refs/tags/Stag + from :302x + tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<TAG + tag S + TAG + EOF + cat err && + test_i18ngrep "after mark" err +' + +# +# cat-blob markref +# +test_expect_success 'S: cat-blob with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + cat-blob :403x + EOF + cat err && + test_i18ngrep "after mark" err +' + +# +# ls markref +# +test_expect_success 'S: ls with garbage after mark must fail' ' + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + ls :302x hello.c + EOF + cat err && + test_i18ngrep "space after mark" err +' + +test_expect_success 'S: ls with garbage after sha1 must fail' ' + sha1=$(grep :302 marks | cut -d\ -f2) && + test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && + ls ${sha1}x hello.c + EOF + cat err && + test_i18ngrep "space after tree-ish" err +' + test_done diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index 463254c727..83acf68bc3 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -505,9 +505,63 @@ test_expect_success 'verify that non-notes are untouched by a fanout change' ' test_cmp expect_non-note3 actual ' + +# Change the notes for the three top commits +test_tick +cat >input <<INPUT_END +commit refs/notes/many_notes +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +changing notes for the top three commits +COMMIT +from refs/notes/many_notes^0 +INPUT_END + +rm expect +i=$num_commits +j=0 +while test $j -lt 3 +do + cat >>input <<INPUT_END +N inline refs/heads/many_commits~$j +data <<EOF +changed note for commit #$i +EOF +INPUT_END + cat >>expect <<EXPECT_END + commit #$i + changed note for commit #$i +EXPECT_END + i=$(($i - 1)) + j=$(($j + 1)) +done + +test_expect_success 'change a few existing notes' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/many_notes git log -n3 refs/heads/many_commits | + grep "^ " > actual && + test_cmp expect actual + +' + +test_expect_success 'verify that changing notes respect existing fanout' ' + + # None of the entries in the top-level notes tree should be a full SHA1 + git ls-tree --name-only refs/notes/many_notes | + while read path + do + if test $(expr length "$path") -ge 40 + then + return 1 + fi + done + +' + remaining_notes=10 test_tick -cat >>input <<INPUT_END +cat >input <<INPUT_END commit refs/notes/many_notes committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE data <<COMMIT @@ -516,12 +570,11 @@ COMMIT from refs/notes/many_notes^0 INPUT_END -i=$remaining_notes -while test $i -lt $num_commits +i=$(($num_commits - $remaining_notes)) +for sha1 in $(git rev-list -n $i refs/heads/many_commits) do - i=$(($i + 1)) cat >>input <<INPUT_END -N 0000000000000000000000000000000000000000 :$i +N 0000000000000000000000000000000000000000 $sha1 INPUT_END done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index f823c05305..3e821f958b 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -86,7 +86,7 @@ test_expect_success 'import/export-marks' ' git checkout -b marks master && git fast-export --export-marks=tmp-marks HEAD && test -s tmp-marks && - test $(wc -l < tmp-marks) -eq 3 && + test_line_count = 3 tmp-marks && test $( git fast-export --import-marks=tmp-marks\ --export-marks=tmp-marks HEAD | @@ -101,7 +101,7 @@ test_expect_success 'import/export-marks' ' grep ^commit\ | wc -l) \ -eq 1 && - test $(wc -l < tmp-marks) -eq 4 + test_line_count = 4 tmp-marks ' @@ -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_PATH" -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 -M 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/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 9199550ef4..806623e885 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -476,14 +476,14 @@ test_expect_success 'cvs status' ' cd cvswork && GIT_CONFIG="$git_config" cvs update && GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out && - test $(wc -l <../out) = 2 + test_line_count = 2 ../out ' cd "$WORKDIR" test_expect_success 'cvs status (nonrecursive)' ' cd cvswork && GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out && - test $(wc -l <../out) = 1 + test_line_count = 1 ../out ' cd "$WORKDIR" @@ -500,8 +500,8 @@ test_expect_success 'cvs status (no subdirs in header)' ' cd "$WORKDIR" test_expect_success 'cvs co -c (shows module database)' ' GIT_CONFIG="$git_config" cvs co -c > out && - grep "^master[ ]\+master$" < out && - ! grep -v "^master[ ]\+master$" < out + grep "^master[ ][ ]*master$" <out && + ! grep -v "^master[ ][ ]*master$" <out ' #------------ diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 53297156a3..90bb6050c1 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -274,6 +274,53 @@ test_expect_success \ 'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=foo-symlinked-to-bar"' # ---------------------------------------------------------------------- +# commitdiff testing (incomplete lines) + +test_expect_success 'setup incomplete lines' ' + cat >file<<-\EOF && + Dominus regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + CHANGE_ME + EOF + git commit -a -m "Preparing for incomplete lines" && + echo "incomplete" | tr -d "\\012" >>file && + git commit -a -m "Add incomplete line" && + git tag incomplete_lines_add && + sed -e s/CHANGE_ME/change_me/ <file >file+ && + mv -f file+ file && + git commit -a -m "Incomplete context line" && + git tag incomplete_lines_ctx && + echo "Dominus regit me," >file && + echo "incomplete line" | tr -d "\\012" >>file && + git commit -a -m "Change incomplete line" && + git tag incomplete_lines_chg + echo "Dominus regit me," >file && + git commit -a -m "Remove incomplete line" && + git tag incomplete_lines_rem +' + +test_expect_success 'commitdiff(1): addition of incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_add" +' + +test_expect_success 'commitdiff(1): incomplete line as context line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_ctx" +' + +test_expect_success 'commitdiff(1): change incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_chg" +' + +test_expect_success 'commitdiff(1): removal of incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_rem" +' + +# ---------------------------------------------------------------------- # commit, commitdiff: merge, large test_expect_success \ 'Create a merge' \ @@ -282,7 +329,8 @@ test_expect_success \ git add b && git commit -a -m "On branch" && git checkout master && - git pull . b' + git pull . b && + git tag merge_commit' test_expect_success \ 'commit(0): merge commit' \ @@ -332,6 +380,29 @@ test_expect_success \ 'gitweb_run "p=.git;a=commitdiff;h=b"' # ---------------------------------------------------------------------- +# side-by-side diff + +test_expect_success 'side-by-side: addition of incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_add;ds=sidebyside" +' + +test_expect_success 'side-by-side: incomplete line as context line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_ctx;ds=sidebyside" +' + +test_expect_success 'side-by-side: changed incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_chg;ds=sidebyside" +' + +test_expect_success 'side-by-side: removal of incomplete line' ' + gitweb_run "p=.git;a=commitdiff;h=incomplete_lines_rem;ds=sidebyside" +' + +test_expect_success 'side-by-side: merge commit' ' + gitweb_run "p=.git;a=commitdiff;h=merge_commit;ds=sidebyside" +' + +# ---------------------------------------------------------------------- # tags testing test_expect_success \ @@ -404,6 +475,14 @@ test_expect_success \ 'gitweb_run "" "/.git/master:foo/"' test_expect_success \ + 'path_info: project/branch (non-existent)' \ + 'gitweb_run "" "/.git/non-existent"' + +test_expect_success \ + 'path_info: project/branch:filename (non-existent branch)' \ + 'gitweb_run "" "/.git/non-existent:non-existent"' + +test_expect_success \ 'path_info: project/branch:file (non-existent)' \ 'gitweb_run "" "/.git/master:non-existent"' @@ -559,6 +638,45 @@ test_expect_success \ 'gitweb_run "p=.git;a=tree"' # ---------------------------------------------------------------------- +# searching + +cat >>gitweb_config.perl <<\EOF + +# enable search +$feature{'search'}{'default'} = [1]; +$feature{'grep'}{'default'} = [1]; +$feature{'pickaxe'}{'default'} = [1]; +EOF + +test_expect_success \ + 'search: preparation' \ + 'echo "1st MATCH" >>file && + echo "2nd MATCH" >>file && + echo "MATCH" >>bar && + git add file bar && + git commit -m "Added MATCH word"' + +test_expect_success \ + 'search: commit author' \ + 'gitweb_run "p=.git;a=search;h=HEAD;st=author;s=A+U+Thor"' + +test_expect_success \ + 'search: commit message' \ + 'gitweb_run "p=.git;a=search;h=HEAD;st=commitr;s=MATCH"' + +test_expect_success \ + 'search: grep' \ + 'gitweb_run "p=.git;a=search;h=HEAD;st=grep;s=MATCH"' + +test_expect_success \ + 'search: pickaxe' \ + 'gitweb_run "p=.git;a=search;h=HEAD;st=pickaxe;s=MATCH"' + +test_expect_success \ + 'search: projects' \ + 'gitweb_run "a=project_list;s=.git"' + +# ---------------------------------------------------------------------- # non-ASCII in README.html test_expect_success \ @@ -660,4 +778,13 @@ test_expect_success \ 'echo "\$projects_list_group_categories = 1;" >>gitweb_config.perl && gitweb_run' +# ---------------------------------------------------------------------- +# unborn branches + +test_expect_success \ + 'unborn HEAD: "summary" page (with "heads" subview)' \ + 'git checkout orphan_branch || git checkout --orphan orphan_branch && + test_when_finished "git checkout master" && + gitweb_run "p=.git;a=summary"' + test_done diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh index 26102ee9b0..ef86948d21 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -12,6 +12,13 @@ code and message.' . ./gitweb-lib.sh +# +# Gitweb only provides the functionality tested by the 'modification times' +# tests if it can access a date parser from one of these modules: +# +perl -MHTTP::Date -e 0 >/dev/null 2>&1 && test_set_prereq DATE_PARSER +perl -MTime::ParseDate -e 0 >/dev/null 2>&1 && test_set_prereq DATE_PARSER + # ---------------------------------------------------------------------- # snapshot settings @@ -92,7 +99,7 @@ test_debug 'cat gitweb.output' test_expect_success 'snapshots: bad tree-ish id (tagged object)' ' echo object > tag-object && git add tag-object && - git commit -m "Object to be tagged" && + test_tick && git commit -m "Object to be tagged" && git tag tagged-object `git hash-object tag-object` && gitweb_run "p=.git;a=snapshot;h=tagged-object;sf=tgz" && grep "400 - Object is not a tree-ish" gitweb.output @@ -112,6 +119,64 @@ test_expect_success 'snapshots: bad object id' ' ' test_debug 'cat gitweb.output' +# ---------------------------------------------------------------------- +# modification times (Last-Modified and If-Modified-Since) + +test_expect_success DATE_PARSER 'modification: feed last-modified' ' + gitweb_run "p=.git;a=atom;h=master" && + grep "Status: 200 OK" gitweb.headers && + grep "Last-modified: Thu, 7 Apr 2005 22:14:13 +0000" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: feed if-modified-since (modified)' ' + export HTTP_IF_MODIFIED_SINCE="Wed, 6 Apr 2005 22:14:13 +0000" && + test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && + gitweb_run "p=.git;a=atom;h=master" && + grep "Status: 200 OK" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: feed if-modified-since (unmodified)' ' + export HTTP_IF_MODIFIED_SINCE="Thu, 7 Apr 2005 22:14:13 +0000" && + test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && + gitweb_run "p=.git;a=atom;h=master" && + grep "Status: 304 Not Modified" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: snapshot last-modified' ' + gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" && + grep "Status: 200 OK" gitweb.headers && + grep "Last-modified: Thu, 7 Apr 2005 22:14:13 +0000" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: snapshot if-modified-since (modified)' ' + export HTTP_IF_MODIFIED_SINCE="Wed, 6 Apr 2005 22:14:13 +0000" && + test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && + gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" && + grep "Status: 200 OK" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: snapshot if-modified-since (unmodified)' ' + export HTTP_IF_MODIFIED_SINCE="Thu, 7 Apr 2005 22:14:13 +0000" && + test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && + gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" && + grep "Status: 304 Not Modified" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_expect_success DATE_PARSER 'modification: tree snapshot' ' + ID=`git rev-parse --verify HEAD^{tree}` && + export HTTP_IF_MODIFIED_SINCE="Wed, 6 Apr 2005 22:14:13 +0000" && + test_when_finished "unset HTTP_IF_MODIFIED_SINCE" && + gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" && + grep "Status: 200 OK" gitweb.headers && + ! grep -i "last-modified" gitweb.headers +' +test_debug 'cat gitweb.headers' # ---------------------------------------------------------------------- # load checking @@ -134,4 +199,14 @@ our $maxload = undef; EOF +# ---------------------------------------------------------------------- +# invalid arguments + +test_expect_success 'invalid arguments: invalid regexp (in project search)' ' + gitweb_run "a=project_list;s=*\.git;sr=1" && + grep "Status: 400" gitweb.headers && + grep "400 - Invalid.*regexp" gitweb.body +' +test_debug 'cat gitweb.headers' + 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 13ba96e21a..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 diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh new file mode 100755 index 0000000000..0f410c45f7 --- /dev/null +++ b/t/t9800-git-p4-basic.sh @@ -0,0 +1,576 @@ +#!/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' ' + git p4 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' ' + git p4 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 git p4 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 && + git p4 sync --branch=refs/remotes/p4/depot //depot@all && + git log --oneline p4/depot >lines && + test_line_count = 2 lines + ) +' + +test_expect_success 'clone two dirs' ' + ( + cd "$cli" && + mkdir sub1 sub2 && + echo sub1/f1 >sub1/f1 && + echo sub2/f2 >sub2/f2 && + p4 add sub1/f1 && + p4 submit -d "sub1/f1" && + p4 add sub2/f2 && + p4 submit -d "sub2/f2" + ) && + git p4 clone --dest="$git" //depot/sub1 //depot/sub2 && + test_when_finished cleanup_git && + ( + cd "$git" && + git ls-files >lines && + test_line_count = 2 lines && + git log --oneline p4/master >lines && + test_line_count = 1 lines + ) +' + +test_expect_success 'clone two dirs, @all' ' + ( + cd "$cli" && + echo sub1/f3 >sub1/f3 && + p4 add sub1/f3 && + p4 submit -d "sub1/f3" + ) && + git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git ls-files >lines && + test_line_count = 3 lines && + git log --oneline p4/master >lines && + test_line_count = 3 lines + ) +' + +test_expect_success 'clone two dirs, @all, conflicting files' ' + ( + cd "$cli" && + echo sub2/f3 >sub2/f3 && + p4 add sub2/f3 && + p4 submit -d "sub2/f3" + ) && + git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git ls-files >lines && + test_line_count = 3 lines && + git log --oneline p4/master >lines && + test_line_count = 4 lines && + echo sub2/f3 >expected && + test_cmp expected f3 + ) +' + +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" git p4 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' ' + git p4 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 'wildcard files submit back to p4, add' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo git-wild-hash >git-wild#hash && + echo git-wild-star >git-wild\*star && + echo git-wild-at >git-wild@at && + echo git-wild-percent >git-wild%percent && + git add git-wild* && + git commit -m "add some wildcard filenames" && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file git-wild#hash && + test_path_is_file git-wild\*star && + test_path_is_file git-wild@at && + test_path_is_file git-wild%percent + ) +' + +test_expect_success 'wildcard files submit back to p4, modify' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo new-line >>git-wild#hash && + echo new-line >>git-wild\*star && + echo new-line >>git-wild@at && + echo new-line >>git-wild%percent && + git add git-wild* && + git commit -m "modify the wildcard files" && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_line_count = 2 git-wild#hash && + test_line_count = 2 git-wild\*star && + test_line_count = 2 git-wild@at && + test_line_count = 2 git-wild%percent + ) +' + +test_expect_success 'wildcard files submit back to p4, copy' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + cp file2 git-wild-cp#hash && + git add git-wild-cp#hash && + cp git-wild\*star file-wild-3 && + git add file-wild-3 && + git commit -m "wildcard copies" && + git config git-p4.detectCopies true && + git config git-p4.detectCopiesHarder true && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file git-wild-cp#hash && + test_path_is_file file-wild-3 + ) +' + +test_expect_success 'wildcard files submit back to p4, rename' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git mv git-wild@at file-wild-4 && + git mv file-wild-3 git-wild-cp%percent && + git commit -m "wildcard renames" && + git config git-p4.detectRenames true && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing git-wild@at && + test_path_is_file git-wild-cp%percent + ) +' + +test_expect_success 'wildcard files submit back to p4, delete' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git rm git-wild* && + git commit -m "delete the wildcard files" && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing git-wild#hash && + test_path_is_missing git-wild\*star && + test_path_is_missing git-wild@at && + test_path_is_missing git-wild%percent + ) +' + +test_expect_success 'clone bare' ' + git p4 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 && + git p4 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 git p4 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' ' + git p4 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 && + export P4EDITOR P4USER P4PASSWD && + test_must_fail git p4 commit --preserve-user && + ! 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' ' + git p4 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 && + export P4EDITOR P4USER P4PASSWD && + test_must_fail git p4 commit --preserve-user && + ! 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 && + git p4 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' ' + git p4 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 && + export P4EDITOR P4USER P4PASSWD && + git p4 commit |\ + grep "git author derek@localhost does not match" && + + make_change_by_user usernamefile3 Charlie charlie@localhost && + git p4 commit |\ + grep "git author charlie@localhost does not match" && + + make_change_by_user usernamefile3 alice alice@localhost && + git p4 commit |\ + test_must_fail grep "git author.*does not match" && + + git config git-p4.skipUserNameCheck true && + make_change_by_user usernamefile3 Charlie charlie@localhost && + git p4 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 && + git p4 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' ' + git p4 clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + + git mv file1 file4 && + git commit -a -m "Rename file1 to file4" && + git diff-tree -r -M HEAD && + git p4 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 && + git p4 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)) && + git p4 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)) && + git p4 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' ' + git p4 clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + + cp file2 file8 && + git add file8 && + git commit -a -m "Copy file2 to file8" && + git diff-tree -r -C HEAD && + git p4 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 && + git p4 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 && + git p4 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 && + git p4 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)) && + git p4 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)) && + git p4 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/t9800-git-p4.sh b/t/t9800-git-p4.sh deleted file mode 100755 index 33b0127651..0000000000 --- a/t/t9800-git-p4.sh +++ /dev/null @@ -1,264 +0,0 @@ -#!/bin/sh - -test_description='git-p4 tests' - -. ./test-lib.sh - -( 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 -P4DPORT=10669 - -export P4PORT=localhost:$P4DPORT - -db="$TRASH_DIRECTORY/db" -cli="$TRASH_DIRECTORY/cli" -git="$TRASH_DIRECTORY/git" - -test_debug 'echo p4d -q -d -r "$db" -p $P4DPORT' -test_expect_success setup ' - mkdir -p "$db" && - p4d -q -d -r "$db" -p $P4DPORT && - mkdir -p "$cli" && - mkdir -p "$git" && - export P4PORT=localhost:$P4DPORT -' - -test_expect_success 'add p4 files' ' - cd "$cli" && - p4 client -i <<-EOF && - Client: client - Description: client - Root: $cli - View: //depot/... //client/... - EOF - export P4CLIENT=client && - echo file1 >file1 && - p4 add file1 && - p4 submit -d "file1" && - echo file2 >file2 && - p4 add file2 && - p4 submit -d "file2" && - cd "$TRASH_DIRECTORY" -' - -test_expect_success 'basic git-p4 clone' ' - "$GITP4" clone --dest="$git" //depot && - cd "$git" && - git log --oneline >lines && - test_line_count = 1 lines && - cd .. && - rm -rf "$git" && mkdir "$git" -' - -test_expect_success 'git-p4 clone @all' ' - "$GITP4" clone --dest="$git" //depot@all && - cd "$git" && - git log --oneline >lines && - test_line_count = 2 lines && - cd .. && - rm -rf "$git" && mkdir "$git" -' - -test_expect_success 'git-p4 sync uninitialized repo' ' - test_create_repo "$git" && - cd "$git" && - test_must_fail "$GITP4" sync && - rm -rf "$git" && mkdir "$git" -' - -# -# 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" && - cd "$git" && - test_commit head && - "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all && - git log --oneline p4/depot >lines && - cat lines && - test_line_count = 2 lines && - cd .. && - rm -rf "$git" && mkdir "$git" -' - -test_expect_success 'exit when p4 fails to produce marshaled output' ' - badp4dir="$TRASH_DIRECTORY/badp4dir" && - mkdir -p "$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" && - cd "$TRASH_DIRECTORY" -' - -test_expect_success 'wildcard files git-p4 clone' ' - "$GITP4" clone --dest="$git" //depot && - cd "$git" && - test -f file-wild#hash && - test -f file-wild\*star && - test -f file-wild@at && - test -f file-wild%percent && - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && mkdir "$git" -' - -test_expect_success 'clone bare' ' - "$GITP4" clone --dest="$git" --bare //depot && - cd "$git" && - test ! -d .git && - bare=`git config --get core.bare` && - test "$bare" = true && - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && mkdir "$git" -' - -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 |\ - awk "{print}END{print \" admin user $name * //depot/...\"}" |\ - p4 protect -i -} - -p4_check_commit_author() { - file=$1 - user=$2 - if p4 changes -m 1 //depot/$file | grep $user > /dev/null ; then - return 0 - else - echo "file $file not modified by user $user" 1>&2 - return 1 - fi -} - -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 && - 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 && - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && mkdir "$git" -' - -# 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 && - cd "$git" && - 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 "$GITP4" commit --preserve-user && - ! git diff --exit-code HEAD..p4/master > /dev/null && - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && mkdir "$git" -' - -# 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 && - 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 "$GITP4" commit --preserve-user && - ! git diff --exit-code HEAD..p4/master > /dev/null && - 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 > /dev/null && - p4_check_commit_author file1 alice && - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && mkdir "$git" -' - -# 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 && - ( - 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 >actual && - grep "git author derek@localhost does not match" actual && - - make_change_by_user usernamefile3 Charlie charlie@localhost && - P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && - grep "git author charlie@localhost does not match" actual && - - make_change_by_user usernamefile3 alice alice@localhost && - P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && - ! grep "git author.*does not match" actual && - - git config git-p4.skipUserNameCheck true && - make_change_by_user usernamefile3 Charlie charlie@localhost && - P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && - ! grep "git author.*does not match" actual && - - p4_check_commit_author usernamefile3 alice - ) && - rm -rf "$git" && mkdir "$git" -' - - -test_expect_success 'shutdown' ' - pid=`pgrep -f p4d` && - test -n "$pid" && - test_debug "ps wl `echo $pid`" && - kill $pid -' - -test_done diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh new file mode 100755 index 0000000000..99fe16b72d --- /dev/null +++ b/t/t9801-git-p4-branch.sh @@ -0,0 +1,417 @@ +#!/bin/sh + +test_description='git p4 tests for p4 branches' + +. ./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 && + git p4 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 && + git p4 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 && + git p4 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 && + git p4 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 && + git p4 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 && + git p4 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 "Create branch1" && + p4 integrate //depot/branch1/... //depot/branch2/... && + p4 submit -d "Integrate branch2 from branch1" && + 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 "Integrate branch3 from branch1" + ) +' + +# 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 && + git p4 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 update file2 && + git reset --hard p4/depot/branch2 && + test -f file1 && + test -f file2 && + test ! -f file3 && + ! grep update file2 && + git reset --hard p4/depot/branch3 && + test -f file1 && + test -f file2 && + test -f file3 && + grep update file2 && + cd "$cli" && + cd branch1 && + p4 edit file2 && + echo file2_ >>file2 && + p4 submit -d "update file2 in branch1" && + cd "$git" && + git reset --hard p4/depot/branch1 && + git p4 rebase && + grep file2_ file2 + ) +' + +# Create a complex branch structure in P4 depot to check if they are correctly +# cloned. The branches are created from older changelists to check if git p4 is +# able to correctly detect them. +# The final expected structure is: +# `branch1 +# | `- file1 +# | `- file2 (updated) +# | `- file3 +# `branch2 +# | `- file1 +# | `- file2 +# `branch3 +# | `- file1 +# | `- file2 (updated) +# | `- file3 +# `branch4 +# | `- file1 +# | `- file2 +# `branch5 +# `- file1 +# `- file2 +# `- file3 +test_expect_success 'git p4 add complex branches' ' + ( + cd "$cli" && + changelist=$(p4 changes -m1 //depot/... | cut -d" " -f2) && + changelist=$(($changelist - 5)) && + p4 integrate //depot/branch1/...@$changelist //depot/branch4/... && + p4 submit -d "Integrate branch4 from branch1@${changelist}" && + changelist=$(($changelist + 2)) && + p4 integrate //depot/branch1/...@$changelist //depot/branch5/... && + p4 submit -d "Integrate branch5 from branch1@${changelist}" + ) +' + +# Configure branches through git-config and clone them. git p4 will only be able +# to clone the original structure if it is able to detect the origin changelist +# of each branch. +test_expect_success 'git p4 clone complex 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 && + git config --add git-p4.branchList branch1:branch4 && + git config --add git-p4.branchList branch1:branch5 && + git p4 clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + grep update file2 && + git reset --hard p4/depot/branch2 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + ! grep update file2 && + git reset --hard p4/depot/branch3 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + grep update file2 && + git reset --hard p4/depot/branch4 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + ! grep update file2 && + git reset --hard p4/depot/branch5 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + ! grep update file2 && + test_path_is_missing .git/git-p4-tmp + ) +' + +# Move branch3/file3 to branch4/file3 in a single changelist +test_expect_success 'git p4 submit to two branches in a single changelist' ' + ( + cd "$cli" && + p4 integrate //depot/branch3/file3 //depot/branch4/file3 && + p4 delete //depot/branch3/file3 && + p4 submit -d "Move branch3/file3 to branch4/file3" + ) +' + +# Confirm that changes to two branches done in a single changelist +# are correctly imported by git p4 +test_expect_success 'git p4 sync changes to two branches in the same changelist' ' + 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 && + git config --add git-p4.branchList branch1:branch4 && + git config --add git-p4.branchList branch1:branch5 && + git p4 clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + grep update file2 && + git reset --hard p4/depot/branch2 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + ! grep update file2 && + git reset --hard p4/depot/branch3 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + grep update file2 && + git reset --hard p4/depot/branch4 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + ! grep update file2 && + git reset --hard p4/depot/branch5 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + ! grep update file2 && + test_path_is_missing .git/git-p4-tmp + ) +' + +# Create a branch by integrating a single file +test_expect_success 'git p4 file subset branch' ' + ( + cd "$cli" && + p4 integrate //depot/branch1/file1 //depot/branch6/file1 && + p4 submit -d "Integrate file1 alone from branch1 to branch6" + ) +' + +# Check if git p4 creates a new branch containing a single file, +# instead of keeping the old files from the original branch +test_expect_failure 'git p4 clone file subset branch' ' + 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 && + git config --add git-p4.branchList branch1:branch4 && + git config --add git-p4.branchList branch1:branch5 && + git config --add git-p4.branchList branch1:branch6 && + git p4 clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + grep update file2 && + git reset --hard p4/depot/branch2 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + ! grep update file2 && + git reset --hard p4/depot/branch3 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_missing file3 && + grep update file2 && + git reset --hard p4/depot/branch4 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + ! grep update file2 && + git reset --hard p4/depot/branch5 && + test_path_is_file file1 && + test_path_is_file file2 && + test_path_is_file file3 && + ! grep update file2 && + git reset --hard p4/depot/branch6 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 + ) +' +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..21924dfd7d --- /dev/null +++ b/t/t9802-git-p4-filetype.sh @@ -0,0 +1,139 @@ +#!/bin/sh + +test_description='git 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 && + git p4 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 && + git p4 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 + ) +' + +build_gendouble() { + cat >gendouble.py <<-\EOF + import sys + import struct + import array + + s = array.array("c", '\0' * 26) + struct.pack_into(">L", s, 0, 0x00051607) # AppleDouble + struct.pack_into(">L", s, 4, 0x00020000) # version 2 + s.tofile(sys.stdout) + EOF +} + +test_expect_success 'ignore apple' ' + test_when_finished rm -f gendouble.py && + build_gendouble && + ( + cd "$cli" && + test-genrandom apple 1024 >double.png && + "$PYTHON_PATH" "$TRASH_DIRECTORY/gendouble.py" >%double.png && + p4 add -t apple double.png && + p4 submit -d appledouble + ) && + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot@all && + ( + cd "$git" && + test ! -f double.png + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9803-git-p4-shell-metachars.sh b/t/t9803-git-p4-shell-metachars.sh new file mode 100755 index 0000000000..fbacff34fe --- /dev/null +++ b/t/t9803-git-p4-shell-metachars.sh @@ -0,0 +1,112 @@ +#!/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' ' + git p4 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 git p4 submit + ) && + ( + cd "$cli" && + p4 sync ... && + test -e "file with spaces" && + test -e "foo\$bar" + ) +' + +test_expect_success 'deleting with shell metachars' ' + git p4 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 git p4 submit + ) && + ( + cd "$cli" && + p4 sync ... && + test ! -e "file with spaces" && + test ! -e foo\$bar + ) +' + +# Create a branch with a shell metachar in its name +# +# 1. //depot/main +# 2. //depot/branch$3 + +test_expect_success 'branch with shell char' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$cli" && + + mkdir -p main && + + echo f1 >main/f1 && + p4 add main/f1 && + p4 submit -d "main/f1" && + + p4 integrate //depot/main/... //depot/branch\$3/... && + p4 submit -d "integrate main to branch\$3" && + + echo f1 >branch\$3/shell_char_branch_file && + p4 add branch\$3/shell_char_branch_file && + p4 submit -d "branch\$3/shell_char_branch_file" && + + p4 branch -i <<-EOF && + Branch: branch\$3 + View: //depot/main/... //depot/branch\$3/... + EOF + + p4 edit main/f1 && + echo "a change" >> main/f1 && + p4 submit -d "a change" main/f1 && + + p4 integrate -b branch\$3 && + p4 resolve -am branch\$3/... && + p4 submit -d "integrate main to branch\$3" && + + cd "$git" && + + git config git-p4.branchList main:branch\$3 && + git p4 clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch\$3 && + test -f shell_char_branch_file && + test -f f1 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9804-git-p4-label.sh b/t/t9804-git-p4-label.sh new file mode 100755 index 0000000000..e30f80e617 --- /dev/null +++ b/t/t9804-git-p4-label.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +test_description='git p4 label tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# Basic p4 label tests. +# +# Note: can't have more than one label per commit - others +# are silently discarded. +# +test_expect_success 'basic p4 labels' ' + test_when_finished cleanup_git && + ( + 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" && + + echo f3 >main/file_with_\$metachar && + p4 add main/file_with_\$metachar && + p4 submit -d "file with metachar" && + + p4 tag -l tag_f1_only main/f1 && + p4 tag -l tag_with\$_shell_char main/... && + + echo f4 >main/f4 && + p4 add main/f4 && + p4 submit -d "main/f4" && + + p4 label -i <<-EOF && + Label: long_label + Description: + A Label first line + A Label second line + View: //depot/... + EOF + + p4 tag -l long_label ... && + + p4 labels ... && + + git p4 clone --dest="$git" --detect-labels //depot@all && + cd "$git" && + + git tag && + git tag >taglist && + test_line_count = 3 taglist && + + cd main && + git checkout tag_tag_f1_only && + ! test -f f2 && + git checkout tag_tag_with\$_shell_char && + test -f f1 && test -f f2 && test -f file_with_\$metachar && + + git show tag_long_label | grep -q "A Label second line" + ) +' + +# Test some label corner cases: +# +# - two tags on the same file; both should be available +# - a tag that is only on one file; this kind of tag +# cannot be imported (at least not easily). + +test_expect_failure 'two labels on the same changelist' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + mkdir -p main && + + p4 edit main/f1 main/f2 && + echo "hello world" >main/f1 && + echo "not in the tag" >main/f2 && + p4 submit -d "main/f[12]: testing two labels" && + + p4 tag -l tag_f1_1 main/... && + p4 tag -l tag_f1_2 main/... && + + p4 labels ... && + + git p4 clone --dest="$git" --detect-labels //depot@all && + cd "$git" && + + git tag | grep tag_f1 && + git tag | grep -q tag_f1_1 && + git tag | grep -q tag_f1_2 && + + cd main && + + git checkout tag_tag_f1_1 && + ls && + test -f f1 && + + git checkout tag_tag_f1_2 && + ls && + test -f f1 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9805-git-p4-skip-submit-edit.sh b/t/t9805-git-p4-skip-submit-edit.sh new file mode 100755 index 0000000000..353dcfbe09 --- /dev/null +++ b/t/t9805-git-p4-skip-submit-edit.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +test_description='git p4 skipSubmitEdit config variables' + +. ./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 "change 1" + ) +' + +# this works because EDITOR is set to : +test_expect_success 'no config, unedited, say yes' ' + git p4 clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + echo line >>file1 && + git commit -a -m "change 2" && + echo y | git p4 submit && + p4 changes //depot/... >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'no config, unedited, say no' ' + git p4 clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + echo line >>file1 && + git commit -a -m "change 3 (not really)" && + printf "bad response\nn\n" | git p4 submit && + p4 changes //depot/... >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'skipSubmitEdit' ' + git p4 clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + # will fail if editor is even invoked + git config core.editor /bin/false && + echo line >>file1 && + git commit -a -m "change 3" && + git p4 submit && + p4 changes //depot/... >wc && + test_line_count = 3 wc + ) +' + +test_expect_success 'skipSubmitEditCheck' ' + git p4 clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo line >>file1 && + git commit -a -m "change 4" && + git p4 submit && + p4 changes //depot/... >wc && + test_line_count = 4 wc + ) +' + +# check the normal case, where the template really is edited +test_expect_success 'no config, edited' ' + git p4 clone --dest="$git" //depot && + test_when_finished cleanup_git && + ed="$TRASH_DIRECTORY/ed.sh" && + test_when_finished "rm \"$ed\"" && + cat >"$ed" <<-EOF && + #!$SHELL_PATH + sleep 1 + touch "\$1" + exit 0 + EOF + chmod 755 "$ed" && + ( + cd "$git" && + echo line >>file1 && + git commit -a -m "change 5" && + P4EDITOR="" EDITOR="\"$ed\"" git p4 submit && + p4 changes //depot/... >wc && + test_line_count = 5 wc + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9806-git-p4-options.sh b/t/t9806-git-p4-options.sh new file mode 100755 index 0000000000..2892367830 --- /dev/null +++ b/t/t9806-git-p4-options.sh @@ -0,0 +1,170 @@ +#!/bin/sh + +test_description='git p4 options' + +. ./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 "change 1" && + echo file2 >file2 && + p4 add file2 && + p4 submit -d "change 2" && + echo file3 >file3 && + p4 add file3 && + p4 submit -d "change 3" + ) +' + +test_expect_success 'clone no --git-dir' ' + test_must_fail git p4 clone --git-dir=xx //depot +' + +test_expect_success 'clone --branch' ' + git p4 clone --branch=refs/remotes/p4/sb --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git ls-files >files && + test_line_count = 0 files && + test_path_is_file .git/refs/remotes/p4/sb + ) +' + +test_expect_success 'clone --changesfile' ' + cf="$TRASH_DIRECTORY/cf" && + test_when_finished "rm \"$cf\"" && + printf "1\n3\n" >"$cf" && + git p4 clone --changesfile="$cf" --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline p4/master >lines && + test_line_count = 2 lines + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 + ) +' + +test_expect_success 'clone --changesfile, @all' ' + cf="$TRASH_DIRECTORY/cf" && + test_when_finished "rm \"$cf\"" && + printf "1\n3\n" >"$cf" && + test_must_fail git p4 clone --changesfile="$cf" --dest="$git" //depot@all +' + +# imports both master and p4/master in refs/heads +# requires --import-local on sync to find p4 refs/heads +# does not update master on sync, just p4/master +test_expect_success 'clone/sync --import-local' ' + git p4 clone --import-local --dest="$git" //depot@1,2 && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline refs/heads/master >lines && + test_line_count = 2 lines && + git log --oneline refs/heads/p4/master >lines && + test_line_count = 2 lines && + test_must_fail git p4 sync && + + git p4 sync --import-local && + git log --oneline refs/heads/master >lines && + test_line_count = 2 lines && + git log --oneline refs/heads/p4/master >lines && + test_line_count = 3 lines + ) +' + +test_expect_success 'clone --max-changes' ' + git p4 clone --dest="$git" --max-changes 2 //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline refs/heads/master >lines && + test_line_count = 2 lines + ) +' + +test_expect_success 'clone --keep-path' ' + ( + cd "$cli" && + mkdir -p sub/dir && + echo f4 >sub/dir/f4 && + p4 add sub/dir/f4 && + p4 submit -d "change 4" + ) && + git p4 clone --dest="$git" --keep-path //depot/sub/dir@all && + test_when_finished cleanup_git && + ( + cd "$git" && + test_path_is_missing f4 && + test_path_is_file sub/dir/f4 + ) && + cleanup_git && + git p4 clone --dest="$git" //depot/sub/dir@all && + ( + cd "$git" && + test_path_is_file f4 && + test_path_is_missing sub/dir/f4 + ) +' + +# clone --use-client-spec must still specify a depot path +# if given, it should rearrange files according to client spec +# when it has view lines that match the depot path +# XXX: should clone/sync just use the client spec exactly, rather +# than needing depot paths? +test_expect_success 'clone --use-client-spec' ' + ( + # big usage message + exec >/dev/null && + test_must_fail git p4 clone --dest="$git" --use-client-spec + ) && + cli2="$TRASH_DIRECTORY/cli2" && + mkdir -p "$cli2" && + test_when_finished "rmdir \"$cli2\"" && + ( + cd "$cli2" && + p4 client -i <<-EOF + Client: client2 + Description: client2 + Root: $cli2 + View: //depot/sub/... //client2/bus/... + EOF + ) && + P4CLIENT=client2 && + test_when_finished cleanup_git && + git p4 clone --dest="$git" --use-client-spec //depot/... && + ( + cd "$git" && + test_path_is_file bus/dir/f4 && + test_path_is_missing file1 + ) && + cleanup_git && + + # same thing again, this time with variable instead of option + mkdir "$git" && + ( + cd "$git" && + git init && + git config git-p4.useClientSpec true && + git p4 sync //depot/... && + git checkout -b master p4/master && + test_path_is_file bus/dir/f4 && + test_path_is_missing file1 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh new file mode 100755 index 0000000000..f23b4c3620 --- /dev/null +++ b/t/t9807-git-p4-submit.sh @@ -0,0 +1,189 @@ +#!/bin/sh + +test_description='git p4 submit' + +. ./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 "change 1" + ) +' + +test_expect_success 'submit with no client dir' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo file2 >file2 && + git add file2 && + git commit -m "git commit 2" && + rm -rf "$cli" && + git config git-p4.skipSubmitEdit true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file file1 && + test_path_is_file file2 + ) +' + +# make two commits, but tell it to apply only from HEAD^ +test_expect_success 'submit --origin' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file3" && + test_commit "file4" && + git config git-p4.skipSubmitEdit true && + git p4 submit --origin=HEAD^ + ) && + ( + cd "$cli" && + test_path_is_missing "file3.t" && + test_path_is_file "file4.t" + ) +' + +test_expect_success 'submit with allowSubmit' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file5" && + git config git-p4.skipSubmitEdit true && + git config git-p4.allowSubmit "nobranch" && + test_must_fail git p4 submit && + git config git-p4.allowSubmit "nobranch,master" && + git p4 submit + ) +' + +test_expect_success 'submit with master branch name from argv' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file6" && + git config git-p4.skipSubmitEdit true && + test_must_fail git p4 submit nobranch && + git branch otherbranch && + git reset --hard HEAD^ && + test_commit "file7" && + git p4 submit otherbranch + ) && + ( + cd "$cli" && + test_path_is_file "file6.t" && + test_path_is_missing "file7.t" + ) +' + +# +# Basic submit tests, the five handled cases +# + +test_expect_success 'submit modify' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo line >>file1 && + git add file1 && + git commit -m file1 && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file file1 && + test_line_count = 2 file1 + ) +' + +test_expect_success 'submit add' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo file13 >file13 && + git add file13 && + git commit -m file13 && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file file13 + ) +' + +test_expect_success 'submit delete' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git rm file4.t && + git commit -m "delete file4.t" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing file4.t + ) +' + +test_expect_success 'submit copy' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.detectCopies true && + git config git-p4.detectCopiesHarder true && + cp file5.t file5.ta && + git add file5.ta && + git commit -m "copy to file5.ta" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file file5.ta && + test ! -w file5.ta + ) +' + +test_expect_success 'submit rename' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.detectRenames true && + git mv file6.t file6.ta && + git commit -m "rename file6.t to file6.ta" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing file6.t && + test_path_is_file file6.ta && + test ! -w file6.ta + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9808-git-p4-chdir.sh b/t/t9808-git-p4-chdir.sh new file mode 100755 index 0000000000..2f8014a60e --- /dev/null +++ b/t/t9808-git-p4-chdir.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='git p4 relative chdir' + +. ./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 "change 1" + ) +' + +# P4 reads from P4CONFIG file to find its server params, if the +# environment variable is set +test_expect_success 'P4CONFIG and absolute dir clone' ' + printf "P4PORT=$P4PORT\nP4CLIENT=$P4CLIENT\n" >p4config && + test_when_finished "rm \"$TRASH_DIRECTORY/p4config\"" && + test_when_finished cleanup_git && + ( + P4CONFIG=p4config && export P4CONFIG && + sane_unset P4PORT P4CLIENT && + git p4 clone --verbose --dest="$git" //depot + ) +' + +# same thing, but with relative directory name, note missing $ on --dest +test_expect_success 'P4CONFIG and relative dir clone' ' + printf "P4PORT=$P4PORT\nP4CLIENT=$P4CLIENT\n" >p4config && + test_when_finished "rm \"$TRASH_DIRECTORY/p4config\"" && + test_when_finished cleanup_git && + ( + P4CONFIG=p4config && export P4CONFIG && + sane_unset P4PORT P4CLIENT && + git p4 clone --verbose --dest="git" //depot + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh new file mode 100755 index 0000000000..7d993ef80a --- /dev/null +++ b/t/t9809-git-p4-client-view.sh @@ -0,0 +1,854 @@ +#!/bin/sh + +test_description='git p4 client view' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# +# Construct a client with this list of View lines +# +client_view() { + ( + cat <<-EOF && + Client: client + Description: client + Root: $cli + View: + EOF + for arg ; do + printf "\t$arg\n" + done + ) | p4 client -i +} + +# +# Verify these files exist, exactly. Caller creates +# a list of files in file "files". +# +check_files_exist() { + ok=0 && + num=$# && + for arg ; do + test_path_is_file "$arg" && + ok=$(($ok + 1)) + done && + test $ok -eq $num && + test_line_count = $num files +} + +# +# Sync up the p4 client, make sure the given files (and only +# those) exist. +# +client_verify() { + ( + cd "$cli" && + p4 sync && + find . -type f ! -name files >files && + check_files_exist "$@" + ) +} + +# +# Make sure the named files, exactly, exist. +# +git_verify() { + ( + cd "$git" && + git ls-files >files && + check_files_exist "$@" + ) +} + +# //depot +# - dir1 +# - file11 +# - file12 +# - dir2 +# - file21 +# - file22 +init_depot() { + for d in 1 2 ; do + mkdir -p dir$d && + for f in 1 2 ; do + echo dir$d/file$d$f >dir$d/file$d$f && + p4 add dir$d/file$d$f && + p4 submit -d "dir$d/file$d$f" + done + done && + find . -type f ! -name files >files && + check_files_exist dir1/file11 dir1/file12 \ + dir2/file21 dir2/file22 +} + +test_expect_success 'init depot' ' + ( + cd "$cli" && + init_depot + ) +' + +# double % for printf +test_expect_success 'unsupported view wildcard %%n' ' + client_view "//depot/%%%%1/sub/... //client/sub/%%%%1/..." && + test_when_finished cleanup_git && + test_must_fail git p4 clone --use-client-spec --dest="$git" //depot +' + +test_expect_success 'unsupported view wildcard *' ' + client_view "//depot/*/bar/... //client/*/bar/..." && + test_when_finished cleanup_git && + test_must_fail git p4 clone --use-client-spec --dest="$git" //depot +' + +test_expect_success 'wildcard ... only supported at end of spec 1' ' + client_view "//depot/.../file11 //client/.../file11" && + test_when_finished cleanup_git && + test_must_fail git p4 clone --use-client-spec --dest="$git" //depot +' + +test_expect_success 'wildcard ... only supported at end of spec 2' ' + client_view "//depot/.../a/... //client/.../a/..." && + test_when_finished cleanup_git && + test_must_fail git p4 clone --use-client-spec --dest="$git" //depot +' + +test_expect_success 'basic map' ' + client_view "//depot/dir1/... //client/cli1/..." && + files="cli1/file11 cli1/file12" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'client view with no mappings' ' + client_view && + client_verify && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify +' + +test_expect_success 'single file map' ' + client_view "//depot/dir1/file11 //client/file11" && + files="file11" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'later mapping takes precedence (entire repo)' ' + client_view "//depot/dir1/... //client/cli1/..." \ + "//depot/... //client/cli2/..." && + files="cli2/dir1/file11 cli2/dir1/file12 + cli2/dir2/file21 cli2/dir2/file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'later mapping takes precedence (partial repo)' ' + client_view "//depot/dir1/... //client/..." \ + "//depot/dir2/... //client/..." && + files="file21 file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +# Reading the view backwards, +# dir2 goes to cli12 +# dir1 cannot go to cli12 since it was filled by dir2 +# dir1 also does not go to cli3, since the second rule +# noticed that it matched, but was already filled +test_expect_success 'depot path matching rejected client path' ' + client_view "//depot/dir1/... //client/cli3/..." \ + "//depot/dir1/... //client/cli12/..." \ + "//depot/dir2/... //client/cli12/..." && + files="cli12/file21 cli12/file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +# since both have the same //client/..., the exclusion +# rule keeps everything out +test_expect_success 'exclusion wildcard, client rhs same (odd)' ' + client_view "//depot/... //client/..." \ + "-//depot/dir2/... //client/..." && + client_verify && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify +' + +test_expect_success 'exclusion wildcard, client rhs different (normal)' ' + client_view "//depot/... //client/..." \ + "-//depot/dir2/... //client/dir2/..." && + files="dir1/file11 dir1/file12" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'exclusion single file' ' + client_view "//depot/... //client/..." \ + "-//depot/dir2/file22 //client/file22" && + files="dir1/file11 dir1/file12 dir2/file21" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'overlay wildcard' ' + client_view "//depot/dir1/... //client/cli/..." \ + "+//depot/dir2/... //client/cli/...\n" && + files="cli/file11 cli/file12 cli/file21 cli/file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'overlay single file' ' + client_view "//depot/dir1/... //client/cli/..." \ + "+//depot/dir2/file21 //client/cli/file21" && + files="cli/file11 cli/file12 cli/file21" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'exclusion with later inclusion' ' + client_view "//depot/... //client/..." \ + "-//depot/dir2/... //client/dir2/..." \ + "//depot/dir2/... //client/dir2incl/..." && + files="dir1/file11 dir1/file12 dir2incl/file21 dir2incl/file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'quotes on rhs only' ' + client_view "//depot/dir1/... \"//client/cdir 1/...\"" && + client_verify "cdir 1/file11" "cdir 1/file12" && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify "cdir 1/file11" "cdir 1/file12" +' + +# +# Submit tests +# + +# clone sets variable +test_expect_success 'clone --use-client-spec sets useClientSpec' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + ( + cd "$git" && + git config --bool git-p4.useClientSpec >actual && + echo true >true && + test_cmp actual true + ) +' + +# clone just a subdir of the client spec +test_expect_success 'subdir clone' ' + client_view "//depot/... //client/..." && + files="dir1/file11 dir1/file12 dir2/file21 dir2/file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + git_verify dir1/file11 dir1/file12 +' + +# +# submit back, see what happens: five cases +# +test_expect_success 'subdir clone, submit modify' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo line >>dir1/file12 && + git add dir1/file12 && + git commit -m dir1/file12 && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file dir1/file12 && + test_line_count = 2 dir1/file12 + ) +' + +test_expect_success 'subdir clone, submit add' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo file13 >dir1/file13 && + git add dir1/file13 && + git commit -m dir1/file13 && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file dir1/file13 + ) +' + +test_expect_success 'subdir clone, submit delete' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git rm dir1/file12 && + git commit -m "delete dir1/file12" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing dir1/file12 + ) +' + +test_expect_success 'subdir clone, submit copy' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.detectCopies true && + cp dir1/file11 dir1/file11a && + git add dir1/file11a && + git commit -m "copy to dir1/file11a" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file dir1/file11a && + test ! -w dir1/file11a + ) +' + +test_expect_success 'subdir clone, submit rename' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.detectRenames true && + git mv dir1/file13 dir1/file13a && + git commit -m "rename dir1/file13 to dir1/file13a" && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_missing dir1/file13 && + test_path_is_file dir1/file13a && + test ! -w dir1/file13a + ) +' + +# see t9800 for the non-client-spec case, and the rest of the wildcard tests +test_expect_success 'wildcard files submit back to p4, client-spec case' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot/dir1 && + ( + cd "$git" && + echo git-wild-hash >dir1/git-wild#hash && + echo git-wild-star >dir1/git-wild\*star && + echo git-wild-at >dir1/git-wild@at && + echo git-wild-percent >dir1/git-wild%percent && + git add dir1/git-wild* && + git commit -m "add some wildcard filenames" && + git config git-p4.skipSubmitEditCheck true && + git p4 submit + ) && + ( + cd "$cli" && + test_path_is_file dir1/git-wild#hash && + test_path_is_file dir1/git-wild\*star && + test_path_is_file dir1/git-wild@at && + test_path_is_file dir1/git-wild%percent + ) && + ( + # delete these carefully, cannot just do "p4 delete" + # on files with wildcards; but git-p4 knows how + cd "$git" && + git rm dir1/git-wild* && + git commit -m "clean up the wildcards" && + git p4 submit + ) +' + +test_expect_success 'reinit depot' ' + ( + cd "$cli" && + rm files && + p4 delete */* && + p4 submit -d "delete all files" && + init_depot + ) +' + +# +# What happens when two files of the same name are overlayed together? +# The last-listed file should take preference. +# +# //depot +# - dir1 +# - file11 +# - file12 +# - filecollide +# - dir2 +# - file21 +# - file22 +# - filecollide +# +test_expect_success 'overlay collision setup' ' + client_view "//depot/... //client/..." && + ( + cd "$cli" && + p4 sync && + echo dir1/filecollide >dir1/filecollide && + p4 add dir1/filecollide && + p4 submit -d dir1/filecollide && + echo dir2/filecollide >dir2/filecollide && + p4 add dir2/filecollide && + p4 submit -d dir2/filecollide + ) +' + +test_expect_success 'overlay collision 1 to 2' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22 filecollide" && + echo dir2/filecollide >actual && + client_verify $files && + test_cmp actual "$cli"/filecollide && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files && + test_cmp actual "$git"/filecollide +' + +test_expect_failure 'overlay collision 2 to 1' ' + client_view "//depot/dir2/... //client/..." \ + "+//depot/dir1/... //client/..." && + files="file11 file12 file21 file22 filecollide" && + echo dir1/filecollide >actual && + client_verify $files && + test_cmp actual "$cli"/filecollide && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files && + test_cmp actual "$git"/filecollide +' + +test_expect_success 'overlay collision delete 2' ' + client_view "//depot/... //client/..." && + ( + cd "$cli" && + p4 sync && + p4 delete dir2/filecollide && + p4 submit -d "remove dir2/filecollide" + ) +' + +# no filecollide, got deleted with dir2 +test_expect_failure 'overlay collision 1 to 2, but 2 deleted' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'overlay collision update 1' ' + client_view "//depot/dir1/... //client/dir1/..." && + ( + cd "$cli" && + p4 sync && + p4 open dir1/filecollide && + echo dir1/filecollide update >dir1/filecollide && + p4 submit -d "update dir1/filecollide" + ) +' + +# still no filecollide, dir2 still wins with the deletion even though the +# change to dir1 is more recent +test_expect_failure 'overlay collision 1 to 2, but 2 deleted, then 1 updated' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files +' + +test_expect_success 'overlay collision delete filecollides' ' + client_view "//depot/... //client/..." && + ( + cd "$cli" && + p4 sync && + p4 delete dir1/filecollide dir2/filecollide && + p4 submit -d "remove filecollides" + ) +' + +# +# Overlays as part of sync, rather than initial checkout: +# 1. add a file in dir1 +# 2. sync to include it +# 3. add same file in dir2 +# 4. sync, make sure content switches as dir2 has priority +# 5. add another file in dir1 +# 6. sync +# 7. add/delete same file in dir2 +# 8. sync, make sure it disappears, again dir2 wins +# 9. cleanup +# +# //depot +# - dir1 +# - file11 +# - file12 +# - colA +# - colB +# - dir2 +# - file21 +# - file22 +# - colA +# - colB +# +test_expect_success 'overlay sync: add colA in dir1' ' + client_view "//depot/dir1/... //client/dir1/..." && + ( + cd "$cli" && + p4 sync && + echo dir1/colA >dir1/colA && + p4 add dir1/colA && + p4 submit -d dir1/colA + ) +' + +test_expect_success 'overlay sync: initial git checkout' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22 colA" && + echo dir1/colA >actual && + client_verify $files && + test_cmp actual "$cli"/colA && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files && + test_cmp actual "$git"/colA +' + +test_expect_success 'overlay sync: add colA in dir2' ' + client_view "//depot/dir2/... //client/dir2/..." && + ( + cd "$cli" && + p4 sync && + echo dir2/colA >dir2/colA && + p4 add dir2/colA && + p4 submit -d dir2/colA + ) +' + +test_expect_success 'overlay sync: colA content switch' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22 colA" && + echo dir2/colA >actual && + client_verify $files && + test_cmp actual "$cli"/colA && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files && + test_cmp actual "$git"/colA +' + +test_expect_success 'overlay sync: add colB in dir1' ' + client_view "//depot/dir1/... //client/dir1/..." && + ( + cd "$cli" && + p4 sync && + echo dir1/colB >dir1/colB && + p4 add dir1/colB && + p4 submit -d dir1/colB + ) +' + +test_expect_success 'overlay sync: colB appears' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22 colA colB" && + echo dir1/colB >actual && + client_verify $files && + test_cmp actual "$cli"/colB && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files && + test_cmp actual "$git"/colB +' + +test_expect_success 'overlay sync: add/delete colB in dir2' ' + client_view "//depot/dir2/... //client/dir2/..." && + ( + cd "$cli" && + p4 sync && + echo dir2/colB >dir2/colB && + p4 add dir2/colB && + p4 submit -d dir2/colB && + p4 delete dir2/colB && + p4 submit -d "delete dir2/colB" + ) +' + +test_expect_success 'overlay sync: colB disappears' ' + client_view "//depot/dir1/... //client/..." \ + "+//depot/dir2/... //client/..." && + files="file11 file12 file21 file22 colA" && + client_verify $files && + test_when_finished cleanup_git && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files +' + +test_expect_success 'overlay sync: cleanup' ' + client_view "//depot/... //client/..." && + ( + cd "$cli" && + p4 sync && + p4 delete dir1/colA dir2/colA dir1/colB && + p4 submit -d "remove overlay sync files" + ) +' + +# +# Overlay tests again, but swapped so dir1 has priority. +# 1. add a file in dir1 +# 2. sync to include it +# 3. add same file in dir2 +# 4. sync, make sure content does not switch +# 5. add another file in dir1 +# 6. sync +# 7. add/delete same file in dir2 +# 8. sync, make sure it is still there +# 9. cleanup +# +# //depot +# - dir1 +# - file11 +# - file12 +# - colA +# - colB +# - dir2 +# - file21 +# - file22 +# - colA +# - colB +# +test_expect_success 'overlay sync swap: add colA in dir1' ' + client_view "//depot/dir1/... //client/dir1/..." && + ( + cd "$cli" && + p4 sync && + echo dir1/colA >dir1/colA && + p4 add dir1/colA && + p4 submit -d dir1/colA + ) +' + +test_expect_success 'overlay sync swap: initial git checkout' ' + client_view "//depot/dir2/... //client/..." \ + "+//depot/dir1/... //client/..." && + files="file11 file12 file21 file22 colA" && + echo dir1/colA >actual && + client_verify $files && + test_cmp actual "$cli"/colA && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify $files && + test_cmp actual "$git"/colA +' + +test_expect_success 'overlay sync swap: add colA in dir2' ' + client_view "//depot/dir2/... //client/dir2/..." && + ( + cd "$cli" && + p4 sync && + echo dir2/colA >dir2/colA && + p4 add dir2/colA && + p4 submit -d dir2/colA + ) +' + +test_expect_failure 'overlay sync swap: colA no content switch' ' + client_view "//depot/dir2/... //client/..." \ + "+//depot/dir1/... //client/..." && + files="file11 file12 file21 file22 colA" && + echo dir1/colA >actual && + client_verify $files && + test_cmp actual "$cli"/colA && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files && + test_cmp actual "$git"/colA +' + +test_expect_success 'overlay sync swap: add colB in dir1' ' + client_view "//depot/dir1/... //client/dir1/..." && + ( + cd "$cli" && + p4 sync && + echo dir1/colB >dir1/colB && + p4 add dir1/colB && + p4 submit -d dir1/colB + ) +' + +test_expect_success 'overlay sync swap: colB appears' ' + client_view "//depot/dir2/... //client/..." \ + "+//depot/dir1/... //client/..." && + files="file11 file12 file21 file22 colA colB" && + echo dir1/colB >actual && + client_verify $files && + test_cmp actual "$cli"/colB && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files && + test_cmp actual "$git"/colB +' + +test_expect_success 'overlay sync swap: add/delete colB in dir2' ' + client_view "//depot/dir2/... //client/dir2/..." && + ( + cd "$cli" && + p4 sync && + echo dir2/colB >dir2/colB && + p4 add dir2/colB && + p4 submit -d dir2/colB && + p4 delete dir2/colB && + p4 submit -d "delete dir2/colB" + ) +' + +test_expect_failure 'overlay sync swap: colB no change' ' + client_view "//depot/dir2/... //client/..." \ + "+//depot/dir1/... //client/..." && + files="file11 file12 file21 file22 colA colB" && + echo dir1/colB >actual && + client_verify $files && + test_cmp actual "$cli"/colB && + test_when_finished cleanup_git && + ( + cd "$git" && + git p4 sync --use-client-spec && + git merge --ff-only p4/master + ) && + git_verify $files && + test_cmp actual "$cli"/colB +' + +test_expect_success 'overlay sync swap: cleanup' ' + client_view "//depot/... //client/..." && + ( + cd "$cli" && + p4 sync && + p4 delete dir1/colA dir2/colA dir1/colB && + p4 submit -d "remove overlay sync files" + ) +' + +# +# Rename directories to test quoting in depot-side mappings +# //depot +# - "dir 1" +# - file11 +# - file12 +# - "dir 2" +# - file21 +# - file22 +# +test_expect_success 'rename files to introduce spaces' ' + client_view "//depot/... //client/..." && + client_verify dir1/file11 dir1/file12 \ + dir2/file21 dir2/file22 && + ( + cd "$cli" && + p4 open dir1/... && + p4 move dir1/... "dir 1"/... && + p4 open dir2/... && + p4 move dir2/... "dir 2"/... && + p4 submit -d "rename with spaces" + ) && + client_verify "dir 1/file11" "dir 1/file12" \ + "dir 2/file21" "dir 2/file22" +' + +test_expect_success 'quotes on lhs only' ' + client_view "\"//depot/dir 1/...\" //client/cdir1/..." && + files="cdir1/file11 cdir1/file12" && + client_verify $files && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + client_verify $files +' + +test_expect_success 'quotes on both sides' ' + client_view "\"//depot/dir 1/...\" \"//client/cdir 1/...\"" && + client_verify "cdir 1/file11" "cdir 1/file12" && + test_when_finished cleanup_git && + git p4 clone --use-client-spec --dest="$git" //depot && + git_verify "cdir 1/file11" "cdir 1/file12" +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh new file mode 100755 index 0000000000..b00ad09d23 --- /dev/null +++ b/t/t9810-git-p4-rcs.sh @@ -0,0 +1,388 @@ +#!/bin/sh + +test_description='git-p4 rcs keywords' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# +# Make one file with keyword lines at the top, and +# enough plain text to be able to test modifications +# far away from the keywords. +# +test_expect_success 'init depot' ' + ( + cd "$cli" && + cat <<-\EOF >filek && + $Id$ + /* $Revision$ */ + # $Change$ + line4 + line5 + line6 + line7 + line8 + EOF + cp filek fileko && + sed -i "s/Revision/Revision: do not scrub me/" fileko + cp fileko file_text && + sed -i "s/Id/Id: do not scrub me/" file_text + p4 add -t text+k filek && + p4 submit -d "filek" && + p4 add -t text+ko fileko && + p4 submit -d "fileko" && + p4 add -t text file_text && + p4 submit -d "file_text" + ) +' + +# +# Generate these in a function to make it easy to use single quote marks. +# +write_scrub_scripts () { + cat >"$TRASH_DIRECTORY/scrub_k.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 >"$TRASH_DIRECTORY/scrub_ko.py" <<-\EOF + import re, sys + sys.stdout.write(re.sub(r'(?i)\$(Id|Header):[^$]*\$', r'$\1$', sys.stdin.read())) + EOF +} + +test_expect_success 'scrub scripts' ' + write_scrub_scripts +' + +# +# Compare $cli/file to its scrubbed version, should be different. +# Compare scrubbed $cli/file to $git/file, should be same. +# +scrub_k_check () { + file="$1" && + scrub="$TRASH_DIRECTORY/$file" && + "$PYTHON_PATH" "$TRASH_DIRECTORY/scrub_k.py" <"$git/$file" >"$scrub" && + ! test_cmp "$cli/$file" "$scrub" && + test_cmp "$git/$file" "$scrub" && + rm "$scrub" +} +scrub_ko_check () { + file="$1" && + scrub="$TRASH_DIRECTORY/$file" && + "$PYTHON_PATH" "$TRASH_DIRECTORY/scrub_ko.py" <"$git/$file" >"$scrub" && + ! test_cmp "$cli/$file" "$scrub" && + test_cmp "$git/$file" "$scrub" && + rm "$scrub" +} + +# +# Modify far away from keywords. If no RCS lines show up +# in the diff, there is no conflict. +# +test_expect_success 'edit far away from RCS lines' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + sed -i "s/^line7/line7 edit/" filek && + git commit -m "filek line7 edit" filek && + git p4 submit && + scrub_k_check filek + ) +' + +# +# Modify near the keywords. This will require RCS scrubbing. +# +test_expect_success 'edit near RCS lines' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + sed -i "s/^line4/line4 edit/" filek && + git commit -m "filek line4 edit" filek && + git p4 submit && + scrub_k_check filek + ) +' + +# +# Modify the keywords themselves. This also will require RCS scrubbing. +# +test_expect_success 'edit keyword lines' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + sed -i "/Revision/d" filek && + git commit -m "filek remove Revision line" filek && + git p4 submit && + scrub_k_check filek + ) +' + +# +# Scrubbing text+ko files should not alter all keywords, just Id, Header. +# +test_expect_success 'scrub ko files differently' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + sed -i "s/^line4/line4 edit/" fileko && + git commit -m "fileko line4 edit" fileko && + git p4 submit && + scrub_ko_check fileko && + ! scrub_k_check fileko + ) +' + +# hack; git-p4 submit should do it on its own +test_expect_success 'cleanup after failure' ' + ( + cd "$cli" && + p4 revert ... + ) +' + +# +# Do not scrub anything but +k or +ko files. Sneak a change into +# the cli file so that submit will get a conflict. Make sure that +# scrubbing doesn't make a mess of things. +# +# Assumes that git-p4 exits leaving the p4 file open, with the +# conflict-generating patch unapplied. +# +# This might happen only if the git repo is behind the p4 repo at +# submit time, and there is a conflict. +# +test_expect_success 'do not scrub plain text' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + sed -i "s/^line4/line4 edit/" file_text && + git commit -m "file_text line4 edit" file_text && + ( + cd "$cli" && + p4 open file_text && + sed -i "s/^line5/line5 p4 edit/" file_text && + p4 submit -d "file5 p4 edit" + ) && + ! git p4 submit && + ( + # exepct something like: + # file_text - file(s) not opened on this client + # but not copious diff output + cd "$cli" && + p4 diff file_text >wc && + test_line_count = 1 wc + ) + ) +' + +# hack; git-p4 submit should do it on its own +test_expect_success 'cleanup after failure 2' ' + ( + cd "$cli" && + p4 revert ... + ) +' + +create_kw_file () { + cat <<\EOF >"$1" +/* A file + Id: $Id$ + Revision: $Revision$ + File: $File$ + */ +int main(int argc, const char **argv) { + return 0; +} +EOF +} + +test_expect_success 'add kwfile' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "file 1" && + create_kw_file kwfile1.c && + p4 add kwfile1.c && + p4 submit -d "Add rcw kw file" kwfile1.c + ) +' + +p4_append_to_file () { + f="$1" && + p4 edit -t ktext "$f" && + echo "/* $(date) */" >>"$f" && + p4 submit -d "appending a line in p4" +} + +# Create some files with RCS keywords. If they get modified +# elsewhere then the version number gets bumped which then +# results in a merge conflict if we touch the RCS kw lines, +# even though the change itself would otherwise apply cleanly. +test_expect_success 'cope with rcs keyword expansion damage' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + (cd ../cli && p4_append_to_file kwfile1.c) && + old_lines=$(wc -l <kwfile1.c) && + "$PERL_PATH" -n -i -e "print unless m/Revision:/" kwfile1.c && + new_lines=$(wc -l <kwfile1.c) && + test $new_lines = $(($old_lines - 1)) && + + git add kwfile1.c && + git commit -m "Zap an RCS kw line" && + git p4 submit && + git p4 rebase && + git diff p4/master && + git p4 commit && + echo "try modifying in both" && + cd "$cli" && + p4 edit kwfile1.c && + echo "line from p4" >>kwfile1.c && + p4 submit -d "add a line in p4" kwfile1.c && + cd "$git" && + echo "line from git at the top" | cat - kwfile1.c >kwfile1.c.new && + mv kwfile1.c.new kwfile1.c && + git commit -m "Add line in git at the top" kwfile1.c && + git p4 rebase && + git p4 submit + ) +' + +test_expect_success 'cope with rcs keyword file deletion' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + echo "\$Revision\$" >kwdelfile.c && + p4 add -t ktext kwdelfile.c && + p4 submit -d "Add file to be deleted" && + cat kwdelfile.c && + grep 1 kwdelfile.c + ) && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + grep Revision kwdelfile.c && + git rm -f kwdelfile.c && + git commit -m "Delete a file containing RCS keywords" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + git p4 submit + ) && + ( + cd "$cli" && + p4 sync && + ! test -f kwdelfile.c + ) +' + +# If you add keywords in git of the form $Header$ then everything should +# work fine without any special handling. +test_expect_success 'Add keywords in git which match the default p4 values' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo "NewKW: \$Revision\$" >>kwfile1.c && + git add kwfile1.c && + git commit -m "Adding RCS keywords in git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + git p4 submit + ) && + ( + cd "$cli" && + p4 sync && + test -f kwfile1.c && + grep "NewKW.*Revision.*[0-9]" kwfile1.c + + ) +' + +# If you add keywords in git of the form $Header:#1$ then things will fail +# unless git-p4 takes steps to scrub the *git* commit. +# +test_expect_failure 'Add keywords in git which do not match the default p4 values' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + echo "NewKW2: \$Revision:1\$" >>kwfile1.c && + git add kwfile1.c && + git commit -m "Adding RCS keywords in git" && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + git p4 submit + ) && + ( + cd "$cli" && + p4 sync && + grep "NewKW2.*Revision.*[0-9]" kwfile1.c + + ) +' + +# Check that the existing merge conflict handling still works. +# Modify kwfile1.c in git, and delete in p4. We should be able +# to skip the git commit. +# +test_expect_success 'merge conflict handling still works' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + echo "Hello:\$Id\$" >merge2.c && + echo "World" >>merge2.c && + p4 add -t ktext merge2.c && + p4 submit -d "add merge test file" + ) && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + sed -e "/Hello/d" merge2.c >merge2.c.tmp && + mv merge2.c.tmp merge2.c && + git add merge2.c && + git commit -m "Modifying merge2.c" + ) && + ( + cd "$cli" && + p4 delete merge2.c && + p4 submit -d "remove merge test file" + ) && + ( + cd "$git" && + test -f merge2.c && + git config git-p4.skipSubmitEdit true && + git config git-p4.attemptRCSCleanup true && + !(echo "s" | git p4 submit) && + git rebase --skip && + ! test -f merge2.c + ) +' + + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh new file mode 100755 index 0000000000..095238fffe --- /dev/null +++ b/t/t9811-git-p4-label-import.sh @@ -0,0 +1,222 @@ +#!/bin/sh + +test_description='git p4 label tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# Basic p4 label import tests. +# +test_expect_success 'basic p4 labels' ' + test_when_finished cleanup_git && + ( + 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" && + + echo f3 >main/file_with_\$metachar && + p4 add main/file_with_\$metachar && + p4 submit -d "file with metachar" && + + p4 tag -l TAG_F1_ONLY main/f1 && + p4 tag -l TAG_WITH\$_SHELL_CHAR main/... && + p4 tag -l this_tag_will_be\ skipped main/... && + + echo f4 >main/f4 && + p4 add main/f4 && + p4 submit -d "main/f4" && + + p4 label -i <<-EOF && + Label: TAG_LONG_LABEL + Description: + A Label first line + A Label second line + View: //depot/... + EOF + + p4 tag -l TAG_LONG_LABEL ... && + + p4 labels ... && + + git p4 clone --dest="$git" //depot@all && + cd "$git" && + git config git-p4.labelImportRegexp ".*TAG.*" && + git p4 sync --import-labels --verbose && + + git tag && + git tag >taglist && + test_line_count = 3 taglist && + + cd main && + git checkout TAG_F1_ONLY && + ! test -f f2 && + git checkout TAG_WITH\$_SHELL_CHAR && + test -f f1 && test -f f2 && test -f file_with_\$metachar && + + git show TAG_LONG_LABEL | grep -q "A Label second line" + ) +' +# Test some label corner cases: +# +# - two tags on the same file; both should be available +# - a tag that is only on one file; this kind of tag +# cannot be imported (at least not easily). + +test_expect_success 'two labels on the same changelist' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + mkdir -p main && + + p4 edit main/f1 main/f2 && + echo "hello world" >main/f1 && + echo "not in the tag" >main/f2 && + p4 submit -d "main/f[12]: testing two labels" && + + p4 tag -l TAG_F1_1 main/... && + p4 tag -l TAG_F1_2 main/... && + + p4 labels ... && + + git p4 clone --dest="$git" //depot@all && + cd "$git" && + git p4 sync --import-labels && + + git tag | grep TAG_F1 && + git tag | grep -q TAG_F1_1 && + git tag | grep -q TAG_F1_2 && + + cd main && + + git checkout TAG_F1_1 && + ls && + test -f f1 && + + git checkout TAG_F1_2 && + ls && + test -f f1 + ) +' + +# Export some git tags to p4 +test_expect_success 'export git tags to p4' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot@all && + ( + cd "$git" && + git tag -m "A tag created in git:xyzzy" GIT_TAG_1 && + echo "hello world" >main/f10 && + git add main/f10 && + git commit -m "Adding file for export test" && + git config git-p4.skipSubmitEdit true && + git p4 submit && + git tag -m "Another git tag" GIT_TAG_2 && + git tag LIGHTWEIGHT_TAG && + git p4 rebase --import-labels --verbose && + git p4 submit --export-labels --verbose + ) && + ( + cd "$cli" && + p4 sync ... && + p4 labels ... | grep GIT_TAG_1 && + p4 labels ... | grep GIT_TAG_2 && + p4 labels ... | grep LIGHTWEIGHT_TAG && + p4 label -o GIT_TAG_1 | grep "tag created in git:xyzzy" && + p4 sync ...@GIT_TAG_1 && + ! test -f main/f10 + p4 sync ...@GIT_TAG_2 && + test -f main/f10 + ) +' + +# Export a tag from git where an affected file is deleted later on +# Need to create git tags after rebase, since only then can the +# git commits be mapped to p4 changelists. +test_expect_success 'export git tags to p4 with deletion' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot@all && + ( + cd "$git" && + git p4 sync --import-labels && + echo "deleted file" >main/deleted_file && + git add main/deleted_file && + git commit -m "create deleted file" && + git rm main/deleted_file && + echo "new file" >main/f11 && + git add main/f11 && + git commit -m "delete the deleted file" && + git config git-p4.skipSubmitEdit true && + git p4 submit && + git p4 rebase --import-labels --verbose && + git tag -m "tag on deleted file" GIT_TAG_ON_DELETED HEAD~1 && + git tag -m "tag after deletion" GIT_TAG_AFTER_DELETION HEAD && + git p4 submit --export-labels --verbose + ) && + ( + cd "$cli" && + p4 sync ... && + p4 sync ...@GIT_TAG_ON_DELETED && + test -f main/deleted_file && + p4 sync ...@GIT_TAG_AFTER_DELETION && + ! test -f main/deleted_file && + echo "checking label contents" && + p4 label -o GIT_TAG_ON_DELETED | grep "tag on deleted file" + ) +' + +# Create a tag in git that cannot be exported to p4 +test_expect_success 'tag that cannot be exported' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" //depot@all && + ( + cd "$git" && + git checkout -b a_branch && + echo "hello" >main/f12 && + git add main/f12 && + git commit -m "adding f12" && + git tag -m "tag on a_branch" GIT_TAG_ON_A_BRANCH && + git checkout master && + git p4 submit --export-labels + ) && + ( + cd "$cli" && + p4 sync ... && + !(p4 labels | grep GIT_TAG_ON_A_BRANCH) + ) +' + +test_expect_success 'use git config to enable import/export of tags' ' + git p4 clone --verbose --dest="$git" //depot@all && + ( + cd "$git" && + git config git-p4.exportLabels true && + git config git-p4.importLabels true && + git tag CFG_A_GIT_TAG && + git p4 rebase --verbose && + git p4 submit --verbose && + git tag && + git tag | grep TAG_F1_1 + ) && + ( + cd "$cli" && + p4 labels && + p4 labels | grep CFG_A_GIT_TAG + ) +' + + +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/t9902-completion.sh b/t/t9902-completion.sh new file mode 100755 index 0000000000..256e6a0b3f --- /dev/null +++ b/t/t9902-completion.sh @@ -0,0 +1,243 @@ +#!/bin/sh +# +# Copyright (c) 2012 Felipe Contreras +# + +if test -n "$BASH" && test -z "$POSIXLY_CORRECT"; then + # we are in full-on bash mode + true +elif type bash >/dev/null 2>&1; then + # execute in full-on bash mode + unset POSIXLY_CORRECT + exec bash "$0" "$@" +else + echo '1..0 #SKIP skipping bash completion tests; bash not available' + exit 0 +fi + +test_description='test bash completion' + +. ./test-lib.sh + +complete () +{ + # do nothing + return 0 +} + +. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" + +# We don't need this function to actually join words or do anything special. +# Also, it's cleaner to avoid touching bash's internal completion variables. +# So let's override it with a minimal version for testing purposes. +_get_comp_words_by_ref () +{ + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=${_words[_cword]} + ;; + prev) + prev=${_words[_cword-1]} + ;; + words) + words=("${_words[@]}") + ;; + cword) + cword=$_cword + ;; + esac + shift + done +} + +print_comp () +{ + local IFS=$'\n' + echo "${COMPREPLY[*]}" > out +} + +run_completion () +{ + local -a COMPREPLY _words + local _cword + _words=( $1 ) + (( _cword = ${#_words[@]} - 1 )) + __git_wrap__git_main && print_comp +} + +test_completion () +{ + test $# -gt 1 && echo "$2" > expected + run_completion "$@" && + test_cmp expected out +} + +newline=$'\n' + +test_expect_success '__gitcomp - trailing space - options' ' + sed -e "s/Z$//" >expected <<-\EOF && + --reuse-message=Z + --reedit-message=Z + --reset-author Z + EOF + ( + local -a COMPREPLY && + cur="--re" && + __gitcomp "--dry-run --reuse-message= --reedit-message= + --reset-author" && + IFS="$newline" && + echo "${COMPREPLY[*]}" > out + ) && + test_cmp expected out +' + +test_expect_success '__gitcomp - trailing space - config keys' ' + sed -e "s/Z$//" >expected <<-\EOF && + branch.Z + branch.autosetupmerge Z + branch.autosetuprebase Z + browser.Z + EOF + ( + local -a COMPREPLY && + cur="br" && + __gitcomp "branch. branch.autosetupmerge + branch.autosetuprebase browser." && + IFS="$newline" && + echo "${COMPREPLY[*]}" > out + ) && + test_cmp expected out +' + +test_expect_success '__gitcomp - option parameter' ' + sed -e "s/Z$//" >expected <<-\EOF && + recursive Z + resolve Z + EOF + ( + local -a COMPREPLY && + cur="--strategy=re" && + __gitcomp "octopus ours recursive resolve subtree + " "" "re" && + IFS="$newline" && + echo "${COMPREPLY[*]}" > out + ) && + test_cmp expected out +' + +test_expect_success '__gitcomp - prefix' ' + sed -e "s/Z$//" >expected <<-\EOF && + branch.maint.merge Z + branch.maint.mergeoptions Z + EOF + ( + local -a COMPREPLY && + cur="branch.me" && + __gitcomp "remote merge mergeoptions rebase + " "branch.maint." "me" && + IFS="$newline" && + echo "${COMPREPLY[*]}" > out + ) && + test_cmp expected out +' + +test_expect_success '__gitcomp - suffix' ' + sed -e "s/Z$//" >expected <<-\EOF && + branch.master.Z + branch.maint.Z + EOF + ( + local -a COMPREPLY && + cur="branch.me" && + __gitcomp "master maint next pu + " "branch." "ma" "." && + IFS="$newline" && + echo "${COMPREPLY[*]}" > out + ) && + test_cmp expected out +' + +test_expect_success 'basic' ' + run_completion "git \"\"" && + # built-in + grep -q "^add \$" out && + # script + grep -q "^filter-branch \$" out && + # plumbing + ! grep -q "^ls-files \$" out && + + run_completion "git f" && + ! grep -q -v "^f" out +' + +test_expect_success 'double dash "git" itself' ' + sed -e "s/Z$//" >expected <<-\EOF && + --paginate Z + --no-pager Z + --git-dir= + --bare Z + --version Z + --exec-path Z + --exec-path= + --html-path Z + --info-path Z + --work-tree= + --namespace= + --no-replace-objects Z + --help Z + EOF + test_completion "git --" +' + +test_expect_success 'double dash "git checkout"' ' + sed -e "s/Z$//" >expected <<-\EOF && + --quiet Z + --ours Z + --theirs Z + --track Z + --no-track Z + --merge Z + --conflict= + --orphan Z + --patch Z + EOF + test_completion "git checkout --" +' + +test_expect_success 'general options' ' + test_completion "git --ver" "--version " && + test_completion "git --hel" "--help " && + sed -e "s/Z$//" >expected <<-\EOF && + --exec-path Z + --exec-path= + EOF + test_completion "git --exe" && + test_completion "git --htm" "--html-path " && + test_completion "git --pag" "--paginate " && + test_completion "git --no-p" "--no-pager " && + test_completion "git --git" "--git-dir=" && + test_completion "git --wor" "--work-tree=" && + test_completion "git --nam" "--namespace=" && + test_completion "git --bar" "--bare " && + test_completion "git --inf" "--info-path " && + test_completion "git --no-r" "--no-replace-objects " +' + +test_expect_success 'general options plus command' ' + test_completion "git --version check" "checkout " && + test_completion "git --paginate check" "checkout " && + test_completion "git --git-dir=foo check" "checkout " && + test_completion "git --bare check" "checkout " && + test_completion "git --help des" "describe " && + test_completion "git --exec-path=foo check" "checkout " && + test_completion "git --html-path check" "checkout " && + test_completion "git --no-pager check" "checkout " && + test_completion "git --work-tree=foo check" "checkout " && + test_completion "git --namespace=foo check" "checkout " && + test_completion "git --paginate check" "checkout " && + test_completion "git --info-path check" "checkout " && + test_completion "git --no-replace-objects check" "checkout " +' + +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-functions.sh b/t/test-lib-functions.sh new file mode 100644 index 0000000000..80daaca780 --- /dev/null +++ b/t/test-lib-functions.sh @@ -0,0 +1,574 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/ . + +# The semantics of the editor variables are that of invoking +# sh -c "$EDITOR \"$@\"" files ... +# +# If our trash directory contains shell metacharacters, they will be +# interpreted if we just set $EDITOR directly, so do a little dance with +# environment variables to work around this. +# +# In particular, quoting isn't enough, as the path may contain the same quote +# that we're using. +test_set_editor () { + FAKE_EDITOR="$1" + export FAKE_EDITOR + EDITOR='"$FAKE_EDITOR"' + export EDITOR +} + +test_decode_color () { + awk ' + function name(n) { + if (n == 0) return "RESET"; + if (n == 1) return "BOLD"; + if (n == 30) return "BLACK"; + if (n == 31) return "RED"; + if (n == 32) return "GREEN"; + if (n == 33) return "YELLOW"; + if (n == 34) return "BLUE"; + if (n == 35) return "MAGENTA"; + if (n == 36) return "CYAN"; + if (n == 37) return "WHITE"; + if (n == 40) return "BLACK"; + if (n == 41) return "BRED"; + if (n == 42) return "BGREEN"; + if (n == 43) return "BYELLOW"; + if (n == 44) return "BBLUE"; + if (n == 45) return "BMAGENTA"; + if (n == 46) return "BCYAN"; + if (n == 47) return "BWHITE"; + } + { + while (match($0, /\033\[[0-9;]*m/) != 0) { + printf "%s<", substr($0, 1, RSTART-1); + codes = substr($0, RSTART+2, RLENGTH-3); + if (length(codes) == 0) + printf "%s", name(0) + else { + n = split(codes, ary, ";"); + sep = ""; + for (i = 1; i <= n; i++) { + printf "%s%s", sep, name(ary[i]); + sep = ";" + } + } + printf ">"; + $0 = substr($0, RSTART + RLENGTH, length($0) - RSTART - RLENGTH + 1); + } + print + } + ' +} + +nul_to_q () { + "$PERL_PATH" -pe 'y/\000/Q/' +} + +q_to_nul () { + "$PERL_PATH" -pe 'y/Q/\000/' +} + +q_to_cr () { + tr Q '\015' +} + +q_to_tab () { + tr Q '\011' +} + +append_cr () { + sed -e 's/$/Q/' | tr Q '\015' +} + +remove_cr () { + tr '\015' Q | sed -e 's/Q$//' +} + +# In some bourne shell implementations, the "unset" builtin returns +# nonzero status when a variable to be unset was not set in the first +# place. +# +# Use sane_unset when that should not be considered an error. + +sane_unset () { + unset "$@" + return 0 +} + +test_tick () { + if test -z "${test_tick+set}" + then + test_tick=1112911993 + else + test_tick=$(($test_tick + 60)) + fi + GIT_COMMITTER_DATE="$test_tick -0700" + GIT_AUTHOR_DATE="$test_tick -0700" + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE +} + +# Stop execution and start a shell. This is useful for debugging tests and +# only makes sense together with "-v". +# +# Be sure to remove all invocations of this command before submitting. + +test_pause () { + if test "$verbose" = t; then + "$SHELL_PATH" <&6 >&3 2>&4 + else + error >&5 "test_pause requires --verbose" + fi +} + +# Call test_commit with the arguments "<message> [<file> [<contents>]]" +# +# This will commit a file with the given contents and the given commit +# message. It will also add a tag with <message> as name. +# +# Both <file> and <contents> default to <message>. + +test_commit () { + notick= && + if test "z$1" = "z--notick" + then + notick=yes + shift + fi && + file=${2:-"$1.t"} && + echo "${3-$1}" > "$file" && + git add "$file" && + if test -z "$notick" + then + test_tick + fi && + git commit -m "$1" && + git tag "$1" +} + +# Call test_merge with the arguments "<message> <commit>", where <commit> +# can be a tag pointing to the commit-to-merge. + +test_merge () { + test_tick && + git merge -m "$1" "$2" && + git tag "$1" +} + +# This function helps systems where core.filemode=false is set. +# Use it instead of plain 'chmod +x' to set or unset the executable bit +# of a file in the working directory and add it to the index. + +test_chmod () { + 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 "$@" +} + +test_config_global () { + test_when_finished "test_unconfig --global '$1'" && + git config --global "$@" +} + +write_script () { + { + echo "#!${2-"$SHELL_PATH"}" && + cat + } >"$1" && + chmod +x "$1" +} + +# Use test_set_prereq to tell that a particular prerequisite is available. +# The prerequisite can later be checked for in two ways: +# +# - Explicitly using test_have_prereq. +# +# - Implicitly by specifying the prerequisite tag in the calls to +# test_expect_{success,failure,code}. +# +# The single parameter is the prerequisite tag (a simple word, in all +# capital letters by convention). + +test_set_prereq () { + satisfied="$satisfied$1 " +} +satisfied=" " + +test_have_prereq () { + # prerequisites can be concatenated with ',' + save_IFS=$IFS + IFS=, + set -- $* + IFS=$save_IFS + + total_prereq=0 + ok_prereq=0 + missing_prereq= + + for prerequisite + do + total_prereq=$(($total_prereq + 1)) + case $satisfied in + *" $prerequisite "*) + ok_prereq=$(($ok_prereq + 1)) + ;; + *) + # Keep a list of missing prerequisites + if test -z "$missing_prereq" + then + missing_prereq=$prerequisite + else + missing_prereq="$prerequisite,$missing_prereq" + fi + esac + done + + test $total_prereq = $ok_prereq +} + +test_declared_prereq () { + case ",$test_prereq," in + *,$1,*) + return 0 + ;; + esac + return 1 +} + +test_expect_failure () { + test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= + test "$#" = 2 || + error "bug in the test script: not 2 or 3 parameters to test-expect-failure" + export test_prereq + if ! test_skip "$@" + then + say >&3 "checking known breakage: $2" + if test_run_ "$2" expecting_failure + then + test_known_broken_ok_ "$1" + else + test_known_broken_failure_ "$1" + fi + fi + echo >&3 "" +} + +test_expect_success () { + test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= + test "$#" = 2 || + error "bug in the test script: not 2 or 3 parameters to test-expect-success" + export test_prereq + if ! test_skip "$@" + then + say >&3 "expecting success: $2" + if test_run_ "$2" + then + test_ok_ "$1" + else + test_failure_ "$@" + fi + fi + echo >&3 "" +} + +# test_external runs external test scripts that provide continuous +# test output about their progress, and succeeds/fails on +# zero/non-zero exit code. It outputs the test output on stdout even +# in non-verbose mode, and announces the external script with "# run +# <n>: ..." before running it. When providing relative paths, keep in +# mind that all scripts run in "trash directory". +# Usage: test_external description command arguments... +# Example: test_external 'Perl API' perl ../path/to/test.pl +test_external () { + test "$#" = 4 && { test_prereq=$1; shift; } || test_prereq= + test "$#" = 3 || + error >&5 "bug in the test script: not 3 or 4 parameters to test_external" + descr="$1" + shift + export test_prereq + if ! test_skip "$descr" "$@" + then + # Announce the script to reduce confusion about the + # test output that follows. + say_color "" "# run $test_count: $descr ($*)" + # Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG + # to be able to use them in script + export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG + # Run command; redirect its stderr to &4 as in + # test_run_, but keep its stdout on our stdout even in + # non-verbose mode. + "$@" 2>&4 + if [ "$?" = 0 ] + then + if test $test_external_has_tap -eq 0; then + test_ok_ "$descr" + else + say_color "" "# test_external test $descr was ok" + test_success=$(($test_success + 1)) + fi + else + if test $test_external_has_tap -eq 0; then + test_failure_ "$descr" "$@" + else + say_color error "# test_external test $descr failed: $@" + test_failure=$(($test_failure + 1)) + fi + fi + fi +} + +# Like test_external, but in addition tests that the command generated +# no output on stderr. +test_external_without_stderr () { + # The temporary file has no (and must have no) security + # implications. + tmp=${TMPDIR:-/tmp} + stderr="$tmp/git-external-stderr.$$.tmp" + test_external "$@" 4> "$stderr" + [ -f "$stderr" ] || error "Internal error: $stderr disappeared." + descr="no stderr: $1" + shift + say >&3 "# expecting no stderr from previous command" + if [ ! -s "$stderr" ]; then + rm "$stderr" + + if test $test_external_has_tap -eq 0; then + test_ok_ "$descr" + else + say_color "" "# test_external_without_stderr test $descr was ok" + test_success=$(($test_success + 1)) + fi + else + if [ "$verbose" = t ]; then + output=`echo; echo "# Stderr is:"; cat "$stderr"` + else + output= + fi + # rm first in case test_failure exits. + rm "$stderr" + if test $test_external_has_tap -eq 0; then + test_failure_ "$descr" "$@" "$output" + else + say_color error "# test_external_without_stderr test $descr failed: $@: $output" + test_failure=$(($test_failure + 1)) + fi + fi +} + +# debugging-friendly alternatives to "test [-f|-d|-e]" +# The commands test the existence or non-existence of $1. $2 can be +# given to provide a more precise diagnosis. +test_path_is_file () { + if ! [ -f "$1" ] + then + echo "File $1 doesn't exist. $*" + false + fi +} + +test_path_is_dir () { + if ! [ -d "$1" ] + then + echo "Directory $1 doesn't exist. $*" + false + fi +} + +test_path_is_missing () { + if [ -e "$1" ] + then + echo "Path exists:" + ls -ld "$1" + if [ $# -ge 1 ]; then + echo "$*" + fi + false + fi +} + +# test_line_count checks that a file has the number of lines it +# ought to. For example: +# +# test_expect_success 'produce exactly one line of output' ' +# do something >output && +# test_line_count = 1 output +# ' +# +# is like "test $(wc -l <output) = 1" except that it passes the +# output through when the number of lines is wrong. + +test_line_count () { + if test $# != 3 + then + error "bug in the test script: not 3 parameters to test_line_count" + elif ! test $(wc -l <"$3") "$1" "$2" + then + echo "test_line_count: line count for $3 !$1 $2" + cat "$3" + return 1 + fi +} + +# This is not among top-level (test_expect_success | test_expect_failure) +# but is a prefix that can be used in the test script, like: +# +# test_expect_success 'complain and die' ' +# do something && +# do something else && +# test_must_fail git checkout ../outerspace +# ' +# +# Writing this as "! git checkout ../outerspace" is wrong, because +# the failure could be due to a segv. We want a controlled failure. + +test_must_fail () { + "$@" + exit_code=$? + if test $exit_code = 0; then + echo >&2 "test_must_fail: command succeeded: $*" + return 1 + elif test $exit_code -gt 129 -a $exit_code -le 192; then + echo >&2 "test_must_fail: died by signal: $*" + return 1 + elif test $exit_code = 127; then + echo >&2 "test_must_fail: command not found: $*" + return 1 + fi + return 0 +} + +# Similar to test_must_fail, but tolerates success, too. This is +# meant to be used in contexts like: +# +# test_expect_success 'some command works without configuration' ' +# test_might_fail git config --unset all.configuration && +# do something +# ' +# +# Writing "git config --unset all.configuration || :" would be wrong, +# because we want to notice if it fails due to segv. + +test_might_fail () { + "$@" + exit_code=$? + if test $exit_code -gt 129 -a $exit_code -le 192; then + echo >&2 "test_might_fail: died by signal: $*" + return 1 + elif test $exit_code = 127; then + echo >&2 "test_might_fail: command not found: $*" + return 1 + fi + return 0 +} + +# Similar to test_must_fail and test_might_fail, but check that a +# given command exited with a given exit code. Meant to be used as: +# +# test_expect_success 'Merge with d/f conflicts' ' +# test_expect_code 1 git merge "merge msg" B master +# ' + +test_expect_code () { + want_code=$1 + shift + "$@" + exit_code=$? + if test $exit_code = $want_code + then + return 0 + 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. +# You can use it like: +# +# test_expect_success 'foo works' ' +# echo expected >expected && +# foo >actual && +# test_cmp expected actual +# ' +# +# This could be written as either "cmp" or "diff -u", but: +# - cmp's output is not nearly as easy to read as diff -u +# - not all diff versions understand "-u" + +test_cmp() { + $GIT_TEST_CMP "$@" +} + +# This function can be used to schedule some commands to be run +# unconditionally at the end of the test to restore sanity: +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# test_when_finished "git config --unset core.capslock" && +# hello world +# ' +# +# That would be roughly equivalent to +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# hello world +# git config --unset core.capslock +# ' +# +# 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="{ $* + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" +} + +# Most tests can use the created repository, but some may need to create more. +# Usage: test_create_repo <directory> +test_create_repo () { + test "$#" = 1 || + error "bug in the test script: not 1 parameter to test-create-repo" + repo="$1" + mkdir -p "$repo" + ( + cd "$repo" || error "Cannot setup test environment" + "$GIT_EXEC_PATH/git-init" "--template=$GIT_BUILD_DIR/templates/blt/" >&3 2>&4 || + error "cannot run git init -- have you built things yet?" + mv .git/hooks .git/hooks-disabled + ) || exit +} diff --git a/t/test-lib.sh b/t/test-lib.sh index 8c57a00595..acda33d177 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -42,9 +42,11 @@ TZ=UTC TERM=dumb export LANG LC_ALL PAGER TERM TZ EDITOR=: -unset VISUAL -unset EMAIL -unset $(perl -e ' +# A call to "unset" with no arguments causes at least Solaris 10 +# /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets +# deriving from the command substitution clustered with the other +# ones. +unset VISUAL EMAIL LANGUAGE COLUMNS $(perl -e ' my @env = keys %ENV; my $ok = join("|", qw( TRACE @@ -54,6 +56,7 @@ unset $(perl -e ' .*_TEST PROVE VALGRIND + PERF_AGGREGATING_LATER )); my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); print join("\n", @vars); @@ -63,7 +66,8 @@ GIT_AUTHOR_NAME='A U Thor' GIT_COMMITTER_EMAIL=committer@example.com GIT_COMMITTER_NAME='C O Mitter' GIT_MERGE_VERBOSITY=5 -export GIT_MERGE_VERBOSITY +GIT_MERGE_AUTOEDIT=no +export GIT_MERGE_VERBOSITY GIT_MERGE_AUTOEDIT export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export EDITOR @@ -92,6 +96,12 @@ _x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05" # Zero SHA-1 _z40=0000000000000000000000000000000000000000 +# Line feed +LF=' +' + +export _x05 _x40 _z40 LF + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... @@ -187,6 +197,7 @@ then fi exec 5>&1 +exec 6<&0 if test "$verbose" = "t" then exec 4>&2 3>&1 @@ -216,203 +227,9 @@ die () { GIT_EXIT_OK= trap 'die' EXIT -# The semantics of the editor variables are that of invoking -# sh -c "$EDITOR \"$@\"" files ... -# -# If our trash directory contains shell metacharacters, they will be -# interpreted if we just set $EDITOR directly, so do a little dance with -# environment variables to work around this. -# -# In particular, quoting isn't enough, as the path may contain the same quote -# that we're using. -test_set_editor () { - FAKE_EDITOR="$1" - export FAKE_EDITOR - EDITOR='"$FAKE_EDITOR"' - export EDITOR -} - -test_decode_color () { - awk ' - function name(n) { - if (n == 0) return "RESET"; - if (n == 1) return "BOLD"; - if (n == 30) return "BLACK"; - if (n == 31) return "RED"; - if (n == 32) return "GREEN"; - if (n == 33) return "YELLOW"; - if (n == 34) return "BLUE"; - if (n == 35) return "MAGENTA"; - if (n == 36) return "CYAN"; - if (n == 37) return "WHITE"; - if (n == 40) return "BLACK"; - if (n == 41) return "BRED"; - if (n == 42) return "BGREEN"; - if (n == 43) return "BYELLOW"; - if (n == 44) return "BBLUE"; - if (n == 45) return "BMAGENTA"; - if (n == 46) return "BCYAN"; - if (n == 47) return "BWHITE"; - } - { - while (match($0, /\033\[[0-9;]*m/) != 0) { - printf "%s<", substr($0, 1, RSTART-1); - codes = substr($0, RSTART+2, RLENGTH-3); - if (length(codes) == 0) - printf "%s", name(0) - else { - n = split(codes, ary, ";"); - sep = ""; - for (i = 1; i <= n; i++) { - printf "%s%s", sep, name(ary[i]); - sep = ";" - } - } - printf ">"; - $0 = substr($0, RSTART + RLENGTH, length($0) - RSTART - RLENGTH + 1); - } - print - } - ' -} - -nul_to_q () { - perl -pe 'y/\000/Q/' -} - -q_to_nul () { - perl -pe 'y/Q/\000/' -} - -q_to_cr () { - tr Q '\015' -} - -q_to_tab () { - tr Q '\011' -} - -append_cr () { - sed -e 's/$/Q/' | tr Q '\015' -} - -remove_cr () { - tr '\015' Q | sed -e 's/Q$//' -} - -# In some bourne shell implementations, the "unset" builtin returns -# nonzero status when a variable to be unset was not set in the first -# place. -# -# Use sane_unset when that should not be considered an error. - -sane_unset () { - unset "$@" - return 0 -} - -test_tick () { - if test -z "${test_tick+set}" - then - test_tick=1112911993 - else - test_tick=$(($test_tick + 60)) - fi - GIT_COMMITTER_DATE="$test_tick -0700" - GIT_AUTHOR_DATE="$test_tick -0700" - export GIT_COMMITTER_DATE GIT_AUTHOR_DATE -} - -# Call test_commit with the arguments "<message> [<file> [<contents>]]" -# -# This will commit a file with the given contents and the given commit -# message. It will also add a tag with <message> as name. -# -# Both <file> and <contents> default to <message>. - -test_commit () { - file=${2:-"$1.t"} - echo "${3-$1}" > "$file" && - git add "$file" && - test_tick && - git commit -m "$1" && - git tag "$1" -} - -# Call test_merge with the arguments "<message> <commit>", where <commit> -# can be a tag pointing to the commit-to-merge. - -test_merge () { - test_tick && - git merge -m "$1" "$2" && - git tag "$1" -} - -# This function helps systems where core.filemode=false is set. -# Use it instead of plain 'chmod +x' to set or unset the executable bit -# of a file in the working directory and add it to the index. - -test_chmod () { - chmod "$@" && - git update-index --add "--chmod=$@" -} - -# Use test_set_prereq to tell that a particular prerequisite is available. -# The prerequisite can later be checked for in two ways: -# -# - Explicitly using test_have_prereq. -# -# - Implicitly by specifying the prerequisite tag in the calls to -# test_expect_{success,failure,code}. -# -# The single parameter is the prerequisite tag (a simple word, in all -# capital letters by convention). - -test_set_prereq () { - satisfied="$satisfied$1 " -} -satisfied=" " - -test_have_prereq () { - # prerequisites can be concatenated with ',' - save_IFS=$IFS - IFS=, - set -- $* - IFS=$save_IFS - - total_prereq=0 - ok_prereq=0 - missing_prereq= - - for prerequisite - do - total_prereq=$(($total_prereq + 1)) - case $satisfied in - *" $prerequisite "*) - ok_prereq=$(($ok_prereq + 1)) - ;; - *) - # Keep a list of missing prerequisites - if test -z "$missing_prereq" - then - missing_prereq=$prerequisite - else - missing_prereq="$prerequisite,$missing_prereq" - fi - esac - done - - test $total_prereq = $ok_prereq -} - -test_declared_prereq () { - case ",$test_prereq," in - *,$1,*) - return 0 - ;; - esac - return 1 -} +# The user-facing functions are loaded from a separate file so that +# test_perf subshells can have them too +. "${TEST_DIRECTORY:-.}"/test-lib-functions.sh # You are not expected to call test_ok_ and test_failure_ directly, use # the text_expect_* functions instead. @@ -444,15 +261,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 </dev/null >&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 () { @@ -489,317 +317,16 @@ test_skip () { esac } -test_expect_failure () { - test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= - test "$#" = 2 || - error "bug in the test script: not 2 or 3 parameters to test-expect-failure" - export test_prereq - if ! test_skip "$@" - then - say >&3 "checking known breakage: $2" - test_run_ "$2" - if [ "$?" = 0 -a "$eval_ret" = 0 ] - then - test_known_broken_ok_ "$1" - else - test_known_broken_failure_ "$1" - fi - fi - echo >&3 "" -} - -test_expect_success () { - test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= - test "$#" = 2 || - error "bug in the test script: not 2 or 3 parameters to test-expect-success" - export test_prereq - if ! test_skip "$@" - then - say >&3 "expecting success: $2" - test_run_ "$2" - if [ "$?" = 0 -a "$eval_ret" = 0 ] - then - test_ok_ "$1" - else - test_failure_ "$@" - fi - fi - echo >&3 "" -} - -# test_external runs external test scripts that provide continuous -# test output about their progress, and succeeds/fails on -# zero/non-zero exit code. It outputs the test output on stdout even -# in non-verbose mode, and announces the external script with "# run -# <n>: ..." before running it. When providing relative paths, keep in -# mind that all scripts run in "trash directory". -# Usage: test_external description command arguments... -# Example: test_external 'Perl API' perl ../path/to/test.pl -test_external () { - test "$#" = 4 && { test_prereq=$1; shift; } || test_prereq= - test "$#" = 3 || - error >&5 "bug in the test script: not 3 or 4 parameters to test_external" - descr="$1" - shift - export test_prereq - if ! test_skip "$descr" "$@" - then - # Announce the script to reduce confusion about the - # test output that follows. - say_color "" "# run $test_count: $descr ($*)" - # Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG - # to be able to use them in script - export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG - # Run command; redirect its stderr to &4 as in - # test_run_, but keep its stdout on our stdout even in - # non-verbose mode. - "$@" 2>&4 - if [ "$?" = 0 ] - then - if test $test_external_has_tap -eq 0; then - test_ok_ "$descr" - else - say_color "" "# test_external test $descr was ok" - test_success=$(($test_success + 1)) - fi - else - if test $test_external_has_tap -eq 0; then - test_failure_ "$descr" "$@" - else - say_color error "# test_external test $descr failed: $@" - test_failure=$(($test_failure + 1)) - fi - fi - fi -} - -# Like test_external, but in addition tests that the command generated -# no output on stderr. -test_external_without_stderr () { - # The temporary file has no (and must have no) security - # implications. - tmp=${TMPDIR:-/tmp} - stderr="$tmp/git-external-stderr.$$.tmp" - test_external "$@" 4> "$stderr" - [ -f "$stderr" ] || error "Internal error: $stderr disappeared." - descr="no stderr: $1" - shift - say >&3 "# expecting no stderr from previous command" - if [ ! -s "$stderr" ]; then - rm "$stderr" - - if test $test_external_has_tap -eq 0; then - test_ok_ "$descr" - else - say_color "" "# test_external_without_stderr test $descr was ok" - test_success=$(($test_success + 1)) - fi - else - if [ "$verbose" = t ]; then - output=`echo; echo "# Stderr is:"; cat "$stderr"` - else - output= - fi - # rm first in case test_failure exits. - rm "$stderr" - if test $test_external_has_tap -eq 0; then - test_failure_ "$descr" "$@" "$output" - else - say_color error "# test_external_without_stderr test $descr failed: $@: $output" - test_failure=$(($test_failure + 1)) - fi - fi -} - -# debugging-friendly alternatives to "test [-f|-d|-e]" -# The commands test the existence or non-existence of $1. $2 can be -# given to provide a more precise diagnosis. -test_path_is_file () { - if ! [ -f "$1" ] - then - echo "File $1 doesn't exist. $*" - false - fi -} - -test_path_is_dir () { - if ! [ -d "$1" ] - then - echo "Directory $1 doesn't exist. $*" - false - fi -} - -test_path_is_missing () { - if [ -e "$1" ] - then - echo "Path exists:" - ls -ld "$1" - if [ $# -ge 1 ]; then - echo "$*" - fi - false - fi -} - -# test_line_count checks that a file has the number of lines it -# ought to. For example: -# -# test_expect_success 'produce exactly one line of output' ' -# do something >output && -# test_line_count = 1 output -# ' -# -# is like "test $(wc -l <output) = 1" except that it passes the -# output through when the number of lines is wrong. - -test_line_count () { - if test $# != 3 - then - error "bug in the test script: not 3 parameters to test_line_count" - elif ! test $(wc -l <"$3") "$1" "$2" - then - echo "test_line_count: line count for $3 !$1 $2" - cat "$3" - return 1 - fi -} - -# This is not among top-level (test_expect_success | test_expect_failure) -# but is a prefix that can be used in the test script, like: -# -# test_expect_success 'complain and die' ' -# do something && -# do something else && -# test_must_fail git checkout ../outerspace -# ' -# -# Writing this as "! git checkout ../outerspace" is wrong, because -# the failure could be due to a segv. We want a controlled failure. - -test_must_fail () { - "$@" - exit_code=$? - if test $exit_code = 0; then - echo >&2 "test_must_fail: command succeeded: $*" - return 1 - elif test $exit_code -gt 129 -a $exit_code -le 192; then - echo >&2 "test_must_fail: died by signal: $*" - return 1 - elif test $exit_code = 127; then - echo >&2 "test_must_fail: command not found: $*" - return 1 - fi - return 0 -} - -# Similar to test_must_fail, but tolerates success, too. This is -# meant to be used in contexts like: -# -# test_expect_success 'some command works without configuration' ' -# test_might_fail git config --unset all.configuration && -# do something -# ' -# -# Writing "git config --unset all.configuration || :" would be wrong, -# because we want to notice if it fails due to segv. - -test_might_fail () { - "$@" - exit_code=$? - if test $exit_code -gt 129 -a $exit_code -le 192; then - echo >&2 "test_might_fail: died by signal: $*" - return 1 - elif test $exit_code = 127; then - echo >&2 "test_might_fail: command not found: $*" - return 1 - fi - return 0 -} - -# Similar to test_must_fail and test_might_fail, but check that a -# given command exited with a given exit code. Meant to be used as: -# -# test_expect_success 'Merge with d/f conflicts' ' -# test_expect_code 1 git merge "merge msg" B master -# ' - -test_expect_code () { - want_code=$1 - shift - "$@" - exit_code=$? - if test $exit_code = $want_code - then - return 0 - 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. -# You can use it like: -# -# test_expect_success 'foo works' ' -# echo expected >expected && -# foo >actual && -# test_cmp expected actual -# ' -# -# This could be written as either "cmp" or "diff -u", but: -# - cmp's output is not nearly as easy to read as diff -u -# - not all diff versions understand "-u" - -test_cmp() { - $GIT_TEST_CMP "$@" -} - -# This function can be used to schedule some commands to be run -# unconditionally at the end of the test to restore sanity: -# -# test_expect_success 'test core.capslock' ' -# git config core.capslock true && -# test_when_finished "git config --unset core.capslock" && -# hello world -# ' -# -# That would be roughly equivalent to -# -# test_expect_success 'test core.capslock' ' -# git config core.capslock true && -# hello world -# git config --unset core.capslock -# ' -# -# except that the greeting and config --unset must both succeed for -# the test to pass. - -test_when_finished () { - test_cleanup="{ $* - } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" -} - -# Most tests can use the created repository, but some may need to create more. -# Usage: test_create_repo <directory> -test_create_repo () { - test "$#" = 1 || - error "bug in the test script: not 1 parameter to test-create-repo" - repo="$1" - mkdir -p "$repo" - ( - cd "$repo" || error "Cannot setup test environment" - "$GIT_EXEC_PATH/git-init" "--template=$GIT_BUILD_DIR/templates/blt/" >&3 2>&4 || - error "cannot run git init -- have you built things yet?" - mv .git/hooks .git/hooks-disabled - ) || exit +# stub; perf-lib overrides it +test_at_end_hook_ () { + : } test_done () { GIT_EXIT_OK=t if test -z "$HARNESS_ACTIVE"; then - test_results_dir="$TEST_DIRECTORY/test-results" + test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results" mkdir -p "$test_results_dir" test_results_path="$test_results_dir/${0%.sh}-$$.counts" @@ -838,6 +365,8 @@ test_done () { cd "$(dirname "$remove_trash")" && rm -rf "$(basename "$remove_trash")" + test_at_end_hook_ + exit 0 ;; *) @@ -860,6 +389,12 @@ then # itself. TEST_DIRECTORY=$(pwd) fi +if test -z "$TEST_OUTPUT_DIRECTORY" +then + # Similarly, override this to store the test-results subdir + # elsewhere + TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY +fi GIT_BUILD_DIR="$TEST_DIRECTORY"/.. if test -n "$valgrind" @@ -916,6 +451,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 @@ -957,6 +494,8 @@ export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +export PERL_PATH + if test -z "$GIT_TEST_CMP" then if test -n "$GIT_TEST_CMP_USE_COPIED_CONTEXT" @@ -993,7 +532,7 @@ test="trash directory.$(basename "$0" .sh)" test -n "$root" && test="$root/$test" case "$test" in /*) TRASH_DIRECTORY="$test" ;; - *) TRASH_DIRECTORY="$TEST_DIRECTORY/$test" ;; + *) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$test" ;; esac test ! -z "$debug" || remove_trash=$TRASH_DIRECTORY rm -fr "$test" || { @@ -1005,7 +544,11 @@ rm -fr "$test" || { HOME="$TRASH_DIRECTORY" export HOME -test_create_repo "$test" +if test -z "$TEST_NO_CREATE_REPO"; then + test_create_repo "$test" +else + mkdir -p "$test" +fi # 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 @@ -1074,15 +617,18 @@ case $(uname -s) in ;; esac +( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1 test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PYTHON" && test_set_prereq PYTHON test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE +test -z "$NO_GETTEXT" && test_set_prereq GETTEXT # 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 + test_set_prereq GETTEXT_POISON else test_set_prereq C_LOCALE_OUTPUT fi diff --git a/t/test-terminal.perl b/t/test-terminal.perl index ee01eb957e..10172aee18 100755 --- a/t/test-terminal.perl +++ b/t/test-terminal.perl @@ -69,6 +69,10 @@ if ($#ARGV < 1) { } my $master_out = new IO::Pty; my $master_err = new IO::Pty; +$master_out->set_raw(); +$master_err->set_raw(); +$master_out->slave->set_raw(); +$master_err->slave->set_raw(); my $pid = start_child(\@ARGV, $master_out->slave, $master_err->slave); close $master_out->slave; close $master_err->slave; 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 |