diff options
Diffstat (limited to 't')
265 files changed, 12175 insertions, 2942 deletions
diff --git a/t/.gitignore b/t/.gitignore index 7dcbb232cd..4e731dc1e3 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -1,2 +1,3 @@ /trash directory* /test-results +/.prove diff --git a/t/Makefile b/t/Makefile index 25c559bb49..c7baefb7ea 100644 --- a/t/Makefile +++ b/t/Makefile @@ -3,10 +3,12 @@ # Copyright (c) 2005 Junio C Hamano # +-include ../config.mak.autogen -include ../config.mak #GIT_TEST_OPTS=--verbose --debug SHELL_PATH ?= $(SHELL) +PERL_PATH ?= /usr/bin/perl TAR ?= $(TAR) RM ?= rm -f @@ -27,15 +29,17 @@ pre-clean: clean: $(RM) -r 'trash directory'.* test-results - $(RM) t????/cvsroot/CVSROOT/?* $(RM) -r valgrind/bin + $(RM) .prove aggregate-results-and-cleanup: $(T) $(MAKE) aggregate-results $(MAKE) clean aggregate-results: - '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-* + for f in test-results/t*-*.counts; do \ + echo "$$f"; \ + done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL full-svn-test: @@ -45,4 +49,42 @@ full-svn-test: valgrind: GIT_TEST_OPTS=--valgrind $(MAKE) -.PHONY: pre-clean $(T) aggregate-results clean valgrind +# Smoke testing targets +-include ../GIT-VERSION-FILE +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo unknown') +uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo unknown') + +test-results: + mkdir -p test-results + +test-results/git-smoke.tar.gz: test-results + $(PERL_PATH) ./harness \ + --archive="test-results/git-smoke.tar.gz" \ + $(T) + +smoke: test-results/git-smoke.tar.gz + +SMOKE_UPLOAD_FLAGS = +ifdef SMOKE_USERNAME + SMOKE_UPLOAD_FLAGS += -F username="$(SMOKE_USERNAME)" -F password="$(SMOKE_PASSWORD)" +endif +ifdef SMOKE_COMMENT + SMOKE_UPLOAD_FLAGS += -F comments="$(SMOKE_COMMENT)" +endif +ifdef SMOKE_TAGS + SMOKE_UPLOAD_FLAGS += -F tags="$(SMOKE_TAGS)" +endif + +smoke_report: smoke + curl \ + -H "Expect: " \ + -F project=Git \ + -F architecture="$(uname_M)" \ + -F platform="$(uname_S)" \ + -F revision="$(GIT_VERSION)" \ + -F report_file=@test-results/git-smoke.tar.gz \ + $(SMOKE_UPLOAD_FLAGS) \ + 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 @@ -18,25 +18,48 @@ The easiest way to run tests is to say "make". This runs all the tests. *** t0000-basic.sh *** - * ok 1: .git/objects should be empty after git-init in an empty repo. - * ok 2: .git/objects should have 256 subdirectories. - * ok 3: git-update-index without --add should fail adding. + ok 1 - .git/objects should be empty after git init in an empty repo. + ok 2 - .git/objects should have 3 subdirectories. + ok 3 - success is reported like this ... - * ok 23: no diff after checkout and git-update-index --refresh. - * passed all 23 test(s) - *** t0100-environment-names.sh *** - * ok 1: using old names should issue warnings. - * ok 2: using old names but having new names should not issue warnings. - ... - -Or you can run each test individually from command line, like -this: - - $ sh ./t3001-ls-files-killed.sh - * ok 1: git-update-index --add to add various paths. - * ok 2: git-ls-files -k to show killed files. - * ok 3: validate git-ls-files -k output. - * passed all 3 test(s) + ok 43 - very long name in the index handled sanely + # fixed 1 known breakage(s) + # still have 1 known breakage(s) + # passed all remaining 42 test(s) + 1..43 + *** t0001-init.sh *** + ok 1 - plain + ok 2 - plain with GIT_WORK_TREE + ok 3 - plain bare + +Since the tests all output TAP (see http://testanything.org) they can +be run with any TAP harness. Here's an example of parallel testing +powered by a recent version of prove(1): + + $ prove --timer --jobs 15 ./t[0-9]*.sh + [19:17:33] ./t0005-signals.sh ................................... ok 36 ms + [19:17:33] ./t0022-crlf-rename.sh ............................... ok 69 ms + [19:17:33] ./t0024-crlf-archive.sh .............................. ok 154 ms + [19:17:33] ./t0004-unwritable.sh ................................ ok 289 ms + [19:17:33] ./t0002-gitfile.sh ................................... ok 480 ms + ===( 102;0 25/? 6/? 5/? 16/? 1/? 4/? 2/? 1/? 3/? 1... )=== + +prove and other harnesses come with a lot of useful options. The +--state option in particular is very useful: + + # Repeat until no more failures + $ prove -j 15 --state=failed,save ./t[0-9]*.sh + +You can also run each test individually from command line, like this: + + $ sh ./t3010-ls-files-killed-modified.sh + ok 1 - git update-index --add to add various paths. + ok 2 - git ls-files -k to show killed files. + ok 3 - validate git ls-files -k output. + ok 4 - git ls-files -m to show modified files. + ok 5 - validate git ls-files -m output. + # passed all 5 test(s) + 1..5 You can pass --verbose (or -v), --debug (or -d), and --immediate (or -i) command line argument to the test, or by setting GIT_TEST_OPTS @@ -84,6 +107,12 @@ appropriately before running "make". implied by other options like --valgrind and GIT_TEST_INSTALLED. +--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. + You can also set the GIT_TEST_INSTALLED environment variable to the bindir of an existing git installation to test that installation. You still need to have built this git sandbox, from which various @@ -192,15 +221,128 @@ This test harness library does the following things: - If the script is invoked with command line argument --help (or -h), it shows the test_description and exits. - - Creates an empty test directory with an empty .git/objects - database and chdir(2) into it. This directory is 't/trash directory' - if you must know, but I do not think you care. + - Creates an empty test directory with an empty .git/objects database + and chdir(2) into it. This directory is 't/trash + directory.$test_name_without_dotsh', with t/ subject to change by + the --root option documented above. - Defines standard test helper functions for your scripts to use. These functions are designed to make all scripts behave consistently when command line arguments --verbose (or -v), --debug (or -d), and --immediate (or -i) is given. +Do's, don'ts & things to keep in mind +------------------------------------- + +Here are a few examples of things you probably should and shouldn't do +when writing tests. + +Do: + + - Put all code inside test_expect_success and other assertions. + + Even code that isn't a test per se, but merely some setup code + should be inside a test assertion. + + - Chain your test assertions + + Write test code like this: + + git merge foo && + git push bar && + test ... + + Instead of: + + git merge hla + git push gh + test ... + + That way all of the commands in your tests will succeed or fail. If + you must ignore the return value of something (e.g., the return + after unsetting a variable that was already unset is unportable) it's + best to indicate so explicitly with a semicolon: + + unset HLAGH; + git merge hla && + git push gh && + test ... + + - Check the test coverage for your tests. See the "Test coverage" + below. + + Don't blindly follow test coverage metrics, they're a good way to + spot if you've missed something. If a new function you added + doesn't have any coverage you're probably doing something wrong, + but having 100% coverage doesn't necessarily mean that you tested + everything. + + Tests that are likely to smoke out future regressions are better + than tests that just inflate the coverage metrics. + +Don't: + + - exit() within a <script> part. + + The harness will catch this as a programming error of the test. + Use test_done instead if you need to stop the tests early (see + "Skipping tests" below). + + - Break the TAP output + + The raw output from your test may be interpreted by a TAP harness. TAP + harnesses will ignore everything they don't know about, but don't step + on their toes in these areas: + + - Don't print lines like "$x..$y" where $x and $y are integers. + + - Don't print lines that begin with "ok" or "not ok". + + TAP harnesses expect a line that begins with either "ok" and "not + ok" to signal a test passed or failed (and our harness already + produces such lines), so your script shouldn't emit such lines to + their output. + + You can glean some further possible issues from the TAP grammar + (see http://search.cpan.org/perldoc?TAP::Parser::Grammar#TAP_Grammar) + but the best indication is to just run the tests with prove(1), + it'll complain if anything is amiss. + +Keep in mind: + + - Inside <script> part, the standard output and standard error + streams are discarded, and the test harness only reports "ok" or + "not ok" to the end user running the tests. Under --verbose, they + are shown to help debugging the tests. + + +Skipping tests +-------------- + +If you need to skip tests you should do so be using the three-arg form +of the test_* functions (see the "Test harness library" section +below), e.g.: + + test_expect_success PERL 'I need Perl' " + '$PERL_PATH' -e 'hlagh() if unf_unf()' + " + +The advantage of skipping tests like this is that platforms that don't +have the PERL and other optional dependencies get an indication of how +many tests they're missing. + +If the test code is too hairy for that (i.e. does a lot of setup work +outside test assertions) you can also skip all remaining tests by +setting skip_all and immediately call test_done: + + if ! test_have_prereq PERL + then + skip_all='skipping perl interface tests, perl not available' + test_done + fi + +The string you give to skip_all will be used as an explanation for why +the test was skipped. End with test_done ------------------ @@ -216,9 +358,9 @@ Test harness library There are a handful helper functions defined in the test harness library for your script to use. - - test_expect_success <message> <script> + - test_expect_success [<prereq>] <message> <script> - This takes two strings as parameter, and evaluates the + Usually takes two strings as parameter, and evaluates the <script>. If it yields success, test is considered successful. <message> should state what it is testing. @@ -228,7 +370,20 @@ library for your script to use. 'git-write-tree should be able to write an empty tree.' \ 'tree=$(git-write-tree)' - - test_expect_failure <message> <script> + If you supply three parameters the first will be taken to be a + prerequisite, see the test_set_prereq and test_have_prereq + documentation below: + + test_expect_success TTY 'git --paginate rev-list uses a pager' \ + ' ... ' + + You can also supply a comma-separated list of prerequisites, in the + rare case where your test depends on more than one: + + test_expect_success PERL,PYTHON 'yo dawg' \ + ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" ' + + - test_expect_failure [<prereq>] <message> <script> This is NOT the opposite of test_expect_success, but is used to mark a test that demonstrates a known breakage. Unlike @@ -237,6 +392,16 @@ library for your script to use. success and "still broken" on failure. Failures from these tests won't cause -i (immediate) to stop. + Like test_expect_success this function can optionally use a three + argument invocation with a prerequisite as the first argument. + + - test_expect_code [<prereq>] <code> <message> <script> + + Analogous to test_expect_success, but pass the test if it exits + with a given exit <code> + + test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master' + - test_debug <script> This takes a single argument, <script>, and evaluates it only @@ -269,6 +434,134 @@ library for your script to use. Merges the given rev using the given message. Like test_commit, creates a tag and calls test_tick before committing. + - test_set_prereq SOME_PREREQ + + Set a test prerequisite to be used later with test_have_prereq. The + test-lib will set some prerequisites for you, see the + "Prerequisites" section below for a full list of these. + + Others you can set yourself and use later with either + test_have_prereq directly, or the three argument invocation of + test_expect_success and test_expect_failure. + + - test_have_prereq SOME PREREQ + + Check if we have a prerequisite previously set with + test_set_prereq. The most common use of this directly is to skip + all the tests if we don't have some essential prerequisite: + + if ! test_have_prereq PERL + then + skip_all='skipping perl interface tests, perl not available' + test_done + fi + + - test_external [<prereq>] <message> <external> <script> + + Execute a <script> with an <external> interpreter (like perl). This + was added for tests like t9700-perl-git.sh which do most of their + work in an external test script. + + test_external \ + 'GitwebCache::*FileCache*' \ + "$PERL_PATH" "$TEST_DIRECTORY"/t9503/test_cache_interface.pl + + If the test is outputting its own TAP you should set the + test_external_has_tap variable somewhere before calling the first + test_external* function. See t9700-perl-git.sh for an example. + + # The external test will outputs its own plan + test_external_has_tap=1 + + - test_external_without_stderr [<prereq>] <message> <external> <script> + + Like test_external but fail if there's any output on stderr, + instead of checking the exit code. + + test_external_without_stderr \ + 'Perl API' \ + "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl + + - test_must_fail <git-command> + + Run a git command and ensure it fails in a controlled way. Use + this instead of "! <git-command>". When git-command dies due to a + segfault, test_must_fail diagnoses it as an error; "! <git-command>" + treats it as just another expected failure, which would let such a + bug go unnoticed. + + - test_might_fail <git-command> + + Similar to test_must_fail, but tolerate success, too. Use this + instead of "<git-command> || :" to catch failures due to segv. + + - test_cmp <expected> <actual> + + Check whether the content of the <actual> file matches the + <expected> file. This behaves like "cmp" but produces more + helpful output when the test is run with "-v" option. + + - test_path_is_file <file> [<diagnosis>] + test_path_is_dir <dir> [<diagnosis>] + test_path_is_missing <path> [<diagnosis>] + + Check whether a file/directory exists or doesn't. <diagnosis> will + be displayed if the test fails. + + - test_when_finished <script> + + Prepend <script> to a list of commands to run to clean up + at the end of the current test. If some clean-up command + fails, the test will not pass. + + Example: + + test_expect_success 'branch pointing to non-commit' ' + git rev-parse HEAD^{tree} >.git/refs/heads/invalid && + test_when_finished "git update-ref -d refs/heads/invalid" && + ... + ' + +Prerequisites +------------- + +These are the prerequisites that the test library predefines with +test_have_prereq. + +See the prereq argument to the test_* functions in the "Test harness +library" section above and the "test_have_prereq" function for how to +use these, and "test_set_prereq" for how to define your own. + + - PERL & PYTHON + + Git wasn't compiled with NO_PERL=YesPlease or + NO_PYTHON=YesPlease. Wrap any tests that need Perl or Python in + these. + + - POSIXPERM + + The filesystem supports POSIX style permission bits. + + - BSLASHPSPEC + + Backslashes in pathspec are not directory separators. This is not + set on Windows. See 6fd1106a for details. + + - EXECKEEPSPID + + The process retains the same pid across exec(2). See fb9a2bea for + details. + + - SYMLINKS + + The filesystem we're on supports symbolic links. E.g. a FAT + filesystem doesn't support these. See 704a3143 for details. + + - SANITY + + Test is not run by root user, and an attempt to write to an + unwritable file is expected to fail correctly. + Tips for Writing Tests ---------------------- @@ -295,3 +588,115 @@ the purpose of t0000-basic.sh, which is to isolate that level of validation in one place. Your test also ends up needing updating when such a change to the internal happens, so do _not_ do it and leave the low level of validation to t0000-basic.sh. + +Test coverage +------------- + +You can use the coverage tests to find code paths that are not being +used or properly exercised yet. + +To do that, run the coverage target at the top-level (not in the t/ +directory): + + make coverage + +That'll compile Git with GCC's coverage arguments, and generate a test +report with gcov after the tests finish. Running the coverage tests +can take a while, since running the tests in parallel is incompatible +with GCC's coverage mode. + +After the tests have run you can generate a list of untested +functions: + + make coverage-untested-functions + +You can also generate a detailed per-file HTML report using the +Devel::Cover module. To install it do: + + # On Debian or Ubuntu: + sudo aptitude install libdevel-cover-perl + + # From the CPAN with cpanminus + curl -L http://cpanmin.us | perl - --sudo --self-upgrade + cpanm --sudo Devel::Cover + +Then, at the top-level: + + make cover_db_html + +That'll generate a detailed cover report in the "cover_db_html" +directory, which you can then copy to a webserver, or inspect locally +in a browser. + +Smoke testing +------------- + +The Git test suite has support for smoke testing. Smoke testing is +when you submit the results of a test run to a central server for +analysis and aggregation. + +Running a smoke tester is an easy and valuable way of contributing to +Git development, particularly if you have access to an uncommon OS on +obscure hardware. + +After building Git you can generate a smoke report like this in the +"t" directory: + + make clean smoke + +You can also pass arguments via the environment. This should make it +faster: + + GIT_TEST_OPTS='--root=/dev/shm' TEST_JOBS=10 make clean smoke + +The "smoke" target will run the Git test suite with Perl's +"TAP::Harness" module, and package up the results in a .tar.gz archive +with "TAP::Harness::Archive". The former is included with Perl v5.10.1 +or later, but you'll need to install the latter from the CPAN. See the +"Test coverage" section above for how you might do that. + +Once the "smoke" target finishes you'll see a message like this: + + TAP Archive created at <path to git>/t/test-results/git-smoke.tar.gz + +To upload the smoke report you need to have curl(1) installed, then +do: + + make smoke_report + +To upload the report anonymously. Hopefully that'll return something +like "Reported #7 added.". + +If you're going to be uploading reports frequently please request a +user account by E-Mailing gitsmoke@v.nix.is. Once you have a username +and password you'll be able to do: + + SMOKE_USERNAME=<username> SMOKE_PASSWORD=<password> make smoke_report + +You can also add an additional comment to attach to the report, and/or +a comma separated list of tags: + + SMOKE_USERNAME=<username> SMOKE_PASSWORD=<password> \ + SMOKE_COMMENT=<comment> SMOKE_TAGS=<tags> \ + make smoke_report + +Once the report is uploaded it'll be made available at +http://smoke.git.nix.is, here's an overview of Recent Smoke Reports +for Git: + + http://smoke.git.nix.is/app/projects/smoke_reports/1 + +The reports will also be mirrored to GitHub every few hours: + + http://github.com/gitsmoke/smoke-reports + +The Smolder SQLite database is also mirrored and made available for +download: + + http://github.com/gitsmoke/smoke-database + +Note that the database includes hashed (with crypt()) user passwords +and E-Mail addresses. Don't use a valuable password for the smoke +service if you have an account, or an E-Mail address you don't want to +be publicly known. The user accounts are just meant to be convenient +labels, they're not meant to be secure. diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index d5bab75d7d..d206b7c4cf 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -6,7 +6,7 @@ failed=0 broken=0 total=0 -for file +while read file do while read type value do diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 396b9653a3..141b60cdcb 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -8,27 +8,27 @@ check_count () { $PROG file $head >.result || return 1 cat .result | perl -e ' my %expect = (@ARGV); - my %count = (); + my %count = map { $_ => 0 } keys %expect; while (<STDIN>) { if (/^[0-9a-f]+\t\(([^\t]+)\t/) { my $author = $1; for ($author) { s/^\s*//; s/\s*$//; } - if (exists $expect{$author}) { - $count{$author}++; - } + $count{$author}++; } } my $bad = 0; while (my ($author, $count) = each %count) { my $ok; - if ($expect{$author} != $count) { + my $value = 0; + $value = $expect{$author} if defined $expect{$author}; + if ($value != $count) { $bad = 1; $ok = "bad"; } else { $ok = "good"; } - print STDERR "Author $author (expected $expect{$author}, attributed $count) $ok\n"; + print STDERR "Author $author (expected $value, attributed $count) $ok\n"; } exit($bad); ' "$@" diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh index 5a734b1b7b..8c490c8707 100644 --- a/t/gitweb-lib.sh +++ b/t/gitweb-lib.sh @@ -19,9 +19,9 @@ our \$site_name = '[localhost]'; our \$site_header = ''; our \$site_footer = ''; our \$home_text = 'indextext.html'; -our @stylesheets = ('file:///$TEST_DIRECTORY/../gitweb/gitweb.css'); -our \$logo = 'file:///$TEST_DIRECTORY/../gitweb/git-logo.png'; -our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/git-favicon.png'; +our @stylesheets = ('file:///$GIT_BUILD_DIR/gitweb/static/gitweb.css'); +our \$logo = 'file:///$GIT_BUILD_DIR/gitweb/static/git-logo.png'; +our \$favicon = 'file:///$GIT_BUILD_DIR/gitweb/static/git-favicon.png'; our \$projects_list = ''; our \$export_ok = ''; our \$strict_export = ''; @@ -38,7 +38,7 @@ gitweb_run () { GATEWAY_INTERFACE='CGI/1.1' HTTP_ACCEPT='*/*' REQUEST_METHOD='GET' - SCRIPT_NAME="$TEST_DIRECTORY/../gitweb/gitweb.perl" + SCRIPT_NAME="$GIT_BUILD_DIR/gitweb/gitweb.perl" QUERY_STRING=""$1"" PATH_INFO=""$2"" export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD \ @@ -76,13 +76,13 @@ gitweb_run () { . ./test-lib.sh if ! test_have_prereq PERL; then - say 'skipping gitweb tests, perl not available' + skip_all='skipping gitweb tests, perl not available' test_done fi perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || { - say 'skipping gitweb tests, perl version is too old' - test_done + skip_all='skipping gitweb tests, perl version is too old' + test_done } gitweb_init diff --git a/t/harness b/t/harness new file mode 100755 index 0000000000..f5c02f49b7 --- /dev/null +++ b/t/harness @@ -0,0 +1,21 @@ +#!/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-cvs.sh b/t/lib-cvs.sh index 4b3b793730..44263ade25 100644 --- a/t/lib-cvs.sh +++ b/t/lib-cvs.sh @@ -3,13 +3,10 @@ . ./test-lib.sh unset CVS_SERVER -# for clean cvsps cache -HOME=$(pwd) -export HOME if ! type cvs >/dev/null 2>&1 then - say 'skipping cvsimport tests, cvs not found' + skip_all='skipping cvsimport tests, cvs not found' test_done fi @@ -21,15 +18,21 @@ case "$cvsps_version" in 2.1 | 2.2*) ;; '') - say 'skipping cvsimport tests, cvsps not found' + skip_all='skipping cvsimport tests, cvsps not found' test_done ;; *) - say 'skipping cvsimport tests, unsupported cvsps version' + skip_all='skipping cvsimport tests, unsupported cvsps version' test_done ;; esac +setup_cvs_test_repository () { + CVSROOT="$(pwd)/.cvsroot" && + cp -r "$TEST_DIRECTORY/$1/cvsroot" "$CVSROOT" && + export CVSROOT +} + test_cvs_co () { # Usage: test_cvs_co BRANCH_NAME rm -rf module-cvs-"$1" diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index 0f7f35ccc9..92d6d31942 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -5,23 +5,22 @@ git_svn_id=git""-svn-id if test -n "$NO_SVN_TESTS" then - say 'skipping git svn tests, NO_SVN_TESTS defined' + skip_all='skipping git svn tests, NO_SVN_TESTS defined' test_done fi if ! test_have_prereq PERL; then - say 'skipping git svn tests, perl not available' + skip_all='skipping git svn tests, perl not available' test_done fi GIT_DIR=$PWD/.git GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn SVN_TREE=$GIT_SVN_DIR/svn-tree -PERL=${PERL:-perl} svn >/dev/null 2>&1 if test $? -ne 1 then - say 'skipping git svn tests, svn not found' + skip_all='skipping git svn tests, svn not found' test_done fi @@ -30,7 +29,7 @@ export svnrepo svnconf=$PWD/svnconf export svnconf -$PERL -w -e " +"$PERL_PATH" -w -e " use SVN::Core; use SVN::Repos; \$SVN::Core::VERSION gt '1.1.0' or exit(42); @@ -40,13 +39,12 @@ x=$? if test $x -ne 0 then if test $x -eq 42; then - err='Perl SVN libraries must be >= 1.1.0' + skip_all='Perl SVN libraries must be >= 1.1.0' elif test $x -eq 41; then - err='svnadmin failed to create fsfs repository' + skip_all='svnadmin failed to create fsfs repository' else - err='Perl SVN libraries not found or unusable, skipping test' + skip_all='Perl SVN libraries not found or unusable' fi - say "$err" test_done fi @@ -131,7 +129,7 @@ stop_httpd () { } convert_to_rev_db () { - $PERL -w -- - "$@" <<\EOF + "$PERL_PATH" -w -- - "$@" <<\EOF use strict; @ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>"; open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]"; @@ -159,7 +157,7 @@ EOF require_svnserve () { if test -z "$SVNSERVE_PORT" then - say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)' + skip_all='skipping svnserve test. (set $SVNSERVE_PORT to enable)' test_done fi } diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index da4b8d5a6f..e733f6516f 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -5,8 +5,7 @@ if test -z "$GIT_TEST_HTTPD" then - say "skipping test, network testing disabled by default" - say "(define GIT_TEST_HTTPD to enable)" + skip_all="Network testing disabled (define GIT_TEST_HTTPD to enable)" test_done fi @@ -46,7 +45,7 @@ HTTPD_DOCUMENT_ROOT_PATH=$HTTPD_ROOT_PATH/www if ! test -x "$LIB_HTTPD_PATH" then - say "skipping test, no web server found at '$LIB_HTTPD_PATH'" + skip_all="skipping test, no web server found at '$LIB_HTTPD_PATH'" test_done fi @@ -59,12 +58,12 @@ then then if ! test $HTTPD_VERSION -ge 2 then - say "skipping test, at least Apache version 2 is required" + skip_all="skipping test, at least Apache version 2 is required" test_done fi if ! test -d "$DEFAULT_HTTPD_MODULE_PATH" then - say "Apache module directory not found. Skipping tests." + skip_all="Apache module directory not found. Skipping tests." test_done fi @@ -119,7 +118,7 @@ start_httpd() { >&3 2>&4 if test $? -ne 0 then - say "skipping test, web server setup failed" + skip_all="skipping test, web server setup failed" trap 'die' EXIT test_done fi @@ -146,7 +145,7 @@ test_http_push_nonff() { echo "changed" > path2 && git commit -a -m path2 --amend && - !(git push -v origin >output 2>&1) && + test_must_fail git push -v origin >output 2>&1 && (cd "$REMOTE_REPO" && test $HEAD = $(git rev-parse --verify HEAD)) ' diff --git a/t/lib-pager.sh b/t/lib-pager.sh new file mode 100644 index 0000000000..ba03eab14f --- /dev/null +++ b/t/lib-pager.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +test_expect_success 'determine default pager' ' + test_might_fail git config --unset core.pager && + less=$( + unset PAGER GIT_PAGER; + git var GIT_PAGER + ) && + test -n "$less" +' + +if expr "$less" : '[a-z][a-z]*$' >/dev/null +then + test_set_prereq SIMPLEPAGER +fi diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh index ce36f34d03..06c3c91762 100644 --- a/t/lib-patch-mode.sh +++ b/t/lib-patch-mode.sh @@ -2,11 +2,6 @@ . ./test-lib.sh -if ! test_have_prereq PERL; then - say 'skipping --patch tests, perl not available' - test_done -fi - set_state () { echo "$3" > "$1" && git add "$1" && diff --git a/t/lib-prereq-FILEMODE.sh b/t/lib-prereq-FILEMODE.sh new file mode 100644 index 0000000000..bce5a4c8bd --- /dev/null +++ b/t/lib-prereq-FILEMODE.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# Copyright (c) 2010 Ævar Arnfjörð Bjarmason +# + +if test "$(git config --bool core.filemode)" = false +then + say 'filemode disabled on the filesystem' +else + test_set_prereq FILEMODE +fi diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 6aefe27593..6ccf797091 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -47,6 +47,8 @@ for line in $FAKE_LINES; do case $line in squash|fixup|edit|reword) action="$line";; + exec*) + echo "$line" | sed 's/_/ /g' >> "$1";; "#") echo '# comment' >> "$1";; ">") diff --git a/t/t6000lib.sh b/t/lib-t6000.sh index 985d517a1c..ea25dd89e5 100644 --- a/t/t6000lib.sh +++ b/t/lib-t6000.sh @@ -91,7 +91,7 @@ check_output() shift 1 if eval "$*" | entag > $_name.actual then - diff $_name.expected $_name.actual + test_cmp $_name.expected $_name.actual else return 1; fi diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index f4ca4fc85c..f688bd3ef5 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -54,9 +54,40 @@ test_expect_success 'success is reported like this' ' test_expect_failure 'pretend we have a known breakage' ' 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 && +cat >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' ' @@ -73,6 +104,48 @@ then exit 1 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 +' +donthaveit=yes +test_expect_success HAVEIT,DONTHAVEIT 'unmet prerequisites causes test to be skipped' ' + donthaveit=no +' +donthaveiteither=yes +test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' ' + donthaveiteither=no +' +if test $haveit$donthaveit$donthaveiteither != yesyesyes +then + say "bug in test framework: multiple prerequisite tags do not work reliably" + exit 1 +fi + +clean=no +test_expect_success 'tests clean up after themselves' ' + test_when_finished clean=yes +' + +cleaner=no +test_expect_code 1 'tests clean up even after a failure' ' + test_when_finished cleaner=yes && + (exit 1) +' + +if test $clean$cleaner != yesyes +then + say "bug in test framework: cleanup commands do not work reliably" + exit 1 +fi + +test_expect_code 2 'failure to clean up causes the test to fail' ' + test_when_finished "(exit 2)" +' + ################################################################ # Basics of the basics @@ -280,7 +353,7 @@ $expectfilter >expected <<\EOF EOF test_expect_success \ 'validate git diff-files output for a know cache/work tree state.' \ - 'git diff-files >current && diff >/dev/null -b current expected' + 'git diff-files >current && test_cmp current expected >/dev/null' test_expect_success \ 'git update-index --refresh should succeed.' \ diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 675773479a..7fe8883ae0 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -171,8 +171,6 @@ test_expect_success 'init with init.templatedir set' ' mkdir templatedir-source && echo Content >templatedir-source/file && ( - HOME="`pwd`" && - export HOME && test_config="${HOME}/.gitconfig" && git config -f "$test_config" init.templatedir "${HOME}/templatedir-source" && mkdir templatedir-set && @@ -188,8 +186,6 @@ test_expect_success 'init with init.templatedir set' ' test_expect_success 'init --bare/--shared overrides system/global config' ' ( - HOME="`pwd`" && - export HOME && test_config="$HOME"/.gitconfig && unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" core.bare false && @@ -205,8 +201,6 @@ test_expect_success 'init --bare/--shared overrides system/global config' ' test_expect_success 'init honors global core.sharedRepository' ' ( - HOME="`pwd`" && - export HOME && test_config="$HOME"/.gitconfig && unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" core.sharedRepository 0666 && @@ -301,7 +295,7 @@ test_expect_success 'init notices EEXIST (2)' ' ) ' -test_expect_success POSIXPERM 'init notices EPERM' ' +test_expect_success POSIXPERM,SANITY 'init notices EPERM' ' rm -fr newdir && ( mkdir newdir && @@ -310,4 +304,18 @@ test_expect_success POSIXPERM 'init notices EPERM' ' ) ' +test_expect_success 'init creates a new bare directory with global --bare' ' + rm -rf newdir && + git --bare init newdir && + test -d newdir/refs +' + +test_expect_success 'init prefers command line to GIT_DIR' ' + rm -rf newdir && + mkdir otherdir && + GIT_DIR=otherdir git --bare init newdir && + test -d newdir/refs && + ! test -d otherdir/refs +' + test_done diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 1c77192eb3..e75153bdea 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -20,8 +20,12 @@ test_expect_success 'setup' ' mkdir -p a/b/d a/c && ( + echo "[attr]notest !test" echo "f test=f" echo "a/i test=a/i" + echo "onoff test -test" + echo "offon -test test" + echo "no notest" ) >.gitattributes && ( echo "g test=a/g" && @@ -30,7 +34,11 @@ test_expect_success 'setup' ' ( echo "h test=a/b/h" && echo "d/* test=a/b/d/*" + echo "d/yes notest" ) >a/b/.gitattributes + ( + echo "global test=global" + ) >"$HOME"/global-gitattributes ' @@ -43,8 +51,23 @@ test_expect_success 'attribute test' ' attr_check a/b/g a/b/g && attr_check b/g unspecified && attr_check a/b/h a/b/h && - attr_check a/b/d/g "a/b/d/*" + attr_check a/b/d/g "a/b/d/*" && + attr_check onoff unset && + attr_check offon set && + attr_check no unspecified && + attr_check a/b/d/no "a/b/d/*" && + attr_check a/b/d/yes unspecified + +' +test_expect_success 'core.attributesfile' ' + attr_check global unspecified && + git config core.attributesfile "$HOME/global-gitattributes" && + attr_check global global && + git config core.attributesfile "~/global-gitattributes" && + attr_check global global && + echo "global test=precedence" >> .gitattributes && + attr_check global precedence ' test_expect_success 'attribute test: read paths from stdin' ' @@ -58,6 +81,11 @@ a/b/g: test: a/b/g b/g: test: unspecified a/b/h: test: a/b/h a/b/d/g: test: a/b/d/* +onoff: test: unset +offon: test: set +no: test: unspecified +a/b/d/no: test: a/b/d/* +a/b/d/yes: test: unspecified EOF sed -e "s/:.*//" < expect | git check-attr --stdin test > actual && diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh index 2342ac5788..e3137d638e 100755 --- a/t/t0004-unwritable.sh +++ b/t/t0004-unwritable.sh @@ -15,54 +15,30 @@ test_expect_success setup ' ' -test_expect_success POSIXPERM 'write-tree should notice unwritable repository' ' - - ( - chmod a-w .git/objects .git/objects/?? && - test_must_fail git write-tree - ) - status=$? - chmod 775 .git/objects .git/objects/?? - (exit $status) - +test_expect_success POSIXPERM,SANITY 'write-tree should notice unwritable repository' ' + test_when_finished "chmod 775 .git/objects .git/objects/??" && + chmod a-w .git/objects .git/objects/?? && + test_must_fail git write-tree ' -test_expect_success POSIXPERM 'commit should notice unwritable repository' ' - - ( - chmod a-w .git/objects .git/objects/?? && - test_must_fail git commit -m second - ) - status=$? - chmod 775 .git/objects .git/objects/?? - (exit $status) - +test_expect_success POSIXPERM,SANITY 'commit should notice unwritable repository' ' + test_when_finished "chmod 775 .git/objects .git/objects/??" && + chmod a-w .git/objects .git/objects/?? && + test_must_fail git commit -m second ' -test_expect_success POSIXPERM 'update-index should notice unwritable repository' ' - - ( - echo 6O >file && - chmod a-w .git/objects .git/objects/?? && - test_must_fail git update-index file - ) - status=$? - chmod 775 .git/objects .git/objects/?? - (exit $status) - +test_expect_success POSIXPERM,SANITY 'update-index should notice unwritable repository' ' + test_when_finished "chmod 775 .git/objects .git/objects/??" && + echo 6O >file && + chmod a-w .git/objects .git/objects/?? && + test_must_fail git update-index file ' -test_expect_success POSIXPERM 'add should notice unwritable repository' ' - - ( - echo b >file && - chmod a-w .git/objects .git/objects/?? && - test_must_fail git add file - ) - status=$? - chmod 775 .git/objects .git/objects/?? - (exit $status) - +test_expect_success POSIXPERM,SANITY 'add should notice unwritable repository' ' + test_when_finished "chmod 775 .git/objects .git/objects/??" && + echo b >file && + chmod a-w .git/objects .git/objects/?? && + test_must_fail git add file ' test_done diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh index 09f855af3e..93e58c00e8 100755 --- a/t/t0005-signals.sh +++ b/t/t0005-signals.sh @@ -13,6 +13,7 @@ test_expect_success 'sigchain works' ' test-sigchain >actual case "$?" in 143) true ;; # POSIX w/ SIGTERM=15 + 271) true ;; # ksh w/ SIGTERM=15 3) true ;; # Windows *) false ;; esac && diff --git a/t/t0006-date.sh b/t/t0006-date.sh index 75b02af86d..1d4d0a5c7d 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -28,8 +28,8 @@ check_show 31449600 '12 months ago' check_parse() { echo "$1 -> $2" >expect - test_expect_${3:-success} "parse date ($1)" " - test-date parse '$1' >actual && + test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" " + TZ=${3:-$TZ} test-date parse '$1' >actual && test_cmp expect actual " } @@ -38,6 +38,8 @@ check_parse 2008 bad check_parse 2008-02 bad check_parse 2008-02-14 bad check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000' +check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5 check_approxidate() { echo "$1 -> $2 +0000" >expect diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index c3e7e322a8..234a94f3e6 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -453,5 +453,57 @@ test_expect_success 'invalid .gitattributes (must not crash)' ' git diff ' +# Some more tests here to add new autocrlf functionality. +# We want to have a known state here, so start a bit from scratch + +test_expect_success 'setting up for new autocrlf tests' ' + git config core.autocrlf false && + git config core.safecrlf false && + rm -rf .????* * && + for w in I am all LF; do echo $w; done >alllf && + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && + for w in I am all CRLF; do echo $w; done | append_cr >allcrlf && + git add -A . && + git commit -m "alllf, allcrlf and mixed only" && + git tag -a -m "message" autocrlf-checkpoint +' + +test_expect_success 'report no change after setting autocrlf' ' + git config core.autocrlf true && + touch * && + git diff --exit-code +' + +test_expect_success 'files are clean after checkout' ' + rm * && + git checkout -f && + git diff --exit-code +' + +cr_to_Q_no_NL () { + tr '\015' Q | tr -d '\012' +} + +test_expect_success 'LF only file gets CRLF with autocrlf' ' + test "$(cr_to_Q_no_NL < alllf)" = "IQamQallQLFQ" +' + +test_expect_success 'Mixed file is still mixed with autocrlf' ' + test "$(cr_to_Q_no_NL < mixed)" = "OhhereisCRLFQintext" +' + +test_expect_success 'CRLF only file has CRLF with autocrlf' ' + test "$(cr_to_Q_no_NL < allcrlf)" = "IQamQallQCRLFQ" +' + +test_expect_success 'New CRLF file gets LF in repo' ' + tr -d "\015" < alllf | append_cr > alllf2 && + git add alllf2 && + git commit -m "alllf2 added" && + git config core.autocrlf false && + rm * && + git checkout -f && + test_cmp alllf alllf2 +' test_done diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 6cb8d60ea2..828e35baf7 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -65,17 +65,21 @@ test_expect_success expanded_in_repo ' echo "\$Id:NoSpaceAtFront \$" echo "\$Id:NoSpaceAtEitherEnd\$" echo "\$Id: NoTerminatingSymbol" + echo "\$Id: Foreign Commit With Spaces \$" + echo "\$Id: NoTerminatingSymbolAtEOF" } > expanded-keywords && { echo "File with expanded keywords" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" - echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" + echo "\$Id: fd0478f5f1486f3d5177d4c3f6eb2765e8fc56b9 \$" echo "\$Id: NoTerminatingSymbol" + echo "\$Id: Foreign Commit With Spaces \$" + echo "\$Id: NoTerminatingSymbolAtEOF" } > expected-output && git add expanded-keywords && diff --git a/t/t0025-crlf-auto.sh b/t/t0025-crlf-auto.sh new file mode 100755 index 0000000000..f5f67a6337 --- /dev/null +++ b/t/t0025-crlf-auto.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +test_description='CRLF conversion' + +. ./test-lib.sh + +has_cr() { + tr '\015' Q <"$1" | grep Q >/dev/null +} + +test_expect_success setup ' + + git config core.autocrlf false && + + for w in Hello world how are you; do echo $w; done >one && + for w in I am very very fine thank you; do echo ${w}Q; done | q_to_cr >two && + for w in Oh here is a QNUL byte how alarming; do echo ${w}; done | q_to_nul >three && + git add . && + + git commit -m initial && + + one=`git rev-parse HEAD:one` && + two=`git rev-parse HEAD:two` && + three=`git rev-parse HEAD:three` && + + echo happy. +' + +test_expect_success 'default settings cause no changes' ' + + rm -f .gitattributes tmp one two three && + git read-tree --reset -u HEAD && + + ! has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + threediff=`git diff three` && + test -z "$onediff" -a -z "$twodiff" -a -z "$threediff" +' + +test_expect_success 'crlf=true causes a CRLF file to be normalized' ' + + # Backwards compatibility check + rm -f .gitattributes tmp one two three && + echo "two crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + # Note, "normalized" means that git will normalize it if added + has_cr two && + twodiff=`git diff two` && + test -n "$twodiff" +' + +test_expect_success 'text=true causes a CRLF file to be normalized' ' + + rm -f .gitattributes tmp one two three && + echo "two text" > .gitattributes && + git read-tree --reset -u HEAD && + + # Note, "normalized" means that git will normalize it if added + has_cr two && + twodiff=`git diff two` && + test -n "$twodiff" +' + +test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=false' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf false && + echo "one eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=input' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf input && + echo "one eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_success 'eol=lf gives a normalized file LFs with autocrlf=true' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf true && + echo "one eol=lf" > .gitattributes && + git read-tree --reset -u HEAD && + + ! has_cr one && + onediff=`git diff one` && + test -z "$onediff" +' + +test_expect_success 'autocrlf=true does not normalize CRLF files' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf true && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + threediff=`git diff three` && + test -z "$onediff" -a -z "$twodiff" -a -z "$threediff" +' + +test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf true && + echo "* text=auto" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + threediff=`git diff three` && + test -z "$onediff" -a -n "$twodiff" -a -z "$threediff" +' + +test_expect_success 'text=auto, autocrlf=true does not normalize binary files' ' + + rm -f .gitattributes tmp one two three && + git config core.autocrlf true && + echo "* text=auto" > .gitattributes && + git read-tree --reset -u HEAD && + + ! has_cr three && + threediff=`git diff three` && + test -z "$threediff" +' + +test_expect_success 'eol=crlf _does_ normalize binary files' ' + + rm -f .gitattributes tmp one two three && + echo "three eol=crlf" > .gitattributes && + git read-tree --reset -u HEAD && + + has_cr three && + threediff=`git diff three` && + test -z "$threediff" +' + +test_done diff --git a/t/t0026-eol-config.sh b/t/t0026-eol-config.sh new file mode 100755 index 0000000000..f37ac8fa0b --- /dev/null +++ b/t/t0026-eol-config.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +test_description='CRLF conversion' + +. ./test-lib.sh + +has_cr() { + tr '\015' Q <"$1" | grep Q >/dev/null +} + +test_expect_success setup ' + + git config core.autocrlf false && + + echo "one text" > .gitattributes + + for w in Hello world how are you; do echo $w; done >one && + for w in I am very very fine thank you; do echo $w; done >two && + git add . && + + git commit -m initial && + + one=`git rev-parse HEAD:one` && + two=`git rev-parse HEAD:two` && + + echo happy. +' + +test_expect_success 'eol=lf puts LFs in normalized file' ' + + rm -f .gitattributes tmp one two && + git config core.eol lf && + git read-tree --reset -u HEAD && + + ! has_cr one && + ! has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_expect_success 'eol=crlf puts CRLFs in normalized file' ' + + rm -f .gitattributes tmp one two && + git config core.eol crlf && + git read-tree --reset -u HEAD && + + has_cr one && + ! has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_expect_success 'autocrlf=true overrides eol=lf' ' + + rm -f .gitattributes tmp one two && + git config core.eol lf && + git config core.autocrlf true && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_expect_success 'autocrlf=true overrides unset eol' ' + + rm -f .gitattributes tmp one two && + git config --unset-all core.eol && + git config core.autocrlf true && + git read-tree --reset -u HEAD && + + has_cr one && + has_cr two && + onediff=`git diff one` && + twodiff=`git diff two` && + test -z "$onediff" -a -z "$twodiff" +' + +test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 3d450ed379..20924506af 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -7,7 +7,7 @@ test_description='our own option parser' . ./test-lib.sh -cat > expect.err << EOF +cat > expect << EOF usage: test-parse-options <options> -b, --boolean get a boolean @@ -46,10 +46,12 @@ EOF test_expect_success 'test help' ' test_must_fail test-parse-options -h > output 2> output.err && - test ! -s output && - test_cmp expect.err output.err + test ! -s output.err && + test_cmp expect output ' +mv expect expect.err + cat > expect << EOF boolean: 2 integer: 1729 diff --git a/t/t0080-vcs-svn.sh b/t/t0080-vcs-svn.sh new file mode 100755 index 0000000000..d3225ada68 --- /dev/null +++ b/t/t0080-vcs-svn.sh @@ -0,0 +1,171 @@ +#!/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 'line buffer' ' + echo HELLO >expected1 && + printf "%s\n" "" HELLO >expected2 && + echo >expected3 && + printf "%s\n" "" Q | q_to_nul >expected4 && + printf "%s\n" foo "" >expected5 && + printf "%s\n" "" foo >expected6 && + + test-line-buffer <<-\EOF >actual1 && + 5 + HELLO + EOF + + test-line-buffer <<-\EOF >actual2 && + 0 + + 5 + HELLO + EOF + + q_to_nul <<-\EOF | + 1 + Q + EOF + test-line-buffer >actual3 && + + q_to_nul <<-\EOF | + 0 + + 1 + Q + EOF + test-line-buffer >actual4 && + + test-line-buffer <<-\EOF >actual5 && + 5 + foo + EOF + + test-line-buffer <<-\EOF >actual6 && + 0 + + 5 + foo + EOF + + test_cmp expected1 actual1 && + test_cmp expected2 actual2 && + test_cmp expected3 actual3 && + test_cmp expected4 actual4 && + test_cmp expected5 actual5 && + test_cmp expected6 actual6 +' + +test_expect_success 'string pool' ' + echo a does not equal b >expected.differ && + echo a equals a >expected.match && + 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/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 6327d205cb..93ca84f9e6 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -359,7 +359,7 @@ test_expect_success \ test_expect_success \ 'a/b (untracked) vs a, plus c/d case test.' \ - '! git read-tree -u -m "$treeH" "$treeM" && + 'test_must_fail git read-tree -u -m "$treeH" "$treeM" && git ls-files --stage && test -f a/b' @@ -390,4 +390,20 @@ test_expect_success \ git ls-files --stage | tee >treeMcheck.out && test_cmp treeM.out treeMcheck.out' +test_expect_success '-m references the correct modified tree' ' + echo >file-a && + echo >file-b && + git add file-a file-b && + git commit -a -m "test for correct modified tree" + git branch initial-mod && + echo b >file-b && + git commit -a -m "B" && + echo a >file-a && + git add file-a && + git ls-tree $(git write-tree) file-a >expect && + git read-tree -m HEAD initial-mod && + git ls-tree $(git write-tree) file-a >actual && + test_cmp expect actual +' + test_done diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index f19b4a2a4a..eb8e3d4476 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -177,7 +177,7 @@ test_expect_success SYMLINKS 'funny symlink in work tree' ' ' -test_expect_success SYMLINKS 'funny symlink in work tree, un-unlink-able' ' +test_expect_success SYMLINKS,SANITY 'funny symlink in work tree, un-unlink-able' ' rm -fr a b && git reset --hard && diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 62246dbf95..9a07de1a5b 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -1,16 +1,30 @@ #!/bin/sh -test_description='sparse checkout tests' +test_description='sparse checkout tests + +* (tag: removed, master) removed +| D sub/added +* (HEAD, tag: top) modified and added +| M init.t +| A sub/added +* (tag: init) init + A init.t +' . ./test-lib.sh -cat >expected <<EOF -100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added -EOF test_expect_success 'setup' ' + cat >expected <<-\EOF && + 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t + 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added + EOF + cat >expected.swt <<-\EOF && + H init.t + H sub/added + EOF + test_commit init && - echo modified >> init.t && + echo modified >>init.t && mkdir sub && touch sub/added && git add init.t sub/added && @@ -20,26 +34,22 @@ test_expect_success 'setup' ' git commit -m removed && git tag removed && git checkout top && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result ' -cat >expected.swt <<EOF -H init.t -H sub/added -EOF test_expect_success 'read-tree without .git/info/sparse-checkout' ' git read-tree -m -u HEAD && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result ' test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' - echo > .git/info/sparse-checkout + echo >.git/info/sparse-checkout git read-tree -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added @@ -47,9 +57,9 @@ test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' ' git config core.sparsecheckout true && - echo > .git/info/sparse-checkout && + echo >.git/info/sparse-checkout && git read-tree --no-sparse-checkout -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added @@ -57,94 +67,113 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse- test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' git config core.sparsecheckout true && - echo > .git/info/sparse-checkout && + echo >.git/info/sparse-checkout && test_must_fail git read-tree -m -u HEAD && - git ls-files --stage > result && + git ls-files --stage >result && test_cmp expected result && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -S init.t -H sub/added -EOF test_expect_success 'match directories with trailing slash' ' + cat >expected.swt-noinit <<-\EOF && + S init.t + H sub/added + EOF + echo sub/ > .git/info/sparse-checkout && git read-tree -m -u HEAD && git ls-files -t > result && - test_cmp expected.swt result && + test_cmp expected.swt-noinit result && test ! -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -H init.t -H sub/added -EOF test_expect_failure 'match directories without trailing slash' ' - echo init.t > .git/info/sparse-checkout && - echo sub >> .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && + echo sub >>.git/info/sparse-checkout && git read-tree -m -u HEAD && - git ls-files -t > result && + git ls-files -t >result && test_cmp expected.swt result && test ! -f init.t && test -f sub/added ' -cat >expected.swt <<EOF -H init.t -S sub/added -EOF test_expect_success 'checkout area changes' ' - echo init.t > .git/info/sparse-checkout && + cat >expected.swt-nosub <<-\EOF && + H init.t + S sub/added + EOF + + echo init.t >.git/info/sparse-checkout && git read-tree -m -u HEAD && - git ls-files -t > result && - test_cmp expected.swt result && + git ls-files -t >result && + test_cmp expected.swt-nosub result && test -f init.t && test ! -f sub/added ' test_expect_success 'read-tree updates worktree, absent case' ' - echo sub/added > .git/info/sparse-checkout && + echo sub/added >.git/info/sparse-checkout && git checkout -f top && git read-tree -m -u HEAD^ && test ! -f init.t ' test_expect_success 'read-tree updates worktree, dirty case' ' - echo sub/added > .git/info/sparse-checkout && + echo sub/added >.git/info/sparse-checkout && git checkout -f top && - echo dirty > init.t && + echo dirty >init.t && git read-tree -m -u HEAD^ && grep -q dirty init.t && rm init.t ' test_expect_success 'read-tree removes worktree, dirty case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f top && - echo dirty > added && + echo dirty >added && git read-tree -m -u HEAD^ && grep -q dirty added ' test_expect_success 'read-tree adds to worktree, absent case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f removed && git read-tree -u -m HEAD^ && test ! -f sub/added ' test_expect_success 'read-tree adds to worktree, dirty case' ' - echo init.t > .git/info/sparse-checkout && + echo init.t >.git/info/sparse-checkout && git checkout -f removed && mkdir sub && - echo dirty > sub/added && + echo dirty >sub/added && git read-tree -u -m HEAD^ && grep -q dirty sub/added ' +test_expect_success 'index removal and worktree narrowing at the same time' ' + >empty && + echo init.t >.git/info/sparse-checkout && + echo sub/added >>.git/info/sparse-checkout && + git checkout -f top && + echo init.t >.git/info/sparse-checkout && + git checkout removed && + git ls-files sub/added >result && + test ! -f sub/added && + test_cmp empty result +' + +test_expect_success 'read-tree --reset removes outside worktree' ' + >empty && + echo init.t >.git/info/sparse-checkout && + git checkout -f top && + git reset --hard removed && + git ls-files sub/added >result && + test_cmp empty result +' + test_done diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 210e594f6f..a3ac33801a 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -16,123 +16,133 @@ test_expect_success setup ' cp one original.one && cp dir/two original.two ' -HERE=`pwd` LF=' ' test_expect_success 'update-index and ls-files' ' - cd "$HERE" && git update-index --add one && case "`git ls-files`" in - one) echo ok one ;; + one) echo pass one ;; *) echo bad one; exit 1 ;; esac && - cd dir && - git update-index --add two && + ( + cd dir && + git update-index --add two && + case "`git ls-files`" in + two) echo pass two ;; + *) echo bad two; exit 1 ;; + esac + ) && case "`git ls-files`" in - two) echo ok two ;; - *) echo bad two; exit 1 ;; - esac && - cd .. && - case "`git ls-files`" in - dir/two"$LF"one) echo ok both ;; + dir/two"$LF"one) echo pass both ;; *) echo bad; exit 1 ;; esac ' test_expect_success 'cat-file' ' - cd "$HERE" && two=`git ls-files -s dir/two` && two=`expr "$two" : "[0-7]* \\([0-9a-f]*\\)"` && echo "$two" && git cat-file -p "$two" >actual && cmp dir/two actual && - cd dir && - git cat-file -p "$two" >actual && - cmp two actual + ( + cd dir && + git cat-file -p "$two" >actual && + cmp two actual + ) ' rm -f actual dir/actual test_expect_success 'diff-files' ' - cd "$HERE" && echo a >>one && echo d >>dir/two && case "`git diff-files --name-only`" in - dir/two"$LF"one) echo ok top ;; + dir/two"$LF"one) echo pass top ;; *) echo bad top; exit 1 ;; esac && # diff should not omit leading paths - cd dir && - case "`git diff-files --name-only`" in - dir/two"$LF"one) echo ok subdir ;; - *) echo bad subdir; exit 1 ;; - esac && - case "`git diff-files --name-only .`" in - dir/two) echo ok subdir limited ;; - *) echo bad subdir limited; exit 1 ;; - esac + ( + cd dir && + case "`git diff-files --name-only`" in + dir/two"$LF"one) echo pass subdir ;; + *) echo bad subdir; exit 1 ;; + esac && + case "`git diff-files --name-only .`" in + dir/two) echo pass subdir limited ;; + *) echo bad subdir limited; exit 1 ;; + esac + ) ' test_expect_success 'write-tree' ' - cd "$HERE" && top=`git write-tree` && echo $top && - cd dir && - sub=`git write-tree` && - echo $sub && - test "z$top" = "z$sub" + ( + cd dir && + sub=`git write-tree` && + echo $sub && + test "z$top" = "z$sub" + ) ' test_expect_success 'checkout-index' ' - cd "$HERE" && git checkout-index -f -u one && cmp one original.one && - cd dir && - git checkout-index -f -u two && - cmp two ../original.two + ( + cd dir && + git checkout-index -f -u two && + cmp two ../original.two + ) ' test_expect_success 'read-tree' ' - cd "$HERE" && rm -f one dir/two && tree=`git write-tree` && git read-tree --reset -u "$tree" && cmp one original.one && cmp dir/two original.two && - cd dir && - rm -f two && - git read-tree --reset -u "$tree" && - cmp two ../original.two && - cmp ../one ../original.one + ( + cd dir && + rm -f two && + git read-tree --reset -u "$tree" && + cmp two ../original.two && + cmp ../one ../original.one + ) ' test_expect_success 'no file/rev ambiguity check inside .git' ' - cd "$HERE" && git commit -a -m 1 && - cd "$HERE"/.git && - git show -s HEAD + ( + cd .git && + git show -s HEAD + ) ' test_expect_success 'no file/rev ambiguity check inside a bare repo' ' - cd "$HERE" && git clone -s --bare .git foo.git && - cd foo.git && GIT_DIR=. git show -s HEAD + ( + cd foo.git && + GIT_DIR=. git show -s HEAD + ) ' # This still does not work as it should... : test_expect_success 'no file/rev ambiguity check inside a bare repo' ' - cd "$HERE" && git clone -s --bare .git foo.git && - cd foo.git && git show -s HEAD + ( + cd foo.git && + git show -s HEAD + ) ' test_expect_success SYMLINKS 'detection should not be fooled by a symlink' ' - cd "$HERE" && rm -fr foo.git && git clone -s .git another && ln -s another yetanother && - cd yetanother/.git && - git show -s HEAD + ( + cd yetanother/.git && + git show -s HEAD + ) ' test_done diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index f11f98c3ce..d0ab8ffe1b 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -701,25 +701,47 @@ cat >expect <<\EOF trailingtilde = foo~ EOF -test_expect_success 'set --path' ' +test_expect_success NOT_MINGW 'set --path' ' git config --path path.home "~/" && git config --path path.normal "/dev/null" && git config --path path.trailingtilde "foo~" && test_cmp expect .git/config' +if test_have_prereq NOT_MINGW && test "${HOME+set}" +then + test_set_prereq HOMEVAR +fi + cat >expect <<EOF $HOME/ /dev/null foo~ EOF -test_expect_success 'get --path' ' +test_expect_success HOMEVAR 'get --path' ' git config --get --path path.home > result && git config --get --path path.normal >> result && git config --get --path path.trailingtilde >> result && test_cmp expect result ' +cat >expect <<\EOF +/dev/null +foo~ +EOF + +test_expect_success NOT_MINGW 'get --path copes with unset $HOME' ' + ( + unset HOME; + test_must_fail git config --get --path path.home \ + >result 2>msg && + git config --get --path path.normal >>result && + git config --get --path path.trailingtilde >>result + ) && + grep "[Ff]ailed to expand.*~/" msg && + test_cmp expect result +' + rm .git/config git config quote.leading " test" @@ -824,4 +846,12 @@ test_expect_success 'check split_cmdline return' " test_must_fail git merge master " +test_expect_success 'git -c "key=value" support' ' + test "z$(git -c name=value config name)" = zvalue && + test "z$(git -c core.name=value config core.name)" = zvalue && + test "z$(git -c CamelCase=value config camelcase)" = zvalue && + test "z$(git -c flag config --bool flag)" = ztrue && + test_must_fail git -c core.name=value config name +' + test_done diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 8d305b4372..a6bf1bf4d6 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -7,41 +7,64 @@ test_description='Test repository version check' . ./test-lib.sh -cat >test.patch <<EOF -diff --git a/test.txt b/test.txt -new file mode 100644 ---- /dev/null -+++ b/test.txt -@@ -0,0 +1 @@ -+123 -EOF +test_expect_success 'setup' ' + cat >test.patch <<-\EOF && + diff --git a/test.txt b/test.txt + new file mode 100644 + --- /dev/null + +++ b/test.txt + @@ -0,0 +1 @@ + +123 + EOF -test_create_repo "test" -test_create_repo "test2" - -GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99 || exit 1 + test_create_repo "test" && + test_create_repo "test2" && + GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99 +' test_expect_success 'gitdir selection on normal repos' ' - (test "$(git config core.repositoryformatversion)" = 0 && - cd test && - test "$(git config core.repositoryformatversion)" = 0)' + echo 0 >expect && + git config core.repositoryformatversion >actual && + ( + cd test && + git config core.repositoryformatversion >../actual2 + ) && + test_cmp expect actual && + test_cmp expect actual2 +' -# Make sure it would stop at test2, not trash test_expect_success 'gitdir selection on unsupported repo' ' - (cd test2 && - test "$(git config core.repositoryformatversion)" = 99)' + # Make sure it would stop at test2, not trash + echo 99 >expect && + ( + cd test2 && + git config core.repositoryformatversion >../actual + ) + test_cmp expect actual +' test_expect_success 'gitdir not required mode' ' - (git apply --stat test.patch && - cd test && git apply --stat ../test.patch && - cd ../test2 && git apply --stat ../test.patch)' - -test_expect_success 'gitdir required mode on normal repos' ' - (git apply --check --index test.patch && - cd test && git apply --check --index ../test.patch)' + git apply --stat test.patch && + ( + cd test && + git apply --stat ../test.patch + ) && + ( + cd test2 && + git apply --stat ../test.patch + ) +' -test_expect_success 'gitdir required mode on unsupported repo' ' - (cd test2 && test_must_fail git apply --check --index ../test.patch) +test_expect_success 'gitdir required mode' ' + git apply --check --index test.patch && + ( + cd test && + git apply --check --index ../test.patch + ) && + ( + cd test2 && + test_must_fail git apply --check --index ../test.patch + ) ' test_done diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh index 055ad00f77..b5d89a2250 100755 --- a/t/t1304-default-acl.sh +++ b/t/t1304-default-acl.sh @@ -15,9 +15,14 @@ umask 077 # is a good candidate: exists on all unices, and it has permission # anyway, so we don't create a security hole running the testsuite. -if ! setfacl -m u:root:rwx .; then - say "Skipping ACL tests: unable to use setfacl" - test_done +setfacl_out="$(setfacl -m u:root:rwx . 2>&1)" +setfacl_ret=$? + +if test $setfacl_ret != 0 +then + say "Unable to use setfacl (output: '$setfacl_out'; return code: '$setfacl_ret')" +else + test_set_prereq SETFACL fi check_perms_and_acl () { @@ -31,7 +36,7 @@ check_perms_and_acl () { dirs_to_set="./ .git/ .git/objects/ .git/objects/pack/" -test_expect_success 'Setup test repo' ' +test_expect_success SETFACL 'Setup test repo' ' setfacl -m d:u::rwx,d:g::---,d:o:---,d:m:rwx $dirs_to_set && setfacl -m m:rwx $dirs_to_set && setfacl -m u:root:rwx $dirs_to_set && @@ -43,12 +48,12 @@ test_expect_success 'Setup test repo' ' git commit -m "init" ' -test_expect_success 'Objects creation does not break ACLs with restrictive umask' ' +test_expect_success SETFACL 'Objects creation does not break ACLs with restrictive umask' ' # SHA1 for empty blob check_perms_and_acl .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 ' -test_expect_success 'git gc does not break ACLs with restrictive umask' ' +test_expect_success SETFACL 'git gc does not break ACLs with restrictive umask' ' git gc && check_perms_and_acl .git/objects/pack/*.pack ' diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index eb45afb018..782e75d000 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -41,6 +41,23 @@ test_expect_success "check-ref-format --branch @{-1}" ' refname2=$(git check-ref-format --branch @{-2}) && test "$refname2" = master' +test_expect_success 'check-ref-format --branch from subdir' ' + mkdir subdir && + + T=$(git write-tree) && + sha1=$(echo A | git commit-tree $T) && + git update-ref refs/heads/master $sha1 && + git update-ref refs/remotes/origin/master $sha1 + git checkout master && + git checkout origin/master && + git checkout master && + refname=$( + cd subdir && + git check-ref-format --branch @{-1} + ) && + test "$refname" = "$sha1" +' + valid_ref_normalized() { test_expect_success "ref name '$1' simplifies to '$2'" " refname=\$(git check-ref-format --print '$1') && diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 49cae3ed52..1be415e334 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -1,19 +1,23 @@ #!/bin/sh -test_description='git fsck random collection of tests' +test_description='git fsck random collection of tests + +* (HEAD) B +* (master) A +' . ./test-lib.sh test_expect_success setup ' + git config gc.auto 0 && + git config i18n.commitencoding ISO-8859-1 && test_commit A fileA one && + git config --unset i18n.commitencoding && git checkout HEAD^0 && test_commit B fileB two && git tag -d A B && - git reflog expire --expire=now --all -' - -test_expect_success 'HEAD is part of refs' ' - test 0 = $(git fsck | wc -l) + git reflog expire --expire=now --all && + >empty ' test_expect_success 'loose objects borrowed from alternate are not missing' ' @@ -23,76 +27,132 @@ 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 && - ! grep "missing blob" out - ) + git fsck >../out 2>&1 + ) && + { + grep -v dangling out >actual || + : + } && + test_cmp empty actual +' + +test_expect_success 'HEAD is part of refs, valid objects appear valid' ' + git fsck >actual 2>&1 && + test_cmp empty actual ' # Corruption tests follow. Make sure to remove all traces of the # specific corruption you test afterwards, lest a later test trip over # it. +test_expect_success 'setup: helpers for corruption tests' ' + sha1_file() { + echo "$*" | sed "s#..#.git/objects/&/#" + } && + + remove_object() { + file=$(sha1_file "$*") && + test -e "$file" && + rm -f "$file" + } +' + test_expect_success 'object with bad sha1' ' sha=$(echo blob | git hash-object -w --stdin) && - echo $sha && 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 && - (git fsck 2>out; true) && - grep "$sha.*corrupt" out && - rm -f .git/objects/$new && - git update-ref -d refs/heads/bogus && - git read-tree -u --reset HEAD + test_when_finished "git update-ref -d refs/heads/bogus" && + + test_might_fail git fsck 2>out && + cat out && + grep "$sha.*corrupt" out ' test_expect_success 'branch pointing to non-commit' ' - git rev-parse HEAD^{tree} > .git/refs/heads/invalid && + git rev-parse HEAD^{tree} >.git/refs/heads/invalid && + test_when_finished "git update-ref -d refs/heads/invalid" && git fsck 2>out && - grep "not a commit" out && - git update-ref -d refs/heads/invalid + cat out && + grep "not a commit" out ' -cat > invalid-tag <<EOF -object ffffffffffffffffffffffffffffffffffffffff -type commit -tag invalid -tagger T A Gger <tagger@example.com> 1234567890 -0000 +test_expect_success 'email without @ is okay' ' + git cat-file commit HEAD >basis && + sed "s/@/AT/" basis >okay && + new=$(git hash-object -t commit -w --stdin <okay) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + ! grep "commit $new" out +' -This is an invalid tag. -EOF +test_expect_success 'email with embedded > is not okay' ' + git cat-file commit HEAD >basis && + sed "s/@[a-z]/&>/" basis >bad-email && + new=$(git hash-object -t commit -w --stdin <bad-email) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + grep "error in commit $new" out +' test_expect_success 'tag pointing to nonexistent' ' - tag=$(git hash-object -t tag -w --stdin < invalid-tag) && - echo $tag > .git/refs/tags/invalid && + cat >invalid-tag <<-\EOF + object ffffffffffffffffffffffffffffffffffffffff + type commit + tag invalid + tagger T A Gger <tagger@example.com> 1234567890 -0000 + + This is an invalid tag. + EOF + + tag=$(git hash-object -t tag -w --stdin <invalid-tag) && + test_when_finished "remove_object $tag" && + echo $tag >.git/refs/tags/invalid && + test_when_finished "git update-ref -d refs/tags/invalid" && test_must_fail git fsck --tags >out && cat out && - grep "broken link" out && - rm .git/refs/tags/invalid + grep "broken link" out ' -cat > wrong-tag <<EOF -object $(echo blob | git hash-object -w --stdin) -type commit -tag wrong -tagger T A Gger <tagger@example.com> 1234567890 -0000 - -This is an invalid tag. -EOF - test_expect_success 'tag pointing to something else than its type' ' - tag=$(git hash-object -t tag -w --stdin < wrong-tag) && - echo $tag > .git/refs/tags/wrong && + sha=$(echo blob | git hash-object -w --stdin) && + test_when_finished "remove_object $sha" && + cat >wrong-tag <<-EOF && + object $sha + type commit + tag wrong + tagger T A Gger <tagger@example.com> 1234567890 -0000 + + This is an invalid tag. + EOF + + tag=$(git hash-object -t tag -w --stdin <wrong-tag) && + test_when_finished "remove_object $tag" && + echo $tag >.git/refs/tags/wrong && + test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && cat out && - grep "error in tag.*broken links" out && - rm .git/refs/tags/wrong + grep "error in tag.*broken links" out ' - +test_expect_success 'cleaned up' ' + git fsck >actual 2>&1 && + test_cmp empty actual +' test_done diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index 9df301211c..2c8f01f668 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -3,175 +3,320 @@ test_description='test separate work tree' . ./test-lib.sh -test_rev_parse() { - name=$1 - shift - - test_expect_success "$name: is-bare-repository" \ - "test '$1' = \"\$(git rev-parse --is-bare-repository)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: is-inside-git-dir" \ - "test '$1' = \"\$(git rev-parse --is-inside-git-dir)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: is-inside-work-tree" \ - "test '$1' = \"\$(git rev-parse --is-inside-work-tree)\"" - shift - [ $# -eq 0 ] && return - - test_expect_success "$name: prefix" \ - "test '$1' = \"\$(git rev-parse --show-prefix)\"" - shift - [ $# -eq 0 ] && return -} - -EMPTY_TREE=$(git write-tree) -mkdir -p work/sub/dir || exit 1 -mv .git repo.git || exit 1 - -say "core.worktree = relative path" -GIT_DIR=repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -export GIT_DIR GIT_CONFIG -unset GIT_WORK_TREE -git config core.worktree ../work -test_rev_parse 'outside' false false false -cd work || exit 1 -GIT_DIR=../repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -GIT_DIR=../../../repo.git -GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -say "core.worktree = absolute path" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -git config core.worktree "$(pwd)/work" -test_rev_parse 'outside' false false false -cd work || exit 1 -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -say "GIT_WORK_TREE=relative path (override core.worktree)" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -git config core.worktree non-existent -GIT_WORK_TREE=work -export GIT_WORK_TREE -test_rev_parse 'outside' false false false -cd work || exit 1 -GIT_WORK_TREE=. -test_rev_parse 'inside' false false true '' -cd sub/dir || exit 1 -GIT_WORK_TREE=../.. -test_rev_parse 'subdirectory' false false true sub/dir/ -cd ../../.. || exit 1 - -mv work repo.git/work - -say "GIT_WORK_TREE=absolute path, work tree below git dir" -GIT_DIR=$(pwd)/repo.git -GIT_CONFIG=$GIT_DIR/config -GIT_WORK_TREE=$(pwd)/repo.git/work -test_rev_parse 'outside' false false false -cd repo.git || exit 1 -test_rev_parse 'in repo.git' false true false -cd objects || exit 1 -test_rev_parse 'in repo.git/objects' false true false -cd ../work || exit 1 -test_rev_parse 'in repo.git/work' false true true '' -cd sub/dir || exit 1 -test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/ -cd ../../../.. || exit 1 - -test_expect_success 'repo finds its work tree' ' - (cd repo.git && - : > work/sub/dir/untracked && - test sub/dir/untracked = "$(git ls-files --others)") -' - -test_expect_success 'repo finds its work tree from work tree, too' ' - (cd repo.git/work/sub/dir && - : > tracked && - git --git-dir=../../.. add tracked && - cd ../../.. && - test sub/dir/tracked = "$(git ls-files)") +test_expect_success 'setup' ' + EMPTY_TREE=$(git write-tree) && + EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) && + CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) && + ZEROES=0000000000000000000000000000000000000000 && + EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") && + CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") && + + mkdir -p work/sub/dir && + mkdir -p work2 && + mv .git repo.git +' + +test_expect_success 'setup: helper for testing rev-parse' ' + test_rev_parse() { + echo $1 >expected.bare && + echo $2 >expected.inside-git && + echo $3 >expected.inside-worktree && + if test $# -ge 4 + then + echo $4 >expected.prefix + fi && + + git rev-parse --is-bare-repository >actual.bare && + git rev-parse --is-inside-git-dir >actual.inside-git && + git rev-parse --is-inside-work-tree >actual.inside-worktree && + if test $# -ge 4 + then + git rev-parse --show-prefix >actual.prefix + fi && + + test_cmp expected.bare actual.bare && + test_cmp expected.inside-git actual.inside-git && + test_cmp expected.inside-worktree actual.inside-worktree && + if test $# -ge 4 + then + # rev-parse --show-prefix should output + # a single newline when at the top of the work tree, + # but we test for that separately. + test -z "$4" && ! test -s actual.prefix || + test_cmp expected.prefix actual.prefix + fi + } +' + +test_expect_success 'setup: core.worktree = relative path' ' + unset GIT_WORK_TREE; + GIT_DIR=repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + export GIT_DIR GIT_CONFIG && + git config core.worktree ../work +' + +test_expect_success 'outside' ' + test_rev_parse false false false +' + +test_expect_success 'inside work tree' ' + ( + cd work && + GIT_DIR=../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + test_rev_parse false false true "" + ) +' + +test_expect_failure 'empty prefix is actually written out' ' + echo >expected && + ( + cd work && + GIT_DIR=../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + git rev-parse --show-prefix >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + GIT_DIR=../../../repo.git && + GIT_CONFIG="$(pwd)"/$GIT_DIR/config && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: core.worktree = absolute path' ' + unset GIT_WORK_TREE; + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + export GIT_DIR GIT_CONFIG && + git config core.worktree "$(pwd)/work" +' + +test_expect_success 'outside' ' + test_rev_parse false false false && + ( + cd work2 && + test_rev_parse false false false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd work && + test_rev_parse false false true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' ' + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + git config core.worktree non-existent && + GIT_WORK_TREE=work && + export GIT_DIR GIT_CONFIG GIT_WORK_TREE +' + +test_expect_success 'outside' ' + test_rev_parse false false false && + ( + cd work2 && + test_rev_parse false false false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd work && + GIT_WORK_TREE=. && + test_rev_parse false false true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd work/sub/dir && + GIT_WORK_TREE=../.. && + test_rev_parse false false true sub/dir/ + ) +' + +test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' ' + mv work repo.git/work && + mv work2 repo.git/work2 && + GIT_DIR=$(pwd)/repo.git && + GIT_CONFIG=$GIT_DIR/config && + GIT_WORK_TREE=$(pwd)/repo.git/work && + export GIT_DIR GIT_CONFIG GIT_WORK_TREE +' + +test_expect_success 'outside' ' + echo outside && + test_rev_parse false false false +' + +test_expect_success 'in repo.git' ' + ( + cd repo.git && + test_rev_parse false true false + ) && + ( + cd repo.git/objects && + test_rev_parse false true false + ) && + ( + cd repo.git/work2 && + test_rev_parse false true false + ) +' + +test_expect_success 'inside work tree' ' + ( + cd repo.git/work && + test_rev_parse false true true "" + ) +' + +test_expect_success 'subdir of work tree' ' + ( + cd repo.git/work/sub/dir && + test_rev_parse false true true sub/dir/ + ) +' + +test_expect_success 'find work tree from repo' ' + echo sub/dir/untracked >expected && + cat <<-\EOF >repo.git/work/.gitignore && + expected.* + actual.* + .gitignore + EOF + >repo.git/work/sub/dir/untracked && + ( + cd repo.git && + git ls-files --others --exclude-standard >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'find work tree from work tree' ' + echo sub/dir/tracked >expected && + >repo.git/work/sub/dir/tracked && + ( + cd repo.git/work/sub/dir && + git --git-dir=../../.. add tracked + ) && + ( + cd repo.git && + git ls-files >../actual + ) && + test_cmp expected actual ' test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' ' - (cd repo.git/work/sub/dir && - GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \ + ( + cd repo.git/work/sub/dir && + GIT_DIR=../../.. && + GIT_WORK_TREE=../.. && + GIT_PAGER= && + export GIT_DIR GIT_WORK_TREE GIT_PAGER && + git diff --exit-code tracked && - echo changed > tracked && - ! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \ - git diff --exit-code tracked) -' -cat > diff-index-cached.expected <<\EOF -:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A sub/dir/tracked -EOF -cat > diff-index.expected <<\EOF -:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A sub/dir/tracked -EOF - - -test_expect_success 'git diff-index' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result && - test_cmp diff-index.expected result && - GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result && - test_cmp diff-index-cached.expected result -' -cat >diff-files.expected <<\EOF -:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M sub/dir/tracked -EOF - -test_expect_success 'git diff-files' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result && - test_cmp diff-files.expected result -' - -cat >diff-TREE.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -new file mode 100644 -index 0000000..5ea2ed4 ---- /dev/null -+++ b/sub/dir/tracked -@@ -0,0 +1 @@ -+changed -EOF -cat >diff-TREE-cached.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -new file mode 100644 -index 0000000..e69de29 -EOF -cat >diff-FILES.expected <<\EOF -diff --git a/sub/dir/tracked b/sub/dir/tracked -index e69de29..5ea2ed4 100644 ---- a/sub/dir/tracked -+++ b/sub/dir/tracked -@@ -0,0 +1 @@ -+changed -EOF - -test_expect_success 'git diff' ' - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result && - test_cmp diff-TREE.expected result && - GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result && - test_cmp diff-TREE-cached.expected result && - GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result && - test_cmp diff-FILES.expected result + echo changed >tracked && + test_must_fail git diff --exit-code tracked + ) +' + +test_expect_success 'diff-index respects work tree under .git dir' ' + cat >diff-index-cached.expected <<-EOF && + :000000 100644 $ZEROES $EMPTY_BLOB A sub/dir/tracked + EOF + cat >diff-index.expected <<-EOF && + :000000 100644 $ZEROES $ZEROES A sub/dir/tracked + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff-index $EMPTY_TREE >diff-index.actual && + git diff-index --cached $EMPTY_TREE >diff-index-cached.actual + ) && + test_cmp diff-index.expected diff-index.actual && + test_cmp diff-index-cached.expected diff-index-cached.actual +' + +test_expect_success 'diff-files respects work tree under .git dir' ' + cat >diff-files.expected <<-EOF && + :100644 100644 $EMPTY_BLOB $ZEROES M sub/dir/tracked + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff-files >diff-files.actual + ) && + test_cmp diff-files.expected diff-files.actual +' + +test_expect_success 'git diff respects work tree under .git dir' ' + cat >diff-TREE.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + new file mode 100644 + index 0000000..$CHANGED_BLOB7 + --- /dev/null + +++ b/sub/dir/tracked + @@ -0,0 +1 @@ + +changed + EOF + cat >diff-TREE-cached.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + new file mode 100644 + index 0000000..$EMPTY_BLOB7 + EOF + cat >diff-FILES.expected <<-EOF && + diff --git a/sub/dir/tracked b/sub/dir/tracked + index $EMPTY_BLOB7..$CHANGED_BLOB7 100644 + --- a/sub/dir/tracked + +++ b/sub/dir/tracked + @@ -0,0 +1 @@ + +changed + EOF + + ( + GIT_DIR=repo.git && + GIT_WORK_TREE=repo.git/work && + export GIT_DIR GIT_WORK_TREE && + git diff $EMPTY_TREE >diff-TREE.actual && + git diff --cached $EMPTY_TREE >diff-TREE-cached.actual && + git diff >diff-FILES.actual + ) && + test_cmp diff-TREE.expected diff-TREE.actual && + test_cmp diff-TREE-cached.expected diff-TREE-cached.actual && + test_cmp diff-FILES.expected diff-FILES.actual ' test_expect_success 'git grep' ' - (cd repo.git/work/sub && - GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked) + echo dir/tracked >expected.grep && + ( + cd repo.git/work/sub && + GIT_DIR=../.. && + GIT_WORK_TREE=.. && + export GIT_DIR GIT_WORK_TREE && + git grep -l changed >../../../actual.grep + ) && + test_cmp expected.grep actual.grep ' test_expect_success 'git commit' ' @@ -183,14 +328,14 @@ test_expect_success 'git commit' ' test_expect_success 'absolute pathspec should fail gracefully' ' ( - cd repo.git || exit 1 - git config --unset core.worktree + cd repo.git && + test_might_fail git config --unset core.worktree && test_must_fail git log HEAD -- /home ) ' test_expect_success 'make_relative_path handles double slashes in GIT_DIR' ' - : > dummy_file + >dummy_file echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file && git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file ' diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index e504058062..b3195c4707 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -3,7 +3,8 @@ test_description='test git rev-parse --parseopt' . ./test-lib.sh -cat > expect.err <<EOF +cat > expect <<\END_EXPECT +cat <<\EOF usage: some-command [options] <args>... some-command does foo and bar! @@ -19,6 +20,7 @@ Extras --extra1 line above used to cause a segfault but no longer does EOF +END_EXPECT cat > optionspec << EOF some-command [options] <args>... @@ -38,8 +40,8 @@ extra1 line above used to cause a segfault but no longer does EOF test_expect_success 'test --parseopt help output' ' - git rev-parse --parseopt -- -h 2> output.err < optionspec - test_cmp expect.err output.err + git rev-parse --parseopt -- -h > output < optionspec + test_cmp expect output ' cat > expect <<EOF @@ -79,4 +81,22 @@ test_expect_success 'test --parseopt --keep-dashdash' ' test_cmp expect output ' +cat >expect <<EOF +set -- --foo -- '--' 'arg' '--spam=ham' +EOF + +test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option with --' ' + git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo -- arg --spam=ham <optionspec >output && + test_cmp expect output +' + +cat > expect <<EOF +set -- --foo -- 'arg' '--spam=ham' +EOF + +test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option without --' ' + git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo arg --spam=ham <optionspec >output && + test_cmp expect output +' + test_done diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh index cc65394947..813cc1b3e2 100755 --- a/t/t1503-rev-parse-verify.sh +++ b/t/t1503-rev-parse-verify.sh @@ -104,4 +104,15 @@ test_expect_success 'use --default' ' test_must_fail git rev-parse --verify --default bar ' +test_expect_success 'master@{n} for various n' ' + N=$(git reflog | wc -l) && + Nm1=$(($N-1)) && + Np1=$(($N+1)) && + git rev-parse --verify master@{0} && + git rev-parse --verify master@{1} && + git rev-parse --verify master@{$Nm1} && + test_must_fail git rev-parse --verify master@{$N} && + test_must_fail git rev-parse --verify master@{$Np1} +' + test_done diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index af721f9719..0eeeb0e450 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -66,4 +66,13 @@ test_expect_success 'incorrect file in :path and :N:path' ' grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error ' +test_expect_success 'invalid @{n} reference' ' + test_must_fail git rev-parse master@{99999} >output 2>error && + test -z "$(cat output)" && + grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error && + test_must_fail git rev-parse --verify master@{99999} >output 2>error && + test -z "$(cat output)" && + grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error +' + test_done diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh index 5322a3bf97..335420fd87 100755 --- a/t/t1509-root-worktree.sh +++ b/t/t1509-root-worktree.sh @@ -99,17 +99,17 @@ test_foobar_foobar() { } if ! test_have_prereq POSIXPERM || ! [ -w / ]; then - say "Dangerous test skipped. Read this test if you want to execute it" + skip_all="Dangerous test skipped. Read this test if you want to execute it" test_done fi if [ "$IKNOWWHATIAMDOING" != "YES" ]; then - say "You must set env var IKNOWWHATIAMDOING=YES in order to run this test" + skip_all="You must set env var IKNOWWHATIAMDOING=YES in order to run this test" test_done fi if [ "$UID" = 0 ]; then - say "No you can't run this with root" + skip_all="No you can't run this with root" test_done fi @@ -134,8 +134,8 @@ cat >ls.expected <<EOF 100644 $ONE_SHA1 0 me EOF -export GIT_DIR="$TRASH_DIRECTORY/.git" -export GIT_WORK_TREE=/ +GIT_DIR="$TRASH_DIRECTORY/.git" && export GIT_DIR +GIT_WORK_TREE=/ && export GIT_WORK_TREE test_vars 'abs gitdir, root' "$GIT_DIR" "/" "" test_foobar_root @@ -154,24 +154,24 @@ say "GIT_DIR relative, GIT_WORK_TREE set" test_expect_success 'go to /' 'cd /' -export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git" -export GIT_WORK_TREE=/ +GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git" && export GIT_DIR +GIT_WORK_TREE=/ && export GIT_WORK_TREE test_vars 'rel gitdir, root' "$GIT_DIR" "/" "" test_foobar_root test_expect_success 'go to /foo' 'cd /foo' -export GIT_DIR="../$TRASH_DIRECTORY/.git" -export GIT_WORK_TREE=/ +GIT_DIR="../$TRASH_DIRECTORY/.git" && export GIT_DIR +GIT_WORK_TREE=/ && export GIT_WORK_TREE test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/" test_foobar_foo test_expect_success 'go to /foo/bar' 'cd /foo/bar' -export GIT_DIR="../../$TRASH_DIRECTORY/.git" -export GIT_WORK_TREE=/ +GIT_DIR="../../$TRASH_DIRECTORY/.git" && export GIT_DIR +GIT_WORK_TREE=/ && export GIT_WORK_TREE test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/" test_foobar_foobar @@ -180,24 +180,24 @@ say "GIT_DIR relative, GIT_WORK_TREE relative" test_expect_success 'go to /' 'cd /' -export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git" -export GIT_WORK_TREE=. +GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git" && export GIT_DIR +GIT_WORK_TREE=. && export GIT_WORK_TREE test_vars 'rel gitdir, root' "$GIT_DIR" "/" "" test_foobar_root test_expect_success 'go to /' 'cd /foo' -export GIT_DIR="../$TRASH_DIRECTORY/.git" -export GIT_WORK_TREE=.. +GIT_DIR="../$TRASH_DIRECTORY/.git" && export GIT_DIR +GIT_WORK_TREE=.. && export GIT_WORK_TREE test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/" test_foobar_foo test_expect_success 'go to /foo/bar' 'cd /foo/bar' -export GIT_DIR="../../$TRASH_DIRECTORY/.git" -export GIT_WORK_TREE=../.. +GIT_DIR="../../$TRASH_DIRECTORY/.git" && export GIT_DIR +GIT_WORK_TREE=../.. && export GIT_WORK_TREE test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/" test_foobar_foobar diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh index 20f33436d0..a74ee227b8 100755 --- a/t/t2007-checkout-symlink.sh +++ b/t/t2007-checkout-symlink.sh @@ -6,13 +6,7 @@ test_description='git checkout to switch between branches with symlink<->dir' . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say "symbolic links not supported - skipping tests" - test_done -fi - -test_expect_success setup ' +test_expect_success SYMLINKS setup ' mkdir frotz && echo hello >frotz/filfre && @@ -38,16 +32,18 @@ test_expect_success setup ' ' -test_expect_success 'switch from symlink to dir' ' +test_expect_success SYMLINKS 'switch from symlink to dir' ' git checkout master ' -rm -fr frotz xyzzy nitfol && -git checkout -f master || exit +test_expect_success SYMLINKS 'Remove temporary directories & switch to master' ' + rm -fr frotz xyzzy nitfol && + git checkout -f master +' -test_expect_success 'switch from dir to symlink' ' +test_expect_success SYMLINKS 'switch from dir to symlink' ' git checkout side diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index fda3f0af7e..70edbb33e2 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -39,4 +39,27 @@ test_expect_success '"checkout <submodule>" updates the index only' ' git diff-files --quiet ' +test_expect_success '"checkout <submodule>" honors diff.ignoreSubmodules' ' + git config diff.ignoreSubmodules dirty && + echo x> submodule/untracked && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + +test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .gitmodules' ' + git config diff.ignoreSubmodules none && + git config -f .gitmodules submodule.submodule.path submodule && + git config -f .gitmodules submodule.submodule.ignore untracked && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + +test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/config' ' + git config -f .gitmodules submodule.submodule.ignore none && + git config submodule.submodule.path submodule && + git config submodule.submodule.ignore all && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + test_done diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh index 2144184d79..a463b13b27 100755 --- a/t/t2016-checkout-patch.sh +++ b/t/t2016-checkout-patch.sh @@ -4,7 +4,7 @@ test_description='git checkout --patch' . ./lib-patch-mode.sh -test_expect_success 'setup' ' +test_expect_success PERL 'setup' ' mkdir dir && echo parent > dir/foo && echo dummy > bar && @@ -18,55 +18,55 @@ test_expect_success 'setup' ' # note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' -test_expect_success 'saying "n" does nothing' ' +test_expect_success PERL 'saying "n" does nothing' ' set_and_save_state dir/foo work head && (echo n; echo n) | git checkout -p && verify_saved_state bar && verify_saved_state dir/foo ' -test_expect_success 'git checkout -p' ' +test_expect_success PERL 'git checkout -p' ' (echo n; echo y) | git checkout -p && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success 'git checkout -p with staged changes' ' +test_expect_success PERL 'git checkout -p with staged changes' ' set_state dir/foo work index (echo n; echo y) | git checkout -p && verify_saved_state bar && verify_state dir/foo index index ' -test_expect_success 'git checkout -p HEAD with NO staged changes: abort' ' +test_expect_success PERL 'git checkout -p HEAD with NO staged changes: abort' ' set_and_save_state dir/foo work head && (echo n; echo y; echo n) | git checkout -p HEAD && verify_saved_state bar && verify_saved_state dir/foo ' -test_expect_success 'git checkout -p HEAD with NO staged changes: apply' ' +test_expect_success PERL 'git checkout -p HEAD with NO staged changes: apply' ' (echo n; echo y; echo y) | git checkout -p HEAD && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success 'git checkout -p HEAD with change already staged' ' - set_state dir/foo index index +test_expect_success PERL 'git checkout -p HEAD with change already staged' ' + set_state dir/foo index index && # the third n is to get out in case it mistakenly does not apply (echo n; echo y; echo n) | git checkout -p HEAD && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success 'git checkout -p HEAD^' ' +test_expect_success PERL 'git checkout -p HEAD^' ' # the third n is to get out in case it mistakenly does not apply (echo n; echo y; echo n) | git checkout -p HEAD^ && verify_saved_state bar && verify_state dir/foo parent parent ' -test_expect_success 'git checkout -p handles deletion' ' +test_expect_success PERL 'git checkout -p handles deletion' ' set_state dir/foo work index && rm dir/foo && (echo n; echo y) | git checkout -p && @@ -79,28 +79,28 @@ test_expect_success 'git checkout -p handles deletion' ' # dir/foo. There's always an extra 'n' to reject edits to dir/foo in # the failure case (and thus get out of the loop). -test_expect_success 'path limiting works: dir' ' +test_expect_success PERL 'path limiting works: dir' ' set_state dir/foo work head && (echo y; echo n) | git checkout -p dir && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success 'path limiting works: -- dir' ' +test_expect_success PERL 'path limiting works: -- dir' ' set_state dir/foo work head && (echo y; echo n) | git checkout -p -- dir && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success 'path limiting works: HEAD^ -- dir' ' +test_expect_success PERL 'path limiting works: HEAD^ -- dir' ' # the third n is to get out in case it mistakenly does not apply (echo y; echo n; echo n) | git checkout -p HEAD^ -- dir && verify_saved_state bar && verify_state dir/foo parent parent ' -test_expect_success 'path limiting works: foo inside dir' ' +test_expect_success PERL 'path limiting works: foo inside dir' ' set_state dir/foo work head && # the third n is to get out in case it mistakenly does not apply (echo y; echo n; echo n) | (cd dir && git checkout -p foo) && @@ -108,7 +108,7 @@ test_expect_success 'path limiting works: foo inside dir' ' verify_state dir/foo head head ' -test_expect_success 'none of this moved HEAD' ' +test_expect_success PERL 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t2017-checkout-orphan.sh b/t/t2017-checkout-orphan.sh new file mode 100755 index 0000000000..2d2f63f22e --- /dev/null +++ b/t/t2017-checkout-orphan.sh @@ -0,0 +1,119 @@ +#!/bin/sh +# +# Copyright (c) 2010 Erick Mattos +# + +test_description='git checkout --orphan + +Main Tests for --orphan functionality.' + +. ./test-lib.sh + +TEST_FILE=foo + +test_expect_success 'Setup' ' + echo "Initial" >"$TEST_FILE" && + git add "$TEST_FILE" && + git commit -m "First Commit" + test_tick && + echo "State 1" >>"$TEST_FILE" && + git add "$TEST_FILE" && + test_tick && + git commit -m "Second Commit" +' + +test_expect_success '--orphan creates a new orphan branch from HEAD' ' + git checkout --orphan alpha && + test_must_fail git rev-parse --verify HEAD && + test "refs/heads/alpha" = "$(git symbolic-ref HEAD)" && + test_tick && + git commit -m "Third Commit" && + test_must_fail git rev-parse --verify HEAD^ && + git diff-tree --quiet master alpha +' + +test_expect_success '--orphan creates a new orphan branch from <start_point>' ' + git checkout master && + git checkout --orphan beta master^ && + test_must_fail git rev-parse --verify HEAD && + test "refs/heads/beta" = "$(git symbolic-ref HEAD)" && + test_tick && + git commit -m "Fourth Commit" && + test_must_fail git rev-parse --verify HEAD^ && + git diff-tree --quiet master^ beta +' + +test_expect_success '--orphan must be rejected with -b' ' + git checkout master && + test_must_fail git checkout --orphan new -b newer && + test refs/heads/master = "$(git symbolic-ref HEAD)" +' + +test_expect_success '--orphan must be rejected with -t' ' + git checkout master && + test_must_fail git checkout --orphan new -t master && + test refs/heads/master = "$(git symbolic-ref HEAD)" +' + +test_expect_success '--orphan ignores branch.autosetupmerge' ' + git checkout master && + git config branch.autosetupmerge always && + git checkout --orphan gamma && + test -z "$(git config branch.gamma.merge)" && + test refs/heads/gamma = "$(git symbolic-ref HEAD)" && + test_must_fail git rev-parse --verify HEAD^ +' + +test_expect_success '--orphan makes reflog by default' ' + git checkout master && + git config --unset core.logAllRefUpdates && + git checkout --orphan delta && + test_must_fail git rev-parse --verify delta@{0} && + git commit -m Delta && + git rev-parse --verify delta@{0} +' + +test_expect_success '--orphan does not make reflog when core.logAllRefUpdates = false' ' + git checkout master && + git config core.logAllRefUpdates false && + git checkout --orphan epsilon && + test_must_fail git rev-parse --verify epsilon@{0} && + git commit -m Epsilon && + test_must_fail git rev-parse --verify epsilon@{0} +' + +test_expect_success '--orphan with -l makes reflog when core.logAllRefUpdates = false' ' + git checkout master && + git checkout -l --orphan zeta && + test_must_fail git rev-parse --verify zeta@{0} && + git commit -m Zeta && + git rev-parse --verify zeta@{0} +' + +test_expect_success 'giving up --orphan not committed when -l and core.logAllRefUpdates = false deletes reflog' ' + git checkout master && + git checkout -l --orphan eta && + test_must_fail git rev-parse --verify eta@{0} && + git checkout master && + test_must_fail git rev-parse --verify eta@{0} +' + +test_expect_success '--orphan is rejected with an existing name' ' + git checkout master && + test_must_fail git checkout --orphan master && + test refs/heads/master = "$(git symbolic-ref HEAD)" +' + +test_expect_success '--orphan refuses to switch if a merge is needed' ' + git checkout master && + git reset --hard && + echo local >>"$TEST_FILE" && + cat "$TEST_FILE" >"$TEST_FILE.saved" && + test_must_fail git checkout --orphan new master^ && + test refs/heads/master = "$(git symbolic-ref HEAD)" && + test_cmp "$TEST_FILE" "$TEST_FILE.saved" && + git diff-index --quiet --cached HEAD && + git reset --hard +' + +test_done diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh new file mode 100755 index 0000000000..fa69016381 --- /dev/null +++ b/t/t2018-checkout-branch.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +test_description='checkout ' + +. ./test-lib.sh + +# Arguments: <branch> <sha> [<checkout options>] +# +# Runs "git checkout" to switch to <branch>, testing that +# +# 1) we are on the specified branch, <branch>; +# 2) HEAD is <sha>; if <sha> is not specified, the old HEAD is used. +# +# If <checkout options> is not specified, "git checkout" is run with -b. +do_checkout() { + exp_branch=$1 && + exp_ref="refs/heads/$exp_branch" && + + # if <sha> is not specified, use HEAD. + exp_sha=${2:-$(git rev-parse --verify HEAD)} && + + # default options for git checkout: -b + if [ -z "$3" ]; then + opts="-b" + else + opts="$3" + fi + + git checkout $opts $exp_branch $exp_sha && + + test $exp_ref = $(git rev-parse --symbolic-full-name HEAD) && + test $exp_sha = $(git rev-parse --verify HEAD) +} + +test_dirty_unmergeable() { + ! git diff --exit-code >/dev/null +} + +setup_dirty_unmergeable() { + echo >>file1 change2 +} + +test_dirty_mergeable() { + ! git diff --cached --exit-code >/dev/null +} + +setup_dirty_mergeable() { + echo >file2 file2 && + git add file2 +} + +test_expect_success 'setup' ' + test_commit initial file1 && + HEAD1=$(git rev-parse --verify HEAD) && + + test_commit change1 file1 && + HEAD2=$(git rev-parse --verify HEAD) && + + git branch -m branch1 +' + +test_expect_success 'checkout -b to a new branch, set to HEAD' ' + do_checkout branch2 +' + +test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' + git checkout branch1 && + git branch -D branch2 && + + do_checkout branch2 $HEAD1 +' + +test_expect_success 'checkout -b to a new branch with unmergeable changes fails' ' + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_unmergeable && + test_must_fail do_checkout branch2 $HEAD1 && + test_dirty_unmergeable +' + +test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' ' + # still dirty and on branch1 + do_checkout branch2 $HEAD1 "-f -b" && + test_must_fail test_dirty_unmergeable +' + +test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 && + test_dirty_mergeable +' + +test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' ' + # clean up from previous test + git reset --hard && + + git checkout branch1 && + + # clean up from previous test + git branch -D branch2 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 "-f -b" && + test_must_fail test_dirty_mergeable +' + +test_expect_success 'checkout -b to an existing branch fails' ' + git reset --hard HEAD && + + test_must_fail do_checkout branch2 $HEAD2 +' + +test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' + git checkout branch1 && + + do_checkout branch2 "" -B +' + +test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' ' + git checkout $(git rev-parse --verify HEAD) && + + do_checkout branch2 "" -B +' + +test_expect_success 'checkout -B to an existing branch with an explicit ref resets branch to that ref' ' + git checkout branch1 && + + do_checkout branch2 $HEAD1 -B +' + +test_expect_success 'checkout -B to an existing branch with unmergeable changes fails' ' + git checkout branch1 && + + setup_dirty_unmergeable && + test_must_fail do_checkout branch2 $HEAD1 -B && + test_dirty_unmergeable +' + +test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' ' + # still dirty and on branch1 + do_checkout branch2 $HEAD1 "-f -B" && + test_must_fail test_dirty_unmergeable +' + +test_expect_success 'checkout -B to an existing branch preserves mergeable changes' ' + git checkout branch1 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 -B && + test_dirty_mergeable +' + +test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' ' + # clean up from previous test + git reset --hard && + + git checkout branch1 && + + setup_dirty_mergeable && + do_checkout branch2 $HEAD1 "-f -B" && + test_must_fail test_dirty_mergeable +' + +test_done diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh index 648184fd98..76ad7c344c 100755 --- a/t/t2101-update-index-reupdate.sh +++ b/t/t2101-update-index-reupdate.sh @@ -63,10 +63,10 @@ cat > expected <<\EOF EOF test_expect_success 'update-index --update from subdir' \ 'echo not so happy >file2 && - cd dir1 && + (cd dir1 && cat ../file2 >file3 && - git update-index --again && - cd .. && + git update-index --again + ) && git ls-files -s >current && cmp current expected' diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh index 1ed44ee503..4d0d0a3515 100755 --- a/t/t2102-update-index-symlinks.sh +++ b/t/t2102-update-index-symlinks.sh @@ -24,7 +24,7 @@ git update-index symlink' test_expect_success \ 'the index entry must still be a symbolic link' ' case "`git ls-files --stage --cached symlink`" in -120000" "*symlink) echo ok;; +120000" "*symlink) echo pass;; *) echo fail; git ls-files --stage --cached symlink; (exit 1);; esac' diff --git a/t/t2105-update-index-gitfile.sh b/t/t2105-update-index-gitfile.sh index 641607d89a..a7f3d47aec 100755 --- a/t/t2105-update-index-gitfile.sh +++ b/t/t2105-update-index-gitfile.sh @@ -13,7 +13,7 @@ test_expect_success 'submodule with absolute .git file' ' (cd sub1 && git init && REAL="$(pwd)/.real" && - mv .git "$REAL" + mv .git "$REAL" && echo "gitdir: $REAL" >.git && test_commit first) ' diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh new file mode 100755 index 0000000000..99d858c6b7 --- /dev/null +++ b/t/t2106-update-index-assume-unchanged.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +test_description='git update-index --assume-unchanged test. +' + +. ./test-lib.sh + +test_expect_success 'setup' \ + ': >file && + git add file && + git commit -m initial && + git branch other && + echo upstream >file && + git add file && + git commit -m upstream' + +test_expect_success 'do not switch branches with dirty file' \ + 'git reset --hard && + git checkout other && + echo dirt >file && + git update-index --assume-unchanged file && + test_must_fail git checkout master' + +test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 86291e8399..2eec0118c4 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -17,57 +17,52 @@ filesystem. ' . ./test-lib.sh -date >path0 -if test_have_prereq SYMLINKS -then - ln -s xyzzy path1 -else - date > path1 -fi -mkdir path2 path3 path4 -date >path2/file2 -date >path2-junk -date >path3/file3 -date >path3-junk -git update-index --add path3-junk path3/file3 - -cat >expected1 <<EOF -expected1 -expected2 -expected3 -output -path0 -path1 -path2-junk -path2/file2 -EOF -sed -e 's|path2/file2|path2/|' <expected1 >expected2 -cat <expected2 >expected3 -echo path4/ >>expected2 - -test_expect_success \ - 'git ls-files --others to show output.' \ - 'git ls-files --others >output' - -test_expect_success \ - 'git ls-files --others should pick up symlinks.' \ - 'test_cmp expected1 output' +test_expect_success 'setup ' ' + date >path0 && + if test_have_prereq SYMLINKS + then + ln -s xyzzy path1 + else + date >path1 + fi && + mkdir path2 path3 path4 && + date >path2/file2 && + date >path2-junk && + date >path3/file3 && + date >path3-junk && + git update-index --add path3-junk path3/file3 +' -test_expect_success \ - 'git ls-files --others --directory to show output.' \ - 'git ls-files --others --directory >output' +test_expect_success 'setup: expected output' ' + cat >expected1 <<-\EOF && + expected1 + expected2 + expected3 + output + path0 + path1 + path2-junk + path2/file2 + EOF + sed -e "s|path2/file2|path2/|" <expected1 >expected2 && + cp expected2 expected3 && + echo path4/ >>expected2 +' -test_expect_success \ - 'git ls-files --others --directory should not get confused.' \ - 'test_cmp expected2 output' +test_expect_success 'ls-files --others' ' + git ls-files --others >output && + test_cmp expected1 output +' -test_expect_success \ - 'git ls-files --others --directory --no-empty-directory to show output.' \ - 'git ls-files --others --directory --no-empty-directory >output' +test_expect_success 'ls-files --others --directory' ' + git ls-files --others --directory >output && + test_cmp expected2 output +' -test_expect_success \ - '--no-empty-directory hides empty directory' \ - 'test_cmp expected3 output' +test_expect_success '--no-empty-directory hides empty directory' ' + git ls-files --others --directory --no-empty-directory >output && + test_cmp expected3 output +' test_done diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh index a7d8187169..ca01053bcc 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -26,4 +26,3 @@ test_expect_success \ 'git ls-files --error-unmatch foo bar' test_done -1 diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 9929f82021..e66e550b24 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -22,6 +22,9 @@ test_expect_success 'setup 1' ' git branch df-2 && git branch df-3 && git branch remove && + git branch submod && + git branch copy && + git branch rename && echo hello >>a && cp a d/e && @@ -236,6 +239,33 @@ test_expect_success 'setup 6' ' test_cmp expected actual ' +test_expect_success 'setup 7' ' + + git checkout submod && + git rm d/e && + test_tick && + git commit -m "remove d/e" && + git update-index --add --cacheinfo 160000 $c1 d && + test_tick && + git commit -m "make d/ a submodule" +' + +test_expect_success 'setup 8' ' + git checkout rename && + git mv a e && + git add e && + test_tick && + git commit -m "rename a->e" +' + +test_expect_success 'setup 9' ' + git checkout copy && + cp a e && + git add e && + test_tick && + git commit -m "copy a->e" +' + test_expect_success 'merge-recursive simple' ' rm -fr [abcd] && @@ -282,7 +312,7 @@ test_expect_success 'fail if the index has unresolved entries' ' grep "You have not concluded your merge" out && rm -f .git/MERGE_HEAD && test_must_fail git merge "$c5" 2> out && - grep "Your local changes to .* would be overwritten by merge." out + grep "Your local changes to the following files would be overwritten by merge:" out ' test_expect_success 'merge-recursive remove conflict' ' @@ -551,4 +581,38 @@ test_expect_success 'merge removes empty directories' ' test_must_fail test -d d ' +test_expect_failure 'merge-recursive simple w/submodule' ' + + git checkout submod && + git merge remove +' + +test_expect_failure 'merge-recursive simple w/submodule result' ' + + git ls-files -s >actual && + ( + echo "100644 $o5 0 a" + echo "100644 $o0 0 c" + echo "160000 $c1 0 d" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'merge-recursive copy vs. rename' ' + git checkout -f copy && + git merge rename && + ( git ls-tree -r HEAD && git ls-files -s ) >actual && + ( + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 blob $o0 e" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + echo "100644 $o0 0 e" + ) >expected && + test_cmp expected actual +' + test_done diff --git a/t/t3032-merge-recursive-options.sh b/t/t3032-merge-recursive-options.sh new file mode 100755 index 0000000000..2293797553 --- /dev/null +++ b/t/t3032-merge-recursive-options.sh @@ -0,0 +1,186 @@ +#!/bin/sh + +test_description='merge-recursive options + +* [master] Clarify + ! [remote] Remove cruft +-- + + [remote] Remove cruft +* [master] Clarify +*+ [remote^] Initial revision +* ok 1: setup +' + +. ./test-lib.sh + +test_expect_success 'setup' ' + conflict_hunks () { + sed -n -e " + /^<<<</ b inconflict + b + : inconflict + p + /^>>>>/ b + n + b inconflict + " "$@" + } && + + cat <<-\EOF >text.txt && + Hope, he says, cherishes the soul of him who lives in + justice and holiness and is the nurse of his age and the + companion of his journey;--hope which is mightiest to sway + the restless soul of man. + + How admirable are his words! And the great blessing of riches, I do + not say to every man, but to a good man, is, that he has had no + occasion to deceive or to defraud others, either intentionally or + unintentionally; and when he departs to the world below he is not in + any apprehension about offerings due to the gods or debts which he owes + to men. Now to this peace of mind the possession of wealth greatly + contributes; and therefore I say, that, setting one thing against + another, of the many advantages which wealth has to give, to a man of + sense this is in my opinion the greatest. + + Well said, Cephalus, I replied; but as concerning justice, what is + it?--to speak the truth and to pay your debts--no more than this? And + even to this are there not exceptions? Suppose that a friend when in + his right mind has deposited arms with me and he asks for them when he + is not in his right mind, ought I to give them back to him? No one + would say that I ought or that I should be right in doing so, any more + than they would say that I ought always to speak the truth to one who + is in his condition. + + You are quite right, he replied. + + But then, I said, speaking the truth and paying your debts is not a + correct definition of justice. + + CEPHALUS - SOCRATES - POLEMARCHUS + + Quite correct, Socrates, if Simonides is to be believed, said + Polemarchus interposing. + + I fear, said Cephalus, that I must go now, for I have to look after the + sacrifices, and I hand over the argument to Polemarchus and the company. + EOF + git add text.txt && + test_tick && + git commit -m "Initial revision" && + + git checkout -b remote && + sed -e " + s/\. /\. /g + s/[?] /? /g + s/ / /g + s/--/---/g + s/but as concerning/but as con cerning/ + /CEPHALUS - SOCRATES - POLEMARCHUS/ d + " text.txt >text.txt+ && + mv text.txt+ text.txt && + git commit -a -m "Remove cruft" && + + git checkout master && + sed -e " + s/\(not in his right mind\),\(.*\)/\1;\2Q/ + s/Quite correct\(.*\)/It is too correct\1Q/ + s/unintentionally/un intentionally/ + /un intentionally/ s/$/Q/ + s/Polemarchus interposing./Polemarchus, interposing.Q/ + /justice and holiness/ s/$/Q/ + /pay your debts/ s/$/Q/ + " text.txt | q_to_cr >text.txt+ && + mv text.txt+ text.txt && + git commit -a -m "Clarify" && + git show-branch --all +' + +test_expect_success 'naive merge fails' ' + git read-tree --reset -u HEAD && + test_must_fail git merge-recursive HEAD^ -- HEAD remote && + test_must_fail git update-index --refresh && + grep "<<<<<<" text.txt +' + +test_expect_success '--ignore-space-change makes merge succeed' ' + git read-tree --reset -u HEAD && + git merge-recursive --ignore-space-change HEAD^ -- HEAD remote +' + +test_expect_success '--ignore-space-change: our w/s-only change wins' ' + q_to_cr <<-\EOF >expected && + justice and holiness and is the nurse of his age and theQ + EOF + + git read-tree --reset -u HEAD && + git merge-recursive --ignore-space-change HEAD^ -- HEAD remote && + grep "justice and holiness" text.txt >actual && + test_cmp expected actual +' + +test_expect_success '--ignore-space-change: their real change wins over w/s' ' + cat <<-\EOF >expected && + it?---to speak the truth and to pay your debts---no more than this? And + EOF + + git read-tree --reset -u HEAD && + git merge-recursive --ignore-space-change HEAD^ -- HEAD remote && + grep "pay your debts" text.txt >actual && + test_cmp expected actual +' + +test_expect_success '--ignore-space-change: does not ignore new spaces' ' + cat <<-\EOF >expected1 && + Well said, Cephalus, I replied; but as con cerning justice, what is + EOF + q_to_cr <<-\EOF >expected2 && + un intentionally; and when he departs to the world below he is not inQ + EOF + + git read-tree --reset -u HEAD && + git merge-recursive --ignore-space-change HEAD^ -- HEAD remote && + grep "Well said" text.txt >actual1 && + grep "when he departs" text.txt >actual2 && + test_cmp expected1 actual1 && + test_cmp expected2 actual2 +' + +test_expect_success '--ignore-all-space drops their new spaces' ' + cat <<-\EOF >expected && + Well said, Cephalus, I replied; but as concerning justice, what is + EOF + + git read-tree --reset -u HEAD && + git merge-recursive --ignore-all-space HEAD^ -- HEAD remote && + grep "Well said" text.txt >actual && + test_cmp expected actual +' + +test_expect_success '--ignore-all-space keeps our new spaces' ' + q_to_cr <<-\EOF >expected && + un intentionally; and when he departs to the world below he is not inQ + EOF + + git read-tree --reset -u HEAD && + git merge-recursive --ignore-all-space HEAD^ -- HEAD remote && + grep "when he departs" text.txt >actual && + test_cmp expected actual +' + +test_expect_success '--ignore-space-at-eol' ' + q_to_cr <<-\EOF >expected && + <<<<<<< HEAD + is not in his right mind; ought I to give them back to him? No oneQ + ======= + is not in his right mind, ought I to give them back to him? No one + >>>>>>> remote + EOF + + git read-tree --reset -u HEAD && + test_must_fail git merge-recursive --ignore-space-at-eol \ + HEAD^ -- HEAD remote && + conflict_hunks text.txt >actual && + test_cmp expected actual +' + +test_done diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh index 3ce501bb97..61c1f53d1b 100755 --- a/t/t3060-ls-files-with-tree.sh +++ b/t/t3060-ls-files-with-tree.sh @@ -53,17 +53,15 @@ test_expect_success setup ' git add . ' -# We have to run from a sub-directory to trigger prune_path -# Then we finally get to run our --with-tree test -cd sub - test_expect_success 'git -ls-files --with-tree should succeed from subdir' ' - - git ls-files --with-tree=HEAD~1 >../output - + # We have to run from a sub-directory to trigger prune_path + # Then we finally get to run our --with-tree test + ( + cd sub && + git ls-files --with-tree=HEAD~1 >../output + ) ' -cd .. test_expect_success \ 'git -ls-files --with-tree should add entries from named tree.' \ 'test_cmp expected output' diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index eee0d344d2..81d90b66c5 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -165,4 +165,13 @@ test_expect_success \ EOF test_output' +test_expect_success \ + 'ls-tree with one path a prefix of the other' \ + 'git ls-tree $tree path2/baz path2/bazbo >current && + make_expected <<\EOF && +040000 tree X path2/baz +120000 blob X path2/bazbo +EOF + test_output' + test_done diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 06654c6f82..026f9f89d9 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -21,33 +21,32 @@ entries. Also test odd filename and missing entries handling. ' . ./test-lib.sh -test_expect_success \ - 'setup' \ - 'echo 111 >1.txt && - echo 222 >2.txt && - mkdir path0 path0/a path0/a/b path0/a/b/c && - echo 111 >path0/a/b/c/1.txt && - mkdir path1 path1/b path1/b/c && - echo 111 >path1/b/c/1.txt && - mkdir path2 && - echo 111 >path2/1.txt && - mkdir path3 && - echo 111 >path3/1.txt && - echo 222 >path3/2.txt && - find *.txt path* \( -type f -o -type l \) -print | - xargs git update-index --add && - tree=`git write-tree` && - echo $tree' +test_expect_success 'setup' ' + echo 111 >1.txt && + echo 222 >2.txt && + mkdir path0 path0/a path0/a/b path0/a/b/c && + echo 111 >path0/a/b/c/1.txt && + mkdir path1 path1/b path1/b/c && + echo 111 >path1/b/c/1.txt && + mkdir path2 && + echo 111 >path2/1.txt && + mkdir path3 && + echo 111 >path3/1.txt && + echo 222 >path3/2.txt && + find *.txt path* \( -type f -o -type l \) -print | + xargs git update-index --add && + tree=`git write-tree` && + echo $tree +' test_output () { - sed -e "s/ $_x40 / X /" <current >check - test_cmp expected check + sed -e "s/ $_x40 / X /" <current >check && + test_cmp expected check } -test_expect_success \ - 'ls-tree plain' \ - 'git ls-tree $tree >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree plain' ' + git ls-tree $tree >current && + cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X 2.txt 040000 tree X path0 @@ -55,13 +54,13 @@ test_expect_success \ 040000 tree X path2 040000 tree X path3 EOF - test_output' + test_output +' # Recursive does not show tree nodes anymore... -test_expect_success \ - 'ls-tree recursive' \ - 'git ls-tree -r $tree >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree recursive' ' + git ls-tree -r $tree >current && + cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X 2.txt 100644 blob X path0/a/b/c/1.txt @@ -70,68 +69,71 @@ test_expect_success \ 100644 blob X path3/1.txt 100644 blob X path3/2.txt EOF - test_output' + test_output +' -test_expect_success \ - 'ls-tree filter 1.txt' \ - 'git ls-tree $tree 1.txt >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree filter 1.txt' ' + git ls-tree $tree 1.txt >current && + cat >expected <<\EOF && 100644 blob X 1.txt EOF - test_output' + test_output +' -test_expect_success \ - 'ls-tree filter path1/b/c/1.txt' \ - 'git ls-tree $tree path1/b/c/1.txt >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree filter path1/b/c/1.txt' ' + git ls-tree $tree path1/b/c/1.txt >current && + cat >expected <<\EOF && 100644 blob X path1/b/c/1.txt EOF - test_output' + test_output +' -test_expect_success \ - 'ls-tree filter all 1.txt files' \ - 'git ls-tree $tree 1.txt path0/a/b/c/1.txt path1/b/c/1.txt path2/1.txt path3/1.txt >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree filter all 1.txt files' ' + git ls-tree $tree 1.txt path0/a/b/c/1.txt \ + path1/b/c/1.txt path2/1.txt path3/1.txt >current && + cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X path0/a/b/c/1.txt 100644 blob X path1/b/c/1.txt 100644 blob X path2/1.txt 100644 blob X path3/1.txt EOF - test_output' + test_output +' # I am not so sure about this one after ls-tree doing pathspec match. # Having both path0/a and path0/a/b/c makes path0/a redundant, and # it behaves as if path0/a/b/c, path1/b/c, path2 and path3 are specified. -test_expect_success \ - 'ls-tree filter directories' \ - 'git ls-tree $tree path3 path2 path0/a/b/c path1/b/c path0/a >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree filter directories' ' + git ls-tree $tree path3 path2 path0/a/b/c path1/b/c path0/a >current && + cat >expected <<\EOF && 040000 tree X path0/a/b/c 040000 tree X path1/b/c 040000 tree X path2 040000 tree X path3 EOF - test_output' + test_output +' # Again, duplicates are filtered away so this is equivalent to # having 1.txt and path3 -test_expect_success \ - 'ls-tree filter odd names' \ - 'git ls-tree $tree 1.txt ./1.txt .//1.txt path3/1.txt path3/./1.txt path3 path3// >current && - cat >expected <<\EOF && +test_expect_success 'ls-tree filter odd names' ' + git ls-tree $tree 1.txt ./1.txt .//1.txt \ + path3/1.txt path3/./1.txt path3 path3// >current && + cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X path3/1.txt 100644 blob X path3/2.txt EOF - test_output' + test_output +' -test_expect_success \ - 'ls-tree filter missing files and extra slashes' \ - 'git ls-tree $tree 1.txt/ abc.txt path3//23.txt path3/2.txt/// >current && - cat >expected <<\EOF && -EOF - test_output' +test_expect_success 'ls-tree filter missing files and extra slashes' ' + git ls-tree $tree 1.txt/ abc.txt \ + path3//23.txt path3/2.txt/// >current && + >expected && + test_output +' test_expect_success 'ls-tree filter is leading path match' ' git ls-tree $tree pa path3/a >current && @@ -198,7 +200,7 @@ EOF ' test_expect_success 'ls-tree --name-only' ' - git ls-tree --name-only $tree >current + git ls-tree --name-only $tree >current && cat >expected <<\EOF && 1.txt 2.txt @@ -211,7 +213,7 @@ EOF ' test_expect_success 'ls-tree --name-only -r' ' - git ls-tree --name-only -r $tree >current + git ls-tree --name-only -r $tree >current && cat >expected <<\EOF && 1.txt 2.txt diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index e0b760513c..f54a533456 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -43,7 +43,7 @@ test_expect_success \ git branch -l d/e/f && test -f .git/refs/heads/d/e/f && test -f .git/logs/refs/heads/d/e/f && - diff expect .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' \ @@ -222,7 +222,28 @@ test_expect_success \ 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 && - diff expect .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' ' + git checkout master && + git config --unset core.logAllRefUpdates && + git checkout -b alpha && + git rev-parse --verify alpha@{0} +' + +test_expect_success 'checkout -b does not make reflog when core.logAllRefUpdates = false' ' + git checkout master && + git config core.logAllRefUpdates false && + git checkout -b beta && + test_must_fail git rev-parse --verify beta@{0} +' + +test_expect_success 'checkout -b with -l makes reflog when core.logAllRefUpdates = false' ' + git checkout master && + git checkout -lb gamma && + git config --unset core.logAllRefUpdates && + git rev-parse --verify gamma@{0} +' test_expect_success 'avoid ambiguous track' ' git config branch.autosetupmerge true && diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index 413019acaf..cd04361df8 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -28,7 +28,7 @@ test_expect_success \ SHA1=`cat .git/refs/heads/a` && echo "$SHA1 refs/heads/a" >expect && git show-ref a >result && - diff expect result' + test_cmp expect result' test_expect_success \ 'see if a branch still exists when packed' \ @@ -37,7 +37,7 @@ test_expect_success \ rm -f .git/refs/heads/b && echo "$SHA1 refs/heads/b" >expect && git show-ref b >result && - diff expect result' + test_cmp expect result' test_expect_success 'git branch c/d should barf if branch c exists' ' git branch c && @@ -52,7 +52,7 @@ test_expect_success \ git pack-refs --all --prune && echo "$SHA1 refs/heads/e" >expect && git show-ref e >result && - diff expect result' + test_cmp expect result' test_expect_success 'see if git pack-refs --prune remove ref files' ' git branch f && @@ -60,6 +60,12 @@ test_expect_success 'see if git pack-refs --prune remove ref files' ' ! test -f .git/refs/heads/f ' +test_expect_success 'see if git pack-refs --prune removes empty dirs' ' + git branch r/s/t && + git pack-refs --all --prune && + ! test -e .git/refs/heads/r +' + test_expect_success \ 'git branch g should work when git branch g/h has been deleted' \ 'git branch g/h && @@ -109,7 +115,7 @@ test_expect_success 'pack, prune and repack' ' git show-ref >all-of-them && git pack-refs && git show-ref >again && - diff all-of-them again + test_cmp all-of-them again ' test_done diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index db46d53e82..f39a261d80 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -24,19 +24,25 @@ EOF cat 2>/dev/null >"$p1" "$p0" echo 'Foo Bar Baz' >"$p2" -test -f "$p1" && cmp "$p0" "$p1" || { +if test -f "$p1" && cmp "$p0" "$p1" +then + test_set_prereq TABS_IN_FILENAMES +else # since FAT/NTFS does not allow tabs in filenames, skip this test - say 'Your filesystem does not allow tabs in filenames, test skipped.' - test_done -} + say 'Your filesystem does not allow tabs in filenames' +fi +test_expect_success TABS_IN_FILENAMES 'setup expect' " echo 'just space no-funny' >expected -test_expect_success 'git ls-files no-funny' \ +" + +test_expect_success TABS_IN_FILENAMES 'git ls-files no-funny' \ 'git update-index --add "$p0" "$p2" && git ls-files >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' t0=`git write-tree` echo "$t0" >t0 @@ -45,18 +51,24 @@ just space no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git ls-files with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git ls-files with-funny' \ 'git update-index --add "$p1" && git ls-files >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' " echo 'just space no-funny -tabs ," (dq) and spaces' >expected -test_expect_success 'git ls-files -z with-funny' \ +tabs ,\" (dq) and spaces' >expected +" + +test_expect_success TABS_IN_FILENAMES 'git ls-files -z with-funny' \ 'git ls-files -z | perl -pe y/\\000/\\012/ >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' t1=`git write-tree` echo "$t1" >t1 @@ -65,60 +77,78 @@ just space no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git ls-tree with funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git ls-tree with funny' \ 'git ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat > expected <<\EOF A "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git diff-index with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-index with-funny' \ 'git diff-index --name-status $t0 >current && test_cmp expected current' -test_expect_success 'git diff-tree with-funny' \ +test_expect_success TABS_IN_FILENAMES 'git diff-tree with-funny' \ 'git diff-tree --name-status $t0 $t1 >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' " echo 'A -tabs ," (dq) and spaces' >expected -test_expect_success 'git diff-index -z with-funny' \ +tabs ,\" (dq) and spaces' >expected +" + +test_expect_success TABS_IN_FILENAMES 'git diff-index -z with-funny' \ 'git diff-index -z --name-status $t0 | perl -pe y/\\000/\\012/ >current && test_cmp expected current' -test_expect_success 'git diff-tree -z with-funny' \ +test_expect_success TABS_IN_FILENAMES 'git diff-tree -z with-funny' \ 'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\000/\\012/ >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat > expected <<\EOF CNUM no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git diff-tree -C with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree -C with-funny' \ 'git diff-tree -C --find-copies-harder --name-status \ $t0 $t1 | sed -e 's/^C[0-9]*/CNUM/' >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat > expected <<\EOF RNUM no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git diff-tree delete with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ 'git update-index --force-remove "$p0" && git diff-index -M --name-status \ $t0 | sed -e 's/^R[0-9]*/RNUM/' >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat > expected <<\EOF diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" similarity index NUM% rename from no-funny rename to "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git diff-tree delete with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ 'git diff-index -M -p $t0 | sed -e "s/index [0-9]*%/index NUM%/" >current && test_cmp expected current' -chmod +x "$p1" +test_expect_success TABS_IN_FILENAMES 'setup expect' ' +chmod +x "$p1" && cat > expected <<\EOF diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" old mode 100644 @@ -127,31 +157,39 @@ similarity index NUM% rename from no-funny rename to "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git diff-tree delete with-funny' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny' \ 'git diff-index -M -p $t0 | sed -e "s/index [0-9]*%/index NUM%/" >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat >expected <<\EOF "tabs\t,\" (dq) and spaces" 1 files changed, 0 insertions(+), 0 deletions(-) EOF -test_expect_success 'git diff-tree rename with-funny applied' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree rename with-funny applied' \ 'git diff-index -M -p $t0 | git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && test_cmp expected current' +test_expect_success TABS_IN_FILENAMES 'setup expect' ' cat > expected <<\EOF no-funny "tabs\t,\" (dq) and spaces" 2 files changed, 3 insertions(+), 3 deletions(-) EOF -test_expect_success 'git diff-tree delete with-funny applied' \ +' + +test_expect_success TABS_IN_FILENAMES 'git diff-tree delete with-funny applied' \ 'git diff-index -p $t0 | git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && test_cmp expected current' -test_expect_success 'git apply non-git diff' \ +test_expect_success TABS_IN_FILENAMES 'git apply non-git diff' \ 'git diff-index -p $t0 | sed -ne "/^[-+@]/p" | git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 64f32ad94d..a2b79a0430 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -299,7 +299,7 @@ cat expect-F >> expect-rm-F test_expect_success 'verify note removal with -F /dev/null' ' git log -4 > output && test_cmp expect-rm-F output && - ! git notes show + test_must_fail git notes show ' test_expect_success 'do not create empty note with -m "" (setup)' ' @@ -309,7 +309,7 @@ test_expect_success 'do not create empty note with -m "" (setup)' ' test_expect_success 'verify non-creation of note with -m ""' ' git log -4 > output && test_cmp expect-rm-F output && - ! git notes show + test_must_fail git notes show ' cat > expect-combine_m_and_F << EOF @@ -357,7 +357,7 @@ cat expect-multiline >> expect-rm-remove test_expect_success 'verify note removal with "git notes remove"' ' git log -4 > output && test_cmp expect-rm-remove output && - ! git notes show HEAD^ + test_must_fail git notes show HEAD^ ' cat > expect << EOF @@ -365,6 +365,13 @@ c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd7 c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5 EOF +test_expect_success 'removing non-existing note should not create new commit' ' + git rev-parse --verify refs/notes/commits > before_commit && + test_must_fail git notes remove HEAD^ && + git rev-parse --verify refs/notes/commits > after_commit && + test_cmp before_commit after_commit +' + test_expect_success 'list notes with "git notes list"' ' git notes list > output && test_cmp expect output @@ -693,7 +700,11 @@ test_expect_success 'create note from non-existing note with "git notes add -c" git add a10 && test_tick && git commit -m 10th && - test_must_fail MSG="yet another note" git notes add -c deadbeef && + ( + MSG="yet another note" && + export MSG && + test_must_fail git notes add -c deadbeef + ) && test_must_fail git notes list HEAD ' @@ -1044,4 +1055,10 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' ' git log -1 > output && test_cmp expect output ' + +test_expect_success 'git notes copy diagnoses too many or too few parameters' ' + test_must_fail git notes copy && + test_must_fail git notes copy one two three +' + test_done diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh index ee84fc4884..e35d7811ac 100755 --- a/t/t3302-notes-index-expensive.sh +++ b/t/t3302-notes-index-expensive.sh @@ -7,11 +7,9 @@ test_description='Test commit notes index (expensive!)' . ./test-lib.sh -test -z "$GIT_NOTES_TIMING_TESTS" && { - say Skipping timing tests - test_done - exit -} +test_set_prereq NOT_EXPENSIVE +test -n "$GIT_NOTES_TIMING_TESTS" && test_set_prereq EXPENSIVE +test -x /usr/bin/time && test_set_prereq USR_BIN_TIME create_repo () { number_of_commits=$1 @@ -98,21 +96,31 @@ time_notes () { for mode in no-notes notes do echo $mode - /usr/bin/time sh ../time_notes $mode $1 + /usr/bin/time "$SHELL_PATH" ../time_notes $mode $1 done } -for count in 10 100 1000 10000; do +do_tests () { + pr=$1 + count=$2 + + test_expect_success $pr 'setup / mkdir' ' + mkdir $count && + cd $count + ' - mkdir $count - (cd $count; + test_expect_success $pr "setup $count" "create_repo $count" - test_expect_success "setup $count" "create_repo $count" + test_expect_success $pr 'notes work' "test_notes $count" - test_expect_success 'notes work' "test_notes $count" + test_expect_success USR_BIN_TIME,$pr 'notes timing with /usr/bin/time' "time_notes 100" + + test_expect_success $pr 'teardown / cd ..' 'cd ..' +} - test_expect_success 'notes timing' "time_notes 100" - ) +do_tests NOT_EXPENSIVE 10 +for count in 100 1000 10000; do + do_tests EXPENSIVE $count done test_done diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh index a0ed0353e6..c4282179b3 100755 --- a/t/t3306-notes-prune.sh +++ b/t/t3306-notes-prune.sh @@ -60,15 +60,15 @@ test_expect_success 'verify commits and notes' ' test_expect_success 'remove some commits' ' - git reset --hard HEAD~2 && + git reset --hard HEAD~1 && git reflog expire --expire=now HEAD && git gc --prune=now ' test_expect_success 'verify that commits are gone' ' - ! git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - ! git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 && + test_must_fail git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 && git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f ' @@ -79,6 +79,26 @@ test_expect_success 'verify that notes are still present' ' git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f ' +test_expect_success 'prune -n does not remove notes' ' + + git notes list > expect && + git notes prune -n && + git notes list > actual && + test_cmp expect actual +' + +cat > expect <<EOF +5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 +EOF + +test_expect_success 'prune -n lists prunable notes' ' + + + git notes prune -n > actual && + test_cmp expect actual +' + + test_expect_success 'prune notes' ' git notes prune @@ -86,8 +106,32 @@ test_expect_success 'prune notes' ' test_expect_success 'verify that notes are gone' ' - ! git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - ! git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && + test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && + git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f +' + +test_expect_success 'remove some commits' ' + + git reset --hard HEAD~1 && + git reflog expire --expire=now HEAD && + git gc --prune=now +' + +cat > expect <<EOF +08341ad9e94faa089d60fd3f523affb25c6da189 +EOF + +test_expect_success 'prune -v notes' ' + + git notes prune -v > actual && + test_cmp expect actual +' + +test_expect_success 'verify that notes are gone' ' + + test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + test_must_fail git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f ' diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh new file mode 100755 index 0000000000..3269f2eebd --- /dev/null +++ b/t/t3307-notes-man.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='Examples from the git-notes man page + +Make sure the manual is not full of lies.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit A && + test_commit B && + test_commit C +' + +test_expect_success 'example 1: notes to add an Acked-by line' ' + cat <<-\EOF >expect && + B + + Notes: + Acked-by: A C Ker <acker@example.com> + EOF + git notes add -m "Acked-by: A C Ker <acker@example.com>" B && + git show -s B^{commit} >log && + tail -n 4 log >actual && + test_cmp expect actual +' + +test_expect_success 'example 2: binary notes' ' + cp "$TEST_DIRECTORY"/test4012.png . + git checkout B && + blob=$(git hash-object -w test4012.png) && + git notes --ref=logo add -C "$blob" && + git notes --ref=logo copy B C && + git notes --ref=logo show C >actual && + test_cmp test4012.png actual +' + +test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index dbf7dfba9b..349eebd542 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -10,128 +10,169 @@ among other things. ' . ./test-lib.sh -GIT_AUTHOR_EMAIL=bogus_email_address -export GIT_AUTHOR_EMAIL - -test_expect_success \ - 'prepare repository with topic branches' \ - 'git config core.logAllRefUpdates true && - echo First > A && - git update-index --add A && - git commit -m "Add A." && - git checkout -b my-topic-branch && - echo Second > B && - git update-index --add B && - git commit -m "Add B." && - git checkout -f master && - echo Third >> A && - git update-index A && - git commit -m "Modify A." && - git checkout -b side my-topic-branch && - echo Side >> C && - git add C && - git commit -m "Add C" && - git checkout -b nonlinear my-topic-branch && - echo Edit >> B && - git add B && - git commit -m "Modify B" && - git merge side && - git checkout -b upstream-merged-nonlinear && - git merge master && - git checkout -f my-topic-branch && - git tag topic +GIT_AUTHOR_NAME=author@name +GIT_AUTHOR_EMAIL=bogus@email@address +export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL + +test_expect_success 'prepare repository with topic branches' ' + git config core.logAllRefUpdates true && + echo First >A && + git update-index --add A && + git commit -m "Add A." && + git checkout -b force-3way && + echo Dummy >Y && + git update-index --add Y && + git commit -m "Add Y." && + git checkout -b filemove && + git reset --soft master && + mkdir D && + git mv A D/A && + git commit -m "Move A." && + git checkout -b my-topic-branch master && + echo Second >B && + git update-index --add B && + git commit -m "Add B." && + git checkout -f master && + echo Third >>A && + git update-index A && + git commit -m "Modify A." && + git checkout -b side my-topic-branch && + echo Side >>C && + git add C && + git commit -m "Add C" && + git checkout -b nonlinear my-topic-branch && + echo Edit >>B && + git add B && + git commit -m "Modify B" && + git merge side && + git checkout -b upstream-merged-nonlinear && + git merge master && + git checkout -f my-topic-branch && + git tag topic ' test_expect_success 'rebase on dirty worktree' ' - echo dirty >> A && - test_must_fail git rebase master' + echo dirty >>A && + test_must_fail git rebase master +' test_expect_success 'rebase on dirty cache' ' - git add A && - test_must_fail git rebase master' + git add A && + test_must_fail git rebase master +' test_expect_success 'rebase against master' ' - git reset --hard HEAD && - git rebase master' + git reset --hard HEAD && + git rebase master +' test_expect_success 'rebase against master twice' ' - git rebase master >out && - grep "Current branch my-topic-branch is up to date" out + git rebase master >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase against master twice with --force' ' - git rebase --force-rebase master >out && - grep "Current branch my-topic-branch is up to date, rebase forced" out + git rebase --force-rebase master >out && + grep "Current branch my-topic-branch is up to date, rebase forced" out ' test_expect_success 'rebase against master twice from another branch' ' - git checkout my-topic-branch^ && - git rebase master my-topic-branch >out && - grep "Current branch my-topic-branch is up to date" out + git checkout my-topic-branch^ && + git rebase master my-topic-branch >out && + grep "Current branch my-topic-branch is up to date" out ' test_expect_success 'rebase fast-forward to master' ' - git checkout my-topic-branch^ && - git rebase my-topic-branch >out && - grep "Fast-forwarded HEAD to my-topic-branch" out + git checkout my-topic-branch^ && + git rebase my-topic-branch >out && + grep "Fast-forwarded HEAD to my-topic-branch" out ' -test_expect_success \ - 'the rebase operation should not have destroyed author information' \ - '! (git log | grep "Author:" | grep "<>")' +test_expect_success 'the rebase operation should not have destroyed author information' ' + ! (git log | grep "Author:" | grep "<>") +' + +test_expect_success 'the rebase operation should not have destroyed author information (2)' " + git log -1 | + grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>' +" test_expect_success 'HEAD was detached during rebase' ' - test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) + test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1}) ' test_expect_success 'rebase after merge master' ' - git reset --hard topic && - git merge master && - git rebase master && - ! (git show | grep "^Merge:") + git reset --hard topic && + git merge master && + git rebase master && + ! (git show | grep "^Merge:") ' test_expect_success 'rebase of history with merges is linearized' ' - git checkout nonlinear && - test 4 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) + git checkout nonlinear && + test 4 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' -test_expect_success \ - 'rebase of history with merges after upstream merge is linearized' ' - git checkout upstream-merged-nonlinear && - test 5 = $(git rev-list master.. | wc -l) && - git rebase master && - test 3 = $(git rev-list master.. | wc -l) +test_expect_success 'rebase of history with merges after upstream merge is linearized' ' + git checkout upstream-merged-nonlinear && + test 5 = $(git rev-list master.. | wc -l) && + git rebase master && + test 3 = $(git rev-list master.. | wc -l) ' test_expect_success 'rebase a single mode change' ' - git checkout master && - echo 1 > X && - git add X && - test_tick && - git commit -m prepare && - git checkout -b modechange HEAD^ && - echo 1 > X && - git add X && - test_chmod +x A && - test_tick && - git commit -m modechange && - GIT_TRACE=1 git rebase master + git checkout master && + echo 1 >X && + git add X && + test_tick && + git commit -m prepare && + git checkout -b modechange HEAD^ && + echo 1 >X && + git add X && + test_chmod +x A && + test_tick && + git commit -m modechange && + GIT_TRACE=1 git rebase master +' + +test_expect_success 'rebase is not broken by diff.renames' ' + git config diff.renames copies && + test_when_finished "git config --unset diff.renames" && + git checkout filemove && + GIT_TRACE=1 git rebase force-3way +' + +test_expect_success 'setup: recover' ' + test_might_fail git rebase --abort && + git reset --hard && + git checkout modechange ' test_expect_success 'Show verbose error when HEAD could not be detached' ' - : > B && - test_must_fail git rebase topic 2> output.err > output.out && - grep "Untracked working tree file .B. would be overwritten" output.err + >B && + test_must_fail git rebase topic 2>output.err >output.out && + grep "The following untracked working tree files would be overwritten by checkout:" output.err && + grep B output.err +' +rm -f B + +test_expect_success 'dump usage when upstream arg is missing' ' + git checkout -b usage topic && + test_must_fail git rebase 2>error1 && + grep "[Uu]sage" error1 && + test_must_fail git rebase --abort 2>error2 && + grep "No rebase in progress" error2 && + test_must_fail git rebase --onto master 2>error3 && + grep "[Uu]sage" error3 && + ! grep "can.t shift" error3 ' test_expect_success 'rebase -q is quiet' ' - rm B && - git checkout -b quiet topic && - git rebase -q master > output.out 2>&1 && - test ! -s output.out + git checkout -b quiet topic && + git rebase -q master >output.out 2>&1 && + test ! -s output.out ' test_expect_success 'Rebase a commit that sprinkles CRs in' ' diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index 7b7d07269a..2bea65634a 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -74,6 +74,15 @@ test_expect_success 'rebase the other way' ' git rebase --merge side ' +test_expect_success 'rebase -Xtheirs' ' + git checkout -b conflicting master~2 && + echo "AB $T" >> original && + git commit -mconflicting original && + git rebase -Xtheirs master && + grep AB original && + ! grep 11 original +' + test_expect_success 'merge and rebase should match' ' git diff-tree -r test-rebase test-merge >difference && if test -s difference diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index f20ea38411..7d20a74c5c 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -64,6 +64,67 @@ test_expect_success 'setup' ' done ' +# "exec" commands are ran with the user shell by default, but this may +# be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work +# to create a file. Unseting SHELL avoids such non-portable behavior +# in tests. +SHELL= + +test_expect_success 'rebase -i with the exec command' ' + git checkout master && + ( + FAKE_LINES="1 exec_>touch-one + 2 exec_>touch-two exec_false exec_>touch-three + 3 4 exec_>\"touch-file__name_with_spaces\";_>touch-after-semicolon 5" && + export FAKE_LINES && + test_must_fail git rebase -i A + ) && + test_path_is_file touch-one && + test_path_is_file touch-two && + test_path_is_missing touch-three " (should have stopped before)" && + test $(git rev-parse C) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of C)" + false + } && + git rebase --continue && + test_path_is_file touch-three && + test_path_is_file "touch-file name with spaces" && + test_path_is_file touch-after-semicolon && + test $(git rev-parse master) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of master)" + false + } && + rm -f touch-* +' + +test_expect_success 'rebase -i with the exec command runs from tree root' ' + git checkout master && + mkdir subdir && (cd subdir && + FAKE_LINES="1 exec_>touch-subdir" \ + git rebase -i HEAD^ + ) && + test_path_is_file touch-subdir && + rm -fr subdir +' + +test_expect_success 'rebase -i with the exec command checks tree cleanness' ' + git checkout master && + ( + FAKE_LINES="exec_echo_foo_>file1 1" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD^ + ) && + test $(git rev-parse master^) = $(git rev-parse HEAD) || { + echo "Stopped at wrong revision:" + echo "($(git describe --tags HEAD) instead of master^)" + false + } && + git reset --hard && + git rebase --continue +' + test_expect_success 'no changes are a nop' ' git checkout branch2 && git rebase -i F && @@ -143,7 +204,18 @@ test_expect_success 'abort' ' git rebase --abort && test $(git rev-parse new-branch1) = $(git rev-parse HEAD) && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && - ! test -d .git/rebase-merge + test_path_is_missing .git/rebase-merge +' + +test_expect_success 'abort with error when new base cannot be checked out' ' + git rm --cached file1 && + git commit -m "remove file in base" && + test_must_fail git rebase -i master > output 2>&1 && + grep "The following untracked working tree files would be overwritten by checkout:" \ + output && + grep "file1" output && + test_path_is_missing .git/rebase-merge && + git reset --hard HEAD^ ' test_expect_success 'retain authorship' ' @@ -181,6 +253,12 @@ test_expect_success '-p handles "no changes" gracefully' ' test $HEAD = $(git rev-parse HEAD) ' +test_expect_failure 'exchange two commits with -p' ' + FAKE_LINES="2 1" git rebase -i -p HEAD~2 && + test H = $(git cat-file commit HEAD^ | sed -ne \$p) && + test G = $(git cat-file commit HEAD | sed -ne \$p) +' + test_expect_success 'preserve merges with -p' ' git checkout -b to-be-preserved master^ && : > unrelated-file && @@ -614,4 +692,28 @@ test_expect_success 'always cherry-pick with --no-ff' ' test_cmp empty out ' +test_expect_success 'set up commits with funny messages' ' + git checkout -b funny A && + echo >>file1 && + test_tick && + git commit -a -m "end with slash\\" && + echo >>file1 && + test_tick && + git commit -a -m "something (\000) that looks like octal" && + echo >>file1 && + test_tick && + git commit -a -m "something (\n) that looks like a newline" && + echo >>file1 && + test_tick && + git commit -a -m "another commit" +' + +test_expect_success 'rebase-i history with funny messages' ' + git rev-list A..funny >expect && + test_tick && + FAKE_LINES="1 2 3 4" git rebase -i A && + git rev-list A.. >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh index 2999e78937..fbb3f2e0df 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -38,7 +38,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && git rebase --abort && test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && test ! -d "$dotest" @@ -49,7 +49,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && test_must_fail git rebase --skip && test $(git rev-parse HEAD) = $(git rev-parse master) && git rebase --abort && @@ -62,7 +62,7 @@ testrebase() { # Clean up the state from the previous one git reset --hard pre-rebase && test_must_fail git rebase$type master && - test -d "$dotest" && + test_path_is_dir "$dotest" && echo c > a && echo d >> a && git add a && diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh index 8f785e7957..74161a42ec 100755 --- a/t/t3409-rebase-preserve-merges.sh +++ b/t/t3409-rebase-preserve-merges.sh @@ -42,23 +42,24 @@ test_expect_success 'setup for merge-preserving rebase' \ git commit -a -m "Modify A2" && git clone ./. clone1 && - cd clone1 && + (cd clone1 && git checkout -b topic origin/topic && - git merge origin/master && - cd .. && + git merge origin/master + ) && echo Fifth > B && git add B && git commit -m "Add different B" && git clone ./. clone2 && - cd clone2 && - git checkout -b topic origin/topic && - test_must_fail git merge origin/master && - echo Resolved > B && - git add B && - git commit -m "Merge origin/master into topic" && - cd .. && + ( + cd clone2 && + git checkout -b topic origin/topic && + test_must_fail git merge origin/master && + echo Resolved >B && + git add B && + git commit -m "Merge origin/master into topic" + ) && git checkout topic && echo Fourth >> B && diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh index c49143a1a4..6f73b95558 100755 --- a/t/t3410-rebase-preserve-dropped-merges.sh +++ b/t/t3410-rebase-preserve-dropped-merges.sh @@ -43,11 +43,11 @@ test_expect_success 'setup' ' # G2 = same changes as G test_expect_success 'skip same-resolution merges with -p' ' git checkout H && - ! git merge E && + test_must_fail git merge E && test_commit L file1 23 && git checkout I && test_commit G2 file1 3 && - ! git merge E && + test_must_fail git merge E && test_commit J file1 23 && test_commit K file7 file7 && git rebase -i -p L && @@ -65,11 +65,11 @@ test_expect_success 'skip same-resolution merges with -p' ' # G2 = different changes as G test_expect_success 'keep different-resolution merges with -p' ' git checkout H && - ! git merge E && + test_must_fail git merge E && test_commit L2 file1 23 && git checkout I && test_commit G3 file1 4 && - ! git merge E && + test_must_fail git merge E && test_commit J2 file1 24 && test_commit K2 file7 file7 && test_must_fail git rebase -i -p L2 && diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index b63f4e2d67..fd2184ce71 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -21,38 +21,62 @@ test_expect_success setup ' git tag base ' -test_expect_success 'auto fixup' ' +test_auto_fixup() { git reset --hard base && echo 1 >file1 && git add -u && test_tick && - git commit -m "fixup! first" + git commit -m "fixup! first" && - git tag final-fixup && + git tag $1 && test_tick && - git rebase --autosquash -i HEAD^^^ && + git rebase $2 -i HEAD^^^ && git log --oneline >actual && test 3 = $(wc -l <actual) && - git diff --exit-code final-fixup && + git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) +} + +test_expect_success 'auto fixup (option)' ' + test_auto_fixup final-fixup-option --autosquash +' + +test_expect_success 'auto fixup (config)' ' + git config rebase.autosquash true && + test_auto_fixup final-fixup-config-true && + test_must_fail test_auto_fixup fixup-config-true-no --no-autosquash && + git config rebase.autosquash false && + test_must_fail test_auto_fixup final-fixup-config-false ' -test_expect_success 'auto squash' ' +test_auto_squash() { git reset --hard base && echo 1 >file1 && git add -u && test_tick && - git commit -m "squash! first" + git commit -m "squash! first" && - git tag final-squash && + git tag $1 && test_tick && - git rebase --autosquash -i HEAD^^^ && + git rebase $2 -i HEAD^^^ && git log --oneline >actual && test 3 = $(wc -l <actual) && - git diff --exit-code final-squash && + git diff --exit-code $1 && test 1 = "$(git cat-file blob HEAD^:file1)" && test 2 = $(git cat-file commit HEAD^ | grep first | wc -l) +} + +test_expect_success 'auto squash (option)' ' + test_auto_squash final-squash --autosquash +' + +test_expect_success 'auto squash (config)' ' + git config rebase.autosquash true && + test_auto_squash final-squash-config-true && + test_must_fail test_auto_squash squash-config-true-no --no-autosquash && + git config rebase.autosquash false && + test_must_fail test_auto_squash final-squash-config-false ' test_expect_success 'misspelled auto squash' ' @@ -60,7 +84,7 @@ test_expect_success 'misspelled auto squash' ' echo 1 >file1 && git add -u && test_tick && - git commit -m "squash! forst" + git commit -m "squash! forst" && git tag final-missquash && test_tick && git rebase --autosquash -i HEAD^^^ && diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh new file mode 100755 index 0000000000..3b0d27350e --- /dev/null +++ b/t/t3418-rebase-continue.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='git rebase --continue tests' + +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +test_expect_success 'setup' ' + test_commit "commit-new-file-F1" F1 1 && + test_commit "commit-new-file-F2" F2 2 && + + git checkout -b topic HEAD^ && + test_commit "commit-new-file-F2-on-topic-branch" F2 22 && + + git checkout master +' + +test_expect_success 'interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + FAKE_LINES="edit 1" git rebase -i HEAD^ && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_expect_success 'non-interactive rebase --continue works with touched file' ' + rm -fr .git/rebase-* && + git reset --hard && + git checkout master && + + test_must_fail git rebase --onto master master topic && + echo "Resolved" >F2 && + git add F2 && + test-chmtime =-60 F1 && + git rebase --continue +' + +test_done diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh index dadbbc2a9f..f038f34b7c 100755 --- a/t/t3500-cherry.sh +++ b/t/t3500-cherry.sh @@ -17,17 +17,19 @@ test_expect_success \ 'prepare repository with topic branch, and check cherry finds the 2 patches from there' \ 'echo First > A && git update-index --add A && + test_tick && git commit -m "Add A." && git checkout -b my-topic-branch && echo Second > B && git update-index --add B && + test_tick && git commit -m "Add B." && - sleep 2 && echo AnotherSecond > C && git update-index --add C && + test_tick && git commit -m "Add C." && git checkout -f master && @@ -35,6 +37,7 @@ test_expect_success \ echo Third >> A && git update-index A && + test_tick && git commit -m "Modify A." && expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* + .*" diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 7f858151d4..bc7aedd048 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -41,13 +41,32 @@ test_expect_success setup ' git tag rename2 ' +test_expect_success 'cherry-pick --nonsense' ' + + pos=$(git rev-parse HEAD) && + git diff --exit-code HEAD && + test_must_fail git cherry-pick --nonsense 2>msg && + git diff --exit-code HEAD "$pos" && + grep '[Uu]sage:' msg +' + +test_expect_success 'revert --nonsense' ' + + pos=$(git rev-parse HEAD) && + git diff --exit-code HEAD && + test_must_fail git revert --nonsense 2>msg && + git diff --exit-code HEAD "$pos" && + grep '[Uu]sage:' msg +' + test_expect_success 'cherry-pick after renaming branch' ' git checkout rename2 && git cherry-pick added && test $(git rev-parse HEAD^) = $(git rev-parse rename2) && test -f opos && - grep "Add extra line at the end" opos + grep "Add extra line at the end" opos && + git reflog -1 | grep cherry-pick ' @@ -57,7 +76,8 @@ test_expect_success 'revert after renaming branch' ' git revert added && test $(git rev-parse HEAD^) = $(git rev-parse rename1) && test -f spoo && - ! grep "Add extra line at the end" spoo + ! grep "Add extra line at the end" spoo && + git reflog -1 | grep revert ' diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh index e51e505a9f..c10b28cf57 100755 --- a/t/t3505-cherry-pick-empty.sh +++ b/t/t3505-cherry-pick-empty.sh @@ -13,12 +13,30 @@ test_expect_success setup ' git checkout -b empty-branch && test_tick && - git commit --allow-empty -m "empty" + git commit --allow-empty -m "empty" && + + echo third >> file1 && + git add file1 && + test_tick && + git commit --allow-empty-message -m "" ' test_expect_success 'cherry-pick an empty commit' ' git checkout master && { + git cherry-pick empty-branch^ + test "$?" = 1 + } +' + +test_expect_success 'index lockfile was removed' ' + + test ! -f .git/index.lock + +' + +test_expect_success 'cherry-pick a commit with an empty message' ' + git checkout master && { git cherry-pick empty-branch test "$?" = 1 } diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh index e17ae712b1..51ca391e47 100755 --- a/t/t3506-cherry-pick-ff.sh +++ b/t/t3506-cherry-pick-ff.sh @@ -95,4 +95,14 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent with --f test_must_fail git cherry-pick --ff -m 3 C ' +test_expect_success 'cherry pick a root commit with --ff' ' + git reset --hard first -- && + git rm file1 && + echo first >file2 && + git add file2 && + git commit --amend -m "file2" && + git cherry-pick --ff first && + test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1" +' + test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index e25cf8039a..607bf25d8f 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -38,6 +38,26 @@ test_expect_success 'failed cherry-pick does not advance HEAD' ' test "$head" = "$newhead" ' +test_expect_success 'advice from failed cherry-pick' " + git checkout -f initial^0 && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + + git update-index --refresh && + git diff-index --exit-code HEAD && + + picked=\$(git rev-parse --short picked) && + cat <<-EOF >expected && + error: could not apply \$picked... picked + hint: after resolving the conflicts, mark the corrected paths + hint: with 'git add <paths>' or 'git rm <paths>' + hint: and commit the result with 'git commit -c \$picked' + EOF + test_must_fail git cherry-pick picked 2>actual && + + test_cmp expected actual +" + test_expect_success 'failed cherry-pick produces dirty index' ' git checkout -f initial^0 && diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh new file mode 100755 index 0000000000..8e09fd0319 --- /dev/null +++ b/t/t3508-cherry-pick-many-commits.sh @@ -0,0 +1,159 @@ +#!/bin/sh + +test_description='test cherry-picking many commits' + +. ./test-lib.sh + +check_head_differs_from() { + head=$(git rev-parse --verify HEAD) && + arg=$(git rev-parse --verify "$1") && + test "$head" != "$arg" +} + +check_head_equals() { + head=$(git rev-parse --verify HEAD) && + arg=$(git rev-parse --verify "$1") && + test "$head" = "$arg" +} + +test_expect_success setup ' + echo first > file1 && + git add file1 && + test_tick && + git commit -m "first" && + git tag first && + + git checkout -b other && + for val in second third fourth + do + echo $val >> file1 && + git add file1 && + test_tick && + git commit -m "$val" && + git tag $val + done +' + +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(-) + [master OBJID] third + Author: A U Thor <author@example.com> + 1 files changed, 1 insertions(+), 0 deletions(-) + [master OBJID] fourth + Author: A U Thor <author@example.com> + 1 files changed, 1 insertions(+), 0 deletions(-) + EOF + + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick first..fourth >actual && + git diff --quiet other && + git diff --quiet HEAD other && + + sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy && + test_cmp expected actual.fuzzy && + check_head_differs_from fourth +' + +test_expect_success 'cherry-pick --strategy resolve first..fourth works' ' + cat <<-\EOF >expected && + Trying simple merge. + [master OBJID] second + Author: A U Thor <author@example.com> + 1 files changed, 1 insertions(+), 0 deletions(-) + Trying simple merge. + [master OBJID] third + Author: A U Thor <author@example.com> + 1 files changed, 1 insertions(+), 0 deletions(-) + Trying simple merge. + [master OBJID] fourth + Author: A U Thor <author@example.com> + 1 files changed, 1 insertions(+), 0 deletions(-) + EOF + + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick --strategy resolve first..fourth >actual && + git diff --quiet other && + git diff --quiet HEAD other && + sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy && + test_cmp expected actual.fuzzy && + check_head_differs_from fourth +' + +test_expect_success 'cherry-pick --ff first..fourth works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick --ff first..fourth && + git diff --quiet other && + git diff --quiet HEAD other && + check_head_equals fourth +' + +test_expect_success 'cherry-pick -n first..fourth works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick -n first..fourth && + git diff --quiet other && + git diff --cached --quiet other && + git diff --quiet HEAD first +' + +test_expect_success 'revert first..fourth works' ' + git checkout -f master && + git reset --hard fourth && + test_tick && + git revert first..fourth && + git diff --quiet first && + git diff --cached --quiet first && + git diff --quiet HEAD first +' + +test_expect_success 'revert ^first fourth works' ' + git checkout -f master && + git reset --hard fourth && + test_tick && + git revert ^first fourth && + git diff --quiet first && + git diff --cached --quiet first && + git diff --quiet HEAD first +' + +test_expect_success 'revert fourth fourth~1 fourth~2 works' ' + git checkout -f master && + git reset --hard fourth && + test_tick && + git revert fourth fourth~1 fourth~2 && + git diff --quiet first && + git diff --cached --quiet first && + git diff --quiet HEAD first +' + +test_expect_success 'cherry-pick -3 fourth works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick -3 fourth && + git diff --quiet other && + git diff --quiet HEAD other && + check_head_differs_from fourth +' + +test_expect_success 'cherry-pick --stdin works' ' + git checkout -f master && + git reset --hard first && + test_tick && + git rev-list --reverse first..fourth | git cherry-pick --stdin && + git diff --quiet other && + git diff --quiet HEAD other && + check_head_differs_from fourth +' + +test_done diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh new file mode 100755 index 0000000000..a5ccdbf8fc --- /dev/null +++ b/t/t3509-cherry-pick-merge-df.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +test_description='Test cherry-pick with directory/file conflicts' +. ./test-lib.sh + +test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' ' + mkdir a && + >a/f && + git add a && + git commit -m a && + + mkdir b && + ln -s ../a b/a && + git add b && + git commit -m b && + + git checkout -b branch && + rm b/a && + mv a b/a && + ln -s b/a a && + git add . && + git commit -m swap && + + >f1 && + git add f1 && + git commit -m f1 +' + +test_expect_success SYMLINKS 'Cherry-pick succeeds with rename across D/F conflicts' ' + git reset --hard && + git checkout master^0 && + git cherry-pick branch +' + +test_done diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 0aaf0ad84b..b26cabd571 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -28,22 +28,6 @@ embedded' && git commit -m 'add files with tabs and newlines' " -# Determine rm behavior -# Later we will try removing an unremovable path to make sure -# git rm barfs, but if the test is run as root that cannot be -# arranged. -: >test-file -chmod a-w . -rm -f test-file 2>/dev/null -if test -f test-file -then - test_set_prereq RO_DIR -else - say 'skipping removal failure test (perhaps running as root?)' -fi -chmod 775 . -rm -f test-file - test_expect_success \ 'Pre-check that foo exists and is in index before git rm foo' \ '[ -f foo ] && git ls-files --error-unmatch foo' diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 525c9a8fdf..ec7108358e 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -26,7 +26,7 @@ test_expect_success \ chmod 755 xfoo1 && git add xfoo1 && case "`git ls-files --stage xfoo1`" in - 100644" "*xfoo1) echo ok;; + 100644" "*xfoo1) echo pass;; *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac' @@ -35,7 +35,7 @@ test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by sym ln -s foo xfoo1 && git add xfoo1 && case "`git ls-files --stage xfoo1`" in - 120000" "*xfoo1) echo ok;; + 120000" "*xfoo1) echo pass;; *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac ' @@ -47,7 +47,7 @@ test_expect_success \ chmod 755 xfoo2 && git update-index --add xfoo2 && case "`git ls-files --stage xfoo2`" in - 100644" "*xfoo2) echo ok;; + 100644" "*xfoo2) echo pass;; *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac' @@ -56,7 +56,7 @@ test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by sym ln -s foo xfoo2 && git update-index --add xfoo2 && case "`git ls-files --stage xfoo2`" in - 120000" "*xfoo2) echo ok;; + 120000" "*xfoo2) echo pass;; *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac ' @@ -67,7 +67,7 @@ test_expect_success SYMLINKS \ ln -s xfoo2 xfoo3 && git update-index --add xfoo3 && case "`git ls-files --stage xfoo3`" in - 120000" "*xfoo3) echo ok;; + 120000" "*xfoo3) echo pass;; *) echo fail; git ls-files --stage xfoo3; (exit 1);; esac' @@ -172,14 +172,14 @@ test_expect_success 'git add --refresh' ' test -z "`git diff-index HEAD -- foo`" && git read-tree HEAD && case "`git diff-index HEAD -- foo`" in - :100644" "*"M foo") echo ok;; + :100644" "*"M foo") echo pass;; *) echo fail; (exit 1);; esac && git add --refresh -- foo && test -z "`git diff-index HEAD -- foo`" ' -test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable file' ' +test_expect_success POSIXPERM,SANITY 'git add should fail atomically upon an unreadable file' ' git reset --hard && date >foo1 && date >foo2 && @@ -190,7 +190,7 @@ test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable rm -f foo2 -test_expect_success POSIXPERM 'git add --ignore-errors' ' +test_expect_success POSIXPERM,SANITY 'git add --ignore-errors' ' git reset --hard && date >foo1 && date >foo2 && @@ -201,7 +201,7 @@ test_expect_success POSIXPERM 'git add --ignore-errors' ' rm -f foo2 -test_expect_success POSIXPERM 'git add (add.ignore-errors)' ' +test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors)' ' git config add.ignore-errors 1 && git reset --hard && date >foo1 && @@ -212,7 +212,7 @@ test_expect_success POSIXPERM 'git add (add.ignore-errors)' ' ' rm -f foo2 -test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' ' +test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors = false)' ' git config add.ignore-errors 0 && git reset --hard && date >foo1 && @@ -223,7 +223,7 @@ test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' ' ' rm -f foo2 -test_expect_success POSIXPERM '--no-ignore-errors overrides config' ' +test_expect_success POSIXPERM,SANITY '--no-ignore-errors overrides config' ' git config add.ignore-errors 1 && git reset --hard && date >foo1 && @@ -260,4 +260,32 @@ test_expect_success '"add non-existent" should fail' ' ! (git ls-files | grep "non-existent") ' +test_expect_success 'git add --dry-run of existing changed file' " + echo new >>track-this && + git add --dry-run track-this >actual 2>&1 && + echo \"add 'track-this'\" | test_cmp - actual +" + +test_expect_success 'git add --dry-run of non-existing file' " + echo ignored-file >>.gitignore && + test_must_fail git add --dry-run track-this ignored-file >actual 2>&1 && + echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual +" + +cat >expect.err <<\EOF +The following paths are ignored by one of your .gitignore files: +ignored-file +Use -f if you really want to add them. +fatal: no files added +EOF +cat >expect.out <<\EOF +add 'track-this' +EOF + +test_expect_success 'git add --dry-run --ignore-missing of non-existing file' ' + test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err && + test_cmp expect.out actual.out && + test_cmp expect.err actual.err +' + test_done diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index b6eba6a839..d6327e7c74 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -2,22 +2,20 @@ test_description='add -i basic tests' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh -if ! test_have_prereq PERL; then - say 'skipping git add -i tests, perl not available' - test_done -fi - -test_expect_success 'setup (initial)' ' +test_expect_success PERL 'setup (initial)' ' echo content >file && git add file && echo more >>file && echo lines >>file ' -test_expect_success 'status works (initial)' ' +test_expect_success PERL 'status works (initial)' ' git add -i </dev/null >output && grep "+1/-0 *+2/-0 file" output ' + +test_expect_success PERL 'setup expected' ' cat >expected <<EOF new file mode 100644 index 0000000..d95f3ad @@ -26,19 +24,21 @@ index 0000000..d95f3ad @@ -0,0 +1 @@ +content EOF -test_expect_success 'diff works (initial)' ' +' + +test_expect_success PERL 'diff works (initial)' ' (echo d; echo 1) | git add -i >output && sed -ne "/new file/,/content/p" <output >diff && test_cmp expected diff ' -test_expect_success 'revert works (initial)' ' +test_expect_success PERL 'revert works (initial)' ' git add file && (echo r; echo 1) | git add -i && git ls-files >output && ! grep . output ' -test_expect_success 'setup (commit)' ' +test_expect_success PERL 'setup (commit)' ' echo baseline >file && git add file && git commit -m commit && @@ -47,10 +47,12 @@ test_expect_success 'setup (commit)' ' echo more >>file && echo lines >>file ' -test_expect_success 'status works (commit)' ' +test_expect_success PERL 'status works (commit)' ' git add -i </dev/null >output && grep "+1/-0 *+2/-0 file" output ' + +test_expect_success PERL 'setup expected' ' cat >expected <<EOF index 180b47c..b6f2c08 100644 --- a/file @@ -59,60 +61,79 @@ index 180b47c..b6f2c08 100644 baseline +content EOF -test_expect_success 'diff works (commit)' ' +' + +test_expect_success PERL 'diff works (commit)' ' (echo d; echo 1) | git add -i >output && sed -ne "/^index/,/content/p" <output >diff && test_cmp expected diff ' -test_expect_success 'revert works (commit)' ' +test_expect_success PERL 'revert works (commit)' ' git add file && (echo r; echo 1) | git add -i && git add -i </dev/null >output && grep "unchanged *+3/-0 file" output ' + +test_expect_success PERL 'setup expected' ' cat >expected <<EOF EOF -cat >fake_editor.sh <<EOF -EOF -chmod a+x fake_editor.sh -test_set_editor "$(pwd)/fake_editor.sh" -test_expect_success 'dummy edit works' ' +' + +test_expect_success PERL 'setup fake editor' ' + cat >fake_editor.sh <<EOF + EOF + chmod a+x fake_editor.sh && + test_set_editor "$(pwd)/fake_editor.sh" && +' + +test_expect_success PERL 'dummy edit works' ' (echo e; echo a) | git add -p && git diff > diff && test_cmp expected diff ' +test_expect_success PERL 'setup patch' ' cat >patch <<EOF @@ -1,1 +1,4 @@ this +patch --doesn't +-does not apply EOF -echo "#!$SHELL_PATH" >fake_editor.sh -cat >>fake_editor.sh <<\EOF +' + +test_expect_success PERL 'setup fake editor' ' + echo "#!$SHELL_PATH" >fake_editor.sh && + cat >>fake_editor.sh <<\EOF && mv -f "$1" oldpatch && mv -f patch "$1" EOF -chmod a+x fake_editor.sh -test_set_editor "$(pwd)/fake_editor.sh" -test_expect_success 'bad edit rejected' ' + chmod a+x fake_editor.sh && + test_set_editor "$(pwd)/fake_editor.sh" +' + +test_expect_success PERL 'bad edit rejected' ' git reset && (echo e; echo n; echo d) | git add -p >output && grep "hunk does not apply" output ' +test_expect_success PERL 'setup patch' ' cat >patch <<EOF this patch is garbage EOF -test_expect_success 'garbage edit rejected' ' +' + +test_expect_success PERL 'garbage edit rejected' ' git reset && (echo e; echo n; echo d) | git add -p >output && grep "hunk does not apply" output ' +test_expect_success PERL 'setup patch' ' cat >patch <<EOF @@ -1,0 +1,0 @@ baseline @@ -120,6 +141,9 @@ cat >patch <<EOF +newcontent +lines EOF +' + +test_expect_success PERL 'setup expected' ' cat >expected <<EOF diff --git a/file b/file index b5dd6c9..f910ae9 100644 @@ -132,13 +156,15 @@ index b5dd6c9..f910ae9 100644 +more lines EOF -test_expect_success 'real edit works' ' +' + +test_expect_success PERL 'real edit works' ' (echo e; echo n; echo d) | git add -p && git diff >output && test_cmp expected output ' -test_expect_success 'skip files similarly as commit -a' ' +test_expect_success PERL 'skip files similarly as commit -a' ' git reset && echo file >.gitignore && echo changed >file && @@ -152,14 +178,7 @@ test_expect_success 'skip files similarly as commit -a' ' ' rm -f .gitignore -if test "$(git config --bool core.filemode)" = false -then - say 'skipping filemode tests (filesystem does not properly support modes)' -else - test_set_prereq FILEMODE -fi - -test_expect_success FILEMODE 'patch does not affect mode' ' +test_expect_success PERL,FILEMODE 'patch does not affect mode' ' git reset --hard && echo content >>file && chmod +x file && @@ -168,7 +187,7 @@ test_expect_success FILEMODE 'patch does not affect mode' ' git diff file | grep "new mode" ' -test_expect_success FILEMODE 'stage mode but not hunk' ' +test_expect_success PERL,FILEMODE 'stage mode but not hunk' ' git reset --hard && echo content >>file && chmod +x file && @@ -178,7 +197,7 @@ test_expect_success FILEMODE 'stage mode but not hunk' ' ' -test_expect_success FILEMODE 'stage mode and hunk' ' +test_expect_success PERL,FILEMODE 'stage mode and hunk' ' git reset --hard && echo content >>file && chmod +x file && @@ -190,13 +209,14 @@ test_expect_success FILEMODE 'stage mode and hunk' ' # end of tests disabled when filemode is not usable -test_expect_success 'setup again' ' +test_expect_success PERL 'setup again' ' git reset --hard && test_chmod +x file && echo content >>file ' # Write the patch file with a new line at the top and bottom +test_expect_success PERL 'setup patch' ' cat >patch <<EOF index 180b47c..b6f2c08 100644 --- a/file @@ -207,7 +227,10 @@ index 180b47c..b6f2c08 100644 content +lastline EOF +' + # Expected output, similar to the patch but w/ diff at the top +test_expect_success PERL 'setup expected' ' cat >expected <<EOF diff --git a/file b/file index b6f2c08..61b9053 100755 @@ -219,8 +242,10 @@ index b6f2c08..61b9053 100755 content +lastline EOF +' + # Test splitting the first patch, then adding both -test_expect_success 'add first line works' ' +test_expect_success PERL 'add first line works' ' git commit -am "clear local changes" && git apply patch && (echo s; echo y; echo y) | git add -p file && @@ -228,6 +253,7 @@ test_expect_success 'add first line works' ' test_cmp expected diff ' +test_expect_success PERL 'setup expected' ' cat >expected <<EOF diff --git a/non-empty b/non-empty deleted file mode 100644 @@ -237,7 +263,9 @@ index d95f3ad..0000000 @@ -1 +0,0 @@ -content EOF -test_expect_success 'deleting a non-empty file' ' +' + +test_expect_success PERL 'deleting a non-empty file' ' git reset --hard && echo content >non-empty && git add non-empty && @@ -248,13 +276,15 @@ test_expect_success 'deleting a non-empty file' ' test_cmp expected diff ' +test_expect_success PERL 'setup expected' ' cat >expected <<EOF diff --git a/empty b/empty deleted file mode 100644 index e69de29..0000000 EOF +' -test_expect_success 'deleting an empty file' ' +test_expect_success PERL 'deleting an empty file' ' git reset --hard && > empty && git add empty && diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh index 29103f65dc..7d49469841 100755 --- a/t/t3902-quoted.sh +++ b/t/t3902-quoted.sh @@ -15,11 +15,13 @@ LF=' DQ='"' echo foo 2>/dev/null > "Name and an${HT}HT" -test -f "Name and an${HT}HT" || { - # since FAT/NTFS does not allow tabs in filenames, skip this test - say 'Your filesystem does not allow tabs in filenames, test skipped.' - test_done -} +if ! test -f "Name and an${HT}HT" +then + # FAT/NTFS does not allow tabs in filenames + say 'Your filesystem does not allow tabs in filenames' +else + test_set_prereq TABS_IN_FILENAMES +fi for_each_name () { for name in \ @@ -31,7 +33,7 @@ for_each_name () { done } -test_expect_success setup ' +test_expect_success TABS_IN_FILENAMES 'setup' ' mkdir "$FN" && for_each_name "echo initial >\"\$name\"" @@ -45,6 +47,7 @@ test_expect_success setup ' ' +test_expect_success TABS_IN_FILENAMES 'setup expected files' ' cat >expect.quoted <<\EOF Name "Name and a\nLF" @@ -72,75 +75,76 @@ With SP in it 濱野/file 濱野純 EOF +' -test_expect_success 'check fully quoted output from ls-files' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from ls-files' ' git ls-files >current && test_cmp expect.quoted current ' -test_expect_success 'check fully quoted output from diff-files' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-files' ' git diff --name-only >current && test_cmp expect.quoted current ' -test_expect_success 'check fully quoted output from diff-index' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-index' ' git diff --name-only HEAD >current && test_cmp expect.quoted current ' -test_expect_success 'check fully quoted output from diff-tree' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-tree' ' git diff --name-only HEAD^ HEAD >current && test_cmp expect.quoted current ' -test_expect_success 'check fully quoted output from ls-tree' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from ls-tree' ' git ls-tree --name-only -r HEAD >current && test_cmp expect.quoted current ' -test_expect_success 'setting core.quotepath' ' +test_expect_success TABS_IN_FILENAMES 'setting core.quotepath' ' git config --bool core.quotepath false ' -test_expect_success 'check fully quoted output from ls-files' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from ls-files' ' git ls-files >current && test_cmp expect.raw current ' -test_expect_success 'check fully quoted output from diff-files' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-files' ' git diff --name-only >current && test_cmp expect.raw current ' -test_expect_success 'check fully quoted output from diff-index' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-index' ' git diff --name-only HEAD >current && test_cmp expect.raw current ' -test_expect_success 'check fully quoted output from diff-tree' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from diff-tree' ' git diff --name-only HEAD^ HEAD >current && test_cmp expect.raw current ' -test_expect_success 'check fully quoted output from ls-tree' ' +test_expect_success TABS_IN_FILENAMES 'check fully quoted output from ls-tree' ' git ls-tree --name-only -r HEAD >current && test_cmp expect.raw current diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 476e5ec038..903a122efe 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -69,9 +69,10 @@ test_expect_success 'apply stashed changes (including index)' ' test_expect_success 'unstashing in a subdirectory' ' git reset --hard HEAD && mkdir subdir && - cd subdir && - git stash apply && - cd .. + ( + cd subdir && + git stash apply + ) ' test_expect_success 'drop top stash' ' @@ -81,7 +82,7 @@ test_expect_success 'drop top stash' ' git stash && git stash drop && git stash list > stashlist2 && - diff stashlist1 stashlist2 && + test_cmp stashlist1 stashlist2 && git stash apply && test 3 = $(cat file) && test 1 = $(git show :file) && @@ -228,4 +229,331 @@ test_expect_success 'stash --invalid-option' ' test bar,bar2 = $(cat file),$(cat file2) ' +test_expect_success 'stash an added file' ' + git reset --hard && + echo new >file3 && + git add file3 && + git stash save "added file" && + ! test -r file3 && + git stash apply && + test new = "$(cat file3)" +' + +test_expect_success 'stash rm then recreate' ' + git reset --hard && + git rm file && + echo bar7 >file && + git stash save "rm then recreate" && + test bar = "$(cat file)" && + git stash apply && + test bar7 = "$(cat file)" +' + +test_expect_success 'stash rm and ignore' ' + git reset --hard && + git rm file && + echo file >.gitignore && + git stash save "rm and ignore" && + test bar = "$(cat file)" && + test file = "$(cat .gitignore)" + git stash apply && + ! test -r file && + test file = "$(cat .gitignore)" +' + +test_expect_success 'stash rm and ignore (stage .gitignore)' ' + git reset --hard && + git rm file && + echo file >.gitignore && + git add .gitignore && + git stash save "rm and ignore (stage .gitignore)" && + test bar = "$(cat file)" && + ! test -r .gitignore + git stash apply && + ! test -r file && + test file = "$(cat .gitignore)" +' + +test_expect_success SYMLINKS 'stash file to symlink' ' + git reset --hard && + rm file && + ln -s file2 file && + git stash save "file to symlink" && + test -f file && + test bar = "$(cat file)" && + git stash apply && + case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac +' + +test_expect_success SYMLINKS 'stash file to symlink (stage rm)' ' + git reset --hard && + git rm file && + ln -s file2 file && + git stash save "file to symlink (stage rm)" && + test -f file && + test bar = "$(cat file)" && + git stash apply && + case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac +' + +test_expect_success SYMLINKS 'stash file to symlink (full stage)' ' + git reset --hard && + rm file && + ln -s file2 file && + git add file && + git stash save "file to symlink (full stage)" && + test -f file && + test bar = "$(cat file)" && + git stash apply && + case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac +' + +# This test creates a commit with a symlink used for the following tests + +test_expect_success SYMLINKS 'stash symlink to file' ' + git reset --hard && + ln -s file filelink && + git add filelink && + git commit -m "Add symlink" && + rm filelink && + cp file filelink && + git stash save "symlink to file" && + test -h filelink && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + git stash apply && + ! test -h filelink && + test bar = "$(cat file)" +' + +test_expect_success SYMLINKS 'stash symlink to file (stage rm)' ' + git reset --hard && + git rm filelink && + cp file filelink && + git stash save "symlink to file (stage rm)" && + test -h filelink && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + git stash apply && + ! test -h filelink && + test bar = "$(cat file)" +' + +test_expect_success SYMLINKS 'stash symlink to file (full stage)' ' + git reset --hard && + rm filelink && + cp file filelink && + git add filelink && + git stash save "symlink to file (full stage)" && + test -h filelink && + case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac && + git stash apply && + ! test -h filelink && + test bar = "$(cat file)" +' + +test_expect_failure 'stash directory to file' ' + git reset --hard && + mkdir dir && + echo foo >dir/file && + git add dir/file && + git commit -m "Add file in dir" && + rm -fr dir && + echo bar >dir && + git stash save "directory to file" && + test -d dir && + test foo = "$(cat dir/file)" && + test_must_fail git stash apply && + test bar = "$(cat dir)" && + git reset --soft HEAD^ +' + +test_expect_failure 'stash file to directory' ' + git reset --hard && + rm file && + mkdir file && + echo foo >file/file && + git stash save "file to directory" && + test -f file && + test bar = "$(cat file)" && + git stash apply && + test -f file/file && + test foo = "$(cat file/file)" +' + +test_expect_success 'stash branch - no stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + STASH_ID=$(git stash create) && + git reset --hard && + git stash branch stash-branch ${STASH_ID} && + test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && + test $(git ls-files --modified | wc -l) -eq 1 +' + +test_expect_success 'stash branch - stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + git stash && + test_when_finished "git stash drop" && + echo bar >> file && + STASH_ID=$(git stash create) && + git reset --hard && + git stash branch stash-branch ${STASH_ID} && + test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && + test $(git ls-files --modified | wc -l) -eq 1 +' + +test_expect_success 'stash show - stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + git stash && + test_when_finished "git stash drop" && + echo bar >> file && + STASH_ID=$(git stash create) && + git reset --hard && + cat >expected <<-EOF && + file | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + EOF + git stash show ${STASH_ID} >actual && + test_cmp expected actual +' + +test_expect_success 'stash show -p - stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + git stash && + test_when_finished "git stash drop" && + echo bar >> file && + STASH_ID=$(git stash create) && + git reset --hard && + cat >expected <<-EOF && + diff --git a/file b/file + index 7601807..935fbd3 100644 + --- a/file + +++ b/file + @@ -1 +1,2 @@ + baz + +bar + EOF + git stash show -p ${STASH_ID} >actual && + test_cmp expected actual +' + +test_expect_success 'stash show - no stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + STASH_ID=$(git stash create) && + git reset --hard && + cat >expected <<-EOF && + file | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + EOF + git stash show ${STASH_ID} >actual && + test_cmp expected actual +' + +test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + git reset --hard && + echo foo >> file && + STASH_ID=$(git stash create) && + git reset --hard && + cat >expected <<-EOF && + diff --git a/file b/file + index 7601807..71b52c4 100644 + --- a/file + +++ b/file + @@ -1 +1,2 @@ + baz + +foo + EOF + git stash show -p ${STASH_ID} >actual && + test_cmp expected actual +' + +test_expect_success 'stash drop - fail early if specified stash is not a stash reference' ' + git stash clear && + test_when_finished "git reset --hard HEAD && git stash clear" && + git reset --hard && + echo foo > file && + git stash && + echo bar > file && + git stash && + test_must_fail git stash drop $(git rev-parse stash@{0}) && + git stash pop && + test bar = "$(cat file)" && + git reset --hard HEAD +' + +test_expect_success 'stash pop - fail early if specified stash is not a stash reference' ' + git stash clear && + test_when_finished "git reset --hard HEAD && git stash clear" && + git reset --hard && + echo foo > file && + git stash && + echo bar > file && + git stash && + test_must_fail git stash pop $(git rev-parse stash@{0}) && + git stash pop && + test bar = "$(cat file)" && + git reset --hard HEAD +' + +test_expect_success 'ref with non-existant reflog' ' + git stash clear && + echo bar5 > file && + echo bar6 > file2 && + git add file2 && + git stash && + ! "git rev-parse --quiet --verify does-not-exist" && + test_must_fail git stash drop does-not-exist && + test_must_fail git stash drop does-not-exist@{0} && + test_must_fail git stash pop does-not-exist && + test_must_fail git stash pop does-not-exist@{0} && + test_must_fail git stash apply does-not-exist && + test_must_fail git stash apply does-not-exist@{0} && + test_must_fail git stash show does-not-exist && + test_must_fail git stash show does-not-exist@{0} && + test_must_fail git stash branch tmp does-not-exist && + test_must_fail git stash branch tmp does-not-exist@{0} && + git stash drop +' + +test_expect_success 'invalid ref of the form stash@{n}, n >= N' ' + git stash clear && + test_must_fail git stash drop stash@{0} && + echo bar5 > file && + echo bar6 > file2 && + git add file2 && + git stash && + test_must_fail git drop stash@{1} && + test_must_fail git pop stash@{1} && + test_must_fail git apply stash@{1} && + test_must_fail git show stash@{1} && + test_must_fail git branch tmp stash@{1} && + git stash drop +' + +test_expect_success 'stash branch should not drop the stash if the branch exists' ' + git stash clear && + echo foo >file && + git add file && + git commit -m initial && + echo bar >file && + git stash && + test_must_fail git stash branch master stash@{0} && + git rev-parse stash@{0} -- +' + test_done diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index f37e3bc6ec..d1819ca23a 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -3,7 +3,7 @@ test_description='git checkout --patch' . ./lib-patch-mode.sh -test_expect_success 'setup' ' +test_expect_success PERL 'setup' ' mkdir dir && echo parent > dir/foo && echo dummy > bar && @@ -19,14 +19,14 @@ test_expect_success 'setup' ' # note: bar sorts before dir, so the first 'n' is always to skip 'bar' -test_expect_success 'saying "n" does nothing' ' +test_expect_success PERL 'saying "n" does nothing' ' 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 ' -test_expect_success 'git stash -p' ' +test_expect_success PERL 'git stash -p' ' (echo n; echo y) | git stash save -p && verify_state dir/foo head index && verify_saved_state bar && @@ -36,7 +36,7 @@ test_expect_success 'git stash -p' ' verify_state bar dummy dummy ' -test_expect_success 'git stash -p --no-keep-index' ' +test_expect_success PERL 'git stash -p --no-keep-index' ' set_state dir/foo work index && set_state bar bar_work bar_index && (echo n; echo y) | git stash save -p --no-keep-index && @@ -48,7 +48,7 @@ test_expect_success 'git stash -p --no-keep-index' ' verify_state bar dummy bar_index ' -test_expect_success 'none of this moved HEAD' ' +test_expect_success PERL 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index 18695ce821..73441a5165 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -135,7 +135,7 @@ cmp_diff_files_output () { # filesystem. sed <"$2" >.test-tmp \ -e '/^:000000 /d;s/'$x40'\( [MCRNDU][0-9]*\) /'$z40'\1 /' && - diff "$1" .test-tmp + test_cmp "$1" .test-tmp } test_expect_success \ diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index a4da1196a9..92a65f4852 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -12,13 +12,7 @@ by an edit for them. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - -test_expect_success \ +test_expect_success SYMLINKS \ 'prepare reference tree' \ 'echo xyzzy | tr -d '\\\\'012 >yomin && ln -s xyzzy frotz && @@ -26,7 +20,7 @@ test_expect_success \ tree=$(git write-tree) && echo $tree' -test_expect_success \ +test_expect_success SYMLINKS \ 'prepare work tree' \ 'mv frotz rezrov && rm -f yomin && @@ -40,8 +34,9 @@ test_expect_success \ # rezrov and nitfol are rename/copy of frotz and bozbar should be # a new creation. -GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current -cat >expected <<\EOF +test_expect_success SYMLINKS 'setup diff output' " + GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current && + cat >expected <<\EOF diff --git a/bozbar b/bozbar new file mode 120000 --- /dev/null @@ -65,8 +60,9 @@ deleted file mode 100644 -xyzzy \ No newline at end of file EOF +" -test_expect_success \ +test_expect_success SYMLINKS \ 'validate diff output' \ 'compare_diff_patch current expected' diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index d7e327cc5b..6f6948925f 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,12 +9,6 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - cat > expected << EOF diff --git a/frotz b/frotz new file mode 120000 @@ -26,7 +20,7 @@ index 0000000..7c465af \ No newline at end of file EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'diff new symlink' \ 'ln -s xyzzy frotz && git update-index && @@ -35,7 +29,7 @@ test_expect_success \ GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current && compare_diff_patch current expected' -test_expect_success \ +test_expect_success SYMLINKS \ 'diff unchanged symlink' \ 'tree=$(git write-tree) && git update-index frotz && @@ -52,9 +46,9 @@ index 7c465af..0000000 \ No newline at end of file EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'diff removed symlink' \ - 'rm frotz && + 'mv frotz frotz2 && git diff-index -M -p $tree > current && compare_diff_patch current expected' @@ -62,10 +56,9 @@ cat > expected << EOF diff --git a/frotz b/frotz EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'diff identical, but newly created symlink' \ - 'sleep 3 && - ln -s xyzzy frotz && + 'ln -s xyzzy frotz && git diff-index -M -p $tree > current && compare_diff_patch current expected' @@ -81,14 +74,14 @@ index 7c465af..df1db54 120000 \ No newline at end of file EOF -test_expect_success \ +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 \ +test_expect_success SYMLINKS \ 'diff symlinks with non-existing targets' \ 'ln -s narf pinky && ln -s take\ over brain && diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index dae6358516..9a66520588 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -208,7 +208,11 @@ log -p --first-parent master log -m -p --first-parent master log -m -p master log -SF master +log -S F master log -SF -p master +log -GF master +log -GF -p master +log -GF -p --pickaxe-all master log --decorate --all log --decorate=full --all @@ -282,4 +286,8 @@ diff master master^ side diff --dirstat master~1 master~2 EOF +test_expect_success 'log -S requires an argument' ' + test_must_fail git log -S +' + test_done diff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ index 8dab4bf93e..1f0f9ad44b 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^ @@ -18,6 +18,9 @@ A U Thor (2): create mode 100644 file1 delete mode 100644 file2 +-- +g-i-t--v-e-r-s-i-o-n + From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:01:00 +0000 diff --git a/t/t4013/diff.log_-GF_-p_--pickaxe-all_master b/t/t4013/diff.log_-GF_-p_--pickaxe-all_master new file mode 100644 index 0000000000..d36f88098b --- /dev/null +++ b/t/t4013/diff.log_-GF_-p_--pickaxe-all_master @@ -0,0 +1,27 @@ +$ git log -GF -p --pickaxe-all master +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third + +diff --git a/dir/sub b/dir/sub +index 8422d40..cead32e 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -2,3 +2,5 @@ A + B + C + D ++E ++F +diff --git a/file1 b/file1 +new file mode 100644 +index 0000000..b1e6722 +--- /dev/null ++++ b/file1 +@@ -0,0 +1,3 @@ ++A ++B ++C +$ diff --git a/t/t4013/diff.log_-GF_-p_master b/t/t4013/diff.log_-GF_-p_master new file mode 100644 index 0000000000..9d93f2c23a --- /dev/null +++ b/t/t4013/diff.log_-GF_-p_master @@ -0,0 +1,18 @@ +$ git log -GF -p master +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third + +diff --git a/dir/sub b/dir/sub +index 8422d40..cead32e 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -2,3 +2,5 @@ A + B + C + D ++E ++F +$ diff --git a/t/t4013/diff.log_-GF_master b/t/t4013/diff.log_-GF_master new file mode 100644 index 0000000000..4c6708d2d0 --- /dev/null +++ b/t/t4013/diff.log_-GF_master @@ -0,0 +1,7 @@ +$ git log -GF master +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third +$ diff --git a/t/t4013/diff.log_-S_F_master b/t/t4013/diff.log_-S_F_master new file mode 100644 index 0000000000..978d2b4118 --- /dev/null +++ b/t/t4013/diff.log_-S_F_master @@ -0,0 +1,7 @@ +$ git log -S F master +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third +$ diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index d21c37f3a2..07bf6eb49d 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -12,24 +12,29 @@ test_expect_success setup ' for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file && cat file >elif && git add file elif && + test_tick && git commit -m Initial && git checkout -b side && for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file && test_chmod +x elif && + test_tick && git commit -m "Side changes #1" && for i in D E F; do echo "$i"; done >>file && git update-index file && + test_tick && git commit -m "Side changes #2" && git tag C2 && for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file && git update-index file && + test_tick && git commit -m "Side changes #3 with \\n backslash-n in it." && git checkout master && git diff-tree -p C2 | git apply --index && + test_tick && git commit -m "Master accepts moral equivalent of #2" ' @@ -51,6 +56,22 @@ test_expect_success "format-patch --ignore-if-in-upstream" ' ' +test_expect_success "format-patch doesn't consider merge commits" ' + + git checkout -b slave master && + echo "Another line" >>file && + test_tick && + git commit -am "Slave change #1" && + echo "Yet another line" >>file && + test_tick && + git commit -am "Slave change #2" && + git checkout -b merger master && + test_tick && + git merge --no-ff slave && + cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` && + test $cnt = 3 +' + test_expect_success "format-patch result applies" ' git checkout -b rebuild-0 master && @@ -613,4 +634,56 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' ' git format-patch --ignore-if-in-upstream HEAD ' +test_expect_success 'format-patch --signature' ' + git format-patch --stdout --signature="my sig" -1 >output && + grep "my sig" output +' + +test_expect_success 'format-patch with format.signature config' ' + git config format.signature "config sig" && + git format-patch --stdout -1 >output && + grep "config sig" output +' + +test_expect_success 'format-patch --signature overrides format.signature' ' + git config format.signature "config sig" && + git format-patch --stdout --signature="overrides" -1 >output && + ! grep "config sig" output && + grep "overrides" output +' + +test_expect_success 'format-patch --no-signature ignores format.signature' ' + git config format.signature "config sig" && + git format-patch --stdout --signature="my sig" --no-signature \ + -1 >output && + ! grep "config sig" output && + ! grep "my sig" output && + ! grep "^-- \$" output +' + +test_expect_success 'format-patch --signature --cover-letter' ' + git config --unset-all format.signature && + git format-patch --stdout --signature="my sig" --cover-letter \ + -1 >output && + grep "my sig" output && + test 2 = $(grep "my sig" output | wc -l) +' + +test_expect_success 'format.signature="" supresses signatures' ' + git config format.signature "" && + git format-patch --stdout -1 >output && + ! grep "^-- \$" output +' + +test_expect_success 'format-patch --no-signature supresses signatures' ' + git config --unset-all format.signature && + git format-patch --stdout --no-signature -1 >output && + ! grep "^-- \$" output +' + +test_expect_success 'format-patch --signature="" supresses signatures' ' + git format-patch --signature="" -1 >output && + ! grep "^-- \$" output +' + test_done diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 90f3342373..935d101fe8 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -352,6 +352,48 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: ' +test_expect_success 'check tabs as indentation (tab-in-indent: off)' ' + + git config core.whitespace "-tab-in-indent" && + echo " foo ();" > x && + git diff --check + +' + +test_expect_success 'check tabs as indentation (tab-in-indent: on)' ' + + git config core.whitespace "tab-in-indent" && + echo " foo ();" > x && + test_must_fail git diff --check + +' + +test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' ' + + git config core.whitespace "tab-in-indent" && + echo " foo ();" > x && + test_must_fail git diff --check + +' + +test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' ' + + git config core.whitespace "tab-in-indent,indent-with-non-tab" && + echo "foo ();" > x && + test_must_fail git diff --check + +' + +test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' ' + + git config --unset core.whitespace && + echo "x whitespace" > .gitattributes && + echo " foo ();" > x && + git diff --check && + rm -f .gitattributes + +' + test_expect_success 'line numbers in --check output are correct' ' echo "" > x && @@ -396,6 +438,43 @@ test_expect_success 'whitespace-only changes not reported' ' test_cmp expect actual ' +cat <<EOF >expect +diff --git a/x b/z +similarity index NUM% +rename from x +rename to z +index 380c32a..a97b785 100644 +EOF +test_expect_success 'whitespace-only changes reported across renames' ' + git reset --hard && + for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x && + git add x && + git commit -m "base" && + sed -e "5s/^/ /" x >z && + git rm x && + git add z && + git diff -w -M --cached | + sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual && + test_cmp expect actual +' + +cat >expected <<\EOF +diff --git a/empty b/void +similarity index 100% +rename from empty +rename to void +EOF + +test_expect_success 'rename empty' ' + git reset --hard && + >empty && + git add empty && + git commit -m empty && + git mv empty void && + git diff -w --cached -M >current && + test_cmp expected current +' + test_expect_success 'combined diff with autocrlf conversion' ' git reset --hard && diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index 55eb5f83f1..ab0c2f0574 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -13,12 +13,14 @@ P1='pathname with HT' P2='pathname with SP' P3='pathname with LF' -: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || { - say 'Your filesystem does not allow tabs in filenames, test skipped.' - test_done -} +if : 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" +then + test_set_prereq TABS_IN_FILENAMES +else + say 'Your filesystem does not allow tabs in filenames' +fi -test_expect_success setup ' +test_expect_success TABS_IN_FILENAMES setup ' echo P0.0 >"$P0.0" && echo P0.1 >"$P0.1" && echo P0.2 >"$P0.2" && @@ -38,6 +40,7 @@ test_expect_success setup ' : ' +test_expect_success TABS_IN_FILENAMES 'setup expected files' ' cat >expect <<\EOF rename pathname.1 => "Rpathname\twith HT.0" (100%) rename pathname.3 => "Rpathname\nwith LF.0" (100%) @@ -47,11 +50,14 @@ cat >expect <<\EOF rename pathname.0 => Rpathname.0 (100%) rename "pathname\twith HT.0" => Rpathname.1 (100%) EOF -test_expect_success 'git diff --summary -M HEAD' ' +' + +test_expect_success TABS_IN_FILENAMES 'git diff --summary -M HEAD' ' git diff --summary -M HEAD >actual && test_cmp expect actual ' +test_expect_success TABS_IN_FILENAMES 'setup expected files' ' cat >expect <<\EOF pathname.1 => "Rpathname\twith HT.0" | 0 pathname.3 => "Rpathname\nwith LF.0" | 0 @@ -62,7 +68,9 @@ cat >expect <<\EOF "pathname\twith HT.0" => Rpathname.1 | 0 7 files changed, 0 insertions(+), 0 deletions(-) EOF -test_expect_success 'git diff --stat -M HEAD' ' +' + +test_expect_success TABS_IN_FILENAMES 'git diff --stat -M HEAD' ' git diff --stat -M HEAD >actual && test_cmp expect actual ' diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 5b10e976a3..0a61b57b5f 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -32,13 +32,18 @@ EOF sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java -builtin_patterns="bibtex cpp html java objc pascal php python ruby tex" +builtin_patterns="bibtex cpp csharp fortran html java objc pascal php python ruby tex" for p in $builtin_patterns do test_expect_success "builtin $p pattern compiles" ' echo "*.java diff=$p" > .gitattributes && - ! ( git diff --no-index Beer.java Beer-correct.java 2>&1 | - grep "fatal" > /dev/null ) + ! { git diff --no-index Beer.java Beer-correct.java 2>&1 | + grep "fatal" > /dev/null; } + ' + test_expect_success "builtin $p wordRegex pattern compiles" ' + ! { git diff --no-index --word-diff \ + Beer.java Beer-correct.java 2>&1 | + grep "fatal" > /dev/null; } ' done diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh index 9bdf6596d8..5d20acf436 100755 --- a/t/t4023-diff-rename-typechange.sh +++ b/t/t4023-diff-rename-typechange.sh @@ -4,13 +4,7 @@ test_description='typechange rename detection' . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - -test_expect_success setup ' +test_expect_success SYMLINKS setup ' rm -f foo bar && cat "$TEST_DIRECTORY"/../COPYING >foo && @@ -56,7 +50,7 @@ test_expect_success setup ' ' -test_expect_success 'cross renames to be detected for regular files' ' +test_expect_success SYMLINKS 'cross renames to be detected for regular files' ' git diff-tree five six -r --name-status -B -M | sort >actual && { @@ -67,7 +61,7 @@ test_expect_success 'cross renames to be detected for regular files' ' ' -test_expect_success 'cross renames to be detected for typechange' ' +test_expect_success SYMLINKS 'cross renames to be detected for typechange' ' git diff-tree one two -r --name-status -B -M | sort >actual && { @@ -78,7 +72,7 @@ test_expect_success 'cross renames to be detected for typechange' ' ' -test_expect_success 'moves and renames' ' +test_expect_success SYMLINKS 'moves and renames' ' git diff-tree three four -r --name-status -B -M | sort >actual && { diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 83c1914771..d99814ac64 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -103,7 +103,78 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' git diff HEAD >actual && sed -e "1,/^@@/d" actual >actual.body && expect_from_to >expect.body $subprev $subprev-dirty && - test_cmp expect.body actual.body + test_cmp expect.body actual.body && + git diff --ignore-submodules HEAD >actual2 && + ! test -s actual2 && + git diff --ignore-submodules=untracked HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git diff --ignore-submodules=dirty HEAD >actual4 && + ! test -s actual4 +' + +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.git/config]' ' + git config diff.ignoreSubmodules all && + git diff HEAD >actual && + ! test -s actual && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff HEAD --ignore-submodules=none >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' ' + git config diff.ignoreSubmodules dirty && + git diff HEAD >actual && + ! test -s actual && + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git config -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + git config --unset diff.ignoreSubmodules && + rm .gitmodules ' test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' ' @@ -129,7 +200,110 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)' git diff HEAD >actual && sed -e "1,/^@@/d" actual >actual.body && expect_from_to >expect.body $subprev $subprev-dirty && - test_cmp expect.body actual.body + test_cmp expect.body actual.body && + git diff --ignore-submodules=all HEAD >actual2 && + ! test -s actual2 && + git diff --ignore-submodules=untracked HEAD >actual3 && + ! test -s actual3 && + git diff --ignore-submodules=dirty HEAD >actual4 && + ! test -s actual4 +' + +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.git/config]' ' + git config submodule.subname.ignore all && + git config submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff --ignore-submodules=none HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname +' + +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.gitmodules]' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + +test_expect_success 'git diff between submodule commits' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules HEAD^..HEAD >actual && + ! test -s actual +' + +test_expect_success 'git diff between submodule commits [.git/config]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname +' + +test_expect_success 'git diff between submodule commits [.gitmodules]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules ' test_expect_success 'git diff (empty submodule dir)' ' diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 2e2e103b31..6f7548c3a1 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -55,6 +55,93 @@ test_expect_success 'word diff with runs of whitespace' ' ' +test_expect_success '--word-diff=color' ' + + word_diff --word-diff=color + +' + +test_expect_success '--color --word-diff=color' ' + + word_diff --color --word-diff=color + +' + +sed 's/#.*$//' > expect <<EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +-h(4) ++h(4),hh[44] +~ + # significant space +~ + a = b + c +~ +~ ++aa = a +~ +~ ++aeff = aeff * ( aaa ) +~ +EOF + +test_expect_success '--word-diff=porcelain' ' + + word_diff --word-diff=porcelain + +' + +cat > expect <<EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +[-h(4)-]{+h(4),hh[44]+} + +a = b + c + +{+aa = a+} + +{+aeff = aeff * ( aaa )+} +EOF + +test_expect_success '--word-diff=plain' ' + + word_diff --word-diff=plain + +' + +test_expect_success '--word-diff=plain --no-color' ' + + word_diff --word-diff=plain --no-color + +' + +cat > expect <<EOF +<WHITE>diff --git a/pre b/post<RESET> +<WHITE>index 330b04f..5ed8eff 100644<RESET> +<WHITE>--- a/pre<RESET> +<WHITE>+++ b/post<RESET> +<CYAN>@@ -1,3 +1,7 @@<RESET> +<RED>[-h(4)-]<RESET><GREEN>{+h(4),hh[44]+}<RESET> + +a = b + c<RESET> + +<GREEN>{+aa = a+}<RESET> + +<GREEN>{+aeff = aeff * ( aaa )+}<RESET> +EOF + +test_expect_success '--word-diff=plain --color' ' + + word_diff --word-diff=plain --color + +' + cat > expect <<\EOF <WHITE>diff --git a/pre b/post<RESET> <WHITE>index 330b04f..5ed8eff 100644<RESET> @@ -143,6 +230,25 @@ test_expect_success 'command-line overrides config' ' word_diff --color-words="[a-z]+" ' +cat > expect <<\EOF +<WHITE>diff --git a/pre b/post<RESET> +<WHITE>index 330b04f..5ed8eff 100644<RESET> +<WHITE>--- a/pre<RESET> +<WHITE>+++ b/post<RESET> +<CYAN>@@ -1,3 +1,7 @@<RESET> +h(4),<GREEN>{+hh+}<RESET>[44] + +a = b + c<RESET> + +<GREEN>{+aa = a+}<RESET> + +<GREEN>{+aeff = aeff * ( aaa+}<RESET> ) +EOF + +test_expect_success 'command-line overrides config: --word-diff-regex' ' + word_diff --color --word-diff-regex="[a-z]+" +' + cp expect.non-whitespace-is-word expect test_expect_success '.gitattributes override config' ' @@ -209,4 +315,20 @@ test_expect_success 'test when words are only removed at the end' ' ' +cat > expect <<\EOF +diff --git a/pre b/post +index 289cb9d..2d06f37 100644 +--- a/pre ++++ b/post +@@ -1 +1 @@ +-(: ++( +EOF + +test_expect_success '--word-diff=none' ' + + word_diff --word-diff=plain --word-diff=none + +' + test_done diff --git a/t/t4041-diff-submodule.sh b/t/t4041-diff-submodule-option.sh index 019acb926d..995bdfafec 100755 --- a/t/t4041-diff-submodule.sh +++ b/t/t4041-diff-submodule-option.sh @@ -85,10 +85,11 @@ EOF " commit_file sm1 && -cd sm1 && -git reset --hard HEAD~2 >/dev/null && -head3=$(git rev-parse --verify HEAD | cut -c1-7) && -cd .. +head3=$( + cd sm1 && + git reset --hard HEAD~2 >/dev/null && + git rev-parse --verify HEAD | cut -c1-7 +) test_expect_success 'modified submodule(backward)' " git diff-index -p --submodule=log HEAD >actual && @@ -205,6 +206,21 @@ Submodule sm1 contains untracked content EOF " +test_expect_success 'submodule contains untracked content (untracked ignored)' " + git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && + ! test -s actual +" + +test_expect_success 'submodule contains untracked content (dirty ignored)' " + git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && + ! test -s actual +" + +test_expect_success 'submodule contains untracked content (all ignored)' " + git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual && + ! test -s actual +" + test_expect_success 'submodule contains untracked and modifed content' " echo new > sm1/foo6 && git diff-index -p --submodule=log HEAD >actual && @@ -214,6 +230,26 @@ Submodule sm1 contains modified content EOF " +test_expect_success 'submodule contains untracked and modifed content (untracked ignored)' " + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 contains modified content +EOF +" + +test_expect_success 'submodule contains untracked and modifed content (dirty ignored)' " + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && + ! test -s actual +" + +test_expect_success 'submodule contains untracked and modifed content (all ignored)' " + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules --submodule=log HEAD >actual && + ! test -s actual +" + test_expect_success 'submodule contains modifed content' " rm -f sm1/new-file && git diff-index -p --submodule=log HEAD >actual && @@ -242,6 +278,27 @@ Submodule sm1 $head6..$head8: EOF " +test_expect_success 'modified submodule contains untracked content (untracked ignored)' " + git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6..$head8: + > change +EOF +" + +test_expect_success 'modified submodule contains untracked content (dirty ignored)' " + git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6..$head8: + > change +EOF +" + +test_expect_success 'modified submodule contains untracked content (all ignored)' " + git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual && + ! test -s actual +" + test_expect_success 'modified submodule contains untracked and modifed content' " echo modification >> sm1/foo6 && git diff-index -p --submodule=log HEAD >actual && @@ -253,6 +310,31 @@ Submodule sm1 $head6..$head8: EOF " +test_expect_success 'modified submodule contains untracked and modifed content (untracked ignored)' " + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 contains modified content +Submodule sm1 $head6..$head8: + > change +EOF +" + +test_expect_success 'modified submodule contains untracked and modifed content (dirty ignored)' " + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6..$head8: + > change +EOF +" + +test_expect_success 'modified submodule contains untracked and modifed content (all ignored)' " + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules --submodule=log HEAD >actual && + ! test -s actual +" + test_expect_success 'modified submodule contains modifed content' " rm -f sm1/new-file && git diff-index -p --submodule=log HEAD >actual && diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh new file mode 100755 index 0000000000..91f8198f05 --- /dev/null +++ b/t/t4042-diff-textconv-caching.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +test_description='test textconv caching' +. ./test-lib.sh + +cat >helper <<'EOF' +#!/bin/sh +sed 's/^/converted: /' "$@" >helper.out +cat helper.out +EOF +chmod +x helper + +test_expect_success 'setup' ' + echo foo content 1 >foo.bin && + echo bar content 1 >bar.bin && + git add . && + git commit -m one && + echo foo content 2 >foo.bin && + echo bar content 2 >bar.bin && + git commit -a -m two && + echo "*.bin diff=magic" >.gitattributes && + git config diff.magic.textconv ./helper && + git config diff.magic.cachetextconv true +' + +cat >expect <<EOF +diff --git a/bar.bin b/bar.bin +index fcf9166..28283d5 100644 +--- a/bar.bin ++++ b/bar.bin +@@ -1 +1 @@ +-converted: bar content 1 ++converted: bar content 2 +diff --git a/foo.bin b/foo.bin +index d5b9fe3..1345db2 100644 +--- a/foo.bin ++++ b/foo.bin +@@ -1 +1 @@ +-converted: foo content 1 ++converted: foo content 2 +EOF + +test_expect_success 'first textconv works' ' + git diff HEAD^ HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'cached textconv produces same output' ' + git diff HEAD^ HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'cached textconv does not run helper' ' + rm -f helper.out && + git diff HEAD^ HEAD >actual && + test_cmp expect actual && + ! test -r helper.out +' + +cat >expect <<EOF +diff --git a/bar.bin b/bar.bin +index fcf9166..28283d5 100644 +--- a/bar.bin ++++ b/bar.bin +@@ -1,2 +1,2 @@ + converted: other +-converted: bar content 1 ++converted: bar content 2 +diff --git a/foo.bin b/foo.bin +index d5b9fe3..1345db2 100644 +--- a/foo.bin ++++ b/foo.bin +@@ -1,2 +1,2 @@ + converted: other +-converted: foo content 1 ++converted: foo content 2 +EOF +test_expect_success 'changing textconv invalidates cache' ' + echo other >other && + git config diff.magic.textconv "./helper other" && + git diff HEAD^ HEAD >actual && + test_cmp expect actual +' + +cat >expect <<EOF +diff --git a/bar.bin b/bar.bin +index fcf9166..28283d5 100644 +--- a/bar.bin ++++ b/bar.bin +@@ -1,2 +1,2 @@ + converted: other +-converted: bar content 1 ++converted: bar content 2 +diff --git a/foo.bin b/foo.bin +index d5b9fe3..1345db2 100644 +--- a/foo.bin ++++ b/foo.bin +@@ -1 +1 @@ +-converted: foo content 1 ++converted: foo content 2 +EOF +test_expect_success 'switching diff driver produces correct results' ' + git config diff.moremagic.textconv ./helper && + echo foo.bin diff=moremagic >>.gitattributes && + git diff HEAD^ HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4043-diff-rename-binary.sh b/t/t4043-diff-rename-binary.sh new file mode 100755 index 0000000000..06012811a1 --- /dev/null +++ b/t/t4043-diff-rename-binary.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Copyright (c) 2010 Jakub Narebski, Christian Couder +# + +test_description='Move a binary file' + +. ./test-lib.sh + + +test_expect_success 'prepare repository' ' + git init && + echo foo > foo && + echo "barQ" | q_to_nul > bar && + git add . && + git commit -m "Initial commit" +' + +test_expect_success 'move the files into a "sub" directory' ' + mkdir sub && + git mv bar foo sub/ && + git commit -m "Moved to sub/" +' + +cat > expected <<\EOF + bar => sub/bar | Bin 5 -> 5 bytes + foo => sub/foo | 0 + 2 files changed, 0 insertions(+), 0 deletions(-) + +diff --git a/bar b/sub/bar +similarity index 100% +rename from bar +rename to sub/bar +diff --git a/foo b/sub/foo +similarity index 100% +rename from foo +rename to sub/foo +EOF + +test_expect_success 'git show -C -C report renames' ' + git show -C -C --raw --binary --stat | tail -n 12 > current && + test_cmp expected current +' + +test_done diff --git a/t/t4044-diff-index-unique-abbrev.sh b/t/t4044-diff-index-unique-abbrev.sh new file mode 100755 index 0000000000..d5ce72be63 --- /dev/null +++ b/t/t4044-diff-index-unique-abbrev.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +test_description='test unique sha1 abbreviation on "index from..to" line' +. ./test-lib.sh + +cat >expect_initial <<EOF +100644 blob 51d2738463ea4ca66f8691c91e33ce64b7d41bb1 foo +EOF + +cat >expect_update <<EOF +100644 blob 51d2738efb4ad8a1e40bed839ab8e116f0a15e47 foo +EOF + +test_expect_success 'setup' ' + echo 4827 > foo && + git add foo && + git commit -m "initial" && + git cat-file -p HEAD: > actual && + test_cmp expect_initial actual && + echo 11742 > foo && + git commit -a -m "update" && + git cat-file -p HEAD: > actual && + test_cmp expect_update actual +' + +cat >expect <<EOF +index 51d27384..51d2738e 100644 +EOF + +test_expect_success 'diff does not produce ambiguous index line' ' + git diff HEAD^..HEAD | grep index > actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh new file mode 100755 index 0000000000..8a3c63b9e2 --- /dev/null +++ b/t/t4045-diff-relative.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='diff --relative tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + git commit --allow-empty -m empty && + echo content >file1 && + mkdir subdir && + echo other content >subdir/file2 && + git add . && + git commit -m one +' + +check_diff() { +expect=$1; shift +cat >expected <<EOF +diff --git a/$expect b/$expect +new file mode 100644 +index 0000000..25c05ef +--- /dev/null ++++ b/$expect +@@ -0,0 +1 @@ ++other content +EOF +test_expect_success "-p $*" " + git diff -p $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_stat() { +expect=$1; shift +cat >expected <<EOF + $expect | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) +EOF +test_expect_success "--stat $*" " + git diff --stat $* HEAD^ >actual && + test_cmp expected actual +" +} + +check_raw() { +expect=$1; shift +cat >expected <<EOF +:000000 100644 0000000000000000000000000000000000000000 25c05ef3639d2d270e7fe765a67668f098092bc5 A $expect +EOF +test_expect_success "--raw $*" " + git diff --no-abbrev --raw $* HEAD^ >actual && + test_cmp expected actual +" +} + +for type in diff stat raw; do + check_$type file2 --relative=subdir/ + check_$type file2 --relative=subdir + check_$type dir/file2 --relative=sub +done + +test_done diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh index 1597965241..e3ea3d5114 100755 --- a/t/t4102-apply-rename.sh +++ b/t/t4102-apply-rename.sh @@ -7,6 +7,7 @@ test_description='git apply handling copy/rename patch. ' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh # setup @@ -31,13 +32,6 @@ test_expect_success setup \ test_expect_success apply \ 'git apply --index --stat --summary --apply test-patch' -if test "$(git config --bool core.filemode)" = false -then - say 'filemode disabled on the filesystem' -else - test_set_prereq FILEMODE -fi - test_expect_success FILEMODE validate \ 'test -f bar && ls -l bar | grep "^-..x......"' diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh new file mode 100755 index 0000000000..a52d94ae21 --- /dev/null +++ b/t/t4111-apply-subdir.sh @@ -0,0 +1,142 @@ +#!/bin/sh + +test_description='patching from inconvenient places' + +. ./test-lib.sh + +test_expect_success 'setup' ' + cat >patch <<-\EOF && + diff file.orig file + --- a/file.orig + +++ b/file + @@ -1 +1,2 @@ + 1 + +2 + EOF + patch="$(pwd)/patch" && + + echo 1 >preimage && + printf "%s\n" 1 2 >postimage && + echo 3 >other && + + test_tick && + git commit --allow-empty -m basis +' + +test_expect_success 'setup: subdir' ' + reset_subdir() { + git reset && + mkdir -p sub/dir/b && + mkdir -p objects && + cp "$1" file && + cp "$1" objects/file && + cp "$1" sub/dir/file && + cp "$1" sub/dir/b/file && + git add file sub/dir/file sub/dir/b/file objects/file && + cp "$2" file && + cp "$2" sub/dir/file && + cp "$2" sub/dir/b/file && + cp "$2" objects/file && + test_might_fail git update-index --refresh -q + } +' + +test_expect_success 'apply from subdir of toplevel' ' + cp postimage expected && + reset_subdir other preimage && + ( + cd sub/dir && + git apply "$patch" + ) && + test_cmp expected sub/dir/file +' + +test_expect_success 'apply --cached from subdir of toplevel' ' + cp postimage expected && + cp other expected.working && + reset_subdir preimage other && + ( + cd sub/dir && + git apply --cached "$patch" + ) && + git show :sub/dir/file >actual && + test_cmp expected actual && + test_cmp expected.working sub/dir/file +' + +test_expect_success 'apply --index from subdir of toplevel' ' + cp postimage expected && + reset_subdir preimage other && + ( + cd sub/dir && + test_must_fail git apply --index "$patch" + ) && + reset_subdir other preimage && + ( + cd sub/dir && + test_must_fail git apply --index "$patch" + ) && + reset_subdir preimage preimage && + ( + cd sub/dir && + git apply --index "$patch" + ) && + git show :sub/dir/file >actual && + test_cmp expected actual && + test_cmp expected sub/dir/file +' + +test_expect_success 'apply from .git dir' ' + cp postimage expected && + cp preimage .git/file && + cp preimage .git/objects/file + ( + cd .git && + git apply "$patch" + ) && + test_cmp expected .git/file +' + +test_expect_success 'apply from subdir of .git dir' ' + cp postimage expected && + cp preimage .git/file && + cp preimage .git/objects/file + ( + cd .git/objects && + git apply "$patch" + ) && + test_cmp expected .git/objects/file +' + +test_expect_success 'apply --cached from .git dir' ' + cp postimage expected && + cp other expected.working && + cp other .git/file && + reset_subdir preimage other && + ( + cd .git && + git apply --cached "$patch" + ) && + git show :file >actual && + test_cmp expected actual && + test_cmp expected.working file && + test_cmp expected.working .git/file +' + +test_expect_success 'apply --cached from subdir of .git dir' ' + cp postimage expected && + cp preimage expected.subdir && + cp other .git/file && + cp other .git/objects/file && + reset_subdir preimage other && + ( + cd .git/objects && + git apply --cached "$patch" + ) && + git show :file >actual && + git show :objects/file >actual.subdir && + test_cmp expected actual && + test_cmp expected.subdir actual.subdir +' + +test_done diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index 99ec13dd53..f12826fb09 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -9,13 +9,7 @@ test_description='git apply should not get confused with type changes. . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - -test_expect_success 'setup repository and commits' ' +test_expect_success SYMLINKS 'setup repository and commits' ' echo "hello world" > foo && echo "hi planet" > bar && git update-index --add foo bar && @@ -48,7 +42,7 @@ test_expect_success 'setup repository and commits' ' git branch foo-baz-renamed-from-foo ' -test_expect_success 'file renamed from foo to foo/baz' ' +test_expect_success SYMLINKS 'file renamed from foo to foo/baz' ' git checkout -f initial && git diff-tree -M -p HEAD foo-baz-renamed-from-foo > patch && git apply --index < patch @@ -56,7 +50,7 @@ test_expect_success 'file renamed from foo to foo/baz' ' test_debug 'cat patch' -test_expect_success 'file renamed from foo/baz to foo' ' +test_expect_success SYMLINKS 'file renamed from foo/baz to foo' ' git checkout -f foo-baz-renamed-from-foo && git diff-tree -M -p HEAD initial > patch && git apply --index < patch @@ -64,7 +58,7 @@ test_expect_success 'file renamed from foo/baz to foo' ' test_debug 'cat patch' -test_expect_success 'directory becomes file' ' +test_expect_success SYMLINKS 'directory becomes file' ' git checkout -f foo-becomes-a-directory && git diff-tree -p HEAD initial > patch && git apply --index < patch @@ -72,7 +66,7 @@ test_expect_success 'directory becomes file' ' test_debug 'cat patch' -test_expect_success 'file becomes directory' ' +test_expect_success SYMLINKS 'file becomes directory' ' git checkout -f initial && git diff-tree -p HEAD foo-becomes-a-directory > patch && git apply --index < patch @@ -80,7 +74,7 @@ test_expect_success 'file becomes directory' ' test_debug 'cat patch' -test_expect_success 'file becomes symlink' ' +test_expect_success SYMLINKS 'file becomes symlink' ' git checkout -f initial && git diff-tree -p HEAD foo-symlinked-to-bar > patch && git apply --index < patch @@ -88,21 +82,21 @@ test_expect_success 'file becomes symlink' ' test_debug 'cat patch' -test_expect_success 'symlink becomes file' ' +test_expect_success SYMLINKS 'symlink becomes file' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p HEAD foo-back-to-file > patch && git apply --index < patch ' test_debug 'cat patch' -test_expect_success 'binary file becomes symlink' ' +test_expect_success SYMLINKS 'binary file becomes symlink' ' git checkout -f foo-becomes-binary && git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch && git apply --index < patch ' test_debug 'cat patch' -test_expect_success 'symlink becomes binary file' ' +test_expect_success SYMLINKS 'symlink becomes binary file' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p --binary HEAD foo-becomes-binary > patch && git apply --index < patch @@ -110,7 +104,7 @@ test_expect_success 'symlink becomes binary file' ' test_debug 'cat patch' -test_expect_success 'symlink becomes directory' ' +test_expect_success SYMLINKS 'symlink becomes directory' ' git checkout -f foo-symlinked-to-bar && git diff-tree -p HEAD foo-becomes-a-directory > patch && git apply --index < patch @@ -118,7 +112,7 @@ test_expect_success 'symlink becomes directory' ' test_debug 'cat patch' -test_expect_success 'directory becomes symlink' ' +test_expect_success SYMLINKS 'directory becomes symlink' ' git checkout -f foo-becomes-a-directory && git diff-tree -p HEAD foo-symlinked-to-bar > patch && git apply --index < patch diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index b852e58980..7674dd2ec9 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -9,13 +9,7 @@ test_description='git apply symlinks and partial files . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - -test_expect_success setup ' +test_expect_success SYMLINKS setup ' ln -s path1/path2/path3/path4/path5 link1 && git add link? && @@ -34,7 +28,7 @@ test_expect_success setup ' ' -test_expect_success 'apply symlink patch' ' +test_expect_success SYMLINKS 'apply symlink patch' ' git checkout side && git apply patch && @@ -43,7 +37,7 @@ test_expect_success 'apply symlink patch' ' ' -test_expect_success 'apply --index symlink patch' ' +test_expect_success SYMLINKS 'apply --index symlink patch' ' git checkout -f side && git apply --index patch && diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh index b463b4f05c..2b2d00b334 100755 --- a/t/t4120-apply-popt.sh +++ b/t/t4120-apply-popt.sh @@ -10,21 +10,50 @@ test_description='git apply -p handling.' test_expect_success setup ' mkdir sub && echo A >sub/file1 && - cp sub/file1 file1 && + cp sub/file1 file1.saved && git add sub/file1 && echo B >sub/file1 && git diff >patch.file && - rm sub/file1 && - rmdir sub + git checkout -- sub/file1 && + git mv sub süb && + echo B >süb/file1 && + git diff >patch.escaped && + grep "[\]" patch.escaped && + rm süb/file1 && + rmdir süb ' test_expect_success 'apply git diff with -p2' ' + cp file1.saved file1 && git apply -p2 patch.file ' test_expect_success 'apply with too large -p' ' + cp file1.saved file1 && test_must_fail git apply --stat -p3 patch.file 2>err && grep "removing 3 leading" err ' +test_expect_success 'apply (-p2) traditional diff with funny filenames' ' + cat >patch.quotes <<-\EOF && + diff -u "a/"sub/file1 "b/"sub/file1 + --- "a/"sub/file1 + +++ "b/"sub/file1 + @@ -1 +1 @@ + -A + +B + EOF + echo B >expected && + + cp file1.saved file1 && + git apply -p2 patch.quotes && + test_cmp expected file1 +' + +test_expect_success 'apply with too large -p and fancy filename' ' + cp file1.saved file1 && + test_must_fail git apply --stat -p3 patch.escaped 2>err && + grep "removing 3 leading" err +' + test_done diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 0d3c1d5dd5..39407376ba 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -3,12 +3,6 @@ test_description='apply to deeper directory without getting fooled with symlink' . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - lecho () { for l_ do @@ -16,7 +10,7 @@ lecho () { done } -test_expect_success setup ' +test_expect_success SYMLINKS setup ' mkdir -p arch/i386/boot arch/x86_64 && lecho 1 2 3 4 5 >arch/i386/boot/Makefile && @@ -37,7 +31,7 @@ test_expect_success setup ' ' -test_expect_success apply ' +test_expect_success SYMLINKS apply ' git checkout test && git diff --exit-code test && @@ -46,7 +40,7 @@ test_expect_success apply ' ' -test_expect_success 'check result' ' +test_expect_success SYMLINKS 'check result' ' git diff --exit-code master && git diff --exit-code --cached master && diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh index fb9ad247bf..8a676a5dcd 100755 --- a/t/t4124-apply-ws-rule.sh +++ b/t/t4124-apply-ws-rule.sh @@ -11,21 +11,22 @@ prepare_test_file () { # ! trailing-space # @ space-before-tab # # indent-with-non-tab + # % tab-in-indent sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF An_SP in an ordinary line>and a HT. - >A HT. - _>A SP and a HT (@). - _>_A SP, a HT and a SP (@). + >A HT (%). + _>A SP and a HT (@%). + _>_A SP, a HT and a SP (@%). _______Seven SP. ________Eight SP (#). - _______>Seven SP and a HT (@). - ________>Eight SP and a HT (@#). - _______>_Seven SP, a HT and a SP (@). - ________>_Eight SP, a HT and a SP (@#). + _______>Seven SP and a HT (@%). + ________>Eight SP and a HT (@#%). + _______>_Seven SP, a HT and a SP (@%). + ________>_Eight SP, a HT and a SP (@#%). _______________Fifteen SP (#). - _______________>Fifteen SP and a HT (@#). + _______________>Fifteen SP and a HT (@#%). ________________Sixteen SP (#). - ________________>Sixteen SP and a HT (@#). + ________________>Sixteen SP and a HT (@#%). _____a__Five SP, a non WS, two SP. A line with a (!) trailing SP_ A line with a (!) trailing HT> @@ -39,12 +40,11 @@ apply_patch () { } test_fix () { - # fix should not barf apply_patch --whitespace=fix || return 1 # find touched lines - diff file target | sed -n -e "s/^> //p" >fixed + $DIFF file target | sed -n -e "s/^> //p" >fixed # the changed lines are all expeced to change fixed_cnt=$(wc -l <fixed) @@ -85,14 +85,14 @@ test_expect_success setup ' test_expect_success 'whitespace=nowarn, default rule' ' apply_patch --whitespace=nowarn && - diff file target + test_cmp file target ' test_expect_success 'whitespace=warn, default rule' ' apply_patch --whitespace=warn && - diff file target + test_cmp file target ' @@ -108,7 +108,7 @@ test_expect_success 'whitespace=error-all, no rule' ' git config core.whitespace -trailing,-space-before,-indent && apply_patch --whitespace=error-all && - diff file target + test_cmp file target ' @@ -117,7 +117,7 @@ test_expect_success 'whitespace=error-all, no rule (attribute)' ' git config --unset core.whitespace && echo "target -whitespace" >.gitattributes && apply_patch --whitespace=error-all && - diff file target + test_cmp file target ' @@ -130,20 +130,25 @@ do for i in - '' do case "$i" in '') ti='#' ;; *) ti= ;; esac - rule=${t}trailing,${s}space,${i}indent - - rm -f .gitattributes - test_expect_success "rule=$rule" ' - git config core.whitespace "$rule" && - test_fix "$tt$ts$ti" - ' - - test_expect_success "rule=$rule (attributes)" ' - git config --unset core.whitespace && - echo "target whitespace=$rule" >.gitattributes && - test_fix "$tt$ts$ti" - ' - + for h in - '' + do + [ -z "$h$i" ] && continue + case "$h" in '') th='%' ;; *) th= ;; esac + rule=${t}trailing,${s}space,${i}indent,${h}tab + + rm -f .gitattributes + test_expect_success "rule=$rule" ' + git config core.whitespace "$rule" && + test_fix "$tt$ts$ti$th" + ' + + test_expect_success "rule=$rule (attributes)" ' + git config --unset core.whitespace && + echo "target whitespace=$rule" >.gitattributes && + test_fix "$tt$ts$ti$th" + ' + + done done done done @@ -325,6 +330,18 @@ test_expect_success 'two missing blank lines at end with --whitespace=fix' ' test_cmp one expect ' +test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' ' + { echo a; echo; } >one && + git add one && + { echo b; echo a; echo; } >one && + cp one expect && + git diff -- one >patch && + echo a >one && + test_must_fail git apply patch && + git apply --whitespace=fix patch && + test_cmp one expect +' + test_expect_success 'shrink file with tons of missing blanks at end of file' ' { echo a; echo b; echo c; } >one && cp one no-blank-lines && diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh index 3a8202ea93..77200c0b2d 100755 --- a/t/t4127-apply-same-fn.sh +++ b/t/t4127-apply-same-fn.sh @@ -27,7 +27,7 @@ test_expect_success 'apply same filename with independent changes' ' cp same_fn same_fn2 && git reset --hard && git apply patch0 && - diff same_fn same_fn2 + test_cmp same_fn same_fn2 ' test_expect_success 'apply same filename with overlapping changes' ' @@ -40,7 +40,7 @@ test_expect_success 'apply same filename with overlapping changes' ' cp same_fn same_fn2 && git reset --hard && git apply patch0 && - diff same_fn same_fn2 + test_cmp same_fn same_fn2 ' test_expect_success 'apply same new filename after rename' ' @@ -54,7 +54,7 @@ test_expect_success 'apply same new filename after rename' ' cp new_fn new_fn2 && git reset --hard && git apply --index patch1 && - diff new_fn new_fn2 + test_cmp new_fn new_fn2 ' test_expect_success 'apply same old filename after rename -- should fail.' ' diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh index fc7af04931..0d36ebdc86 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -3,13 +3,7 @@ test_description='applying patch with mode bits' . ./test-lib.sh - -if test "$(git config --bool core.filemode)" = false -then - say 'filemode disabled on the filesystem' -else - test_set_prereq FILEMODE -fi +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh test_expect_success setup ' echo original >file && diff --git a/t/t4134-apply-submodule.sh b/t/t4134-apply-submodule.sh new file mode 100755 index 0000000000..1b82f93cff --- /dev/null +++ b/t/t4134-apply-submodule.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# Copyright (c) 2010 Peter Collingbourne +# + +test_description='git apply submodule tests' + +. ./test-lib.sh + +test_expect_success setup ' + cat > create-sm.patch <<EOF +diff --git a/dir/sm b/dir/sm +new file mode 160000 +index 0000000..0123456 +--- /dev/null ++++ b/dir/sm +@@ -0,0 +1 @@ ++Subproject commit 0123456789abcdef0123456789abcdef01234567 +EOF + cat > remove-sm.patch <<EOF +diff --git a/dir/sm b/dir/sm +deleted file mode 160000 +index 0123456..0000000 +--- a/dir/sm ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit 0123456789abcdef0123456789abcdef01234567 +EOF +' + +test_expect_success 'removing a submodule also removes all leading subdirectories' ' + git apply --index create-sm.patch && + test -d dir/sm && + git apply --index remove-sm.patch && + test \! -d dir +' + +test_done diff --git a/t/t4135-apply-weird-filenames.sh b/t/t4135-apply-weird-filenames.sh new file mode 100755 index 0000000000..1e5aad57ab --- /dev/null +++ b/t/t4135-apply-weird-filenames.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +test_description='git apply with weird postimage filenames' + +. ./test-lib.sh + +test_expect_success 'setup' ' + vector=$TEST_DIRECTORY/t4135 && + + test_tick && + git commit --allow-empty -m preimage && + git tag preimage && + + reset_preimage() { + git checkout -f preimage^0 && + git read-tree -u --reset HEAD && + git update-index --refresh + } && + + test_when_finished "rm -f \"tab embedded.txt\"" && + test_when_finished "rm -f '\''\"quoteembedded\".txt'\''" && + if touch -- "tab embedded.txt" '\''"quoteembedded".txt'\'' + then + test_set_prereq FUNNYNAMES + fi +' + +try_filename() { + desc=$1 + postimage=$2 + prereq=${3:-} + exp1=${4:-success} + exp2=${5:-success} + exp3=${6:-success} + + test_expect_$exp1 $prereq "$desc, git-style file creation patch" " + echo postimage >expected && + reset_preimage && + rm -f '$postimage' && + git apply -v \"\$vector\"/'git-$desc.diff' && + test_cmp expected '$postimage' + " + + test_expect_$exp2 $prereq "$desc, traditional patch" " + echo postimage >expected && + reset_preimage && + echo preimage >'$postimage' && + git apply -v \"\$vector\"/'diff-$desc.diff' && + test_cmp expected '$postimage' + " + + test_expect_$exp3 $prereq "$desc, traditional file creation patch" " + echo postimage >expected && + reset_preimage && + rm -f '$postimage' && + git apply -v \"\$vector\"/'add-$desc.diff' && + test_cmp expected '$postimage' + " +} + +try_filename 'plain' 'postimage.txt' +try_filename 'with spaces' 'post image.txt' +try_filename 'with tab' 'post image.txt' FUNNYNAMES +try_filename 'with backslash' 'post\image.txt' BSLASHPSPEC +try_filename 'with quote' '"postimage".txt' FUNNYNAMES success failure success + +test_expect_success 'whitespace-damaged traditional patch' ' + echo postimage >expected && + reset_preimage && + rm -f postimage.txt && + git apply -v "$vector/damaged.diff" && + test_cmp expected postimage.txt +' + +test_done diff --git a/t/t4135/.gitignore b/t/t4135/.gitignore new file mode 100644 index 0000000000..3e58e65f57 --- /dev/null +++ b/t/t4135/.gitignore @@ -0,0 +1,3 @@ +/file-creation/ +/trad-creation/ +/trad-modification/ diff --git a/t/t4135/add-plain.diff b/t/t4135/add-plain.diff new file mode 100644 index 0000000000..cf5970a089 --- /dev/null +++ b/t/t4135/add-plain.diff @@ -0,0 +1,5 @@ +diff -pruN a/postimage.txt b/postimage.txt +--- a/postimage.txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/postimage.txt 2010-08-18 20:13:31.484002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/add-with backslash.diff b/t/t4135/add-with backslash.diff new file mode 100644 index 0000000000..c6861e1966 --- /dev/null +++ b/t/t4135/add-with backslash.diff @@ -0,0 +1,5 @@ +diff -pruN a/post\image.txt b/post\image.txt +--- a/post\image.txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/post\image.txt 2010-08-18 20:13:31.692002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/add-with quote.diff b/t/t4135/add-with quote.diff new file mode 100644 index 0000000000..866de78ca1 --- /dev/null +++ b/t/t4135/add-with quote.diff @@ -0,0 +1,5 @@ +diff -pruN a/"postimage".txt b/"postimage".txt +--- a/"postimage".txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/"postimage".txt 2010-08-18 20:13:31.756002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/add-with spaces.diff b/t/t4135/add-with spaces.diff new file mode 100644 index 0000000000..a9a1212a21 --- /dev/null +++ b/t/t4135/add-with spaces.diff @@ -0,0 +1,5 @@ +diff -pruN a/post image.txt b/post image.txt +--- a/post image.txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/post image.txt 2010-08-18 20:13:31.556002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/add-with tab.diff b/t/t4135/add-with tab.diff new file mode 100644 index 0000000000..bb67cb7930 --- /dev/null +++ b/t/t4135/add-with tab.diff @@ -0,0 +1,5 @@ +diff -pruN a/post image.txt b/post image.txt +--- a/post image.txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/post image.txt 2010-08-18 20:13:31.628002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/damaged.diff b/t/t4135/damaged.diff new file mode 100644 index 0000000000..68f7ededf9 --- /dev/null +++ b/t/t4135/damaged.diff @@ -0,0 +1,5 @@ +diff -pruN a/postimage.txt b/postimage.txt +--- a/postimage.txt 1969-12-31 18:00:00.000000000 -0600 ++++ b/postimage.txt 2010-08-18 20:13:31.484002255 -0500 +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/diff-plain.diff b/t/t4135/diff-plain.diff new file mode 100644 index 0000000000..acedcfa612 --- /dev/null +++ b/t/t4135/diff-plain.diff @@ -0,0 +1,5 @@ +--- postimage.txt.orig 2010-08-18 20:13:31.432002255 -0500 ++++ postimage.txt 2010-08-18 20:13:31.432002255 -0500 +@@ -1 +1 @@ +-preimage ++postimage diff --git a/t/t4135/diff-with backslash.diff b/t/t4135/diff-with backslash.diff new file mode 100644 index 0000000000..9068a61bd9 --- /dev/null +++ b/t/t4135/diff-with backslash.diff @@ -0,0 +1,5 @@ +--- post\image.txt.orig 2010-08-18 20:13:31.680002255 -0500 ++++ post\image.txt 2010-08-18 20:13:31.680002255 -0500 +@@ -1 +1 @@ +-preimage ++postimage diff --git a/t/t4135/diff-with quote.diff b/t/t4135/diff-with quote.diff new file mode 100644 index 0000000000..c8e8cc1a8d --- /dev/null +++ b/t/t4135/diff-with quote.diff @@ -0,0 +1,5 @@ +--- "postimage".txt.orig 2010-08-18 20:13:31.744002255 -0500 ++++ "postimage".txt 2010-08-18 20:13:31.744002255 -0500 +@@ -1 +1 @@ +-preimage ++postimage diff --git a/t/t4135/diff-with spaces.diff b/t/t4135/diff-with spaces.diff new file mode 100644 index 0000000000..3512056f21 --- /dev/null +++ b/t/t4135/diff-with spaces.diff @@ -0,0 +1,5 @@ +--- post image.txt.orig 2010-08-18 20:13:31.544002255 -0500 ++++ post image.txt 2010-08-18 20:13:31.544002255 -0500 +@@ -1 +1 @@ +-preimage ++postimage diff --git a/t/t4135/diff-with tab.diff b/t/t4135/diff-with tab.diff new file mode 100644 index 0000000000..4e6d9b2941 --- /dev/null +++ b/t/t4135/diff-with tab.diff @@ -0,0 +1,5 @@ +--- post image.txt.orig 2010-08-18 20:13:31.616002255 -0500 ++++ post image.txt 2010-08-18 20:13:31.616002255 -0500 +@@ -1 +1 @@ +-preimage ++postimage diff --git a/t/t4135/git-plain.diff b/t/t4135/git-plain.diff new file mode 100644 index 0000000000..db47d1a693 --- /dev/null +++ b/t/t4135/git-plain.diff @@ -0,0 +1,7 @@ +diff --git a/postimage.txt b/postimage.txt +new file mode 100644 +index 0000000..eff0c54 +--- /dev/null ++++ b/postimage.txt +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/git-with backslash.diff b/t/t4135/git-with backslash.diff new file mode 100644 index 0000000000..0e84a10e93 --- /dev/null +++ b/t/t4135/git-with backslash.diff @@ -0,0 +1,7 @@ +diff --git "a/post\\image.txt" "b/post\\image.txt" +new file mode 100644 +index 0000000..eff0c54 +--- /dev/null ++++ "b/post\\image.txt" +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/git-with quote.diff b/t/t4135/git-with quote.diff new file mode 100644 index 0000000000..bdbea8af35 --- /dev/null +++ b/t/t4135/git-with quote.diff @@ -0,0 +1,7 @@ +diff --git "a/\"postimage\".txt" "b/\"postimage\".txt" +new file mode 100644 +index 0000000..eff0c54 +--- /dev/null ++++ "b/\"postimage\".txt" +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/git-with spaces.diff b/t/t4135/git-with spaces.diff new file mode 100644 index 0000000000..baaa810de0 --- /dev/null +++ b/t/t4135/git-with spaces.diff @@ -0,0 +1,7 @@ +diff --git a/post image.txt b/post image.txt +new file mode 100644 +index 0000000..eff0c54 +--- /dev/null ++++ b/post image.txt +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/git-with tab.diff b/t/t4135/git-with tab.diff new file mode 100644 index 0000000000..cca3c9287b --- /dev/null +++ b/t/t4135/git-with tab.diff @@ -0,0 +1,7 @@ +diff --git "a/post\timage.txt" "b/post\timage.txt" +new file mode 100644 +index 0000000..eff0c54 +--- /dev/null ++++ "b/post\timage.txt" +@@ -0,0 +1 @@ ++postimage diff --git a/t/t4135/make-patches b/t/t4135/make-patches new file mode 100755 index 0000000000..f5f45ddd09 --- /dev/null +++ b/t/t4135/make-patches @@ -0,0 +1,45 @@ +#!/bin/sh + +do_filename() { + desc=$1 + postimage=$2 + + rm -fr file-creation && + git init file-creation && + ( + cd file-creation && + git commit --allow-empty -m init && + echo postimage >"$postimage" && + git add -N "$postimage" && + git diff HEAD >"../git-$desc.diff" + ) && + + rm -fr trad-modification && + mkdir trad-modification && + ( + cd trad-modification && + echo preimage >"$postimage.orig" && + echo postimage >"$postimage" && + ! diff -u "$postimage.orig" "$postimage" >"../diff-$desc.diff" + ) && + + rm -fr trad-creation && + mkdir trad-creation && + ( + cd trad-creation && + mkdir a b && + echo postimage >"b/$postimage" && + ! diff -pruN a b >"../add-$desc.diff" + ) +} + +do_filename plain postimage.txt && +do_filename 'with spaces' 'post image.txt' && +do_filename 'with tab' 'post image.txt' && +do_filename 'with backslash' 'post\image.txt' && +do_filename 'with quote' '"postimage".txt' && +expand add-plain.diff >damaged.diff || +{ + echo >&2 Failed. && + exit 1 +} diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 810b04b817..1c3d8ed548 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -4,66 +4,71 @@ test_description='git am running' . ./test-lib.sh -cat >msg <<EOF -second - -Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy -eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam -voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita -kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem -ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod -tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At -vero eos et accusam et justo duo dolores et ea rebum. - - Duis autem vel eum iriure dolor in hendrerit in vulputate velit - esse molestie consequat, vel illum dolore eu feugiat nulla facilisis - at vero eros et accumsan et iusto odio dignissim qui blandit - praesent luptatum zzril delenit augue duis dolore te feugait nulla - facilisi. - - -Lorem ipsum dolor sit amet, -consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut -laoreet dolore magna aliquam erat volutpat. - - git - --- - +++ - -Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit -lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure -dolor in hendrerit in vulputate velit esse molestie consequat, vel illum -dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio -dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te -feugait nulla facilisi. -EOF - -cat >failmail <<EOF -From foo@example.com Fri May 23 10:43:49 2008 -From: foo@example.com -To: bar@example.com -Subject: Re: [RFC/PATCH] git-foo.sh -Date: Fri, 23 May 2008 05:23:42 +0200 - -Sometimes we have to find out that there's nothing left. - -EOF - -cat >pine <<EOF -From MAILER-DAEMON Fri May 23 10:43:49 2008 -Date: 23 May 2008 05:23:42 +0200 -From: Mail System Internal Data <MAILER-DAEMON@example.com> -Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA -Message-ID: <foo-0001@example.com> - -This text is part of the internal format of your mail folder, and is not -a real message. It is created automatically by the mail system software. -If deleted, important folder data will be lost, and it will be re-created -with the data reset to initial values. - -EOF - -echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected +test_expect_success 'setup: messages' ' + cat >msg <<-\EOF && + second + + Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy + eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam + voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita + kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem + ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod + tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At + vero eos et accusam et justo duo dolores et ea rebum. + + EOF + q_to_tab <<-\EOF >>msg && + QDuis autem vel eum iriure dolor in hendrerit in vulputate velit + Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis + Qat vero eros et accumsan et iusto odio dignissim qui blandit + Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla + Qfacilisi. + EOF + cat >>msg <<-\EOF && + + Lorem ipsum dolor sit amet, + consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut + laoreet dolore magna aliquam erat volutpat. + + git + --- + +++ + + Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit + lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure + dolor in hendrerit in vulputate velit esse molestie consequat, vel illum + dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio + dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te + feugait nulla facilisi. + EOF + + cat >failmail <<-\EOF && + From foo@example.com Fri May 23 10:43:49 2008 + From: foo@example.com + To: bar@example.com + Subject: Re: [RFC/PATCH] git-foo.sh + Date: Fri, 23 May 2008 05:23:42 +0200 + + Sometimes we have to find out that there'\''s nothing left. + + EOF + + cat >pine <<-\EOF && + From MAILER-DAEMON Fri May 23 10:43:49 2008 + Date: 23 May 2008 05:23:42 +0200 + From: Mail System Internal Data <MAILER-DAEMON@example.com> + Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA + Message-ID: <foo-0001@example.com> + + This text is part of the internal format of your mail folder, and is not + a real message. It is created automatically by the mail system software. + If deleted, important folder data will be lost, and it will be re-created + with the data reset to initial values. + + EOF + + signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +' test_expect_success setup ' echo hello >file && @@ -71,11 +76,13 @@ test_expect_success setup ' test_tick && git commit -m first && git tag first && + echo world >>file && git add file && test_tick && git commit -s -F msg && git tag second && + git format-patch --stdout first >patch1 && { echo "X-Fake-Field: Line One" && @@ -89,74 +96,101 @@ test_expect_success setup ' echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } | append_cr >patch1-crlf.eml && + sed -n -e "3,\$p" msg >file && git add file && test_tick && git commit -m third && + git format-patch --stdout first >patch2 && + git checkout -b lorem && sed -n -e "11,\$p" msg >file && head -n 9 msg >>file && test_tick && git commit -a -m "moved stuff" && + echo goodbye >another && git add another && test_tick && git commit -m "added another file" && - git format-patch --stdout master >lorem-move.patch -' -# reset time -unset test_tick -test_tick + git format-patch --stdout master >lorem-move.patch && + + git checkout -b rename && + git mv file renamed && + git commit -m "renamed a file" && + + git format-patch -M --stdout lorem >rename.patch && + + git reset --soft lorem^ && + git commit -m "renamed a file and added another" && + + git format-patch -M --stdout lorem^ >rename-add.patch && + + # reset time + unset test_tick && + test_tick +' test_expect_success 'am applies patch correctly' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am <patch1 && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox with CRLF' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch1-crlf.eml && ! test -d .git/rebase-apply && - test -z "$(git diff second)" && + git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' -GIT_AUTHOR_NAME="Another Thor" -GIT_AUTHOR_EMAIL="a.thor@example.com" -GIT_COMMITTER_NAME="Co M Miter" -GIT_COMMITTER_EMAIL="c.miter@example.com" -export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +test_expect_success 'setup: new author and committer' ' + GIT_AUTHOR_NAME="Another Thor" && + GIT_AUTHOR_EMAIL="a.thor@example.com" && + GIT_COMMITTER_NAME="Co M Miter" && + GIT_COMMITTER_EMAIL="c.miter@example.com" && + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL +' compare () { - test "$(git cat-file commit "$2" | grep "^$1 ")" = \ - "$(git cat-file commit "$3" | grep "^$1 ")" + a=$(git cat-file commit "$2" | grep "^$1 ") && + b=$(git cat-file commit "$3" | grep "^$1 ") && + test "$a" = "$b" } test_expect_success 'am changes committer and keeps author' ' test_tick && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && git am patch2 && ! test -d .git/rebase-apply && test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" && - test -z "$(git diff master..HEAD)" && - test -z "$(git diff master^..HEAD^)" && + git diff --exit-code master..HEAD && + git diff --exit-code master^..HEAD^ && compare author master HEAD && compare author master^ HEAD^ && test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \ @@ -164,41 +198,55 @@ test_expect_success 'am changes committer and keeps author' ' ' test_expect_success 'am --signoff adds Signed-off-by: line' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b master2 first && git am --signoff <patch2 && + printf "%s\n" "$signoff" >expected && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected && git cat-file commit HEAD^ | grep "Signed-off-by:" >actual && - test_cmp actual expected && + test_cmp expected actual && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected && git cat-file commit HEAD | grep "Signed-off-by:" >actual && - test_cmp actual expected + test_cmp expected actual ' test_expect_success 'am stays in branch' ' - test "refs/heads/master2" = "$(git symbolic-ref HEAD)" + echo refs/heads/master2 >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual ' test_expect_success 'am --signoff does not add Signed-off-by: line if already there' ' git format-patch --stdout HEAD^ >patch3 && sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4 + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --signoff patch4 && - test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1 + git cat-file commit HEAD >actual && + test $(grep -c "^Signed-off-by:" actual) -eq 1 ' test_expect_success 'am without --keep removes Re: and [PATCH] stuff' ' - test "$(git rev-parse HEAD)" = "$(git rev-parse master2)" + git rev-parse HEAD >expected && + git rev-parse master2 >actual && + test_cmp expected actual ' test_expect_success 'am --keep really keeps the subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout HEAD^ && git am --keep patch4 && ! test -d .git/rebase-apply && - git cat-file commit HEAD | - fgrep "Re: Re: Re: [PATCH 1/5 v2] third" + git cat-file commit HEAD >actual && + grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual ' test_expect_success 'am -3 falls back to 3-way merge' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout -b lorem2 master2 && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && @@ -207,34 +255,75 @@ test_expect_success 'am -3 falls back to 3-way merge' ' git commit -m "copied stuff" && git am -3 lorem-move.patch && ! test -d .git/rebase-apply && - test -z "$(git diff lorem)" + git diff --exit-code lorem +' + +test_expect_success 'am can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file' ' + grep "^rename from" rename.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename +' + +test_expect_success 'am -3 can rename a file after falling back to 3-way merge' ' + grep "^rename from" rename-add.patch && + rm -fr .git/rebase-apply && + git reset --hard && + git checkout lorem^0 && + git am -3 rename-add.patch && + ! test -d .git/rebase-apply && + git update-index --refresh && + git diff --exit-code rename ' test_expect_success 'am -3 -q is quiet' ' + rm -fr .git/rebase-apply && + git checkout -f lorem2 && git reset master2 --hard && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && git add file && test_tick && git commit -m "copied stuff" && - git am -3 -q lorem-move.patch > output.out 2>&1 && + git am -3 -q lorem-move.patch >output.out 2>&1 && ! test -s output.out ' test_expect_success 'am pauses on conflict' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply ' test_expect_success 'am --skip works' ' + echo goodbye >expected && git am --skip && ! test -d .git/rebase-apply && - test -z "$(git diff lorem2^^ -- file)" && - test goodbye = "$(cat another)" + git diff --exit-code lorem2^^ -- file && + test_cmp expected another ' test_expect_success 'am --resolved works' ' + echo goodbye >expected && + rm -fr .git/rebase-apply && + git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply && @@ -242,22 +331,29 @@ test_expect_success 'am --resolved works' ' git add file && git am --resolved && ! test -d .git/rebase-apply && - test goodbye = "$(cat another)" + test_cmp expected another ' test_expect_success 'am takes patches from a Pine mailbox' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && cat pine patch1 | git am && ! test -d .git/rebase-apply && - test -z "$(git diff master^..HEAD)" + git diff --exit-code master^..HEAD ' test_expect_success 'am fails on mail without patch' ' + rm -fr .git/rebase-apply && + git reset --hard && test_must_fail git am <failmail && - rm -r .git/rebase-apply/ + git am --abort && + ! test -d .git/rebase-apply ' test_expect_success 'am fails on empty patch' ' + rm -fr .git/rebase-apply && + git reset --hard && echo "---" >>failmail && test_must_fail git am <failmail && git am --skip && @@ -266,28 +362,34 @@ test_expect_success 'am fails on empty patch' ' test_expect_success 'am works from stdin in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am <../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (relative path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && ( mkdir -p subdir && cd subdir && git am ../patch1 ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am works from file (absolute path given) in subdirectory' ' rm -fr subdir && + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && P=$(pwd) && ( @@ -295,27 +397,31 @@ test_expect_success 'am works from file (absolute path given) in subdirectory' ' cd subdir && git am "$P/patch1" ) && - test -z "$(git diff second)" + git diff --exit-code second ' test_expect_success 'am --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --committer-date-is-author-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" = "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + test_cmp at ct ' test_expect_success 'am without --committer-date-is-author-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - ct=$(sed -ne "/^committer /s/.*> //p" head1) && - test "$at" != "$ct" + sed -ne "/^author /s/.*> //p" head1 >at && + sed -ne "/^committer /s/.*> //p" head1 >ct && + ! test_cmp at ct ' # This checks for +0000 because TZ is set to UTC and that should @@ -323,41 +429,51 @@ test_expect_success 'am without --committer-date-is-author-date' ' # by test_tick that uses -0700 timezone; if this feature does not # work, we will see that instead of +0000. test_expect_success 'am --ignore-date' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && git am --ignore-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && - at=$(sed -ne "/^author /s/.*> //p" head1) && - echo "$at" | grep "+0000" + sed -ne "/^author /s/.*> //p" head1 >at && + grep "+0000" at ' test_expect_success 'am into an unborn branch' ' + git rev-parse first^{tree} >expected && + rm -fr .git/rebase-apply && + git reset --hard && rm -fr subdir && - mkdir -p subdir && + mkdir subdir && git format-patch --numbered-files -o subdir -1 first && ( cd subdir && git init && git am 1 ) && - result=$( - cd subdir && git rev-parse HEAD^{tree} + ( + cd subdir && + git rev-parse HEAD^{tree} >../actual ) && - test "z$result" = "z$(git rev-parse first^{tree})" + test_cmp expected actual ' test_expect_success 'am newline in subject' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - sed -e "s/second/second \\\n foo/" patch1 > patchnl && - git am < patchnl > output.out 2>&1 && + sed -e "s/second/second \\\n foo/" patch1 >patchnl && + git am <patchnl >output.out 2>&1 && grep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' + rm -fr .git/rebase-apply && + git reset --hard && git checkout first && test_tick && - git am -q < patch1 > output.out 2>&1 && + git am -q <patch1 >output.out 2>&1 && ! test -s output.out ' diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index 2b912d7728..b55c411788 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -47,7 +47,7 @@ do test_must_fail git am$with3 --skip >output && test "$(grep "^Applying" output)" = "Applying: 6" && test_cmp file-2-expect file-2 && - test ! -f .git/rr-cache/MERGE_RR + test ! -f .git/MERGE_RR ' test_expect_success "am --abort goes back after failed am$with3" ' @@ -57,7 +57,7 @@ do test_cmp expect actual && test_cmp file-2-expect file-2 && git diff-index --exit-code --cached HEAD && - test ! -f .git/rr-cache/MERGE_RR + test ! -f .git/MERGE_RR ' done diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 70856d07ed..36255d608a 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -4,237 +4,391 @@ # test_description='git rerere + +! [fifth] version1 + ! [first] first + ! [fourth] version1 + ! [master] initial + ! [second] prefer first over second + ! [third] version2 +------ + + [third] version2 ++ [fifth] version1 + + [fourth] version1 ++ + + [third^] third + - [second] prefer first over second + + + [first] first + + [second^] second +++++++ [master] initial ' . ./test-lib.sh -test_expect_success 'setup' " - cat > a1 <<- EOF && +test_expect_success 'setup' ' + cat >a1 <<-\EOF && Some title ========== - Whether 'tis nobler in the mind to suffer + Whether '\''tis nobler in the mind to suffer The slings and arrows of outrageous fortune, Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks - That flesh is heir to, 'tis a consummation - Devoutly to be wish'd. + That flesh is heir to, '\''tis a consummation + Devoutly to be wish'\''d. EOF git add a1 && + test_tick && git commit -q -a -m initial && - git checkout -b first && - cat >> a1 <<- EOF && + cat >>a1 <<-\EOF && Some title ========== To die, to sleep; - To sleep: perchance to dream: ay, there's the rub; + To sleep: perchance to dream: ay, there'\''s the rub; For in that sleep of death what dreams may come When we have shuffled off this mortal coil, - Must give us pause: there's the respect + Must give us pause: there'\''s the respect That makes calamity of so long life; EOF + + git checkout -b first && + test_tick && git commit -q -a -m first && git checkout -b second master && git show first:a1 | - sed -e 's/To die, t/To die! T/' -e 's/Some title/Some Title/' > a1 && - echo '* END *' >>a1 && + sed -e "s/To die, t/To die! T/" -e "s/Some title/Some Title/" >a1 && + echo "* END *" >>a1 && + test_tick && git commit -q -a -m second -" +' test_expect_success 'nothing recorded without rerere' ' - (rm -rf .git/rr-cache; git config rerere.enabled false) && + rm -rf .git/rr-cache && + git config rerere.enabled false && test_must_fail git merge first && ! test -d .git/rr-cache ' -# activate rerere, old style -test_expect_success 'conflicting merge' ' +test_expect_success 'activate rerere, old style (conflicting merge)' ' git reset --hard && mkdir .git/rr-cache && - git config --unset rerere.enabled && - test_must_fail git merge first -' + test_might_fail git config --unset rerere.enabled && + test_must_fail git merge first && -sha1=$(perl -pe 's/ .*//' .git/MERGE_RR) -rr=.git/rr-cache/$sha1 -test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage" + sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + rr=.git/rr-cache/$sha1 && + grep "^=======\$" $rr/preimage && + ! test -f $rr/postimage && + ! test -f $rr/thisimage +' test_expect_success 'rerere.enabled works, too' ' rm -rf .git/rr-cache && git config rerere.enabled true && git reset --hard && test_must_fail git merge first && + + sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + rr=.git/rr-cache/$sha1 && grep ^=======$ $rr/preimage ' -test_expect_success 'no postimage or thisimage yet' \ - "test ! -f $rr/postimage -a ! -f $rr/thisimage" +test_expect_success 'set up rr-cache' ' + rm -rf .git/rr-cache && + git config rerere.enabled true && + git reset --hard && + test_must_fail git merge first && + sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + rr=.git/rr-cache/$sha1 +' -test_expect_success 'preimage has right number of lines' ' +test_expect_success 'rr-cache looks sane' ' + # no postimage or thisimage yet + ! test -f $rr/postimage && + ! test -f $rr/thisimage && + # preimage has right number of lines cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) && + echo $cnt && test $cnt = 13 - ' -git show first:a1 > a1 - -cat > expect << EOF ---- a/a1 -+++ b/a1 -@@ -1,4 +1,4 @@ --Some Title -+Some title - ========== - Whether 'tis nobler in the mind to suffer - The slings and arrows of outrageous fortune, -@@ -8,21 +8,11 @@ - The heart-ache and the thousand natural shocks - That flesh is heir to, 'tis a consummation - Devoutly to be wish'd. --<<<<<<< --Some Title --========== --To die! To sleep; --======= - Some title - ========== - To die, to sleep; -->>>>>>> - To sleep: perchance to dream: ay, there's the rub; - For in that sleep of death what dreams may come - When we have shuffled off this mortal coil, - Must give us pause: there's the respect - That makes calamity of so long life; --<<<<<<< --======= --* END * -->>>>>>> -EOF -git rerere diff > out - -test_expect_success 'rerere diff' 'test_cmp expect out' - -cat > expect << EOF -a1 -EOF - -git rerere status > out - -test_expect_success 'rerere status' 'test_cmp expect out' - -test_expect_success 'commit succeeds' \ - "git commit -q -a -m 'prefer first over second'" - -test_expect_success 'recorded postimage' "test -f $rr/postimage" - -test_expect_success 'another conflicting merge' ' - git checkout -b third master && - git show second^:a1 | sed "s/To die: t/To die! T/" > a1 && - git commit -q -a -m third && - test_must_fail git pull . first +test_expect_success 'rerere diff' ' + git show first:a1 >a1 && + cat >expect <<-\EOF && + --- a/a1 + +++ b/a1 + @@ -1,4 +1,4 @@ + -Some Title + +Some title + ========== + Whether '\''tis nobler in the mind to suffer + The slings and arrows of outrageous fortune, + @@ -8,21 +8,11 @@ + The heart-ache and the thousand natural shocks + That flesh is heir to, '\''tis a consummation + Devoutly to be wish'\''d. + -<<<<<<< + -Some Title + -========== + -To die! To sleep; + -======= + Some title + ========== + To die, to sleep; + ->>>>>>> + To sleep: perchance to dream: ay, there'\''s the rub; + For in that sleep of death what dreams may come + When we have shuffled off this mortal coil, + Must give us pause: there'\''s the respect + That makes calamity of so long life; + -<<<<<<< + -======= + -* END * + ->>>>>>> + EOF + git rerere diff >out && + test_cmp expect out ' -git show first:a1 | sed 's/To die: t/To die! T/' > expect -test_expect_success 'rerere kicked in' "! grep ^=======$ a1" +test_expect_success 'rerere status' ' + echo a1 >expect && + git rerere status >out && + test_cmp expect out +' -test_expect_success 'rerere prefers first change' 'test_cmp a1 expect' +test_expect_success 'first postimage wins' ' + git show first:a1 | sed "s/To die: t/To die! T/" >expect && -rm $rr/postimage -echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR + git commit -q -a -m "prefer first over second" && + test -f $rr/postimage && -test_expect_success 'rerere clear' 'git rerere clear' + oldmtimepost=$(test-chmtime -v -60 $rr/postimage | cut -f 1) && -test_expect_success 'clear removed the directory' "test ! -d $rr" + git checkout -b third master && + git show second^:a1 | sed "s/To die: t/To die! T/" >a1 && + git commit -q -a -m third && -mkdir $rr -echo Hello > $rr/preimage -echo World > $rr/postimage + test_must_fail git pull . first && + # rerere kicked in + ! grep "^=======\$" a1 && + test_cmp expect a1 +' -sha2=4000000000000000000000000000000000000000 -rr2=.git/rr-cache/$sha2 -mkdir $rr2 -echo Hello > $rr2/preimage +test_expect_success 'rerere updates postimage timestamp' ' + newmtimepost=$(test-chmtime -v +0 $rr/postimage | cut -f 1) && + test $oldmtimepost -lt $newmtimepost +' -almost_15_days_ago=$((60-15*86400)) -just_over_15_days_ago=$((-1-15*86400)) -almost_60_days_ago=$((60-60*86400)) -just_over_60_days_ago=$((-1-60*86400)) +test_expect_success 'rerere clear' ' + rm $rr/postimage && + echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR && + git rerere clear && + ! test -d $rr +' -test-chmtime =$almost_60_days_ago $rr/preimage -test-chmtime =$almost_15_days_ago $rr2/preimage +test_expect_success 'set up for garbage collection tests' ' + mkdir -p $rr && + echo Hello >$rr/preimage && + echo World >$rr/postimage && -test_expect_success 'garbage collection (part1)' 'git rerere gc' + sha2=4000000000000000000000000000000000000000 && + rr2=.git/rr-cache/$sha2 && + mkdir $rr2 && + echo Hello >$rr2/preimage && -test_expect_success 'young records still live' \ - "test -f $rr/preimage && test -f $rr2/preimage" + almost_15_days_ago=$((60-15*86400)) && + just_over_15_days_ago=$((-1-15*86400)) && + almost_60_days_ago=$((60-60*86400)) && + just_over_60_days_ago=$((-1-60*86400)) && -test-chmtime =$just_over_60_days_ago $rr/preimage -test-chmtime =$just_over_15_days_ago $rr2/preimage + test-chmtime =$just_over_60_days_ago $rr/preimage && + test-chmtime =$almost_60_days_ago $rr/postimage && + test-chmtime =$almost_15_days_ago $rr2/preimage +' -test_expect_success 'garbage collection (part2)' 'git rerere gc' +test_expect_success 'gc preserves young or recently used records' ' + git rerere gc && + test -f $rr/preimage && + test -f $rr2/preimage +' -test_expect_success 'old records rest in peace' \ - "test ! -f $rr/preimage && test ! -f $rr2/preimage" +test_expect_success 'old records rest in peace' ' + test-chmtime =$just_over_60_days_ago $rr/postimage && + test-chmtime =$just_over_15_days_ago $rr2/preimage && + git rerere gc && + ! test -f $rr/preimage && + ! test -f $rr2/preimage +' -test_expect_success 'file2 added differently in two branches' ' +test_expect_success 'setup: file2 added differently in two branches' ' git reset --hard && + git checkout -b fourth && - echo Hallo > file2 && + echo Hallo >file2 && git add file2 && + test_tick && git commit -m version1 && + git checkout third && - echo Bello > file2 && + echo Bello >file2 && git add file2 && + test_tick && git commit -m version2 && + test_must_fail git merge fourth && - echo Cello > file2 && + echo Cello >file2 && git add file2 && git commit -m resolution ' test_expect_success 'resolution was recorded properly' ' + echo Cello >expected && + git reset --hard HEAD~2 && git checkout -b fifth && - echo Hallo > file3 && + + echo Hallo >file3 && git add file3 && + test_tick && git commit -m version1 && + git checkout third && - echo Bello > file3 && + echo Bello >file3 && git add file3 && + test_tick && git commit -m version2 && git tag version2 && + test_must_fail git merge fifth && - test Cello = "$(cat file3)" && - test 0 != $(git ls-files -u | wc -l) + test_cmp expected file3 && + test_must_fail git update-index --refresh ' test_expect_success 'rerere.autoupdate' ' - git config rerere.autoupdate true + git config rerere.autoupdate true && git reset --hard && git checkout version2 && test_must_fail git merge fifth && - test 0 = $(git ls-files -u | wc -l) + git update-index --refresh ' test_expect_success 'merge --rerere-autoupdate' ' - git config --unset rerere.autoupdate + test_might_fail git config --unset rerere.autoupdate && git reset --hard && git checkout version2 && test_must_fail git merge --rerere-autoupdate fifth && - test 0 = $(git ls-files -u | wc -l) + git update-index --refresh ' test_expect_success 'merge --no-rerere-autoupdate' ' - git config rerere.autoupdate true + headblob=$(git rev-parse version2:file3) && + mergeblob=$(git rev-parse fifth:file3) && + cat >expected <<-EOF && + 100644 $headblob 2 file3 + 100644 $mergeblob 3 file3 + EOF + + git config rerere.autoupdate true && git reset --hard && git checkout version2 && test_must_fail git merge --no-rerere-autoupdate fifth && - test 2 = $(git ls-files -u | wc -l) + git ls-files -u >actual && + test_cmp expected actual +' + +test_expect_success 'set up an unresolved merge' ' + headblob=$(git rev-parse version2:file3) && + mergeblob=$(git rev-parse fifth:file3) && + cat >expected.unresolved <<-EOF && + 100644 $headblob 2 file3 + 100644 $mergeblob 3 file3 + EOF + + test_might_fail git config --unset rerere.autoupdate && + git reset --hard && + git checkout version2 && + fifth=$(git rev-parse fifth) && + echo "$fifth branch 'fifth' of ." | + git fmt-merge-msg >msg && + ancestor=$(git merge-base version2 fifth) && + test_must_fail git merge-recursive "$ancestor" -- HEAD fifth && + + git ls-files --stage >failedmerge && + cp file3 file3.conflict && + + git ls-files -u >actual && + test_cmp expected.unresolved actual +' + +test_expect_success 'explicit rerere' ' + test_might_fail git config --unset rerere.autoupdate && + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + test_must_fail git update-index --refresh -q && + + git rerere && + git ls-files -u >actual && + test_cmp expected.unresolved actual +' + +test_expect_success 'explicit rerere with autoupdate' ' + git config rerere.autoupdate true && + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + test_must_fail git update-index --refresh -q && + + git rerere && + git update-index --refresh +' + +test_expect_success 'explicit rerere --rerere-autoupdate overrides' ' + git config rerere.autoupdate false && + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + git rerere && + git ls-files -u >actual1 && + + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + git rerere --rerere-autoupdate && + git update-index --refresh && + + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + git rerere --rerere-autoupdate --no-rerere-autoupdate && + git ls-files -u >actual2 && + + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + git rerere --rerere-autoupdate --no-rerere-autoupdate --rerere-autoupdate && + git update-index --refresh && + + test_cmp expected.unresolved actual1 && + test_cmp expected.unresolved actual2 +' + +test_expect_success 'rerere --no-no-rerere-autoupdate' ' + git rm -fr --cached . && + git update-index --index-info <failedmerge && + cp file3.conflict file3 && + test_must_fail git rerere --no-no-rerere-autoupdate 2>err && + grep [Uu]sage err && + test_must_fail git update-index --refresh +' + +test_expect_success 'rerere -h' ' + test_must_fail git rerere -h >help && + grep [Uu]sage help ' test_done diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index a01e55bf6b..cdb70b4b33 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -8,30 +8,93 @@ test_description='git shortlog . ./test-lib.sh -echo 1 > a1 -git add a1 -tree=$(git write-tree) -commit=$( (echo "Test"; echo) | git commit-tree $tree ) -git update-ref HEAD $commit +test_expect_success 'setup' ' + echo 1 >a1 && + git add a1 && + tree=$(git write-tree) && + commit=$(printf "%s\n" "Test" "" | git commit-tree "$tree") && + git update-ref HEAD "$commit" && + + echo 2 >a1 && + git commit --quiet -m "This is a very, very long first line for the commit message to see if it is wrapped correctly" a1 && + + # test if the wrapping is still valid + # when replacing all is by treble clefs. + echo 3 >a1 && + git commit --quiet -m "$( + echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | + sed "s/i/1234/g" | + tr 1234 "\360\235\204\236")" a1 && + + # now fsck up the utf8 + git config i18n.commitencoding non-utf-8 && + echo 4 >a1 && + git commit --quiet -m "$( + echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | + sed "s/i/1234/g" | + tr 1234 "\370\235\204\236")" a1 && + + echo 5 >a1 && + git commit --quiet -m "a 12 34 56 78" a1 + + echo 6 >a1 && + git commit --quiet -m "Commit by someone else" \ + --author="Someone else <not!me>" a1 && + + cat >expect.template <<-\EOF + A U Thor (5): + SUBJECT + SUBJECT + SUBJECT + SUBJECT + SUBJECT + + Someone else (1): + SUBJECT + + EOF +' -echo 2 > a1 -git commit --quiet -m "This is a very, very long first line for the commit message to see if it is wrapped correctly" a1 +fuzz() { + file=$1 && + sed " + s/$_x40/OBJECT_NAME/g + s/$_x05/OBJID/g + s/^ \{6\}[CTa].*/ SUBJECT/g + s/^ \{8\}[^ ].*/ CONTINUATION/g + " <"$file" >"$file.fuzzy" && + sed "/CONTINUATION/ d" <"$file.fuzzy" +} -# test if the wrapping is still valid when replacing all i's by treble clefs. -echo 3 > a1 -git commit --quiet -m "$(echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | sed "s/i/1234/g" | tr 1234 '\360\235\204\236')" a1 +test_expect_success 'default output format' ' + git shortlog HEAD >log && + fuzz log >log.predictable && + test_cmp expect.template log.predictable +' -# now fsck up the utf8 -git config i18n.commitencoding non-utf-8 -echo 4 > a1 -git commit --quiet -m "$(echo "This is a very, very long first line for the commit message to see if it is wrapped correctly" | sed "s/i/1234/g" | tr 1234 '\370\235\204\236')" a1 +test_expect_success 'pretty format' ' + sed s/SUBJECT/OBJECT_NAME/ expect.template >expect && + git shortlog --format="%H" HEAD >log && + fuzz log >log.predictable && + test_cmp expect log.predictable +' -echo 5 > a1 -git commit --quiet -m "a 12 34 56 78" a1 +test_expect_success '--abbrev' ' + sed s/SUBJECT/OBJID/ expect.template >expect && + git shortlog --format="%h" --abbrev=5 HEAD >log && + fuzz log >log.predictable && + test_cmp expect log.predictable +' -git shortlog -w HEAD > out +test_expect_success 'output from user-defined format is re-wrapped' ' + sed "s/SUBJECT/two lines/" expect.template >expect && + git shortlog --format="two%nlines" HEAD >log && + fuzz log >log.predictable && + test_cmp expect log.predictable +' -cat > expect << EOF +test_expect_success 'shortlog wrapping' ' + cat >expect <<\EOF && A U Thor (5): Test This is a very, very long first line for the commit message to see if @@ -43,14 +106,19 @@ A U Thor (5): a 12 34 56 78 -EOF - -test_expect_success 'shortlog wrapping' 'test_cmp expect out' +Someone else (1): + Commit by someone else -git log HEAD > log -GIT_DIR=non-existing git shortlog -w < log > out +EOF + git shortlog -w HEAD >out && + test_cmp expect out +' -test_expect_success 'shortlog from non-git directory' 'test_cmp expect out' +test_expect_success 'shortlog from non-git directory' ' + git log HEAD >log && + GIT_DIR=non-existing git shortlog -w <log >out && + test_cmp expect out +' iconvfromutf8toiso88591() { printf "%s" "$*" | iconv -f UTF-8 -t ISO8859-1 diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 1dc224f6fb..2e51356947 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -100,13 +100,11 @@ test_expect_success 'oneline' ' test_expect_success 'diff-filter=A' ' - actual=$(git log --pretty="format:%s" --diff-filter=A HEAD) && - expect=$(echo fifth ; echo fourth ; echo third ; echo initial) && - test "$actual" = "$expect" || { - echo Oops - echo "Actual: $actual" - false - } + git log --pretty="format:%s" --diff-filter=A HEAD > actual && + git log --pretty="format:%s" --diff-filter A HEAD > actual-separate && + printf "fifth\nfourth\nthird\ninitial" > expect && + test_cmp expect actual && + test_cmp expect actual-separate ' @@ -203,6 +201,13 @@ test_expect_success 'log --grep' ' test_cmp expect actual ' +test_expect_success 'log --grep option parsing' ' + echo second >expect && + git log -1 --pretty="tformat:%s" --grep sec >actual && + test_cmp expect actual && + test_must_fail git log -1 --pretty="tformat:%s" --grep +' + test_expect_success 'log -i --grep' ' echo Second >expect && git log -1 --pretty="tformat:%s" -i --grep=sec >actual && @@ -387,5 +392,66 @@ test_expect_success 'log --graph with merge' ' test_cmp expect actual ' -test_done +test_expect_success 'log.decorate configuration' ' + git config --unset-all log.decorate || : + + git log --oneline >expect.none && + git log --oneline --decorate >expect.short && + git log --oneline --decorate=full >expect.full && + + echo "[log] decorate" >>.git/config && + git log --oneline >actual && + test_cmp expect.short actual && + + git config --unset-all log.decorate && + git config log.decorate true && + git log --oneline >actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + git log --oneline --decorate=no >actual && + test_cmp expect.none actual && + + git config --unset-all log.decorate && + git config log.decorate no && + git log --oneline >actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + + git config --unset-all log.decorate && + git config log.decorate short && + git log --oneline >actual && + test_cmp expect.short actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate=full >actual && + test_cmp expect.full actual && + + git config --unset-all log.decorate && + git config log.decorate full && + git log --oneline >actual && + test_cmp expect.full actual && + git log --oneline --no-decorate >actual && + test_cmp expect.none actual && + git log --oneline --decorate >actual && + test_cmp expect.short actual + +' +test_expect_success 'show added path under "--follow -M"' ' + # This tests for a regression introduced in v1.7.2-rc0~103^2~2 + test_create_repo regression && + ( + cd regression && + test_commit needs-another-commit && + test_commit foo.bar && + git log -M --follow -p foo.bar.t && + git log -M --follow --stat foo.bar.t && + git log -M --follow --name-only foo.bar.t + ) +' + +test_done diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh index 04f7bae850..68e2652814 100755 --- a/t/t4204-patch-id.sh +++ b/t/t4204-patch-id.sh @@ -18,6 +18,11 @@ test_expect_success 'patch-id output is well-formed' ' grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output ' +calc_patch_id () { + git patch-id | + sed "s# .*##" > patch-id_"$1" +} + get_patch_id () { git log -p -1 "$1" | git patch-id | sed "s# .*##" > patch-id_"$1" @@ -35,4 +40,27 @@ test_expect_success 'patch-id detects inequality' ' ! test_cmp patch-id_master patch-id_notsame ' +test_expect_success 'patch-id supports git-format-patch output' ' + get_patch_id master && + git checkout same && + git format-patch -1 --stdout | calc_patch_id same && + test_cmp patch-id_master patch-id_same && + set `git format-patch -1 --stdout | git patch-id` && + test "$2" = `git rev-parse HEAD` +' + +test_expect_success 'whitespace is irrelevant in footer' ' + get_patch_id master && + git checkout same && + git format-patch -1 --stdout | sed "s/ \$//" | calc_patch_id same && + test_cmp patch-id_master patch-id_same +' + +test_expect_success 'patch-id supports git-format-patch MIME output' ' + get_patch_id master && + git checkout same && + git format-patch -1 --attach --stdout | calc_patch_id same && + test_cmp patch-id_master patch-id_same +' + test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh new file mode 100755 index 0000000000..cb9f2bdd29 --- /dev/null +++ b/t/t4205-log-pretty-formats.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# +# Copyright (c) 2010, Will Palmer +# + +test_description='Test pretty formats' +. ./test-lib.sh + +test_expect_success 'set up basic repos' ' + >foo && + >bar && + git add foo && + test_tick && + git commit -m initial && + git add bar && + test_tick && + git commit -m "add bar" +' + +test_expect_success 'alias builtin format' ' + git log --pretty=oneline >expected && + git config pretty.test-alias oneline && + git log --pretty=test-alias >actual && + test_cmp expected actual +' + +test_expect_success 'alias masking builtin format' ' + git log --pretty=oneline >expected && + git config pretty.oneline "%H" && + git log --pretty=oneline >actual && + test_cmp expected actual +' + +test_expect_success 'alias user-defined format' ' + git log --pretty="format:%h" >expected && + git config pretty.test-alias "format:%h" && + git log --pretty=test-alias >actual && + test_cmp expected actual +' + +test_expect_success 'alias user-defined tformat' ' + git log --pretty="tformat:%h" >expected && + git config pretty.test-alias "tformat:%h" && + git log --pretty=test-alias >actual && + test_cmp expected actual +' + +test_expect_success 'alias non-existant format' ' + git config pretty.test-alias format-that-will-never-exist && + test_must_fail git log --pretty=test-alias +' + +test_expect_success 'alias of an alias' ' + git log --pretty="tformat:%h" >expected && + git config pretty.test-foo "tformat:%h" && + git config pretty.test-bar test-foo && + git log --pretty=test-bar >actual && test_cmp expected actual +' + +test_expect_success 'alias masking an alias' ' + git log --pretty=format:"Two %H" >expected && + git config pretty.duplicate "format:One %H" && + git config --add pretty.duplicate "format:Two %H" && + git log --pretty=duplicate >actual && + test_cmp expected actual +' + +test_expect_success 'alias loop' ' + git config pretty.test-foo test-bar && + git config pretty.test-bar test-foo && + test_must_fail git log --pretty=test-foo +' + +test_done diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh new file mode 100755 index 0000000000..ad29e65fcb --- /dev/null +++ b/t/t4206-log-follow-harder-copies.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# +# Copyright (c) 2010 Bo Yang +# + +test_description='Test --follow should always find copies hard in git log. + +' +. ./test-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh + +echo >path0 'Line 1 +Line 2 +Line 3 +' + +test_expect_success \ + 'add a file path0 and commit.' \ + 'git add path0 && + git commit -m "Add path0"' + +echo >path0 'New line 1 +New line 2 +New line 3 +' +test_expect_success \ + 'Change path0.' \ + 'git add path0 && + git commit -m "Change path0"' + +cat <path0 >path1 +test_expect_success \ + 'copy path0 to path1.' \ + 'git add path1 && + git commit -m "Copy path1 from path0"' + +test_expect_success \ + 'find the copy path0 -> path1 harder' \ + 'git log --follow --name-status --pretty="format:%s" path1 > current' + +cat >expected <<\EOF +Copy path1 from path0 +C100 path0 path1 + +Change path0 +M path0 + +Add path0 +A path0 +EOF + +test_expect_success \ + 'validate the output.' \ + 'compare_diff_patch current expected' + +test_done diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh new file mode 100755 index 0000000000..bbde31b019 --- /dev/null +++ b/t/t4207-log-decoration-colors.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2010 Nazri Ramliy +# + +test_description='Test for "git log --decorate" colors' + +. ./test-lib.sh + +get_color () +{ + git config --get-color no.such.slot "$1" +} + +test_expect_success setup ' + git config diff.color.commit yellow && + git config color.decorate.branch green && + git config color.decorate.remoteBranch red && + git config color.decorate.tag "reverse bold yellow" && + git config color.decorate.stash magenta && + git config color.decorate.HEAD cyan && + + c_reset=$(get_color reset) && + + c_commit=$(get_color yellow) && + c_branch=$(get_color green) && + c_remoteBranch=$(get_color red) && + c_tag=$(get_color "reverse bold yellow") && + c_stash=$(get_color magenta) && + c_HEAD=$(get_color cyan) && + + test_commit A && + git clone . other && + ( + cd other && + test_commit A1 + ) && + + git remote add -f other ./other && + test_commit B && + git tag v1.0 && + echo >>A.t && + git stash save Changes to A.t +' + +cat >expected <<EOF +${c_commit}COMMIT_ID (${c_HEAD}HEAD${c_reset}${c_commit},\ + ${c_tag}tag: v1.0${c_reset}${c_commit},\ + ${c_tag}tag: B${c_reset}${c_commit},\ + ${c_branch}master${c_reset}${c_commit})${c_reset} B +${c_commit}COMMIT_ID (${c_tag}tag: A1${c_reset}${c_commit},\ + ${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1 +${c_commit}COMMIT_ID (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\ + On master: Changes to A.t +${c_commit}COMMIT_ID (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A +EOF + +# We want log to show all, but the second parent to refs/stash is irrelevant +# to this test since it does not contain any decoration, hence --first-parent +test_expect_success 'Commit Decorations Colored Correctly' ' + git log --first-parent --abbrev=10 --all --decorate --oneline --color=always | + sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" >out && + test_cmp expected out +' + +test_done diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh new file mode 100755 index 0000000000..46c3fe76d3 --- /dev/null +++ b/t/t4300-merge-tree.sh @@ -0,0 +1,257 @@ +#!/bin/sh +# +# Copyright (c) 2010 Will Palmer +# + +test_description='git merge-tree' +. ./test-lib.sh + +test_expect_success setup ' + test_commit "initial" "initial-file" "initial" +' + +test_expect_success 'file add A, !B' ' + cat >expected <<\EXPECTED && +added in remote + their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE +@@ -0,0 +1 @@ ++AAA +EXPECTED + + git reset --hard initial && + test_commit "add-a-not-b" "ONE" "AAA" && + git merge-tree initial initial add-a-not-b >actual && + test_cmp expected actual +' + +test_expect_success 'file add !A, B' ' + cat >expected <<\EXPECTED && +added in local + our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE +EXPECTED + + git reset --hard initial && + test_commit "add-not-a-b" "ONE" "AAA" && + git merge-tree initial add-not-a-b initial >actual && + test_cmp expected actual +' + +test_expect_success 'file add A, B (same)' ' + cat >expected <<\EXPECTED && +added in both + our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE +EXPECTED + + git reset --hard initial && + test_commit "add-a-b-same-A" "ONE" "AAA" && + git reset --hard initial && + test_commit "add-a-b-same-B" "ONE" "AAA" && + git merge-tree initial add-a-b-same-A add-a-b-same-B >actual && + test_cmp expected actual +' + +test_expect_success 'file add A, B (different)' ' + cat >expected <<\EXPECTED && +added in both + our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE +@@ -1 +1,5 @@ ++<<<<<<< .our + AAA ++======= ++BBB ++>>>>>>> .their +EXPECTED + + git reset --hard initial && + test_commit "add-a-b-diff-A" "ONE" "AAA" && + git reset --hard initial && + test_commit "add-a-b-diff-B" "ONE" "BBB" && + git merge-tree initial add-a-b-diff-A add-a-b-diff-B >actual && + test_cmp expected actual +' + +test_expect_success 'file change A, !B' ' + cat >expected <<\EXPECTED && +EXPECTED + + git reset --hard initial && + test_commit "change-a-not-b" "initial-file" "BBB" && + git merge-tree initial change-a-not-b initial >actual && + test_cmp expected actual +' + +test_expect_success 'file change !A, B' ' + cat >expected <<\EXPECTED && +merged + result 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file + our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file +@@ -1 +1 @@ +-initial ++BBB +EXPECTED + + git reset --hard initial && + test_commit "change-not-a-b" "initial-file" "BBB" && + git merge-tree initial initial change-not-a-b >actual && + test_cmp expected actual +' + +test_expect_success 'file change A, B (same)' ' + cat >expected <<\EXPECTED && +EXPECTED + + git reset --hard initial && + test_commit "change-a-b-same-A" "initial-file" "AAA" && + git reset --hard initial && + test_commit "change-a-b-same-B" "initial-file" "AAA" && + git merge-tree initial change-a-b-same-A change-a-b-same-B >actual && + test_cmp expected actual +' + +test_expect_success 'file change A, B (different)' ' + cat >expected <<\EXPECTED && +changed in both + base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file + our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d initial-file + their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file +@@ -1 +1,5 @@ ++<<<<<<< .our + AAA ++======= ++BBB ++>>>>>>> .their +EXPECTED + + git reset --hard initial && + test_commit "change-a-b-diff-A" "initial-file" "AAA" && + git reset --hard initial && + test_commit "change-a-b-diff-B" "initial-file" "BBB" && + git merge-tree initial change-a-b-diff-A change-a-b-diff-B >actual && + test_cmp expected actual +' + +test_expect_success 'file change A, B (mixed)' ' + cat >expected <<\EXPECTED && +changed in both + base 100644 f4f1f998c7776568c4ff38f516d77fef9399b5a7 ONE + our 100644 af14c2c3475337c73759d561ef70b59e5c731176 ONE + their 100644 372d761493f524d44d59bd24700c3bdf914c973c ONE +@@ -7,7 +7,11 @@ + AAA + AAA + AAA ++<<<<<<< .our + BBB ++======= ++CCC ++>>>>>>> .their + AAA + AAA + AAA +EXPECTED + + git reset --hard initial && + test_commit "change-a-b-mix-base" "ONE" " +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA +AAA" && + test_commit "change-a-b-mix-A" "ONE" \ + "$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/BBB/;}" <ONE)" && + git reset --hard change-a-b-mix-base && + test_commit "change-a-b-mix-B" "ONE" \ + "$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/CCC/;}" <ONE)" && + git merge-tree change-a-b-mix-base change-a-b-mix-A change-a-b-mix-B \ + >actual && + test_cmp expected actual +' + +test_expect_success 'file remove A, !B' ' + cat >expected <<\EXPECTED && +removed in local + base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE +EXPECTED + + git reset --hard initial && + test_commit "rm-a-not-b-base" "ONE" "AAA" && + git rm ONE && + git commit -m "rm-a-not-b" && + git tag "rm-a-not-b" && + git merge-tree rm-a-not-b-base rm-a-not-b rm-a-not-b-base >actual && + test_cmp expected actual +' + +test_expect_success 'file remove !A, B' ' + cat >expected <<\EXPECTED && +removed in remote + base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE +@@ -1 +0,0 @@ +-AAA +EXPECTED + + git reset --hard initial && + test_commit "rm-not-a-b-base" "ONE" "AAA" && + git rm ONE && + git commit -m "rm-not-a-b" && + git tag "rm-not-a-b" && + git merge-tree rm-a-not-b-base rm-a-not-b-base rm-a-not-b >actual && + test_cmp expected actual +' + +test_expect_success 'file change A, remove B' ' + cat >expected <<\EXPECTED && +removed in remote + base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE +@@ -1 +0,0 @@ +-BBB +EXPECTED + + git reset --hard initial && + test_commit "change-a-rm-b-base" "ONE" "AAA" && + test_commit "change-a-rm-b-A" "ONE" "BBB" && + git reset --hard change-a-rm-b-base && + git rm ONE && + git commit -m "change-a-rm-b-B" && + git tag "change-a-rm-b-B" && + git merge-tree change-a-rm-b-base change-a-rm-b-A change-a-rm-b-B \ + >actual && + test_cmp expected actual +' + +test_expect_success 'file remove A, change B' ' + cat >expected <<\EXPECTED && +removed in local + base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE +EXPECTED + + git reset --hard initial && + test_commit "rm-a-change-b-base" "ONE" "AAA" && + + git rm ONE && + git commit -m "rm-a-change-b-A" && + git tag "rm-a-change-b-A" && + git reset --hard rm-a-change-b-base && + test_commit "rm-a-change-b-B" "ONE" "BBB" && + git merge-tree rm-a-change-b-base rm-a-change-b-A rm-a-change-b-B \ + >actual && + test_cmp expected actual +' + +test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 27bfba55bd..cff1b3e050 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -94,7 +94,7 @@ test_expect_success 'git archive with --output' \ 'git archive --output=b4.tar HEAD && test_cmp b.tar b4.tar' -test_expect_success 'git archive --remote' \ +test_expect_success NOT_MINGW 'git archive --remote' \ 'git archive --remote=. HEAD >b5.tar && test_cmp b.tar b5.tar' diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 426b319bd3..02d4d2284d 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -4,7 +4,7 @@ test_description='git archive attribute tests' . ./test-lib.sh -SUBSTFORMAT=%H%n +SUBSTFORMAT='%H (%h)%n' test_expect_exists() { test_expect_success " $1 exists" "test -e $1" diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh new file mode 100755 index 0000000000..9cc0a42ea9 --- /dev/null +++ b/t/t5150-request-pull.sh @@ -0,0 +1,228 @@ +#!/bin/sh + +test_description='Test workflows involving pull request.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + + git init --bare upstream.git && + git init --bare downstream.git && + git clone upstream.git upstream-private && + git clone downstream.git local && + + trash_url="file://$TRASH_DIRECTORY" && + downstream_url="$trash_url/downstream.git/" && + upstream_url="$trash_url/upstream.git/" && + + ( + cd upstream-private && + cat <<-\EOT >mnemonic.txt && + Thirtey days hath November, + Aprile, June, and September: + EOT + git add mnemonic.txt && + test_tick && + git commit -m "\"Thirty days\", a reminder of month lengths" && + git tag -m "version 1" -a initial && + git push --tags origin master + ) && + ( + cd local && + git remote add upstream "$trash_url/upstream.git" && + git fetch upstream && + git pull upstream master && + cat <<-\EOT >>mnemonic.txt && + Of twyecescore-eightt is but eine, + And all the remnante be thrycescore-eine. + O’course Leap yare comes an’pynes, + Ev’rie foure yares, gote it ryghth. + An’twyecescore-eight is but twyecescore-nyne. + EOT + git add mnemonic.txt && + test_tick && + git commit -m "More detail" && + git tag -m "version 2" -a full && + git checkout -b simplify HEAD^ && + mv mnemonic.txt mnemonic.standard && + cat <<-\EOT >mnemonic.clarified && + Thirty days has September, + All the rest I can’t remember. + EOT + git add -N mnemonic.standard mnemonic.clarified && + git commit -a -m "Adapt to use modern, simpler English + +But keep the old version, too, in case some people prefer it." && + git checkout master + ) + +' + +test_expect_success 'setup: two scripts for reading pull requests' ' + + downstream_url_for_sed=$( + printf "%s\n" "$downstream_url" | + sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\'' + ) && + + cat <<-\EOT >read-request.sed && + #!/bin/sed -nf + / in the git repository at:$/!d + n + /^$/ n + s/^[ ]*\(.*\) \([^ ]*\)/please pull\ + \1\ + \2/p + q + EOT + + cat <<-EOT >fuzz.sed + #!/bin/sed -nf + s/$_x40/OBJECT_NAME/g + s/A U Thor/AUTHOR/g + s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g + s/ [^ ].*/ SUBJECT/g + s/ [^ ].* (DATE)/ SUBJECT (DATE)/g + s/$downstream_url_for_sed/URL/g + s/for-upstream/BRANCH/g + s/mnemonic.txt/FILENAME/g + /^ FILENAME | *[0-9]* [-+]*\$/ b diffstat + /^AUTHOR ([0-9]*):\$/ b shortlog + p + b + : diffstat + n + / [0-9]* files changed/ { + a\\ + DIFFSTAT + b + } + b diffstat + : shortlog + /^ [a-zA-Z]/ n + /^[a-zA-Z]* ([0-9]*):\$/ n + /^\$/ N + /^\n[a-zA-Z]* ([0-9]*):\$/!{ + a\\ + SHORTLOG + D + } + n + b shortlog + EOT + +' + +test_expect_success 'pull request when forgot to push' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + test_must_fail git request-pull initial "$downstream_url" \ + 2>../err + ) && + grep "No branch of.*is at:\$" err && + grep "Are you sure you pushed" err + +' + +test_expect_success 'pull request after push' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + git push origin master:for-upstream && + git request-pull initial origin >../request + ) && + sed -nf read-request.sed <request >digest && + cat digest && + { + read task && + read repository && + read branch + } <digest && + ( + cd upstream-private && + git checkout initial && + git pull --ff-only "$repository" "$branch" + ) && + test "$branch" = for-upstream && + test_cmp local/mnemonic.txt upstream-private/mnemonic.txt + +' + +test_expect_success 'request names an appropriate branch' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + git push --tags origin master simplify && + git push origin master:for-upstream && + git request-pull initial "$downstream_url" >../request + ) && + sed -nf read-request.sed <request >digest && + cat digest && + { + read task && + read repository && + read branch + } <digest && + { + test "$branch" = master || + test "$branch" = for-upstream + } + +' + +test_expect_success 'pull request format' ' + + rm -fr downstream.git && + git init --bare downstream.git && + cat <<-\EOT >expect && + The following changes since commit OBJECT_NAME: + + SUBJECT (DATE) + + are available in the git repository at: + URL BRANCH + + SHORTLOG + + DIFFSTAT + EOT + ( + cd local && + git checkout initial && + git merge --ff-only master && + git push origin master:for-upstream && + git request-pull initial "$downstream_url" >../request + ) && + <request sed -nf fuzz.sed >request.fuzzy && + test_cmp expect request.fuzzy + +' + +test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' ' + + ( + cd local && + OPTIONS_KEEPDASHDASH=Yes && + export OPTIONS_KEEPDASHDASH && + git checkout initial && + git merge --ff-only master && + git push origin master:for-upstream && + git request-pull -- initial "$downstream_url" >../request + ) + +' + +test_done diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 7649b810b1..bbb9c1251d 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -147,7 +147,7 @@ test_expect_success \ git cat-file $t $object || return 1 done <obj-list } >current && - diff expect current' + test_cmp expect current' test_expect_success \ 'use packed deltified (REF_DELTA) objects' \ @@ -162,7 +162,7 @@ test_expect_success \ git cat-file $t $object || return 1 done <obj-list } >current && - diff expect current' + test_cmp expect current' test_expect_success \ 'use packed deltified (OFS_DELTA) objects' \ @@ -177,7 +177,7 @@ test_expect_success \ git cat-file $t $object || return 1 done <obj-list } >current && - diff expect current' + test_cmp expect current' unset GIT_OBJECT_DIRECTORY diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 4360e77d31..fb3a270822 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -74,7 +74,7 @@ if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) || then test_set_prereq OFF64_T else - say "skipping tests concerning 64-bit offsets" + say "# skipping tests concerning 64-bit offsets" fi test_expect_success OFF64_T \ diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index c718253673..5bcf0b867a 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -94,6 +94,29 @@ test_expect_success 'refuse deleting push with denyDeletes' ' test_must_fail git send-pack ./victim :extra master ' +test_expect_success 'cannot override denyDeletes with git -c send-pack' ' + ( + cd victim && + test_might_fail git branch -D extra && + git config receive.denyDeletes true && + git branch extra master + ) && + test_must_fail git -c receive.denyDeletes=false \ + send-pack ./victim :extra master +' + +test_expect_success 'override denyDeletes with git -c receive-pack' ' + ( + cd victim && + test_might_fail git branch -D extra && + git config receive.denyDeletes true && + git branch extra master + ) && + git send-pack \ + --receive-pack="git -c receive.denyDeletes=false receive-pack" \ + ./victim :extra master +' + test_expect_success 'denyNonFastforwards trumps --force' ' ( cd victim && diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh index d5db75d826..aa0ada0147 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -4,11 +4,9 @@ test_description='test automatic tag following' . ./test-lib.sh -case $(uname -s) in -*MINGW*) +if ! test_have_prereq NOT_MINGW; then say "GIT_DEBUG_SEND_PACK not supported - skipping tests" - test_done -esac +fi # End state of the repository: # @@ -19,7 +17,7 @@ esac # \ C - origin/cat \ # origin/master master -test_expect_success setup ' +test_expect_success NOT_MINGW setup ' test_tick && echo ichi >file && git add file && @@ -42,12 +40,15 @@ test_expect_success setup ' U=UPLOAD_LOG +test_expect_success NOT_MINGW 'setup expect' ' cat - <<EOF >expect #S want $A #E EOF -test_expect_success 'fetch A (new commit : 1 connection)' ' +' + +test_expect_success NOT_MINGW 'fetch A (new commit : 1 connection)' ' rm -f $U ( cd cloned && @@ -59,7 +60,7 @@ test_expect_success 'fetch A (new commit : 1 connection)' ' test_cmp expect actual ' -test_expect_success "create tag T on A, create C on branch cat" ' +test_expect_success NOT_MINGW "create tag T on A, create C on branch cat" ' git tag -a -m tag1 tag1 $A && T=$(git rev-parse --verify tag1) && @@ -71,13 +72,16 @@ test_expect_success "create tag T on A, create C on branch cat" ' git checkout master ' +test_expect_success NOT_MINGW 'setup expect' ' cat - <<EOF >expect #S want $C want $T #E EOF -test_expect_success 'fetch C, T (new branch, tag : 1 connection)' ' +' + +test_expect_success NOT_MINGW 'fetch C, T (new branch, tag : 1 connection)' ' rm -f $U ( cd cloned && @@ -91,7 +95,7 @@ test_expect_success 'fetch C, T (new branch, tag : 1 connection)' ' test_cmp expect actual ' -test_expect_success "create commits O, B, tag S on B" ' +test_expect_success NOT_MINGW "create commits O, B, tag S on B" ' test_tick && echo O >file && git add file && @@ -107,13 +111,16 @@ test_expect_success "create commits O, B, tag S on B" ' S=$(git rev-parse --verify tag2) ' +test_expect_success NOT_MINGW 'setup expect' ' cat - <<EOF >expect #S want $B want $S #E EOF -test_expect_success 'fetch B, S (commit and tag : 1 connection)' ' +' + +test_expect_success NOT_MINGW 'fetch B, S (commit and tag : 1 connection)' ' rm -f $U ( cd cloned && @@ -127,13 +134,16 @@ test_expect_success 'fetch B, S (commit and tag : 1 connection)' ' test_cmp expect actual ' +test_expect_success NOT_MINGW 'setup expect' ' cat - <<EOF >expect #S want $B want $S #E EOF -test_expect_success 'new clone fetch master and tags' ' +' + +test_expect_success NOT_MINGW 'new clone fetch master and tags' ' git branch -D cat rm -f $U ( diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 230c0cd784..5d1c66ea71 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -320,6 +320,69 @@ test_expect_success 'add alt && prune' ' git rev-parse --verify refs/remotes/origin/side2) ' +cat >test/expect <<\EOF +some-tag +EOF + +test_expect_success 'add with reachable tags (default)' ' + (cd one && + >foobar && + git add foobar && + git commit -m "Foobar" && + git tag -a -m "Foobar tag" foobar-tag && + git reset --hard HEAD~1 && + git tag -a -m "Some tag" some-tag) && + (mkdir add-tags && + cd add-tags && + git init && + git remote add -f origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >>../test/output && + test_must_fail git config remote.origin.tagopt) && + test_cmp test/expect test/output +' + +cat >test/expect <<\EOF +some-tag +foobar-tag +--tags +EOF + +test_expect_success 'add --tags' ' + (rm -rf add-tags && + mkdir add-tags && + cd add-tags && + git init && + git remote add -f --tags origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >>../test/output && + git config remote.origin.tagopt >>../test/output) && + test_cmp test/expect test/output +' + +cat >test/expect <<\EOF +--no-tags +EOF + +test_expect_success 'add --no-tags' ' + (rm -rf add-tags && + mkdir add-no-tags && + cd add-no-tags && + git init && + git remote add -f --no-tags origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >../test/output && + git config remote.origin.tagopt >>../test/output) && + (cd one && + git tag -d some-tag foobar-tag) && + test_cmp test/expect test/output +' + +test_expect_success 'reject --no-no-tags' ' + (cd add-no-tags && + test_must_fail git remote add -f --no-no-tags neworigin ../one) +' + cat > one/expect << EOF apis/master apis/side @@ -372,7 +435,7 @@ test_expect_success 'update --prune' ' git branch -m side2 side3) && (cd test && git remote update --prune && - (cd ../one && git branch -m side3 side2) + (cd ../one && git branch -m side3 side2) && git rev-parse refs/remotes/origin/side3 && test_must_fail git rev-parse refs/remotes/origin/side2) ' @@ -534,6 +597,94 @@ test_expect_success 'show empty remote' ' ) ' +test_expect_success 'remote set-branches requires a remote' ' + test_must_fail git remote set-branches && + test_must_fail git remote set-branches --add +' + +test_expect_success 'remote set-branches' ' + echo "+refs/heads/*:refs/remotes/scratch/*" >expect.initial && + sort <<-\EOF >expect.add && + +refs/heads/*:refs/remotes/scratch/* + +refs/heads/other:refs/remotes/scratch/other + EOF + sort <<-\EOF >expect.replace && + +refs/heads/maint:refs/remotes/scratch/maint + +refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + EOF + sort <<-\EOF >expect.add-two && + +refs/heads/maint:refs/remotes/scratch/maint + +refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + +refs/heads/pu:refs/remotes/scratch/pu + +refs/heads/t/topic:refs/remotes/scratch/t/topic + EOF + sort <<-\EOF >expect.setup-ffonly && + refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + EOF + sort <<-\EOF >expect.respect-ffonly && + refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + +refs/heads/pu:refs/remotes/scratch/pu + EOF + + git clone .git/ setbranches && + ( + cd setbranches && + git remote rename origin scratch && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.initial && + + git remote set-branches scratch --add other && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.add && + + git remote set-branches scratch maint master next && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.replace && + + git remote set-branches --add scratch pu t/topic && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.add-two && + + git config --unset-all remote.scratch.fetch && + git config remote.scratch.fetch \ + refs/heads/master:refs/remotes/scratch/master && + git config --add remote.scratch.fetch \ + +refs/heads/next:refs/remotes/scratch/next && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.setup-ffonly && + + git remote set-branches --add scratch pu && + git config --get-all remote.scratch.fetch >config-result && + sort <config-result >../actual.respect-ffonly + ) && + test_cmp expect.initial actual.initial && + test_cmp expect.add actual.add && + test_cmp expect.replace actual.replace && + test_cmp expect.add-two actual.add-two && + test_cmp expect.setup-ffonly actual.setup-ffonly && + test_cmp expect.respect-ffonly actual.respect-ffonly +' + +test_expect_success 'remote set-branches with --mirror' ' + echo "+refs/*:refs/*" >expect.initial && + echo "+refs/heads/master:refs/heads/master" >expect.replace && + git clone --mirror .git/ setbranches-mirror && + ( + cd setbranches-mirror && + git remote rename origin scratch && + git config --get-all remote.scratch.fetch >../actual.initial && + + git remote set-branches scratch heads/master && + git config --get-all remote.scratch.fetch >../actual.replace + ) && + test_cmp expect.initial actual.initial && + test_cmp expect.replace actual.replace +' + test_expect_success 'new remote' ' git remote add someremote foo && echo foo >expect && diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 721821ec92..9a884751ec 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -21,27 +21,30 @@ test_expect_success setup ' test_expect_success "clone and setup child repos" ' git clone . one && - cd one && - echo >file updated by one && - git commit -a -m "updated by one" && - cd .. && + ( + cd one && + echo >file updated by one && + git commit -a -m "updated by one" + ) && git clone . two && - cd two && - git config branch.master.remote one && - git config remote.one.url ../one/.git/ && - git config remote.one.fetch refs/heads/master:refs/heads/one && - cd .. && + ( + cd two && + git config branch.master.remote one && + git config remote.one.url ../one/.git/ && + git config remote.one.fetch refs/heads/master:refs/heads/one + ) && git clone . three && - cd three && - git config branch.master.remote two && - git config branch.master.merge refs/heads/one && - mkdir -p .git/remotes && - { - echo "URL: ../two/.git/" - echo "Pull: refs/heads/master:refs/heads/two" - echo "Pull: refs/heads/one:refs/heads/one" - } >.git/remotes/two && - cd .. && + ( + cd three && + git config branch.master.remote two && + git config branch.master.merge refs/heads/one && + mkdir -p .git/remotes && + { + echo "URL: ../two/.git/" + echo "Pull: refs/heads/master:refs/heads/two" + echo "Pull: refs/heads/one:refs/heads/one" + } >.git/remotes/two + ) && git clone . bundle && git clone . seven ' @@ -71,7 +74,7 @@ test_expect_success "fetch test for-merge" ' echo "$one_in_two " } >expected && cut -f -2 .git/FETCH_HEAD >actual && - diff expected actual' + test_cmp expected actual' test_expect_success 'fetch tags when there is no tags' ' @@ -240,6 +243,38 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' ' git fetch blub ' +# URL supplied to fetch does not match the url of the configured branch's remote +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' ' + one_head=$(cd one && git rev-parse HEAD) && + this_head=$(git rev-parse HEAD) && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + +# URL supplied to fetch matches the url of the configured branch's remote and +# the merge spec matches the branch the remote HEAD points to +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' ' + one_ref=$(cd one && git symbolic-ref HEAD) && + git config branch.master.remote blub && + git config branch.master.merge "$one_ref" && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + +# URL supplied to fetch matches the url of the configured branch's remote, but +# the merge spec does not match the branch the remote HEAD points to +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' ' + git config branch.master.merge "${one_ref}_not" && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + # the strange name is: a\!'b test_expect_success 'quoting of a strangely named repo' ' test_must_fail git fetch "a\\!'\''b" > result 2>&1 && diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 1dd8eed5bb..d1912351db 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -49,4 +49,78 @@ test_expect_success 'ls-remote self' ' ' +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 && + + git remote add origin "$URL" && + git ls-remote 2>actual_err >actual && + + 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. + # + + # setup a new remote to differentiate from "origin" + git clone . other.git && + ( + cd other.git && + echo "$(git rev-parse HEAD) HEAD" + git show-ref | sed -e "s/ / /" + ) >exp && + + URL="other.git" && + echo "From $URL" >exp_err && + + git remote add other $URL && + git config branch.master.remote other && + + 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' ' + # + # Do not expect "git ls-remote <pattern>" to work; ls-remote, correctly, + # confuses <pattern> for <remote>. Although ugly, this behaviour is akin + # to the confusion of refspecs for remotes by git-fetch and git-push, + # eg: + # + # $ git fetch branch + # + + # We could just as easily have used "master"; the "*" emphasizes its + # role as a pattern. + test_must_fail git ls-remote refs*master >actual 2>&1 && + test_cmp exp actual + +' + test_done diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 2de98e6561..b11da79c9c 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -64,13 +64,13 @@ check_push_result () { test_expect_success setup ' - : >path1 && + >path1 && git add path1 && test_tick && git commit -a -m repo && the_first_commit=$(git show-ref -s --verify refs/heads/master) && - : >path2 && + >path2 && git add path2 && test_tick && git commit -a -m second && @@ -483,8 +483,10 @@ git config --remove-section remote.there test_expect_success 'push with dry-run' ' mk_test heads/master && - (cd testrepo && - old_commit=$(git show-ref -s --verify refs/heads/master)) && + ( + cd testrepo && + old_commit=$(git show-ref -s --verify refs/heads/master) + ) && git push --dry-run testrepo && check_push_result $old_commit heads/master ' @@ -493,10 +495,13 @@ test_expect_success 'push updates local refs' ' mk_test heads/master && mk_child child && - (cd child && + ( + cd child && git pull .. master && git push && - test $(git rev-parse master) = $(git rev-parse remotes/origin/master)) + test $(git rev-parse master) = \ + $(git rev-parse remotes/origin/master) + ) ' @@ -506,10 +511,13 @@ test_expect_success 'push updates up-to-date local refs' ' mk_child child1 && mk_child child2 && (cd child1 && git pull .. master && git push) && - (cd child2 && + ( + cd child2 && git pull ../child1 master && git push && - test $(git rev-parse master) = $(git rev-parse remotes/origin/master)) + test $(git rev-parse master) = \ + $(git rev-parse remotes/origin/master) + ) ' @@ -517,9 +525,11 @@ test_expect_success 'push preserves up-to-date packed refs' ' mk_test heads/master && mk_child child && - (cd child && + ( + cd child && git push && - ! test -f .git/refs/remotes/origin/master) + ! test -f .git/refs/remotes/origin/master + ) ' @@ -528,13 +538,15 @@ test_expect_success 'push does not update local refs on failure' ' mk_test heads/master && mk_child child && mkdir testrepo/.git/hooks && - echo exit 1 >testrepo/.git/hooks/pre-receive && + echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive && chmod +x testrepo/.git/hooks/pre-receive && - (cd child && + ( + cd child && git pull .. master test_must_fail git push && test $(git rev-parse master) != \ - $(git rev-parse remotes/origin/master)) + $(git rev-parse remotes/origin/master) + ) ' @@ -575,34 +587,41 @@ test_expect_success 'push --delete refuses src:dest refspecs' ' test_expect_success 'warn on push to HEAD of non-bare repository' ' mk_test heads/master - (cd testrepo && + ( + cd testrepo && git checkout master && - git config receive.denyCurrentBranch warn) && + git config receive.denyCurrentBranch warn + ) && git push testrepo master 2>stderr && grep "warning: updating the current branch" stderr ' test_expect_success 'deny push to HEAD of non-bare repository' ' mk_test heads/master - (cd testrepo && + ( + cd testrepo && git checkout master && - git config receive.denyCurrentBranch true) && + git config receive.denyCurrentBranch true + ) && test_must_fail git push testrepo master ' test_expect_success 'allow push to HEAD of bare repository (bare)' ' mk_test heads/master - (cd testrepo && + ( + cd testrepo && git checkout master && git config receive.denyCurrentBranch true && - git config core.bare true) && + git config core.bare true + ) && git push testrepo master 2>stderr && ! grep "warning: updating the current branch" stderr ' test_expect_success 'allow push to HEAD of non-bare repository (config)' ' mk_test heads/master - (cd testrepo && + ( + cd testrepo && git checkout master && git config receive.denyCurrentBranch false ) && @@ -615,7 +634,8 @@ test_expect_success 'fetch with branches' ' git branch second $the_first_commit && git checkout second && echo ".." > testrepo/.git/branches/branch1 && - (cd testrepo && + ( + cd testrepo && git fetch branch1 && r=$(git show-ref -s --verify refs/heads/branch1) && test "z$r" = "z$the_commit" && @@ -627,7 +647,8 @@ test_expect_success 'fetch with branches' ' test_expect_success 'fetch with branches containing #' ' mk_empty && echo "..#second" > testrepo/.git/branches/branch2 && - (cd testrepo && + ( + cd testrepo && git fetch branch2 && r=$(git show-ref -s --verify refs/heads/branch2) && test "z$r" = "z$the_first_commit" && @@ -641,7 +662,8 @@ test_expect_success 'push with branches' ' git checkout second && echo "testrepo" > .git/branches/branch1 && git push branch1 && - (cd testrepo && + ( + cd testrepo && r=$(git show-ref -s --verify refs/heads/master) && test "z$r" = "z$the_first_commit" && test 1 = $(git for-each-ref refs/heads | wc -l) @@ -652,7 +674,8 @@ test_expect_success 'push with branches containing #' ' mk_empty && echo "testrepo#branch3" > .git/branches/branch2 && git push branch2 && - (cd testrepo && + ( + cd testrepo && r=$(git show-ref -s --verify refs/heads/branch3) && test "z$r" = "z$the_first_commit" && test 1 = $(git for-each-ref refs/heads | wc -l) @@ -660,6 +683,55 @@ test_expect_success 'push with branches containing #' ' git checkout master ' +test_expect_success 'push into aliased refs (consistent)' ' + mk_test heads/master && + mk_child child1 && + mk_child child2 && + ( + cd child1 && + git branch foo && + git symbolic-ref refs/heads/bar refs/heads/foo + git config receive.denyCurrentBranch false + ) && + ( + cd child2 && + >path2 && + git add path2 && + test_tick && + git commit -a -m child2 && + git branch foo && + git branch bar && + git push ../child1 foo bar + ) +' + +test_expect_success 'push into aliased refs (inconsistent)' ' + mk_test heads/master && + mk_child child1 && + mk_child child2 && + ( + cd child1 && + git branch foo && + git symbolic-ref refs/heads/bar refs/heads/foo + git config receive.denyCurrentBranch false + ) && + ( + cd child2 && + >path2 && + git add path2 && + test_tick && + git commit -a -m child2 && + git branch foo && + >path3 && + git add path3 && + test_tick && + git commit -a -m child2 && + git branch bar && + test_must_fail git push ../child1 foo bar 2>stderr && + grep "refusing inconsistent update" stderr + ) +' + test_expect_success 'push --porcelain' ' mk_empty && echo >.git/foo "To testrepo" && diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index dd2ee842e0..0b489f5b12 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -4,6 +4,11 @@ test_description='pulling into void' . ./test-lib.sh +modify () { + sed -e "$1" <"$2" >"$2.x" && + mv "$2.x" "$2" +} + D=`pwd` test_expect_success setup ' @@ -26,7 +31,7 @@ cd "$D" test_expect_success 'checking the results' ' test -f file && test -f cloned/file && - diff file cloned/file + test_cmp file cloned/file ' test_expect_success 'pulling into void using master:master' ' @@ -160,4 +165,61 @@ test_expect_success 'pull --rebase works on branch yet to be born' ' test_cmp expect actual ' +test_expect_success 'setup for detecting upstreamed changes' ' + mkdir src && + (cd src && + git init && + printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff && + git add stuff && + git commit -m "Initial revision" + ) && + git clone src dst && + (cd src && + modify s/5/43/ stuff && + git commit -a -m "5->43" && + modify s/6/42/ stuff && + git commit -a -m "Make it bigger" + ) && + (cd dst && + modify s/5/43/ stuff && + git commit -a -m "Independent discovery of 5->43" + ) +' + +test_expect_success 'git pull --rebase detects upstreamed changes' ' + (cd dst && + git pull --rebase && + test -z "$(git ls-files -u)" + ) +' + +test_expect_success 'setup for avoiding reapplying old patches' ' + (cd dst && + test_might_fail git rebase --abort && + git reset --hard origin/master + ) && + git clone --bare src src-replace.git && + rm -rf src && + mv src-replace.git src && + (cd dst && + modify s/2/22/ stuff && + git commit -a -m "Change 2" && + modify s/3/33/ stuff && + git commit -a -m "Change 3" && + modify s/4/44/ stuff && + git commit -a -m "Change 4" && + git push && + + modify s/44/55/ stuff && + git commit --amend -a -m "Modified Change 4" + ) +' + +test_expect_success 'git pull --rebase does not reapply old patches' ' + (cd dst && + test_must_fail git pull --rebase && + test 1 = $(find .git/rebase-apply -name "000*" | wc -l) + ) +' + test_done diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh index 7206817ca1..8e9b204e02 100755 --- a/t/t5522-pull-symlink.sh +++ b/t/t5522-pull-symlink.sh @@ -4,12 +4,6 @@ test_description='pulling from symlinked subdir' . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - # The scenario we are building: # # trash\ directory/ @@ -20,7 +14,7 @@ fi # # The working directory is subdir-link. -test_expect_success setup ' +test_expect_success SYMLINKS setup ' mkdir subdir && echo file >subdir/file && git add subdir/file && @@ -36,7 +30,7 @@ test_expect_success setup ' # Demonstrate that things work if we just avoid the symlink # -test_expect_success 'pulling from real subdir' ' +test_expect_success SYMLINKS 'pulling from real subdir' ' ( echo real >subdir/file && git commit -m real subdir/file && @@ -64,7 +58,7 @@ test_expect_success 'pulling from real subdir' ' # directory. A POSIX shell's "cd" works a little differently # than chdir() in C; "cd -P" is much closer to chdir(). # -test_expect_success 'pulling from symlinked subdir' ' +test_expect_success SYMLINKS 'pulling from symlinked subdir' ' ( echo link >subdir/file && git commit -m link subdir/file && @@ -77,7 +71,7 @@ test_expect_success 'pulling from symlinked subdir' ' # Prove that the remote end really is a repo, and other commands # work fine in this context. It's just that "git pull" breaks. # -test_expect_success 'pushing from symlinked subdir' ' +test_expect_success SYMLINKS 'pushing from symlinked subdir' ' ( cd subdir-link/ && echo push >file && diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh new file mode 100755 index 0000000000..4fbf7a120f --- /dev/null +++ b/t/t5525-fetch-tagopt.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='tagopt variable affects "git fetch" and is overridden by commandline.' + +. ./test-lib.sh + +setup_clone () { + git clone --mirror . $1 && + git remote add remote_$1 $1 && + (cd $1 && + git tag tag_$1) +} + +test_expect_success setup ' + test_commit test && + setup_clone one && + git config remote.remote_one.tagopt --no-tags && + setup_clone two && + git config remote.remote_two.tagopt --tags + ' + +test_expect_success "fetch with tagopt=--no-tags does not get tag" ' + git fetch remote_one && + test_must_fail git show-ref tag_one + ' + +test_expect_success "fetch --tags with tagopt=--no-tags gets tag" ' + git fetch --tags remote_one && + git show-ref tag_one + ' + +test_expect_success "fetch --no-tags with tagopt=--tags does not get tag" ' + git fetch --no-tags remote_two && + test_must_fail git show-ref tag_two + ' + +test_expect_success "fetch with tagopt=--tags gets tag" ' + git fetch remote_two && + git show-ref tag_two + ' +test_done diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index a696b8791b..6b2a5f4a65 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -32,9 +32,9 @@ test_expect_success 'fsck fails' ' test_expect_success 'upload-pack fails due to error in pack-objects packing' ' - ! echo "0032want $(git rev-parse HEAD) -00000009done -0000" | git upload-pack . > /dev/null 2> output.err && + printf "0032want %s\n00000009done\n0000" \ + $(git rev-parse HEAD) >input && + test_must_fail git upload-pack . <input >/dev/null 2>output.err && grep "unable to read" output.err && grep "pack-objects died" output.err ' @@ -51,20 +51,29 @@ test_expect_success 'fsck fails' ' ' test_expect_success 'upload-pack fails due to error in rev-list' ' - ! echo "0032want $(git rev-parse HEAD) -0034shallow $(git rev-parse HEAD^)00000009done -0000" | git upload-pack . > /dev/null 2> output.err && + printf "0032want %s\n0034shallow %s00000009done\n0000" \ + $(git rev-parse HEAD) $(git rev-parse HEAD^) >input && + test_must_fail git upload-pack . <input >/dev/null 2>output.err && # pack-objects survived grep "Total.*, reused" output.err && # but there was an error, which must have been in rev-list grep "bad tree object" output.err ' +test_expect_success 'upload-pack error message when bad ref requested' ' + + printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input && + test_must_fail git upload-pack . <input >output 2>output.err && + grep -q "not our ref" output.err && + ! grep -q multi_ack_detailed output.err +' + test_expect_success 'upload-pack fails due to error in pack-objects enumeration' ' - ! echo "0032want $(git rev-parse HEAD) -00000009done -0000" | git upload-pack . > /dev/null 2> output.err && + printf "0032want %s\n00000009done\n0000" \ + $(git rev-parse HEAD) >input && + test_must_fail git upload-pack . <input >/dev/null 2>output.err && grep "bad tree object" output.err && grep "pack-objects died" output.err ' diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index 37fe875411..a266ca5636 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -11,7 +11,7 @@ This test runs various sanity checks on http-push.' if git http-push > /dev/null 2>&1 || [ $? -eq 128 ] then - say "skipping test, USE_CURL_MULTI is not defined" + skip_all="skipping test, USE_CURL_MULTI is not defined" test_done fi diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh index 795dc2bcdf..b0c2a2c3ae 100755 --- a/t/t5541-http-push.sh +++ b/t/t5541-http-push.sh @@ -7,7 +7,7 @@ test_description='test smart pushing over http via http-backend' . ./test-lib.sh if test -n "$NO_CURL"; then - say 'skipping test, git built without http support' + skip_all='skipping test, git built without http support' test_done fi @@ -34,8 +34,34 @@ test_expect_success 'setup remote repository' ' mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" ' -test_expect_success 'clone remote repository' ' +cat >exp <<EOF +GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 +POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200 +EOF +test_expect_success 'no empty path components' ' + # In the URL, add a trailing slash, and see if git appends yet another + # slash. cd "$ROOT_PATH" && + git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone && + + sed -e " + s/^.* \"// + s/\"// + s/ [1-9][0-9]*\$// + s/^GET /GET / + " >act <"$HTTPD_ROOT_PATH"/access.log && + + # Clear the log, so that it does not affect the "used receive-pack + # service" test which reads the log too. + # + # We do this before the actual comparison to ensure the log is cleared. + echo > "$HTTPD_ROOT_PATH"/access.log && + + test_cmp exp act +' + +test_expect_success 'clone remote repository' ' + rm -rf test_repo_clone && git clone $HTTPD_URL/smart/test_repo.git test_repo_clone ' @@ -68,6 +94,7 @@ test_expect_success 'create and delete remote branch' ' ' cat >exp <<EOF + GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200 GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 @@ -101,7 +128,7 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he # push master too; this ensures there is at least one '"'push'"' command to # the remote helper and triggers interaction with the helper. - !(git push -v origin +master master:retsam >output 2>&1) && + test_must_fail git push -v origin +master master:retsam >output 2>&1 && grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output && grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output && diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index 8cfce969bc..2fb48d09ed 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -4,7 +4,7 @@ test_description='test dumb fetching over http via static file' . ./test-lib.sh if test -n "$NO_CURL"; then - say 'skipping test, git built without http support' + skip_all='skipping test, git built without http support' test_done fi @@ -55,12 +55,43 @@ 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 && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git && + git --bare repack && + git --bare prune-packed + ) && git clone $HTTPD_URL/dumb/repo_pack.git ' +test_expect_success 'fetch notices corrupt pack' ' + cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git && + (cd "$HTTPD_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 $HTTPD_URL/dumb/repo_bad1.git && + test 0 = `ls objects/pack/pack-*.pack | wc -l` + ) +' + +test_expect_success 'fetch notices corrupt idx' ' + cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git && + (cd "$HTTPD_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 $HTTPD_URL/dumb/repo_bad2.git && + test 0 = `ls objects/pack | wc -l` + ) +' + test_expect_success 'did not use upload-pack service' ' grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act : >exp diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh index 7faa31a299..fd19121372 100755 --- a/t/t5551-http-fetch.sh +++ b/t/t5551-http-fetch.sh @@ -4,7 +4,7 @@ test_description='test smart fetching over http via http-backend' . ./test-lib.sh if test -n "$NO_CURL"; then - say 'skipping test, git built without http support' + skip_all='skipping test, git built without http support' test_done fi diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh index 44885b850c..0ad7ce07c4 100755 --- a/t/t5560-http-backend-noserver.sh +++ b/t/t5560-http-backend-noserver.sh @@ -5,16 +5,17 @@ test_description='test git-http-backend-noserver' HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY" +test_have_prereq MINGW && export GREP_OPTIONS=-U + run_backend() { echo "$2" | QUERY_STRING="${1#*\?}" \ - GIT_PROJECT_ROOT="$HTTPD_DOCUMENT_ROOT_PATH" \ - PATH_INFO="${1%%\?*}" \ + PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%\?*}" \ git http-backend >act.out 2>act.err } GET() { - export REQUEST_METHOD="GET" && + REQUEST_METHOD="GET" && export REQUEST_METHOD && run_backend "/repo.git/$1" && unset REQUEST_METHOD && if ! grep "Status" act.out >act @@ -26,8 +27,8 @@ GET() { } POST() { - export REQUEST_METHOD="POST" && - export CONTENT_TYPE="application/x-$1-request" && + 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 && @@ -46,7 +47,7 @@ log_div() { . "$TEST_DIRECTORY"/t556x_common expect_aliased() { - export REQUEST_METHOD="GET" && + REQUEST_METHOD="GET" && export REQUEST_METHOD && if test $1 = 0; then run_backend "$2" else diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh index 8c6d0b2f20..b5d7fbc381 100755 --- a/t/t5561-http-backend.sh +++ b/t/t5561-http-backend.sh @@ -4,7 +4,7 @@ test_description='test git-http-backend' . ./test-lib.sh if test -n "$NO_CURL"; then - say 'skipping test, git built without http support' + skip_all='skipping test, git built without http support' test_done fi diff --git a/t/t556x_common b/t/t556x_common index be024e551c..51287d89d8 100755 --- a/t/t556x_common +++ b/t/t556x_common @@ -50,7 +50,7 @@ get_static_files() { } SMART=smart -export GIT_HTTP_EXPORT_ALL=1 +GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL test_expect_success 'direct refs/heads/master not found' ' log_div "refs/heads/master" GET refs/heads/master "404 Not Found" @@ -73,7 +73,7 @@ test_expect_success 'export if git-daemon-export-ok' ' get_static_files "200 OK" ' SMART=smart -export GIT_HTTP_EXPORT_ALL=1 +GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL test_expect_success 'static file if http.getanyfile true is ok' ' log_div "getanyfile true" config http.getanyfile true && diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 214756731b..987e0c8463 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -34,7 +34,7 @@ test_expect_success 'clone with excess parameters (2)' ' test_expect_success 'output from clone' ' rm -fr dst && git clone -n "file://$(pwd)/src" dst >output && - test $(grep Initialized output | wc -l) = 1 + test $(grep Clon output | wc -l) = 1 ' test_expect_success 'clone does not keep pack' ' @@ -163,8 +163,6 @@ test_expect_success 'clone a void' ' test_expect_success 'clone respects global branch.autosetuprebase' ' ( - HOME=$(pwd) && - export HOME && test_config="$HOME/.gitconfig" && unset GIT_CONFIG_NOGLOBAL && git config -f "$test_config" branch.autosetuprebase remote && @@ -176,4 +174,22 @@ test_expect_success 'clone respects global branch.autosetuprebase' ' ) ' +test_expect_success 'respect url-encoding of file://' ' + git init x+y && + git clone "file://$PWD/x+y" xy-url-1 && + git clone "file://$PWD/x%2By" xy-url-2 +' + +test_expect_success 'do not query-string-decode + in URLs' ' + rm -rf x+y && + git init "x y" && + test_must_fail git clone "file://$PWD/x+y" xy-no-plus +' + +test_expect_success 'do not respect url-encoding of non-url path' ' + git init x+y && + test_must_fail git clone x%2By xy-regular && + git clone x+y xy-regular +' + test_done diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index 1c10916069..895f5595ae 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -48,7 +48,7 @@ test_expect_success 'that reference gets used' \ 'cd C && echo "0 objects, 0 kilobytes" > expected && git count-objects > current && -diff expected current' +test_cmp expected current' cd "$base_dir" @@ -75,7 +75,7 @@ cd "$base_dir" test_expect_success 'that reference gets used' \ 'cd D && echo "0 objects, 0 kilobytes" > expected && git count-objects > current && -diff expected current' +test_cmp expected current' cd "$base_dir" @@ -100,7 +100,7 @@ test_expect_success 'that alternate to origin gets used' \ 'cd C && echo "2 objects" > expected && git count-objects | cut -d, -f1 > current && -diff expected current' +test_cmp expected current' cd "$base_dir" @@ -116,7 +116,7 @@ test_expect_success 'check objects expected to exist locally' \ 'cd D && echo "5 objects" > expected && git count-objects | cut -d, -f1 > current && -diff expected current' +test_cmp expected current' cd "$base_dir" diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh index a8f4419e61..728ccd88c3 100755 --- a/t/t5704-bundle.sh +++ b/t/t5704-bundle.sh @@ -30,4 +30,27 @@ test_expect_success 'tags can be excluded by rev-list options' ' ' +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_done diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh index adfaae8c5b..e9783c341a 100755 --- a/t/t5705-clone-2gb.sh +++ b/t/t5705-clone-2gb.sh @@ -3,16 +3,18 @@ test_description='Test cloning a repository larger than 2 gigabyte' . ./test-lib.sh -test -z "$GIT_TEST_CLONE_2GB" && -say "Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" && -test_done && -exit +if test -z "$GIT_TEST_CLONE_2GB" +then + say 'Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t' +else + test_set_prereq CLONE_2GB +fi -test_expect_success 'setup' ' +test_expect_success CLONE_2GB 'setup' ' git config pack.compression 0 && git config pack.depth 0 && - blobsize=$((20*1024*1024)) && + blobsize=$((100*1024*1024)) && blobcount=$((2*1024*1024*1024/$blobsize+1)) && i=1 && (while test $i -le $blobcount @@ -36,9 +38,15 @@ test_expect_success 'setup' ' ' -test_expect_success 'clone' ' +test_expect_success CLONE_2GB 'clone - bare' ' - git clone --bare --no-hardlinks . clone + git clone --bare --no-hardlinks . clone-bare + +' + +test_expect_success CLONE_2GB 'clone - with worktree, file:// protocol' ' + + git clone file://. clone-wt ' diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh new file mode 100755 index 0000000000..1fb6380fce --- /dev/null +++ b/t/t5800-remote-helpers.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Copyright (c) 2010 Sverre Rabbelier +# + +test_description='Test remote-helper import and export commands' + +. ./test-lib.sh + +if test_have_prereq PYTHON && "$PYTHON_PATH" -c ' +import sys +if sys.hexversion < 0x02040000: + sys.exit(1) +' +then + # Requires Python 2.4 or newer + test_set_prereq PYTHON_24 +fi + +test_expect_success PYTHON_24 'setup repository' ' + git init --bare server/.git && + git clone server public && + (cd public && + echo content >file && + git add file && + git commit -m one && + git push origin master) +' + +test_expect_success PYTHON_24 'cloning from local repo' ' + git clone "testgit::${PWD}/server" localclone && + test_cmp public/file localclone/file +' + +test_expect_success PYTHON_24 'cloning from remote repo' ' + git clone "testgit::file://${PWD}/server" clone && + test_cmp public/file clone/file +' + +test_expect_success PYTHON_24 'create new commit on remote' ' + (cd public && + echo content >>file && + git commit -a -m two && + git push) +' + +test_expect_success PYTHON_24 'pulling from local repo' ' + (cd localclone && git pull) && + test_cmp public/file localclone/file +' + +test_expect_success PYTHON_24 'pulling from remote remote' ' + (cd clone && git pull) && + test_cmp public/file clone/file +' + +test_expect_success PYTHON_24 'pushing to local repo' ' + (cd localclone && + echo content >>file && + git commit -a -m three && + git push) && + HEAD=$(git --git-dir=localclone/.git rev-parse --verify HEAD) && + test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) +' + +test_expect_success PYTHON_24 'synch with changes from localclone' ' + (cd clone && + git pull) +' + +test_expect_success PYTHON_24 'pushing remote local repo' ' + (cd clone && + echo content >>file && + git commit -a -m four && + git push) && + HEAD=$(git --git-dir=clone/.git rev-parse --verify HEAD) && + test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) +' + +test_done diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh index b2131cdacd..fc57e7d3fd 100755 --- a/t/t6001-rev-list-graft.sh +++ b/t/t6001-rev-list-graft.sh @@ -84,7 +84,7 @@ check () { git rev-list --parents --pretty=raw $arg | sed -n -e 's/^commit //p' >test.actual fi - diff test.expect test.actual + test_cmp test.expect test.actual } for type in basic parents parents-raw diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index b4e8fbaa5e..fb07536a0f 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -5,7 +5,7 @@ test_description='Tests git rev-list --bisect functionality' . ./test-lib.sh -. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions # usage: test_bisection max-diff bisect-option head ^prune... # diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh index 2c73f2da7b..e4c52b0214 100755 --- a/t/t6003-rev-list-topo-order.sh +++ b/t/t6003-rev-list-topo-order.sh @@ -6,7 +6,7 @@ test_description='Tests git rev-list --topo-order functionality' . ./test-lib.sh -. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions list_duplicates() { diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index a49b7c5722..cccacd4add 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -101,6 +101,15 @@ commit 131a310eb913d107dd3c09a65d1651175898735d commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 EOF +test_format raw-body %B <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo + +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo + +EOF + test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF' commit 131a310eb913d107dd3c09a65d1651175898735d [31mfoo[32mbar[34mbaz[mxyzzy @@ -191,6 +200,41 @@ test_expect_success 'add LF before non-empty (2)' ' grep "^$" actual ' +test_expect_success 'add SP before non-empty (1)' ' + git show -s --pretty=format:"%s% bThanks" HEAD^^ >actual && + test $(wc -w <actual) = 2 +' + +test_expect_success 'add SP before non-empty (2)' ' + git show -s --pretty=format:"%s% sThanks" HEAD^^ >actual && + test $(wc -w <actual) = 4 +' + +test_expect_success '--abbrev' ' + echo SHORT SHORT SHORT >expect2 && + echo LONG LONG LONG >expect3 && + git log -1 --format="%h %h %h" HEAD >actual1 && + git log -1 --abbrev=5 --format="%h %h %h" HEAD >actual2 && + git log -1 --abbrev=5 --format="%H %H %H" HEAD >actual3 && + sed -e "s/$_x40/LONG/g" -e "s/$_x05/SHORT/g" <actual2 >fuzzy2 && + sed -e "s/$_x40/LONG/g" -e "s/$_x05/SHORT/g" <actual3 >fuzzy3 && + test_cmp expect2 fuzzy2 && + test_cmp expect3 fuzzy3 && + ! test_cmp actual1 actual2 +' + +test_expect_success '%H is not affected by --abbrev-commit' ' + git log -1 --format=%H --abbrev-commit --abbrev=20 HEAD >actual && + len=$(wc -c <actual) && + test $len = 41 +' + +test_expect_success '%h is not affected by --abbrev-commit' ' + git log -1 --format=%h --abbrev-commit --abbrev=20 HEAD >actual && + len=$(wc -c <actual) && + test $len = 21 +' + test_expect_success '"%h %gD: %gs" is same as git-reflog' ' git reflog >expect && git log -g --format="%h %gD: %gs" >actual && @@ -203,6 +247,12 @@ test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' ' test_cmp expect actual ' +test_expect_success '"%h %gD: %gs" is same as git-reflog (with --abbrev)' ' + git reflog --abbrev=13 --date=raw >expect && + git log -g --abbrev=13 --format="%h %gD: %gs" --date=raw >actual && + test_cmp expect actual +' + test_expect_success '%gd shortens ref name' ' echo "master@{0}" >expect.gd-short && git log -g -1 --format=%gd refs/heads/master >actual.gd-short && diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index 4b8611ce20..b565638e92 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -32,6 +32,23 @@ test_expect_success setup ' git tag B ' +cat >expect <<EOF +<tags/B +>tags/C +EOF + +test_expect_success '--left-right' ' + git rev-list --left-right B...C > actual && + git name-rev --stdin --name-only --refs="*tags/*" \ + < actual > actual.named && + test_cmp actual.named expect +' + +test_expect_success '--count' ' + git rev-list --count B...C > actual && + test "$(cat actual)" = 2 +' + test_expect_success '--cherry-pick foo comes up empty' ' test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)" ' @@ -54,4 +71,16 @@ test_expect_success '--cherry-pick with independent, but identical branches' ' HEAD...master -- foo)" ' +cat >expect <<EOF +1 2 +EOF + +# Insert an extra commit to break the symmetry +test_expect_success '--count --left-right' ' + git checkout branch && + test_commit D && + git rev-list --count --left-right B...D > actual && + test_cmp expect actual +' + test_done diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh index 0144d9e858..62197a3d35 100755 --- a/t/t6010-merge-base.sh +++ b/t/t6010-merge-base.sh @@ -3,175 +3,231 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='Merge base computation. +test_description='Merge base and parent list computation. ' . ./test-lib.sh -T=$(git write-tree) - -M=1130000000 -Z=+0000 - -GIT_COMMITTER_EMAIL=git@comm.iter.xz -GIT_COMMITTER_NAME='C O Mmiter' -GIT_AUTHOR_NAME='A U Thor' -GIT_AUTHOR_EMAIL=git@au.thor.xz -export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL - -doit() { - OFFSET=$1; shift - NAME=$1; shift - PARENTS= - for P - do - PARENTS="${PARENTS}-p $P " - done - GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" - GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE - export GIT_COMMITTER_DATE GIT_AUTHOR_DATE - commit=$(echo $NAME | git commit-tree $T $PARENTS) - echo $commit >.git/refs/tags/$NAME - echo $commit -} - -# E---D---C---B---A -# \'-_ \ \ -# \ `---------G \ -# \ \ -# F----------------H - -# Setup... -E=$(doit 5 E) -D=$(doit 4 D $E) -F=$(doit 6 F $E) -C=$(doit 3 C $D) -B=$(doit 2 B $C) -A=$(doit 1 A $B) -G=$(doit 7 G $B $E) -H=$(doit 8 H $A $F) - -test_expect_success 'compute merge-base (single)' \ - 'MB=$(git merge-base G H) && - expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"' - -test_expect_success 'compute merge-base (all)' \ - 'MB=$(git merge-base --all G H) && - expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"' - -test_expect_success 'compute merge-base with show-branch' \ - 'MB=$(git show-branch --merge-base G H) && - expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"' - -# Setup for second test to demonstrate that relying on timestamps in a -# distributed SCM to provide a _consistent_ partial ordering of commits -# leads to insanity. -# -# Relative -# Structure timestamps -# -# PL PR +4 +4 -# / \/ \ / \/ \ -# L2 C2 R2 +3 -1 +3 -# | | | | | | -# L1 C1 R1 +2 -2 +2 -# | | | | | | -# L0 C0 R0 +1 -3 +1 -# \ | / \ | / -# S 0 -# -# The left and right chains of commits can be of any length and complexity as -# long as all of the timestamps are greater than that of S. +test_expect_success 'setup' ' + T=$(git write-tree) && -S=$(doit 0 S) + M=1130000000 && + Z=+0000 && -C0=$(doit -3 C0 $S) -C1=$(doit -2 C1 $C0) -C2=$(doit -1 C2 $C1) + GIT_COMMITTER_EMAIL=git@comm.iter.xz && + GIT_COMMITTER_NAME="C O Mmiter" && + GIT_AUTHOR_NAME="A U Thor" && + GIT_AUTHOR_EMAIL=git@au.thor.xz && + export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL && -L0=$(doit 1 L0 $S) -L1=$(doit 2 L1 $L0) -L2=$(doit 3 L2 $L1) + doit() { + OFFSET=$1 && + NAME=$2 && + shift 2 && -R0=$(doit 1 R0 $S) -R1=$(doit 2 R1 $R0) -R2=$(doit 3 R2 $R1) + PARENTS= && + for P + do + PARENTS="${PARENTS}-p $P " + done && -PL=$(doit 4 PL $L2 $C2) -PR=$(doit 4 PR $C2 $R2) + GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" && + GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE && + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE && -test_expect_success 'compute merge-base (single)' \ - 'MB=$(git merge-base PL PR) && - expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"' + commit=$(echo $NAME | git commit-tree $T $PARENTS) && -test_expect_success 'compute merge-base (all)' \ - 'MB=$(git merge-base --all PL PR) && - expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"' + echo $commit >.git/refs/tags/$NAME && + echo $commit + } +' -# Another set to demonstrate base between one commit and a merge -# in the documentation. -# -# * C (MMC) * B (MMB) * A (MMA) -# * o * o * o -# * o * o * o -# * o * o * o -# * o | _______/ -# | |/ -# | * 1 (MM1) -# | _______/ -# |/ -# * root (MMR) +test_expect_success 'set up G and H' ' + # E---D---C---B---A + # \"-_ \ \ + # \ `---------G \ + # \ \ + # F----------------H + E=$(doit 5 E) && + D=$(doit 4 D $E) && + F=$(doit 6 F $E) && + C=$(doit 3 C $D) && + B=$(doit 2 B $C) && + A=$(doit 1 A $B) && + G=$(doit 7 G $B $E) && + H=$(doit 8 H $A $F) +' + +test_expect_success 'merge-base G H' ' + git name-rev $B >expected && + + MB=$(git merge-base G H) && + git name-rev "$MB" >actual.single && + + MB=$(git merge-base --all G H) && + git name-rev "$MB" >actual.all && + + MB=$(git show-branch --merge-base G H) && + git name-rev "$MB" >actual.sb && + + test_cmp expected actual.single && + test_cmp expected actual.all && + test_cmp expected actual.sb +' +test_expect_success 'merge-base/show-branch --independent' ' + git name-rev "$H" >expected1 && + git name-rev "$H" "$G" >expected2 && + + parents=$(git merge-base --independent H) && + git name-rev $parents >actual1.mb && + parents=$(git merge-base --independent A H G) && + git name-rev $parents >actual2.mb && + + parents=$(git show-branch --independent H) && + git name-rev $parents >actual1.sb && + parents=$(git show-branch --independent A H G) && + git name-rev $parents >actual2.sb && + + test_cmp expected1 actual1.mb && + test_cmp expected2 actual2.mb && + test_cmp expected1 actual1.sb && + test_cmp expected2 actual2.sb +' + +test_expect_success 'unsynchronized clocks' ' + # This test is to demonstrate that relying on timestamps in a distributed + # SCM to provide a _consistent_ partial ordering of commits leads to + # insanity. + # + # Relative + # Structure timestamps + # + # PL PR +4 +4 + # / \/ \ / \/ \ + # L2 C2 R2 +3 -1 +3 + # | | | | | | + # L1 C1 R1 +2 -2 +2 + # | | | | | | + # L0 C0 R0 +1 -3 +1 + # \ | / \ | / + # S 0 + # + # The left and right chains of commits can be of any length and complexity as + # long as all of the timestamps are greater than that of S. + + S=$(doit 0 S) && + + C0=$(doit -3 C0 $S) && + C1=$(doit -2 C1 $C0) && + C2=$(doit -1 C2 $C1) && + + L0=$(doit 1 L0 $S) && + L1=$(doit 2 L1 $L0) && + L2=$(doit 3 L2 $L1) && + + R0=$(doit 1 R0 $S) && + R1=$(doit 2 R1 $R0) && + R2=$(doit 3 R2 $R1) && + + PL=$(doit 4 PL $L2 $C2) && + PR=$(doit 4 PR $C2 $R2) + + git name-rev $C2 >expected && + + MB=$(git merge-base PL PR) && + git name-rev "$MB" >actual.single && + + MB=$(git merge-base --all PL PR) && + git name-rev "$MB" >actual.all && + + test_cmp expected actual.single && + test_cmp expected actual.all +' + +test_expect_success '--independent with unsynchronized clocks' ' + IB=$(doit 0 IB) && + I1=$(doit -10 I1 $IB) && + I2=$(doit -9 I2 $I1) && + I3=$(doit -8 I3 $I2) && + I4=$(doit -7 I4 $I3) && + I5=$(doit -6 I5 $I4) && + I6=$(doit -5 I6 $I5) && + I7=$(doit -4 I7 $I6) && + I8=$(doit -3 I8 $I7) && + IH=$(doit -2 IH $I8) && + + echo $IH >expected && + git merge-base --independent IB IH >actual && + test_cmp expected actual +' test_expect_success 'merge-base for octopus-step (setup)' ' - test_tick && git commit --allow-empty -m root && git tag MMR && - test_tick && git commit --allow-empty -m 1 && git tag MM1 && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m A && git tag MMA && + # Another set to demonstrate base between one commit and a merge + # in the documentation. + # + # * C (MMC) * B (MMB) * A (MMA) + # * o * o * o + # * o * o * o + # * o * o * o + # * o | _______/ + # | |/ + # | * 1 (MM1) + # | _______/ + # |/ + # * root (MMR) + + test_commit MMR && + test_commit MM1 && + test_commit MM-o && + test_commit MM-p && + test_commit MM-q && + test_commit MMA && git checkout MM1 && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m B && git tag MMB && + test_commit MM-r && + test_commit MM-s && + test_commit MM-t && + test_commit MMB && git checkout MMR && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m C && git tag MMC + test_commit MM-u && + test_commit MM-v && + test_commit MM-w && + test_commit MM-x && + test_commit MMC ' test_expect_success 'merge-base A B C' ' - MB=$(git merge-base --all MMA MMB MMC) && - MM1=$(git rev-parse --verify MM1) && - test "$MM1" = "$MB" -' + git rev-parse --verify MM1 >expected && + git rev-parse --verify MMR >expected.sb && -test_expect_success 'merge-base A B C using show-branch' ' - MB=$(git show-branch --merge-base MMA MMB MMC) && - MMR=$(git rev-parse --verify MMR) && - test "$MMR" = "$MB" + git merge-base --all MMA MMB MMC >actual && + git merge-base --all --octopus MMA MMB MMC >actual.common && + git show-branch --merge-base MMA MMB MMC >actual.sb && + + test_cmp expected actual && + test_cmp expected.sb actual.common && + test_cmp expected.sb actual.sb ' -test_expect_success 'criss-cross merge-base for octopus-step (setup)' ' +test_expect_success 'criss-cross merge-base for octopus-step' ' git reset --hard MMR && - test_tick && git commit --allow-empty -m 1 && git tag CC1 && + test_commit CC1 && git reset --hard E && - test_tick && git commit --allow-empty -m 2 && git tag CC2 && - test_tick && git merge -s ours CC1 && - test_tick && git commit --allow-empty -m o && - test_tick && git commit --allow-empty -m B && git tag CCB && + test_commit CC2 && + test_tick && + git merge -s ours CC1 && + test_commit CC-o && + test_commit CCB && git reset --hard CC1 && - test_tick && git merge -s ours CC2 && - test_tick && git commit --allow-empty -m A && git tag CCA -' + git merge -s ours CC2 && + test_commit CCA && + + git rev-parse CC1 CC2 >expected && + git merge-base --all CCB CCA^^ CCA^^2 >actual && -test_expect_success 'merge-base B A^^ A^^2' ' - MB0=$(git merge-base --all CCB CCA^^ CCA^^2 | sort) && - MB1=$(git rev-parse CC1 CC2 | sort) && - test "$MB0" = "$MB1" + sort expected >expected.sorted && + sort actual >actual.sorted && + test_cmp expected.sorted actual.sorted ' test_done diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index 8d3fa7d014..fb8291c812 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -34,7 +34,9 @@ test_expect_success 'setup' ' git checkout master && commit master2 && git tag foo/bar master && - git update-ref refs/remotes/foo/baz master + commit master3 && + git update-ref refs/remotes/foo/baz master && + commit master4 ' test_expect_success 'rev-parse --glob=refs/heads/subspace/*' ' @@ -121,6 +123,12 @@ test_expect_success 'rev-list --glob=refs/heads/subspace/*' ' ' +test_expect_success 'rev-list --glob refs/heads/subspace/*' ' + + compare rev-list "subspace/one subspace/two" "--glob refs/heads/subspace/*" + +' + test_expect_success 'rev-list --glob=heads/subspace/*' ' compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/*" @@ -162,6 +170,13 @@ test_expect_success 'rev-list --branches=subspace' ' compare rev-list "subspace/one subspace/two" "--branches=subspace" ' + +test_expect_success 'rev-list --branches' ' + + compare rev-list "master subspace-x someref other/three subspace/one subspace/two" "--branches" + +' + test_expect_success 'rev-list --glob=heads/someref/* master' ' compare rev-list "master" "--glob=heads/someref/* master" @@ -186,6 +201,12 @@ test_expect_success 'rev-list --tags=foo' ' ' +test_expect_success 'rev-list --tags' ' + + compare rev-list "foo/bar" "--tags" + +' + test_expect_success 'rev-list --remotes=foo' ' compare rev-list "foo/baz" "--remotes=foo" diff --git a/t/t6019-rev-list-ancestry-path.sh b/t/t6019-rev-list-ancestry-path.sh new file mode 100755 index 0000000000..76410293b3 --- /dev/null +++ b/t/t6019-rev-list-ancestry-path.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='--ancestry-path' + +# D---E-------F +# / \ \ +# B---C---G---H---I---J +# / \ +# A-------K---------------L--M +# +# D..M == E F G H I J K L M +# --ancestry-path D..M == E F H I J L M +# +# D..M -- M.t == M +# --ancestry-path D..M -- M.t == M + +. ./test-lib.sh + +test_merge () { + test_tick && + git merge -s ours -m "$2" "$1" && + git tag "$2" +} + +test_expect_success setup ' + test_commit A && + test_commit B && + test_commit C && + test_commit D && + test_commit E && + test_commit F && + git reset --hard C && + test_commit G && + test_merge E H && + test_commit I && + test_merge F J && + git reset --hard A && + test_commit K && + test_merge J L && + test_commit M +' + +test_expect_success 'rev-list D..M' ' + for c in E F G H I J K L M; do echo $c; done >expect && + git rev-list --format=%s D..M | + sed -e "/^commit /d" | + sort >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list --ancestry-path D..M' ' + for c in E F H I J L M; do echo $c; done >expect && + git rev-list --ancestry-path --format=%s D..M | + sed -e "/^commit /d" | + sort >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list D..M -- M.t' ' + echo M >expect && + git rev-list --format=%s D..M -- M.t | + sed -e "/^commit /d" >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list --ancestry-patch D..M -- M.t' ' + echo M >expect && + git rev-list --ancestry-path --format=%s D..M -- M.t | + sed -e "/^commit /d" >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh index e71c687f2b..490d397114 100755 --- a/t/t6020-merge-df.sh +++ b/t/t6020-merge-df.sh @@ -22,7 +22,7 @@ git commit -m "File: dir"' test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master' -test_expect_failure 'F/D conflict' ' +test_expect_success 'F/D conflict' ' git reset --hard && git checkout master && rm .git/index && diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index e3f7ae8120..b66544b76d 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -280,7 +280,7 @@ test_expect_success 'updated working tree file should prevent the merge' ' echo "BAD: should have complained" return 1 } - diff M M.saved || { + test_cmp M M.saved || { echo "BAD: should have left M intact" return 1 } @@ -301,7 +301,7 @@ test_expect_success 'updated working tree file should prevent the merge' ' echo "BAD: should have complained" return 1 } - diff M M.saved || { + test_cmp M M.saved || { echo "BAD: should have left M intact" return 1 } diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh index 8a3304fb0b..1cd649e245 100755 --- a/t/t6031-merge-recursive.sh +++ b/t/t6031-merge-recursive.sh @@ -2,11 +2,7 @@ test_description='merge-recursive: handle file mode' . ./test-lib.sh - -if ! test "$(git config --bool core.filemode)" = false -then - test_set_prereq FILEMODE -fi +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh test_expect_success 'mode change in one branch: keep changed version' ' : >file1 && @@ -57,4 +53,35 @@ test_expect_success FILEMODE 'verify executable bit on file' ' test -x file2 ' +test_expect_success 'merging with triple rename across D/F conflict' ' + git reset --hard HEAD && + git checkout -b main && + git rm -rf . && + + echo "just a file" >sub1 && + mkdir -p sub2 && + echo content1 >sub2/file1 && + echo content2 >sub2/file2 && + echo content3 >sub2/file3 && + mkdir simple && + echo base >simple/bar && + git add -A && + test_tick && + git commit -m base && + + git checkout -b other && + echo more >>simple/bar && + test_tick && + git commit -a -m changesimplefile && + + git checkout main && + git rm sub1 && + git mv sub2 sub1 && + test_tick && + git commit -m changefiletodir && + + test_tick && + git merge other +' + test_done diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh index 3202e1de6d..92e02d5d77 100755 --- a/t/t6035-merge-dir-to-symlink.sh +++ b/t/t6035-merge-dir-to-symlink.sh @@ -3,13 +3,7 @@ test_description='merging when a directory was replaced with a symlink' . ./test-lib.sh -if ! test_have_prereq SYMLINKS -then - say 'Symbolic links not supported, skipping tests.' - test_done -fi - -test_expect_success 'create a commit where dir a/b changed to symlink' ' +test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' ' mkdir -p a/b/c a/b-2/c && > a/b/c/d && > a/b-2/c/d && @@ -23,7 +17,7 @@ test_expect_success 'create a commit where dir a/b changed to symlink' ' git commit -m "dir to symlink" ' -test_expect_success 'keep a/b-2/c/d across checkout' ' +test_expect_success SYMLINKS 'keep a/b-2/c/d across checkout' ' git checkout HEAD^0 && git reset --hard master && git rm --cached a/b && @@ -32,14 +26,14 @@ test_expect_success 'keep a/b-2/c/d across checkout' ' test -f a/b-2/c/d ' -test_expect_success 'checkout should not have deleted a/b-2/c/d' ' +test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' ' git checkout HEAD^0 && git reset --hard master && git checkout start^0 && test -f a/b-2/c/d ' -test_expect_success 'setup for merge test' ' +test_expect_success SYMLINKS 'setup for merge test' ' git reset --hard && test -f a/b-2/c/d && echo x > a/x && @@ -48,7 +42,7 @@ test_expect_success 'setup for merge test' ' git tag baseline ' -test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' ' +test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolve)' ' git reset --hard && git checkout baseline^0 && git merge -s resolve master && @@ -56,7 +50,7 @@ test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' ' test -f a/b-2/c/d ' -test_expect_failure 'do not lose a/b-2/c/d in merge (recursive)' ' +test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recursive)' ' git reset --hard && git checkout baseline^0 && git merge -s recursive master && @@ -64,7 +58,55 @@ test_expect_failure 'do not lose a/b-2/c/d in merge (recursive)' ' test -f a/b-2/c/d ' -test_expect_success 'setup a merge where dir a/b-2 changed to symlink' ' +test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolve)' ' + git reset --hard && + git checkout master^0 && + git merge -s resolve baseline^0 && + test -h a/b && + test -f a/b-2/c/d +' + +test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recursive)' ' + git reset --hard && + git checkout master^0 && + git merge -s recursive baseline^0 && + test -h a/b && + test -f a/b-2/c/d +' + +test_expect_failure SYMLINKS 'do not lose untracked in merge (resolve)' ' + git reset --hard && + git checkout baseline^0 && + >a/b/c/e && + test_must_fail git merge -s resolve master && + test -f a/b/c/e && + test -f a/b-2/c/d +' + +test_expect_success SYMLINKS 'do not lose untracked in merge (recursive)' ' + git reset --hard && + git checkout baseline^0 && + >a/b/c/e && + test_must_fail git merge -s recursive master && + test -f a/b/c/e && + test -f a/b-2/c/d +' + +test_expect_success SYMLINKS 'do not lose modifications in merge (resolve)' ' + git reset --hard && + git checkout baseline^0 && + echo more content >>a/b/c/d && + test_must_fail git merge -s resolve master +' + +test_expect_success SYMLINKS 'do not lose modifications in merge (recursive)' ' + git reset --hard && + git checkout baseline^0 && + echo more content >>a/b/c/d && + test_must_fail git merge -s recursive master +' + +test_expect_success SYMLINKS 'setup a merge where dir a/b-2 changed to symlink' ' git reset --hard && git checkout start^0 && rm -rf a/b-2 && @@ -74,7 +116,7 @@ test_expect_success 'setup a merge where dir a/b-2 changed to symlink' ' git tag test2 ' -test_expect_success 'merge should not have conflicts (resolve)' ' +test_expect_success SYMLINKS 'merge should not have D/F conflicts (resolve)' ' git reset --hard && git checkout baseline^0 && git merge -s resolve test2 && @@ -82,7 +124,7 @@ test_expect_success 'merge should not have conflicts (resolve)' ' test -f a/b/c/d ' -test_expect_failure 'merge should not have conflicts (recursive)' ' +test_expect_success SYMLINKS 'merge should not have D/F conflicts (recursive)' ' git reset --hard && git checkout baseline^0 && git merge -s recursive test2 && @@ -90,4 +132,12 @@ test_expect_failure 'merge should not have conflicts (recursive)' ' test -f a/b/c/d ' +test_expect_success SYMLINKS 'merge should not have F/D conflicts (recursive)' ' + git reset --hard && + git checkout -b foo test2 && + git merge -s recursive baseline^0 && + test -h a/b-2 && + test -f a/b/c/d +' + test_done diff --git a/t/t6037-merge-ours-theirs.sh b/t/t6037-merge-ours-theirs.sh index 8ab3d61f44..2cf42c73f1 100755 --- a/t/t6037-merge-ours-theirs.sh +++ b/t/t6037-merge-ours-theirs.sh @@ -58,7 +58,7 @@ test_expect_success 'pull with -X' ' git reset --hard master && git pull -s recursive -X ours . side && git reset --hard master && git pull -s recursive -Xtheirs . side && git reset --hard master && git pull -s recursive -X theirs . side && - git reset --hard master && ! git pull -s recursive -X bork . side + git reset --hard master && test_must_fail git pull -s recursive -X bork . side ' test_done diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh new file mode 100755 index 0000000000..460bf741b5 --- /dev/null +++ b/t/t6038-merge-text-auto.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +test_description='CRLF merge conflict across text=auto change + +* [master] remove .gitattributes + ! [side] add line from b +-- + + [side] add line from b +* [master] remove .gitattributes +* [master^] add line from a +* [master~2] normalize file +*+ [side^] Initial +' + +. ./test-lib.sh + +test_have_prereq MINGW && SED_OPTIONS=-b + +test_expect_success setup ' + git config core.autocrlf false && + + echo first line | append_cr >file && + echo first line >control_file && + echo only line >inert_file && + + git add file control_file inert_file && + test_tick && + git commit -m "Initial" && + git tag initial && + git branch side && + + echo "* text=auto" >.gitattributes && + touch file && + git add .gitattributes file && + test_tick && + git commit -m "normalize file" && + + echo same line | append_cr >>file && + echo same line >>control_file && + git add file control_file && + test_tick && + git commit -m "add line from a" && + git tag a && + + git rm .gitattributes && + rm file && + git checkout file && + test_tick && + git commit -m "remove .gitattributes" && + git tag c && + + git checkout side && + echo same line | append_cr >>file && + echo same line >>control_file && + git add file control_file && + test_tick && + git commit -m "add line from b" && + git tag b && + + git checkout master +' + +test_expect_success 'set up fuzz_conflict() helper' ' + fuzz_conflict() { + sed $SED_OPTIONS -e "s/^\([<>=]......\) .*/\1/" "$@" + } +' + +test_expect_success 'Merge after setting text=auto' ' + cat <<-\EOF >expected && + first line + same line + EOF + + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes && + git reset --hard a && + git merge b && + test_cmp expected file +' + +test_expect_success 'Merge addition of text=auto' ' + cat <<-\EOF >expected && + first line + same line + EOF + + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes && + git reset --hard b && + git merge a && + test_cmp expected file +' + +test_expect_success 'Detect CRLF/LF conflict after setting text=auto' ' + q_to_cr <<-\EOF >expected && + <<<<<<< + first line + same line + ======= + first lineQ + same lineQ + >>>>>>> + EOF + + git config merge.renormalize false && + rm -f .gitattributes && + git reset --hard a && + test_must_fail git merge b && + fuzz_conflict file >file.fuzzy && + test_cmp expected file.fuzzy +' + +test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' ' + q_to_cr <<-\EOF >expected && + <<<<<<< + first lineQ + same lineQ + ======= + first line + same line + >>>>>>> + EOF + + git config merge.renormalize false && + rm -f .gitattributes && + git reset --hard b && + test_must_fail git merge a && + fuzz_conflict file >file.fuzzy && + test_cmp expected file.fuzzy +' + +test_expect_failure 'checkout -m after setting text=auto' ' + cat <<-\EOF >expected && + first line + same line + EOF + + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes && + git reset --hard initial && + git checkout a -- . && + git checkout -m b && + test_cmp expected file +' + +test_expect_failure 'checkout -m addition of text=auto' ' + cat <<-\EOF >expected && + first line + same line + EOF + + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes file && + git reset --hard initial && + git checkout b -- . && + git checkout -m a && + test_cmp expected file +' + +test_expect_failure 'cherry-pick patch from after text=auto was added' ' + append_cr <<-\EOF >expected && + first line + same line + EOF + + git config merge.renormalize true && + git rm -fr . && + git reset --hard b && + test_must_fail git cherry-pick a >err 2>&1 && + grep "[Nn]othing added" err && + test_cmp expected file +' + +test_expect_success 'Test delete/normalize conflict' ' + git checkout -f side && + git rm -fr . && + rm -f .gitattributes && + git reset --hard initial && + git rm file && + git commit -m "remove file" && + git checkout master && + git reset --hard a^ && + git merge side +' + +test_done diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 203ffdb17a..95b180f469 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -104,17 +104,18 @@ test_expect_success '"git fsck" works' ' test_expect_success 'repack, clone and fetch work' ' git repack -a -d && git clone --no-hardlinks . clone_dir && - cd clone_dir && - git show HEAD~5 | grep "A U Thor" && - git show $HASH2 | grep "A U Thor" && - git cat-file commit $R && - git repack -a -d && - test_must_fail git cat-file commit $R && - git fetch ../ "refs/replace/*:refs/replace/*" && - git show HEAD~5 | grep "O Thor" && - git show $HASH2 | grep "O Thor" && - git cat-file commit $R && - cd .. + ( + cd clone_dir && + git show HEAD~5 | grep "A U Thor" && + git show $HASH2 | grep "A U Thor" && + git cat-file commit $R && + git repack -a -d && + test_must_fail git cat-file commit $R && + git fetch ../ "refs/replace/*:refs/replace/*" && + git show HEAD~5 | grep "O Thor" && + git show $HASH2 | grep "O Thor" && + git cat-file commit $R + ) ' test_expect_success '"git replace" listing and deleting' ' @@ -177,10 +178,11 @@ test_expect_success 'create parallel branch without the bug' ' test_expect_success 'push to cloned repo' ' git push cloned $HASH6^:refs/heads/parallel && - cd clone_dir && - git checkout parallel && - git log --pretty=oneline | grep $PARA2 && - cd .. + ( + cd clone_dir && + git checkout parallel && + git log --pretty=oneline | grep $PARA2 + ) ' test_expect_success 'push branch with replacement' ' @@ -191,25 +193,34 @@ test_expect_success 'push branch with replacement' ' git show $HASH6~2 | grep "O Thor" && git show $PARA3 | grep "O Thor" && git push cloned $HASH6^:refs/heads/parallel2 && - cd clone_dir && - git checkout parallel2 && - git log --pretty=oneline | grep $PARA3 && - git show $PARA3 | grep "A U Thor" && - cd .. + ( + cd clone_dir && + git checkout parallel2 && + git log --pretty=oneline | grep $PARA3 && + git show $PARA3 | grep "A U Thor" + ) ' test_expect_success 'fetch branch with replacement' ' git branch tofetch $HASH6 && - cd clone_dir && - git fetch origin refs/heads/tofetch:refs/heads/parallel3 - git log --pretty=oneline parallel3 | grep $PARA3 - git show $PARA3 | grep "A U Thor" - cd .. + ( + cd clone_dir && + git fetch origin refs/heads/tofetch:refs/heads/parallel3 && + git log --pretty=oneline parallel3 > output.txt && + ! grep $PARA3 output.txt && + git show $PARA3 > para3.txt && + grep "A U Thor" para3.txt && + git fetch origin "refs/replace/*:refs/replace/*" && + git log --pretty=oneline parallel3 > output.txt && + grep $PARA3 output.txt && + git show $PARA3 > para3.txt && + grep "O Thor" para3.txt + ) ' test_expect_success 'bisect and replacements' ' git bisect start $HASH7 $HASH1 && - test "$S" = "$(git rev-parse --verify HEAD)" && + test "$PARA3" = "$(git rev-parse --verify HEAD)" && git bisect reset && GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 && test "$HASH4" = "$(git rev-parse --verify HEAD)" && @@ -219,6 +230,12 @@ test_expect_success 'bisect and replacements' ' git bisect reset ' +test_expect_success 'index-pack and replacements' ' + git --no-replace-objects rev-list --objects HEAD | + git --no-replace-objects pack-objects test- && + git index-pack test-*.pack +' + # # test_done diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index f105fab98e..e673c25e94 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -6,7 +6,7 @@ test_description='Test git rev-parse with different parent options' . ./test-lib.sh -. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions date >path0 git update-index --add path0 diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 065deadc29..876d1ab743 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -8,7 +8,7 @@ test_description='test describe o----o----o----o----o----. / \ A c / .------------o---o---o - D e + D,R e ' . ./test-lib.sh @@ -68,6 +68,8 @@ test_expect_success setup ' echo D >another && git add another && git commit -m D && test_tick && git tag -a -m D D && + test_tick && + git tag -a -m R R && test_tick && echo DD >another && git commit -a -m another && @@ -89,10 +91,10 @@ test_expect_success setup ' check_describe A-* HEAD check_describe A-* HEAD^ -check_describe D-* HEAD^^ +check_describe R-* HEAD^^ check_describe A-* HEAD^^2 check_describe B HEAD^^2^ -check_describe D-* HEAD^^^ +check_describe R-* HEAD^^^ check_describe c-* --tags HEAD check_describe c-* --tags HEAD^ diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 42f8ece097..9a16806921 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -70,14 +70,13 @@ test_expect_success setup ' i=$(($i+1)) done && - git show-branch -' + git show-branch && -cat >expected <<\EOF -Merge branch 'left' -EOF + apos="'\''" +' -test_expect_success 'merge-msg test #1' ' +test_expect_success 'message for merging local branch' ' + echo "Merge branch ${apos}left${apos}" >expected && git checkout master && git fetch . left && @@ -86,11 +85,8 @@ test_expect_success 'merge-msg test #1' ' test_cmp expected actual ' -cat >expected <<EOF -Merge branch 'left' of $(pwd) -EOF - -test_expect_success 'merge-msg test #2' ' +test_expect_success 'message for merging external branch' ' + echo "Merge branch ${apos}left${apos} of $(pwd)" >expected && git checkout master && git fetch "$(pwd)" left && @@ -99,139 +95,231 @@ test_expect_success 'merge-msg test #2' ' test_cmp expected actual ' -cat >expected <<\EOF -Merge branch 'left' +test_expect_success '[merge] summary/log configuration' ' + cat >expected <<-EOF && + Merge branch ${apos}left${apos} -* left: - Left #5 - Left #4 - Left #3 - Common #2 - Common #1 -EOF + * left: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF -test_expect_success 'merge-msg test #3-1' ' - - git config --unset-all merge.log - git config --unset-all merge.summary git config merge.log true && + test_might_fail git config --unset-all merge.summary && git checkout master && test_tick && git fetch . left && - git fmt-merge-msg <.git/FETCH_HEAD >actual && - test_cmp expected actual -' - -test_expect_success 'merge-msg test #3-2' ' + git fmt-merge-msg <.git/FETCH_HEAD >actual1 && - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary true && git checkout master && test_tick && git fetch . left && - git fmt-merge-msg <.git/FETCH_HEAD >actual && + git fmt-merge-msg <.git/FETCH_HEAD >actual2 && + + test_cmp expected actual1 && + test_cmp expected actual2 +' + +test_expect_success 'setup: clear [merge] configuration' ' + test_might_fail git config --unset-all merge.log && + test_might_fail git config --unset-all merge.summary +' + +test_expect_success 'setup FETCH_HEAD' ' + git checkout master && + test_tick && + git fetch . left +' + +test_expect_success 'merge.log=3 limits shortlog length' ' + cat >expected <<-EOF && + Merge branch ${apos}left${apos} + + * left: (5 commits) + Left #5 + Left #4 + Left #3 + ... + EOF + + git -c merge.log=3 fmt-merge-msg <.git/FETCH_HEAD >actual && test_cmp expected actual ' -cat >expected <<\EOF -Merge branches 'left' and 'right' +test_expect_success 'merge.log=5 shows all 5 commits' ' + cat >expected <<-EOF && + Merge branch ${apos}left${apos} -* left: - Left #5 - Left #4 - Left #3 - Common #2 - Common #1 + * left: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF -* right: - Right #5 - Right #4 - Right #3 - Common #2 - Common #1 -EOF + git -c merge.log=5 fmt-merge-msg <.git/FETCH_HEAD >actual && + test_cmp expected actual +' -test_expect_success 'merge-msg test #4-1' ' +test_expect_success 'merge.log=0 disables shortlog' ' + echo "Merge branch ${apos}left${apos}" >expected + git -c merge.log=0 fmt-merge-msg <.git/FETCH_HEAD >actual && + test_cmp expected actual +' - git config --unset-all merge.log - git config --unset-all merge.summary - git config merge.log true && +test_expect_success '--log=3 limits shortlog length' ' + cat >expected <<-EOF && + Merge branch ${apos}left${apos} - git checkout master && - test_tick && - git fetch . left right && + * left: (5 commits) + Left #5 + Left #4 + Left #3 + ... + EOF - git fmt-merge-msg <.git/FETCH_HEAD >actual && + git fmt-merge-msg --log=3 <.git/FETCH_HEAD >actual && test_cmp expected actual ' -test_expect_success 'merge-msg test #4-2' ' +test_expect_success '--log=5 shows all 5 commits' ' + cat >expected <<-EOF && + Merge branch ${apos}left${apos} - git config --unset-all merge.log - git config --unset-all merge.summary - git config merge.summary true && + * left: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF - git checkout master && - test_tick && - git fetch . left right && + git fmt-merge-msg --log=5 <.git/FETCH_HEAD >actual && + test_cmp expected actual +' - git fmt-merge-msg <.git/FETCH_HEAD >actual && +test_expect_success '--no-log disables shortlog' ' + echo "Merge branch ${apos}left${apos}" >expected && + git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual && test_cmp expected actual ' -test_expect_success 'merge-msg test #5-1' ' +test_expect_success '--log=0 disables shortlog' ' + echo "Merge branch ${apos}left${apos}" >expected && + git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual && + test_cmp expected actual +' - git config --unset-all merge.log - git config --unset-all merge.summary - git config merge.log yes && +test_expect_success 'fmt-merge-msg -m' ' + echo "Sync with left" >expected && + cat >expected.log <<-EOF && + Sync with left + + * ${apos}left${apos} of $(pwd): + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF + + test_might_fail git config --unset merge.log && + test_might_fail git config --unset merge.summary && + git checkout master && + git fetch "$(pwd)" left && + git fmt-merge-msg -m "Sync with left" <.git/FETCH_HEAD >actual && + git fmt-merge-msg --log -m "Sync with left" \ + <.git/FETCH_HEAD >actual.log && + git config merge.log true && + git fmt-merge-msg -m "Sync with left" \ + <.git/FETCH_HEAD >actual.log-config && + git fmt-merge-msg --no-log -m "Sync with left" \ + <.git/FETCH_HEAD >actual.nolog && + + test_cmp expected actual && + test_cmp expected.log actual.log && + test_cmp expected.log actual.log-config && + test_cmp expected actual.nolog +' + +test_expect_success 'setup: expected shortlog for two branches' ' + cat >expected <<-EOF + Merge branches ${apos}left${apos} and ${apos}right${apos} + + * left: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + + * right: + Right #5 + Right #4 + Right #3 + Common #2 + Common #1 + EOF +' +test_expect_success 'shortlog for two branches' ' + git config merge.log true && + test_might_fail git config --unset-all merge.summary && git checkout master && test_tick && git fetch . left right && + git fmt-merge-msg <.git/FETCH_HEAD >actual1 && - git fmt-merge-msg <.git/FETCH_HEAD >actual && - test_cmp expected actual -' + test_might_fail git config --unset-all merge.log && + git config merge.summary true && + git checkout master && + test_tick && + git fetch . left right && + git fmt-merge-msg <.git/FETCH_HEAD >actual2 && -test_expect_success 'merge-msg test #5-2' ' + git config merge.log yes && + test_might_fail git config --unset-all merge.summary && + git checkout master && + test_tick && + git fetch . left right && + git fmt-merge-msg <.git/FETCH_HEAD >actual3 && - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary yes && - git checkout master && test_tick && git fetch . left right && + git fmt-merge-msg <.git/FETCH_HEAD >actual4 && - git fmt-merge-msg <.git/FETCH_HEAD >actual && - test_cmp expected actual + test_cmp expected actual1 && + test_cmp expected actual2 && + test_cmp expected actual3 && + test_cmp expected actual4 ' test_expect_success 'merge-msg -F' ' - - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary yes && - git checkout master && test_tick && git fetch . left right && - git fmt-merge-msg -F .git/FETCH_HEAD >actual && test_cmp expected actual ' test_expect_success 'merge-msg -F in subdirectory' ' - - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary yes && - git checkout master && test_tick && git fetch . left right && @@ -245,11 +333,11 @@ test_expect_success 'merge-msg -F in subdirectory' ' ' test_expect_success 'merge-msg with nothing to merge' ' - - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary yes && + >empty && + ( cd remote && git checkout -b unrelated && @@ -258,22 +346,20 @@ test_expect_success 'merge-msg with nothing to merge' ' git fmt-merge-msg <.git/FETCH_HEAD >../actual ) && - test_cmp /dev/null actual + test_cmp empty actual ' -cat >expected <<\EOF -Merge tag 'tag-r3' - -* tag 'tag-r3': - Right #3 - Common #2 - Common #1 -EOF - test_expect_success 'merge-msg tag' ' + cat >expected <<-EOF && + Merge tag ${apos}tag-r3${apos} + + * tag ${apos}tag-r3${apos}: + Right #3 + Common #2 + Common #1 + EOF - git config --unset-all merge.log - git config --unset-all merge.summary + test_might_fail git config --unset-all merge.log && git config merge.summary yes && git checkout master && @@ -284,26 +370,24 @@ test_expect_success 'merge-msg tag' ' test_cmp expected actual ' -cat >expected <<\EOF -Merge tags 'tag-r3' and 'tag-l5' - -* tag 'tag-r3': - Right #3 - Common #2 - Common #1 - -* tag 'tag-l5': - Left #5 - Left #4 - Left #3 - Common #2 - Common #1 -EOF - test_expect_success 'merge-msg two tags' ' - - git config --unset-all merge.log - git config --unset-all merge.summary + cat >expected <<-EOF && + Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos} + + * tag ${apos}tag-r3${apos}: + Right #3 + Common #2 + Common #1 + + * tag ${apos}tag-l5${apos}: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF + + test_might_fail git config --unset-all merge.log && git config merge.summary yes && git checkout master && @@ -314,26 +398,24 @@ test_expect_success 'merge-msg two tags' ' test_cmp expected actual ' -cat >expected <<\EOF -Merge branch 'left', tag 'tag-r3' - -* tag 'tag-r3': - Right #3 - Common #2 - Common #1 - -* left: - Left #5 - Left #4 - Left #3 - Common #2 - Common #1 -EOF - test_expect_success 'merge-msg tag and branch' ' - - git config --unset-all merge.log - git config --unset-all merge.summary + cat >expected <<-EOF && + Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos} + + * tag ${apos}tag-r3${apos}: + Right #3 + Common #2 + Common #1 + + * left: + Left #5 + Left #4 + Left #3 + Common #2 + Common #1 + EOF + + test_might_fail git config --unset-all merge.log && git config merge.summary yes && git checkout master && @@ -344,26 +426,27 @@ test_expect_success 'merge-msg tag and branch' ' test_cmp expected actual ' -cat >expected <<\EOF -Merge branch 'long' - -* long: (35 commits) -EOF - test_expect_success 'merge-msg lots of commits' ' + { + cat <<-EOF && + Merge branch ${apos}long${apos} + + * long: (35 commits) + EOF + + i=29 && + while test $i -gt 9 + do + echo " $i" && + i=$(($i-1)) + done && + echo " ..." + } >expected && git checkout master && test_tick && git fetch . long && - i=29 && - while test $i -gt 9 - do - echo " $i" && - i=$(($i-1)) - done >>expected && - echo " ..." >>expected - git fmt-merge-msg <.git/FETCH_HEAD >actual && test_cmp expected actual ' diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 8052c86ad3..7dc8a510c7 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -295,6 +295,15 @@ test_expect_success 'Check short upstream format' ' test_cmp expected actual ' +cat >expected <<EOF +67a36f1 +EOF + +test_expect_success 'Check short objectname format' ' + git for-each-ref --format="%(objectname:short)" refs/heads >actual && + test_cmp expected actual +' + test_expect_success 'Check for invalid refname format' ' test_must_fail git for-each-ref --format="%(refname:INVALID)" ' diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 0da13a8d6b..e0227730de 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -3,31 +3,34 @@ test_description='git filter-branch' . ./test-lib.sh -make_commit () { - lower=$(echo $1 | tr '[A-Z]' '[a-z]') - echo $lower > $lower - git add $lower - test_tick - git commit -m $1 - git tag $1 -} - test_expect_success 'setup' ' - make_commit A - make_commit B - git checkout -b branch B - make_commit D - mkdir dir - make_commit dir/D - make_commit E - git checkout master - make_commit C - git checkout branch - git merge C - git tag F - make_commit G - make_commit H -' + test_commit A && + test_commit B && + git checkout -b branch B && + test_commit D && + mkdir dir && + test_commit dir/D && + test_commit E && + git checkout master && + test_commit C && + git checkout branch && + git merge C && + git tag F && + test_commit G && + test_commit H +' +# * (HEAD, branch) H +# * G +# * Merge commit 'C' into branch +# |\ +# | * (master) C +# * | E +# * | dir/D +# * | D +# |/ +# * B +# * A + H=$(git rev-parse H) @@ -65,14 +68,14 @@ test_expect_success 'Fail if commit filter fails' ' ' test_expect_success 'rewrite, renaming a specific file' ' - git filter-branch -f --tree-filter "mv d doh || :" HEAD + git filter-branch -f --tree-filter "mv D.t doh || :" HEAD ' test_expect_success 'test that the file was renamed' ' - test d = "$(git show HEAD:doh --)" && - ! test -f d && + test D = "$(git show HEAD:doh --)" && + ! test -f D.t && test -f doh && - test d = "$(cat doh)" + test D = "$(cat doh)" ' test_expect_success 'rewrite, renaming a specific directory' ' @@ -80,18 +83,18 @@ test_expect_success 'rewrite, renaming a specific directory' ' ' test_expect_success 'test that the directory was renamed' ' - test dir/d = "$(git show HEAD:diroh/d --)" && + test dir/D = "$(git show HEAD:diroh/D.t --)" && ! test -d dir && test -d diroh && ! test -d diroh/dir && - test -f diroh/d && - test dir/d = "$(cat diroh/d)" + test -f diroh/D.t && + test dir/D = "$(cat diroh/D.t)" ' git tag oldD HEAD~4 test_expect_success 'rewrite one branch, keeping a side branch' ' git branch modD oldD && - git filter-branch -f --tree-filter "mv b boh || :" D..modD + git filter-branch -f --tree-filter "mv B.t boh || :" D..modD ' test_expect_success 'common ancestor is still common (unchanged)' ' @@ -104,13 +107,13 @@ test_expect_success 'filter subdirectory only' ' git add subdir/new && test_tick && git commit -m "subdir" && - echo H > a && + echo H > A.t && test_tick && - git commit -m "not subdir" a && + git commit -m "not subdir" A.t && echo A > subdir/new && test_tick && git commit -m "again subdir" subdir/new && - git rm a && + git rm A.t && test_tick && git commit -m "again not subdir" && git branch sub && @@ -134,7 +137,7 @@ test_expect_success 'more setup' ' git add subdir/new && test_tick && git commit -m "subdir on master" subdir/new && - git rm a && + git rm A.t && test_tick && git commit -m "again subdir on master" && git merge branch @@ -143,11 +146,12 @@ test_expect_success 'more setup' ' test_expect_success 'use index-filter to move into a subdirectory' ' git branch directorymoved && git filter-branch -f --index-filter \ - "git ls-files -s | sed \"s-\\t-&newsubdir/-\" | + "git ls-files -s | sed \"s- -&newsubdir/-\" | GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \ git update-index --index-info && mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved && - test -z "$(git diff HEAD directorymoved:newsubdir)"' + git diff --exit-code HEAD directorymoved:newsubdir +' test_expect_success 'stops when msg filter fails' ' old=$(git rev-parse HEAD) && @@ -282,8 +286,8 @@ test_expect_success 'Tag name filtering allows slashes in tag names' ' test_expect_success 'Prune empty commits' ' git rev-list HEAD > expect && - make_commit to_remove && - git filter-branch -f --index-filter "git update-index --remove to_remove" --prune-empty HEAD && + test_commit to_remove && + git filter-branch -f --index-filter "git update-index --remove to_remove.t" --prune-empty HEAD && git rev-list HEAD > actual && test_cmp expect actual ' @@ -306,6 +310,24 @@ test_expect_success '--remap-to-ancestor with filename filters' ' test $orig_invariant = $(git rev-parse invariant) ' +test_expect_success 'automatic remapping to ancestor with filename filters' ' + git checkout master && + git reset --hard A && + test_commit add-foo2 foo 1 && + git branch moved-foo2 && + test_commit add-bar2 bar a && + git branch invariant2 && + orig_invariant=$(git rev-parse invariant2) && + git branch moved-bar2 && + test_commit change-foo2 foo 2 && + git filter-branch -f \ + moved-foo2 moved-bar2 A..master \ + -- -- foo && + test $(git rev-parse moved-foo2) = $(git rev-parse moved-bar2) && + test $(git rev-parse moved-foo2) = $(git rev-parse master^) && + test $orig_invariant = $(git rev-parse invariant2) +' + test_expect_success 'setup submodule' ' rm -fr ?* .git && git init && diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 73dbc4360b..ac943f5eee 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -583,7 +583,7 @@ test_expect_success \ # 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" + 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 diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 5257f4d261..1b530b5022 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -13,7 +13,7 @@ test_expect_success 'determine default editor' ' ' -if ! expr "$vi" : '^[a-z]*$' >/dev/null +if ! expr "$vi" : '[a-z]*$' >/dev/null then vi= fi @@ -38,7 +38,7 @@ test_expect_success setup ' test_commit "$msg" && echo "$msg" >expect && git show -s --format=%s > actual && - diff actual expect + test_cmp actual expect ' @@ -85,7 +85,7 @@ do git --exec-path=. commit --amend && git show -s --pretty=oneline | sed -e "s/^[0-9a-f]* //" >actual && - diff actual expect + test_cmp actual expect ' done @@ -107,17 +107,17 @@ do git --exec-path=. commit --amend && git show -s --pretty=oneline | sed -e "s/^[0-9a-f]* //" >actual && - diff actual expect + test_cmp actual expect ' done -if ! echo 'echo space > "$1"' > "e space.sh" +if echo 'echo space > "$1"' > "e space.sh" then - say "Skipping; FS does not support spaces in filenames" - test_done + # FS supports spaces in filenames + test_set_prereq SPACES_IN_FILENAMES fi -test_expect_success 'editor with a space' ' +test_expect_success SPACES_IN_FILENAMES 'editor with a space' ' chmod a+x "e space.sh" && GIT_EDITOR="./e\ space.sh" git commit --amend && @@ -126,7 +126,7 @@ test_expect_success 'editor with a space' ' ' unset GIT_EDITOR -test_expect_success 'core.editor with a space' ' +test_expect_success SPACES_IN_FILENAMES 'core.editor with a space' ' git config core.editor \"./e\ space.sh\" && git commit --amend && diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index d9202d5af5..fb744e3c4a 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -3,18 +3,26 @@ test_description='Test automatic use of a pager.' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-pager.sh + +cleanup_fail() { + echo >&2 cleanup failed + (exit 1) +} -rm -f stdout_is_tty test_expect_success 'set up terminal for tests' ' + rm -f stdout_is_tty || + cleanup_fail && + if test -t 1 then - : > stdout_is_tty + >stdout_is_tty elif test_have_prereq PERL && "$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl \ sh -c "test -t 1" then - : > test_terminal_works + >test_terminal_works fi ' @@ -29,148 +37,402 @@ then } test_set_prereq TTY else - say no usable terminal, so skipping some tests + say "# no usable terminal, so skipping some tests" fi -unset GIT_PAGER GIT_PAGER_IN_USE -git config --unset core.pager -PAGER='cat > paginated.out' -export PAGER - test_expect_success 'setup' ' + unset GIT_PAGER GIT_PAGER_IN_USE; + test_might_fail git config --unset core.pager && + + PAGER="cat >paginated.out" && + export PAGER && + test_commit initial ' -rm -f paginated.out test_expect_success TTY 'some commands use a pager' ' + rm -f paginated.out || + cleanup_fail && + test_terminal git log && test -e paginated.out ' -rm -f paginated.out +test_expect_failure TTY 'pager runs from subdir' ' + echo subdir/paginated.out >expected && + mkdir -p subdir && + rm -f paginated.out subdir/paginated.out && + ( + cd subdir && + test_terminal git log + ) && + { + ls paginated.out subdir/paginated.out || + : + } >actual && + test_cmp expected actual +' + test_expect_success TTY 'some commands do not use a pager' ' + rm -f paginated.out || + cleanup_fail && + test_terminal git rev-list HEAD && ! test -e paginated.out ' -rm -f paginated.out test_expect_success 'no pager when stdout is a pipe' ' + rm -f paginated.out || + cleanup_fail && + git log | cat && ! test -e paginated.out ' -rm -f paginated.out test_expect_success 'no pager when stdout is a regular file' ' - git log > file && + rm -f paginated.out || + cleanup_fail && + + git log >file && ! test -e paginated.out ' -rm -f paginated.out test_expect_success TTY 'git --paginate rev-list uses a pager' ' + rm -f paginated.out || + cleanup_fail && + test_terminal git --paginate rev-list HEAD && test -e paginated.out ' -rm -f file paginated.out test_expect_success 'no pager even with --paginate when stdout is a pipe' ' + rm -f file paginated.out || + cleanup_fail && + git --paginate log | cat && ! test -e paginated.out ' -rm -f paginated.out test_expect_success TTY 'no pager with --no-pager' ' + rm -f paginated.out || + cleanup_fail && + test_terminal git --no-pager log && ! test -e paginated.out ' +test_expect_success TTY 'configuration can disable pager' ' + rm -f paginated.out && + test_might_fail git config --unset pager.grep && + test_terminal git grep initial && + test -e paginated.out && + + rm -f paginated.out && + git config pager.grep false && + test_when_finished "git config --unset pager.grep" && + test_terminal git grep initial && + ! test -e paginated.out +' + +test_expect_success TTY 'git config uses a pager if configured to' ' + rm -f paginated.out && + git config pager.config true && + test_when_finished "git config --unset pager.config" && + test_terminal git config --list && + test -e paginated.out +' + +test_expect_success TTY 'configuration can enable pager (from subdir)' ' + rm -f paginated.out && + mkdir -p subdir && + git config pager.bundle true && + test_when_finished "git config --unset pager.bundle" && + + git bundle create test.bundle --all && + rm -f paginated.out subdir/paginated.out && + ( + cd subdir && + test_terminal git bundle unbundle ../test.bundle + ) && + { + test -e paginated.out || + test -e subdir/paginated.out + } +' + # A colored commit log will begin with an appropriate ANSI escape # for the first color; the text "commit" comes later. colorful() { - read firstline < $1 - ! expr "$firstline" : "^[a-zA-Z]" >/dev/null + read firstline <$1 + ! expr "$firstline" : "[a-zA-Z]" >/dev/null } -rm -f colorful.log colorless.log test_expect_success 'tests can detect color' ' - git log --no-color > colorless.log && - git log --color > colorful.log && + rm -f colorful.log colorless.log || + cleanup_fail && + + git log --no-color >colorless.log && + git log --color >colorful.log && ! colorful colorless.log && colorful colorful.log ' -rm -f colorless.log -git config color.ui auto test_expect_success 'no color when stdout is a regular file' ' - git log > colorless.log && + rm -f colorless.log && + git config color.ui auto || + cleanup_fail && + + git log >colorless.log && ! colorful colorless.log ' -rm -f paginated.out -git config color.ui auto test_expect_success TTY 'color when writing to a pager' ' - TERM=vt100 test_terminal git log && + rm -f paginated.out && + git config color.ui auto || + cleanup_fail && + + ( + TERM=vt100 && + export TERM && + test_terminal git log + ) && colorful paginated.out ' -rm -f colorful.log -git config color.ui auto test_expect_success 'color when writing to a file intended for a pager' ' - TERM=vt100 GIT_PAGER_IN_USE=true git log > colorful.log && - colorful colorful.log -' + rm -f colorful.log && + git config color.ui auto || + cleanup_fail && -unset PAGER GIT_PAGER -git config --unset core.pager -test_expect_success 'determine default pager' ' - less=$(git var GIT_PAGER) && - test -n "$less" + ( + TERM=vt100 && + GIT_PAGER_IN_USE=true && + export TERM GIT_PAGER_IN_USE && + git log >colorful.log + ) && + colorful colorful.log ' -if expr "$less" : '^[a-z]*$' > /dev/null && test_have_prereq TTY +if test_have_prereq SIMPLEPAGER && test_have_prereq TTY then - test_set_prereq SIMPLEPAGER + test_set_prereq SIMPLEPAGERTTY fi -unset PAGER GIT_PAGER -git config --unset core.pager -rm -f default_pager_used -test_expect_success SIMPLEPAGER 'default pager is used by default' ' - cat > $less <<-EOF && - #!$SHELL_PATH - wc > default_pager_used - EOF - chmod +x $less && - PATH=.:$PATH test_terminal git log && - test -e default_pager_used -' - -unset GIT_PAGER -git config --unset core.pager -rm -f PAGER_used -test_expect_success TTY 'PAGER overrides default pager' ' - PAGER="wc > PAGER_used" && - export PAGER && - test_terminal git log && - test -e PAGER_used -' +# Use this helper to make it easy for the caller of your +# terminal-using function to specify whether it should fail. +# If you write +# +# your_test() { +# parse_args "$@" +# +# $test_expectation "$cmd - behaves well" " +# ... +# $full_command && +# ... +# " +# } +# +# then your test can be used like this: +# +# your_test expect_(success|failure) [test_must_fail] 'git foo' +# +parse_args() { + test_expectation="test_$1" + shift + if test "$1" = test_must_fail + then + full_command="test_must_fail test_terminal " + shift + else + full_command="test_terminal " + fi + cmd=$1 + full_command="$full_command $1" +} -unset GIT_PAGER -rm -f core.pager_used -test_expect_success TTY 'core.pager overrides PAGER' ' - PAGER=wc && - export PAGER && - git config core.pager "wc > core.pager_used" && - test_terminal git log && - test -e core.pager_used +test_default_pager() { + parse_args "$@" + + $test_expectation SIMPLEPAGERTTY "$cmd - default pager is used by default" " + unset PAGER GIT_PAGER; + test_might_fail git config --unset core.pager && + rm -f default_pager_used || + cleanup_fail && + + cat >\$less <<-\EOF && + #!/bin/sh + wc >default_pager_used + EOF + chmod +x \$less && + ( + PATH=.:\$PATH && + export PATH && + $full_command + ) && + test -e default_pager_used + " +} + +test_PAGER_overrides() { + parse_args "$@" + + $test_expectation TTY "$cmd - PAGER overrides default pager" " + unset GIT_PAGER; + test_might_fail git config --unset core.pager && + rm -f PAGER_used || + cleanup_fail && + + PAGER='wc >PAGER_used' && + export PAGER && + $full_command && + test -e PAGER_used + " +} + +test_core_pager_overrides() { + if_local_config= + used_if_wanted='overrides PAGER' + test_core_pager "$@" +} + +test_local_config_ignored() { + if_local_config='! ' + used_if_wanted='is not used' + test_core_pager "$@" +} + +test_core_pager() { + parse_args "$@" + + $test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" " + unset GIT_PAGER; + rm -f core.pager_used || + cleanup_fail && + + PAGER=wc && + export PAGER && + git config core.pager 'wc >core.pager_used' && + $full_command && + ${if_local_config}test -e core.pager_used + " +} + +test_core_pager_subdir() { + if_local_config= + used_if_wanted='overrides PAGER' + test_pager_subdir_helper "$@" +} + +test_no_local_config_subdir() { + if_local_config='! ' + used_if_wanted='is not used' + test_pager_subdir_helper "$@" +} + +test_pager_subdir_helper() { + parse_args "$@" + + $test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" " + unset GIT_PAGER; + rm -f core.pager_used && + rm -fr sub || + cleanup_fail && + + PAGER=wc && + stampname=\$(pwd)/core.pager_used && + export PAGER stampname && + git config core.pager 'wc >\"\$stampname\"' && + mkdir sub && + ( + cd sub && + $full_command + ) && + ${if_local_config}test -e core.pager_used + " +} + +test_GIT_PAGER_overrides() { + parse_args "$@" + + $test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" " + rm -f GIT_PAGER_used || + cleanup_fail && + + git config core.pager wc && + GIT_PAGER='wc >GIT_PAGER_used' && + export GIT_PAGER && + $full_command && + test -e GIT_PAGER_used + " +} + +test_doesnt_paginate() { + parse_args "$@" + + $test_expectation TTY "no pager for '$cmd'" " + rm -f GIT_PAGER_used || + cleanup_fail && + + GIT_PAGER='wc >GIT_PAGER_used' && + export GIT_PAGER && + $full_command && + ! test -e GIT_PAGER_used + " +} + +test_pager_choices() { + test_default_pager expect_success "$@" + test_PAGER_overrides expect_success "$@" + test_core_pager_overrides expect_success "$@" + test_core_pager_subdir expect_success "$@" + test_GIT_PAGER_overrides expect_success "$@" +} + +test_expect_success 'setup: some aliases' ' + git config alias.aliasedlog log && + git config alias.true "!true" ' -rm -f GIT_PAGER_used -test_expect_success TTY 'GIT_PAGER overrides core.pager' ' - git config core.pager wc && - GIT_PAGER="wc > GIT_PAGER_used" && - export GIT_PAGER && - test_terminal git log && - test -e GIT_PAGER_used +test_pager_choices 'git log' +test_pager_choices 'git -p log' +test_pager_choices 'git aliasedlog' + +test_default_pager expect_success 'git -p aliasedlog' +test_PAGER_overrides expect_success 'git -p aliasedlog' +test_core_pager_overrides expect_success 'git -p aliasedlog' +test_core_pager_subdir expect_failure 'git -p aliasedlog' +test_GIT_PAGER_overrides expect_success 'git -p aliasedlog' + +test_default_pager expect_success 'git -p true' +test_PAGER_overrides expect_success 'git -p true' +test_core_pager_overrides expect_success 'git -p true' +test_core_pager_subdir expect_failure 'git -p true' +test_GIT_PAGER_overrides expect_success 'git -p true' + +test_default_pager expect_success test_must_fail 'git -p request-pull' +test_PAGER_overrides expect_success test_must_fail 'git -p request-pull' +test_core_pager_overrides expect_success test_must_fail 'git -p request-pull' +test_core_pager_subdir expect_failure test_must_fail 'git -p request-pull' +test_GIT_PAGER_overrides expect_success test_must_fail 'git -p request-pull' + +test_default_pager expect_success test_must_fail 'git -p' +test_PAGER_overrides expect_success test_must_fail 'git -p' +test_local_config_ignored expect_failure test_must_fail 'git -p' +test_no_local_config_subdir expect_success test_must_fail 'git -p' +test_GIT_PAGER_overrides expect_success test_must_fail 'git -p' + +test_doesnt_paginate expect_failure test_must_fail 'git -p nonsense' + +test_pager_choices 'git shortlog' +test_expect_success 'setup: configure shortlog not to paginate' ' + git config pager.shortlog false ' +test_doesnt_paginate expect_success 'git shortlog' +test_no_local_config_subdir expect_success 'git shortlog' +test_default_pager expect_success 'git -p shortlog' +test_core_pager_subdir expect_success 'git -p shortlog' + +test_core_pager_subdir expect_success test_must_fail \ + 'git -p apply </dev/null' test_done diff --git a/t/t7006/test-terminal.perl b/t/t7006/test-terminal.perl index 73ff809371..6b5f22ae4a 100755 --- a/t/t7006/test-terminal.perl +++ b/t/t7006/test-terminal.perl @@ -1,4 +1,5 @@ #!/usr/bin/perl +use 5.008; use strict; use warnings; use IO::Pty; diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh new file mode 100755 index 0000000000..e058d184d1 --- /dev/null +++ b/t/t7008-grep-binary.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='git grep in binary files' + +. ./test-lib.sh + +test_expect_success 'setup' " + echo 'binaryQfile' | q_to_nul >a && + git add a && + git commit -m. +" + +test_expect_success 'git grep ina a' ' + echo Binary file a matches >expect && + git grep ina a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -ah ina a' ' + git grep -ah ina a >actual && + test_cmp a actual +' + +test_expect_success 'git grep -I ina a' ' + : >expect && + test_must_fail git grep -I ina a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -c ina a' ' + echo a:1 >expect && + git grep -c ina a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -l ina a' ' + echo a >expect && + git grep -l ina a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -L bar a' ' + echo a >expect && + git grep -L bar a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -q ina a' ' + : >expect && + git grep -q ina a >actual && + test_cmp expect actual +' + +test_expect_success 'git grep -F ile a' ' + git grep -F ile a +' + +test_expect_success 'git grep -Fi iLE a' ' + git grep -Fi iLE a +' + +# This test actually passes on platforms where regexec() supports the +# flag REG_STARTEND. +test_expect_success 'git grep ile a' ' + git grep ile a +' + +test_expect_failure 'git grep .fi a' ' + git grep .fi a +' + +test_expect_success 'git grep -F y<NUL>f a' " + printf 'yQf' | q_to_nul >f && + git grep -f f -F a +" + +test_expect_success 'git grep -F y<NUL>x a' " + printf 'yQx' | q_to_nul >f && + test_must_fail git grep -f f -F a +" + +test_expect_success 'git grep -Fi Y<NUL>f a' " + printf 'YQf' | q_to_nul >f && + git grep -f f -Fi a +" + +test_expect_failure 'git grep -Fi Y<NUL>x a' " + printf 'YQx' | q_to_nul >f && + test_must_fail git grep -f f -Fi a +" + +test_expect_success 'git grep y<NUL>f a' " + printf 'yQf' | q_to_nul >f && + git grep -f f a +" + +test_expect_failure 'git grep y<NUL>x a' " + printf 'yQx' | q_to_nul >f && + test_must_fail git grep -f f a +" + +test_done diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh index d8a7c79852..0335a9a158 100755 --- a/t/t7010-setup.sh +++ b/t/t7010-setup.sh @@ -103,14 +103,10 @@ test_expect_success 'git ls-files (relative #3)' ' git add a && ( cd a/b && - if git ls-files "../e/f" - then - echo Gaah, should have failed - exit 1 - else - : happy - fi - ) + git ls-files "../e/f" + ) >current && + echo ../e/f >expect && + test_cmp expect current ' diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh index c1f4fc3c65..9891e2c1f5 100755 --- a/t/t7105-reset-patch.sh +++ b/t/t7105-reset-patch.sh @@ -3,7 +3,7 @@ test_description='git reset --patch' . ./lib-patch-mode.sh -test_expect_success 'setup' ' +test_expect_success PERL 'setup' ' mkdir dir && echo parent > dir/foo && echo dummy > bar && @@ -17,20 +17,20 @@ test_expect_success 'setup' ' # note: bar sorts before foo, so the first 'n' is always to skip 'bar' -test_expect_success 'saying "n" does nothing' ' +test_expect_success PERL 'saying "n" does nothing' ' set_and_save_state dir/foo work work (echo n; echo n) | git reset -p && verify_saved_state dir/foo && verify_saved_state bar ' -test_expect_success 'git reset -p' ' +test_expect_success PERL 'git reset -p' ' (echo n; echo y) | git reset -p && verify_state dir/foo work head && verify_saved_state bar ' -test_expect_success 'git reset -p HEAD^' ' +test_expect_success PERL 'git reset -p HEAD^' ' (echo n; echo y) | git reset -p HEAD^ && verify_state dir/foo work parent && verify_saved_state bar @@ -41,27 +41,27 @@ test_expect_success 'git reset -p HEAD^' ' # dir/foo. There's always an extra 'n' to reject edits to dir/foo in # the failure case (and thus get out of the loop). -test_expect_success 'git reset -p dir' ' +test_expect_success PERL 'git reset -p dir' ' set_state dir/foo work work (echo y; echo n) | git reset -p dir && verify_state dir/foo work head && verify_saved_state bar ' -test_expect_success 'git reset -p -- foo (inside dir)' ' +test_expect_success PERL 'git reset -p -- foo (inside dir)' ' set_state dir/foo work work (echo y; echo n) | (cd dir && git reset -p -- foo) && verify_state dir/foo work head && verify_saved_state bar ' -test_expect_success 'git reset -p HEAD^ -- dir' ' +test_expect_success PERL 'git reset -p HEAD^ -- dir' ' (echo y; echo n) | git reset -p HEAD^ -- dir && verify_state dir/foo work parent && verify_saved_state bar ' -test_expect_success 'none of this moved HEAD' ' +test_expect_success PERL 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 7d8ed68bef..6c776e9bec 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -388,16 +388,15 @@ test_expect_success 'core.excludesfile' ' ' -test_expect_success 'removal failure' ' +test_expect_success SANITY 'removal failure' ' mkdir foo && touch foo/bar && (exec <foo/bar && chmod 0 foo && - test_must_fail git clean -f -d) - + test_must_fail git clean -f -d && + chmod 755 foo) ' -chmod 755 foo test_expect_success 'nested git work tree' ' rm -fr foo bar && @@ -438,4 +437,20 @@ test_expect_success 'force removal of nested git work tree' ' ! test -d bar ' +test_expect_success 'git clean -e' ' + rm -fr repo && + mkdir repo && + ( + cd repo && + git init && + touch known 1 2 3 && + git add known && + git clean -f -e 1 -e 2 && + test -e 1 && + test -e 2 && + ! (test -e 3) && + test -e known + ) +' + test_done diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 1a4dc5f893..782b0a3ece 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -11,226 +11,317 @@ subcommands of git submodule. . ./test-lib.sh -# -# Test setup: -# -create a repository in directory init -# -add a couple of files -# -add directory init to 'superproject', this creates a DIRLINK entry -# -add a couple of regular files to enable testing of submodule filtering -# -mv init subrepo -# -add an entry to .gitmodules for submodule 'example' -# -test_expect_success 'Prepare submodule testing' ' - : > t && +test_expect_success 'setup - initial commit' ' + >t && git add t && git commit -m "initial commit" && - git branch initial HEAD && + git branch initial +' + +test_expect_success 'setup - repository in init subdirectory' ' mkdir init && - cd init && - git init && - echo a >a && - git add a && - git commit -m "submodule commit 1" && - git tag -a -m "rev-1" rev-1 && - rev1=$(git rev-parse HEAD) && - if test -z "$rev1" - then - echo "[OOPS] submodule git rev-parse returned nothing" - false - fi && - cd .. && + ( + cd init && + git init && + echo a >a && + git add a && + git commit -m "submodule commit 1" && + git tag -a -m "rev-1" rev-1 + ) +' + +test_expect_success 'setup - commit with gitlink' ' echo a >a && echo z >z && git add a init z && - git commit -m "super commit 1" && - mv init .subrepo && - GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git + git commit -m "super commit 1" ' -test_expect_success 'Prepare submodule add testing' ' - submodurl=$(pwd) +test_expect_success 'setup - hide init subdirectory' ' + mv init .subrepo +' + +test_expect_success 'setup - repository to add submodules to' ' + git init addtest && + git init addtest-ignore +' + +# The 'submodule add' tests need some repository to add as a submodule. +# The trash directory is a good one as any. +submodurl=$TRASH_DIRECTORY + +listbranches() { + git for-each-ref --format='%(refname)' 'refs/heads/*' +} + +inspect() { + dir=$1 && + dotdot="${2:-..}" && + ( - mkdir addtest && - cd addtest && - git init + cd "$dir" && + listbranches >"$dotdot/heads" && + { git symbolic-ref HEAD || :; } >"$dotdot/head" && + git rev-parse HEAD >"$dotdot/head-sha1" && + git update-index --refresh && + git diff-files --exit-code && + git clean -n -d -x >"$dotdot/untracked" ) -' +} test_expect_success 'submodule add' ' + echo "refs/heads/master" >expect && + >empty && + ( cd addtest && git submodule add "$submodurl" submod && git submodule init + ) && + + rm -f heads head untracked && + inspect addtest/submod ../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked +' + +test_expect_success 'submodule add to .gitignored path fails' ' + ( + cd addtest-ignore && + cat <<-\EOF >expect && + The following path is ignored by one of your .gitignore files: + submod + Use -f if you really want to add it. + EOF + # Does not use test_commit due to the ignore + echo "*" > .gitignore && + git add --force .gitignore && + git commit -m"Ignore everything" && + ! git submodule add "$submodurl" submod >actual 2>&1 && + test_cmp expect actual + ) +' + +test_expect_success 'submodule add to .gitignored path with --force' ' + ( + cd addtest-ignore && + git submodule add --force "$submodurl" submod ) ' test_expect_success 'submodule add --branch' ' + echo "refs/heads/initial" >expect-head && + cat <<-\EOF >expect-heads && + refs/heads/initial + refs/heads/master + EOF + >empty && + ( cd addtest && git submodule add -b initial "$submodurl" submod-branch && - git submodule init && - cd submod-branch && - git branch | grep initial - ) + git submodule init + ) && + + rm -f heads head untracked && + inspect addtest/submod-branch ../.. && + test_cmp expect-heads heads && + test_cmp expect-head head && + test_cmp empty untracked ' test_expect_success 'submodule add with ./ in path' ' + echo "refs/heads/master" >expect && + >empty && + ( cd addtest && git submodule add "$submodurl" ././dotsubmod/./frotz/./ && git submodule init - ) + ) && + + rm -f heads head untracked && + inspect addtest/dotsubmod/frotz ../../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked ' test_expect_success 'submodule add with // in path' ' + echo "refs/heads/master" >expect && + >empty && + ( cd addtest && git submodule add "$submodurl" slashslashsubmod///frotz// && git submodule init - ) + ) && + + rm -f heads head untracked && + inspect addtest/slashslashsubmod/frotz ../../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked ' test_expect_success 'submodule add with /.. in path' ' + echo "refs/heads/master" >expect && + >empty && + ( cd addtest && git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. && git submodule init - ) + ) && + + rm -f heads head untracked && + inspect addtest/realsubmod ../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked ' test_expect_success 'submodule add with ./, /.. and // in path' ' + echo "refs/heads/master" >expect && + >empty && + ( cd addtest && git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. && git submodule init - ) + ) && + + rm -f heads head untracked && + inspect addtest/realsubmod2 ../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked +' + +test_expect_success 'setup - add an example entry to .gitmodules' ' + GIT_CONFIG=.gitmodules \ + git config submodule.example.url git://example.com/init.git ' test_expect_success 'status should fail for unmapped paths' ' - if git submodule status - then - echo "[OOPS] submodule status succeeded" - false - elif ! GIT_CONFIG=.gitmodules git config submodule.example.path init - then - echo "[OOPS] git config failed to update .gitmodules" - false - fi + test_must_fail git submodule status +' + +test_expect_success 'setup - map path in .gitmodules' ' + cat <<\EOF >expect && +[submodule "example"] + url = git://example.com/init.git + path = init +EOF + + GIT_CONFIG=.gitmodules git config submodule.example.path init && + + test_cmp expect .gitmodules ' test_expect_success 'status should only print one line' ' - lines=$(git submodule status | wc -l) && - test $lines = 1 + git submodule status >lines && + test $(wc -l <lines) = 1 +' + +test_expect_success 'setup - fetch commit name from submodule' ' + rev1=$(cd .subrepo && git rev-parse HEAD) && + printf "rev1: %s\n" "$rev1" && + test -n "$rev1" ' test_expect_success 'status should initially be "missing"' ' - git submodule status | grep "^-$rev1" + git submodule status >lines && + grep "^-$rev1" lines ' test_expect_success 'init should register submodule url in .git/config' ' + echo git://example.com/init.git >expect && + git submodule init && - url=$(git config submodule.example.url) && - if test "$url" != "git://example.com/init.git" - then - echo "[OOPS] init succeeded but submodule url is wrong" - false - elif test_must_fail git config submodule.example.url ./.subrepo - then - echo "[OOPS] init succeeded but update of url failed" - false - fi + git config submodule.example.url >url && + git config submodule.example.url ./.subrepo && + + test_cmp expect url ' test_expect_success 'update should fail when path is used by a file' ' + echo hello >expect && + echo "hello" >init && - if git submodule update - then - echo "[OOPS] update should have failed" - false - elif test "$(cat init)" != "hello" - then - echo "[OOPS] update failed but init file was molested" - false - else - rm init - fi + test_must_fail git submodule update && + + test_cmp expect init ' test_expect_success 'update should fail when path is used by a nonempty directory' ' + echo hello >expect && + + rm -fr init && mkdir init && echo "hello" >init/a && - if git submodule update - then - echo "[OOPS] update should have failed" - false - elif test "$(cat init/a)" != "hello" - then - echo "[OOPS] update failed but init/a was molested" - false - else - rm init/a - fi + + test_must_fail git submodule update && + + test_cmp expect init/a ' test_expect_success 'update should work when path is an empty dir' ' - rm -rf init && + rm -fr init && + rm -f head-sha1 && + echo "$rev1" >expect && + mkdir init && git submodule update && - head=$(cd init && git rev-parse HEAD) && - if test -z "$head" - then - echo "[OOPS] Failed to obtain submodule head" - false - elif test "$head" != "$rev1" - then - echo "[OOPS] Submodule head is $head but should have been $rev1" - false - fi + + inspect init && + test_cmp expect head-sha1 ' test_expect_success 'status should be "up-to-date" after update' ' - git submodule status | grep "^ $rev1" + git submodule status >list && + grep "^ $rev1" list ' test_expect_success 'status should be "modified" after submodule commit' ' - cd init && - echo b >b && - git add b && - git commit -m "submodule commit 2" && - rev2=$(git rev-parse HEAD) && - cd .. && - if test -z "$rev2" - then - echo "[OOPS] submodule git rev-parse returned nothing" - false - fi && - git submodule status | grep "^+$rev2" + ( + cd init && + echo b >b && + git add b && + git commit -m "submodule commit 2" + ) && + + rev2=$(cd init && git rev-parse HEAD) && + test -n "$rev2" && + git submodule status >list && + + grep "^+$rev2" list ' test_expect_success 'the --cached sha1 should be rev1' ' - git submodule --cached status | grep "^+$rev1" + git submodule --cached status >list && + grep "^+$rev1" list ' test_expect_success 'git diff should report the SHA1 of the new submodule commit' ' - git diff | grep "^+Subproject commit $rev2" + git diff >diff && + grep "^+Subproject commit $rev2" diff ' test_expect_success 'update should checkout rev1' ' + rm -f head-sha1 && + echo "$rev1" >expect && + git submodule update init && - head=$(cd init && git rev-parse HEAD) && - if test -z "$head" - then - echo "[OOPS] submodule git rev-parse returned nothing" - false - elif test "$head" != "$rev1" - then - echo "[OOPS] init did not checkout correct head" - false - fi + inspect init && + + test_cmp expect head-sha1 ' test_expect_success 'status should be "up-to-date" after update' ' - git submodule status | grep "^ $rev1" + git submodule status >list && + grep "^ $rev1" list ' test_expect_success 'checkout superproject with subproject already present' ' @@ -239,6 +330,8 @@ test_expect_success 'checkout superproject with subproject already present' ' ' test_expect_success 'apply submodule diff' ' + >empty && + git branch second && ( cd init && @@ -251,21 +344,24 @@ test_expect_success 'apply submodule diff' ' git format-patch -1 --stdout >P.diff && git checkout second && git apply --index P.diff && - D=$(git diff --cached master) && - test -z "$D" + + git diff --cached master >staged && + test_cmp empty staged ' test_expect_success 'update --init' ' - mv init init2 && git config -f .gitmodules submodule.example.url "$(pwd)/init2" && - git config --remove-section submodule.example + git config --remove-section submodule.example && + test_must_fail git config submodule.example.url && + git submodule update init > update.out && + cat update.out && grep "not initialized" update.out && - test ! -d init/.git && + ! test -d init/.git && + git submodule update --init init && test -d init/.git - ' test_expect_success 'do not add files from a submodule' ' @@ -317,12 +413,13 @@ test_expect_success 'submodule <invalid-path> warns' ' test_expect_success 'add submodules without specifying an explicit path' ' mkdir repo && - cd repo && - git init && - echo r >r && - git add r && - git commit -m "repo commit 1" && - cd .. && + ( + cd repo && + git init && + echo r >r && + git add r && + git commit -m "repo commit 1" + ) && git clone --bare repo/ bare.git && cd addtest && git submodule add "$submodurl/repo" && diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index cee319da0a..294584452b 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -66,10 +66,11 @@ EOF " commit_file sm1 && -cd sm1 && -git reset --hard HEAD~2 >/dev/null && -head3=$(git rev-parse --verify HEAD | cut -c1-7) && -cd .. +head3=$( + cd sm1 && + git reset --hard HEAD~2 >/dev/null && + git rev-parse --verify HEAD | cut -c1-7 +) test_expect_success 'modified submodule(backward)' " git submodule summary >actual && diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 7538756487..02522f9627 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -14,7 +14,7 @@ test_expect_success setup ' echo file > file && git add file && test_tick && - git commit -m upstream + git commit -m upstream && git clone . super && git clone super submodule && (cd super && @@ -42,7 +42,7 @@ test_expect_success 'change submodule url' ' ) && mv submodule moved-submodule && (cd super && - git config -f .gitmodules submodule.submodule.url ../moved-submodule + git config -f .gitmodules submodule.submodule.url ../moved-submodule && test_tick && git commit -a -m moved-submodule ) @@ -58,6 +58,9 @@ test_expect_success '"git submodule sync" should update submodule URLs' ' (cd super-clone/submodule && git checkout master && git pull + ) && + (cd super-clone && + test -d "$(git config submodule.submodule.url)" ) ' diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh index 9a21f783d3..7e2e258950 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -45,7 +45,7 @@ test_expect_success setup ' git commit -m sub-b) && git add sub && test_tick && - git commit -m b + git commit -m b && git checkout -b c a && git merge -s ours b && @@ -54,21 +54,132 @@ test_expect_success setup ' git merge -s ours a ' -test_expect_success 'merging with modify/modify conflict' ' +# History setup +# +# b +# / \ +# a d +# \ / +# c +# +# a in the main repository records to sub-a in the submodule and +# analogous b and c. d should be automatically found by merging c into +# b in the main repository. +test_expect_success 'setup for merge search' ' + mkdir merge-search && + (cd merge-search && + git init && + mkdir sub && + (cd sub && + git init && + echo "file-a" > file-a && + git add file-a && + git commit -m "sub-a" && + git branch sub-a) && + git add sub && + git commit -m "a" && + git branch a && + + git checkout -b b && + (cd sub && + git checkout -b sub-b && + echo "file-b" > file-b && + git add file-b && + git commit -m "sub-b") && + git commit -a -m "b" && + + git checkout -b c a && + (cd sub && + git checkout -b sub-c sub-a && + echo "file-c" > file-c && + git add file-c && + git commit -m "sub-c") && + git commit -a -m "c" && - git checkout -b test1 a && - test_must_fail git merge b && - test -f .git/MERGE_MSG && - git diff && - test -n "$(git ls-files -u)" + git checkout -b d a && + (cd sub && + git checkout -b sub-d sub-b && + git merge sub-c) && + git commit -a -m "d" && + git branch test b) ' -test_expect_success 'merging with a modify/modify conflict between merge bases' ' +test_expect_success 'merge with one side as a fast-forward of the other' ' + (cd merge-search && + git checkout -b test-forward b && + git merge d && + git ls-tree test-forward sub | cut -f1 | cut -f3 -d" " > actual && + (cd sub && + git rev-parse sub-d > ../expect) && + test_cmp actual expect) +' +test_expect_success 'merging should conflict for non fast-forward' ' + (cd merge-search && + git checkout -b test-nonforward b && + (cd sub && + git rev-parse sub-d > ../expect) && + test_must_fail git merge c 2> actual && + grep $(cat expect) actual > /dev/null && + git reset --hard) +' + +test_expect_success 'merging should fail for ambiguous common parent' ' + (cd merge-search && + git checkout -b test-ambiguous b && + (cd sub && + git checkout -b ambiguous sub-b && + git merge sub-c && + git rev-parse sub-d > ../expect1 && + git rev-parse ambiguous > ../expect2) && + test_must_fail git merge c 2> actual && + grep $(cat expect1) actual > /dev/null && + grep $(cat expect2) actual > /dev/null && + git reset --hard) +' + +# in a situation like this +# +# submodule tree: +# +# sub-a --- sub-b --- sub-d +# +# main tree: +# +# e (sub-a) +# / +# bb (sub-b) +# \ +# f (sub-d) +# +# A merge between e and f should fail because one of the submodule +# commits (sub-a) does not descend from the submodule merge-base (sub-b). +# +test_expect_success 'merging should fail for changes that are backwards' ' + (cd merge-search && + git checkout -b bb a && + (cd sub && + git checkout sub-b) && + git commit -a -m "bb" && + + git checkout -b e bb && + (cd sub && + git checkout sub-a) && + git commit -a -m "e" && + + git checkout -b f bb && + (cd sub && + git checkout sub-d) && + git commit -a -m "f" && + + git checkout -b test-backward e && + test_must_fail git merge f) +' + +test_expect_success 'merging with a modify/modify conflict between merge bases' ' git reset --hard HEAD && git checkout -b test2 c && git merge d - ' test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 1382a8e58a..bfb4975e94 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -25,7 +25,7 @@ test_expect_success 'setup a submodule tree' ' echo file > file && git add file && test_tick && - git commit -m upstream + git commit -m upstream && git clone . super && git clone super submodule && git clone super rebasing && diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 2a527750ce..905a8baae9 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -16,7 +16,7 @@ test_expect_success 'setup a submodule tree' ' echo file > file && git add file && test_tick && - git commit -m upstream + git commit -m upstream && git clone . super && git clone super submodule && ( @@ -30,7 +30,7 @@ test_expect_success 'setup a submodule tree' ' submodule.sub2 submodule.foo2 && git config -f .gitmodules --rename-section \ submodule.sub3 submodule.foo3 && - git add .gitmodules + git add .gitmodules && test_tick && git commit -m "submodules" && git submodule init sub1 && @@ -59,11 +59,13 @@ test_expect_success 'setup a submodule tree' ' sub1sha1=$(cd super/sub1 && git rev-parse HEAD) sub3sha1=$(cd super/sub3 && git rev-parse HEAD) +pwd=$(pwd) + cat > expect <<EOF Entering 'sub1' -foo1-sub1-$sub1sha1 +$pwd/clone-foo1-sub1-$sub1sha1 Entering 'sub3' -foo3-sub3-$sub3sha1 +$pwd/clone-foo3-sub3-$sub3sha1 EOF test_expect_success 'test basic "submodule foreach" usage' ' @@ -71,7 +73,9 @@ test_expect_success 'test basic "submodule foreach" usage' ' ( cd clone && git submodule update --init -- sub1 sub3 && - git submodule foreach "echo \$name-\$path-\$sha1" > ../actual + git submodule foreach "echo \$toplevel-\$name-\$path-\$sha1" > ../actual && + git config foo.bar zar && + git submodule foreach "git config --file \"\$toplevel/.git/config\" foo.bar" ) && test_cmp expect actual ' diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index 9f5c3edb03..aa9c577e9e 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -193,4 +193,26 @@ test_expect_success 'commit -F overrides -t' ' commit_msg_is "-F log" ' +test_expect_success 'Commit without message is allowed with --allow-empty-message' ' + echo "more content" >>foo && + git add foo && + >empty && + git commit --allow-empty-message <empty && + commit_msg_is "" +' + +test_expect_success 'Commit without message is no-no without --allow-empty-message' ' + echo "more content" >>foo && + git add foo && + >empty && + test_must_fail git commit <empty +' + +test_expect_success 'Commit a message with --allow-empty-message' ' + echo "even more content" >>foo && + git add foo && + git commit --allow-empty-message -m"hello there" && + commit_msg_is "hello there" +' + test_done diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 844fb43c6d..ac2e187a57 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -4,8 +4,76 @@ test_description='git commit porcelain-ish' . ./test-lib.sh +# Arguments: [<prefix] [<commit message>] [<commit options>] +check_summary_oneline() { + test_tick && + git commit ${3+"$3"} -m "$2" | head -1 > act && + + # branch name + SUMMARY_PREFIX="$(git name-rev --name-only HEAD)" && + + # append the "special" prefix, like "root-commit", "detached HEAD" + if test -n "$1" + then + SUMMARY_PREFIX="$SUMMARY_PREFIX ($1)" + fi + + # abbrev SHA-1 + SUMMARY_POSTFIX="$(git log -1 --pretty='format:%h')" + echo "[$SUMMARY_PREFIX $SUMMARY_POSTFIX] $2" >exp && + + test_cmp exp act +} + +test_expect_success 'output summary format' ' + + echo new >file1 && + git add file1 && + check_summary_oneline "root-commit" "initial" && + + echo change >>file1 && + git add file1 && + check_summary_oneline "" "a change" +' + +test_expect_success 'output summary format for commit with an empty diff' ' + + check_summary_oneline "" "empty" "--allow-empty" +' + +test_expect_success 'output summary format for merges' ' + + git checkout -b recursive-base && + test_commit base file1 && + + git checkout -b recursive-a recursive-base && + test_commit commit-a file1 && + + git checkout -b recursive-b recursive-base && + test_commit commit-b file1 && + + # conflict + git checkout recursive-a && + test_must_fail git merge recursive-b && + # resolve the conflict + echo commit-a > file1 && + git add file1 && + check_summary_oneline "" "Merge" +' + +output_tests_cleanup() { + # this is needed for "do not fire editor in the presence of conflicts" + git checkout master && + + # this is needed for the "partial removal" test to pass + git rm file1 && + git commit -m "cleanup" +} + test_expect_success 'the basics' ' + output_tests_cleanup && + echo doing partial >"commit is" && mkdir not && echo very much encouraged but we should >not/forbid && @@ -35,7 +103,7 @@ test_expect_success 'partial' ' ' -test_expect_success 'partial modification in a subdirecotry' ' +test_expect_success 'partial modification in a subdirectory' ' test_tick && git commit -m "partial commit to subdirectory" not && diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 556d0faa77..c9300f3c8b 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -69,6 +69,34 @@ test_expect_success 'status (2)' ' ' cat >expect <<\EOF +# On branch master +# Changes to be committed: +# new file: dir2/added +# +# Changed but not updated: +# modified: dir1/modified +# +# Untracked files: +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + +git config advice.statusHints false + +test_expect_success 'status (advice.statusHints false)' ' + + git status >output && + test_cmp expect output + +' + +git config --unset advice.statusHints + +cat >expect <<\EOF M dir1/modified A dir2/added ?? dir1/untracked @@ -79,13 +107,32 @@ A dir2/added ?? untracked EOF -test_expect_success 'status -s (2)' ' +test_expect_success 'status -s' ' git status -s >output && test_cmp expect output ' +cat >expect <<\EOF +## master + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +test_expect_success 'status -s -b' ' + + git status -s -b >output && + test_cmp expect output + +' + cat >expect <<EOF # On branch master # Changes to be committed: @@ -115,6 +162,23 @@ test_expect_success 'status (status.showUntrackedFiles no)' ' test_cmp expect output ' +cat >expect <<EOF +# On branch master +# Changes to be committed: +# new file: dir2/added +# +# Changed but not updated: +# modified: dir1/modified +# +# Untracked files not listed +EOF +git config advice.statusHints false +test_expect_success 'status -uno (advice.statusHints false)' ' + git status -uno >output && + test_cmp expect output +' +git config --unset advice.statusHints + cat >expect << EOF M dir1/modified A dir2/added @@ -392,6 +456,25 @@ test_expect_success 'status -s with color.status' ' ' cat >expect <<\EOF +## <GREEN>master<RESET> + <RED>M<RESET> dir1/modified +<GREEN>A<RESET> dir2/added +<BLUE>??<RESET> dir1/untracked +<BLUE>??<RESET> dir2/modified +<BLUE>??<RESET> dir2/untracked +<BLUE>??<RESET> expect +<BLUE>??<RESET> output +<BLUE>??<RESET> untracked +EOF + +test_expect_success 'status -s -b with color.status' ' + + git status -s -b | test_decode_color >output && + test_cmp expect output + +' + +cat >expect <<\EOF M dir1/modified A dir2/added ?? dir1/untracked @@ -424,6 +507,13 @@ test_expect_success 'status --porcelain ignores color.status' ' git config --unset color.status git config --unset color.ui +test_expect_success 'status --porcelain ignores -b' ' + + git status --porcelain -b >output && + test_cmp expect output + +' + cat >expect <<\EOF # On branch master # Changes to be committed: @@ -496,6 +586,16 @@ test_expect_success 'dry-run of partial commit excluding new file in index' ' test_cmp expect output ' +cat >expect <<EOF +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M dir1/modified +EOF +test_expect_success 'status refreshes the index' ' + touch dir2/added && + git status && + git diff-files >output && + test_cmp expect output +' + test_expect_success 'setup status submodule summary' ' test_create_repo sm && ( cd sm && @@ -693,4 +793,321 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' ' test_cmp expect output ' +test_expect_success POSIXPERM,SANITY 'status succeeds in a read-only repository' ' + ( + chmod a-w .git && + # make dir1/tracked stat-dirty + >dir1/tracked1 && mv -f dir1/tracked1 dir1/tracked && + git status -s >output && + ! grep dir1/tracked output && + # make sure "status" succeeded without writing index out + git diff-files | grep dir1/tracked + ) + status=$? + chmod 775 .git + (exit $status) +' + +(cd sm && echo > bar && git add bar && git commit -q -m 'Add bar') && git add sm +new_head=$(cd sm && git rev-parse --short=7 --verify HEAD) +touch .gitmodules + +cat > expect << EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# .gitmodules +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + +test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' + echo modified > sm/untracked && + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +test_expect_success '.gitmodules ignore=untracked suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + test_cmp expect output && + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname +' + +test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' ' + git status --ignore-submodules=dirty > output && + test_cmp expect output +' + +test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + ! test -s actual && + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules +' + +test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' ' + echo modified > sm/foo && + git status --ignore-submodules=dirty > output && + test_cmp expect output +' + +test_expect_success '.gitmodules ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success '.git/config ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + +cat > expect << EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# (commit or discard the untracked or modified content in submodules) +# +# modified: dir1/modified +# modified: sm (modified content) +# +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# .gitmodules +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + +test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + +head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD) + +cat > expect << EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: sm +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# modified: sm (new commits) +# +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# +# Submodules changed but not updated: +# +# * sm $new_head...$head2 (1): +# > 2nd commit +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# .gitmodules +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + +test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" ' + git status --ignore-submodules=dirty > output && + test_cmp expect output +' +test_expect_success ".gitmodules ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + +cat > expect << EOF +# On branch master +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# .gitmodules +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +no changes added to commit (use "git add" and/or "git commit -a") +EOF + +test_expect_success "--ignore-submodules=all suppresses submodule summary" ' + git status --ignore-submodules=all > output && + test_cmp expect output +' + +test_expect_failure '.gitmodules ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + +test_expect_failure '.git/config ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && + git config --add submodule.subname.ignore all && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname +' + test_done diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh index d52c060b06..643ab03f99 100755 --- a/t/t7509-commit.sh +++ b/t/t7509-commit.sh @@ -83,6 +83,52 @@ test_expect_success '--amend option copies authorship' ' test_cmp expect actual ' +sha1_file() { + echo "$*" | sed "s#..#.git/objects/&/#" +} +remove_object() { + rm -f $(sha1_file "$*") +} +no_reflog() { + cp .git/config .git/config.saved && + echo "[core] logallrefupdates = false" >>.git/config && + test_when_finished "mv -f .git/config.saved .git/config" && + + if test -e .git/logs + then + mv .git/logs . && + test_when_finished "mv logs .git/" + fi +} + +test_expect_success '--amend option with empty author' ' + git cat-file commit Initial >tmp && + sed "s/author [^<]* </author </" tmp >empty-author && + no_reflog && + sha=$(git hash-object -t commit -w empty-author) && + test_when_finished "remove_object $sha" && + git checkout $sha && + test_when_finished "git checkout Initial" && + echo "Empty author test" >>foo && + test_tick && + test_must_fail git commit -a -m "empty author" --amend 2>err && + grep "empty ident" err +' + +test_expect_success '--amend option with missing author' ' + git cat-file commit Initial >tmp && + sed "s/author [^<]* </author </" tmp >malformed && + no_reflog && + sha=$(git hash-object -t commit -w malformed) && + test_when_finished "remove_object $sha" && + git checkout $sha && + test_when_finished "git checkout Initial" && + echo "Missing author test" >>foo && + test_tick && + test_must_fail git commit -a -m "malformed author" --amend 2>err && + grep "empty ident" err +' + test_expect_success '--reset-author makes the commit ours even with --amend option' ' git checkout Initial && echo "Test 6" >>foo && diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 57f6d2bae7..b4f40e4c3a 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -5,189 +5,103 @@ test_description='git merge -Testing basic merge operations/option parsing.' +Testing basic merge operations/option parsing. + +! [c0] commit 0 + ! [c1] commit 1 + ! [c2] commit 2 + ! [c3] commit 3 + ! [c4] c4 + ! [c5] c5 + ! [c6] c6 + * [master] Merge commit 'c1' +-------- + - [master] Merge commit 'c1' + + * [c1] commit 1 + + [c6] c6 + + [c5] c5 + ++ [c4] c4 + ++++ [c3] commit 3 + + [c2] commit 2 ++++++++* [c0] commit 0 +' . ./test-lib.sh -cat >file <<EOF -1 -2 -3 -4 -5 -6 -7 -8 -9 -EOF - -cat >file.1 <<EOF -1 X -2 -3 -4 -5 -6 -7 -8 -9 -EOF - -cat >file.5 <<EOF -1 -2 -3 -4 -5 X -6 -7 -8 -9 -EOF - -cat >file.9 <<EOF -1 -2 -3 -4 -5 -6 -7 -8 -9 X -EOF - -cat >result.1 <<EOF -1 X -2 -3 -4 -5 -6 -7 -8 -9 -EOF - -cat >result.1-5 <<EOF -1 X -2 -3 -4 -5 X -6 -7 -8 -9 -EOF - -cat >result.1-5-9 <<EOF -1 X -2 -3 -4 -5 X -6 -7 -8 -9 X -EOF - -create_merge_msgs() { - echo "Merge commit 'c2'" >msg.1-5 && - echo "Merge commit 'c2'; commit 'c3'" >msg.1-5-9 && - echo "Squashed commit of the following:" >squash.1 && - echo >>squash.1 && - git log --no-merges ^HEAD c1 >>squash.1 && - echo "Squashed commit of the following:" >squash.1-5 && - echo >>squash.1-5 && - git log --no-merges ^HEAD c2 >>squash.1-5 && - echo "Squashed commit of the following:" >squash.1-5-9 && - echo >>squash.1-5-9 && - git log --no-merges ^HEAD c2 c3 >>squash.1-5-9 && - echo > msg.nolog && - echo "* commit 'c3':" >msg.log && - echo " commit 3" >>msg.log && - echo >>msg.log -} - -verify_diff() { - if ! test_cmp "$1" "$2" - then - echo "$3" - false - fi -} - -verify_merge() { - verify_diff "$2" "$1" "[OOPS] bad merge result" && - if test $(git ls-files -u | wc -l) -gt 0 - then - echo "[OOPS] unmerged files" - false - fi && - if test_must_fail git diff --exit-code - then - echo "[OOPS] working tree != index" - false - fi && - if test -n "$3" - then - git show -s --pretty=format:%s HEAD >msg.act && - verify_diff "$3" msg.act "[OOPS] bad merge message" - fi -} - -verify_head() { - if test "$1" != "$(git rev-parse HEAD)" - then - echo "[OOPS] HEAD != $1" - false - fi -} - -verify_parents() { - i=1 - while test $# -gt 0 - do - if test "$1" != "$(git rev-parse HEAD^$i)" +test_expect_success 'set up test data and helpers' ' + printf "%s\n" 1 2 3 4 5 6 7 8 9 >file && + printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >file.1 && + printf "%s\n" 1 2 3 4 "5 X" 6 7 8 9 >file.5 && + printf "%s\n" 1 2 3 4 5 6 7 8 "9 X" >file.9 && + printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >result.1 && + printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 9 >result.1-5 && + printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 "9 X" >result.1-5-9 && + + create_merge_msgs() { + echo "Merge commit '\''c2'\''" >msg.1-5 && + echo "Merge commit '\''c2'\''; commit '\''c3'\''" >msg.1-5-9 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c1 + } >squash.1 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c2 + } >squash.1-5 && + { + echo "Squashed commit of the following:" && + echo && + git log --no-merges ^HEAD c2 c3 + } >squash.1-5-9 && + echo >msg.nolog && + { + echo "* commit '\''c3'\'':" && + echo " commit 3" && + echo + } >msg.log + } && + + verify_merge() { + test_cmp "$2" "$1" && + git update-index --refresh && + git diff --exit-code && + if test -n "$3" then - echo "[OOPS] HEAD^$i != $1" - return 1 + git show -s --pretty=format:%s HEAD >msg.act && + test_cmp "$3" msg.act fi - i=$(expr $i + 1) - shift - done -} - -verify_mergeheads() { - i=1 - if ! test -f .git/MERGE_HEAD - then - echo "[OOPS] MERGE_HEAD is missing" - false - fi && - while test $# -gt 0 - do - head=$(head -n $i .git/MERGE_HEAD | sed -ne \$p) - if test "$1" != "$head" - then - echo "[OOPS] MERGE_HEAD $i != $1" + } && + + verify_head() { + echo "$1" >head.expected && + git rev-parse HEAD >head.actual && + test_cmp head.expected head.actual + } && + + verify_parents() { + printf "%s\n" "$@" >parents.expected && + >parents.actual && + i=1 && + while test $i -le $# + do + git rev-parse HEAD^$i >>parents.actual && + i=$(expr $i + 1) || return 1 - fi - i=$(expr $i + 1) - shift - done -} + done && + test_cmp parents.expected parents.actual + } && -verify_no_mergehead() { - if test -f .git/MERGE_HEAD - then - echo "[OOPS] MERGE_HEAD exists" - false - fi -} + verify_mergeheads() { + printf "%s\n" "$@" >mergehead.expected && + test_cmp mergehead.expected .git/MERGE_HEAD + } && + verify_no_mergehead() { + ! test -e .git/MERGE_HEAD + } +' test_expect_success 'setup' ' git add file && @@ -219,7 +133,7 @@ test_expect_success 'setup' ' create_merge_msgs ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'test option parsing' ' test_must_fail git merge -$ c1 && @@ -235,13 +149,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' ' ' test_expect_success 'merge c0 with c1' ' + echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected && + git reset --hard c0 && git merge c1 && verify_merge file result.1 && - verify_head "$c1" + verify_head "$c1" && + + git reflog -1 >reflog.actual && + sed "s/$_x05[0-9a-f]*/OBJID/g" reflog.actual >reflog.fuzzy && + test_cmp reflog.expected reflog.fuzzy ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c0 with c1 with --ff-only' ' git reset --hard c0 && @@ -251,7 +171,28 @@ test_expect_success 'merge c0 with c1 with --ff-only' ' verify_head "$c1" ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' + +test_expect_success 'merge from unborn branch' ' + git checkout -f master && + test_might_fail git branch -D kid && + + echo "OBJID HEAD@{0}: initial pull" >reflog.expected && + + git checkout --orphan kid && + test_when_finished "git checkout -f master" && + git rm -fr . && + test_tick && + git merge --ff-only c1 && + verify_merge file result.1 && + verify_head "$c1" && + + git reflog -1 >reflog.actual && + sed "s/$_x05[0-9a-f][0-9a-f]/OBJID/g" reflog.actual >reflog.fuzzy && + test_cmp reflog.expected reflog.fuzzy +' + +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2' ' git reset --hard c1 && @@ -261,7 +202,7 @@ test_expect_success 'merge c1 with c2' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 and c3' ' git reset --hard c1 && @@ -271,7 +212,7 @@ test_expect_success 'merge c1 with c2 and c3' ' verify_parents $c1 $c2 $c3 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'failing merges with --ff-only' ' git reset --hard c1 && @@ -288,7 +229,7 @@ test_expect_success 'merge c0 with c1 (no-commit)' ' verify_head $c1 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (no-commit)' ' git reset --hard c1 && @@ -298,7 +239,7 @@ test_expect_success 'merge c1 with c2 (no-commit)' ' verify_mergeheads $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 and c3 (no-commit)' ' git reset --hard c1 && @@ -308,7 +249,7 @@ test_expect_success 'merge c1 with c2 and c3 (no-commit)' ' verify_mergeheads $c2 $c3 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c0 with c1 (squash)' ' git reset --hard c0 && @@ -316,10 +257,10 @@ test_expect_success 'merge c0 with c1 (squash)' ' verify_merge file result.1 && verify_head $c0 && verify_no_mergehead && - verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message" + test_cmp squash.1 .git/SQUASH_MSG ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c0 with c1 (squash, ff-only)' ' git reset --hard c0 && @@ -327,10 +268,10 @@ test_expect_success 'merge c0 with c1 (squash, ff-only)' ' verify_merge file result.1 && verify_head $c0 && verify_no_mergehead && - verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message" + test_cmp squash.1 .git/SQUASH_MSG ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (squash)' ' git reset --hard c1 && @@ -338,17 +279,17 @@ test_expect_success 'merge c1 with c2 (squash)' ' verify_merge file result.1-5 && verify_head $c1 && verify_no_mergehead && - verify_diff squash.1-5 .git/SQUASH_MSG "[OOPS] bad squash message" + test_cmp squash.1-5 .git/SQUASH_MSG ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' ' git reset --hard c1 && test_must_fail git merge --squash --ff-only c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 and c3 (squash)' ' git reset --hard c1 && @@ -356,10 +297,10 @@ test_expect_success 'merge c1 with c2 and c3 (squash)' ' verify_merge file result.1-5-9 && verify_head $c1 && verify_no_mergehead && - verify_diff squash.1-5-9 .git/SQUASH_MSG "[OOPS] bad squash message" + test_cmp squash.1-5-9 .git/SQUASH_MSG ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (no-commit in config)' ' git reset --hard c1 && @@ -370,7 +311,7 @@ test_expect_success 'merge c1 with c2 (no-commit in config)' ' verify_mergeheads $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (squash in config)' ' git reset --hard c1 && @@ -379,10 +320,10 @@ test_expect_success 'merge c1 with c2 (squash in config)' ' verify_merge file result.1-5 && verify_head $c1 && verify_no_mergehead && - verify_diff squash.1-5 .git/SQUASH_MSG "[OOPS] bad squash message" + test_cmp squash.1-5 .git/SQUASH_MSG ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'override config option -n with --summary' ' git reset --hard c1 && @@ -412,7 +353,7 @@ test_expect_success 'override config option -n with --stat' ' fi ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'override config option --stat' ' git reset --hard c1 && @@ -428,7 +369,7 @@ test_expect_success 'override config option --stat' ' fi ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (override --no-commit)' ' git reset --hard c1 && @@ -439,7 +380,7 @@ test_expect_success 'merge c1 with c2 (override --no-commit)' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 (override --squash)' ' git reset --hard c1 && @@ -450,7 +391,7 @@ test_expect_success 'merge c1 with c2 (override --squash)' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c0 with c1 (no-ff)' ' git reset --hard c0 && @@ -461,7 +402,7 @@ test_expect_success 'merge c0 with c1 (no-ff)' ' verify_parents $c0 $c1 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'combining --squash and --no-ff is refused' ' test_must_fail git merge --squash --no-ff c1 && @@ -485,20 +426,20 @@ test_expect_success 'merge log message' ' git reset --hard c0 && git merge --no-log c2 && git show -s --pretty=format:%b HEAD >msg.act && - verify_diff msg.nolog msg.act "[OOPS] bad merge log message" && + test_cmp msg.nolog msg.act && git merge --log c3 && git show -s --pretty=format:%b HEAD >msg.act && - verify_diff msg.log msg.act "[OOPS] bad merge log message" && + test_cmp msg.log msg.act && git reset --hard HEAD^ && git config merge.log yes && git merge c3 && git show -s --pretty=format:%b HEAD >msg.act && - verify_diff msg.log msg.act "[OOPS] bad merge log message" + test_cmp msg.log msg.act ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c0, c2, c0, and c1' ' git reset --hard c1 && @@ -509,7 +450,7 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c0, c2, c0, and c1' ' git reset --hard c1 && @@ -520,7 +461,7 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c1 and c2' ' git reset --hard c1 && @@ -531,7 +472,7 @@ test_expect_success 'merge c1 with c1 and c2' ' verify_parents $c1 $c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge fast-forward in a dirty tree' ' git reset --hard c0 && @@ -541,49 +482,56 @@ test_expect_success 'merge fast-forward in a dirty tree' ' git merge c2 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'in-index merge' ' git reset --hard c0 && - git merge --no-ff -s resolve c1 > out && + git merge --no-ff -s resolve c1 >out && grep "Wonderful." out && verify_parents $c0 $c1 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'refresh the index before merging' ' git reset --hard c1 && - sleep 1 && - touch file && + cp file file.n && mv -f file.n file && git merge c3 ' -cat >expected <<EOF -Merge branch 'c5' (early part) +cat >expected.branch <<\EOF +Merge branch 'c5-branch' (early part) +EOF +cat >expected.tag <<\EOF +Merge commit 'c5~1' EOF test_expect_success 'merge early part of c2' ' git reset --hard c3 && - echo c4 > c4.c && + echo c4 >c4.c && git add c4.c && git commit -m c4 && git tag c4 && - echo c5 > c5.c && + echo c5 >c5.c && git add c5.c && git commit -m c5 && git tag c5 && git reset --hard c3 && - echo c6 > c6.c && + echo c6 >c6.c && git add c6.c && git commit -m c6 && git tag c6 && + git branch -f c5-branch c5 && + git merge c5-branch~1 && + git show -s --pretty=format:%s HEAD >actual.branch && + git reset --keep HEAD^ && git merge c5~1 && - git show -s --pretty=format:%s HEAD > actual && - test_cmp actual expected + git show -s --pretty=format:%s HEAD >actual.tag && + test_cmp expected.branch actual.branch && + test_cmp expected.tag actual.tag ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge --no-ff --no-commit && commit' ' git reset --hard c0 && @@ -592,13 +540,13 @@ test_expect_success 'merge --no-ff --no-commit && commit' ' verify_parents $c0 $c1 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'amending no-ff merge commit' ' EDITOR=: git commit --amend && verify_parents $c0 $c1 ' -test_debug 'gitk --all' +test_debug 'git log --graph --decorate --oneline --all' test_done diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh index 269cfdf267..9114785ef7 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -6,6 +6,15 @@ Testing merge when using a custom message for the merge commit.' . ./test-lib.sh +create_merge_msgs() { + echo >exp.subject "custom message" + + cp exp.subject exp.log && + echo >>exp.log "" && + echo >>exp.log "* commit 'c2':" && + echo >>exp.log " c2" +} + test_expect_success 'setup' ' echo c0 > c0.c && git add c0.c && @@ -19,16 +28,23 @@ test_expect_success 'setup' ' echo c2 > c2.c && git add c2.c && git commit -m c2 && - git tag c2 + git tag c2 && + create_merge_msgs ' test_expect_success 'merge c2 with a custom message' ' git reset --hard c1 && - echo >expected "custom message" && - git merge -m "custom message" c2 && + git merge -m "$(cat exp.subject)" c2 && + git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + test_cmp exp.subject actual +' + +test_expect_success 'merge --log appends to custom message' ' + git reset --hard c1 && + git merge --log -m "$(cat exp.subject)" c2 && git cat-file commit HEAD | sed -e "1,/^$/d" >actual && - test_cmp expected actual + test_cmp exp.log actual ' test_done diff --git a/t/t7606-merge-custom.sh b/t/t7606-merge-custom.sh index 52a451dd57..8e8c4d7246 100755 --- a/t/t7606-merge-custom.sh +++ b/t/t7606-merge-custom.sh @@ -1,49 +1,93 @@ #!/bin/sh -test_description='git merge +test_description="git merge -Testing a custom strategy.' +Testing a custom strategy. + +* (HEAD, master) Merge commit 'c3' +|\ +| * (tag: c3) c3 +* | (tag: c1) c1 +|/ +| * tag: c2) c2 +|/ +* (tag: c0) c0 +" . ./test-lib.sh -cat >git-merge-theirs <<EOF -#!$SHELL_PATH -eval git read-tree --reset -u \\\$\$# -EOF -chmod +x git-merge-theirs -PATH=.:$PATH -export PATH +test_expect_success 'set up custom strategy' ' + cat >git-merge-theirs <<-EOF && + #!$SHELL_PATH + eval git read-tree --reset -u \\\$\$# + EOF + + chmod +x git-merge-theirs && + PATH=.:$PATH && + export PATH +' test_expect_success 'setup' ' - echo c0 >c0.c && - git add c0.c && - git commit -m c0 && - git tag c0 && - echo c1 >c1.c && - git add c1.c && - git commit -m c1 && - git tag c1 && - git reset --hard c0 && + test_commit c0 c0.c && + test_commit c1 c1.c && + git reset --keep c0 && echo c1c1 >c1.c && - echo c2 >c2.c && - git add c1.c c2.c && - git commit -m c2 && - git tag c2 + git add c1.c && + test_commit c2 c2.c && + git reset --keep c0 && + test_commit c3 c3.c ' test_expect_success 'merge c2 with a custom strategy' ' git reset --hard c1 && + + git rev-parse c1 >head.old && + git rev-parse c2 >second-parent.expected && + git rev-parse c2^{tree} >tree.expected && git merge -s theirs c2 && - test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && - test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" && - test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" && - test "$(git rev-parse c2^{tree})" = "$(git rev-parse HEAD^{tree})" && + + git rev-parse HEAD >head.new && + git rev-parse HEAD^1 >first-parent && + git rev-parse HEAD^2 >second-parent && + git rev-parse HEAD^{tree} >tree && + git update-index --refresh && git diff --exit-code && git diff --exit-code c2 HEAD && git diff --exit-code c2 && + + ! test_cmp head.old head.new && + test_cmp head.old first-parent && + test_cmp second-parent.expected second-parent && + test_cmp tree.expected tree && test -f c0.c && grep c1c1 c1.c && test -f c2.c ' +test_expect_success 'trivial merge with custom strategy' ' + git reset --hard c1 && + + git rev-parse c1 >head.old && + git rev-parse c3 >second-parent.expected && + git rev-parse c3^{tree} >tree.expected && + git merge -s theirs c3 && + + git rev-parse HEAD >head.new && + git rev-parse HEAD^1 >first-parent && + git rev-parse HEAD^2 >second-parent && + git rev-parse HEAD^{tree} >tree && + git update-index --refresh && + git diff --exit-code && + git diff --exit-code c3 HEAD && + git diff --exit-code c3 && + + ! test_cmp head.old head.new && + test_cmp head.old first-parent && + test_cmp second-parent.expected second-parent && + test_cmp tree.expected tree && + test -f c0.c && + ! test -e c1.c && + test -f c3.c +' + test_done diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 49f4e1599a..d82349a6a8 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -31,7 +31,7 @@ test_expect_success 'setup' ' test_expect_success 'will not overwrite untracked file' ' git reset --hard c1 && cat important > c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@ -39,7 +39,7 @@ test_expect_success 'will not overwrite new file' ' git reset --hard c1 && cat important > c2.c && git add c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@ -48,7 +48,7 @@ test_expect_success 'will not overwrite staged changes' ' cat important > c2.c && git add c2.c && rm c2.c && - ! git merge c2 && + test_must_fail git merge c2 && git checkout c2.c && test_cmp important c2.c ' @@ -58,7 +58,7 @@ test_expect_success 'will not overwrite removed file' ' git rm c1.c && git commit -m "rm c1.c" && cat important > c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@ -68,7 +68,7 @@ test_expect_success 'will not overwrite re-added file' ' git commit -m "rm c1.c" && cat important > c1.c && git add c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@ -79,7 +79,7 @@ test_expect_success 'will not overwrite removed file with staged changes' ' cat important > c1.c && git add c1.c && rm c1.c && - ! git merge c1a && + test_must_fail git merge c1a && git checkout c1.c && test_cmp important c1.c ' diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh new file mode 100755 index 0000000000..114d2bd785 --- /dev/null +++ b/t/t7609-merge-co-error-msgs.sh @@ -0,0 +1,133 @@ +#!/bin/sh + +test_description='unpack-trees error messages' + +. ./test-lib.sh + + +test_expect_success 'setup' ' + echo one >one && + git add one && + git commit -a -m First && + + git checkout -b branch && + echo two >two && + echo three >three && + echo four >four && + echo five >five && + git add two three four five && + git commit -m Second && + + git checkout master && + echo other >two && + echo other >three && + echo other >four && + echo other >five +' + +cat >expect <<\EOF +error: The following untracked working tree files would be overwritten by merge: + two + three + four + five +Please move or remove them before you can merge. +EOF + +test_expect_success 'untracked files overwritten by merge (fast and non-fast forward)' ' + test_must_fail git merge branch 2>out && + test_cmp out expect && + git commit --allow-empty -m empty && + ( + GIT_MERGE_VERBOSITY=0 && + export GIT_MERGE_VERBOSITY && + test_must_fail git merge branch 2>out2 + ) && + test_cmp out2 expect && + git reset --hard HEAD^ +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by merge: + two + three + four +Please, commit your changes or stash them before you can merge. +error: The following untracked working tree files would be overwritten by merge: + five +Please move or remove them before you can merge. +EOF + +test_expect_success 'untracked files or local changes ovewritten by merge' ' + git add two && + git add three && + git add four && + test_must_fail git merge branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by checkout: + rep/two + rep/one +Please, commit your changes or stash them before you can switch branches. +EOF + +test_expect_success 'cannot switch branches because of local changes' ' + git add five && + mkdir rep && + echo one >rep/one && + echo two >rep/two && + git add rep/one rep/two && + git commit -m Fourth && + git checkout master && + echo uno >rep/one && + echo dos >rep/two && + test_must_fail git checkout branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Your local changes to the following files would be overwritten by checkout: + rep/two + rep/one +Please, commit your changes or stash them before you can switch branches. +EOF + +test_expect_success 'not uptodate file porcelain checkout error' ' + git add rep/one rep/two && + test_must_fail git checkout branch 2>out && + test_cmp out expect +' + +cat >expect <<\EOF +error: Updating the following directories would lose untracked files in it: + rep2 + rep + +EOF + +test_expect_success 'not_uptodate_dir porcelain checkout error' ' + git init uptodate && + cd uptodate && + mkdir rep && + mkdir rep2 && + touch rep/foo && + touch rep2/foo && + git add rep/foo rep2/foo && + git commit -m init && + git checkout -b branch && + git rm rep -r && + git rm rep2 -r && + >rep && + >rep2 && + git add rep rep2&& + git commit -m "added test as a file" && + git checkout master && + >rep/untracked-file && + >rep2/untracked-file && + test_must_fail git checkout branch 2>out && + test_cmp out ../expect +' + +test_done diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index e768c3eb2d..3bd74042ef 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -14,6 +14,7 @@ Testing basic merge tool invocation' # running mergetool test_expect_success 'setup' ' + git config rerere.enabled true && echo master >file1 && mkdir subdir && echo master sub >subdir/file3 && @@ -67,23 +68,47 @@ test_expect_success 'mergetool crlf' ' ' test_expect_success 'mergetool in subdir' ' - git checkout -b test3 branch1 - cd subdir && ( - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && - test "$(cat file3)" = "master new sub" ) + git checkout -b test3 branch1 && + ( + cd subdir && + test_must_fail git merge master >/dev/null 2>&1 && + ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && + test "$(cat file3)" = "master new sub" + ) ' -# We can't merge files from parent directories when running mergetool -# from a subdir. Is this a bug? -# -#test_expect_failure 'mergetool in subdir' ' -# cd subdir && ( -# ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && -# ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) && -# test "$(cat ../file1)" = "master updated" && -# test "$(cat ../file2)" = "master new" && -# git commit -m "branch1 resolved with mergetool - subdir" ) -#' +test_expect_success 'mergetool on file in parent dir' ' + ( + cd subdir && + ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && + ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) && + test "$(cat ../file1)" = "master updated" && + test "$(cat ../file2)" = "master new" && + git commit -m "branch1 resolved with mergetool - subdir" + ) +' + +test_expect_success 'mergetool skips autoresolved' ' + git checkout -b test4 branch1 && + test_must_fail git merge master && + test -n "$(git ls-files -u)" && + output="$(git mergetool --no-prompt)" && + test "$output" = "No files need merging" && + git reset --hard +' + +test_expect_success 'mergetool merges all from subdir' ' + ( + cd subdir && + git config rerere.enabled false && + test_must_fail git merge master && + git mergetool --no-prompt && + test "$(cat ../file1)" = "master updated" && + test "$(cat ../file2)" = "master new" && + test "$(cat file3)" = "master new sub" && + git add ../file1 ../file2 file3 && + git commit -m "branch2 resolved by mergetool from subdir" + ) +' test_done diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index f4aa054750..c2f66ff170 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -8,6 +8,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' ' echo content1 > file1 && echo content2 > file2 && git add . && + test_tick && git commit -m initial_commit && # Create two packs # The first pack will contain all of the objects except one @@ -40,6 +41,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' ' echo content3 > file3 && objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) && git add file3 && + test_tick && git commit -m commit_file3 && git repack -a -d -l && git prune-packed && @@ -73,6 +75,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack rm -f .git/objects/pack/* && echo new_content >> file1 && git add file1 && + test_tick && git commit -m more_content && git repack && git repack -a -d && @@ -118,8 +121,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' mv .git/objects/pack/* alt_objects/pack/ && csha1=$(git rev-parse HEAD^{commit}) && git reset --hard HEAD^ && - sleep 1 && - git reflog expire --expire=now --expire-unreachable=now --all && + test_tick && + git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all && # The pack-objects call on the next line is equivalent to # git repack -A -d without the call to prune-packed git pack-objects --honor-pack-keep --non-empty --all --reflog \ @@ -156,7 +159,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' ' H1=$(git rev-parse HEAD^) && H2=$(git rev-parse HEAD^^) && echo "$H0 $H2" > .git/info/grafts && - git reflog expire --expire=now --expire-unreachable=now --all && + git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all && git repack -a -d && git cat-file -t $H1 ' diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index 5babdf26e6..200ab61278 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -11,17 +11,20 @@ tsha1= test_expect_success '-A with -d option leaves unreachable objects unpacked' ' echo content > file1 && git add . && + test_tick && git commit -m initial_commit && # create a transient branch with unique content git checkout -b transient_branch && echo more content >> file1 && # record the objects created in the database for file, commit, tree fsha1=$(git hash-object file1) && + test_tick && git commit -a -m more_content && csha1=$(git rev-parse HEAD^{commit}) && tsha1=$(git rev-parse HEAD^{tree}) && git checkout master && echo even more content >> file1 && + test_tick && git commit -a -m even_more_content && # delete the transient branch git branch -D transient_branch && @@ -34,9 +37,11 @@ test_expect_success '-A with -d option leaves unreachable objects unpacked' ' git show $fsha1 && git show $csha1 && git show $tsha1 && - # now expire the reflog - sleep 1 && - git reflog expire --expire-unreachable=now --all && + # now expire the reflog, while keeping reachable ones but expiring + # unreachables immediately + test_tick && + sometimeago=$(( $test_tick - 10000 )) && + git reflog expire --expire=$sometimeago --expire-unreachable=$test_tick --all && # and repack git repack -A -d -l && # verify objects are retained unpacked @@ -71,7 +76,7 @@ test_expect_success '-A without -d option leaves unreachable objects packed' ' test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) && packfile=$(ls .git/objects/pack/pack-*.pack) && git branch -D transient_branch && - sleep 1 && + test_tick && git repack -A -l && test ! -f "$fsha1path" && test ! -f "$csha1path" && diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 1de83ef98f..58dc6f6452 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -10,11 +10,6 @@ Testing basic diff tool invocation . ./test-lib.sh -if ! test_have_prereq PERL; then - say 'skipping difftool tests, perl not available' - test_done -fi - LF=' ' @@ -50,7 +45,7 @@ prompt_given() } # Create a file on master and change it on branch -test_expect_success 'setup' ' +test_expect_success PERL 'setup' ' echo master >file && git add file && git commit -m "added file" && @@ -62,7 +57,7 @@ test_expect_success 'setup' ' ' # Configure a custom difftool.<tool>.cmd and use it -test_expect_success 'custom commands' ' +test_expect_success PERL 'custom commands' ' restore_test_defaults && git config difftool.test-tool.cmd "cat \$REMOTE" && @@ -75,13 +70,13 @@ test_expect_success 'custom commands' ' ' # Ensures that git-difftool ignores bogus --tool values -test_expect_success 'difftool ignores bad --tool values' ' +test_expect_success PERL 'difftool ignores bad --tool values' ' diff=$(git difftool --no-prompt --tool=bad-tool branch) test "$?" = 1 && test "$diff" = "" ' -test_expect_success 'difftool honors --gui' ' +test_expect_success PERL 'difftool honors --gui' ' git config merge.tool bogus-tool && git config diff.tool bogus-tool && git config diff.guitool test-tool && @@ -92,7 +87,7 @@ test_expect_success 'difftool honors --gui' ' restore_test_defaults ' -test_expect_success 'difftool --gui works without configured diff.guitool' ' +test_expect_success PERL 'difftool --gui works without configured diff.guitool' ' git config diff.tool test-tool && diff=$(git difftool --no-prompt --gui branch) && @@ -102,7 +97,7 @@ test_expect_success 'difftool --gui works without configured diff.guitool' ' ' # Specify the diff tool using $GIT_DIFF_TOOL -test_expect_success 'GIT_DIFF_TOOL variable' ' +test_expect_success PERL 'GIT_DIFF_TOOL variable' ' git config --unset diff.tool GIT_DIFF_TOOL=test-tool && export GIT_DIFF_TOOL && @@ -115,7 +110,7 @@ test_expect_success 'GIT_DIFF_TOOL variable' ' # Test the $GIT_*_TOOL variables and ensure # that $GIT_DIFF_TOOL always wins unless --tool is specified -test_expect_success 'GIT_DIFF_TOOL overrides' ' +test_expect_success PERL 'GIT_DIFF_TOOL overrides' ' git config diff.tool bogus-tool && git config merge.tool bogus-tool && @@ -136,7 +131,7 @@ test_expect_success 'GIT_DIFF_TOOL overrides' ' # Test that we don't have to pass --no-prompt to difftool # when $GIT_DIFFTOOL_NO_PROMPT is true -test_expect_success 'GIT_DIFFTOOL_NO_PROMPT variable' ' +test_expect_success PERL 'GIT_DIFFTOOL_NO_PROMPT variable' ' GIT_DIFFTOOL_NO_PROMPT=true && export GIT_DIFFTOOL_NO_PROMPT && @@ -148,7 +143,7 @@ test_expect_success 'GIT_DIFFTOOL_NO_PROMPT variable' ' # git-difftool supports the difftool.prompt variable. # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false -test_expect_success 'GIT_DIFFTOOL_PROMPT variable' ' +test_expect_success PERL 'GIT_DIFFTOOL_PROMPT variable' ' git config difftool.prompt false && GIT_DIFFTOOL_PROMPT=true && export GIT_DIFFTOOL_PROMPT && @@ -160,7 +155,7 @@ test_expect_success 'GIT_DIFFTOOL_PROMPT variable' ' ' # Test that we don't have to pass --no-prompt when difftool.prompt is false -test_expect_success 'difftool.prompt config variable is false' ' +test_expect_success PERL 'difftool.prompt config variable is false' ' git config difftool.prompt false && diff=$(git difftool branch) && @@ -170,7 +165,7 @@ test_expect_success 'difftool.prompt config variable is false' ' ' # Test that we don't have to pass --no-prompt when mergetool.prompt is false -test_expect_success 'difftool merge.prompt = false' ' +test_expect_success PERL 'difftool merge.prompt = false' ' git config --unset difftool.prompt git config mergetool.prompt false && @@ -181,7 +176,7 @@ test_expect_success 'difftool merge.prompt = false' ' ' # Test that the -y flag can override difftool.prompt = true -test_expect_success 'difftool.prompt can overridden with -y' ' +test_expect_success PERL 'difftool.prompt can overridden with -y' ' git config difftool.prompt true && diff=$(git difftool -y branch) && @@ -191,7 +186,7 @@ test_expect_success 'difftool.prompt can overridden with -y' ' ' # Test that the --prompt flag can override difftool.prompt = false -test_expect_success 'difftool.prompt can overridden with --prompt' ' +test_expect_success PERL 'difftool.prompt can overridden with --prompt' ' git config difftool.prompt false && prompt=$(echo | git difftool --prompt branch | tail -1) && @@ -201,7 +196,7 @@ test_expect_success 'difftool.prompt can overridden with --prompt' ' ' # Test that the last flag passed on the command-line wins -test_expect_success 'difftool last flag wins' ' +test_expect_success PERL 'difftool last flag wins' ' diff=$(git difftool --prompt --no-prompt branch) && test "$diff" = "branch" && @@ -215,7 +210,7 @@ test_expect_success 'difftool last flag wins' ' # git-difftool falls back to git-mergetool config variables # so test that behavior here -test_expect_success 'difftool + mergetool config variables' ' +test_expect_success PERL 'difftool + mergetool config variables' ' remove_config_vars git config merge.tool test-tool && git config mergetool.test-tool.cmd "cat \$LOCAL" && @@ -233,7 +228,7 @@ test_expect_success 'difftool + mergetool config variables' ' restore_test_defaults ' -test_expect_success 'difftool.<tool>.path' ' +test_expect_success PERL 'difftool.<tool>.path' ' git config difftool.tkdiff.path echo && diff=$(git difftool --tool=tkdiff --no-prompt branch) && git config --unset difftool.tkdiff.path && @@ -243,32 +238,32 @@ test_expect_success 'difftool.<tool>.path' ' restore_test_defaults ' -test_expect_success 'difftool --extcmd=cat' ' +test_expect_success PERL 'difftool --extcmd=cat' ' diff=$(git difftool --no-prompt --extcmd=cat branch) && test "$diff" = branch"$LF"master ' -test_expect_success 'difftool --extcmd cat' ' +test_expect_success PERL 'difftool --extcmd cat' ' diff=$(git difftool --no-prompt --extcmd cat branch) && test "$diff" = branch"$LF"master ' -test_expect_success 'difftool -x cat' ' +test_expect_success PERL 'difftool -x cat' ' diff=$(git difftool --no-prompt -x cat branch) && test "$diff" = branch"$LF"master ' -test_expect_success 'difftool --extcmd echo arg1' ' +test_expect_success PERL 'difftool --extcmd echo arg1' ' diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch) test "$diff" = file ' -test_expect_success 'difftool --extcmd cat arg1' ' +test_expect_success PERL 'difftool --extcmd cat arg1' ' diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch) test "$diff" = master ' -test_expect_success 'difftool --extcmd cat arg2' ' +test_expect_success PERL 'difftool --extcmd cat arg2' ' diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch) test "$diff" = branch ' diff --git a/t/t7002-grep.sh b/t/t7810-grep.sh index e249c3ed41..50658845ca 100755 --- a/t/t7002-grep.sh +++ b/t/t7810-grep.sh @@ -60,12 +60,12 @@ do echo ${HC}file:5:foo_mmap bar mmap baz } >expected && git grep -n -w -e mmap $H >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep -w $L (w)" ' : >expected && - ! git grep -n -w -e "^w" >actual && + test_must_fail git grep -n -w -e "^w" >actual && test_cmp expected actual ' @@ -74,7 +74,7 @@ do echo ${HC}x:1:x x xx x } >expected && git grep -n -w -e "x xx* x" $H >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep -w $L (y-1)" ' @@ -82,7 +82,7 @@ do echo ${HC}y:1:y yy } >expected && git grep -n -w -e "^y" $H >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep -w $L (y-2)" ' @@ -93,7 +93,7 @@ do cat actual false else - diff expected actual + test_cmp expected actual fi ' @@ -105,14 +105,14 @@ do cat actual false else - diff expected actual + test_cmp expected actual fi ' test_expect_success "grep $L (t-1)" ' echo "${HC}t/t:1:test" >expected && git grep -n -e test $H >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep $L (t-2)" ' @@ -121,7 +121,7 @@ do cd t && git grep -n -e test $H ) >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep $L (t-3)" ' @@ -130,7 +130,7 @@ do cd t && git grep --full-name -n -e test $H ) >actual && - diff expected actual + test_cmp expected actual ' test_expect_success "grep -c $L (no /dev/null)" ' @@ -324,8 +324,13 @@ test_expect_success 'log grep setup' ' echo a >>file && test_tick && - git commit -a -m "third" + git commit -a -m "third" && + echo a >>file && + test_tick && + GIT_AUTHOR_NAME="Night Fall" \ + GIT_AUTHOR_EMAIL="nitfol@frobozz.com" \ + git commit -a -m "fourth" ' test_expect_success 'log grep (1)' ' @@ -372,6 +377,28 @@ test_expect_success 'log --grep --author implicitly uses all-match' ' test_cmp expect actual ' +test_expect_success 'log with multiple --author uses union' ' + git log --author="Thor" --author="Aster" --format=%s >actual && + { + echo third && echo second && echo initial + } >expect && + test_cmp expect actual +' + +test_expect_success 'log with --grep and multiple --author uses all-match' ' + git log --author="Thor" --author="Night" --grep=i --format=%s >actual && + { + echo third && echo initial + } >expect && + test_cmp expect actual +' + +test_expect_success 'log with --grep and multiple --author uses all-match' ' + git log --author="Thor" --author="Night" --grep=q --format=%s >actual && + >expect && + test_cmp expect actual +' + test_expect_success 'grep with CE_VALID file' ' git update-index --assume-unchanged t/t && rm t/t && diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh new file mode 100755 index 0000000000..568a6f2b69 --- /dev/null +++ b/t/t7811-grep-open.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +test_description='git grep --open-files-in-pager +' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-pager.sh +unset PAGER GIT_PAGER + +test_expect_success 'setup' ' + test_commit initial grep.h " +enum grep_pat_token { + GREP_PATTERN, + GREP_PATTERN_HEAD, + GREP_PATTERN_BODY, + GREP_AND, + GREP_OPEN_PAREN, + GREP_CLOSE_PAREN, + GREP_NOT, + GREP_OR, +};" && + + test_commit add-user revision.c " + } + if (seen_dashdash) + read_pathspec_from_stdin(revs, &sb, prune); + strbuf_release(&sb); +} + +static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) +{ + append_grep_pattern(&revs->grep_filter, ptn, \"command line\", 0, what); +" && + + mkdir subdir && + test_commit subdir subdir/grep.c "enum grep_pat_token" && + + test_commit uninteresting unrelated "hello, world" && + + echo GREP_PATTERN >untracked +' + +test_expect_success SIMPLEPAGER 'git grep -O' ' + cat >$less <<-\EOF && + #!/bin/sh + printf "%s\n" "$@" >pager-args + EOF + chmod +x $less && + cat >expect.less <<-\EOF && + +/*GREP_PATTERN + grep.h + EOF + echo grep.h >expect.notless && + >empty && + + PATH=.:$PATH git grep -O GREP_PATTERN >out && + { + test_cmp expect.less pager-args || + test_cmp expect.notless pager-args + } && + test_cmp empty out +' + +test_expect_success 'git grep -O --cached' ' + test_must_fail git grep --cached -O GREP_PATTERN >out 2>msg && + grep open-files-in-pager msg +' + +test_expect_success 'git grep -O --no-index' ' + rm -f expect.less pager-args out && + cat >expect <<-\EOF && + grep.h + untracked + EOF + >empty && + + ( + GIT_PAGER='\''printf "%s\n" >pager-args'\'' && + export GIT_PAGER && + git grep --no-index -O GREP_PATTERN >out + ) && + test_cmp expect pager-args && + test_cmp empty out +' + +test_expect_success 'setup: fake "less"' ' + cat >less <<-\EOF && + #!/bin/sh + printf "%s\n" "$@" >actual + EOF + chmod +x less +' + +test_expect_success 'git grep -O jumps to line in less' ' + cat >expect <<-\EOF && + +/*GREP_PATTERN + grep.h + EOF + >empty && + + GIT_PAGER=./less git grep -O GREP_PATTERN >out && + test_cmp expect actual && + test_cmp empty out && + + git grep -O./less GREP_PATTERN >out2 && + test_cmp expect actual && + test_cmp empty out2 +' + +test_expect_success 'modified file' ' + rm -f actual && + cat >expect <<-\EOF && + +/*enum grep_pat_token + grep.h + revision.c + subdir/grep.c + unrelated + EOF + >empty && + + echo "enum grep_pat_token" >unrelated && + test_when_finished "git checkout HEAD unrelated" && + GIT_PAGER=./less git grep -F -O "enum grep_pat_token" >out && + test_cmp expect actual && + test_cmp empty out +' + +test_config() { + git config "$1" "$2" && + test_when_finished "git config --unset $1" +} + +test_expect_success 'copes with color settings' ' + rm -f actual && + echo grep.h >expect && + test_config color.grep always && + test_config color.grep.filename yellow && + test_config color.grep.separator green && + git grep -O'\''printf "%s\n" >actual'\'' GREP_AND && + test_cmp expect actual +' + +test_expect_success 'run from subdir' ' + rm -f actual && + echo grep.c >expect && + >empty && + + ( + cd subdir && + export GIT_PAGER && + GIT_PAGER='\''printf "%s\n" >../args'\'' && + git grep -O "enum grep_pat_token" >../out && + git grep -O"pwd >../dir; :" "enum grep_pat_token" >../out2 + ) && + case $(cat dir) in + *subdir) + : good + ;; + *) + false + ;; + esac && + test_cmp expect args && + test_cmp empty out && + test_cmp empty out2 +' + +test_done diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh new file mode 100755 index 0000000000..9ad96d4d32 --- /dev/null +++ b/t/t8006-blame-textconv.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +test_description='git blame textconv support' +. ./test-lib.sh + +find_blame() { + sed -e 's/^[^(]*//' +} + +cat >helper <<'EOF' +#!/bin/sh +sed 's/^/converted: /' "$@" +EOF +chmod +x helper + +test_expect_success 'setup ' ' + echo test 1 >one.bin && + echo test number 2 >two.bin && + git add . && + GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" && + echo test 1 version 2 >one.bin && + echo test number 2 version 2 >>two.bin && + GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00" +' + +cat >expected <<EOF +(Number2 2010-01-01 20:00:00 +0000 1) test 1 version 2 +EOF + +test_expect_success 'no filter specified' ' + git blame one.bin >blame && + find_blame Number2 <blame >result && + test_cmp expected result +' + +test_expect_success 'setup textconv filters' ' + echo "*.bin diff=test" >.gitattributes && + git config diff.test.textconv ./helper && + git config diff.test.cachetextconv false +' + +test_expect_success 'blame with --no-textconv' ' + git blame --no-textconv one.bin >blame && + find_blame <blame> result && + test_cmp expected result +' + +cat >expected <<EOF +(Number2 2010-01-01 20:00:00 +0000 1) converted: test 1 version 2 +EOF + +test_expect_success 'basic blame on last commit' ' + git blame one.bin >blame && + find_blame <blame >result && + test_cmp expected result +' + +cat >expected <<EOF +(Number1 2010-01-01 18:00:00 +0000 1) converted: test number 2 +(Number2 2010-01-01 20:00:00 +0000 2) converted: test number 2 version 2 +EOF + +test_expect_success 'blame --textconv going through revisions' ' + git blame --textconv two.bin >blame && + find_blame <blame >result && + test_cmp expected result +' + +test_expect_success 'make a new commit' ' + echo "test number 2 version 3" >>two.bin && + GIT_AUTHOR_NAME=Number3 git commit -a -m Third --date="2010-01-01 22:00:00" +' + +test_expect_success 'blame from previous revision' ' + git blame HEAD^ two.bin >blame && + find_blame <blame >result && + test_cmp expected result +' + +test_done diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh new file mode 100755 index 0000000000..38ac05e4a0 --- /dev/null +++ b/t/t8007-cat-file-textconv.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='git cat-file textconv support' +. ./test-lib.sh + +cat >helper <<'EOF' +#!/bin/sh +sed 's/^/converted: /' "$@" +EOF +chmod +x helper + +test_expect_success 'setup ' ' + echo test >one.bin && + git add . && + GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" && + echo test version 2 >one.bin && + GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00" +' + +cat >expected <<EOF +fatal: git cat-file --textconv: unable to run textconv on :one.bin +EOF + +test_expect_success 'no filter specified' ' + git cat-file --textconv :one.bin 2>result + test_cmp expected result +' + +test_expect_success 'setup textconv filters' ' + echo "*.bin diff=test" >.gitattributes && + git config diff.test.textconv ./helper && + git config diff.test.cachetextconv false +' + +cat >expected <<EOF +test version 2 +EOF + +test_expect_success 'cat-file without --textconv' ' + git cat-file blob :one.bin >result && + test_cmp expected result +' + +cat >expected <<EOF +test +EOF + +test_expect_success 'cat-file without --textconv on previous commit' ' + git cat-file -p HEAD^:one.bin >result && + test_cmp expected result +' + +cat >expected <<EOF +converted: test version 2 +EOF + +test_expect_success 'cat-file --textconv on last commit' ' + git cat-file --textconv :one.bin >result && + test_cmp expected result +' + +cat >expected <<EOF +converted: test +EOF + +test_expect_success 'cat-file --textconv on previous commit' ' + git cat-file --textconv HEAD^:one.bin >result && + test_cmp expected result +' +test_done diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 640b3d2bb4..d1ba25205b 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -3,20 +3,17 @@ test_description='git send-email' . ./test-lib.sh -if ! test_have_prereq PERL; then - say 'skipping git send-email tests, perl not available' - test_done -fi +# May be altered later in the test +PREREQ="PERL" -PROG='git send-email' -test_expect_success \ +test_expect_success $PREREQ \ 'prepare reference tree' \ 'echo "1A quick brown fox jumps over the" >file && echo "lazy dog" >>file && git add file && GIT_AUTHOR_NAME="A" git commit -a -m "Initial."' -test_expect_success \ +test_expect_success $PREREQ \ 'Setup helper tool' \ '(echo "#!$SHELL_PATH" echo shift @@ -36,7 +33,7 @@ clean_fake_sendmail() { rm -f commandline* msgtxt* } -test_expect_success 'Extract patches' ' +test_expect_success $PREREQ 'Extract patches' ' patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1` ' @@ -57,49 +54,56 @@ test_no_confirm () { # Exit immediately to prevent hang if a no-confirm test fails check_no_confirm () { - test -f no_confirm_okay || { - say 'No confirm test failed; skipping remaining tests to prevent hanging' - test_done - } + if ! test -f no_confirm_okay + then + say 'confirm test failed; skipping remaining tests to prevent hanging' + PREREQ="$PREREQ,CHECK_NO_CONFIRM" + fi + return 0 } -test_expect_success 'No confirm with --suppress-cc' ' - test_no_confirm --suppress-cc=sob +test_expect_success $PREREQ 'No confirm with --suppress-cc' ' + test_no_confirm --suppress-cc=sob && + check_no_confirm ' -check_no_confirm -test_expect_success 'No confirm with --confirm=never' ' - test_no_confirm --confirm=never + +test_expect_success $PREREQ 'No confirm with --confirm=never' ' + test_no_confirm --confirm=never && + check_no_confirm ' -check_no_confirm # leave sendemail.confirm set to never after this so that none of the # remaining tests prompt unintentionally. -test_expect_success 'No confirm with sendemail.confirm=never' ' +test_expect_success $PREREQ 'No confirm with sendemail.confirm=never' ' git config sendemail.confirm never && - test_no_confirm --compose --subject=foo + test_no_confirm --compose --subject=foo && + check_no_confirm ' -check_no_confirm -test_expect_success 'Send patches' ' +test_expect_success $PREREQ 'Send patches' ' git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors ' +test_expect_success $PREREQ 'setup expect' ' cat >expected <<\EOF !nobody@example.com! !author@example.com! !one@example.com! !two@example.com! EOF -test_expect_success \ +' + +test_expect_success $PREREQ \ 'Verify commandline' \ 'test_cmp expected commandline1' -test_expect_success 'Send patches with --envelope-sender' ' +test_expect_success $PREREQ 'Send patches with --envelope-sender' ' clean_fake_sendmail && git send-email --envelope-sender="Patch Contributer <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors ' +test_expect_success $PREREQ 'setup expect' ' cat >expected <<\EOF !patch@example.com! !-i! @@ -108,15 +112,18 @@ cat >expected <<\EOF !one@example.com! !two@example.com! EOF -test_expect_success \ +' + +test_expect_success $PREREQ \ 'Verify commandline' \ 'test_cmp expected commandline1' -test_expect_success 'Send patches with --envelope-sender=auto' ' +test_expect_success $PREREQ 'Send patches with --envelope-sender=auto' ' clean_fake_sendmail && git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors ' +test_expect_success $PREREQ 'setup expect' ' cat >expected <<\EOF !nobody@example.com! !-i! @@ -125,10 +132,13 @@ cat >expected <<\EOF !one@example.com! !two@example.com! EOF -test_expect_success \ +' + +test_expect_success $PREREQ \ 'Verify commandline' \ 'test_cmp expected commandline1' +test_expect_success $PREREQ 'setup expect' " cat >expected-show-all-headers <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -158,8 +168,9 @@ References: <unique-message-id@example.com> Result: OK EOF +" -test_expect_success 'Show all headers' ' +test_expect_success $PREREQ 'Show all headers' ' git send-email \ --dry-run \ --suppress-cc=sob \ @@ -177,7 +188,7 @@ test_expect_success 'Show all headers' ' test_cmp expected-show-all-headers actual-show-all-headers ' -test_expect_success 'Prompting works' ' +test_expect_success $PREREQ 'Prompting works' ' clean_fake_sendmail && (echo "Example <from@example.com>" echo "to@example.com" @@ -190,10 +201,28 @@ test_expect_success 'Prompting works' ' grep "^To: to@example.com\$" msgtxt1 ' -test_expect_success 'cccmd works' ' +test_expect_success $PREREQ 'tocmd works' ' + clean_fake_sendmail && + cp $patches tocmd.patch && + echo tocmd--tocmd@example.com >>tocmd.patch && + { + echo "#!$SHELL_PATH" + echo sed -n -e s/^tocmd--//p \"\$1\" + } > tocmd-sed && + chmod +x tocmd-sed && + git send-email \ + --from="Example <nobody@example.com>" \ + --to-cmd=./tocmd-sed \ + --smtp-server="$(pwd)/fake.sendmail" \ + tocmd.patch \ + && + grep "^To: tocmd@example.com" msgtxt1 +' + +test_expect_success $PREREQ 'cccmd works' ' clean_fake_sendmail && cp $patches cccmd.patch && - echo cccmd--cccmd@example.com >>cccmd.patch && + echo "cccmd-- cccmd@example.com" >>cccmd.patch && { echo "#!$SHELL_PATH" echo sed -n -e s/^cccmd--//p \"\$1\" @@ -209,10 +238,10 @@ test_expect_success 'cccmd works' ' grep "^ cccmd@example.com" msgtxt1 ' -z8=zzzzzzzz -z64=$z8$z8$z8$z8$z8$z8$z8$z8 -z512=$z64$z64$z64$z64$z64$z64$z64$z64 -test_expect_success 'reject long lines' ' +test_expect_success $PREREQ 'reject long lines' ' + z8=zzzzzzzz && + z64=$z8$z8$z8$z8$z8$z8$z8$z8 && + z512=$z64$z64$z64$z64$z64$z64$z64$z64 && clean_fake_sendmail && cp $patches longline.patch && echo $z512$z512 >>longline.patch && @@ -225,11 +254,11 @@ test_expect_success 'reject long lines' ' grep longline.patch errors ' -test_expect_success 'no patch was sent' ' +test_expect_success $PREREQ 'no patch was sent' ' ! test -e commandline1 ' -test_expect_success 'Author From: in message body' ' +test_expect_success $PREREQ 'Author From: in message body' ' clean_fake_sendmail && git send-email \ --from="Example <nobody@example.com>" \ @@ -240,7 +269,7 @@ test_expect_success 'Author From: in message body' ' grep "From: A <author@example.com>" msgbody1 ' -test_expect_success 'Author From: not in message body' ' +test_expect_success $PREREQ 'Author From: not in message body' ' clean_fake_sendmail && git send-email \ --from="A <author@example.com>" \ @@ -251,7 +280,7 @@ test_expect_success 'Author From: not in message body' ' ! grep "From: A <author@example.com>" msgbody1 ' -test_expect_success 'allow long lines with --no-validate' ' +test_expect_success $PREREQ 'allow long lines with --no-validate' ' git send-email \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ @@ -261,19 +290,19 @@ test_expect_success 'allow long lines with --no-validate' ' 2>errors ' -test_expect_success 'Invalid In-Reply-To' ' +test_expect_success $PREREQ 'Invalid In-Reply-To' ' clean_fake_sendmail && git send-email \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --in-reply-to=" " \ --smtp-server="$(pwd)/fake.sendmail" \ - $patches + $patches \ 2>errors ! grep "^In-Reply-To: < *>" msgtxt1 ' -test_expect_success 'Valid In-Reply-To when prompting' ' +test_expect_success $PREREQ 'Valid In-Reply-To when prompting' ' clean_fake_sendmail && (echo "From Example <from@example.com>" echo "To Example <to@example.com>" @@ -284,7 +313,7 @@ test_expect_success 'Valid In-Reply-To when prompting' ' ! grep "^In-Reply-To: < *>" msgtxt1 ' -test_expect_success 'setup fake editor' ' +test_expect_success $PREREQ 'setup fake editor' ' (echo "#!$SHELL_PATH" && echo "echo fake edit >>\"\$1\"" ) >fake-editor && @@ -293,7 +322,7 @@ test_expect_success 'setup fake editor' ' test_set_editor "$(pwd)/fake-editor" -test_expect_success '--compose works' ' +test_expect_success $PREREQ '--compose works' ' clean_fake_sendmail && git send-email \ --compose --subject foo \ @@ -304,14 +333,15 @@ test_expect_success '--compose works' ' 2>errors ' -test_expect_success 'first message is compose text' ' +test_expect_success $PREREQ 'first message is compose text' ' grep "^fake edit" msgtxt1 ' -test_expect_success 'second message is patch' ' +test_expect_success $PREREQ 'second message is patch' ' grep "Subject:.*Second" msgtxt2 ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-sob <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -338,6 +368,7 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" test_suppression () { git send-email \ @@ -354,11 +385,12 @@ test_suppression () { test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"} } -test_expect_success 'sendemail.cc set' ' +test_expect_success $PREREQ 'sendemail.cc set' ' git config sendemail.cc cc@example.com && test_suppression sob ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-sob <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -383,12 +415,14 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success 'sendemail.cc unset' ' +test_expect_success $PREREQ 'sendemail.cc unset' ' git config --unset sendemail.cc && test_suppression sob ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-cccmd <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -416,14 +450,16 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success 'sendemail.cccmd' ' +test_expect_success $PREREQ 'sendemail.cccmd' ' echo echo cc-cmd@example.com > cccmd && chmod +x cccmd && git config sendemail.cccmd ./cccmd && test_suppression cccmd ' +test_expect_success $PREREQ 'setup expect' ' cat >expected-suppress-all <<\EOF 0001-Second.patch Dry-OK. Log says: @@ -439,11 +475,13 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +' -test_expect_success '--suppress-cc=all' ' +test_expect_success $PREREQ '--suppress-cc=all' ' test_suppression all ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-body <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -471,11 +509,13 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success '--suppress-cc=body' ' +test_expect_success $PREREQ '--suppress-cc=body' ' test_suppression body ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-body-cccmd <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -500,11 +540,13 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success '--suppress-cc=body --suppress-cc=cccmd' ' +test_expect_success $PREREQ '--suppress-cc=body --suppress-cc=cccmd' ' test_suppression body cccmd ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-sob <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -529,12 +571,14 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success '--suppress-cc=sob' ' +test_expect_success $PREREQ '--suppress-cc=sob' ' git config --unset sendemail.cccmd test_suppression sob ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-bodycc <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -562,11 +606,13 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success '--suppress-cc=bodycc' ' +test_expect_success $PREREQ '--suppress-cc=bodycc' ' test_suppression bodycc ' +test_expect_success $PREREQ 'setup expect' " cat >expected-suppress-cc <<\EOF 0001-Second.patch (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' @@ -588,8 +634,9 @@ X-Mailer: X-MAILER-STRING Result: OK EOF +" -test_expect_success '--suppress-cc=cc' ' +test_expect_success $PREREQ '--suppress-cc=cc' ' test_suppression cc ' @@ -604,23 +651,23 @@ test_confirm () { grep "Send this email" stdout } -test_expect_success '--confirm=always' ' +test_expect_success $PREREQ '--confirm=always' ' test_confirm --confirm=always --suppress-cc=all ' -test_expect_success '--confirm=auto' ' +test_expect_success $PREREQ '--confirm=auto' ' test_confirm --confirm=auto ' -test_expect_success '--confirm=cc' ' +test_expect_success $PREREQ '--confirm=cc' ' test_confirm --confirm=cc ' -test_expect_success '--confirm=compose' ' +test_expect_success $PREREQ '--confirm=compose' ' test_confirm --confirm=compose --compose ' -test_expect_success 'confirm by default (due to cc)' ' +test_expect_success $PREREQ 'confirm by default (due to cc)' ' CONFIRM=$(git config --get sendemail.confirm) && git config --unset sendemail.confirm && test_confirm @@ -629,7 +676,7 @@ test_expect_success 'confirm by default (due to cc)' ' test $ret = "0" ' -test_expect_success 'confirm by default (due to --compose)' ' +test_expect_success $PREREQ 'confirm by default (due to --compose)' ' CONFIRM=$(git config --get sendemail.confirm) && git config --unset sendemail.confirm && test_confirm --suppress-cc=all --compose @@ -638,7 +685,7 @@ test_expect_success 'confirm by default (due to --compose)' ' test $ret = "0" ' -test_expect_success 'confirm detects EOF (inform assumes y)' ' +test_expect_success $PREREQ 'confirm detects EOF (inform assumes y)' ' CONFIRM=$(git config --get sendemail.confirm) && git config --unset sendemail.confirm && rm -fr outdir && @@ -654,7 +701,7 @@ test_expect_success 'confirm detects EOF (inform assumes y)' ' test $ret = "0" ' -test_expect_success 'confirm detects EOF (auto causes failure)' ' +test_expect_success $PREREQ 'confirm detects EOF (auto causes failure)' ' CONFIRM=$(git config --get sendemail.confirm) && git config sendemail.confirm auto && GIT_SEND_EMAIL_NOTTY=1 && @@ -669,7 +716,7 @@ test_expect_success 'confirm detects EOF (auto causes failure)' ' test $ret = "0" ' -test_expect_success 'confirm doesnt loop forever' ' +test_expect_success $PREREQ 'confirm doesnt loop forever' ' CONFIRM=$(git config --get sendemail.confirm) && git config sendemail.confirm auto && GIT_SEND_EMAIL_NOTTY=1 && @@ -684,7 +731,7 @@ test_expect_success 'confirm doesnt loop forever' ' test $ret = "0" ' -test_expect_success 'utf8 Cc is rfc2047 encoded' ' +test_expect_success $PREREQ 'utf8 Cc is rfc2047 encoded' ' clean_fake_sendmail && rm -fr outdir && git format-patch -1 -o outdir --cc="à éìöú <utf8@example.com>" && @@ -697,7 +744,7 @@ test_expect_success 'utf8 Cc is rfc2047 encoded' ' grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>" ' -test_expect_success '--compose adds MIME for utf8 body' ' +test_expect_success $PREREQ '--compose adds MIME for utf8 body' ' clean_fake_sendmail && (echo "#!$SHELL_PATH" && echo "echo utf8 body: à éìöú >>\"\$1\"" @@ -714,7 +761,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' -test_expect_success '--compose respects user mime type' ' +test_expect_success $PREREQ '--compose respects user mime type' ' clean_fake_sendmail && (echo "#!$SHELL_PATH" && echo "(echo MIME-Version: 1.0" @@ -737,7 +784,7 @@ test_expect_success '--compose respects user mime type' ' ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' -test_expect_success '--compose adds MIME for utf8 subject' ' +test_expect_success $PREREQ '--compose adds MIME for utf8 subject' ' clean_fake_sendmail && GIT_EDITOR="\"$(pwd)/fake-editor\"" \ git send-email \ @@ -750,7 +797,7 @@ test_expect_success '--compose adds MIME for utf8 subject' ' grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 ' -test_expect_success 'detects ambiguous reference/file conflict' ' +test_expect_success $PREREQ 'detects ambiguous reference/file conflict' ' echo master > master && git add master && git commit -m"add master" && @@ -758,7 +805,7 @@ test_expect_success 'detects ambiguous reference/file conflict' ' grep disambiguate errors ' -test_expect_success 'feed two files' ' +test_expect_success $PREREQ 'feed two files' ' rm -fr outdir && git format-patch -2 -o outdir && git send-email \ @@ -771,7 +818,7 @@ test_expect_success 'feed two files' ' test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master" ' -test_expect_success 'in-reply-to but no threading' ' +test_expect_success $PREREQ 'in-reply-to but no threading' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -782,7 +829,7 @@ test_expect_success 'in-reply-to but no threading' ' grep "In-Reply-To: <in-reply-id@example.com>" ' -test_expect_success 'no in-reply-to and no threading' ' +test_expect_success $PREREQ 'no in-reply-to and no threading' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -792,7 +839,7 @@ test_expect_success 'no in-reply-to and no threading' ' ! grep "In-Reply-To: " stdout ' -test_expect_success 'threading but no chain-reply-to' ' +test_expect_success $PREREQ 'threading but no chain-reply-to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -803,7 +850,7 @@ test_expect_success 'threading but no chain-reply-to' ' grep "In-Reply-To: " stdout ' -test_expect_success 'warning with an implicit --chain-reply-to' ' +test_expect_success $PREREQ 'warning with an implicit --chain-reply-to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -812,7 +859,7 @@ test_expect_success 'warning with an implicit --chain-reply-to' ' grep "no-chain-reply-to" errors ' -test_expect_success 'no warning with an explicit --chain-reply-to' ' +test_expect_success $PREREQ 'no warning with an explicit --chain-reply-to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -822,7 +869,7 @@ test_expect_success 'no warning with an explicit --chain-reply-to' ' ! grep "no-chain-reply-to" errors ' -test_expect_success 'no warning with an explicit --no-chain-reply-to' ' +test_expect_success $PREREQ 'no warning with an explicit --no-chain-reply-to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -832,7 +879,7 @@ test_expect_success 'no warning with an explicit --no-chain-reply-to' ' ! grep "no-chain-reply-to" errors ' -test_expect_success 'no warning with sendemail.chainreplyto = false' ' +test_expect_success $PREREQ 'no warning with sendemail.chainreplyto = false' ' git config sendemail.chainreplyto false && git send-email \ --dry-run \ @@ -842,7 +889,7 @@ test_expect_success 'no warning with sendemail.chainreplyto = false' ' ! grep "no-chain-reply-to" errors ' -test_expect_success 'no warning with sendemail.chainreplyto = true' ' +test_expect_success $PREREQ 'no warning with sendemail.chainreplyto = true' ' git config sendemail.chainreplyto true && git send-email \ --dry-run \ @@ -852,7 +899,7 @@ test_expect_success 'no warning with sendemail.chainreplyto = true' ' ! grep "no-chain-reply-to" errors ' -test_expect_success 'sendemail.to works' ' +test_expect_success $PREREQ 'sendemail.to works' ' git config --replace-all sendemail.to "Somebody <somebody@ex.com>" && git send-email \ --dry-run \ @@ -861,7 +908,7 @@ test_expect_success 'sendemail.to works' ' grep "To: Somebody <somebody@ex.com>" stdout ' -test_expect_success '--no-to overrides sendemail.to' ' +test_expect_success $PREREQ '--no-to overrides sendemail.to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -872,7 +919,7 @@ test_expect_success '--no-to overrides sendemail.to' ' ! grep "To: Somebody <somebody@ex.com>" stdout ' -test_expect_success 'sendemail.cc works' ' +test_expect_success $PREREQ 'sendemail.cc works' ' git config --replace-all sendemail.cc "Somebody <somebody@ex.com>" && git send-email \ --dry-run \ @@ -882,7 +929,7 @@ test_expect_success 'sendemail.cc works' ' grep "Cc: Somebody <somebody@ex.com>" stdout ' -test_expect_success '--no-cc overrides sendemail.cc' ' +test_expect_success $PREREQ '--no-cc overrides sendemail.cc' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -894,7 +941,7 @@ test_expect_success '--no-cc overrides sendemail.cc' ' ! grep "Cc: Somebody <somebody@ex.com>" stdout ' -test_expect_success 'sendemail.bcc works' ' +test_expect_success $PREREQ 'sendemail.bcc works' ' git config --replace-all sendemail.bcc "Other <other@ex.com>" && git send-email \ --dry-run \ @@ -905,7 +952,7 @@ test_expect_success 'sendemail.bcc works' ' grep "RCPT TO:<other@ex.com>" stdout ' -test_expect_success '--no-bcc overrides sendemail.bcc' ' +test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ @@ -918,4 +965,164 @@ test_expect_success '--no-bcc overrides sendemail.bcc' ' ! grep "RCPT TO:<other@ex.com>" stdout ' +test_expect_success $PREREQ 'patches To headers are used by default' ' + patch=`git format-patch -1 --to="bodies@example.com"` && + test_when_finished "rm $patch" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --smtp-server relay.example.com \ + $patch >stdout && + grep "RCPT TO:<bodies@example.com>" stdout +' + +test_expect_success $PREREQ 'patches To headers are appended to' ' + patch=`git format-patch -1 --to="bodies@example.com"` && + test_when_finished "rm $patch" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server relay.example.com \ + $patch >stdout && + grep "RCPT TO:<bodies@example.com>" stdout && + grep "RCPT TO:<nobody@example.com>" stdout +' + +test_expect_success $PREREQ 'To headers from files reset each patch' ' + patch1=`git format-patch -1 --to="bodies@example.com"` && + patch2=`git format-patch -1 --to="other@example.com" HEAD~` && + test_when_finished "rm $patch1 && rm $patch2" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to="nobody@example.com" \ + --smtp-server relay.example.com \ + $patch1 $patch2 >stdout && + test $(grep -c "RCPT TO:<bodies@example.com>" stdout) = 1 && + test $(grep -c "RCPT TO:<nobody@example.com>" stdout) = 2 && + test $(grep -c "RCPT TO:<other@example.com>" stdout) = 1 +' + +test_expect_success $PREREQ 'setup expect' ' +cat >email-using-8bit <<EOF +From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 +Message-Id: <bogus-message-id@example.com> +From: author@example.com +Date: Sat, 12 Jun 2010 15:53:58 +0200 +Subject: subject goes here + +Dieser deutsche Text enthält einen Umlaut! +EOF +' + +test_expect_success $PREREQ 'setup expect' ' +cat >content-type-decl <<EOF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +EOF +' + +test_expect_success $PREREQ 'asks about and fixes 8bit encodings' ' + clean_fake_sendmail && + echo | + git send-email --from=author@example.com --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + email-using-8bit >stdout && + grep "do not declare a Content-Transfer-Encoding" stdout && + grep email-using-8bit stdout && + grep "Which 8bit encoding" stdout && + egrep "Content|MIME" msgtxt1 >actual && + test_cmp actual content-type-decl +' + +test_expect_success $PREREQ 'sendemail.8bitEncoding works' ' + clean_fake_sendmail && + git config sendemail.assume8bitEncoding UTF-8 && + echo bogus | + git send-email --from=author@example.com --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + email-using-8bit >stdout && + egrep "Content|MIME" msgtxt1 >actual && + test_cmp actual content-type-decl +' + +test_expect_success $PREREQ '--8bit-encoding overrides sendemail.8bitEncoding' ' + clean_fake_sendmail && + git config sendemail.assume8bitEncoding "bogus too" && + echo bogus | + git send-email --from=author@example.com --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --8bit-encoding=UTF-8 \ + email-using-8bit >stdout && + egrep "Content|MIME" msgtxt1 >actual && + test_cmp actual content-type-decl +' + +test_expect_success $PREREQ 'setup expect' ' +cat >email-using-8bit <<EOF +From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 +Message-Id: <bogus-message-id@example.com> +From: author@example.com +Date: Sat, 12 Jun 2010 15:53:58 +0200 +Subject: Dieser Betreff enthält auch einen Umlaut! + +Nothing to see here. +EOF +' + +test_expect_success $PREREQ 'setup expect' ' +cat >expected <<EOF +Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?= +EOF +' + +test_expect_success $PREREQ '--8bit-encoding also treats subject' ' + clean_fake_sendmail && + echo bogus | + git send-email --from=author@example.com --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --8bit-encoding=UTF-8 \ + email-using-8bit >stdout && + grep "Subject" msgtxt1 >actual && + test_cmp expected actual +' + +# Note that the patches in this test are deliberately out of order; we +# want to make sure it works even if the cover-letter is not in the +# first mail. +test_expect_success 'refusing to send cover letter template' ' + clean_fake_sendmail && + rm -fr outdir && + git format-patch --cover-letter -2 -o outdir && + test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/0002-*.patch \ + outdir/0000-*.patch \ + outdir/0001-*.patch \ + 2>errors >out && + grep "SUBJECT HERE" errors && + test -z "$(ls msgtxt*)" +' + +test_expect_success '--force sends cover letter template anyway' ' + clean_fake_sendmail && + rm -fr outdir && + git format-patch --cover-letter -2 -o outdir && + git send-email \ + --force \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/0002-*.patch \ + outdir/0000-*.patch \ + outdir/0001-*.patch \ + 2>errors >out && + ! grep "SUBJECT HERE" errors && + test -n "$(ls msgtxt*)" +' + test_done diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh new file mode 100755 index 0000000000..a713dfc50b --- /dev/null +++ b/t/t9010-svn-fe.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='check svn dumpfile importer' + +. ./lib-git-svn.sh + +test_dump() { + label=$1 + dump=$2 + test_expect_success "$dump" ' + svnadmin create "$label-svn" && + svnadmin load "$label-svn" < "$TEST_DIRECTORY/$dump" && + svn_cmd export "file://$PWD/$label-svn" "$label-svnco" && + git init "$label-git" && + test-svn-fe "$TEST_DIRECTORY/$dump" >"$label.fe" && + ( + cd "$label-git" && + git fast-import < ../"$label.fe" + ) && + ( + cd "$label-svnco" && + git init && + git add . && + git fetch "../$label-git" master && + git diff --exit-code FETCH_HEAD + ) + ' +} + +test_dump simple t9135/svn.dump + +test_done diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 570e0359e4..b041516a1d 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -15,24 +15,25 @@ case "$GIT_SVN_LC_ALL" in test_set_prereq UTF8 ;; *) - say "UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)" + say "# UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)" ;; esac test_expect_success \ 'initialize git svn' ' mkdir import && - cd import && - echo foo > foo && - ln -s foo foo.link - mkdir -p dir/a/b/c/d/e && - echo "deep dir" > dir/a/b/c/d/e/file && - mkdir bar && - echo "zzz" > bar/zzz && - echo "#!/bin/sh" > exec.sh && - chmod +x exec.sh && - svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null && - cd .. && + ( + cd import && + echo foo >foo && + ln -s foo foo.link + mkdir -p dir/a/b/c/d/e && + echo "deep dir" >dir/a/b/c/d/e/file && + mkdir bar && + echo "zzz" >bar/zzz && + echo "#!/bin/sh" >exec.sh && + chmod +x exec.sh && + svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null + ) && rm -rf import && git svn init "$svnrepo"' @@ -142,7 +143,7 @@ test_expect_success "$name" ' git svn set-tree --find-copies-harder --rmdir \ ${remotes_git_svn}..mybranch5 && svn_cmd up "$SVN_TREE" && - test -L "$SVN_TREE"/exec.sh' + test -h "$SVN_TREE"/exec.sh' name='new symlink is added to a file that was also just made executable' @@ -155,7 +156,7 @@ test_expect_success "$name" ' ${remotes_git_svn}..mybranch5 && svn_cmd up "$SVN_TREE" && test -x "$SVN_TREE"/bar/zzz && - test -L "$SVN_TREE"/exec-2.sh' + test -h "$SVN_TREE"/exec-2.sh' name='modify a symlink to become a file' test_expect_success "$name" ' @@ -168,7 +169,7 @@ test_expect_success "$name" ' ${remotes_git_svn}..mybranch5 && svn_cmd up "$SVN_TREE" && test -f "$SVN_TREE"/exec-2.sh && - test ! -L "$SVN_TREE"/exec-2.sh && + test ! -h "$SVN_TREE"/exec-2.sh && test_cmp help "$SVN_TREE"/exec-2.sh' name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL" @@ -271,6 +272,17 @@ test_expect_success 'able to dcommit to a subdirectory' " test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" " +test_expect_success 'dcommit should not fail with a touched file' ' + test_commit "commit-new-file-foo2" foo2 && + test-chmtime =-60 foo && + git svn dcommit +' + +test_expect_success 'rebase should not fail with a touched file' ' + test-chmtime =-60 foo && + git svn rebase +' + test_expect_success 'able to set-tree to a subdirectory' " echo cba > d && git update-index d && diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index 929499e996..8869f5018e 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -53,8 +53,9 @@ cd .. rm -rf import test_expect_success 'checkout working copy from svn' 'svn co "$svnrepo" test_wc' -test_expect_success 'setup some commits to svn' \ - 'cd test_wc && +test_expect_success 'setup some commits to svn' ' + ( + cd test_wc && echo Greetings >> kw.c && poke kw.c && svn_cmd commit -m "Not yet an Id" && @@ -63,8 +64,9 @@ test_expect_success 'setup some commits to svn' \ svn_cmd commit -m "Modified file, but still not yet an Id" && svn_cmd propset svn:keywords Id kw.c && poke kw.c && - svn_cmd commit -m "Propset Id" && - cd ..' + svn_cmd commit -m "Propset Id" + ) +' test_expect_success 'initialize git svn' 'git svn init "$svnrepo"' test_expect_success 'fetch revisions from svn' 'git svn fetch' @@ -81,13 +83,15 @@ expect='/* $Id$ */' got="`sed -ne 2p kw.c`" test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'" -test_expect_success "propset CR on crlf files" \ - 'cd test_wc && +test_expect_success "propset CR on crlf files" ' + ( + cd test_wc && svn_cmd propset svn:eol-style CR empty && svn_cmd propset svn:eol-style CR crlf && svn_cmd propset svn:eol-style CR ne_crlf && - svn_cmd commit -m "propset CR on crlf files" && - cd ..' + svn_cmd commit -m "propset CR on crlf files" + ) +' test_expect_success 'fetch and pull latest from svn and checkout a new wc' \ 'git svn fetch && @@ -137,19 +141,20 @@ cat > show-ignore.expect <<\EOF EOF test_expect_success 'test show-ignore' " - cd test_wc && - mkdir -p deeply/nested/directory && - touch deeply/nested/directory/.keep && - svn_cmd add deeply && - svn_cmd up && - svn_cmd propset -R svn:ignore ' + ( + cd test_wc && + mkdir -p deeply/nested/directory && + touch deeply/nested/directory/.keep && + svn_cmd add deeply && + svn_cmd up && + svn_cmd propset -R svn:ignore ' no-such-file* ' . - svn_cmd commit -m 'propset svn:ignore' - cd .. && + svn_cmd commit -m 'propset svn:ignore' + ) && git svn show-ignore > show-ignore.got && cmp show-ignore.expect show-ignore.got - " +" cat >create-ignore.expect <<\EOF /no-such-file* diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh index 028fb19e09..eb70f4839c 100755 --- a/t/t9102-git-svn-deep-rmdir.sh +++ b/t/t9102-git-svn-deep-rmdir.sh @@ -4,13 +4,14 @@ test_description='git svn rmdir' test_expect_success 'initialize repo' ' mkdir import && - cd import && - mkdir -p deeply/nested/directory/number/1 && - mkdir -p deeply/nested/directory/number/2 && - echo foo > deeply/nested/directory/number/1/file && - echo foo > deeply/nested/directory/number/2/another && - svn_cmd import -m "import for git svn" . "$svnrepo" && - cd .. + ( + cd import && + mkdir -p deeply/nested/directory/number/1 && + mkdir -p deeply/nested/directory/number/2 && + echo foo >deeply/nested/directory/number/1/file && + echo foo >deeply/nested/directory/number/2/another && + svn_cmd import -m "import for git svn" . "$svnrepo" + ) ' test_expect_success 'mirror via git svn' ' diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index bbfd7f4793..f7f3c5ab8e 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -8,22 +8,24 @@ test_description='git svn fetching' test_expect_success 'initialize repo' ' mkdir import && - cd import && - mkdir -p trunk && - echo hello > trunk/readme && - svn_cmd import -m "initial" . "$svnrepo" && - cd .. && + ( + cd import && + mkdir -p trunk && + echo hello >trunk/readme && + svn_cmd import -m "initial" . "$svnrepo" + ) && svn_cmd co "$svnrepo" wc && - cd wc && - echo world >> trunk/readme && - poke trunk/readme && - svn_cmd commit -m "another commit" && - svn_cmd up && - svn_cmd mv trunk thunk && - echo goodbye >> thunk/readme && - poke thunk/readme && - svn_cmd commit -m "bye now" && - cd .. + ( + cd wc && + echo world >>trunk/readme && + poke trunk/readme && + svn_cmd commit -m "another commit" && + svn_cmd up && + svn_cmd mv trunk thunk && + echo goodbye >>thunk/readme && + poke thunk/readme && + svn_cmd commit -m "bye now" + ) ' test_expect_success 'init and fetch a moved directory' ' @@ -83,16 +85,17 @@ test_expect_success 'follow larger parent' ' ' test_expect_success 'follow higher-level parent' ' - svn mkdir -m "follow higher-level parent" "$svnrepo"/blob && - svn co "$svnrepo"/blob blob && - cd blob && - echo hi > hi && - svn add hi && - svn commit -m "hihi" && - cd .. - svn mkdir -m "new glob at top level" "$svnrepo"/glob && - svn mv -m "move blob down a level" "$svnrepo"/blob "$svnrepo"/glob/blob && - git svn init --minimize-url -i blob "$svnrepo"/glob/blob && + svn mkdir -m "follow higher-level parent" "$svnrepo"/blob && + svn co "$svnrepo"/blob blob && + ( + cd blob && + echo hi > hi && + svn add hi && + svn commit -m "hihi" + ) && + svn mkdir -m "new glob at top level" "$svnrepo"/glob && + svn mv -m "move blob down a level" "$svnrepo"/blob "$svnrepo"/glob/blob && + git svn init --minimize-url -i blob "$svnrepo"/glob/blob && git svn fetch -i blob ' @@ -117,18 +120,23 @@ test_expect_success 'follow-parent avoids deleting relevant info' ' import/trunk/subversion/bindings/swig/perl/t/larger-parent && echo "bad delete test 2" > \ import/trunk/subversion/bindings/swig/perl/another-larger && - cd import && - svn import -m "r9270 test" . "$svnrepo"/r9270 && - cd .. && + ( + cd import && + svn import -m "r9270 test" . "$svnrepo"/r9270 + ) && svn_cmd co "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl r9270 && - cd r9270 && - svn mkdir native && - svn mv t native/t && - for i in a b c; do svn mv $i.pm native/$i.pm; done && - echo z >> native/t/c.t && - poke native/t/c.t && - svn commit -m "reorg test" && - cd .. && + ( + cd r9270 && + svn mkdir native && + svn mv t native/t && + for i in a b c + do + svn mv $i.pm native/$i.pm + done && + echo z >>native/t/c.t && + poke native/t/c.t && + svn commit -m "reorg test" + ) && git svn init --minimize-url -i r9270-t \ "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl/native/t && git svn fetch -i r9270-t && diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh index dd48e9cba8..5d0afeae6c 100755 --- a/t/t9105-git-svn-commit-diff.sh +++ b/t/t9105-git-svn-commit-diff.sh @@ -6,10 +6,11 @@ test_description='git svn commit-diff' test_expect_success 'initialize repo' ' mkdir import && - cd import && - echo hello > readme && - svn_cmd import -m "initial" . "$svnrepo" && - cd .. && + ( + cd import && + echo hello >readme && + svn_cmd import -m "initial" . "$svnrepo" + ) && echo hello > readme && git update-index --add readme && git commit -a -m "initial" && diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh index 12f21b700e..f6d7ac7c5f 100755 --- a/t/t9106-git-svn-commit-diff-clobber.sh +++ b/t/t9106-git-svn-commit-diff-clobber.sh @@ -6,21 +6,23 @@ test_description='git svn commit-diff clobber' test_expect_success 'initialize repo' ' mkdir import && - cd import && - echo initial > file && - svn_cmd import -m "initial" . "$svnrepo" && - cd .. && + ( + cd import && + echo initial >file && + svn_cmd import -m "initial" . "$svnrepo" + ) && echo initial > file && git update-index --add file && git commit -a -m "initial" ' test_expect_success 'commit change from svn side' ' svn_cmd co "$svnrepo" t.svn && - cd t.svn && - echo second line from svn >> file && - poke file && - svn_cmd commit -m "second line from svn" && - cd .. && + ( + cd t.svn && + echo second line from svn >>file && + poke file && + svn_cmd commit -m "second line from svn" + ) && rm -rf t.svn ' @@ -44,11 +46,12 @@ test_expect_success 'dcommit fails to commit because of conflict' ' git svn fetch && git reset --hard refs/${remotes_git_svn} && svn_cmd co "$svnrepo" t.svn && - cd t.svn && - echo fourth line from svn >> file && - poke file && - svn_cmd commit -m "fourth line from svn" && - cd .. && + ( + cd t.svn && + echo fourth line from svn >>file && + poke file && + svn_cmd commit -m "fourth line from svn" + ) && rm -rf t.svn && echo "fourth line from git" >> file && git commit -a -m "fourth line from git" && @@ -68,11 +71,12 @@ test_expect_success 'dcommit does the svn equivalent of an index merge' " test_expect_success 'commit another change from svn side' ' svn_cmd co "$svnrepo" t.svn && - cd t.svn && - echo third line from svn >> file && + ( + cd t.svn && + echo third line from svn >>file && poke file && - svn_cmd commit -m "third line from svn" && - cd .. && + svn_cmd commit -m "third line from svn" + ) && rm -rf t.svn ' diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index 901b8e09fb..289fc313fb 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -6,14 +6,16 @@ test_description='git svn metadata migrations from previous versions' test_expect_success 'setup old-looking metadata' ' cp "$GIT_DIR"/config "$GIT_DIR"/config-old-git-svn && mkdir import && - cd import && - for i in trunk branches/a branches/b \ - tags/0.1 tags/0.2 tags/0.3; do - mkdir -p $i && \ - echo hello >> $i/README || exit 1 - done && \ + ( + cd import && + for i in trunk branches/a branches/b tags/0.1 tags/0.2 tags/0.3 + do + mkdir -p $i && + echo hello >>$i/README || + exit 1 + done && svn_cmd import -m test . "$svnrepo" - cd .. && + ) && git svn init "$svnrepo" && git svn fetch && rm -rf "$GIT_DIR"/svn && diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index 84f7c9b4bb..3077851015 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -37,11 +37,12 @@ EOF test_expect_success 'setup svn repository' ' svn_cmd co "$svnrepo" mysvnwork && mkdir -p mysvnwork/trunk && - cd mysvnwork && - big_text_block >> trunk/README && + ( + cd mysvnwork && + big_text_block >>trunk/README && svn_cmd add trunk && - svn_cmd ci -m "first commit" trunk && - cd .. + svn_cmd ci -m "first commit" trunk + ) ' test_expect_success 'setup git mirror and merge' ' diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh index 767799e7a7..6a48e40429 100755 --- a/t/t9115-git-svn-dcommit-funky-renames.sh +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -61,11 +61,12 @@ test_expect_success 'add a file with plus signs' ' test_expect_success 'clone the repository to test rebase' ' git svn clone "$svnrepo" test-rebase && - cd test-rebase && - echo test-rebase > test-rebase && + ( + cd test-rebase && + echo test-rebase >test-rebase && git add test-rebase && - git commit -m test-rebase && - cd .. + git commit -m test-rebase + ) ' test_expect_success 'make a commit to test rebase' ' diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh index 0374a7476b..5d477e4bda 100755 --- a/t/t9116-git-svn-log.sh +++ b/t/t9116-git-svn-log.sh @@ -8,14 +8,16 @@ test_description='git svn log tests' test_expect_success 'setup repository and import' ' mkdir import && - cd import && - for i in trunk branches/a branches/b \ - tags/0.1 tags/0.2 tags/0.3; do - mkdir -p $i && \ - echo hello >> $i/README || exit 1 - done && \ + ( + cd import && + for i in trunk branches/a branches/b tags/0.1 tags/0.2 tags/0.3 + do + mkdir -p $i && + echo hello >>$i/README || + exit 1 + done && svn_cmd import -m test . "$svnrepo" - cd .. && + ) && git svn init "$svnrepo" -T trunk -b branches -t tags && git svn fetch && git reset --hard trunk && diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index ac52bff0ef..63fc982c8c 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -21,34 +21,59 @@ test_expect_success 'setup svnrepo' ' "$svnrepo/pr ject/branches/more fun plugin!" && svn_cmd cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \ "$svnrepo/pr ject/branches/$scary_uri" && + svn_cmd cp -m "leading dot" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/.leading_dot" && + svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/trailing_dot." && + svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/trailing_dotlock.lock" && + svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/not-a%40{0}reflog" && start_httpd ' test_expect_success 'test clone with funky branch names' ' git svn clone -s "$svnrepo/pr ject" project && - cd project && + ( + cd project && git rev-parse "refs/remotes/fun%20plugin" && git rev-parse "refs/remotes/more%20fun%20plugin!" && git rev-parse "refs/remotes/$scary_ref" && - cd .. + git rev-parse "refs/remotes/%2Eleading_dot" && + git rev-parse "refs/remotes/trailing_dot%2E" && + git rev-parse "refs/remotes/trailing_dotlock%2Elock" && + git rev-parse "refs/remotes/not-a%40{0}reflog" + ) ' test_expect_success 'test dcommit to funky branch' " - cd project && - git reset --hard 'refs/remotes/more%20fun%20plugin!' && - echo hello >> foo && - git commit -m 'hello' -- foo && - git svn dcommit && - cd .. + ( + cd project && + git reset --hard 'refs/remotes/more%20fun%20plugin!' && + echo hello >> foo && + git commit -m 'hello' -- foo && + git svn dcommit + ) " test_expect_success 'test dcommit to scary branch' ' - cd project && - git reset --hard "refs/remotes/$scary_ref" && - echo urls are scary >> foo && - git commit -m "eep" -- foo && - git svn dcommit && - cd .. + ( + cd project && + git reset --hard "refs/remotes/$scary_ref" && + echo urls are scary >> foo && + git commit -m "eep" -- foo && + git svn dcommit + ) + ' + +test_expect_success 'test dcommit to trailing_dotlock branch' ' + ( + cd project && + git reset --hard "refs/remotes/trailing_dotlock%2Elock" && + echo who names branches like this anyway? >> foo && + git commit -m "bar" -- foo && + git svn dcommit + ) ' stop_httpd diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh index a9a558d292..f3f397cdda 100755 --- a/t/t9119-git-svn-info.sh +++ b/t/t9119-git-svn-info.sh @@ -13,7 +13,7 @@ case $v in 1.[456].*) ;; *) - say "skipping svn-info test (SVN version: $v not supported)" + skip_all="skipping svn-info test (SVN version: $v not supported)" test_done ;; esac @@ -39,27 +39,30 @@ quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')" test_expect_success 'setup repository and import' ' mkdir info && - cd info && - echo FIRST > A && - echo one > file && + ( + cd info && + echo FIRST >A && + echo one >file && ln -s file symlink-file && mkdir directory && touch directory/.placeholder && ln -s directory symlink-directory && - svn_cmd import -m "initial" . "$svnrepo" && - cd .. && + svn_cmd import -m "initial" . "$svnrepo" + ) && svn_cmd co "$svnrepo" svnwc && - cd svnwc && - echo foo > foo && + ( + cd svnwc && + echo foo >foo && svn_cmd add foo && svn_cmd commit -m "change outside directory" && - svn_cmd update && - cd .. && + svn_cmd update + ) && mkdir gitwc && - cd gitwc && + ( + cd gitwc && git svn init "$svnrepo" && - git svn fetch && - cd .. && + git svn fetch + ) && ptouch gitwc/file svnwc/file && ptouch gitwc/directory svnwc/directory && ptouch gitwc/symlink-file svnwc/symlink-file && @@ -138,14 +141,16 @@ test_expect_success 'info --url symlink-directory' ' test_expect_success 'info added-file' " echo two > gitwc/added-file && - cd gitwc && - git add added-file && - cd .. && + ( + cd gitwc && + git add added-file + ) && cp gitwc/added-file svnwc/added-file && ptouch gitwc/added-file svnwc/added-file && - cd svnwc && - svn_cmd add added-file > /dev/null && - cd .. && + ( + cd svnwc && + svn_cmd add added-file > /dev/null + ) && (cd svnwc; svn info added-file) > expected.info-added-file && (cd gitwc; git svn info added-file) > actual.info-added-file && test_cmp expected.info-added-file actual.info-added-file @@ -160,12 +165,14 @@ test_expect_success 'info added-directory' " mkdir gitwc/added-directory svnwc/added-directory && ptouch gitwc/added-directory svnwc/added-directory && touch gitwc/added-directory/.placeholder && - cd svnwc && - svn_cmd add added-directory > /dev/null && - cd .. && - cd gitwc && - git add added-directory && - cd .. && + ( + cd svnwc && + svn_cmd add added-directory > /dev/null + ) && + ( + cd gitwc && + git add added-directory + ) && (cd svnwc; svn info added-directory) \ > expected.info-added-directory && (cd gitwc; git svn info added-directory) \ @@ -179,14 +186,16 @@ test_expect_success 'info --url added-directory' ' ' test_expect_success 'info added-symlink-file' " - cd gitwc && + ( + cd gitwc && ln -s added-file added-symlink-file && - git add added-symlink-file && - cd .. && - cd svnwc && + git add added-symlink-file + ) && + ( + cd svnwc && ln -s added-file added-symlink-file && - svn_cmd add added-symlink-file > /dev/null && - cd .. && + svn_cmd add added-symlink-file > /dev/null + ) && ptouch gitwc/added-symlink-file svnwc/added-symlink-file && (cd svnwc; svn info added-symlink-file) \ > expected.info-added-symlink-file && @@ -202,14 +211,16 @@ test_expect_success 'info --url added-symlink-file' ' ' test_expect_success 'info added-symlink-directory' " - cd gitwc && + ( + cd gitwc && ln -s added-directory added-symlink-directory && - git add added-symlink-directory && - cd .. && - cd svnwc && + git add added-symlink-directory + ) && + ( + cd svnwc && ln -s added-directory added-symlink-directory && - svn_cmd add added-symlink-directory > /dev/null && - cd .. && + svn_cmd add added-symlink-directory > /dev/null + ) && ptouch gitwc/added-symlink-directory svnwc/added-symlink-directory && (cd svnwc; svn info added-symlink-directory) \ > expected.info-added-symlink-directory && @@ -230,12 +241,14 @@ test_expect_success 'info --url added-symlink-directory' ' # simply reuses the Last Changed Date. test_expect_success 'info deleted-file' " - cd gitwc && - git rm -f file > /dev/null && - cd .. && - cd svnwc && - svn_cmd rm --force file > /dev/null && - cd .. && + ( + cd gitwc && + git rm -f file > /dev/null + ) && + ( + cd svnwc && + svn_cmd rm --force file > /dev/null + ) && (cd svnwc; svn info file) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > expected.info-deleted-file && @@ -251,12 +264,14 @@ test_expect_success 'info --url file (deleted)' ' ' test_expect_success 'info deleted-directory' " - cd gitwc && - git rm -r -f directory > /dev/null && - cd .. && - cd svnwc && - svn_cmd rm --force directory > /dev/null && - cd .. && + ( + cd gitwc && + git rm -r -f directory > /dev/null + ) && + ( + cd svnwc && + svn_cmd rm --force directory > /dev/null + ) && (cd svnwc; svn info directory) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > expected.info-deleted-directory && @@ -272,12 +287,14 @@ test_expect_success 'info --url directory (deleted)' ' ' test_expect_success 'info deleted-symlink-file' " - cd gitwc && - git rm -f symlink-file > /dev/null && - cd .. && - cd svnwc && - svn_cmd rm --force symlink-file > /dev/null && - cd .. && + ( + cd gitwc && + git rm -f symlink-file > /dev/null + ) && + ( + cd svnwc && + svn_cmd rm --force symlink-file > /dev/null + ) && (cd svnwc; svn info symlink-file) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > expected.info-deleted-symlink-file && @@ -294,12 +311,14 @@ test_expect_success 'info --url symlink-file (deleted)' ' ' test_expect_success 'info deleted-symlink-directory' " - cd gitwc && - git rm -f symlink-directory > /dev/null && - cd .. && - cd svnwc && - svn_cmd rm --force symlink-directory > /dev/null && - cd .. && + ( + cd gitwc && + git rm -f symlink-directory > /dev/null + ) && + ( + cd svnwc && + svn_cmd rm --force symlink-directory > /dev/null + ) && (cd svnwc; svn info symlink-directory) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > expected.info-deleted-symlink-directory && @@ -346,9 +365,10 @@ test_expect_success 'info --url unknown-directory' ' ' test_expect_success 'info unknown-symlink-file' " - cd gitwc && - ln -s unknown-file unknown-symlink-file && - cd .. && + ( + cd gitwc && + ln -s unknown-file unknown-symlink-file + ) && (cd gitwc; test_must_fail git svn info unknown-symlink-file) \ 2> actual.info-unknown-symlink-file && grep unknown-symlink-file actual.info-unknown-symlink-file @@ -361,9 +381,10 @@ test_expect_success 'info --url unknown-symlink-file' ' ' test_expect_success 'info unknown-symlink-directory' " - cd gitwc && - ln -s unknown-directory unknown-symlink-directory && - cd .. && + ( + cd gitwc && + ln -s unknown-directory unknown-symlink-directory + ) && (cd gitwc; test_must_fail git svn info unknown-symlink-directory) \ 2> actual.info-unknown-symlink-directory && grep unknown-symlink-directory actual.info-unknown-symlink-directory diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh index 9d9ebd533c..1d92c05035 100755 --- a/t/t9120-git-svn-clone-with-percent-escapes.sh +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -20,9 +20,10 @@ test_expect_success 'setup svnrepo' ' test_expect_success 'test clone with percent escapes' ' git svn clone "$svnrepo/pr%20ject" clone && - cd clone && - git rev-parse refs/${remotes_git_svn} && - cd .. + ( + cd clone && + git rev-parse refs/${remotes_git_svn} + ) ' # SVN works either way, so should we... diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh index 045521615c..0ed90d982d 100755 --- a/t/t9123-git-svn-rebuild-with-rewriteroot.sh +++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh @@ -8,10 +8,10 @@ test_description='git svn respects rewriteRoot during rebuild' . ./lib-git-svn.sh mkdir import -cd import +(cd import touch foo svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null -cd .. +) rm -rf import test_expect_success 'init, fetch and checkout repository' ' diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh index c19418614f..096abd1fe5 100755 --- a/t/t9125-git-svn-multi-glob-branch-names.sh +++ b/t/t9125-git-svn-multi-glob-branch-names.sh @@ -19,19 +19,19 @@ test_expect_success 'setup svnrepo' ' test_expect_success 'test clone with multi-glob in branch names' ' git svn clone -T trunk -b branches/*/* -t tags \ "$svnrepo/project" project && - cd project && + (cd project && git rev-parse "refs/remotes/v14.1/beta" && - git rev-parse "refs/remotes/v14.1/gold" && - cd .. + git rev-parse "refs/remotes/v14.1/gold" + ) ' test_expect_success 'test dcommit to multi-globbed branch' " - cd project && + (cd project && git reset --hard 'refs/remotes/v14.1/gold' && echo hello >> foo && git commit -m 'hello' -- foo && - git svn dcommit && - cd .. + git svn dcommit + ) " test_done diff --git a/t/t9127-git-svn-partial-rebuild.sh b/t/t9127-git-svn-partial-rebuild.sh index 4aab8ecc14..2e4789d061 100755 --- a/t/t9127-git-svn-partial-rebuild.sh +++ b/t/t9127-git-svn-partial-rebuild.sh @@ -9,27 +9,27 @@ test_description='git svn partial-rebuild tests' test_expect_success 'initialize svnrepo' ' mkdir import && ( - cd import && + (cd import && mkdir trunk branches tags && - cd trunk && - echo foo > foo && - cd .. && + (cd trunk && + echo foo > foo + ) && svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null && svn_cmd copy "$svnrepo"/trunk "$svnrepo"/branches/a \ - -m "created branch a" && - cd .. && + -m "created branch a" + ) && rm -rf import && svn_cmd co "$svnrepo"/trunk trunk && - cd trunk && + (cd trunk && echo bar >> foo && - svn_cmd ci -m "updated trunk" && - cd .. && + svn_cmd ci -m "updated trunk" + ) && svn_cmd co "$svnrepo"/branches/a a && - cd a && + (cd a && echo baz >> a && svn_cmd add a && - svn_cmd ci -m "updated a" && - cd .. && + svn_cmd ci -m "updated a" + ) && git svn init --stdlayout "$svnrepo" ) ' @@ -41,11 +41,11 @@ test_expect_success 'import an early SVN revision into git' ' test_expect_success 'make full git mirror of SVN' ' mkdir mirror && ( - cd mirror && + (cd mirror && git init && git svn init --stdlayout "$svnrepo" && - git svn fetch && - cd .. + git svn fetch + ) ) ' diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh index 807e494a3a..4b034a67f3 100755 --- a/t/t9128-git-svn-cmd-branch.sh +++ b/t/t9128-git-svn-cmd-branch.sh @@ -9,19 +9,19 @@ test_description='git svn partial-rebuild tests' test_expect_success 'initialize svnrepo' ' mkdir import && ( - cd import && + (cd import && mkdir trunk branches tags && - cd trunk && - echo foo > foo && - cd .. && - svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null && - cd .. && + (cd trunk && + echo foo > foo + ) && + svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null + ) && rm -rf import && svn_cmd co "$svnrepo"/trunk trunk && - cd trunk && + (cd trunk && echo bar >> foo && - svn_cmd ci -m "updated trunk" && - cd .. && + svn_cmd ci -m "updated trunk" + ) && rm -rf trunk ) ' diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh index b9224bdb20..8cfdfe790f 100755 --- a/t/t9129-git-svn-i18n-commitencoding.sh +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -14,10 +14,22 @@ compare_git_head_with () { test_cmp current "$1" } +a_utf8_locale=$(locale -a | sed -n '/\.[uU][tT][fF]-*8$/{ + p + q +}') + +if test -n "$a_utf8_locale" +then + test_set_prereq UTF8 +else + say "# UTF-8 locale not available, some tests are skipped" +fi + compare_svn_head_with () { # extract just the log message and strip out committer info. # don't use --limit here since svn 1.1.x doesn't have it, - LC_ALL=en_US.UTF-8 svn log `git svn info --url` | perl -w -e ' + LC_ALL="$a_utf8_locale" svn log `git svn info --url` | perl -w -e ' use bytes; $/ = ("-"x72) . "\n"; my @x = <STDIN>; @@ -69,12 +81,6 @@ do ' done -if locale -a |grep -q en_US.utf8; then - test_set_prereq UTF8 -else - say "UTF-8 locale not available, test skipped" -fi - test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' ' ( cd ISO8859-1 && diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh index 134411e0a5..ec0a106614 100755 --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@ -20,7 +20,7 @@ test_expect_success 'setup svnrepo' ' ' test_expect_success 'start import with incomplete authors file' ' - ! git svn clone --authors-file=svn-authors "$svnrepo" x + test_must_fail git svn clone --authors-file=svn-authors "$svnrepo" x ' test_expect_success 'imported 2 revisions successfully' ' @@ -63,7 +63,7 @@ test_expect_success 'authors-file against globs' ' ' test_expect_success 'fetch fails on ee' ' - ( cd aa-work && ! git svn fetch --authors-file=../svn-authors ) + ( cd aa-work && test_must_fail git svn fetch --authors-file=../svn-authors ) ' tmp_config_get () { @@ -95,8 +95,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' ' ( rm -r "$GIT_DIR" && test x = x"$(git config svn.authorsfile)" && - HOME="`pwd`" && - export HOME && test_config="$HOME"/.gitconfig && unset GIT_CONFIG_NOGLOBAL && unset GIT_DIR && diff --git a/t/t9131-git-svn-empty-symlink.sh b/t/t9131-git-svn-empty-symlink.sh index 9a24a65b64..f762038f0e 100755 --- a/t/t9131-git-svn-empty-symlink.sh +++ b/t/t9131-git-svn-empty-symlink.sh @@ -88,7 +88,7 @@ test_expect_success 'enable broken symlink workaround' \ test_expect_success '"bar" is an empty file' 'test -f x/bar && ! test -s x/bar' test_expect_success 'get "bar" => symlink fix from svn' \ '(cd x && git svn rebase)' -test_expect_success SYMLINKS '"bar" becomes a symlink' 'test -L x/bar' +test_expect_success SYMLINKS '"bar" becomes a symlink' 'test -h x/bar' test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" y' diff --git a/t/t9137-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh index 636ca0abb9..d60da63f7a 100755 --- a/t/t9137-git-svn-dcommit-clobber-series.sh +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -6,10 +6,10 @@ test_description='git svn dcommit clobber series' test_expect_success 'initialize repo' ' mkdir import && - cd import && + (cd import && awk "BEGIN { for (i = 1; i < 64; i++) { print i } }" > file - svn_cmd import -m "initial" . "$svnrepo" && - cd .. && + svn_cmd import -m "initial" . "$svnrepo" + ) && git svn init "$svnrepo" && git svn fetch && test -e file @@ -19,14 +19,14 @@ test_expect_success '(supposedly) non-conflicting change from SVN' ' test x"`sed -n -e 58p < file`" = x58 && test x"`sed -n -e 61p < file`" = x61 && svn_cmd co "$svnrepo" tmp && - cd tmp && + (cd tmp && perl -i.bak -p -e "s/^58$/5588/" file && perl -i.bak -p -e "s/^61$/6611/" file && poke file && test x"`sed -n -e 58p < file`" = x5588 && test x"`sed -n -e 61p < file`" = x6611 && - svn_cmd commit -m "58 => 5588, 61 => 6611" && - cd .. + svn_cmd commit -m "58 => 5588, 61 => 6611" + ) ' test_expect_success 'some unrelated changes to git' " diff --git a/t/t9139-git-svn-non-utf8-commitencoding.sh b/t/t9139-git-svn-non-utf8-commitencoding.sh index f337959ccc..22d80b0be2 100755 --- a/t/t9139-git-svn-non-utf8-commitencoding.sh +++ b/t/t9139-git-svn-non-utf8-commitencoding.sh @@ -39,7 +39,7 @@ do ( cd $H && git config --unset i18n.commitencoding && - ! git svn dcommit + test_must_fail git svn dcommit ) ' done diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh index 0735526d4b..e855904629 100755 --- a/t/t9140-git-svn-reset.sh +++ b/t/t9140-git-svn-reset.sh @@ -41,7 +41,7 @@ test_expect_success 'modify hidden file in SVN repo' ' test_expect_success 'fetch fails on modified hidden file' ' ( cd g && git svn find-rev refs/remotes/git-svn > ../expect && - ! git svn fetch 2> ../errors && + test_must_fail git svn fetch 2> ../errors && git svn find-rev refs/remotes/git-svn > ../expect2 ) && fgrep "not found in commit" errors && test_cmp expect expect2 diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh index 99f69c6a0b..337ea59711 100755 --- a/t/t9143-git-svn-gc.sh +++ b/t/t9143-git-svn-gc.sh @@ -43,7 +43,7 @@ then gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz ' else - say "Perl Compress::Zlib unavailable, skipping gunzip test" + say "# Perl Compress::Zlib unavailable, skipping gunzip test" fi test_expect_success 'git svn gc does not change unhandled.log files' ' diff --git a/t/t9155-git-svn-fetch-deleted-tag.sh b/t/t9155-git-svn-fetch-deleted-tag.sh new file mode 100755 index 0000000000..a486a98f84 --- /dev/null +++ b/t/t9155-git-svn-fetch-deleted-tag.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='git svn fetch deleted tag' + +. ./lib-git-svn.sh + +test_expect_success 'setup svn repo' ' + mkdir -p import/trunk/subdir && + mkdir -p import/branches && + mkdir -p import/tags && + echo "base" >import/trunk/subdir/file && + svn_cmd import -m "import for git svn" import "$svnrepo" && + rm -rf import && + + svn_cmd mkdir -m "create mybranch directory" "$svnrepo/branches/mybranch" && + svn_cmd cp -m "create branch mybranch" "$svnrepo/trunk" "$svnrepo/branches/mybranch/trunk" && + + svn_cmd co "$svnrepo/trunk" svn_project && + (cd svn_project && + echo "trunk change" >>subdir/file && + svn_cmd ci -m "trunk change" subdir/file && + + svn_cmd switch "$svnrepo/branches/mybranch/trunk" && + echo "branch change" >>subdir/file && + svn_cmd ci -m "branch change" subdir/file + ) && + + svn_cmd cp -m "create mytag attempt 1" -r5 "$svnrepo/trunk/subdir" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag attempt 1" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag attempt 2" -r5 "$svnrepo/branches/mybranch/trunk/subdir" "$svnrepo/tags/mytag" +' + +test_expect_success 'fetch deleted tags from same revision with checksum error' ' + git svn init --stdlayout "$svnrepo" git_project && + cd git_project && + git svn fetch && + + git diff --exit-code mybranch:trunk/subdir/file tags/mytag:file && + git diff --exit-code master:subdir/file tags/mytag^:file +' + +test_done diff --git a/t/t9156-git-svn-fetch-deleted-tag-2.sh b/t/t9156-git-svn-fetch-deleted-tag-2.sh new file mode 100755 index 0000000000..5ce7e2f3b0 --- /dev/null +++ b/t/t9156-git-svn-fetch-deleted-tag-2.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='git svn fetch deleted tag 2' + +. ./lib-git-svn.sh + +test_expect_success 'setup svn repo' ' + mkdir -p import/branches && + mkdir -p import/tags && + mkdir -p import/trunk/subdir1 && + mkdir -p import/trunk/subdir2 && + mkdir -p import/trunk/subdir3 && + echo "file1" >import/trunk/subdir1/file && + echo "file2" >import/trunk/subdir2/file && + echo "file3" >import/trunk/subdir3/file && + svn_cmd import -m "import for git svn" import "$svnrepo" && + rm -rf import && + + svn_cmd co "$svnrepo/trunk" svn_project && + (cd svn_project && + echo "change1" >>subdir1/file && + echo "change2" >>subdir2/file && + echo "change3" >>subdir3/file && + svn_cmd ci -m "change" . + ) && + + svn_cmd cp -m "create mytag 1" -r2 "$svnrepo/trunk/subdir1" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag 1" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag 2" -r2 "$svnrepo/trunk/subdir2" "$svnrepo/tags/mytag" && + svn_cmd rm -m "delete mytag 2" "$svnrepo/tags/mytag" && + svn_cmd cp -m "create mytag 3" -r2 "$svnrepo/trunk/subdir3" "$svnrepo/tags/mytag" +' + +test_expect_success 'fetch deleted tags from same revision with no checksum error' ' + git svn init --stdlayout "$svnrepo" git_project && + cd git_project && + git svn fetch && + + git diff --exit-code master:subdir3/file tags/mytag:file && + git diff --exit-code master:subdir2/file tags/mytag^:file && + git diff --exit-code master:subdir1/file tags/mytag^^:file +' + +test_done diff --git a/t/t9157-git-svn-fetch-merge.sh b/t/t9157-git-svn-fetch-merge.sh new file mode 100755 index 0000000000..da582c5382 --- /dev/null +++ b/t/t9157-git-svn-fetch-merge.sh @@ -0,0 +1,50 @@ +#!/bin/sh +# +# Copyright (c) 2010 Steven Walter +# + +test_description='git svn merge detection' +. ./lib-git-svn.sh + +test_expect_success 'initialize source svn repo' ' + svn_cmd mkdir -m x "$svnrepo"/trunk && + svn_cmd mkdir -m x "$svnrepo"/branches && + svn_cmd co "$svnrepo"/trunk "$SVN_TREE" && + ( + cd "$SVN_TREE" && + touch foo && + svn add foo && + svn commit -m "initial commit" && + svn cp -m branch "$svnrepo"/trunk "$svnrepo"/branches/branch1 && + touch bar && + svn add bar && + svn commit -m x && + svn cp -m branch "$svnrepo"/trunk "$svnrepo"/branches/branch2 && + svn switch "$svnrepo"/branches/branch1 && + touch baz && + svn add baz && + svn commit -m x && + svn switch "$svnrepo"/trunk && + svn merge "$svnrepo"/branches/branch1 && + svn commit -m "merge" && + svn switch "$svnrepo"/branches/branch1 && + svn commit -m x && + svn switch "$svnrepo"/branches/branch2 && + svn merge "$svnrepo"/branches/branch1 && + svn commit -m "merge branch1" && + svn switch "$svnrepo"/trunk && + svn merge "$svnrepo"/branches/branch2 && + svn resolved baz && + svn commit -m "merge branch2" + ) && + rm -rf "$SVN_TREE" +' + +test_expect_success 'clone svn repo' ' + git svn init -s "$svnrepo" && + git svn fetch +' + +test_expect_success 'verify merge commit' 'git rev-parse HEAD^2' + +test_done diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index fc3795dc98..e5da65b99f 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -5,16 +5,17 @@ test_description='Test export of commits to CVS' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh if ! test_have_prereq PERL; then - say 'skipping git cvsexportcommit tests, perl not available' + skip_all='skipping git cvsexportcommit tests, perl not available' test_done fi cvs >/dev/null 2>&1 if test $? -ne 1 then - say 'skipping git cvsexportcommit tests, cvs not found' + skip_all='skipping git cvsexportcommit tests, cvs not found' test_done fi @@ -63,10 +64,10 @@ test_expect_success \ check_entries B "newfile2.txt/1.1/" && check_entries C "newfile3.png/1.1/-kb" && check_entries D "newfile4.png/1.1/-kb" && - diff A/newfile1.txt ../A/newfile1.txt && - diff B/newfile2.txt ../B/newfile2.txt && - diff C/newfile3.png ../C/newfile3.png && - diff D/newfile4.png ../D/newfile4.png + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp B/newfile2.txt ../B/newfile2.txt && + test_cmp C/newfile3.png ../C/newfile3.png && + test_cmp D/newfile4.png ../D/newfile4.png )' test_expect_success \ @@ -89,10 +90,10 @@ test_expect_success \ check_entries D "newfile4.png/1.2/-kb" && check_entries E "newfile5.txt/1.1/" && check_entries F "newfile6.png/1.1/-kb" && - diff A/newfile1.txt ../A/newfile1.txt && - diff D/newfile4.png ../D/newfile4.png && - diff E/newfile5.txt ../E/newfile5.txt && - diff F/newfile6.png ../F/newfile6.png + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp D/newfile4.png ../D/newfile4.png && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png )' # Should fail (but only on the git cvsexportcommit stage) @@ -137,9 +138,9 @@ test_expect_success \ check_entries D "" && check_entries E "newfile5.txt/1.1/" && check_entries F "newfile6.png/1.1/-kb" && - diff A/newfile1.txt ../A/newfile1.txt && - diff E/newfile5.txt ../E/newfile5.txt && - diff F/newfile6.png ../F/newfile6.png + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png )' test_expect_success \ @@ -155,8 +156,8 @@ test_expect_success \ check_entries D "" && check_entries E "newfile5.txt/1.1/" && check_entries F "newfile6.png/1.1/-kb" && - diff E/newfile5.txt ../E/newfile5.txt && - diff F/newfile6.png ../F/newfile6.png + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png )' test_expect_success \ @@ -229,11 +230,6 @@ test_expect_success \ test_must_fail git cvsexportcommit -c $id )' -if ! test "$(git config --bool core.filemode)" = false -then - test_set_prereq FILEMODE -fi - test_expect_success FILEMODE \ 'Retain execute bit' \ 'mkdir G && diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 131f032988..3c0cf0509d 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -166,6 +166,63 @@ test_expect_success \ test `git rev-parse --verify master:file2` \ = `git rev-parse --verify verify--import-marks:copy-of-file2`' +test_tick +mt=$(git hash-object --stdin < /dev/null) +: >input.blob +: >marks.exp +: >tree.exp + +cat >input.commit <<EOF +commit refs/heads/verify--dump-marks +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +test the sparse array dumping routines with exponentially growing marks +COMMIT +EOF + +i=0 +l=4 +m=6 +n=7 +while test "$i" -lt 27; do + cat >>input.blob <<EOF +blob +mark :$l +data 0 +blob +mark :$m +data 0 +blob +mark :$n +data 0 +EOF + echo "M 100644 :$l l$i" >>input.commit + echo "M 100644 :$m m$i" >>input.commit + echo "M 100644 :$n n$i" >>input.commit + + echo ":$l $mt" >>marks.exp + echo ":$m $mt" >>marks.exp + echo ":$n $mt" >>marks.exp + + printf "100644 blob $mt\tl$i\n" >>tree.exp + printf "100644 blob $mt\tm$i\n" >>tree.exp + printf "100644 blob $mt\tn$i\n" >>tree.exp + + l=$(($l + $l)) + m=$(($m + $m)) + n=$(($l + $n)) + + i=$((1 + $i)) +done + +sort tree.exp > tree.exp_s + +test_expect_success 'A: export marks with large values' ' + cat input.blob input.commit | git fast-import --export-marks=marks.large && + git ls-tree refs/heads/verify--dump-marks >tree.out && + test_cmp tree.exp_s tree.out && + test_cmp marks.exp marks.large' + ### ### series B ### @@ -796,6 +853,81 @@ test_expect_success \ 'git fast-import <input && test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`' +test_expect_success \ + 'N: copy directory by id' \ + 'cat >expect <<-\EOF && + :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf + :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf + EOF + subdir=$(git rev-parse refs/heads/branch^0:file2) && + cat >input <<-INPUT_END && + commit refs/heads/N4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy by tree hash + COMMIT + + from refs/heads/branch^0 + M 040000 $subdir file3 + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N4^ N4 >actual && + compare_diff_raw expect actual' + +test_expect_success \ + 'N: copy root directory by tree hash' \ + 'cat >expect <<-\EOF && + :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file3/newf + :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file3/oldf + EOF + root=$(git rev-parse refs/heads/branch^0^{tree}) && + cat >input <<-INPUT_END && + commit refs/heads/N6 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy root directory by tree hash + COMMIT + + from refs/heads/branch^0 + M 040000 $root "" + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N4 N6 >actual && + compare_diff_raw expect actual' + +test_expect_success \ + 'N: modify copied tree' \ + 'cat >expect <<-\EOF && + :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100 newdir/interesting file3/file5 + :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file3/newf + :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100 file2/oldf file3/oldf + EOF + subdir=$(git rev-parse refs/heads/branch^0:file2) && + cat >input <<-INPUT_END && + commit refs/heads/N5 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy by tree hash + COMMIT + + from refs/heads/branch^0 + M 040000 $subdir file3 + + commit refs/heads/N5 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + modify directory copy + COMMIT + + M 644 inline file3/file5 + data <<EOF + $file5_data + EOF + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N5^^ N5 >actual && + compare_diff_raw expect actual' + ### ### series O ### @@ -999,11 +1131,10 @@ test_expect_success \ 'P: supermodule & submodule mix' \ 'git fast-import <input && git checkout subuse1 && - rm -rf sub && mkdir sub && cd sub && + rm -rf sub && mkdir sub && (cd sub && git init && git fetch --update-head-ok .. refs/heads/sub:refs/heads/master && - git checkout master && - cd .. && + git checkout master) && git submodule init && git submodule update' diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index d43f37ccaf..8c8e679468 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -355,6 +355,20 @@ test_expect_failure 'no exact-ref revisions included' ' ) ' +test_expect_success 'path limiting with import-marks does not lose unmodified files' ' + git checkout -b simple marks~2 && + git fast-export --export-marks=marks simple -- file > /dev/null && + echo more content >> file && + test_tick && + git commit -mnext file && + git fast-export --import-marks=marks simple -- file file0 | grep file0 +' + +test_expect_success 'full-tree re-shows unmodified files' ' + git checkout -f simple && + test $(git fast-export --full-tree simple | grep -c file0) -eq 3 +' + test_expect_success 'set-up a few more tags for tag export tests' ' git checkout -f master && HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` && @@ -376,4 +390,28 @@ test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj' test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag' test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' +test_expect_success SYMLINKS 'directory becomes symlink' ' + git init dirtosymlink && + git init result && + ( + cd dirtosymlink && + mkdir foo && + mkdir bar && + echo hello > foo/world && + echo hello > bar/world && + git add foo/world bar/world && + git commit -q -mone && + git rm -r foo && + ln -s bar foo && + git add foo && + git commit -q -mtwo + ) && + ( + cd dirtosymlink && + git fast-export master -- foo | + (cd ../result && git fast-import --quiet) + ) && + (cd result && git show master:foo) +' + test_done diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index daef2d6c23..36c457e7f2 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -11,17 +11,17 @@ cvs CLI client via git-cvsserver server' . ./test-lib.sh if ! test_have_prereq PERL; then - say 'skipping git cvsserver tests, perl not available' + skip_all='skipping git cvsserver tests, perl not available' test_done fi cvs >/dev/null 2>&1 if test $? -ne 1 then - say 'skipping git-cvsserver tests, cvs not found' + skip_all='skipping git-cvsserver tests, cvs not found' test_done fi "$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { - say 'skipping git-cvsserver tests, Perl SQLite interface unavailable' + skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable' test_done } @@ -48,7 +48,9 @@ test_expect_success 'setup' ' git pull secondroot master && git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 && GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && - GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" + GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" && + GIT_DIR="$SERVERDIR" git config gitcvs.authdb "$SERVERDIR/auth.db" && + echo cvsuser:cvGVEarMLnhlA > "$SERVERDIR/auth.db" ' # note that cvs doesn't accept absolute pathnames @@ -94,6 +96,14 @@ git END VERIFICATION REQUEST EOF +cat >login-git-ok <<EOF +BEGIN VERIFICATION REQUEST +$SERVERDIR +cvsuser +Ah<Z:yZZ30 e +END VERIFICATION REQUEST +EOF + test_expect_success 'pserver authentication' \ 'cat request-anonymous | git-cvsserver pserver >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$"' @@ -107,6 +117,10 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \ fi && sed -ne \$p log | grep "^I HATE YOU\$"' +test_expect_success 'pserver authentication success (non-anonymous user with password)' \ + 'cat login-git-ok | git-cvsserver pserver >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + test_expect_success 'pserver authentication (login)' \ 'cat login-anonymous | git-cvsserver pserver >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$"' @@ -435,7 +449,7 @@ test_expect_success 'cvs update (-p)' ' rm -f failures && for i in merge no-lf empty really-empty; do GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out - diff $i.out ../$i >>failures 2>&1 + test_cmp $i.out ../$i >>failures 2>&1 done && test -z "$(cat failures)" ' diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh index ed7b513f3e..1bbfd824e5 100755 --- a/t/t9401-git-cvsserver-crlf.sh +++ b/t/t9401-git-cvsserver-crlf.sh @@ -41,16 +41,16 @@ not_present() { cvs >/dev/null 2>&1 if test $? -ne 1 then - say 'skipping git-cvsserver tests, cvs not found' + skip_all='skipping git-cvsserver tests, cvs not found' test_done fi if ! test_have_prereq PERL then - say 'skipping git-cvsserver tests, perl not available' + skip_all='skipping git-cvsserver tests, perl not available' test_done fi "$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { - say 'skipping git-cvsserver tests, Perl SQLite interface unavailable' + skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable' test_done } @@ -129,21 +129,22 @@ test_expect_success 'cvs co (use attributes)' ' ' test_expect_success 'adding files' ' - cd cvswork/subdir && + (cd cvswork && + (cd subdir && echo "more text" > src.c && GIT_CONFIG="$git_config" cvs -Q add src.c >cvs.log 2>&1 && marked_as . src.c "" && - echo "psuedo-binary" > temp.bin && - cd .. && + echo "psuedo-binary" > temp.bin + ) && GIT_CONFIG="$git_config" cvs -Q add subdir/temp.bin >cvs.log 2>&1 && marked_as subdir temp.bin "-kb" && cd subdir && GIT_CONFIG="$git_config" cvs -Q ci -m "adding files" >cvs.log 2>&1 && marked_as . temp.bin "-kb" && marked_as . src.c "" + ) ' -cd "$WORKDIR" test_expect_success 'updating' ' git pull gitcvs.git && echo 'hi' > subdir/newfile.bin && @@ -153,9 +154,9 @@ test_expect_success 'updating' ' git add subdir/newfile.bin subdir/file.h subdir/newfile.c binfile.bin && git commit -q -m "Add and change some files" && git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - cd .. && + (cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update + ) && marked_as cvswork textfile.c "" && marked_as cvswork binfile.bin -kb && marked_as cvswork .gitattributes "" && @@ -233,35 +234,35 @@ test_expect_success 'cvs co another copy (guess)' ' ' test_expect_success 'add text (guess)' ' - cd cvswork && + (cd cvswork && echo "simpleText" > simpleText.c && - GIT_CONFIG="$git_config" cvs -Q add simpleText.c && - cd .. && + GIT_CONFIG="$git_config" cvs -Q add simpleText.c + ) && marked_as cvswork simpleText.c "" ' test_expect_success 'add bin (guess)' ' - cd cvswork && + (cd cvswork && echo "simpleBin: NUL: Q <- there" | q_to_nul > simpleBin.bin && - GIT_CONFIG="$git_config" cvs -Q add simpleBin.bin && - cd .. && + GIT_CONFIG="$git_config" cvs -Q add simpleBin.bin + ) && marked_as cvswork simpleBin.bin -kb ' test_expect_success 'remove files (guess)' ' - cd cvswork && + (cd cvswork && GIT_CONFIG="$git_config" cvs -Q rm -f subdir/file.h && - cd subdir && - GIT_CONFIG="$git_config" cvs -Q rm -f withCr.bin && - cd ../.. && + (cd subdir && + GIT_CONFIG="$git_config" cvs -Q rm -f withCr.bin + )) && marked_as cvswork/subdir withCr.bin -kb && marked_as cvswork/subdir file.h "" ' test_expect_success 'cvs ci (guess)' ' - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q ci -m "add/rm files" >cvs.log 2>&1 && - cd .. && + (cd cvswork && + GIT_CONFIG="$git_config" cvs -Q ci -m "add/rm files" >cvs.log 2>&1 + ) && marked_as cvswork textfile.c "" && marked_as cvswork binfile.bin -kb && marked_as cvswork .gitattributes "" && @@ -278,9 +279,9 @@ test_expect_success 'cvs ci (guess)' ' ' test_expect_success 'update subdir of other copy (guess)' ' - cd cvswork2/subdir && - GIT_CONFIG="$git_config" cvs -Q update && - cd ../.. && + (cd cvswork2/subdir && + GIT_CONFIG="$git_config" cvs -Q update + ) && marked_as cvswork2 textfile.c "" && marked_as cvswork2 binfile.bin -kb && marked_as cvswork2 .gitattributes "" && @@ -304,11 +305,11 @@ test_expect_success 'update/merge full other copy (guess)' ' git add multilineTxt.c && git commit -q -m "modify multiline file" >> "${WORKDIR}/marked.log" && git push gitcvs.git >/dev/null && - cd cvswork2 && + (cd cvswork2 && sed "s/1/replaced_1/" < multilineTxt.c > ml.temp && mv ml.temp multilineTxt.c && - GIT_CONFIG="$git_config" cvs update > cvs.log 2>&1 && - cd .. && + GIT_CONFIG="$git_config" cvs update > cvs.log 2>&1 + ) && marked_as cvswork2 textfile.c "" && marked_as cvswork2 binfile.bin -kb && marked_as cvswork2 .gitattributes "" && diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 63b6b060e6..21cd286bb7 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -647,4 +647,34 @@ test_expect_success \ gitweb_run "p=.git;a=summary"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# syntax highlighting + + +highlight --version >/dev/null 2>&1 +if [ $? -eq 127 ]; then + say "Skipping syntax highlighting test, because 'highlight' was not found" +else + test_set_prereq HIGHLIGHT + cat >>gitweb_config.perl <<-\EOF + our $highlight_bin = "highlight"; + $feature{'highlight'}{'override'} = 1; + EOF +fi + +test_expect_success HIGHLIGHT \ + 'syntax highlighting (no highlight, unknown syntax)' \ + 'git config gitweb.highlight yes && + gitweb_run "p=.git;a=blob;f=file"' +test_debug 'cat gitweb.log' + +test_expect_success HIGHLIGHT \ + 'syntax highlighting (highlighted, shell script)' \ + 'git config gitweb.highlight yes && + echo "#!/usr/bin/sh" > test.sh && + git add test.sh && + git commit -m "Add test.sh" && + gitweb_run "p=.git;a=blob;f=test.sh"' +test_debug 'cat gitweb.log' + test_done diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh index b572ce3ab7..432b82e3d5 100755 --- a/t/t9600-cvsimport.sh +++ b/t/t9600-cvsimport.sh @@ -3,21 +3,18 @@ test_description='git cvsimport basic tests' . ./lib-cvs.sh -if ! test_have_prereq PERL; then - say 'skipping git cvsimport tests, perl not available' - test_done -fi - -CVSROOT=$(pwd)/cvsroot -export CVSROOT +test_expect_success PERL 'setup cvsroot environment' ' + CVSROOT=$(pwd)/cvsroot && + export CVSROOT +' -test_expect_success 'setup cvsroot' '$CVS init' +test_expect_success PERL 'setup cvsroot' '$CVS init' -test_expect_success 'setup a cvs module' ' +test_expect_success PERL 'setup a cvs module' ' mkdir "$CVSROOT/module" && $CVS co -d module-cvs module && - cd module-cvs && + (cd module-cvs && cat <<EOF >o_fortuna && O Fortuna velut luna @@ -41,29 +38,28 @@ add "O Fortuna" lyrics These public domain lyrics make an excellent sample text. EOF - $CVS commit -F message && - cd .. + $CVS commit -F message + ) ' -test_expect_success 'import a trivial module' ' +test_expect_success PERL 'import a trivial module' ' git cvsimport -a -R -z 0 -C module-git module && test_cmp module-cvs/o_fortuna module-git/o_fortuna ' -test_expect_success 'pack refs' 'cd module-git && git gc && cd ..' +test_expect_success PERL 'pack refs' '(cd module-git && git gc)' -test_expect_success 'initial import has correct .git/cvs-revisions' ' +test_expect_success PERL 'initial import has correct .git/cvs-revisions' ' (cd module-git && git log --format="o_fortuna 1.1 %H" -1) > expected && test_cmp expected module-git/.git/cvs-revisions ' -test_expect_success 'update cvs module' ' - - cd module-cvs && +test_expect_success PERL 'update cvs module' ' + (cd module-cvs && cat <<EOF >o_fortuna && O Fortune, like the moon @@ -86,21 +82,21 @@ translate to English My Latin is terrible. EOF - $CVS commit -F message && - cd .. + $CVS commit -F message + ) ' -test_expect_success 'update git module' ' +test_expect_success PERL 'update git module' ' - cd module-git && + (cd module-git && git cvsimport -a -R -z 0 module && - git merge origin && - cd .. && + git merge origin + ) && test_cmp module-cvs/o_fortuna module-git/o_fortuna ' -test_expect_success 'update has correct .git/cvs-revisions' ' +test_expect_success PERL 'update has correct .git/cvs-revisions' ' (cd module-git && git log --format="o_fortuna 1.1 %H" -1 HEAD^ && @@ -108,28 +104,27 @@ test_expect_success 'update has correct .git/cvs-revisions' ' test_cmp expected module-git/.git/cvs-revisions ' -test_expect_success 'update cvs module' ' +test_expect_success PERL 'update cvs module' ' - cd module-cvs && + (cd module-cvs && echo 1 >tick && $CVS add tick && $CVS commit -m 1 - cd .. - + ) ' -test_expect_success 'cvsimport.module config works' ' +test_expect_success PERL 'cvsimport.module config works' ' - cd module-git && + (cd module-git && git config cvsimport.module module && git cvsimport -a -R -z0 && - git merge origin && - cd .. && + git merge origin + ) && test_cmp module-cvs/tick module-git/tick ' -test_expect_success 'second update has correct .git/cvs-revisions' ' +test_expect_success PERL 'second update has correct .git/cvs-revisions' ' (cd module-git && git log --format="o_fortuna 1.1 %H" -1 HEAD^^ && @@ -138,24 +133,24 @@ test_expect_success 'second update has correct .git/cvs-revisions' ' test_cmp expected module-git/.git/cvs-revisions ' -test_expect_success 'import from a CVS working tree' ' +test_expect_success PERL 'import from a CVS working tree' ' $CVS co -d import-from-wt module && - cd import-from-wt && + (cd import-from-wt && git cvsimport -a -z0 && echo 1 >expect && git log -1 --pretty=format:%s%n >actual && - test_cmp actual expect && - cd .. + test_cmp actual expect + ) ' -test_expect_success 'no .git/cvs-revisions created by default' ' +test_expect_success PERL 'no .git/cvs-revisions created by default' ' ! test -e import-from-wt/.git/cvs-revisions ' -test_expect_success 'test entire HEAD' 'test_cmp_branch_tree master' +test_expect_success PERL 'test entire HEAD' 'test_cmp_branch_tree master' test_done diff --git a/t/t9601-cvsimport-vendor-branch.sh b/t/t9601-cvsimport-vendor-branch.sh index 3afaf56526..827d39f5bf 100755 --- a/t/t9601-cvsimport-vendor-branch.sh +++ b/t/t9601-cvsimport-vendor-branch.sh @@ -34,50 +34,49 @@ test_description='git cvsimport handling of vendor branches' . ./lib-cvs.sh -CVSROOT="$TEST_DIRECTORY"/t9601/cvsroot -export CVSROOT +setup_cvs_test_repository t9601 -test_expect_success 'import a module with a vendor branch' ' +test_expect_success PERL 'import a module with a vendor branch' ' git cvsimport -C module-git module ' -test_expect_success 'check HEAD out of cvs repository' 'test_cvs_co master' +test_expect_success PERL 'check HEAD out of cvs repository' 'test_cvs_co master' -test_expect_success 'check master out of git repository' 'test_git_co master' +test_expect_success PERL 'check master out of git repository' 'test_git_co master' -test_expect_success 'check a file that was imported once' ' +test_expect_success PERL 'check a file that was imported once' ' test_cmp_branch_file master imported-once.txt ' -test_expect_failure 'check a file that was imported twice' ' +test_expect_failure PERL 'check a file that was imported twice' ' test_cmp_branch_file master imported-twice.txt ' -test_expect_success 'check a file that was imported then modified on HEAD' ' +test_expect_success PERL 'check a file that was imported then modified on HEAD' ' test_cmp_branch_file master imported-modified.txt ' -test_expect_success 'check a file that was imported, modified, then imported again' ' +test_expect_success PERL 'check a file that was imported, modified, then imported again' ' test_cmp_branch_file master imported-modified-imported.txt ' -test_expect_success 'check a file that was added to HEAD then imported' ' +test_expect_success PERL 'check a file that was added to HEAD then imported' ' test_cmp_branch_file master added-imported.txt ' -test_expect_success 'a vendor branch whose tag has been removed' ' +test_expect_success PERL 'a vendor branch whose tag has been removed' ' test_cmp_branch_file master imported-anonymously.txt diff --git a/t/t9602-cvsimport-branches-tags.sh b/t/t9602-cvsimport-branches-tags.sh index 67878b2d0c..e1db323f54 100755 --- a/t/t9602-cvsimport-branches-tags.sh +++ b/t/t9602-cvsimport-branches-tags.sh @@ -6,70 +6,69 @@ test_description='git cvsimport handling of branches and tags' . ./lib-cvs.sh -CVSROOT="$TEST_DIRECTORY"/t9602/cvsroot -export CVSROOT +setup_cvs_test_repository t9602 -test_expect_success 'import module' ' +test_expect_success PERL 'import module' ' git cvsimport -C module-git module ' -test_expect_success 'test branch master' ' +test_expect_success PERL 'test branch master' ' test_cmp_branch_tree master ' -test_expect_success 'test branch vendorbranch' ' +test_expect_success PERL 'test branch vendorbranch' ' test_cmp_branch_tree vendorbranch ' -test_expect_failure 'test branch B_FROM_INITIALS' ' +test_expect_failure PERL 'test branch B_FROM_INITIALS' ' test_cmp_branch_tree B_FROM_INITIALS ' -test_expect_failure 'test branch B_FROM_INITIALS_BUT_ONE' ' +test_expect_failure PERL 'test branch B_FROM_INITIALS_BUT_ONE' ' test_cmp_branch_tree B_FROM_INITIALS_BUT_ONE ' -test_expect_failure 'test branch B_MIXED' ' +test_expect_failure PERL 'test branch B_MIXED' ' test_cmp_branch_tree B_MIXED ' -test_expect_success 'test branch B_SPLIT' ' +test_expect_success PERL 'test branch B_SPLIT' ' test_cmp_branch_tree B_SPLIT ' -test_expect_failure 'test tag vendortag' ' +test_expect_failure PERL 'test tag vendortag' ' test_cmp_branch_tree vendortag ' -test_expect_success 'test tag T_ALL_INITIAL_FILES' ' +test_expect_success PERL 'test tag T_ALL_INITIAL_FILES' ' test_cmp_branch_tree T_ALL_INITIAL_FILES ' -test_expect_failure 'test tag T_ALL_INITIAL_FILES_BUT_ONE' ' +test_expect_failure PERL 'test tag T_ALL_INITIAL_FILES_BUT_ONE' ' test_cmp_branch_tree T_ALL_INITIAL_FILES_BUT_ONE ' -test_expect_failure 'test tag T_MIXED' ' +test_expect_failure PERL 'test tag T_MIXED' ' test_cmp_branch_tree T_MIXED diff --git a/t/t9603-cvsimport-patchsets.sh b/t/t9603-cvsimport-patchsets.sh index 958bdce4dd..52034c8f77 100755 --- a/t/t9603-cvsimport-patchsets.sh +++ b/t/t9603-cvsimport-patchsets.sh @@ -14,18 +14,17 @@ test_description='git cvsimport testing for correct patchset estimation' . ./lib-cvs.sh -CVSROOT="$TEST_DIRECTORY"/t9603/cvsroot -export CVSROOT +setup_cvs_test_repository t9603 test_expect_failure 'import with criss cross times on revisions' ' git cvsimport -p"-x" -C module-git module && - cd module-git && + (cd module-git && git log --pretty=format:%s > ../actual-master && git log A~2..A --pretty="format:%s %ad" -- > ../actual-A && echo "" >> ../actual-master && - echo "" >> ../actual-A && - cd .. && + echo "" >> ../actual-A + ) && echo "Rev 4 Rev 3 Rev 2 diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh index 8686086dde..3787186703 100755 --- a/t/t9700-perl-git.sh +++ b/t/t9700-perl-git.sh @@ -7,12 +7,12 @@ test_description='perl interface (Git.pm)' . ./test-lib.sh if ! test_have_prereq PERL; then - say 'skipping perl interface tests, perl not available' + skip_all='skipping perl interface tests, perl not available' test_done fi "$PERL_PATH" -MTest::More -e 0 2>/dev/null || { - say "Perl Test::More unavailable, skipping test" + skip_all="Perl Test::More unavailable, skipping test" test_done } @@ -46,6 +46,9 @@ test_expect_success \ git config --add test.int 2k ' +# The external test will outputs its own plan +test_external_has_tap=1 + test_external_without_stderr \ 'Perl API' \ "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl diff --git a/t/t9700/test.pl b/t/t9700/test.pl index 666722d9bf..c15ca2d647 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -1,12 +1,19 @@ #!/usr/bin/perl use lib (split(/:/, $ENV{GITPERLLIB})); -use 5.006002; +use 5.008; use warnings; use strict; use Test::More qw(no_plan); +BEGIN { + # t9700-perl-git.sh kicks off our testing, so we have to go from + # there. + Test::More->builder->current_test(1); + Test::More->builder->no_ending(1); +} + use Cwd; use File::Basename; @@ -105,3 +112,8 @@ my $last_commit = $r2->command_oneline(qw(rev-parse --verify HEAD)); like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash'); my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.'); isnt($last_commit, $dir_commit, 'log . does not show last commit'); + +printf "1..%d\n", Test::More->builder->current_test; + +my $is_passing = eval { Test::More->is_passing }; +exit($is_passing ? 0 : 1) unless $@ =~ /Can't locate object method/; diff --git a/t/test-lib.sh b/t/test-lib.sh index c582964b0d..2af8f10c83 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -2,6 +2,18 @@ # # 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/ . # if --tee was passed, write the output not only to the terminal, but # additionally to the file test-results/$BASENAME.out, too. @@ -63,7 +75,6 @@ export GIT_MERGE_VERBOSITY export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export EDITOR -GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u} # Protect ourselves from common misconfiguration to export # CDPATH into the environment @@ -116,14 +127,13 @@ do -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; -q|--q|--qu|--qui|--quie|--quiet) - quiet=t; shift ;; + # Ignore --quiet under a TAP::Harness. Saying how many tests + # passed without the ok/not ok details is always an error. + test -z "$HARNESS_ACTIVE" && quiet=t; shift ;; --with-dashes) with_dashes=t; shift ;; --no-color) color=; shift ;; - --no-python) - # noop now... - shift ;; --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) valgrind=t; verbose=t; shift ;; --tee) @@ -149,7 +159,7 @@ if test -n "$color"; then *) test -n "$quiet" && return;; esac shift - printf "* %s" "$*" + printf "%s" "$*" tput sgr0 echo ) @@ -158,7 +168,7 @@ else say_color() { test -z "$1" && test -n "$quiet" && return shift - echo "* $*" + echo "$*" } fi @@ -195,6 +205,8 @@ test_fixed=0 test_broken=0 test_success=0 +test_external_has_tap=0 + die () { code=$? if test -n "$GIT_EXIT_OK" @@ -244,6 +256,10 @@ q_to_cr () { tr Q '\015' } +q_to_tab () { + tr Q '\011' +} + append_cr () { sed -e 's/$/Q/' | tr Q '\015' } @@ -315,12 +331,35 @@ test_set_prereq () { satisfied=" " test_have_prereq () { - case $satisfied in - *" $1 "*) - : yes, have it ;; - *) - ! : nope ;; - esac + # 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 } # You are not expected to call test_ok_ and test_failure_ directly, use @@ -328,25 +367,25 @@ test_have_prereq () { test_ok_ () { test_success=$(($test_success + 1)) - say_color "" " ok $test_count: $@" + say_color "" "ok $test_count - $@" } test_failure_ () { test_failure=$(($test_failure + 1)) - say_color error "FAIL $test_count: $1" + say_color error "not ok - $test_count $1" shift - echo "$@" | sed -e 's/^/ /' + echo "$@" | sed -e 's/^/# /' test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; } } test_known_broken_ok_ () { test_fixed=$(($test_fixed+1)) - say_color "" " FIXED $test_count: $@" + say_color "" "ok $test_count - $@ # TODO known breakage" } test_known_broken_failure_ () { test_broken=$(($test_broken+1)) - say_color skip " still broken $test_count: $@" + say_color skip "not ok $test_count - $@ # TODO known breakage" } test_debug () { @@ -354,8 +393,13 @@ test_debug () { } test_run_ () { + test_cleanup=: eval >&3 2>&4 "$1" - eval_ret="$?" + eval_ret=$? + eval >&3 2>&4 "$test_cleanup" + if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then + echo "" + fi return 0 } @@ -367,6 +411,7 @@ test_skip () { case $this_test.$test_count in $skp) to_skip=t + break esac done if test -z "$to_skip" && test -n "$prereq" && @@ -376,8 +421,14 @@ test_skip () { fi case "$to_skip" in t) + of_prereq= + if test "$missing_prereq" != "$prereq" + then + of_prereq=" of $prereq" + fi + say_color skip >&3 "skipping test: $@" - say_color skip "skip $test_count: $1" + say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})" : true ;; *) @@ -443,7 +494,7 @@ test_expect_code () { # 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 +# 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... @@ -458,16 +509,29 @@ test_external () { then # Announce the script to reduce confusion about the # test output that follows. - say_color "" " run $test_count: $descr ($*)" + 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 - test_ok_ "$descr" + 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 - test_failure_ "$descr" "$@" + 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 } @@ -483,22 +547,65 @@ test_external_without_stderr () { [ -f "$stderr" ] || error "Internal error: $stderr disappeared." descr="no stderr: $1" shift - say >&3 "expecting no stderr from previous command" + say >&3 "# expecting no stderr from previous command" if [ ! -s "$stderr" ]; then rm "$stderr" - test_ok_ "$descr" + + 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"` + output=`echo; echo "# Stderr is:"; cat "$stderr"` else output= fi # rm first in case test_failure exits. rm "$stderr" - test_failure_ "$descr" "$@" "$output" + 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 } + # 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: # @@ -513,7 +620,42 @@ test_external_without_stderr () { test_must_fail () { "$@" - test $? -gt 0 -a $? -le 129 -o $? -gt 192 + 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 } # test_cmp is a helper function to compare actual and expected output. @@ -533,48 +675,82 @@ test_cmp() { $GIT_TEST_CMP "$@" } +# This function can be used to schedule some commands to be run +# unconditionally at the end of the test to restore sanity: +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# test_when_finished "git config --unset core.capslock" && +# hello world +# ' +# +# That would be roughly equivalent to +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# hello world +# git config --unset core.capslock +# ' +# +# except that the greeting and config --unset must both succeed for +# the test to pass. + +test_when_finished () { + test_cleanup="{ $* + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" +} + # Most tests can use the created repository, but some may need to create more. # Usage: test_create_repo <directory> test_create_repo () { test "$#" = 1 || error "bug in the test script: not 1 parameter to test-create-repo" - owd=`pwd` repo="$1" mkdir -p "$repo" - cd "$repo" || error "Cannot setup test environment" - "$GIT_EXEC_PATH/git-init" "--template=$TEST_DIRECTORY/../templates/blt/" >&3 2>&4 || - error "cannot run git init -- have you built things yet?" - mv .git/hooks .git/hooks-disabled - cd "$owd" + ( + 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 } test_done () { GIT_EXIT_OK=t - test_results_dir="$TEST_DIRECTORY/test-results" - mkdir -p "$test_results_dir" - test_results_path="$test_results_dir/${0%.sh}-$$" - echo "total $test_count" >> $test_results_path - echo "success $test_success" >> $test_results_path - echo "fixed $test_fixed" >> $test_results_path - echo "broken $test_broken" >> $test_results_path - echo "failed $test_failure" >> $test_results_path - echo "" >> $test_results_path + if test -z "$HARNESS_ACTIVE"; then + test_results_dir="$TEST_DIRECTORY/test-results" + mkdir -p "$test_results_dir" + test_results_path="$test_results_dir/${0%.sh}-$$.counts" + + echo "total $test_count" >> $test_results_path + echo "success $test_success" >> $test_results_path + echo "fixed $test_fixed" >> $test_results_path + echo "broken $test_broken" >> $test_results_path + echo "failed $test_failure" >> $test_results_path + echo "" >> $test_results_path + fi if test "$test_fixed" != 0 then - say_color pass "fixed $test_fixed known breakage(s)" + say_color pass "# fixed $test_fixed known breakage(s)" fi if test "$test_broken" != 0 then - say_color error "still have $test_broken known breakage(s)" + say_color error "# still have $test_broken known breakage(s)" msg="remaining $(($test_count-$test_broken)) test(s)" else msg="$test_count test(s)" fi case "$test_failure" in 0) - say_color pass "passed all $msg" + # Maybe print SKIP message + [ -z "$skip_all" ] || skip_all=" # SKIP $skip_all" + + if test $test_external_has_tap -eq 0; then + say_color pass "# passed all $msg" + say "1..$test_count$skip_all" + fi test -d "$remove_trash" && cd "$(dirname "$remove_trash")" && @@ -583,7 +759,11 @@ test_done () { exit 0 ;; *) - say_color error "failed $test_failure among $msg" + if test $test_external_has_tap -eq 0; then + say_color error "# failed $test_failure among $msg" + say "1..$test_count" + fi + exit 1 ;; esac @@ -591,7 +771,15 @@ test_done () { # Test the binaries we have just built. The tests are kept in # t/ subdirectory and are run in 'trash directory' subdirectory. -TEST_DIRECTORY=$(pwd) +if test -z "$TEST_DIRECTORY" +then + # We allow tests to override this, in case they want to run tests + # outside of t/, e.g. for running tests on the test library + # itself. + TEST_DIRECTORY=$(pwd) +fi +GIT_BUILD_DIR="$TEST_DIRECTORY"/.. + if test -n "$valgrind" then make_symlink () { @@ -618,7 +806,7 @@ then test -x "$1" || return base=$(basename "$1") - symlink_target=$TEST_DIRECTORY/../$base + symlink_target=$GIT_BUILD_DIR/$base # do not override scripts if test -x "$symlink_target" && test ! -d "$symlink_target" && @@ -637,7 +825,7 @@ then # override all git executables in TEST_DIRECTORY/.. GIT_VALGRIND=$TEST_DIRECTORY/valgrind mkdir -p "$GIT_VALGRIND"/bin - for file in $TEST_DIRECTORY/../git* $TEST_DIRECTORY/../test-* + for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-* do make_valgrind_symlink $file done @@ -658,10 +846,10 @@ then elif test -n "$GIT_TEST_INSTALLED" ; then GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) || error "Cannot run git from $GIT_TEST_INSTALLED." - PATH=$GIT_TEST_INSTALLED:$TEST_DIRECTORY/..:$PATH + PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR:$PATH GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH} else # normal case, use ../bin-wrappers only unless $with_dashes: - git_bin_dir="$TEST_DIRECTORY/../bin-wrappers" + git_bin_dir="$GIT_BUILD_DIR/bin-wrappers" if ! test -x "$git_bin_dir/git" ; then if test -z "$with_dashes" ; then say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH" @@ -669,35 +857,45 @@ else # normal case, use ../bin-wrappers only unless $with_dashes: with_dashes=t fi PATH="$git_bin_dir:$PATH" - GIT_EXEC_PATH=$TEST_DIRECTORY/.. + GIT_EXEC_PATH=$GIT_BUILD_DIR if test -n "$with_dashes" ; then - PATH="$TEST_DIRECTORY/..:$PATH" + PATH="$GIT_BUILD_DIR:$PATH" fi fi -GIT_TEMPLATE_DIR=$(pwd)/../templates/blt +GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt unset GIT_CONFIG GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_NOGLOBAL=1 export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL -. ../GIT-BUILD-OPTIONS +. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS + +if test -z "$GIT_TEST_CMP" +then + if test -n "$GIT_TEST_CMP_USE_COPIED_CONTEXT" + then + GIT_TEST_CMP="$DIFF -c" + else + GIT_TEST_CMP="$DIFF -u" + fi +fi -GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git +GITPERLLIB="$GIT_BUILD_DIR"/perl/blib/lib:"$GIT_BUILD_DIR"/perl/blib/arch/auto/Git export GITPERLLIB -test -d ../templates/blt || { +test -d "$GIT_BUILD_DIR"/templates/blt || { error "You haven't built things yet, have you?" } if test -z "$GIT_TEST_INSTALLED" && test -z "$NO_PYTHON" then - GITPYTHONLIB="$(pwd)/../git_remote_helpers/build/lib" + GITPYTHONLIB="$GIT_BUILD_DIR/git_remote_helpers/build/lib" export GITPYTHONLIB - test -d ../git_remote_helpers/build || { + test -d "$GIT_BUILD_DIR"/git_remote_helpers/build || { error "You haven't built git_remote_helpers yet, have you?" } fi -if ! test -x ../test-chmtime; then +if ! test -x "$GIT_BUILD_DIR"/test-chmtime; then echo >&2 'You need to build test-chmtime:' echo >&2 'Run "make test-chmtime" in the source (toplevel) directory' exit 1 @@ -722,22 +920,17 @@ test_create_repo "$test" # in subprocesses like git equals our $PWD (for pathname comparisons). cd -P "$test" || exit 1 +HOME=$(pwd) +export HOME + this_test=${0##*/} this_test=${this_test%%-*} for skp in $GIT_SKIP_TESTS do - to_skip= - for skp in $GIT_SKIP_TESTS - do - case "$this_test" in - $skp) - to_skip=t - esac - done - case "$to_skip" in - t) + case "$this_test" in + $skp) say_color skip >&3 "skipping test $this_test altogether" - say_color skip "skip all tests in $this_test" + skip_all="skip all tests in $this_test" test_done esac done @@ -777,11 +970,13 @@ case $(uname -s) in # no POSIX permissions # backslashes in pathspec are converted to '/' # exec does not inherit the PID + test_set_prereq MINGW ;; *) test_set_prereq POSIXPERM test_set_prereq BSLASHPSPEC test_set_prereq EXECKEEPSPID + test_set_prereq NOT_MINGW ;; esac @@ -791,3 +986,7 @@ test -z "$NO_PYTHON" && test_set_prereq PYTHON # test whether the filesystem supports symbolic links ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS rm -f y + +# When the tests are run as root, permission tests will report that +# things are writable when they shouldn't be. +test -w / || test_set_prereq SANITY |