diff options
Diffstat (limited to 't')
303 files changed, 12164 insertions, 2898 deletions
diff --git a/t/Makefile b/t/Makefile index 9046ec9816..6091211f10 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) @@ -73,6 +73,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 +114,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 @@ -548,6 +548,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 +671,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/gitweb-lib.sh b/t/gitweb-lib.sh index 292753f77c..21d11d6c2d 100644 --- a/t/gitweb-lib.sh +++ b/t/gitweb-lib.sh @@ -16,6 +16,7 @@ our \$projectroot = "$safe_pwd"; our \$project_maxdepth = 8; our \$home_link_str = 'projects'; our \$site_name = '[localhost]'; +our \$site_html_head_string = ''; our \$site_header = ''; our \$site_footer = ''; our \$home_text = 'indextext.html'; 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-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..ef2d01f369 --- /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 + echo >&4 "$line" + cat >&4 & + + # 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 + } <git_daemon_output +} + +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..a870f9a5d2 --- /dev/null +++ b/t/lib-git-p4.sh @@ -0,0 +1,74 @@ +# +# Library code for git-p4 tests +# + +. ./test-lib.sh + +if ! test_have_prereq PYTHON; then + skip_all='skipping git-p4 tests; python not available' + test_done +fi +( p4 -h && p4d -h ) >/dev/null 2>&1 || { + skip_all='skipping git-p4 tests; no p4 or p4d' + test_done +} + +GITP4="$GIT_BUILD_DIR/contrib/fast-import/git-p4" + +# Try to pick a unique port: guess a large number, then hope +# no more than one of each test is running. +# +# This does not handle the case where somebody else is running the +# same tests and has chosen the same ports. +testid=${this_test#t} +git_p4_test_start=9800 +P4DPORT=$((10669 + ($testid - $git_p4_test_start))) + +export P4PORT=localhost:$P4DPORT +export P4CLIENT=client + +db="$TRASH_DIRECTORY/db" +cli="$TRASH_DIRECTORY/cli" +git="$TRASH_DIRECTORY/git" +pidfile="$TRASH_DIRECTORY/p4d.pid" + +start_p4d() { + mkdir -p "$db" "$cli" "$git" && + ( + p4d -q -r "$db" -p $P4DPORT & + echo $! >"$pidfile" + ) && + for i in 1 2 3 4 5 ; do + p4 info >/dev/null 2>&1 && break || true && + echo waiting for p4d to start && + sleep 1 + done && + # complain if it never started + p4 info >/dev/null && + ( + cd "$cli" && + p4 client -i <<-EOF + Client: client + Description: client + Root: $cli + View: //depot/... //client/... + EOF + ) +} + +kill_p4d() { + pid=$(cat "$pidfile") + # it had better exist for the first kill + kill $pid && + for i in 1 2 3 4 5 ; do + kill $pid >/dev/null 2>&1 || break + sleep 1 + done && + # complain if it would not die + test_must_fail kill $pid >/dev/null 2>&1 && + rm -rf "$db" "$cli" "$pidfile" +} + +cleanup_git() { + rm -rf "$git" +} diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh new file mode 100755 index 0000000000..05824fa8e4 --- /dev/null +++ b/t/lib-gpg.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +gpg_version=`gpg --version 2>&1` +if test $? = 127; then + say "You do not seem to have gpg installed" +else + # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 + # the gpg version 1.0.6 didn't parse trust packets correctly, so for + # that version, creation of signed tags using the generated key fails. + case "$gpg_version" in + 'gpg (GnuPG) 1.0.6'*) + say "Your version of gpg (1.0.6) is too buggy for testing" + ;; + *) + # key generation info: gpg --homedir t/lib-gpg --gen-key + # Type DSA and Elgamal, size 2048 bits, no expiration date. + # Name and email: C O Mitter <committer@example.com> + # No password given, to enable non-interactive operation. + cp -R "$TEST_DIRECTORY"/lib-gpg ./gpghome + chmod 0700 gpghome + GNUPGHOME="$(pwd)/gpghome" + export GNUPGHOME + test_set_prereq GPG + ;; + esac +fi + +sanitize_pgp() { + perl -ne ' + /^-----END PGP/ and $in_pgp = 0; + print unless $in_pgp; + /^-----BEGIN PGP/ and $in_pgp = 1; + ' +} diff --git a/t/t7004/pubring.gpg b/t/lib-gpg/pubring.gpg Binary files differindex 83855fa4e1..83855fa4e1 100644 --- a/t/t7004/pubring.gpg +++ b/t/lib-gpg/pubring.gpg diff --git a/t/t7004/random_seed b/t/lib-gpg/random_seed Binary files differindex 8fed1339ed..8fed1339ed 100644 --- a/t/t7004/random_seed +++ b/t/lib-gpg/random_seed diff --git a/t/t7004/secring.gpg b/t/lib-gpg/secring.gpg Binary files differindex d831cd9eb3..d831cd9eb3 100644 --- a/t/t7004/secring.gpg +++ b/t/lib-gpg/secring.gpg diff --git a/t/t7004/trustdb.gpg b/t/lib-gpg/trustdb.gpg Binary files differindex abace962b8..abace962b8 100644 --- a/t/t7004/trustdb.gpg +++ b/t/lib-gpg/trustdb.gpg diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index b8996a373a..f7dc0781d5 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -81,8 +81,7 @@ prepare_httpd() { if test -n "$LIB_HTTPD_SSL" then - HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT - AUTH_HTTPD_URL=https://user%40host:user%40host@127.0.0.1:$LIB_HTTPD_PORT + HTTPD_PROTO=https RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \ -config "$TEST_PATH/ssl.cnf" \ @@ -93,9 +92,12 @@ prepare_httpd() { export GIT_SSL_NO_VERIFY HTTPD_PARA="$HTTPD_PARA -DSSL" else - HTTPD_URL=http://127.0.0.1:$LIB_HTTPD_PORT - AUTH_HTTPD_URL=http://user%40host:user%40host@127.0.0.1:$LIB_HTTPD_PORT + HTTPD_PROTO=http fi + HTTPD_DEST=127.0.0.1:$LIB_HTTPD_PORT + HTTPD_URL=$HTTPD_PROTO://$HTTPD_DEST + HTTPD_URL_USER=$HTTPD_PROTO://user%40host@$HTTPD_DEST + HTTPD_URL_USER_PASS=$HTTPD_PROTO://user%40host:user%40host@$HTTPD_DEST if test -n "$LIB_HTTPD_DAV" -o -n "$LIB_HTTPD_SVN" then diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 0a4cdfa93e..3c12b05d60 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -92,6 +92,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/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 19265c77cf..51f3045ba4 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -5,20 +5,16 @@ test_description=gitattributes . ./test-lib.sh attr_check () { - - path="$1" - expect="$2" + path="$1" expect="$2" git $3 check-attr test -- "$path" >actual 2>err && echo "$path: test: $2" >expect && test_cmp expect actual && test_line_count = 0 err - } test_expect_success 'setup' ' - mkdir -p a/b/d a/c b && ( echo "[attr]notest !test" @@ -41,29 +37,27 @@ test_expect_success 'setup' ' ( echo "global test=global" ) >"$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 - + 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 && @@ -73,11 +67,9 @@ test_expect_success 'command line checks' ' 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 && @@ -91,7 +83,6 @@ 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' ' @@ -151,16 +142,13 @@ test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' ' ' 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) && @@ -169,7 +157,6 @@ test_expect_success 'relative paths' ' (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' ' @@ -188,41 +175,43 @@ test_expect_success 'core.attributesfile' ' attr_check global global && git config core.attributesfile "~/global-gitattributes" && attr_check global global && - echo "global test=precedence" >> .gitattributes && + echo "global test=precedence" >>.gitattributes && attr_check global precedence ' test_expect_success 'attribute test: read paths from stdin' ' - - grep -v notest < expect-all > expect && - 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 '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 +' - grep -v unspecified < expect-all | sort > expect && - sed -e "s/:.*//" < expect-all | uniq | - git check-attr --stdin --all | sort > actual && - test_cmp expect 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" @@ -232,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" @@ -246,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/t0021-conversion.sh b/t/t0021-conversion.sh index f19e6510d0..e50f0f742f 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -153,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/t0040-parse-options.sh b/t/t0040-parse-options.sh index 007f39d5e1..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 @@ -53,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 @@ -87,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 ' @@ -180,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 @@ -296,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 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/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..267f4c8ba3 --- /dev/null +++ b/t/t0303-credential-external.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +test_description='external credential helper tests' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential.sh + +pre_test() { + 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" +} + +post_test() { + # 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" +} + +if test -z "$GIT_TEST_CREDENTIAL_HELPER"; then + say "# skipping external helper tests (set GIT_TEST_CREDENTIAL_HELPER)" +else + pre_test + helper_test "$GIT_TEST_CREDENTIAL_HELPER" + post_test +fi + +if test -z "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT"; then + say "# skipping external helper timeout tests" +else + pre_test + helper_test_timeout "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT" + post_test +fi + +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/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 index 0a9cedd374..fbf5f2fc00 100755 --- a/t/t1013-loose-object-format.sh +++ b/t/t1013-loose-object-format.sh @@ -34,7 +34,7 @@ assert_blob_equals() { } test_expect_success setup ' - cp -R "$TEST_DIRECTORY/t1013/objects" .git/ + cp -R "$TEST_DIRECTORY/t1013/objects" .git/ && git --version ' diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 3b1b985996..e23ac0e69d 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -118,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 && diff --git a/t/t1050-large.sh b/t/t1050-large.sh index deba111bd7..29d6024b7f 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -7,21 +7,97 @@ test_description='adding and checking out large blobs' test_expect_success setup ' git config core.bigfilethreshold 200k && - echo X | dd of=large bs=1k seek=2000 + 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 ' -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_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/t1200-tutorial.sh b/t/t1200-tutorial.sh index 5e29e13782..9356beaf4b 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -156,7 +156,7 @@ Updating VARIABLE..VARIABLE FASTFORWARD (no commit created; -m option ignored) example | 1 + hello | 1 + - 2 files changed, 2 insertions(+), 0 deletions(-) + 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 dffccf84f8..36e227b3bb 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] @@ -367,8 +399,6 @@ cat > .git/config << EOF c = d EOF -git config a.x y - cat > expect << EOF [a.b] c = d @@ -376,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] @@ -391,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' @@ -405,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' @@ -416,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] @@ -432,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 @@ -522,8 +566,6 @@ EOF test_expect_success "section was removed properly" \ "test_cmp expect .git/config" -rm .git/config - cat > expect << EOF [gitcvs] enabled = true @@ -534,10 +576,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 ' @@ -606,8 +649,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 @@ -622,6 +663,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 && @@ -632,8 +674,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 @@ -643,13 +683,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 @@ -663,6 +702,7 @@ cat >expect <<\EOF EOF test_expect_success 'get --bool-or-int' ' + rm -f .git/config && ( echo "[bool]" echo true1 @@ -682,7 +722,6 @@ test_expect_success 'get --bool-or-int' ' ' -rm .git/config cat >expect <<\EOF [bool] true1 = true @@ -696,6 +735,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 && @@ -706,8 +746,6 @@ test_expect_success 'set --bool-or-int' ' test_cmp expect .git/config ' -rm .git/config - cat >expect <<\EOF [path] home = ~/ @@ -716,6 +754,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~" && @@ -756,13 +795,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" @@ -770,8 +802,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 @@ -796,9 +834,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"] @@ -819,16 +858,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" && @@ -928,4 +968,52 @@ 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/t1305-config-include.sh b/t/t1305-config-include.sh new file mode 100755 index 0000000000..4b1cbaa028 --- /dev/null +++ b/t/t1305-config-include.sh @@ -0,0 +1,134 @@ +#!/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 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 ed4275afe3..1ae4d87c92 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -5,34 +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/' -valid_ref '/heads/foo' -valid_ref '///heads/foo' -invalid_ref '/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) && @@ -65,23 +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 '/heads/foo' '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 '/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/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index 647d888507..3acd895afb 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -20,7 +20,7 @@ test_expect_success 'setup reflog with alternating commits' ' ' test_expect_success 'reflog shows all entries' ' - cat >expect <<-\EOF + cat >expect <<-\EOF && topic@{0} reset: moving to two topic@{1} reset: moving to one topic@{2} reset: moving to two diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 523ce9c45b..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 ' @@ -191,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..e661147c57 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 && @@ -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/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/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh index c551d39a66..6352b74e2e 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,13 @@ 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_done diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 75874e85df..2741262369 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -189,12 +189,13 @@ test_expect_success 'checkout -b <describe>' ' test_cmp expect actual ' -test_expect_success 'checkout -B to the current branch fails before merging' ' +test_expect_success 'checkout -B to the current branch works' ' git checkout branch1 && + git checkout -B branch1-scratch && + setup_dirty_mergeable && - git commit -mfooble && - test_must_fail git checkout -B branch1 initial && - test_must_fail test_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 2366f0f414..068fba4c8e 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -12,11 +12,14 @@ check_not_detached () { } ORPHAN_WARNING='you are leaving .* commit.*behind' +PREV_HEAD_DESC='Previous HEAD position was' check_orphan_warning() { - test_i18ngrep "$ORPHAN_WARNING" "$1" + test_i18ngrep "$ORPHAN_WARNING" "$1" && + test_i18ngrep ! "$PREV_HEAD_DESC" "$1" } check_no_orphan_warning() { - test_i18ngrep ! "$ORPHAN_WARNING" "$1" + test_i18ngrep ! "$ORPHAN_WARNING" "$1" && + test_i18ngrep "$PREV_HEAD_DESC" "$1" } reset () { 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/t2203-add-intent.sh b/t/t2203-add-intent.sh index 25435290a7..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 -m initial + 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/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 55ef1895d7..a5e3da7e41 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -285,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' ' @@ -334,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' ' @@ -388,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' ' @@ -422,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' ' @@ -456,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' ' @@ -490,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' ' 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/t3200-branch.sh b/t/t3200-branch.sh index 7633930bb4..9fe1d8feab 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 && @@ -110,6 +112,54 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou 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 +' + mv .git/config .git/config-saved test_expect_success 'git branch -m q q2 without config should succeed' ' @@ -124,12 +174,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 && @@ -140,8 +190,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 \ @@ -250,8 +300,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' ' @@ -567,4 +617,44 @@ test_expect_success 'use set-upstream on the current branch' ' ' +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..9f00ada5f7 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -167,7 +167,7 @@ test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat >expected <<\EOF "tabs\t,\" (dq) and spaces" - 1 files changed, 0 insertions(+), 0 deletions(-) + 1 file changed, 0 insertions(+), 0 deletions(-) EOF ' 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..7ba17974c5 100755 --- a/t/t3401-rebase-partial.sh +++ b/t/t3401-rebase-partial.sh @@ -11,51 +11,35 @@ 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 && - - echo Third >> A && - git update-index A && - git commit -m "Modify A." +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 ' -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_expect_success 'pick top patch from topic branch into master' ' + git cherry-pick C && + git checkout -f 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 ! -d .git/rebase-apply' +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 --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 --merge topic branch that was partially merged upstream' ' + git reset --hard C && + git rebase --merge master && + test_path_is_missing .git/rebase-merge +' test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index b981572d73..7fd2127625 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -624,8 +624,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/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/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..1b3a344158 100755 --- a/t/t3508-cherry-pick-many-commits.sh +++ b/t/t3508-cherry-pick-many-commits.sh @@ -38,13 +38,13 @@ test_expect_success 'cherry-pick first..fourth works' ' 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 && @@ -64,15 +64,15 @@ test_expect_success 'cherry-pick --strategy resolve first..fourth works' ' 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 && diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh new file mode 100755 index 0000000000..97f3710700 --- /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 1f62c151b0..d48a7c002d 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" ' diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index fcdb18217a..663c60a12e 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -444,7 +444,7 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' ' git reset --hard && cat >expected <<-EOF && file | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) EOF git stash show ${STASH_ID} >actual && test_cmp expected actual @@ -482,7 +482,7 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' ' git reset --hard && cat >expected <<-EOF && file | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) EOF git stash show ${STASH_ID} >actual && test_cmp expected actual @@ -601,4 +601,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 index 4f2eedfd4f..a5e7e6b2ba 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -17,22 +17,32 @@ test_expect_success 'stash save --include-untracked some dirty working directory 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 -?? output EOF test_expect_success 'stash save --include-untracked cleaned the untracked files' ' - git status --porcelain > output - test_cmp output expect + 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 @@ -40,17 +50,28 @@ index 0000000..d00491f +++ 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 "!" -f file2 && - git diff HEAD..stash^3 -- file2 > output && - test_cmp output expect.diff && - git ls-tree --name-only stash^3: > output && - test_cmp output expect.lstree + 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 @@ -64,18 +85,22 @@ git clean --force --quiet cat > expect <<EOF M file +?? HEAD +?? actual ?? expect ?? file2 -?? output +?? untracked/ EOF test_expect_success 'stash pop after save --include-untracked leaves files untracked again' ' git stash pop && - git status --porcelain > output - test_cmp output expect + git status --porcelain >actual && + test_cmp expect actual && + test "1" = "`cat file2`" && + test untracked = "`cat untracked/untracked`" ' -git clean --force --quiet +git clean --force --quiet -d test_expect_success 'stash save -u dirty index' ' echo 4 > file3 && @@ -96,16 +121,18 @@ EOF test_expect_success 'stash save --include-untracked dirty index got stashed' ' git stash pop --index && - git diff --cached > output && - test_cmp output expect + 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 > output.out 2>&1 && - test ! -s output.out + 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' ' @@ -119,36 +146,42 @@ rm -f expect test_expect_success 'stash save --include-untracked removed files got stashed' ' git stash pop && - test ! -f file + 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 "!" -f file4 + git stash -u && + test_path_is_missing file4 ' test_expect_success 'stash save --all does not respect .gitignore' ' git stash -a && - test "!" -f ignored && - test "!" -f .gitignore + 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 ' 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/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master index 3a9f78a09d..2f8560c369 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 @@ -2,7 +2,7 @@ $ git diff-tree --cc --patch-with-stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..72e03c14fb 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 @@ -3,7 +3,7 @@ c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..8b357d964b 100644 --- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master +++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master @@ -2,7 +2,7 @@ $ git diff-tree --cc --patch-with-stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..e0568d6883 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master +++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master @@ -2,5 +2,5 @@ $ git diff-tree --cc --stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..5afc8239a1 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_side +++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_side @@ -3,6 +3,6 @@ c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..f48367a89a 100644 --- a/t/t4013/diff.diff-tree_--cc_--stat_master +++ b/t/t4013/diff.diff-tree_--cc_--stat_master @@ -2,5 +2,5 @@ $ git diff-tree --cc --stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..590864c2d7 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 @@ -3,7 +3,7 @@ $ git diff-tree --pretty=oneline --root --patch-with-stat initial dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..e05e77875c 100644 --- a/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side +++ b/t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..0e2c956633 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 @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..384fa44ddd 100644 --- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial +++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..10384a83d3 100644 --- a/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial +++ b/t/t4013/diff.diff-tree_--pretty_--root_--stat_initial @@ -8,5 +8,5 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..f57062ea07 100644 --- a/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial +++ b/t/t4013/diff.diff-tree_--root_--patch-with-stat_initial @@ -3,7 +3,7 @@ $ git diff-tree --root --patch-with-stat initial dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..7088683444 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master +++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_master @@ -2,5 +2,5 @@ $ git diff-tree -c --stat --summary master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..ef216abb1d 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_--summary_side +++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_side @@ -3,6 +3,6 @@ c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..ad19f103eb 100644 --- a/t/t4013/diff.diff-tree_-c_--stat_master +++ b/t/t4013/diff.diff-tree_-c_--stat_master @@ -2,5 +2,5 @@ $ git diff-tree -c --stat master 59d314ad6f356dd08601a4cd5e530381da3e3c64 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..ddad917ae8 100644 --- a/t/t4013/diff.diff_--patch-with-stat_-r_initial..side +++ b/t/t4013/diff.diff_--patch-with-stat_-r_initial..side @@ -2,7 +2,7 @@ $ git diff --patch-with-stat -r initial..side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..bdbd114d8e 100644 --- a/t/t4013/diff.diff_--patch-with-stat_initial..side +++ b/t/t4013/diff.diff_--patch-with-stat_initial..side @@ -2,7 +2,7 @@ $ git diff --patch-with-stat initial..side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..6d08f3d355 100644 --- a/t/t4013/diff.diff_--stat_initial..side +++ b/t/t4013/diff.diff_--stat_initial..side @@ -2,5 +2,5 @@ $ git diff --stat initial..side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..2ddb2540e6 100644 --- a/t/t4013/diff.diff_-r_--stat_initial..side +++ b/t/t4013/diff.diff_-r_--stat_initial..side @@ -2,5 +2,5 @@ $ git diff -r --stat initial..side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..3cab049f7d 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 @@ -15,7 +15,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..564a4d38f2 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -124,7 +124,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..4f28460b83 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..b10cc2e251 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side @@ -15,7 +15,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..a976a8aaf4 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 @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -124,7 +124,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..b4fd66477a 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 @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -124,7 +124,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..0d31036e7f 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 @@ -124,7 +124,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..18d4714423 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ @@ -75,7 +75,7 @@ Content-Transfer-Encoding: 8bit --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side index 67633d424a..3572f20b5d 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side @@ -15,7 +15,7 @@ Content-Transfer-Encoding: 8bit dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..54cdcdab40 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^ @@ -75,7 +75,7 @@ Subject: [DIFFERENT_PREFIX 2/2] Third --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..23194ebdaa 100644 --- a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master +++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master @@ -53,7 +53,7 @@ Subject: [PATCH] Third --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -88,7 +88,7 @@ Subject: [PATCH] Side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..78f1a80a97 100644 --- a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master +++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master @@ -53,7 +53,7 @@ Subject: [PATCH 2/3] Third --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -88,7 +88,7 @@ Subject: [PATCH 3/3] Side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..a3dab7f773 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--stdout_initial..master @@ -53,7 +53,7 @@ Subject: [PATCH 2/3] Third --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -88,7 +88,7 @@ Subject: [PATCH 3/3] Side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..39f4a3f2d1 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--stdout_initial..master^ @@ -53,7 +53,7 @@ Subject: [PATCH 2/2] Third --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 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..88109209db 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--stdout_initial..side @@ -8,7 +8,7 @@ Subject: [PATCH] Side dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..4085bbde87 100644 --- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ @@ -13,7 +13,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -32,7 +32,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -54,7 +54,7 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 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..458627953e 100644 --- a/t/t4013/diff.log_--patch-with-stat_master +++ b/t/t4013/diff.log_--patch-with-stat_master @@ -15,7 +15,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -56,7 +56,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ index 5a4e72765d..6e172cfadd 100644 --- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ @@ -13,7 +13,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -32,7 +32,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -54,7 +54,7 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 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..48b0d4b91d 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 @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:04:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -89,7 +89,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -165,7 +165,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..f9dc5122e2 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master @@ -15,7 +15,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -57,7 +57,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -133,7 +133,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..0807ece234 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_master @@ -15,7 +15,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -56,7 +56,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -130,7 +130,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..84f5ef6911 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 @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:04:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --combined dir/sub index cead32e,7289e35..992913c @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -89,7 +89,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -165,7 +165,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..e60384d24d 100644 --- a/t/t4013/diff.show_--patch-with-stat_--summary_side +++ b/t/t4013/diff.show_--patch-with-stat_--summary_side @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..a3a3255fd3 100644 --- a/t/t4013/diff.show_--patch-with-stat_side +++ b/t/t4013/diff.show_--patch-with-stat_side @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..d16f464aca 100644 --- a/t/t4013/diff.show_--stat_--summary_side +++ b/t/t4013/diff.show_--stat_--summary_side @@ -8,6 +8,6 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..6300c0535f 100644 --- a/t/t4013/diff.show_--stat_side +++ b/t/t4013/diff.show_--stat_side @@ -8,5 +8,5 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 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..16ae54345f 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ +++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ @@ -6,7 +6,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -25,7 +25,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 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..f3e45ec270 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_master +++ b/t/t4013/diff.whatchanged_--patch-with-stat_master @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -49,7 +49,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ index 13789f169b..c77f0bc320 100644 --- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ +++ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ @@ -6,7 +6,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 Side --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -25,7 +25,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 Third --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 1 file changed, 2 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:01:00 2006 +0000 This is the second commit. --- dir/sub | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + 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..8d03efea6c 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 @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:04:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --cc dir/sub index cead32e,7289e35..992913c @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -89,7 +89,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -165,7 +165,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..1874d0616c 100644 --- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -50,7 +50,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -126,7 +126,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..5211ff2a75 100644 --- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master +++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 @@ -49,7 +49,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -123,7 +123,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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..ad30245a59 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 @@ -8,7 +8,7 @@ Date: Mon Jun 26 00:04:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) diff --combined dir/sub index cead32e,7289e35..992913c @@ -47,7 +47,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file3 | 4 ++++ - 3 files changed, 9 insertions(+), 0 deletions(-) + 3 files changed, 9 insertions(+) create mode 100644 file3 diff --git a/dir/sub b/dir/sub @@ -89,7 +89,7 @@ Date: Mon Jun 26 00:02:00 2006 +0000 --- dir/sub | 2 ++ file1 | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) + 2 files changed, 5 insertions(+) create mode 100644 file1 diff --git a/dir/sub b/dir/sub @@ -165,7 +165,7 @@ Date: Mon Jun 26 00:00:00 2006 +0000 dir/sub | 2 ++ file0 | 3 +++ file2 | 3 +++ - 3 files changed, 8 insertions(+), 0 deletions(-) + 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 67975129bc..7dfe716cf9 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -520,7 +520,7 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' ' cat > expect << EOF --- file | 16 ++++++++++++++++ - 1 files changed, 16 insertions(+), 0 deletions(-) + 1 file changed, 16 insertions(+) diff --git a/file b/file index 40f36c6..2dc5c23 100644 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/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/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 88c5619ae7..4ac162cfcf 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -86,7 +86,7 @@ test_expect_success 'status -v produces text' ' cat >expect.stat <<'EOF' file | Bin 2 -> 4 bytes - 1 files changed, 0 insertions(+), 0 deletions(-) + 1 file changed, 0 insertions(+), 0 deletions(-) EOF test_expect_success 'diffstat does not run textconv' ' echo file diff=fail >.gitattributes && 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/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index 8a3c63b9e2..bd119be106 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -33,7 +33,7 @@ check_stat() { expect=$1; shift cat >expected <<EOF $expect | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) EOF test_expect_success "--stat $*" " git diff --stat $* HEAD^ >actual && diff --git a/t/t4049-diff-stat-count.sh b/t/t4049-diff-stat-count.sh index 641e70d14d..a6d1887536 100755 --- a/t/t4049-diff-stat-count.sh +++ b/t/t4049-diff-stat-count.sh @@ -16,7 +16,7 @@ test_expect_success setup ' cat >expect <<-\EOF a | 1 + b | 1 + - 2 files changed, 2 insertions(+), 0 deletions(-) + 2 files changed, 2 insertions(+) EOF git diff --stat --stat-count=2 >actual && test_cmp expect actual 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..328aa8f398 --- /dev/null +++ b/t/t4052-stat-output.sh @@ -0,0 +1,220 @@ +#!/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' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 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' + ...aaaaaaaaaaaaaaaaaaaaaaaaaa | 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 >expect200 <<'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 + ' +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 + +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_expect_success "$cmd $verb statGraphWidth config" ' + git -c diff.statGraphWidth=26 $cmd $args >output + grep " | " output >actual && + test_cmp "$expect" 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 +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 + ' +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 +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 + ' +done <<\EOF +format-patch -1 --stdout +diff HEAD^ HEAD --stat +show --stat +log -1 --stat +EOF + +cat >expect80 <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++ +EOF +cat >expect200 <<'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 + ' +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 >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/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/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 d7d9ccc1c8..ccc0280f52 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -123,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 && @@ -136,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 ' @@ -237,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^ && @@ -259,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' ' @@ -276,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 && @@ -495,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 && + { git am empty-file > actual 2>&1 && false || :; } && + echo Patch format detection failed. >expected && + test_cmp expected actual +' + test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 19a0851e7a..32cf0bd218 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 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/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index d9068981f8..527c9e7548 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -96,7 +96,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' @@ -242,6 +242,14 @@ 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 && ( @@ -266,7 +274,7 @@ test_expect_success 'archive --list mentions user filter' ' grep "^bar\$" output ' -test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' ' +test_expect_success 'archive --list shows only enabled remote filters' ' git archive --list --remote=. >output && ! grep "^tar\.foo\$" output && grep "^bar\$" output @@ -298,7 +306,7 @@ test_expect_success 'extension matching requires dot' ' test_cmp b.tar config-implicittar.foo ' -test_expect_success NOT_MINGW 'only enabled filters are available remotely' ' +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 && @@ -341,12 +349,12 @@ test_expect_success GZIP,GUNZIP 'extract tgz file' ' test_cmp b.tar j.tar ' -test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' ' +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,NOT_MINGW 'remote tar.gz can be disabled' ' +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 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/t5150-request-pull.sh b/t/t5150-request-pull.sh index 9cc0a42ea9..2af8947eeb 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 diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 602806d09c..d9d856b87b 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -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 diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index f8fa92446c..fe82025d4a 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -74,6 +74,10 @@ test_expect_success 'index-pack --verify on index version 2' ' ' 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)' 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..ce51692bb2 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,23 @@ 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 '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 +259,71 @@ 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: 12" > 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_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/t5510-fetch.sh b/t/t5510-fetch.sh index e0af4c4e62..308c02ea75 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,8 +78,8 @@ 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' @@ -166,7 +174,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 && @@ -175,8 +183,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' ' @@ -207,13 +214,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 ' @@ -230,13 +231,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 ' @@ -434,14 +429,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/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..c334c51a07 --- /dev/null +++ b/t/t5528-push-default.sh @@ -0,0 +1,54 @@ +#!/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 +' + +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_config push.default upstream && + test_commit two && + git push && + echo two >expect && + git --git-dir=repo1 log -1 --format=%s foo >actual && + test_cmp expect actual +' + +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_must_fail git push +' + +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_must_fail git push +' + +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_done diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index 64767d8705..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 @@ -144,6 +160,24 @@ test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' ' 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..cc6f081711 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' ' @@ -95,6 +96,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 +133,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 " @@ -154,5 +183,44 @@ 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 'quiet push' ' + cd "$ROOT_PATH"/test_repo_clone && + test_commit quiet && + test_terminal git push --quiet --no-progress 2>&1 | tee output && + test_cmp /dev/null output +' + stop_httpd test_done diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index a1883ca6b6..e5e6b8f643 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -8,8 +8,8 @@ if test -n "$NO_CURL"; then test_done fi -. "$TEST_DIRECTORY"/lib-httpd.sh LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'} +. "$TEST_DIRECTORY"/lib-httpd.sh start_httpd test_expect_success 'setup repository' ' @@ -35,11 +35,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 +162,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/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..7cbc9994a3 --- /dev/null +++ b/t/t5570-git-daemon.sh @@ -0,0 +1,148 @@ +#!/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 + + if test $# -ne 3 + then + error "invalid number of arguments" + fi + + cmd=$1 + repo=$2 + msg=$3 + + 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 clone nowhere.git '$msg'" +test_expect_success 'push disabled' "test_remote_error push repo.git '$msg'" +test_expect_success 'read access denied' "test_remote_error -x fetch repo.git '$msg'" +test_expect_success 'not exported' "test_remote_error -n fetch repo.git '$msg'" + +stop_git_daemon +start_git_daemon --informative-errors + +test_expect_success 'clone non-existent' "test_remote_error clone nowhere.git 'no such repository'" +test_expect_success 'push disabled' "test_remote_error push repo.git 'service not enabled'" +test_expect_success 'read access denied' "test_remote_error -x fetch repo.git 'no such repository'" +test_expect_success 'not exported' "test_remote_error -n fetch repo.git 'repository not exported'" + +stop_git_daemon +test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index e8103144bb..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 && @@ -206,6 +229,20 @@ 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 @@ -234,4 +271,13 @@ test_expect_success 'clone from original with relative alternate' ' 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..bbc4691bd7 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -52,13 +52,13 @@ 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" @@ -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/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/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..444279077e 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -267,6 +267,12 @@ 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 && 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/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index 9d8584e957..1104249182 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -884,4 +884,20 @@ test_expect_success 'no spurious "refusing to lose untracked" message' ' ! 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/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index c6f1f9f8ab..691e4a4481 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -164,7 +164,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - grep "* (no branch)" branch.output > /dev/null && + test_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' ' diff --git a/t/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh index fdb6c25371..94f010be8a 100755 --- a/t/t6032-merge-large-rename.sh +++ b/t/t6032-merge-large-rename.sh @@ -95,7 +95,7 @@ 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)" ' diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index 19de5b16eb..19272bc551 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -51,6 +51,22 @@ 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 diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 7dc8a510c7..172178490a 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -6,6 +6,7 @@ test_description='for-each-ref test' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh # Mon Jul 3 15:18:43 2006 +0000 datestamp=1151939923 @@ -37,11 +38,13 @@ test_atom() { case "$1" in head) ref=refs/heads/master ;; tag) ref=refs/tags/testtag ;; + *) ref=$1 ;; esac printf '%s\n' "$3" >expected - test_expect_${4:-success} "basic atom: $1 $2" " + test_expect_${4:-success} $PREREQ "basic atom: $1 $2" " git for-each-ref --format='%($2)' $ref >actual && - test_cmp expected actual + sanitize_pgp <actual >actual.clean && + test_cmp expected actual.clean " } @@ -71,7 +74,10 @@ test_atom head taggerdate '' test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200' test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200' test_atom head subject 'Initial' +test_atom head contents:subject 'Initial' test_atom head body '' +test_atom head contents:body '' +test_atom head contents:signature '' test_atom head contents 'Initial ' @@ -101,7 +107,10 @@ test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200' test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200' test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200' test_atom tag subject 'Tagging at 1151939927' +test_atom tag contents:subject 'Tagging at 1151939927' test_atom tag body '' +test_atom tag contents:body '' +test_atom tag contents:signature '' test_atom tag contents 'Tagging at 1151939927 ' @@ -359,4 +368,92 @@ test_expect_success 'an unusual tag with an incomplete line' ' ' +test_expect_success 'create tag with subject and body content' ' + cat >>msg <<-\EOF && + the subject line + + first body line + second body line + EOF + git tag -F msg subject-body +' +test_atom refs/tags/subject-body subject 'the subject line' +test_atom refs/tags/subject-body body 'first body line +second body line +' +test_atom refs/tags/subject-body contents 'the subject line + +first body line +second body line +' + +test_expect_success 'create tag with multiline subject' ' + cat >msg <<-\EOF && + first subject line + second subject line + + first body line + second body line + EOF + git tag -F msg multiline +' +test_atom refs/tags/multiline subject 'first subject line second subject line' +test_atom refs/tags/multiline contents:subject 'first subject line second subject line' +test_atom refs/tags/multiline body 'first body line +second body line +' +test_atom refs/tags/multiline contents:body 'first body line +second body line +' +test_atom refs/tags/multiline contents:signature '' +test_atom refs/tags/multiline contents 'first subject line +second subject line + +first body line +second body line +' + +test_expect_success GPG 'create signed tags' ' + git tag -s -m "" signed-empty && + git tag -s -m "subject line" signed-short && + cat >msg <<-\EOF && + subject line + + body contents + EOF + git tag -s -F msg signed-long +' + +sig='-----BEGIN PGP SIGNATURE----- +-----END PGP SIGNATURE----- +' + +PREREQ=GPG +test_atom refs/tags/signed-empty subject '' +test_atom refs/tags/signed-empty contents:subject '' +test_atom refs/tags/signed-empty body "$sig" +test_atom refs/tags/signed-empty contents:body '' +test_atom refs/tags/signed-empty contents:signature "$sig" +test_atom refs/tags/signed-empty contents "$sig" + +test_atom refs/tags/signed-short subject 'subject line' +test_atom refs/tags/signed-short contents:subject 'subject line' +test_atom refs/tags/signed-short body "$sig" +test_atom refs/tags/signed-short contents:body '' +test_atom refs/tags/signed-short contents:signature "$sig" +test_atom refs/tags/signed-short contents "subject line +$sig" + +test_atom refs/tags/signed-long subject 'subject line' +test_atom refs/tags/signed-long contents:subject 'subject line' +test_atom refs/tags/signed-long body "body contents +$sig" +test_atom refs/tags/signed-long contents:body 'body contents +' +test_atom refs/tags/signed-long contents:signature "$sig" +test_atom refs/tags/signed-long contents "subject line + +body contents +$sig" + test_done diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 097ce2bc83..f8c247a750 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: @@ -585,23 +586,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: @@ -625,16 +621,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 @@ -1296,4 +1282,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 320e1d1dbe..ff2590849d 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -6,11 +6,6 @@ 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_unconfig core.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,49 +38,37 @@ 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 ' @@ -136,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 && @@ -147,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 && - test_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 && - test_config color.ui auto || - cleanup_fail && - + test_config color.ui auto && ( TERM=vt100 && export TERM && @@ -181,9 +156,7 @@ test_expect_success TTY 'colors are suppressed by color.pager' ' test_expect_success 'color when writing to a file intended for a pager' ' rm -f colorful.log && - test_config color.ui auto || - cleanup_fail && - + test_config color.ui auto && ( TERM=vt100 && GIT_PAGER_IN_USE=true && @@ -242,9 +215,7 @@ test_default_pager() { $test_expectation SIMPLEPAGER,TTY "$cmd - default pager is used by default" " sane_unset PAGER GIT_PAGER && test_unconfig core.pager && - rm -f default_pager_used || - cleanup_fail && - + rm -f default_pager_used && cat >\$less <<-\EOF && #!/bin/sh wc >default_pager_used @@ -265,9 +236,7 @@ test_PAGER_overrides() { $test_expectation TTY "$cmd - PAGER overrides default pager" " sane_unset GIT_PAGER && test_unconfig core.pager && - rm -f PAGER_used || - cleanup_fail && - + rm -f PAGER_used && PAGER='wc >PAGER_used' && export PAGER && $full_command && @@ -292,9 +261,7 @@ 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 && test_config core.pager 'wc >core.pager_used' && @@ -321,9 +288,7 @@ 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 && @@ -341,9 +306,7 @@ test_GIT_PAGER_overrides() { parse_args "$@" $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" " - rm -f GIT_PAGER_used || - cleanup_fail && - + rm -f GIT_PAGER_used && test_config core.pager wc && GIT_PAGER='wc >GIT_PAGER_used' && export GIT_PAGER && @@ -356,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 && diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh index 917a264eea..fd6410fc71 100755 --- a/t/t7008-grep-binary.sh +++ b/t/t7008-grep-binary.sh @@ -99,4 +99,28 @@ test_expect_success 'git grep y<NUL>x a' " 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/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 69115269c2..b377a7af28 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -79,6 +79,15 @@ test_expect_success 'submodule add' ' cd addtest && 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 ) && @@ -362,10 +371,10 @@ test_expect_success 'update --init' ' git submodule update init > update.out && cat update.out && test_i18ngrep "not initialized" update.out && - ! test -d init/.git && + 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' ' @@ -498,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/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 95ffe349a7..3620215c1f 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -56,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 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 c679f36a4d..dcb195b4cf 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 ' ' @@ -298,6 +304,62 @@ 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 && @@ -408,6 +470,7 @@ test_expect_success 'submodule update exit immediately in case of merge conflict test_cmp expect actual ) ' + test_expect_success 'submodule update exit immediately after recursive rebase error' ' (cd super && git checkout master && @@ -442,4 +505,135 @@ test_expect_success 'submodule update exit immediately after recursive rebase er 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_done diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index be745fb23f..9b69fe2e14 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -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 ) ' @@ -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,18 +280,18 @@ 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 ) ' diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index cc16d3f05d..ab37c368d0 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -43,7 +43,7 @@ git commit -m B-super-added' cd "$base_dir" test_expect_success 'after add: existence of info/alternates' \ -'test `wc -l <super/sub/.git/objects/info/alternates` = 1' +'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1' cd "$base_dir" @@ -66,7 +66,7 @@ test_expect_success 'update with reference' \ cd "$base_dir" test_expect_success 'after update: existence of info/alternates' \ -'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1' +'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1' cd "$base_dir" diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 3ad04363b5..b20ca0eace 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,175 @@ 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 \ - "testing nothing to commit" \ - "test_must_fail git commit -m initial" +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 \ - "next 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 \ - "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 '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 +' -# Empty except stray tabs and spaces on a few lines. -sed -e 's/@$//' >msg <<EOF - @ +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 +' - @ -Signed-off-by: hula -EOF -test_expect_success \ - "empty commit message" \ - "test_must_fail git commit -F msg -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 +' -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 '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 +' -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 '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 \ - "amend commit" \ - "EDITOR=./editor git commit --amend" +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 \ - "passing -m and -F" \ - "echo 'enough with the bongos' >file && \ - test_must_fail git commit -F msg -m amending ." +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 \ - "using message from other commit" \ - "git commit -C HEAD^ ." +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 +' -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 +254,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 +382,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 +408,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 ' diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh index ee7f0cd459..984889b39d 100755 --- a/t/t7503-pre-commit-hook.sh +++ b/t/t7503-pre-commit-hook.sh @@ -118,4 +118,22 @@ test_expect_success 'with failing hook requiring GIT_PREFIX' ' 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 905255adf0..fc57b135c5 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -189,7 +189,7 @@ test_expect_success 'status with gitignore' ' # untracked EOF git status --ignored >output && - test_cmp expect output + test_i18ncmp expect output ' test_expect_success 'status with gitignore (nothing untracked)' ' @@ -247,7 +247,7 @@ test_expect_success 'status with gitignore (nothing untracked)' ' # untracked EOF git status --ignored >output && - test_cmp expect output + test_i18ncmp expect output ' rm -f .gitignore 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/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 61f36baa1f..5783ebf3ab 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -57,7 +57,7 @@ Merge made by the 'octopus' strategy. c2.c | 1 + c3.c | 1 + c4.c | 1 + - 3 files changed, 3 insertions(+), 0 deletions(-) + 3 files changed, 3 insertions(+) create mode 100644 c2.c create mode 100644 c3.c create mode 100644 c4.c @@ -74,7 +74,7 @@ Already up-to-date with c4 Trying simple merge with c5 Merge made by the 'octopus' strategy. c5.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) + 1 file changed, 1 insertion(+) create mode 100644 c5.c EOF @@ -89,7 +89,7 @@ Trying simple merge with c2 Merge made by the 'octopus' strategy. c1.c | 1 + c2.c | 1 + - 2 files changed, 2 insertions(+), 0 deletions(-) + 2 files changed, 2 insertions(+) create mode 100644 c1.c create mode 100644 c2.c EOF 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/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/t7610-mergetool.sh b/t/t7610-mergetool.sh index 4aab2a75b8..f5e16fc7db 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -39,6 +39,7 @@ test_expect_success 'setup' ' 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 && @@ -50,6 +51,7 @@ test_expect_success 'setup' ' git checkout -b submod-branch1 ) && git add file1 "spaced name" file11 file13 file2 subdir/file3 submod && + git add both && git rm file12 && git commit -m "branch1 changes" && @@ -58,6 +60,7 @@ test_expect_success 'setup' ' 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 && @@ -69,18 +72,22 @@ test_expect_success 'setup' ' git checkout -b submod-master ) && 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 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 ) && @@ -101,6 +108,7 @@ test_expect_success 'mergetool crlf' ' ( 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 ) && @@ -131,6 +139,7 @@ test_expect_success 'mergetool on file in parent dir' ' cd subdir && ( yes "" | git mergetool ../file1 >/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 ) && @@ -212,6 +221,7 @@ test_expect_success 'deleted vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -228,6 +238,7 @@ test_expect_success 'deleted vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -241,6 +252,7 @@ test_expect_success 'deleted vs modified submodule' ' test_must_fail git merge test6 && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -256,6 +268,7 @@ test_expect_success 'deleted vs modified submodule' ' test_must_fail git merge test6 && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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" && @@ -279,6 +292,7 @@ test_expect_success 'file vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -294,6 +308,7 @@ test_expect_success 'file vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -309,6 +324,7 @@ test_expect_success 'file vs modified submodule' ' test_must_fail git merge test7 && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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 && @@ -324,6 +340,7 @@ test_expect_success 'file vs modified submodule' ' test_must_fail git merge test7 && test -n "$(git ls-files -u)" && ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && + ( yes "" | 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" && @@ -445,4 +462,13 @@ test_expect_success 'directory vs modified submodule' ' 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/t7800-difftool.sh b/t/t7800-difftool.sh index 395adfc8a9..4fb4c9384a 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -38,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 @@ -265,4 +275,35 @@ test_expect_success PERL 'difftool --extcmd cat arg2' ' test "$diff" = branch ' +# Create a second file on master and a different version on branch +test_expect_success PERL 'setup with 2 files different' ' + echo m2 >file2 && + git add file2 && + git commit -m "added file2" && + + git checkout branch && + echo br2 >file2 && + git add file2 && + git commit -a -m "branch changed file2" && + git checkout master +' + +test_expect_success PERL 'say no to the first file' ' + diff=$( (echo n; echo) | git difftool -x cat branch ) && + + echo "$diff" | stdin_contains m2 && + echo "$diff" | stdin_contains br2 && + echo "$diff" | stdin_doesnot_contain master && + echo "$diff" | stdin_doesnot_contain branch +' + +test_expect_success PERL 'say no to the second file' ' + diff=$( (echo; echo n) | git difftool -x cat branch ) && + + echo "$diff" | stdin_contains master && + echo "$diff" | stdin_contains branch && + echo "$diff" | stdin_doesnot_contain m2 && + echo "$diff" | stdin_doesnot_contain br2 +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 0d600163c8..d9ad633310 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 @@ -523,6 +552,20 @@ test_expect_success 'grep -W' ' 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 && ( @@ -554,7 +597,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 @@ -571,6 +613,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 ) ' @@ -583,6 +642,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 && @@ -591,12 +654,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 ) ' @@ -825,4 +900,20 @@ test_expect_success 'mimic ack-grep --group' ' 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..c3c22f7764 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 -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/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/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/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 41db05cb4a..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" @@ -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 1a6c06631c..0f5b5e5964 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -820,6 +820,18 @@ test_expect_success \ 'test 1 = `git rev-list J | wc -l` && test 0 = `git ls-tree J | wc -l`' +cat >input <<INPUT_END +reset refs/heads/J2 + +tag wrong_tag +from refs/heads/J2 +data <<EOF +Tag branch that was reset. +EOF +INPUT_END +test_expect_success \ + 'J: tag must fail on empty branch' \ + 'test_must_fail git fast-import <input' ### ### series K ### @@ -1295,6 +1307,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 && @@ -1975,6 +2026,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) ### @@ -2208,7 +2276,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 @@ -2220,7 +2288,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 && @@ -2241,7 +2309,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 @@ -2259,7 +2327,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 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/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..31076edc5b 100755 --- a/t/t9501-gitweb-standalone-http-status.sh +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -134,4 +134,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..486c8eeb7e --- /dev/null +++ b/t/t9800-git-p4-basic.sh @@ -0,0 +1,470 @@ +#!/bin/sh + +test_description='git-p4 tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'add p4 files' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "file1" && + echo file2 >file2 && + p4 add file2 && + p4 submit -d "file2" + ) +' + +test_expect_success 'basic git-p4 clone' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline >lines && + test_line_count = 1 lines + ) +' + +test_expect_success 'git-p4 clone @all' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git log --oneline >lines && + test_line_count = 2 lines + ) +' + +test_expect_success 'git-p4 sync uninitialized repo' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_must_fail "$GITP4" sync + ) +' + +# +# Create a git repo by hand. Add a commit so that HEAD is valid. +# Test imports a new p4 repository into a new git branch. +# +test_expect_success 'git-p4 sync new branch' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all && + git log --oneline p4/depot >lines && + test_line_count = 2 lines + ) +' + +test_expect_success '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" + ) && + "$GITP4" 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" + ) && + "$GITP4" 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" + ) && + "$GITP4" 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" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? && + test $retval -eq 1 && + test_must_fail grep -q Traceback errs +' + +test_expect_success 'add p4 files with wildcards in the names' ' + ( + cd "$cli" && + echo file-wild-hash >file-wild#hash && + echo file-wild-star >file-wild\*star && + echo file-wild-at >file-wild@at && + echo file-wild-percent >file-wild%percent && + p4 add -f file-wild* && + p4 submit -d "file wildcards" + ) +' + +test_expect_success 'wildcard files git-p4 clone' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + test -f file-wild#hash && + test -f file-wild\*star && + test -f file-wild@at && + test -f file-wild%percent + ) +' + +test_expect_success 'clone bare' ' + "$GITP4" clone --dest="$git" --bare //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + test ! -d .git && + bare=`git config --get core.bare` && + test "$bare" = true + ) +' + +p4_add_user() { + name=$1 fullname=$2 && + p4 user -f -i <<-EOF && + User: $name + Email: $name@localhost + FullName: $fullname + EOF + p4 passwd -P secret $name +} + +p4_grant_admin() { + name=$1 && + { + p4 protect -o && + echo " admin user $name * //depot/..." + } | p4 protect -i +} + +p4_check_commit_author() { + file=$1 user=$2 && + p4 changes -m 1 //depot/$file | grep -q $user +} + +make_change_by_user() { + file=$1 name=$2 email=$3 && + echo "username: a change by $name" >>"$file" && + git add "$file" && + git commit --author "$name <$email>" -m "a change by $name" +} + +# Test username support, submitting as user 'alice' +test_expect_success 'preserve users' ' + p4_add_user alice Alice && + p4_add_user bob Bob && + p4_grant_admin alice && + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + echo "username: a change by alice" >>file1 && + echo "username: a change by bob" >>file2 && + git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 && + git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 && + git config git-p4.skipSubmitEditCheck true && + P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user && + p4_check_commit_author file1 alice && + p4_check_commit_author file2 bob + ) +' + +# Test username support, submitting as bob, who lacks admin rights. Should +# not submit change to p4 (git diff should show deltas). +test_expect_success 'refuse to preserve users without perms' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo "username-noperms: a change by alice" >>file1 && + git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 && + P4EDITOR=touch P4USER=bob P4PASSWD=secret && + export P4EDITOR P4USER P4PASSWD && + test_must_fail "$GITP4" 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' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo "username-bob: a change by bob" >>file1 && + git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 && + echo "username-unknown: a change by charlie" >>file1 && + git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 && + P4EDITOR=touch P4USER=alice P4PASSWD=secret && + export P4EDITOR P4USER P4PASSWD && + test_must_fail "$GITP4" 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 && + "$GITP4" commit && + git diff --exit-code HEAD..p4/master && + p4_check_commit_author file1 alice + ) +' + +# If we're *not* using --preserve-user, git-p4 should warn if we're submitting +# changes that are not all ours. +# Test: user in p4 and user unknown to p4. +# Test: warning disabled and user is the same. +test_expect_success 'not preserving user with mixed authorship' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + p4_add_user derek Derek && + + make_change_by_user usernamefile3 Derek derek@localhost && + P4EDITOR=cat P4USER=alice P4PASSWD=secret && + export P4EDITOR P4USER P4PASSWD && + "$GITP4" commit |\ + grep "git author derek@localhost does not match" && + + make_change_by_user usernamefile3 Charlie charlie@localhost && + "$GITP4" commit |\ + grep "git author charlie@localhost does not match" && + + make_change_by_user usernamefile3 alice alice@localhost && + "$GITP4" commit |\ + test_must_fail grep "git author.*does not match" && + + git config git-p4.skipUserNameCheck true && + make_change_by_user usernamefile3 Charlie charlie@localhost && + "$GITP4" commit |\ + test_must_fail grep "git author.*does not match" && + + p4_check_commit_author usernamefile3 alice + ) +' + +marshal_dump() { + what=$1 + "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]' +} + +# Sleep a bit so that the top-most p4 change did not happen "now". Then +# import the repo and make sure that the initial import has the same time +# as the top-most change. +test_expect_success 'initial import time from top change time' ' + p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) && + p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) && + sleep 3 && + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + gittime=$(git show -s --raw --pretty=format:%at HEAD) && + echo $p4time $gittime && + test $p4time = $gittime + ) +' + +# Rename a file and confirm that rename is not detected in P4. +# Rename the new file again with detectRenames option enabled and confirm that +# this is detected in P4. +# Rename the new file again adding an extra line, configure a big threshold in +# detectRenames and confirm that rename is not detected in P4. +# Repeat, this time with a smaller threshold and confirm that the rename is +# detected in P4. +test_expect_success 'detect renames' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + + git mv file1 file4 && + git commit -a -m "Rename file1 to file4" && + git diff-tree -r -M HEAD && + "$GITP4" submit && + p4 filelog //depot/file4 && + p4 filelog //depot/file4 | test_must_fail grep -q "branch from" && + + git mv file4 file5 && + git commit -a -m "Rename file4 to file5" && + git diff-tree -r -M HEAD && + git config git-p4.detectRenames true && + "$GITP4" submit && + p4 filelog //depot/file5 && + p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && + + git mv file5 file6 && + echo update >>file6 && + git add file6 && + git commit -a -m "Rename file5 to file6 with changes" && + git diff-tree -r -M HEAD && + level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && + test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && + git config git-p4.detectRenames $(($level + 2)) && + "$GITP4" submit && + p4 filelog //depot/file6 && + p4 filelog //depot/file6 | test_must_fail grep -q "branch from" && + + git mv file6 file7 && + echo update >>file7 && + git add file7 && + git commit -a -m "Rename file6 to file7 with changes" && + git diff-tree -r -M HEAD && + level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && + test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && + git config git-p4.detectRenames $(($level - 2)) && + "$GITP4" submit && + p4 filelog //depot/file7 && + p4 filelog //depot/file7 | grep -q "branch from //depot/file6" + ) +' + +# Copy a file and confirm that copy is not detected in P4. +# Copy a file with detectCopies option enabled and confirm that copy is not +# detected in P4. +# Modify and copy a file with detectCopies option enabled and confirm that copy +# is detected in P4. +# Copy a file with detectCopies and detectCopiesHarder options enabled and +# confirm that copy is detected in P4. +# Modify and copy a file, configure a bigger threshold in detectCopies and +# confirm that copy is not detected in P4. +# Modify and copy a file, configure a smaller threshold in detectCopies and +# confirm that copy is detected in P4. +test_expect_success 'detect copies' ' + "$GITP4" clone --dest="$git" //depot@all && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + + cp file2 file8 && + git add file8 && + git commit -a -m "Copy file2 to file8" && + git diff-tree -r -C HEAD && + "$GITP4" submit && + p4 filelog //depot/file8 && + p4 filelog //depot/file8 | test_must_fail grep -q "branch from" && + + cp file2 file9 && + git add file9 && + git commit -a -m "Copy file2 to file9" && + git diff-tree -r -C HEAD && + git config git-p4.detectCopies true && + "$GITP4" submit && + p4 filelog //depot/file9 && + p4 filelog //depot/file9 | test_must_fail grep -q "branch from" && + + echo "file2" >>file2 && + cp file2 file10 && + git add file2 file10 && + git commit -a -m "Modify and copy file2 to file10" && + git diff-tree -r -C HEAD && + "$GITP4" submit && + p4 filelog //depot/file10 && + p4 filelog //depot/file10 | grep -q "branch from //depot/file" && + + cp file2 file11 && + git add file11 && + git commit -a -m "Copy file2 to file11" && + git diff-tree -r -C --find-copies-harder HEAD && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopiesHarder true && + "$GITP4" submit && + p4 filelog //depot/file11 && + p4 filelog //depot/file11 | grep -q "branch from //depot/file" && + + cp file2 file12 && + echo "some text" >>file12 && + git add file12 && + git commit -a -m "Copy file2 to file12 with changes" && + git diff-tree -r -C --find-copies-harder HEAD && + level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && + test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopies $(($level + 2)) && + "$GITP4" submit && + p4 filelog //depot/file12 && + p4 filelog //depot/file12 | test_must_fail grep -q "branch from" && + + cp file2 file13 && + echo "different text" >>file13 && + git add file13 && + git commit -a -m "Copy file2 to file13 with changes" && + git diff-tree -r -C --find-copies-harder HEAD && + level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && + test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && + src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && + test "$src" = file10 && + git config git-p4.detectCopies $(($level - 2)) && + "$GITP4" submit && + p4 filelog //depot/file13 && + p4 filelog //depot/file13 | grep -q "branch from //depot/file" + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/t9800-git-p4.sh b/t/t9800-git-p4.sh deleted file mode 100755 index 01ba041fde..0000000000 --- a/t/t9800-git-p4.sh +++ /dev/null @@ -1,476 +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" -' - -cleanup_git() { - cd "$TRASH_DIRECTORY" && - rm -rf "$git" && - mkdir "$git" -} - -test_expect_success 'basic git-p4 clone' ' - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - git log --oneline >lines && - test_line_count = 1 lines -' - -test_expect_success 'git-p4 clone @all' ' - "$GITP4" clone --dest="$git" //depot@all && - test_when_finished cleanup_git && - cd "$git" && - git log --oneline >lines && - test_line_count = 2 lines -' - -test_expect_success 'git-p4 sync uninitialized repo' ' - test_create_repo "$git" && - test_when_finished cleanup_git && - cd "$git" && - test_must_fail "$GITP4" sync -' - -# -# Create a git repo by hand. Add a commit so that HEAD is valid. -# Test imports a new p4 repository into a new git branch. -# -test_expect_success 'git-p4 sync new branch' ' - test_create_repo "$git" && - test_when_finished cleanup_git && - cd "$git" && - test_commit head && - "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all && - git log --oneline p4/depot >lines && - test_line_count = 2 lines -' - -test_expect_success 'exit when p4 fails to produce marshaled output' ' - badp4dir="$TRASH_DIRECTORY/badp4dir" && - mkdir -p "$badp4dir" && - test_when_finished "rm -rf $badp4dir" && - cat >"$badp4dir"/p4 <<-EOF && - #!$SHELL_PATH - exit 1 - EOF - chmod 755 "$badp4dir"/p4 && - PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? && - test $retval -eq 1 && - test_must_fail grep -q Traceback errs -' - -test_expect_success 'add p4 files with wildcards in the names' ' - cd "$cli" && - echo file-wild-hash >file-wild#hash && - echo file-wild-star >file-wild\*star && - echo file-wild-at >file-wild@at && - echo file-wild-percent >file-wild%percent && - p4 add -f file-wild* && - p4 submit -d "file wildcards" -' - -test_expect_success 'wildcard files git-p4 clone' ' - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - test -f file-wild#hash && - test -f file-wild\*star && - test -f file-wild@at && - test -f file-wild%percent -' - -test_expect_success 'clone bare' ' - "$GITP4" clone --dest="$git" --bare //depot && - test_when_finished cleanup_git && - cd "$git" && - test ! -d .git && - bare=`git config --get core.bare` && - test "$bare" = true -' - -p4_add_user() { - name=$1 - fullname=$2 - p4 user -f -i <<EOF && -User: $name -Email: $name@localhost -FullName: $fullname -EOF - p4 passwd -P secret $name -} - -p4_grant_admin() { - name=$1 - p4 protect -o |\ - 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 && - test_when_finished cleanup_git && - cd "$git" && - echo "username: a change by alice" >> file1 && - echo "username: a change by bob" >> file2 && - git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 && - git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 && - git config git-p4.skipSubmitEditCheck true && - P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user && - p4_check_commit_author file1 alice && - p4_check_commit_author file2 bob -' - -# Test username support, submitting as bob, who lacks admin rights. Should -# not submit change to p4 (git diff should show deltas). -test_expect_success 'refuse to preserve users without perms' ' - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - git config git-p4.skipSubmitEditCheck true && - echo "username-noperms: a change by alice" >> file1 && - git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 && - ! P4EDITOR=touch P4USER=bob P4PASSWD=secret "$GITP4" commit --preserve-user && - ! git diff --exit-code HEAD..p4/master > /dev/null -' - -# What happens with unknown author? Without allowMissingP4Users it should fail. -test_expect_success 'preserve user where author is unknown to p4' ' - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - git config git-p4.skipSubmitEditCheck true && - echo "username-bob: a change by bob" >> file1 && - git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 && - echo "username-unknown: a change by charlie" >> file1 && - git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 && - ! P4EDITOR=touch P4USER=alice P4PASSWD=secret "$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 -' - -# If we're *not* using --preserve-user, git-p4 should warn if we're submitting -# changes that are not all ours. -# Test: user in p4 and user unknown to p4. -# Test: warning disabled and user is the same. -test_expect_success 'not preserving user with mixed authorship' ' - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - git config git-p4.skipSubmitEditCheck true && - p4_add_user derek Derek && - - make_change_by_user usernamefile3 Derek derek@localhost && - P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >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 -' - -marshal_dump() { - what=$1 - python -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]' -} - -# Sleep a bit so that the top-most p4 change did not happen "now". Then -# import the repo and make sure that the initial import has the same time -# as the top-most change. -test_expect_success 'initial import time from top change time' ' - p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) && - p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) && - sleep 3 && - "$GITP4" clone --dest="$git" //depot && - test_when_finished cleanup_git && - cd "$git" && - gittime=$(git show -s --raw --pretty=format:%at HEAD) && - echo $p4time $gittime && - test $p4time = $gittime -' - -# Rename a file and confirm that rename is not detected in P4. -# Rename the new file again with detectRenames option enabled and confirm that -# this is detected in P4. -# Rename the new file again adding an extra line, configure a big threshold in -# detectRenames and confirm that rename is not detected in P4. -# Repeat, this time with a smaller threshold and confirm that the rename is -# detected in P4. -test_expect_success 'detect renames' ' - "$GITP4" clone --dest="$git" //depot@all && - test_when_finished cleanup_git && - cd "$git" && - git config git-p4.skipSubmitEditCheck true && - - git mv file1 file4 && - git commit -a -m "Rename file1 to file4" && - git diff-tree -r -M HEAD && - "$GITP4" submit && - p4 filelog //depot/file4 && - ! p4 filelog //depot/file4 | grep -q "branch from" && - - git mv file4 file5 && - git commit -a -m "Rename file4 to file5" && - git diff-tree -r -M HEAD && - git config git-p4.detectRenames true && - "$GITP4" submit && - p4 filelog //depot/file5 && - p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && - - git mv file5 file6 && - echo update >>file6 && - git add file6 && - git commit -a -m "Rename file5 to file6 with changes" && - git diff-tree -r -M HEAD && - level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && - test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && - git config git-p4.detectRenames $((level + 2)) && - "$GITP4" submit && - p4 filelog //depot/file6 && - ! p4 filelog //depot/file6 | grep -q "branch from" && - - git mv file6 file7 && - echo update >>file7 && - git add file7 && - git commit -a -m "Rename file6 to file7 with changes" && - git diff-tree -r -M HEAD && - level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && - test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && - git config git-p4.detectRenames $((level - 2)) && - "$GITP4" submit && - p4 filelog //depot/file7 && - p4 filelog //depot/file7 | grep -q "branch from //depot/file6" -' - -# Copy a file and confirm that copy is not detected in P4. -# Copy a file with detectCopies option enabled and confirm that copy is not -# detected in P4. -# Modify and copy a file with detectCopies option enabled and confirm that copy -# is detected in P4. -# Copy a file with detectCopies and detectCopiesHarder options enabled and -# confirm that copy is detected in P4. -# Modify and copy a file, configure a bigger threshold in detectCopies and -# confirm that copy is not detected in P4. -# Modify and copy a file, configure a smaller threshold in detectCopies and -# confirm that copy is detected in P4. -test_expect_success 'detect copies' ' - "$GITP4" clone --dest="$git" //depot@all && - test_when_finished cleanup_git && - cd "$git" && - git config git-p4.skipSubmitEditCheck true && - - cp file2 file8 && - git add file8 && - git commit -a -m "Copy file2 to file8" && - git diff-tree -r -C HEAD && - "$GITP4" submit && - p4 filelog //depot/file8 && - ! p4 filelog //depot/file8 | grep -q "branch from" && - - cp file2 file9 && - git add file9 && - git commit -a -m "Copy file2 to file9" && - git diff-tree -r -C HEAD && - git config git-p4.detectCopies true && - "$GITP4" submit && - p4 filelog //depot/file9 && - ! p4 filelog //depot/file9 | grep -q "branch from" && - - echo "file2" >>file2 && - cp file2 file10 && - git add file2 file10 && - git commit -a -m "Modify and copy file2 to file10" && - git diff-tree -r -C HEAD && - "$GITP4" submit && - p4 filelog //depot/file10 && - p4 filelog //depot/file10 | grep -q "branch from //depot/file" && - - cp file2 file11 && - git add file11 && - git commit -a -m "Copy file2 to file11" && - git diff-tree -r -C --find-copies-harder HEAD && - src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && - test "$src" = file10 && - git config git-p4.detectCopiesHarder true && - "$GITP4" submit && - p4 filelog //depot/file11 && - p4 filelog //depot/file11 | grep -q "branch from //depot/file" && - - cp file2 file12 && - echo "some text" >>file12 && - git add file12 && - git commit -a -m "Copy file2 to file12 with changes" && - git diff-tree -r -C --find-copies-harder HEAD && - level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && - test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && - src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && - test "$src" = file10 && - git config git-p4.detectCopies $((level + 2)) && - "$GITP4" submit && - p4 filelog //depot/file12 && - ! p4 filelog //depot/file12 | grep -q "branch from" && - - cp file2 file13 && - echo "different text" >>file13 && - git add file13 && - git commit -a -m "Copy file2 to file13 with changes" && - git diff-tree -r -C --find-copies-harder HEAD && - level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && - test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && - src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && - test "$src" = file10 && - git config git-p4.detectCopies $((level - 2)) && - "$GITP4" submit && - p4 filelog //depot/file13 && - p4 filelog //depot/file13 | grep -q "branch from //depot/file" -' - -# Create a simple branch structure in P4 depot to check if it is correctly -# cloned. -test_expect_success 'add simple p4 branches' ' - cd "$cli" && - mkdir branch1 && - cd branch1 && - echo file1 >file1 && - echo file2 >file2 && - p4 add file1 file2 && - p4 submit -d "branch1" && - p4 integrate //depot/branch1/... //depot/branch2/... && - p4 submit -d "branch2" && - echo file3 >file3 && - p4 add file3 && - p4 submit -d "add file3 in branch1" && - p4 open file2 && - echo update >>file2 && - p4 submit -d "update file2 in branch1" && - p4 integrate //depot/branch1/... //depot/branch3/... && - p4 submit -d "branch3" && - cd "$TRASH_DIRECTORY" -' - -# Configure branches through git-config and clone them. -# All files are tested to make sure branches were cloned correctly. -# Finally, make an update to branch1 on P4 side to check if it is imported -# correctly by git-p4. -test_expect_success 'git-p4 clone simple branches' ' - test_when_finished cleanup_git && - test_create_repo "$git" && - cd "$git" && - git config git-p4.branchList branch1:branch2 && - git config --add git-p4.branchList branch1:branch3 && - "$GITP4" clone --dest=. --detect-branches //depot@all && - git log --all --graph --decorate --stat && - git reset --hard p4/depot/branch1 && - test -f file1 && - test -f file2 && - test -f file3 && - grep -q update file2 && - git reset --hard p4/depot/branch2 && - test -f file1 && - test -f file2 && - test ! -f file3 && - ! grep -q update file2 && - git reset --hard p4/depot/branch3 && - test -f file1 && - test -f file2 && - test -f file3 && - grep -q update file2 && - cd "$cli" && - cd branch1 && - p4 edit file2 && - echo file2_ >>file2 && - p4 submit -d "update file2 in branch1" && - cd "$git" && - git reset --hard p4/depot/branch1 && - "$GITP4" rebase && - grep -q file2_ file2 -' - -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..d414705416 --- /dev/null +++ b/t/t9801-git-p4-branch.sh @@ -0,0 +1,313 @@ +#!/bin/sh + +test_description='git-p4 p4 branching tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +# +# 1: //depot/main/f1 +# 2: //depot/main/f2 +# 3: integrate //depot/main/... -> //depot/branch1/... +# 4: //depot/main/f4 +# 5: //depot/branch1/f5 +# .: named branch branch2 +# 6: integrate -b branch2 +# 7: //depot/branch2/f7 +# 8: //depot/main/f8 +# +test_expect_success 'basic p4 branches' ' + ( + cd "$cli" && + mkdir -p main && + + echo f1 >main/f1 && + p4 add main/f1 && + p4 submit -d "main/f1" && + + echo f2 >main/f2 && + p4 add main/f2 && + p4 submit -d "main/f2" && + + p4 integrate //depot/main/... //depot/branch1/... && + p4 submit -d "integrate main to branch1" && + + echo f4 >main/f4 && + p4 add main/f4 && + p4 submit -d "main/f4" && + + echo f5 >branch1/f5 && + p4 add branch1/f5 && + p4 submit -d "branch1/f5" && + + p4 branch -i <<-EOF && + Branch: branch2 + View: //depot/main/... //depot/branch2/... + EOF + + p4 integrate -b branch2 && + p4 submit -d "integrate main to branch2" && + + echo f7 >branch2/f7 && + p4 add branch2/f7 && + p4 submit -d "branch2/f7" && + + echo f8 >main/f8 && + p4 add main/f8 && + p4 submit -d "main/f8" + ) +' + +test_expect_success 'import main, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/main@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 4 wc + ) +' + +test_expect_success 'import branch1, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/branch1@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'import branch2, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot/branch2@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'import depot, no branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + git log --oneline --graph --decorate --all && + git rev-list master >wc && + test_line_count = 8 wc + ) +' + +test_expect_success 'import depot, branch detection' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" --detect-branches //depot@all && + ( + cd "$git" && + + git log --oneline --graph --decorate --all && + + # 4 main commits + git rev-list master >wc && + test_line_count = 4 wc && + + # 3 main, 1 integrate, 1 on branch2 + git rev-list p4/depot/branch2 >wc && + test_line_count = 5 wc && + + # no branch1, since no p4 branch created for it + test_must_fail git show-ref p4/depot/branch1 + ) +' + +test_expect_success 'import depot, branch detection, branchList branch definition' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + "$GITP4" clone --dest=. --detect-branches //depot@all && + + git log --oneline --graph --decorate --all && + + # 4 main commits + git rev-list master >wc && + test_line_count = 4 wc && + + # 3 main, 1 integrate, 1 on branch2 + git rev-list p4/depot/branch2 >wc && + test_line_count = 5 wc && + + # 2 main, 1 integrate, 1 on branch1 + git rev-list p4/depot/branch1 >wc && + test_line_count = 4 wc + ) +' + +test_expect_success 'restart p4d' ' + kill_p4d && + start_p4d +' + +# +# 1: //depot/branch1/file1 +# //depot/branch1/file2 +# 2: integrate //depot/branch1/... -> //depot/branch2/... +# 3: //depot/branch1/file3 +# 4: //depot/branch1/file2 (edit) +# 5: integrate //depot/branch1/... -> //depot/branch3/... +# +## Create a simple branch structure in P4 depot. +test_expect_success 'add simple p4 branches' ' + ( + cd "$cli" && + mkdir branch1 && + cd branch1 && + echo file1 >file1 && + echo file2 >file2 && + p4 add file1 file2 && + p4 submit -d "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 && + "$GITP4" clone --dest=. --detect-branches //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test -f file1 && + test -f file2 && + test -f file3 && + grep 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 branch3" && + cd "$git" && + git reset --hard p4/depot/branch1 && + "$GITP4" 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' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + 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 && + "$GITP4" 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 + ) +' + +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..992bb8cf0b --- /dev/null +++ b/t/t9802-git-p4-filetype.sh @@ -0,0 +1,139 @@ +#!/bin/sh + +test_description='git-p4 p4 filetype tests' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'utf-16 file create' ' + ( + cd "$cli" && + + # p4 saves this verbatim + printf "three\nline\ntext\n" >f-ascii && + p4 add -t text f-ascii && + + # p4 adds \377\376 header + cp f-ascii f-ascii-as-utf16 && + p4 add -t utf16 f-ascii-as-utf16 && + + # p4 saves this exactly as iconv produced it + printf "three\nline\ntext\n" | iconv -f ascii -t utf-16 >f-utf16 && + p4 add -t utf16 f-utf16 && + + # this also is unchanged + cp f-utf16 f-utf16-as-text && + p4 add -t text f-utf16-as-text && + + p4 submit -d "f files" && + + # force update of client files + p4 sync -f + ) +' + +test_expect_success 'utf-16 file test' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + + test_cmp "$cli/f-ascii" f-ascii && + test_cmp "$cli/f-ascii-as-utf16" f-ascii-as-utf16 && + test_cmp "$cli/f-utf16" f-utf16 && + test_cmp "$cli/f-utf16-as-text" f-utf16-as-text + ) +' + +test_expect_success 'keyword file create' ' + ( + cd "$cli" && + + printf "id\n\$Id\$\n\$Author\$\ntext\n" >k-text-k && + p4 add -t text+k k-text-k && + + cp k-text-k k-text-ko && + p4 add -t text+ko k-text-ko && + + cat k-text-k | iconv -f ascii -t utf-16 >k-utf16-k && + p4 add -t utf16+k k-utf16-k && + + cp k-utf16-k k-utf16-ko && + p4 add -t utf16+ko k-utf16-ko && + + p4 submit -d "k files" && + p4 sync -f + ) +' + +build_smush() { + cat >k_smush.py <<-\EOF && + import re, sys + sys.stdout.write(re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$', r'$\1$', sys.stdin.read())) + EOF + cat >ko_smush.py <<-\EOF + import re, sys + sys.stdout.write(re.sub(r'(?i)\$(Id|Header):[^$]*\$', r'$\1$', sys.stdin.read())) + EOF +} + +test_expect_success 'keyword file test' ' + build_smush && + test_when_finished rm -f k_smush.py ko_smush.py && + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot@all && + ( + cd "$git" && + + # text, ensure unexpanded + "$PYTHON_PATH" "$TRASH_DIRECTORY/k_smush.py" <"$cli/k-text-k" >cli-k-text-k-smush && + test_cmp cli-k-text-k-smush k-text-k && + "$PYTHON_PATH" "$TRASH_DIRECTORY/ko_smush.py" <"$cli/k-text-ko" >cli-k-text-ko-smush && + test_cmp cli-k-text-ko-smush k-text-ko && + + # utf16, even though p4 expands keywords, git-p4 does not + # try to undo that + test_cmp "$cli/k-utf16-k" k-utf16-k && + test_cmp "$cli/k-utf16-ko" k-utf16-ko + ) +' + +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 && + "$GITP4" 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..db670207bd --- /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' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + echo f1 >foo\$bar && + git add foo\$bar && + echo f2 >"file with spaces" && + git add "file with spaces" && + git commit -m "add files" && + P4EDITOR=touch "$GITP4" submit + ) && + ( + cd "$cli" && + p4 sync ... && + test -e "file with spaces" && + test -e "foo\$bar" + ) +' + +test_expect_success 'deleting with shell metachars' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + git config git-p4.skipSubmitEditCheck true && + git rm foo\$bar && + git rm file\ with\ spaces && + git commit -m "remove files" && + P4EDITOR=touch "$GITP4" submit + ) && + ( + cd "$cli" && + p4 sync ... && + test ! -e "file with spaces" && + test ! -e foo\$bar + ) +' + +# 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 && + "$GITP4" 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..a9e04efb88 --- /dev/null +++ b/t/t9804-git-p4-label.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +test_description='git-p4 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 ... && + + "$GITP4" 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 ... && + + "$GITP4" 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..df929e0555 --- /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' ' + "$GITP4" clone --dest="$git" //depot && + test_when_finished cleanup_git && + ( + cd "$git" && + echo line >>file1 && + git commit -a -m "change 2" && + echo y | "$GITP4" submit && + p4 changes //depot/... >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'no config, unedited, say no' ' + "$GITP4" 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" | "$GITP4" submit && + p4 changes //depot/... >wc && + test_line_count = 2 wc + ) +' + +test_expect_success 'skipSubmitEdit' ' + "$GITP4" 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" && + "$GITP4" submit && + p4 changes //depot/... >wc && + test_line_count = 3 wc + ) +' + +test_expect_success 'skipSubmitEditCheck' ' + "$GITP4" 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" && + "$GITP4" 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' ' + "$GITP4" 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" && + EDITOR="\"$ed\"" "$GITP4" 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..0571602129 --- /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 "$GITP4" clone --git-dir=xx //depot +' + +test_expect_success 'clone --branch' ' + "$GITP4" 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" && + "$GITP4" 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 "$GITP4" 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' ' + "$GITP4" 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 "$GITP4" sync && + + "$GITP4" 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' ' + "$GITP4" 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" + ) && + "$GITP4" 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 && + "$GITP4" 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 "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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..b1f61e3db5 --- /dev/null +++ b/t/t9807-git-p4-submit.sh @@ -0,0 +1,92 @@ +#!/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 && + "$GITP4" 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 && + "$GITP4" submit + ) +' + +# make two commits, but tell it to apply only from HEAD^ +test_expect_success 'submit --origin' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file3" && + test_commit "file4" && + git config git-p4.skipSubmitEdit true && + "$GITP4" submit --origin=HEAD^ + ) && + ( + cd "$cli" && + p4 sync && + test_path_is_missing "file3.t" && + test_path_is_file "file4.t" + ) +' + +test_expect_success 'submit with allowSubmit' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file5" && + git config git-p4.skipSubmitEdit true && + git config git-p4.allowSubmit "nobranch" && + test_must_fail "$GITP4" submit && + git config git-p4.allowSubmit "nobranch,master" && + "$GITP4" submit + ) +' + +test_expect_success 'submit with master branch name from argv' ' + test_when_finished cleanup_git && + "$GITP4" clone --dest="$git" //depot && + ( + cd "$git" && + test_commit "file6" && + git config git-p4.skipSubmitEdit true && + test_must_fail "$GITP4" submit nobranch && + git branch otherbranch && + git reset --hard HEAD^ && + test_commit "file7" && + "$GITP4" submit otherbranch + ) && + ( + cd "$cli" && + p4 sync && + test_path_is_file "file6.t" && + test_path_is_missing "file7.t" + ) +' + +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..f0022839c7 --- /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 && + "$GITP4" 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 && + "$GITP4" 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..773a516ff0 --- /dev/null +++ b/t/t9809-git-p4-client-view.sh @@ -0,0 +1,820 @@ +#!/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 "$GITP4" 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 "$GITP4" 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 "$GITP4" 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 "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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" && + "$GITP4" 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 && + "$GITP4" 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" && + "$GITP4" submit + ) && + ( + cd "$cli" && + test_path_is_file dir1/file11a + ) +' + +test_expect_success 'subdir clone, submit rename' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + "$GITP4" 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" && + "$GITP4" submit + ) && + ( + cd "$cli" && + test_path_is_missing dir1/file13 && + test_path_is_file dir1/file13a + ) +' + +test_expect_success 'reinit depot' ' + ( + cd "$cli" && + p4 sync -f && + 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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" && + "$GITP4" 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" && + "$GITP4" 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" && + "$GITP4" 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 && + "$GITP4" 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" && + "$GITP4" 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" && + "$GITP4" 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" && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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..49dfde0616 --- /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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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" + ) && + ! "$GITP4" 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 && + "$GITP4" 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 -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" && + "$GITP4" submit && + "$GITP4" rebase && + git diff p4/master && + "$GITP4" 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 && + "$GITP4" rebase && + "$GITP4" 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 + ) && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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 && + "$GITP4" 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" + ) && + "$GITP4" 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" | "$GITP4" submit) && + git rebase --skip && + ! test -f merge2.c + ) +' + + +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/test-lib-functions.sh b/t/test-lib-functions.sh new file mode 100644 index 0000000000..7b3b4bef30 --- /dev/null +++ b/t/test-lib-functions.sh @@ -0,0 +1,565 @@ +#!/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 -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 +} + +# 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 () { + 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=$@" +} + +# 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 bdd9513b84..b7d7100c4e 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 @@ -96,6 +100,8 @@ _z40=0000000000000000000000000000000000000000 LF=' ' +export _x05 _x40 _z40 LF + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... @@ -191,6 +197,7 @@ then fi exec 5>&1 +exec 6<&0 if test "$verbose" = "t" then exec 4>&2 3>&1 @@ -220,221 +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=$@" -} - -# Unset a configuration variable, but don't fail if it doesn't exist. -test_unconfig () { - git config --unset-all "$@" - config_status=$? - case "$config_status" in - 5) # ok, nothing to unset - config_status=0 - ;; - esac - return $config_status -} - -# Set git config, automatically unsetting it after the test is over. -test_config () { - test_when_finished "test_unconfig '$1'" && - git config "$@" -} - -# Use test_set_prereq to tell that a particular prerequisite is available. -# The prerequisite can later be checked for in two ways: -# -# - 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. @@ -469,7 +264,7 @@ test_debug () { test_eval_ () { # This is a separate function because some tests use # "return" to end a test_expect_success block early. - eval >&3 2>&4 "$*" + eval </dev/null >&3 2>&4 "$*" } test_run_ () { @@ -522,318 +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" - 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 +# 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" @@ -872,6 +365,8 @@ test_done () { cd "$(dirname "$remove_trash")" && rm -rf "$(basename "$remove_trash")" + test_at_end_hook_ + exit 0 ;; *) @@ -894,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" @@ -1029,7 +530,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" || { @@ -1041,7 +542,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 @@ -1113,12 +618,14 @@ esac test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PYTHON" && test_set_prereq PYTHON test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE +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; |