diff options
Diffstat (limited to 't')
773 files changed, 72358 insertions, 3937 deletions
diff --git a/t/.gitattributes b/t/.gitattributes new file mode 100644 index 0000000000..1b97c5465b --- /dev/null +++ b/t/.gitattributes @@ -0,0 +1 @@ +t[0-9][0-9][0-9][0-9]/* -whitespace diff --git a/t/.gitignore b/t/.gitignore index fad67c097b..7dcbb232cd 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -1 +1,2 @@ -trash +/trash directory* +/test-results diff --git a/t/Makefile b/t/Makefile index 19e38508a7..cf5f9e2e1e 100644 --- a/t/Makefile +++ b/t/Makefile @@ -3,9 +3,13 @@ # Copyright (c) 2005 Junio C Hamano # +-include ../config.mak.autogen +-include ../config.mak + #GIT_TEST_OPTS=--verbose --debug SHELL_PATH ?= $(SHELL) TAR ?= $(TAR) +RM ?= rm -f # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) @@ -13,19 +17,35 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) TSVN = $(wildcard t91[0-9][0-9]-*.sh) -all: $(T) clean +all: pre-clean + $(MAKE) aggregate-results-and-cleanup $(T): @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) +pre-clean: + $(RM) -r test-results + clean: - rm -fr trash + $(RM) -r 'trash directory'.* test-results + $(RM) t????/cvsroot/CVSROOT/?* + $(RM) -r valgrind/bin + +aggregate-results-and-cleanup: $(T) + $(MAKE) aggregate-results + $(MAKE) clean + +aggregate-results: + 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: $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8 -.PHONY: $(T) clean -.NOTPARALLEL: +valgrind: + GIT_TEST_OPTS=--valgrind $(MAKE) +.PHONY: pre-clean $(T) aggregate-results clean valgrind @@ -18,28 +18,52 @@ 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 -i) command line argument to the test, or by setting GIT_TEST_OPTS +appropriately before running "make". --verbose:: This makes the test more verbose. Specifically, the @@ -54,6 +78,81 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate This causes the test to immediately exit upon the first failed test. +--long-tests:: + This causes additional long-running tests to be run (where + available), for more exhaustive testing. + +--valgrind:: + Execute all Git binaries with valgrind and exit with status + 126 on errors (just like regular tests, this will only stop + the test script when running under -i). Valgrind errors + go to stderr, so you might want to pass the -v option, too. + + Since it makes no sense to run the tests with --valgrind and + not see any output, this option implies --verbose. For + convenience, it also implies --tee. + +--tee:: + In addition to printing the test output to the terminal, + write it to files named 't/test-results/$TEST_NAME.out'. + As the names depend on the tests' file names, it is safe to + run the tests with this option in parallel. + +--with-dashes:: + By default tests are run without dashed forms of + commands (like git-commit) in the PATH (it only uses + wrappers from ../bin-wrappers). Use this option to include + the build directory (..) in the PATH, which contains all + the dashed forms of commands. This option is currently + 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 +test-* support programs, templates, and perl libraries are used. +If your installed git is incomplete, it will silently test parts of +your built version instead. + +When using GIT_TEST_INSTALLED, you can also set GIT_TEST_EXEC_PATH to +override the location of the dashed-form subcommands (what +GIT_EXEC_PATH would be used for during normal operation). +GIT_TEST_EXEC_PATH defaults to `$GIT_TEST_INSTALLED/git --exec-path`. + + +Skipping Tests +-------------- + +In some environments, certain tests have no way of succeeding +due to platform limitation, such as lack of 'unzip' program, or +filesystem that do not allow arbitrary sequence of non-NUL bytes +as pathnames. + +You should be able to say something like + + $ GIT_SKIP_TESTS=t9200.8 sh ./t9200-git-cvsexport-commit.sh + +and even: + + $ GIT_SKIP_TESTS='t[0-4]??? t91?? t9200.8' make + +to omit such tests. The value of the environment variable is a +SP separated list of patterns that tells which tests to skip, +and either can match the "t[0-9]{4}" part to skip the whole +test, or t[0-9]{4} followed by ".$number" to say which +particular test to skip. + +Note that some tests in the existing test suite rely on previous +test item, so you cannot arbitrarily disable one and expect the +remainder of test to check what the test originally was intended +to check. + Naming Tests ------------ @@ -122,15 +221,101 @@ 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' - 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 ... + +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 all the remaining tests you should set skip_all +and immediately call test_done. The string you give to skip_all will +be used as an explanation for why the test was skipped. for instance: + + if ! test_have_prereq PERL + then + skip_all='skipping perl interface tests, perl not available' + test_done + fi End with test_done ------------------ @@ -146,9 +331,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. @@ -158,16 +343,31 @@ 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: - This is the opposite of test_expect_success. If <script> - yields success, test is considered a failure. + test_expect_success TTY 'git --paginate rev-list uses a pager' \ + ' ... ' - Example: + - 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 + the usual test_expect_success tests, which say "ok" on + success and "FAIL" on failure, this will say "FIXED" on + 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_failure \ - 'git-update-index without --add should fail adding.' \ - 'git-update-index should-be-empty' + test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master' - test_debug <script> @@ -182,6 +382,105 @@ library for your script to use. is to summarize successes and failures in the test script and exit with an appropriate error code. + - test_tick + + Make commit and tag names consistent by setting the author and + committer times to defined stated. Subsequent calls will + advance the times by a fixed amount. + + - test_commit <message> [<filename> [<contents>]] + + Creates a commit with the given message, committing the given + file with the given contents (default for both is to reuse the + message string), and adds a tag (again reusing the message + string as name). Calls test_tick to make the SHA-1s + reproducible. + + - test_merge <message> <commit-or-tag> + + 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, e.g. PERL and PYTHON + which are derived from ./GIT-BUILD-OPTIONS (grep test_set_prereq + test-lib.sh for more). 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_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" && + ... + ' + Tips for Writing Tests ---------------------- diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh new file mode 100755 index 0000000000..d206b7c4cf --- /dev/null +++ b/t/aggregate-results.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +fixed=0 +success=0 +failed=0 +broken=0 +total=0 + +while read file +do + while read type value + do + case $type in + '') + continue ;; + fixed) + fixed=$(($fixed + $value)) ;; + success) + success=$(($success + $value)) ;; + failed) + failed=$(($failed + $value)) ;; + broken) + broken=$(($broken + $value)) ;; + total) + total=$(($total + $value)) ;; + esac + done <"$file" +done + +printf "%-8s%d\n" fixed $fixed +printf "%-8s%d\n" success $success +printf "%-8s%d\n" failed $failed +printf "%-8s%d\n" broken $broken +printf "%-8s%d\n" total $total diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 87403da780..396b9653a3 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -114,7 +114,11 @@ test_expect_success \ test_expect_success \ 'some edit' \ 'mv file file.orig && - sed -e "s/^3A/99/" -e "/^1A/d" < file.orig > file && + { + cat file.orig && + echo + } | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" > file && + echo "incomplete" | tr -d "\\012" >>file && GIT_AUTHOR_NAME="D" git commit -a -m "edit"' test_expect_success \ diff --git a/t/diff-lib.sh b/t/diff-lib.sh index 745a1b0311..75a35fcd06 100755..100644 --- a/t/diff-lib.sh +++ b/t/diff-lib.sh @@ -1,7 +1,5 @@ : -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" sanitize_diff_raw='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /' compare_diff_raw () { # When heuristics are improved, the score numbers would change. @@ -11,7 +9,7 @@ compare_diff_raw () { sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 + test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } sanitize_diff_raw_z='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/' @@ -21,9 +19,9 @@ compare_diff_raw_z () { # Also we do not check SHA1 hash generation in this test, which # is a job for t0000-basic.sh - tr '\0' '\012' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 - tr '\0' '\012' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 + perl -pe 'y/\000/\012/' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 + perl -pe 'y/\000/\012/' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 + test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } compare_diff_patch () { @@ -37,5 +35,5 @@ compare_diff_patch () { /^[dis]*imilarity index [0-9]*%$/d /^index [0-9a-f]*\.\.[0-9a-f]/d ' <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 + test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh new file mode 100644 index 0000000000..81ef2a0969 --- /dev/null +++ b/t/gitweb-lib.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Copyright (c) 2007 Jakub Narebski +# + +gitweb_init () { + safe_pwd="$(perl -MPOSIX=getcwd -e 'print quotemeta(getcwd)')" + cat >gitweb_config.perl <<EOF +#!/usr/bin/perl + +# gitweb configuration for tests + +our \$version = 'current'; +our \$GIT = 'git'; +our \$projectroot = "$safe_pwd"; +our \$project_maxdepth = 8; +our \$home_link_str = 'projects'; +our \$site_name = '[localhost]'; +our \$site_header = ''; +our \$site_footer = ''; +our \$home_text = 'indextext.html'; +our @stylesheets = ('file:///$TEST_DIRECTORY/../gitweb/static/gitweb.css'); +our \$logo = 'file:///$TEST_DIRECTORY/../gitweb/static/git-logo.png'; +our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/static/git-favicon.png'; +our \$projects_list = ''; +our \$export_ok = ''; +our \$strict_export = ''; +our \$maxload = undef; + +EOF + + cat >.git/description <<EOF +$0 test repository +EOF +} + +gitweb_run () { + GATEWAY_INTERFACE='CGI/1.1' + HTTP_ACCEPT='*/*' + REQUEST_METHOD='GET' + SCRIPT_NAME="$TEST_DIRECTORY/../gitweb/gitweb.perl" + QUERY_STRING=""$1"" + PATH_INFO=""$2"" + export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD \ + SCRIPT_NAME QUERY_STRING PATH_INFO + + GITWEB_CONFIG=$(pwd)/gitweb_config.perl + export GITWEB_CONFIG + + # some of git commands write to STDERR on error, but this is not + # written to web server logs, so we are not interested in that: + # we are interested only in properly formatted errors/warnings + rm -f gitweb.log && + perl -- "$SCRIPT_NAME" \ + >gitweb.output 2>gitweb.log && + perl -w -e ' + open O, ">gitweb.headers"; + while (<>) { + print O; + last if (/^\r$/ || /^$/); + } + open O, ">gitweb.body"; + while (<>) { + print O; + } + close O; + ' gitweb.output && + if grep '^[[]' gitweb.log >/dev/null 2>&1; then false; else true; fi + + # gitweb.log is left for debugging + # gitweb.output is used to parse HTTP output + # gitweb.headers contains only HTTP headers + # gitweb.body contains body of message, without headers +} + +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping gitweb tests, perl not available' + test_done +fi + +perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || { + skip_all='skipping gitweb tests, perl version is too old' + test_done +} + +gitweb_init diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh new file mode 100644 index 0000000000..648d1619c8 --- /dev/null +++ b/t/lib-cvs.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +. ./test-lib.sh + +unset CVS_SERVER +# for clean cvsps cache +HOME=$(pwd) +export HOME + +if ! type cvs >/dev/null 2>&1 +then + skip_all='skipping cvsimport tests, cvs not found' + test_done +fi + +CVS="cvs -f" +export CVS + +cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'` +case "$cvsps_version" in +2.1 | 2.2*) + ;; +'') + skip_all='skipping cvsimport tests, cvsps not found' + test_done + ;; +*) + skip_all='skipping cvsimport tests, unsupported cvsps version' + test_done + ;; +esac + +test_cvs_co () { + # Usage: test_cvs_co BRANCH_NAME + rm -rf module-cvs-"$1" + if [ "$1" = "master" ] + then + $CVS co -P -d module-cvs-"$1" -A module + else + $CVS co -P -d module-cvs-"$1" -r "$1" module + fi +} + +test_git_co () { + # Usage: test_git_co BRANCH_NAME + (cd module-git && git checkout "$1") +} + +test_cmp_branch_file () { + # Usage: test_cmp_branch_file BRANCH_NAME PATH + # The branch must already be checked out of CVS and git. + test_cmp module-cvs-"$1"/"$2" module-git/"$2" +} + +test_cmp_branch_tree () { + # Usage: test_cmp_branch_tree BRANCH_NAME + # Check BRANCH_NAME out of CVS and git and make sure that all + # of the files and directories are identical. + + test_cvs_co "$1" && + test_git_co "$1" && + ( + cd module-cvs-"$1" + find . -type d -name CVS -prune -o -type f -print + ) | sort >module-cvs-"$1".list && + ( + cd module-git + find . -type d -name .git -prune -o -type f -print + ) | sort >module-git-"$1".list && + test_cmp module-cvs-"$1".list module-git-"$1".list && + cat module-cvs-"$1".list | while read f + do + test_cmp_branch_file "$1" "$f" || return 1 + done +} diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index f6fe78cd27..92d6d31942 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -1,45 +1,51 @@ . ./test-lib.sh +remotes_git_svn=remotes/git""-svn +git_svn_id=git""-svn-id + if test -n "$NO_SVN_TESTS" then - test_expect_success '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 + skip_all='skipping git svn tests, perl not available' test_done - exit fi GIT_DIR=$PWD/.git -GIT_SVN_DIR=$GIT_DIR/svn/git-svn +GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn SVN_TREE=$GIT_SVN_DIR/svn-tree svn >/dev/null 2>&1 if test $? -ne 1 then - test_expect_success 'skipping git-svn tests, svn not found' : + skip_all='skipping git svn tests, svn not found' test_done - exit fi svnrepo=$PWD/svnrepo +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); -system(qw/svnadmin create --fs-type fsfs/, '$svnrepo') == 0 or exit(41); +system(qw/svnadmin create --fs-type fsfs/, \$ENV{svnrepo}) == 0 or exit(41); " >&3 2>&4 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 - test_expect_success "$err" : test_done - exit fi rawsvnrepo="$svnrepo" @@ -48,3 +54,118 @@ svnrepo="file://$svnrepo" poke() { test-chmtime +1 "$1" } + +# We need this, because we should pass empty configuration directory to +# the 'svn commit' to avoid automated property changes and other stuff +# that could be set from user's configuration files in ~/.subversion. +svn_cmd () { + [ -d "$svnconf" ] || mkdir "$svnconf" + orig_svncmd="$1"; shift + if [ -z "$orig_svncmd" ]; then + svn + return + fi + svn "$orig_svncmd" --config-dir "$svnconf" "$@" +} + +for d in \ + "$SVN_HTTPD_PATH" \ + /usr/sbin/apache2 \ + /usr/sbin/httpd \ +; do + if test -f "$d" + then + SVN_HTTPD_PATH="$d" + break + fi +done +for d in \ + "$SVN_HTTPD_MODULE_PATH" \ + /usr/lib/apache2/modules \ + /usr/libexec/apache2 \ +; do + if test -d "$d" + then + SVN_HTTPD_MODULE_PATH="$d" + break + fi +done + +start_httpd () { + repo_base_path="$1" + if test -z "$SVN_HTTPD_PORT" + then + echo >&2 'SVN_HTTPD_PORT is not defined!' + return + fi + if test -z "$repo_base_path" + then + repo_base_path=svn + fi + + mkdir "$GIT_DIR"/logs + + cat > "$GIT_DIR/httpd.conf" <<EOF +ServerName "git svn test" +ServerRoot "$GIT_DIR" +DocumentRoot "$GIT_DIR" +PidFile "$GIT_DIR/httpd.pid" +LockFile logs/accept.lock +Listen 127.0.0.1:$SVN_HTTPD_PORT +LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so +LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so +<Location /$repo_base_path> + DAV svn + SVNPath "$rawsvnrepo" +</Location> +EOF + "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start + svnrepo="http://127.0.0.1:$SVN_HTTPD_PORT/$repo_base_path" +} + +stop_httpd () { + test -z "$SVN_HTTPD_PORT" && return + "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k stop +} + +convert_to_rev_db () { + "$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]"; +open my $rd, '<', $ARGV[0] or die "$!: couldn't open: $ARGV[0]"; +my $size = (stat($rd))[7]; +($size % 24) == 0 or die "Inconsistent size: $size"; +while (sysread($rd, my $buf, 24) == 24) { + my ($r, $c) = unpack('NH40', $buf); + my $offset = $r * 41; + seek $wr, 0, 2 or die $!; + my $pos = tell $wr; + if ($pos < $offset) { + for (1 .. (($offset - $pos) / 41)) { + print $wr (('0' x 40),"\n") or die $!; + } + } + seek $wr, $offset, 0 or die $!; + print $wr $c,"\n" or die $!; +} +close $wr or die $!; +close $rd or die $!; +EOF +} + +require_svnserve () { + if test -z "$SVNSERVE_PORT" + then + skip_all='skipping svnserve test. (set $SVNSERVE_PORT to enable)' + test_done + fi +} + +start_svnserve () { + svnserve --listen-port $SVNSERVE_PORT \ + --root "$rawsvnrepo" \ + --listen-once \ + --listen-host 127.0.0.1 & +} + diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh new file mode 100644 index 0000000000..e733f6516f --- /dev/null +++ b/t/lib-httpd.sh @@ -0,0 +1,161 @@ +#!/bin/sh +# +# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at> +# + +if test -z "$GIT_TEST_HTTPD" +then + skip_all="Network testing disabled (define GIT_TEST_HTTPD to enable)" + test_done +fi + +HTTPD_PARA="" + +for DEFAULT_HTTPD_PATH in '/usr/sbin/httpd' '/usr/sbin/apache2' +do + if test -x "$DEFAULT_HTTPD_PATH" + then + break + fi +done + +for DEFAULT_HTTPD_MODULE_PATH in '/usr/libexec/apache2' \ + '/usr/lib/apache2/modules' \ + '/usr/lib64/httpd/modules' \ + '/usr/lib/httpd/modules' +do + if test -d "$DEFAULT_HTTPD_MODULE_PATH" + then + break + fi +done + +case $(uname) in + Darwin) + HTTPD_PARA="$HTTPD_PARA -DDarwin" + ;; +esac + +LIB_HTTPD_PATH=${LIB_HTTPD_PATH-"$DEFAULT_HTTPD_PATH"} +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'8111'} + +TEST_PATH="$TEST_DIRECTORY"/lib-httpd +HTTPD_ROOT_PATH="$PWD"/httpd +HTTPD_DOCUMENT_ROOT_PATH=$HTTPD_ROOT_PATH/www + +if ! test -x "$LIB_HTTPD_PATH" +then + skip_all="skipping test, no web server found at '$LIB_HTTPD_PATH'" + test_done +fi + +HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \ + sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q'` + +if test -n "$HTTPD_VERSION" +then + if test -z "$LIB_HTTPD_MODULE_PATH" + then + if ! test $HTTPD_VERSION -ge 2 + then + skip_all="skipping test, at least Apache version 2 is required" + test_done + fi + if ! test -d "$DEFAULT_HTTPD_MODULE_PATH" + then + skip_all="Apache module directory not found. Skipping tests." + test_done + fi + + LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH" + fi +else + error "Could not identify web server at '$LIB_HTTPD_PATH'" +fi + +prepare_httpd() { + mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH" + + ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules" + + if test -n "$LIB_HTTPD_SSL" + then + HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT + + RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \ + -config "$TEST_PATH/ssl.cnf" \ + -new -x509 -nodes \ + -out "$HTTPD_ROOT_PATH/httpd.pem" \ + -keyout "$HTTPD_ROOT_PATH/httpd.pem" + GIT_SSL_NO_VERIFY=t + export GIT_SSL_NO_VERIFY + HTTPD_PARA="$HTTPD_PARA -DSSL" + else + HTTPD_URL=http://127.0.0.1:$LIB_HTTPD_PORT + fi + + if test -n "$LIB_HTTPD_DAV" -o -n "$LIB_HTTPD_SVN" + then + HTTPD_PARA="$HTTPD_PARA -DDAV" + + if test -n "$LIB_HTTPD_SVN" + then + HTTPD_PARA="$HTTPD_PARA -DSVN" + rawsvnrepo="$HTTPD_ROOT_PATH/svnrepo" + svnrepo="http://127.0.0.1:$LIB_HTTPD_PORT/svn" + fi + fi +} + +start_httpd() { + prepare_httpd >&3 2>&4 + + trap 'code=$?; stop_httpd; (exit $code); die' EXIT + + "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ + -f "$TEST_PATH/apache.conf" $HTTPD_PARA \ + -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start \ + >&3 2>&4 + if test $? -ne 0 + then + skip_all="skipping test, web server setup failed" + trap 'die' EXIT + test_done + fi +} + +stop_httpd() { + trap 'die' EXIT + + "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ + -f "$TEST_PATH/apache.conf" $HTTPD_PARA -k stop +} + +test_http_push_nonff() { + REMOTE_REPO=$1 + LOCAL_REPO=$2 + BRANCH=$3 + + test_expect_success 'non-fast-forward push fails' ' + cd "$REMOTE_REPO" && + HEAD=$(git rev-parse --verify HEAD) && + + cd "$LOCAL_REPO" && + git checkout $BRANCH && + echo "changed" > path2 && + git commit -a -m path2 --amend && + + test_must_fail git push -v origin >output 2>&1 && + (cd "$REMOTE_REPO" && + test $HEAD = $(git rev-parse --verify HEAD)) + ' + + test_expect_success 'non-fast-forward push show ref status' ' + grep "^ ! \[rejected\][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" output + ' + + test_expect_success 'non-fast-forward push shows help message' ' + grep "To prevent you from losing history, non-fast-forward updates were rejected" \ + output + ' +} diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf new file mode 100644 index 0000000000..4961505d1d --- /dev/null +++ b/t/lib-httpd/apache.conf @@ -0,0 +1,68 @@ +ServerName dummy +LockFile accept.lock +PidFile httpd.pid +DocumentRoot www +LogFormat "%h %l %u %t \"%r\" %>s %b" common +CustomLog access.log common +ErrorLog error.log +<IfModule !mod_log_config.c> + LoadModule log_config_module modules/mod_log_config.so +</IfModule> +<IfModule !mod_alias.c> + LoadModule alias_module modules/mod_alias.so +</IfModule> +<IfModule !mod_cgi.c> + LoadModule cgi_module modules/mod_cgi.so +</IfModule> +<IfModule !mod_env.c> + LoadModule env_module modules/mod_env.so +</IfModule> + +Alias /dumb/ www/ + +<Location /smart/> + SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} + SetEnv GIT_HTTP_EXPORT_ALL +</Location> +<Location /smart_noexport/> + SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} +</Location> +ScriptAlias /smart/ ${GIT_EXEC_PATH}/git-http-backend/ +ScriptAlias /smart_noexport/ ${GIT_EXEC_PATH}/git-http-backend/ +<Directory ${GIT_EXEC_PATH}> + Options None +</Directory> +<Files ${GIT_EXEC_PATH}/git-http-backend> + Options ExecCGI +</Files> + +<IfDefine SSL> +LoadModule ssl_module modules/mod_ssl.so + +SSLCertificateFile httpd.pem +SSLCertificateKeyFile httpd.pem +SSLRandomSeed startup file:/dev/urandom 512 +SSLRandomSeed connect file:/dev/urandom 512 +SSLSessionCache none +SSLMutex file:ssl_mutex +SSLEngine On +</IfDefine> + +<IfDefine DAV> + LoadModule dav_module modules/mod_dav.so + LoadModule dav_fs_module modules/mod_dav_fs.so + + DAVLockDB DAVLock + <Location /dumb/> + Dav on + </Location> +</IfDefine> + +<IfDefine SVN> + LoadModule dav_svn_module modules/mod_dav_svn.so + + <Location /svn> + DAV svn + SVNPath svnrepo + </Location> +</IfDefine> diff --git a/t/lib-httpd/ssl.cnf b/t/lib-httpd/ssl.cnf new file mode 100644 index 0000000000..6dab2579cb --- /dev/null +++ b/t/lib-httpd/ssl.cnf @@ -0,0 +1,8 @@ +RANDFILE = $ENV::RANDFILE_PATH + +[ req ] +default_bits = 1024 +distinguished_name = req_distinguished_name +prompt = no +[ req_distinguished_name ] +commonName = 127.0.0.1 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 new file mode 100644 index 0000000000..375e248651 --- /dev/null +++ b/t/lib-patch-mode.sh @@ -0,0 +1,43 @@ +: included from t2016 and others + +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping --patch tests, perl not available' + test_done +fi + +set_state () { + echo "$3" > "$1" && + git add "$1" && + echo "$2" > "$1" +} + +save_state () { + noslash="$(echo "$1" | tr / _)" && + cat "$1" > _worktree_"$noslash" && + git show :"$1" > _index_"$noslash" +} + +set_and_save_state () { + set_state "$@" && + save_state "$1" +} + +verify_state () { + test "$(cat "$1")" = "$2" && + test "$(git show :"$1")" = "$3" +} + +verify_saved_state () { + noslash="$(echo "$1" | tr / _)" && + verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")" +} + +save_head () { + git rev-parse HEAD > _head +} + +verify_saved_head () { + test "$(cat _head)" = "$(git rev-parse HEAD)" +} diff --git a/t/lib-read-tree-m-3way.sh b/t/lib-read-tree-m-3way.sh index d195603dfa..168329adbc 100755..100644 --- a/t/lib-read-tree-m-3way.sh +++ b/t/lib-read-tree-m-3way.sh @@ -10,14 +10,14 @@ do echo This is Z/$p from the original tree. >Z/$p test_expect_success \ "adding test file $p and Z/$p" \ - 'git-update-index --add $p && - git-update-index --add Z/$p' + 'git update-index --add $p && + git update-index --add Z/$p' done done echo This is SS from the original tree. >SS test_expect_success \ 'adding test file SS' \ - 'git-update-index --add SS' + 'git update-index --add SS' cat >TT <<\EOF This is a trivial merge sample text. Branch A is expected to upcase this word, here. @@ -32,10 +32,10 @@ This concludes the trivial merge sample file. EOF test_expect_success \ 'adding test file TT' \ - 'git-update-index --add TT' + 'git update-index --add TT' test_expect_success \ 'prepare initial tree' \ - 'tree_O=$(git-write-tree)' + 'tree_O=$(git write-tree)' ################################################################ # Branch A and B makes the changes according to the above matrix. @@ -47,14 +47,14 @@ to_remove=$(echo D? Z/D?) rm -f $to_remove test_expect_success \ 'change in branch A (removal)' \ - 'git-update-index --remove $to_remove' + 'git update-index --remove $to_remove' for p in M? Z/M? do echo This is modified $p in the branch A. >$p test_expect_success \ 'change in branch A (modification)' \ - "git-update-index $p" + "git update-index $p" done for p in AN AA Z/AN Z/AA @@ -62,32 +62,32 @@ do echo This is added $p in the branch A. >$p test_expect_success \ 'change in branch A (addition)' \ - "git-update-index --add $p" + "git update-index --add $p" done echo This is SS from the modified tree. >SS echo This is LL from the modified tree. >LL test_expect_success \ 'change in branch A (addition)' \ - 'git-update-index --add LL && - git-update-index SS' + 'git update-index --add LL && + git update-index SS' mv TT TT- sed -e '/Branch A/s/word/WORD/g' <TT- >TT rm -f TT- test_expect_success \ 'change in branch A (edit)' \ - 'git-update-index TT' + 'git update-index TT' mkdir DF echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF test_expect_success \ 'change in branch A (change file to directory)' \ - 'git-update-index --add DF/DF' + 'git update-index --add DF/DF' test_expect_success \ 'recording branch A tree' \ - 'tree_A=$(git-write-tree)' - + 'tree_A=$(git write-tree)' + ################################################################ # Branch B # Start from O @@ -96,21 +96,21 @@ rm -rf [NDMASLT][NDMASLT] Z DF mkdir Z test_expect_success \ 'reading original tree and checking out' \ - 'git-read-tree $tree_O && - git-checkout-index -a' + 'git read-tree $tree_O && + git checkout-index -a' to_remove=$(echo ?D Z/?D) rm -f $to_remove test_expect_success \ 'change in branch B (removal)' \ - "git-update-index --remove $to_remove" + "git update-index --remove $to_remove" for p in ?M Z/?M do echo This is modified $p in the branch B. >$p test_expect_success \ 'change in branch B (modification)' \ - "git-update-index $p" + "git update-index $p" done for p in NA AA Z/NA Z/AA @@ -118,41 +118,41 @@ do echo This is added $p in the branch B. >$p test_expect_success \ 'change in branch B (addition)' \ - "git-update-index --add $p" + "git update-index --add $p" done echo This is SS from the modified tree. >SS echo This is LL from the modified tree. >LL test_expect_success \ 'change in branch B (addition and modification)' \ - 'git-update-index --add LL && - git-update-index SS' + 'git update-index --add LL && + git update-index SS' mv TT TT- sed -e '/Branch B/s/word/WORD/g' <TT- >TT rm -f TT- test_expect_success \ 'change in branch B (modification)' \ - 'git-update-index TT' + 'git update-index TT' echo Branch B makes a file at DF. >DF test_expect_success \ 'change in branch B (addition of a file to conflict with directory)' \ - 'git-update-index --add DF' + 'git update-index --add DF' test_expect_success \ 'recording branch B tree' \ - 'tree_B=$(git-write-tree)' + 'tree_B=$(git write-tree)' test_expect_success \ 'keep contents of 3 trees for easy access' \ 'rm -f .git/index && - git-read-tree $tree_O && + git read-tree $tree_O && mkdir .orig-O && - git-checkout-index --prefix=.orig-O/ -f -q -a && + git checkout-index --prefix=.orig-O/ -f -q -a && rm -f .git/index && - git-read-tree $tree_A && + git read-tree $tree_A && mkdir .orig-A && - git-checkout-index --prefix=.orig-A/ -f -q -a && + git checkout-index --prefix=.orig-A/ -f -q -a && rm -f .git/index && - git-read-tree $tree_B && + git read-tree $tree_B && mkdir .orig-B && - git-checkout-index --prefix=.orig-B/ -f -q -a' + git checkout-index --prefix=.orig-B/ -f -q -a' diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh new file mode 100644 index 0000000000..6aefe27593 --- /dev/null +++ b/t/lib-rebase.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# After setting the fake editor with this function, you can +# +# - override the commit message with $FAKE_COMMIT_MESSAGE +# - amend the commit message with $FAKE_COMMIT_AMEND +# - check that non-commit messages have a certain line count with $EXPECT_COUNT +# - check the commit count in the commit message header with $EXPECT_HEADER_COUNT +# - rewrite a rebase -i script as directed by $FAKE_LINES. +# $FAKE_LINES consists of a sequence of words separated by spaces. +# The following word combinations are possible: +# +# "<lineno>" -- add a "pick" line with the SHA1 taken from the +# specified line. +# +# "<cmd> <lineno>" -- add a line with the specified command +# ("squash", "fixup", "edit", or "reword") and the SHA1 taken +# from the specified line. +# +# "#" -- Add a comment line. +# +# ">" -- Add a blank line. + +set_fake_editor () { + echo "#!$SHELL_PATH" >fake-editor.sh + cat >> fake-editor.sh <<\EOF +case "$1" in +*/COMMIT_EDITMSG) + test -z "$EXPECT_HEADER_COUNT" || + test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" || + exit + test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1" + test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1" + exit + ;; +esac +test -z "$EXPECT_COUNT" || + test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) || + exit +test -z "$FAKE_LINES" && exit +grep -v '^#' < "$1" > "$1".tmp +rm -f "$1" +echo 'rebase -i script before editing:' +cat "$1".tmp +action=pick +for line in $FAKE_LINES; do + case $line in + squash|fixup|edit|reword) + action="$line";; + "#") + echo '# comment' >> "$1";; + ">") + echo >> "$1";; + *) + sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1" + action=pick;; + esac +done +echo 'rebase -i script after editing:' +cat "$1" +EOF + + test_set_editor "$(pwd)/fake-editor.sh" + chmod a+x fake-editor.sh +} diff --git a/t/t6000lib.sh b/t/lib-t6000.sh index d40262159b..ea25dd89e5 100755..100644 --- a/t/t6000lib.sh +++ b/t/lib-t6000.sh @@ -1,3 +1,5 @@ +: included from 6002 and others + [ -d .git/refs/tags ] || mkdir -p .git/refs/tags :> sed.script @@ -17,17 +19,17 @@ unique_commit() _text=$1 _tree=$2 shift 2 - echo $_text | git-commit-tree $(tag $_tree) "$@" + echo $_text | git commit-tree $(tag $_tree) "$@" } # Save the output of a command into the tag specified. Prepend # a substitution script for the tag onto the front of sed.script save_tag() { - _tag=$1 + _tag=$1 [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..." shift 1 - "$@" >.git/refs/tags/$_tag + "$@" >.git/refs/tags/$_tag echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp cat sed.script >> sed.script.tmp @@ -35,7 +37,7 @@ save_tag() mv sed.script.tmp sed.script } -# Replace unhelpful sha1 hashses with their symbolic equivalents +# Replace unhelpful sha1 hashses with their symbolic equivalents entag() { sed -f sed.script @@ -49,27 +51,30 @@ as_author() shift 1 _save=$GIT_AUTHOR_EMAIL - export GIT_AUTHOR_EMAIL="$_author" + GIT_AUTHOR_EMAIL="$_author" + export GIT_AUTHOR_EMAIL "$@" if test -z "$_save" then unset GIT_AUTHOR_EMAIL else - export GIT_AUTHOR_EMAIL="$_save" + GIT_AUTHOR_EMAIL="$_save" + export GIT_AUTHOR_EMAIL fi } commit_date() { _commit=$1 - git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" + git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" } on_committer_date() { _date=$1 shift 1 - export GIT_COMMITTER_DATE="$_date" + GIT_COMMITTER_DATE="$_date" + export GIT_COMMITTER_DATE "$@" unset GIT_COMMITTER_DATE } @@ -86,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 @@ -97,20 +102,26 @@ check_output() # from front and back. name_from_description() { - tr "'" '-' | tr '~`!@#$%^&*()_+={}[]|\;:"<>,/? ' '-' | tr -s '-' | tr '[A-Z]' '[a-z]' | sed "s/^-*//;s/-*\$//" + perl -pe ' + s/[^A-Za-z0-9.]/-/g; + s/-+/-/g; + s/-$//; + s/^-//; + y/A-Z/a-z/; + ' } # Execute the test described by the first argument, by eval'ing # command line specified in the 2nd argument. Check the status code -# is zero and that the output matches the stream read from +# is zero and that the output matches the stream read from # stdin. test_output_expect_success() -{ +{ _description=$1 _test=$2 [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF" _name=$(echo $_description | name_from_description) cat > $_name.expected - test_expect_success "$_description" "check_output $_name \"$_test\"" + test_expect_success "$_description" "check_output $_name \"$_test\"" } diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 186de70243..f2c73369a5 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -31,13 +31,13 @@ fi . ./test-lib.sh ################################################################ -# git-init has been done in an empty repository. +# git init has been done in an empty repository. # make sure it is empty. find .git/objects -type f -print >should-be-empty test_expect_success \ - '.git/objects should be empty after git-init in an empty repo.' \ - 'cmp -s /dev/null should-be-empty' + '.git/objects should be empty after git init in an empty repo.' \ + 'cmp -s /dev/null should-be-empty' # also it should have 2 subdirectories; no fan-out anymore, pack, and info. # 3 is counting "objects" itself @@ -47,21 +47,69 @@ test_expect_success \ 'test $(wc -l < full-of-directories) = 3' ################################################################ +# Test harness +test_expect_success 'success is reported like this' ' + : +' +test_expect_failure 'pretend we have a known breakage' ' + false +' +test_expect_failure 'pretend we have fixed a known breakage' ' + : +' +test_set_prereq HAVEIT +haveit=no +test_expect_success HAVEIT 'test runs if prerequisite is satisfied' ' + test_have_prereq HAVEIT && + haveit=yes +' +donthaveit=yes +test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' ' + donthaveit=no +' +if test $haveit$donthaveit != yesyes +then + say "bug in test framework: 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 # updating a new file without --add should fail. -test_expect_failure \ - 'git-update-index without --add should fail adding.' \ - 'git-update-index should-be-empty' +test_expect_success 'git update-index without --add should fail adding.' ' + test_must_fail git update-index should-be-empty +' # and with --add it should succeed, even if it is empty (it used to fail). test_expect_success \ - 'git-update-index with --add should succeed.' \ - 'git-update-index --add should-be-empty' + 'git update-index with --add should succeed.' \ + 'git update-index --add should-be-empty' test_expect_success \ - 'writing tree out with git-write-tree' \ - 'tree=$(git-write-tree)' + 'writing tree out with git write-tree' \ + 'tree=$(git write-tree)' # we know the shape and contents of the tree and know the object ID for it. test_expect_success \ @@ -70,40 +118,59 @@ test_expect_success \ # Removing paths. rm -f should-be-empty full-of-directories -test_expect_failure \ - 'git-update-index without --remove should fail removing.' \ - 'git-update-index should-be-empty' +test_expect_success 'git update-index without --remove should fail removing.' ' + test_must_fail git update-index should-be-empty +' test_expect_success \ - 'git-update-index with --remove should be able to remove.' \ - 'git-update-index --remove should-be-empty' + 'git update-index with --remove should be able to remove.' \ + 'git update-index --remove should-be-empty' # Empty tree can be written with recent write-tree. test_expect_success \ - 'git-write-tree should be able to write an empty tree.' \ - 'tree=$(git-write-tree)' + 'git write-tree should be able to write an empty tree.' \ + 'tree=$(git write-tree)' test_expect_success \ 'validate object ID of a known tree.' \ 'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904' # Various types of objects +# Some filesystems do not support symblic links; on such systems +# some expected values are different mkdir path2 path3 path3/subp3 -for p in path0 path2/file2 path3/file3 path3/subp3/file3 +paths='path0 path2/file2 path3/file3 path3/subp3/file3' +for p in $paths do echo "hello $p" >$p - ln -s "hello $p" ${p}sym done +if test_have_prereq SYMLINKS +then + for p in $paths + do + ln -s "hello $p" ${p}sym + done + expectfilter=cat + expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b + expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3 + expectedptree2=3c5e5399f3a333eddecce7a9b9465b63f65f51e2 +else + expectfilter='grep -v sym' + expectedtree=8e18edf7d7edcf4371a3ac6ae5f07c2641db7c46 + expectedptree1=cfb8591b2f65de8b8cc1020cd7d9e67e7793b325 + expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f +fi + test_expect_success \ - 'adding various types of objects with git-update-index --add.' \ - 'find path* ! -type d -print | xargs git-update-index --add' + 'adding various types of objects with git update-index --add.' \ + 'find path* ! -type d -print | xargs git update-index --add' # Show them and see that matches what we expect. test_expect_success \ - 'showing stage with git-ls-files --stage' \ - 'git-ls-files --stage >current' + 'showing stage with git ls-files --stage' \ + 'git ls-files --stage >current' -cat >expected <<\EOF +$expectfilter >expected <<\EOF 100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 @@ -114,35 +181,35 @@ cat >expected <<\EOF 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym EOF test_expect_success \ - 'validate git-ls-files output for a known tree.' \ - 'diff current expected' + 'validate git ls-files output for a known tree.' \ + 'test_cmp expected current' test_expect_success \ - 'writing tree out with git-write-tree.' \ - 'tree=$(git-write-tree)' + 'writing tree out with git write-tree.' \ + 'tree=$(git write-tree)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b' + 'test "$tree" = "$expectedtree"' test_expect_success \ - 'showing tree with git-ls-tree' \ - 'git-ls-tree $tree >current' + 'showing tree with git ls-tree' \ + 'git ls-tree $tree >current' cat >expected <<\EOF 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 EOF -test_expect_success \ - 'git-ls-tree output for a known tree.' \ - 'diff current expected' +test_expect_success SYMLINKS \ + 'git ls-tree output for a known tree.' \ + 'test_cmp expected current' # This changed in ls-tree pathspec change -- recursive does # not show tree nodes anymore. test_expect_success \ - 'showing tree with git-ls-tree -r' \ - 'git-ls-tree -r $tree >current' -cat >expected <<\EOF + 'showing tree with git ls-tree -r' \ + 'git ls-tree -r $tree >current' +$expectfilter >expected <<\EOF 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 @@ -153,13 +220,13 @@ cat >expected <<\EOF 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym EOF test_expect_success \ - 'git-ls-tree -r output for a known tree.' \ - 'diff current expected' + 'git ls-tree -r output for a known tree.' \ + 'test_cmp expected current' # But with -r -t we can have both. test_expect_success \ - 'showing tree with git-ls-tree -r -t' \ - 'git-ls-tree -r -t $tree >current' + 'showing tree with git ls-tree -r -t' \ + 'git ls-tree -r -t $tree >current' cat >expected <<\EOF 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym @@ -173,23 +240,23 @@ cat >expected <<\EOF 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym EOF -test_expect_success \ - 'git-ls-tree -r output for a known tree.' \ - 'diff current expected' +test_expect_success SYMLINKS \ + 'git ls-tree -r output for a known tree.' \ + 'test_cmp expected current' test_expect_success \ - 'writing partial tree out with git-write-tree --prefix.' \ - 'ptree=$(git-write-tree --prefix=path3)' + 'writing partial tree out with git write-tree --prefix.' \ + 'ptree=$(git write-tree --prefix=path3)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3' + 'test "$ptree" = "$expectedptree1"' test_expect_success \ - 'writing partial tree out with git-write-tree --prefix.' \ - 'ptree=$(git-write-tree --prefix=path3/subp3)' + 'writing partial tree out with git write-tree --prefix.' \ + 'ptree=$(git write-tree --prefix=path3/subp3)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2' + 'test "$ptree" = "$expectedptree2"' cat >badobjects <<EOF 100644 blob 1000000000000000000000000000000000000000 dir/file1 @@ -202,27 +269,27 @@ EOF rm .git/index test_expect_success \ 'put invalid objects into the index.' \ - 'git-update-index --index-info < badobjects' + 'git update-index --index-info < badobjects' -test_expect_failure \ - 'writing this tree without --missing-ok.' \ - 'git-write-tree' +test_expect_success 'writing this tree without --missing-ok.' ' + test_must_fail git write-tree +' test_expect_success \ 'writing this tree with --missing-ok.' \ - 'git-write-tree --missing-ok' + 'git write-tree --missing-ok' ################################################################ rm .git/index test_expect_success \ - 'git-read-tree followed by write-tree should be idempotent.' \ - 'git-read-tree $tree && + 'git read-tree followed by write-tree should be idempotent.' \ + 'git read-tree $tree && test -f .git/index && - newtree=$(git-write-tree) && + newtree=$(git write-tree) && test "$newtree" = "$tree"' -cat >expected <<\EOF +$expectfilter >expected <<\EOF :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2 @@ -233,36 +300,36 @@ cat >expected <<\EOF :120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M path3/subp3/file3sym EOF test_expect_success \ - 'validate git-diff-files output for a know cache/work tree state.' \ - 'git-diff-files >current && diff >/dev/null -b current expected' + 'validate git diff-files output for a know cache/work tree state.' \ + 'git diff-files >current && test_cmp current expected >/dev/null' test_expect_success \ - 'git-update-index --refresh should succeed.' \ - 'git-update-index --refresh' + 'git update-index --refresh should succeed.' \ + 'git update-index --refresh' test_expect_success \ - 'no diff after checkout and git-update-index --refresh.' \ - 'git-diff-files >current && cmp -s current /dev/null' + 'no diff after checkout and git update-index --refresh.' \ + 'git diff-files >current && cmp -s current /dev/null' ################################################################ -P=087704a96baf1c2d1c869a8b084481e121c88b5b +P=$expectedtree test_expect_success \ - 'git-commit-tree records the correct tree in a commit.' \ - 'commit0=$(echo NO | git-commit-tree $P) && + 'git commit-tree records the correct tree in a commit.' \ + 'commit0=$(echo NO | git commit-tree $P) && tree=$(git show --pretty=raw $commit0 | sed -n -e "s/^tree //p" -e "/^author /q") && test "z$tree" = "z$P"' test_expect_success \ - 'git-commit-tree records the correct parent in a commit.' \ - 'commit1=$(echo NO | git-commit-tree $P -p $commit0) && + 'git commit-tree records the correct parent in a commit.' \ + 'commit1=$(echo NO | git commit-tree $P -p $commit0) && parent=$(git show --pretty=raw $commit1 | sed -n -e "s/^parent //p" -e "/^author /q") && test "z$commit0" = "z$parent"' test_expect_success \ - 'git-commit-tree omits duplicated parent in a commit.' \ - 'commit2=$(echo NO | git-commit-tree $P -p $commit0 -p $commit0) && + 'git commit-tree omits duplicated parent in a commit.' \ + 'commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) && parent=$(git show --pretty=raw $commit2 | sed -n -e "s/^parent //p" -e "/^author /q" | sort -u) && @@ -281,4 +348,42 @@ test_expect_success 'update-index D/F conflict' ' test $numpath0 = 1 ' +test_expect_success SYMLINKS 'absolute path works as expected' ' + mkdir first && + ln -s ../.git first/.git && + mkdir second && + ln -s ../first second/other && + mkdir third && + dir="$(cd .git; pwd -P)" && + dir2=third/../second/other/.git && + test "$dir" = "$(test-path-utils make_absolute_path $dir2)" && + file="$dir"/index && + test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" && + basename=blub && + test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" && + ln -s ../first/file .git/syml && + sym="$(cd first; pwd -P)"/file && + test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")" +' + +test_expect_success 'very long name in the index handled sanely' ' + + a=a && # 1 + a=$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a && # 16 + a=$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a && # 256 + a=$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a$a && # 4096 + a=${a}q && + + >path4 && + git update-index --add path4 && + ( + git ls-files -s path4 | + sed -e "s/ .*/ /" | + tr -d "\012" + echo "$a" + ) | git update-index --index-info && + len=$(git ls-files "a*" | wc -c) && + test $len = 4098 +' + test_done diff --git a/t/t0001-init.sh b/t/t0001-init.sh new file mode 100755 index 0000000000..7c0a698b92 --- /dev/null +++ b/t/t0001-init.sh @@ -0,0 +1,327 @@ +#!/bin/sh + +test_description='git init' + +. ./test-lib.sh + +check_config () { + if test -d "$1" && test -f "$1/config" && test -d "$1/refs" + then + : happy + else + echo "expected a directory $1, a file $1/config and $1/refs" + return 1 + fi + bare=$(GIT_CONFIG="$1/config" git config --bool core.bare) + worktree=$(GIT_CONFIG="$1/config" git config core.worktree) || + worktree=unset + + test "$bare" = "$2" && test "$worktree" = "$3" || { + echo "expected bare=$2 worktree=$3" + echo " got bare=$bare worktree=$worktree" + return 1 + } +} + +test_expect_success 'plain' ' + ( + unset GIT_DIR GIT_WORK_TREE + mkdir plain && + cd plain && + git init + ) && + check_config plain/.git false unset +' + +test_expect_success 'plain with GIT_WORK_TREE' ' + if ( + unset GIT_DIR + mkdir plain-wt && + cd plain-wt && + GIT_WORK_TREE=$(pwd) git init + ) + then + echo Should have failed -- GIT_WORK_TREE should not be used + false + fi +' + +test_expect_success 'plain bare' ' + ( + unset GIT_DIR GIT_WORK_TREE GIT_CONFIG + mkdir plain-bare-1 && + cd plain-bare-1 && + git --bare init + ) && + check_config plain-bare-1 true unset +' + +test_expect_success 'plain bare with GIT_WORK_TREE' ' + if ( + unset GIT_DIR GIT_CONFIG + mkdir plain-bare-2 && + cd plain-bare-2 && + GIT_WORK_TREE=$(pwd) git --bare init + ) + then + echo Should have failed -- GIT_WORK_TREE should not be used + false + fi +' + +test_expect_success 'GIT_DIR bare' ' + + ( + unset GIT_CONFIG + mkdir git-dir-bare.git && + GIT_DIR=git-dir-bare.git git init + ) && + check_config git-dir-bare.git true unset +' + +test_expect_success 'init --bare' ' + + ( + unset GIT_DIR GIT_WORK_TREE GIT_CONFIG + mkdir init-bare.git && + cd init-bare.git && + git init --bare + ) && + check_config init-bare.git true unset +' + +test_expect_success 'GIT_DIR non-bare' ' + + ( + unset GIT_CONFIG + mkdir non-bare && + cd non-bare && + GIT_DIR=.git git init + ) && + check_config non-bare/.git false unset +' + +test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' ' + + ( + unset GIT_CONFIG + mkdir git-dir-wt-1.git && + GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-1.git git init + ) && + check_config git-dir-wt-1.git false "$(pwd)" +' + +test_expect_success 'GIT_DIR & GIT_WORK_TREE (2)' ' + + if ( + unset GIT_CONFIG + mkdir git-dir-wt-2.git && + GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-2.git git --bare init + ) + then + echo Should have failed -- --bare should not be used + false + fi +' + +test_expect_success 'reinit' ' + + ( + unset GIT_CONFIG GIT_WORK_TREE GIT_CONFIG + + mkdir again && + cd again && + git init >out1 2>err1 && + git init >out2 2>err2 + ) && + grep "Initialized empty" again/out1 && + grep "Reinitialized existing" again/out2 && + >again/empty && + test_cmp again/empty again/err1 && + test_cmp again/empty again/err2 +' + +test_expect_success 'init with --template' ' + mkdir template-source && + echo content >template-source/file && + ( + mkdir template-custom && + cd template-custom && + git init --template=../template-source + ) && + test_cmp template-source/file template-custom/.git/file +' + +test_expect_success 'init with --template (blank)' ' + ( + mkdir template-plain && + cd template-plain && + git init + ) && + test -f template-plain/.git/info/exclude && + ( + mkdir template-blank && + cd template-blank && + git init --template= + ) && + ! test -f template-blank/.git/info/exclude +' + +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 && + cd templatedir-set && + unset GIT_CONFIG_NOGLOBAL && + unset GIT_TEMPLATE_DIR && + NO_SET_GIT_TEMPLATE_DIR=t && + export NO_SET_GIT_TEMPLATE_DIR && + git init + ) && + test_cmp templatedir-source/file templatedir-set/.git/file +' + +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 && + git config -f "$test_config" core.sharedRepository 0640 && + mkdir init-bare-shared-override && + cd init-bare-shared-override && + git init --bare --shared=0666 + ) && + check_config init-bare-shared-override true unset && + test x0666 = \ + x`git config -f init-bare-shared-override/config core.sharedRepository` +' + +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 && + mkdir shared-honor-global && + cd shared-honor-global && + git init + ) && + test x0666 = \ + x`git config -f shared-honor-global/.git/config core.sharedRepository` +' + +test_expect_success 'init rejects insanely long --template' ' + ( + insane=$(printf "x%09999dx" 1) && + mkdir test && + cd test && + test_must_fail git init --template=$insane + ) +' + +test_expect_success 'init creates a new directory' ' + rm -fr newdir && + ( + git init newdir && + test -d newdir/.git/refs + ) +' + +test_expect_success 'init creates a new bare directory' ' + rm -fr newdir && + ( + git init --bare newdir && + test -d newdir/refs + ) +' + +test_expect_success 'init recreates a directory' ' + rm -fr newdir && + ( + mkdir newdir && + git init newdir && + test -d newdir/.git/refs + ) +' + +test_expect_success 'init recreates a new bare directory' ' + rm -fr newdir && + ( + mkdir newdir && + git init --bare newdir && + test -d newdir/refs + ) +' + +test_expect_success 'init creates a new deep directory' ' + rm -fr newdir && + git init newdir/a/b/c && + test -d newdir/a/b/c/.git/refs +' + +test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shared)' ' + rm -fr newdir && + ( + # Leading directories should honor umask while + # the repository itself should follow "shared" + umask 002 && + git init --bare --shared=0660 newdir/a/b/c && + test -d newdir/a/b/c/refs && + ls -ld newdir/a newdir/a/b > lsab.out && + ! grep -v "^drwxrw[sx]r-x" lsab.out && + ls -ld newdir/a/b/c > lsc.out && + ! grep -v "^drwxrw[sx]---" lsc.out + ) +' + +test_expect_success 'init notices EEXIST (1)' ' + rm -fr newdir && + ( + >newdir && + test_must_fail git init newdir && + test -f newdir + ) +' + +test_expect_success 'init notices EEXIST (2)' ' + rm -fr newdir && + ( + mkdir newdir && + >newdir/a + test_must_fail git init newdir/a/b && + test -f newdir/a + ) +' + +test_expect_success POSIXPERM 'init notices EPERM' ' + rm -fr newdir && + ( + mkdir newdir && + chmod -w newdir && + test_must_fail git init newdir/a/b + ) +' + +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/t0002-gitfile.sh b/t/t0002-gitfile.sh new file mode 100755 index 0000000000..cb144258cc --- /dev/null +++ b/t/t0002-gitfile.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='.git file + +Verify that plumbing commands work when .git is a file +' +. ./test-lib.sh + +objpath() { + echo "$1" | sed -e 's|\(..\)|\1/|' +} + +objck() { + p=$(objpath "$1") + if test ! -f "$REAL/objects/$p" + then + echo "Object not found: $REAL/objects/$p" + false + fi +} + + +test_expect_success 'initial setup' ' + REAL="$(pwd)/.real" && + mv .git "$REAL" +' + +test_expect_success 'bad setup: invalid .git file format' ' + echo "gitdir $REAL" >.git && + if git rev-parse 2>.err + then + echo "git rev-parse accepted an invalid .git file" + false + fi && + if ! grep "Invalid gitfile format" .err + then + echo "git rev-parse returned wrong error" + false + fi +' + +test_expect_success 'bad setup: invalid .git file path' ' + echo "gitdir: $REAL.not" >.git && + if git rev-parse 2>.err + then + echo "git rev-parse accepted an invalid .git file path" + false + fi && + if ! grep "Not a git repository" .err + then + echo "git rev-parse returned wrong error" + false + fi +' + +test_expect_success 'final setup + check rev-parse --git-dir' ' + echo "gitdir: $REAL" >.git && + test "$REAL" = "$(git rev-parse --git-dir)" +' + +test_expect_success 'check hash-object' ' + echo "foo" >bar && + SHA=$(cat bar | git hash-object -w --stdin) && + objck $SHA +' + +test_expect_success 'check cat-file' ' + git cat-file blob $SHA >actual && + test_cmp bar actual +' + +test_expect_success 'check update-index' ' + if test -f "$REAL/index" + then + echo "Hmm, $REAL/index exists?" + false + fi && + rm -f "$REAL/objects/$(objpath $SHA)" && + git update-index --add bar && + if ! test -f "$REAL/index" + then + echo "$REAL/index not found" + false + fi && + objck $SHA +' + +test_expect_success 'check write-tree' ' + SHA=$(git write-tree) && + objck $SHA +' + +test_expect_success 'check commit-tree' ' + SHA=$(echo "commit bar" | git commit-tree $SHA) && + objck $SHA +' + +test_expect_success 'check rev-list' ' + echo $SHA >"$REAL/HEAD" && + test "$SHA" = "$(git rev-list HEAD)" +' + +test_done diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh new file mode 100755 index 0000000000..53bd7fcc4a --- /dev/null +++ b/t/t0003-attributes.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +test_description=gitattributes + +. ./test-lib.sh + +attr_check () { + + path="$1" + expect="$2" + + git check-attr test -- "$path" >actual && + echo "$path: test: $2" >expect && + test_cmp expect actual + +} + + +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" && + echo "b/g test=a/b/g" + ) >a/.gitattributes && + ( + echo "h test=a/b/h" && + echo "d/* test=a/b/d/*" + echo "d/yes notest" + ) >a/b/.gitattributes + +' + +test_expect_success 'attribute test' ' + + attr_check f f && + attr_check a/f f && + attr_check a/c/f f && + attr_check a/g a/g && + 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 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 'attribute test: read paths from stdin' ' + + cat <<EOF > expect +f: test: f +a/f: test: f +a/c/f: test: f +a/g: test: a/g +a/b/g: test: a/b/g +b/g: test: unspecified +a/b/h: test: a/b/h +a/b/d/g: test: a/b/d/* +onoff: test: unset +offon: test: set +no: test: unspecified +a/b/d/no: test: a/b/d/* +a/b/d/yes: test: unspecified +EOF + + sed -e "s/:.*//" < expect | git check-attr --stdin test > actual && + test_cmp expect actual +' + +test_expect_success 'root subdir attribute test' ' + + attr_check a/i a/i && + attr_check subdir/a/i unspecified + +' + +test_expect_success 'setup bare' ' + + git clone --bare . bare.git && + cd bare.git + +' + +test_expect_success 'bare repository: check that .gitattribute is ignored' ' + + ( + echo "f test=f" + echo "a/i test=a/i" + ) >.gitattributes && + attr_check f unspecified && + attr_check a/f unspecified && + attr_check a/c/f unspecified && + attr_check a/i unspecified && + attr_check subdir/a/i unspecified + +' + +test_expect_success 'bare repository: test info/attributes' ' + + ( + echo "f test=f" + echo "a/i test=a/i" + ) >info/attributes && + attr_check f f && + attr_check a/f f && + attr_check a/c/f f && + attr_check a/i a/i && + attr_check subdir/a/i unspecified + +' + +test_done diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh new file mode 100755 index 0000000000..2342ac5788 --- /dev/null +++ b/t/t0004-unwritable.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +test_description='detect unwritable repository and fail correctly' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + test_tick && + git commit -m initial && + echo >file && + git add file + +' + +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 '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 '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 '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_done diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh new file mode 100755 index 0000000000..93e58c00e8 --- /dev/null +++ b/t/t0005-signals.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description='signals work as we expect' +. ./test-lib.sh + +cat >expect <<EOF +three +two +one +EOF + +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 && + test_cmp expect actual +' + +test_done diff --git a/t/t0006-date.sh b/t/t0006-date.sh new file mode 100755 index 0000000000..1d4d0a5c7d --- /dev/null +++ b/t/t0006-date.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +test_description='test date parsing and printing' +. ./test-lib.sh + +# arbitrary reference time: 2009-08-30 19:20:00 +TEST_DATE_NOW=1251660000; export TEST_DATE_NOW + +check_show() { + t=$(($TEST_DATE_NOW - $1)) + echo "$t -> $2" >expect + test_expect_${3:-success} "relative date ($2)" " + test-date show $t >actual && + test_cmp expect actual + " +} + +check_show 5 '5 seconds ago' +check_show 300 '5 minutes ago' +check_show 18000 '5 hours ago' +check_show 432000 '5 days ago' +check_show 1728000 '3 weeks ago' +check_show 13000000 '5 months ago' +check_show 37500000 '1 year, 2 months ago' +check_show 55188000 '1 year, 9 months ago' +check_show 630000000 '20 years ago' +check_show 31449600 '12 months ago' + +check_parse() { + echo "$1 -> $2" >expect + test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" " + TZ=${3:-$TZ} test-date parse '$1' >actual && + test_cmp expect actual + " +} + +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 + test_expect_${3:-success} "parse approxidate ($1)" " + test-date approxidate '$1' >actual && + test_cmp expect actual + " +} + +check_approxidate now '2009-08-30 19:20:00' +check_approxidate '5 seconds ago' '2009-08-30 19:19:55' +check_approxidate 5.seconds.ago '2009-08-30 19:19:55' +check_approxidate 10.minutes.ago '2009-08-30 19:10:00' +check_approxidate yesterday '2009-08-29 19:20:00' +check_approxidate 3.days.ago '2009-08-27 19:20:00' +check_approxidate 3.weeks.ago '2009-08-09 19:20:00' +check_approxidate 3.months.ago '2009-05-30 19:20:00' +check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00' + +check_approxidate '6am yesterday' '2009-08-29 06:00:00' +check_approxidate '6pm yesterday' '2009-08-29 18:00:00' +check_approxidate '3:00' '2009-08-30 03:00:00' +check_approxidate '15:00' '2009-08-30 15:00:00' +check_approxidate 'noon today' '2009-08-30 12:00:00' +check_approxidate 'noon yesterday' '2009-08-29 12:00:00' + +check_approxidate 'last tuesday' '2009-08-25 19:20:00' +check_approxidate 'July 5th' '2009-07-05 19:20:00' +check_approxidate '06/05/2009' '2009-06-05 19:20:00' +check_approxidate '06.05.2009' '2009-05-06 19:20:00' + +check_approxidate 'Jun 6, 5AM' '2009-06-06 05:00:00' +check_approxidate '5AM Jun 6' '2009-06-06 05:00:00' +check_approxidate '6AM, June 7, 2009' '2009-06-07 06:00:00' + +test_done diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 723b29ad17..234a94f3e6 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -4,22 +4,18 @@ test_description='CRLF conversion' . ./test-lib.sh -append_cr () { - sed -e 's/$/Q/' | tr Q '\015' -} - -remove_cr () { - tr '\015' Q <"$1" | grep Q >/dev/null && - tr '\015' Q <"$1" | sed -ne 's/Q$//p' +has_cr() { + tr '\015' Q <"$1" | grep Q >/dev/null } test_expect_success setup ' - git repo-config core.autocrlf false && + git config core.autocrlf false && for w in Hello world how are you; do echo $w; done >one && mkdir dir && for w in I am very very fine thank you; do echo $w; done >dir/two && + for w in Oh here is NULQin text here; do echo $w; done | q_to_nul >three && git add . && git commit -m initial && @@ -27,6 +23,7 @@ test_expect_success setup ' one=`git rev-parse HEAD:one` && dir=`git rev-parse HEAD:dir` && two=`git rev-parse HEAD:dir/two` && + three=`git rev-parse HEAD:three` && for w in Some extra lines here; do echo $w; done >>one && git diff >patch.file && @@ -36,11 +33,65 @@ test_expect_success setup ' echo happy. ' +test_expect_success 'safecrlf: autocrlf=input, all CRLF' ' + + git config core.autocrlf input && + git config core.safecrlf true && + + for w in I am all CRLF; do echo $w; done | append_cr >allcrlf && + test_must_fail git add allcrlf +' + +test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' ' + + git config core.autocrlf input && + git config core.safecrlf true && + + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && + test_must_fail git add mixed +' + +test_expect_success 'safecrlf: autocrlf=true, all LF' ' + + git config core.autocrlf true && + git config core.safecrlf true && + + for w in I am all LF; do echo $w; done >alllf && + test_must_fail git add alllf +' + +test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' ' + + git config core.autocrlf true && + git config core.safecrlf true && + + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && + test_must_fail git add mixed +' + +test_expect_success 'safecrlf: print warning only once' ' + + git config core.autocrlf input && + git config core.safecrlf warn && + + for w in I am all LF; do echo $w; done >doublewarn && + git add doublewarn && + git commit -m "nowarn" && + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >doublewarn && + test $(git add doublewarn 2>&1 | grep "CRLF will be replaced by LF" | wc -l) = 1 +' + +test_expect_success 'switch off autocrlf, safecrlf, reset HEAD' ' + git config core.autocrlf false && + git config core.safecrlf false && + git reset --hard HEAD^ +' + test_expect_success 'update with autocrlf=input' ' - rm -f tmp one dir/two && + rm -f tmp one dir/two three && git read-tree --reset -u HEAD && - git repo-config core.autocrlf input && + git config core.autocrlf input && for f in one dir/two do @@ -62,9 +113,9 @@ test_expect_success 'update with autocrlf=input' ' test_expect_success 'update with autocrlf=true' ' - rm -f tmp one dir/two && + rm -f tmp one dir/two three && git read-tree --reset -u HEAD && - git repo-config core.autocrlf true && + git config core.autocrlf true && for f in one dir/two do @@ -86,13 +137,13 @@ test_expect_success 'update with autocrlf=true' ' test_expect_success 'checkout with autocrlf=true' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf true && + rm -f tmp one dir/two three && + git config core.autocrlf true && git read-tree --reset -u HEAD && for f in one dir/two do - remove_cr "$f" >tmp && mv -f tmp $f && + remove_cr <"$f" >tmp && mv -f tmp $f && git update-index -- $f || { echo "Eh? $f" false @@ -110,13 +161,13 @@ test_expect_success 'checkout with autocrlf=true' ' test_expect_success 'checkout with autocrlf=input' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf input && + rm -f tmp one dir/two three && + git config core.autocrlf input && git read-tree --reset -u HEAD && for f in one dir/two do - if remove_cr "$f" >/dev/null + if has_cr "$f" then echo "Eh? $f" false @@ -136,8 +187,8 @@ test_expect_success 'checkout with autocrlf=input' ' test_expect_success 'apply patch (autocrlf=input)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf input && + rm -f tmp one dir/two three && + git config core.autocrlf input && git read-tree --reset -u HEAD && git apply patch.file && @@ -149,8 +200,8 @@ test_expect_success 'apply patch (autocrlf=input)' ' test_expect_success 'apply patch --cached (autocrlf=input)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf input && + rm -f tmp one dir/two three && + git config core.autocrlf input && git read-tree --reset -u HEAD && git apply --cached patch.file && @@ -162,8 +213,8 @@ test_expect_success 'apply patch --cached (autocrlf=input)' ' test_expect_success 'apply patch --index (autocrlf=input)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf input && + rm -f tmp one dir/two three && + git config core.autocrlf input && git read-tree --reset -u HEAD && git apply --index patch.file && @@ -176,12 +227,12 @@ test_expect_success 'apply patch --index (autocrlf=input)' ' test_expect_success 'apply patch (autocrlf=true)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf true && + rm -f tmp one dir/two three && + git config core.autocrlf true && git read-tree --reset -u HEAD && git apply patch.file && - test "$patched" = "`remove_cr one | git hash-object --stdin`" || { + test "$patched" = "`remove_cr <one | git hash-object --stdin`" || { echo "Eh? apply without index" false } @@ -189,8 +240,8 @@ test_expect_success 'apply patch (autocrlf=true)' ' test_expect_success 'apply patch --cached (autocrlf=true)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf true && + rm -f tmp one dir/two three && + git config core.autocrlf true && git read-tree --reset -u HEAD && git apply --cached patch.file && @@ -202,16 +253,257 @@ test_expect_success 'apply patch --cached (autocrlf=true)' ' test_expect_success 'apply patch --index (autocrlf=true)' ' - rm -f tmp one dir/two && - git repo-config core.autocrlf true && + rm -f tmp one dir/two three && + git config core.autocrlf true && git read-tree --reset -u HEAD && git apply --index patch.file && test "$patched" = `git rev-parse :one` && - test "$patched" = "`remove_cr one | git hash-object --stdin`" || { + test "$patched" = "`remove_cr <one | git hash-object --stdin`" || { echo "Eh? apply with --index" false } ' +test_expect_success '.gitattributes says two is binary' ' + + rm -f tmp one dir/two three && + echo "two -crlf" >.gitattributes && + git config core.autocrlf true && + git read-tree --reset -u HEAD && + + if has_cr dir/two + then + echo "Huh?" + false + else + : happy + fi && + + if has_cr one + then + : happy + else + echo "Huh?" + false + fi && + + if has_cr three + then + echo "Huh?" + false + else + : happy + fi +' + +test_expect_success '.gitattributes says two is input' ' + + rm -f tmp one dir/two three && + echo "two crlf=input" >.gitattributes && + git read-tree --reset -u HEAD && + + if has_cr dir/two + then + echo "Huh?" + false + else + : happy + fi +' + +test_expect_success '.gitattributes says two and three are text' ' + + rm -f tmp one dir/two three && + echo "t* crlf" >.gitattributes && + git read-tree --reset -u HEAD && + + if has_cr dir/two + then + : happy + else + echo "Huh?" + false + fi && + + if has_cr three + then + : happy + else + echo "Huh?" + false + fi +' + +test_expect_success 'in-tree .gitattributes (1)' ' + + echo "one -crlf" >>.gitattributes && + git add .gitattributes && + git commit -m "Add .gitattributes" && + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset -u HEAD && + + if has_cr one + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + has_cr three || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (2)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -f -q -u -a && + + if has_cr one + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + has_cr three || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (3)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -u .gitattributes && + git checkout-index -u one dir/two three && + + if has_cr one + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + has_cr three || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (4)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -u one dir/two three && + git checkout-index -u .gitattributes && + + if has_cr one + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + has_cr three || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'checkout with existing .gitattributes' ' + + git config core.autocrlf true && + git config --unset core.safecrlf && + echo ".file2 -crlfQ" | q_to_cr >> .gitattributes && + git add .gitattributes && + git commit -m initial && + echo ".file -crlfQ" | q_to_cr >> .gitattributes && + echo "contents" > .file && + git add .gitattributes .file && + git commit -m second && + + git checkout master~1 && + git checkout master && + test "$(git diff-files --raw)" = "" + +' + +test_expect_success 'checkout when deleting .gitattributes' ' + + git rm .gitattributes && + echo "contentsQ" | q_to_cr > .file2 && + git add .file2 && + git commit -m third + + git checkout master~1 && + git checkout master && + has_cr .file2 + +' + +test_expect_success 'invalid .gitattributes (must not crash)' ' + + echo "three +crlf" >>.gitattributes && + 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 new file mode 100755 index 0000000000..828e35baf7 --- /dev/null +++ b/t/t0021-conversion.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +test_description='blob conversion via gitattributes' + +. ./test-lib.sh + +cat <<EOF >rot13.sh +#!$SHELL_PATH +tr \ + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \ + 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM' +EOF +chmod +x rot13.sh + +test_expect_success setup ' + git config filter.rot13.smudge ./rot13.sh && + git config filter.rot13.clean ./rot13.sh && + + { + echo "*.t filter=rot13" + echo "*.i ident" + } >.gitattributes && + + { + echo a b c d e f g h i j k l m + echo n o p q r s t u v w x y z + echo '\''$Id$'\'' + } >test && + cat test >test.t && + cat test >test.o && + cat test >test.i && + git add test test.t test.i && + rm -f test test.t test.i && + git checkout -- test test.t test.i +' + +script='s/^\$Id: \([0-9a-f]*\) \$/\1/p' + +test_expect_success check ' + + cmp test.o test && + cmp test.o test.t && + + # ident should be stripped in the repository + git diff --raw --exit-code :test :test.i && + id=$(git rev-parse --verify :test) && + embedded=$(sed -ne "$script" test.i) && + test "z$id" = "z$embedded" && + + git cat-file blob :test.t > test.r && + + ./rot13.sh < test.o > test.t && + cmp test.r test.t +' + +# If an expanded ident ever gets into the repository, we want to make sure that +# it is collapsed before being expanded again on checkout +test_expect_success expanded_in_repo ' + { + echo "File with expanded keywords" + echo "\$Id\$" + echo "\$Id:\$" + echo "\$Id: 0000000000000000000000000000000000000000 \$" + echo "\$Id: NoSpaceAtEnd\$" + 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: 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 && + git commit -m "File with keywords expanded" && + + echo "expanded-keywords ident" >> .gitattributes && + + rm -f expanded-keywords && + git checkout -- expanded-keywords && + cat expanded-keywords && + cmp expanded-keywords expected-output +' + +test_done diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh new file mode 100755 index 0000000000..7af3fbcc7b --- /dev/null +++ b/t/t0022-crlf-rename.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +test_description='ignore CR in CRLF sequence while computing similiarity' + +. ./test-lib.sh + +test_expect_success setup ' + + cat "$TEST_DIRECTORY"/t0022-crlf-rename.sh >sample && + git add sample && + + test_tick && + git commit -m Initial && + + append_cr <"$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas && + git add elpmas && + rm -f sample && + + test_tick && + git commit -a -m Second + +' + +test_expect_success 'diff -M' ' + + git diff-tree -M -r --name-status HEAD^ HEAD | + sed -e "s/R[0-9]*/RNUM/" >actual && + echo "RNUM sample elpmas" >expect && + test_cmp expect actual + +' + +test_done diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh new file mode 100755 index 0000000000..aaed725402 --- /dev/null +++ b/t/t0023-crlf-am.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='Test am with auto.crlf' + +. ./test-lib.sh + +cat >patchfile <<\EOF +From 38be10072e45dd6b08ce40851e3fca60a31a340b Mon Sep 17 00:00:00 2001 +From: Marius Storm-Olsen <x@y.com> +Date: Thu, 23 Aug 2007 13:00:00 +0200 +Subject: test1 + +--- + foo | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + create mode 100644 foo + +diff --git a/foo b/foo +new file mode 100644 +index 0000000000000000000000000000000000000000..5716ca5987cbf97d6bb54920bea6adde242d87e6 +--- /dev/null ++++ b/foo +@@ -0,0 +1 @@ ++bar +EOF + +test_expect_success 'setup' ' + + git config core.autocrlf true && + echo foo >bar && + git add bar && + test_tick && + git commit -m initial + +' + +test_expect_success 'am' ' + + git am -3 <patchfile && + git diff-files --name-status --exit-code + +' + +test_done diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh new file mode 100755 index 0000000000..c7d0324374 --- /dev/null +++ b/t/t0024-crlf-archive.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +test_description='respect crlf in git archive' + +. ./test-lib.sh +UNZIP=${UNZIP:-unzip} + +test_expect_success setup ' + + git config core.autocrlf true + + printf "CRLF line ending\r\nAnd another\r\n" > sample && + git add sample && + + test_tick && + git commit -m Initial + +' + +test_expect_success 'tar archive' ' + + git archive --format=tar HEAD | + ( mkdir untarred && cd untarred && "$TAR" -xf - ) + + test_cmp sample untarred/sample + +' + +"$UNZIP" -v >/dev/null 2>&1 +if [ $? -eq 127 ]; then + say "Skipping ZIP test, because unzip was not found" +else + test_set_prereq UNZIP +fi + +test_expect_success UNZIP 'zip archive' ' + + git archive --format=zip HEAD >test.zip && + + ( mkdir unzipped && cd unzipped && unzip ../test.zip ) && + + test_cmp sample unzipped/sample + +' + +test_done 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/t0030-stripspace.sh b/t/t0030-stripspace.sh new file mode 100755 index 0000000000..ccb0a3cb61 --- /dev/null +++ b/t/t0030-stripspace.sh @@ -0,0 +1,400 @@ +#!/bin/sh +# +# Copyright (c) 2007 Carlos Rica +# + +test_description='git stripspace' + +. ./test-lib.sh + +t40='A quick brown fox jumps over the lazy do' +s40=' ' +sss="$s40$s40$s40$s40$s40$s40$s40$s40$s40$s40" # 400 +ttt="$t40$t40$t40$t40$t40$t40$t40$t40$t40$t40" # 400 + +test_expect_success \ + 'long lines without spaces should be unchanged' ' + echo "$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual +' + +test_expect_success \ + 'lines with spaces at the beginning should be unchanged' ' + echo "$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$sss$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual +' + +test_expect_success \ + 'lines with intermediate spaces should be unchanged' ' + echo "$ttt$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual +' + +test_expect_success \ + 'consecutive blank lines should be unified' ' + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'only consecutive blank lines should be completely removed' ' + > expect && + + printf "\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss\n$sss\n$sss\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss\n$sss\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n$sss\n$sss$sss\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'consecutive blank lines at the beginning should be removed' ' + printf "$ttt\n" > expect && + printf "\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" > expect && + printf "\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" > expect && + + printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'consecutive blank lines at the end should be removed' ' + printf "$ttt\n" > expect && + printf "$ttt\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" > expect && + printf "$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n" > expect && + printf "$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt$ttt\n" > expect && + printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" > expect && + + printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'text without newline at end should end with newline' ' + test `printf "$ttt" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt$ttt" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt$ttt$ttt" | git stripspace | wc -l` -gt 0 +' + +# text plus spaces at the end: + +test_expect_success \ + 'text plus spaces without newline at end should end with newline' ' + test `printf "$ttt$sss" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt$sss" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt$ttt$sss" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$sss$sss" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$ttt$sss$sss" | git stripspace | wc -l` -gt 0 && + test `printf "$ttt$sss$sss$sss" | git stripspace | wc -l` -gt 0 +' + +test_expect_success \ + 'text plus spaces without newline at end should not show spaces' ' + ! (printf "$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$ttt$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$ttt$ttt$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$ttt$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$ttt$ttt$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$ttt$sss$sss$sss" | git stripspace | grep " " >/dev/null) +' + +test_expect_success \ + 'text plus spaces without newline should show the correct lines' ' + printf "$ttt\n" >expect && + printf "$ttt$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" >expect && + printf "$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n" >expect && + printf "$ttt$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n" >expect && + printf "$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n" >expect && + printf "$ttt$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt$ttt\n" >expect && + printf "$ttt$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'text plus spaces at end should not show spaces' ' + ! (echo "$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (echo "$ttt$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (echo "$ttt$ttt$ttt$sss" | git stripspace | grep " " >/dev/null) && + ! (echo "$ttt$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (echo "$ttt$ttt$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (echo "$ttt$sss$sss$sss" | git stripspace | grep " " >/dev/null) +' + +test_expect_success \ + 'text plus spaces at end should be cleaned and newline must remain' ' + echo "$ttt" >expect && + echo "$ttt$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$ttt" >expect && + echo "$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$ttt" >expect && + echo "$ttt$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$ttt$ttt" >expect && + echo "$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$ttt$ttt" >expect && + echo "$ttt$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$ttt$ttt$ttt" >expect && + echo "$ttt$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual +' + +# spaces only: + +test_expect_success \ + 'spaces with newline at end should be replaced with empty string' ' + printf "" >expect && + + echo | git stripspace >actual && + test_cmp expect actual && + + echo "$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + echo "$sss$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'spaces without newline at end should not show spaces' ' + ! (printf "" | git stripspace | grep " " >/dev/null) && + ! (printf "$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$sss$sss$sss" | git stripspace | grep " " >/dev/null) && + ! (printf "$sss$sss$sss$sss" | git stripspace | grep " " >/dev/null) +' + +test_expect_success \ + 'spaces without newline at end should be replaced with empty string' ' + printf "" >expect && + + printf "" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && + + printf "$sss$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success \ + 'consecutive text lines should be unchanged' ' + printf "$ttt$ttt\n$ttt\n" >expect && + printf "$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$ttt$ttt\n$ttt\n" >expect && + printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect && + printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect && + printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect && + printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && + + printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect && + printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual +' + +test_expect_success 'strip comments, too' ' + test ! -z "$(echo "# comment" | git stripspace)" && + test -z "$(echo "# comment" | git stripspace -s)" +' + +test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh new file mode 100755 index 0000000000..20924506af --- /dev/null +++ b/t/t0040-parse-options.sh @@ -0,0 +1,340 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes Schindelin +# + +test_description='our own option parser' + +. ./test-lib.sh + +cat > expect << EOF +usage: test-parse-options <options> + + -b, --boolean get a boolean + -4, --or4 bitwise-or boolean with ...0100 + --neg-or4 same as --no-or4 + + -i, --integer <n> get a integer + -j <n> get a integer, too + --set23 set integer to 23 + -t <time> get timestamp of <time> + -L, --length <str> get length of <str> + -F, --file <FILE> set file to <FILE> + +String options + -s, --string <string> + get a string + --string2 <str> get another string + --st <st> get another string (pervert ordering) + -o <str> get another string + --default-string set string to default + +Magic arguments + --quux means --quux + -NUM set integer to NUM + + same as -b + --ambiguous positive ambiguity + --no-ambiguous negative ambiguity + +Standard options + --abbrev[=<n>] use <n> digits to display SHA-1s + -v, --verbose be verbose + -n, --dry-run dry run + -q, --quiet be quiet + +EOF + +test_expect_success 'test help' ' + test_must_fail test-parse-options -h > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +mv expect expect.err + +cat > expect << EOF +boolean: 2 +integer: 1729 +timestamp: 0 +string: 123 +abbrev: 7 +verbose: 2 +quiet: no +dry run: yes +file: prefix/my.file +EOF + +test_expect_success 'short options' ' + test-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \ + > output 2> output.err && + test_cmp expect output && + test ! -s output.err +' + +cat > expect << EOF +boolean: 2 +integer: 1729 +timestamp: 0 +string: 321 +abbrev: 10 +verbose: 2 +quiet: no +dry run: no +file: prefix/fi.le +EOF + +test_expect_success 'long options' ' + test-parse-options --boolean --integer 1729 --boolean --string2=321 \ + --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\ + > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'missing required value' ' + test-parse-options -s; + test $? = 129 && + test-parse-options --string; + test $? = 129 && + test-parse-options --file; + test $? = 129 +' + +cat > expect << EOF +boolean: 1 +integer: 13 +timestamp: 0 +string: 123 +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +arg 00: a1 +arg 01: b1 +arg 02: --boolean +EOF + +test_expect_success 'intermingled arguments' ' + test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \ + > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect << EOF +boolean: 0 +integer: 2 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'unambiguously abbreviated option' ' + test-parse-options --int 2 --boolean --no-bo > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'unambiguously abbreviated option with "="' ' + test-parse-options --int=2 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'ambiguously abbreviated option' ' + test-parse-options --strin 123; + test $? = 129 +' + +cat > expect << EOF +boolean: 0 +integer: 0 +timestamp: 0 +string: 123 +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'non ambiguous option (after two options it abbreviates)' ' + test-parse-options --st 123 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > typo.err << EOF +error: did you mean \`--boolean\` (with two dashes ?) +EOF + +test_expect_success 'detect possible typos' ' + test_must_fail test-parse-options -boolean > output 2> output.err && + test ! -s output && + test_cmp typo.err output.err +' + +cat > expect <<EOF +boolean: 0 +integer: 0 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +arg 00: --quux +EOF + +test_expect_success 'keep some options as arguments' ' + test-parse-options --quux > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect <<EOF +boolean: 0 +integer: 0 +timestamp: 1 +string: default +abbrev: 7 +verbose: 0 +quiet: yes +dry run: no +file: (not set) +arg 00: foo +EOF + +test_expect_success 'OPT_DATE() and OPT_SET_PTR() work' ' + test-parse-options -t "1970-01-01 00:00:01 +0000" --default-string \ + foo -q > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect <<EOF +Callback: "four", 0 +boolean: 5 +integer: 4 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' ' + test-parse-options --length=four -b -4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect <<EOF +Callback: "not set", 1 +EOF + +test_expect_success 'OPT_CALLBACK() and callback errors work' ' + test_must_fail test-parse-options --no-length > output 2> output.err && + test_cmp expect output && + test_cmp expect.err output.err +' + +cat > expect <<EOF +boolean: 1 +integer: 23 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'OPT_BIT() and OPT_SET_INT() work' ' + test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' ' + test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect <<EOF +boolean: 6 +integer: 0 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'OPT_BIT() works' ' + test-parse-options -bb --or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'OPT_NEGBIT() works' ' + test-parse-options -bb --no-neg-or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' ' + test-parse-options + + + + + + > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect <<EOF +boolean: 0 +integer: 12345 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'OPT_NUMBER_CALLBACK() works' ' + test-parse-options -12345 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat >expect <<EOF +boolean: 0 +integer: 0 +timestamp: 0 +string: (not set) +abbrev: 7 +verbose: 0 +quiet: no +dry run: no +file: (not set) +EOF + +test_expect_success 'negation of OPT_NONEG flags is not ambiguous' ' + test-parse-options --no-ambig >output 2>output.err && + test ! -s output.err && + test_cmp expect output +' + +test_done diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh new file mode 100755 index 0000000000..41df6bcf27 --- /dev/null +++ b/t/t0050-filesystem.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +test_description='Various filesystem issues' + +. ./test-lib.sh + +auml=`printf '\xc3\xa4'` +aumlcdiar=`printf '\x61\xcc\x88'` + +case_insensitive= +unibad= +no_symlinks= +test_expect_success 'see what we expect' ' + + test_case=test_expect_success + test_unicode=test_expect_success + mkdir junk && + echo good >junk/CamelCase && + echo bad >junk/camelcase && + if test "$(cat junk/CamelCase)" != good + then + test_case=test_expect_failure + case_insensitive=t + fi && + rm -fr junk && + mkdir junk && + >junk/"$auml" && + case "$(cd junk && echo *)" in + "$aumlcdiar") + test_unicode=test_expect_failure + unibad=t + ;; + *) ;; + esac && + rm -fr junk && + { + ln -s x y 2> /dev/null && + test -h y 2> /dev/null || + no_symlinks=1 + rm -f y + } +' + +test "$case_insensitive" && + say "will test on a case insensitive filesystem" +test "$unibad" && + say "will test on a unicode corrupting filesystem" +test "$no_symlinks" && + say "will test on a filesystem lacking symbolic links" + +if test "$case_insensitive" +then +test_expect_success "detection of case insensitive filesystem during repo init" ' + + test $(git config --bool core.ignorecase) = true +' +else +test_expect_success "detection of case insensitive filesystem during repo init" ' + + test_must_fail git config --bool core.ignorecase >/dev/null || + test $(git config --bool core.ignorecase) = false +' +fi + +if test "$no_symlinks" +then +test_expect_success "detection of filesystem w/o symlink support during repo init" ' + + v=$(git config --bool core.symlinks) && + test "$v" = false +' +else +test_expect_success "detection of filesystem w/o symlink support during repo init" ' + + test_must_fail git config --bool core.symlinks || + test "$(git config --bool core.symlinks)" = true +' +fi + +test_expect_success "setup case tests" ' + + git config core.ignorecase true && + touch camelcase && + git add camelcase && + git commit -m "initial" && + git tag initial && + git checkout -b topic && + git mv camelcase tmp && + git mv tmp CamelCase && + git commit -m "rename" && + git checkout -f master + +' + +$test_case 'rename (case change)' ' + + git mv camelcase CamelCase && + git commit -m "rename" + +' + +$test_case 'merge (case change)' ' + + rm -f CamelCase && + rm -f camelcase && + git reset --hard initial && + git merge topic + +' + + + +test_expect_failure 'add (with different case)' ' + + git reset --hard initial && + rm camelcase && + echo 1 >CamelCase && + git add CamelCase && + camel=$(git ls-files | grep -i camelcase) && + test $(echo "$camel" | wc -l) = 1 && + test "z$(git cat-file blob :$camel)" = z1 + +' + +test_expect_success "setup unicode normalization tests" ' + + test_create_repo unicode && + cd unicode && + touch "$aumlcdiar" && + git add "$aumlcdiar" && + git commit -m initial + git tag initial && + git checkout -b topic && + git mv $aumlcdiar tmp && + git mv tmp "$auml" && + git commit -m rename && + git checkout -f master + +' + +$test_unicode 'rename (silent unicode normalization)' ' + + git mv "$aumlcdiar" "$auml" && + git commit -m rename + +' + +$test_unicode 'merge (silent unicode normalization)' ' + + git reset --hard initial && + git merge topic + +' + +test_done diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh new file mode 100755 index 0000000000..0c6ff567a1 --- /dev/null +++ b/t/t0055-beyond-symlinks.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +test_description='update-index and add refuse to add beyond symlinks' + +. ./test-lib.sh + +test_expect_success SYMLINKS setup ' + >a && + mkdir b && + ln -s b c && + >c/d && + git update-index --add a b/d +' + +test_expect_success SYMLINKS 'update-index --add beyond symlinks' ' + test_must_fail git update-index --add c/d && + ! ( git ls-files | grep c/d ) +' + +test_expect_success SYMLINKS 'add beyond symlinks' ' + test_must_fail git add c/d && + ! ( git ls-files | grep c/d ) +' + +test_done diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh new file mode 100755 index 0000000000..53cf1f8dc4 --- /dev/null +++ b/t/t0060-path-utils.sh @@ -0,0 +1,142 @@ +#!/bin/sh +# +# Copyright (c) 2008 David Reiss +# + +test_description='Test various path utilities' + +. ./test-lib.sh + +norm_path() { + test_expect_success $3 "normalize path: $1 => $2" \ + "test \"\$(test-path-utils normalize_path_copy '$1')\" = '$2'" +} + +# On Windows, we are using MSYS's bash, which mangles the paths. +# Absolute paths are anchored at the MSYS installation directory, +# which means that the path / accounts for this many characters: +rootoff=$(test-path-utils normalize_path_copy / | wc -c) +# Account for the trailing LF: +if test $rootoff = 2; then + rootoff= # we are on Unix +else + rootoff=$(($rootoff-1)) +fi + +ancestor() { + # We do some math with the expected ancestor length. + expected=$3 + if test -n "$rootoff" && test "x$expected" != x-1; then + expected=$(($expected+$rootoff)) + fi + test_expect_success "longest ancestor: $1 $2 => $expected" \ + "actual=\$(test-path-utils longest_ancestor_length '$1' '$2') && + test \"\$actual\" = '$expected'" +} + +# Absolute path tests must be skipped on Windows because due to path mangling +# the test program never sees a POSIX-style absolute path +case $(uname -s) in +*MINGW*) + ;; +*) + test_set_prereq POSIX + ;; +esac + +norm_path "" "" +norm_path . "" +norm_path ./ "" +norm_path ./. "" +norm_path ./.. ++failed++ +norm_path ../. ++failed++ +norm_path ./../.// ++failed++ +norm_path dir/.. "" +norm_path dir/sub/../.. "" +norm_path dir/sub/../../.. ++failed++ +norm_path dir dir +norm_path dir// dir/ +norm_path ./dir dir +norm_path dir/. dir/ +norm_path dir///./ dir/ +norm_path dir//sub/.. dir/ +norm_path dir/sub/../ dir/ +norm_path dir/sub/../. dir/ +norm_path dir/s1/../s2/ dir/s2/ +norm_path d1/s1///s2/..//../s3/ d1/s3/ +norm_path d1/s1//../s2/../../d2 d2 +norm_path d1/.../d2 d1/.../d2 +norm_path d1/..././../d2 d1/d2 + +norm_path / / POSIX +norm_path // / POSIX +norm_path /// / POSIX +norm_path /. / POSIX +norm_path /./ / POSIX +norm_path /./.. ++failed++ POSIX +norm_path /../. ++failed++ POSIX +norm_path /./../.// ++failed++ POSIX +norm_path /dir/.. / POSIX +norm_path /dir/sub/../.. / POSIX +norm_path /dir/sub/../../.. ++failed++ POSIX +norm_path /dir /dir POSIX +norm_path /dir// /dir/ POSIX +norm_path /./dir /dir POSIX +norm_path /dir/. /dir/ POSIX +norm_path /dir///./ /dir/ POSIX +norm_path /dir//sub/.. /dir/ POSIX +norm_path /dir/sub/../ /dir/ POSIX +norm_path //dir/sub/../. /dir/ POSIX +norm_path /dir/s1/../s2/ /dir/s2/ POSIX +norm_path /d1/s1///s2/..//../s3/ /d1/s3/ POSIX +norm_path /d1/s1//../s2/../../d2 /d2 POSIX +norm_path /d1/.../d2 /d1/.../d2 POSIX +norm_path /d1/..././../d2 /d1/d2 POSIX + +ancestor / "" -1 +ancestor / / -1 +ancestor /foo "" -1 +ancestor /foo : -1 +ancestor /foo ::. -1 +ancestor /foo ::..:: -1 +ancestor /foo / 0 +ancestor /foo /fo -1 +ancestor /foo /foo -1 +ancestor /foo /foo/ -1 +ancestor /foo /bar -1 +ancestor /foo /bar/ -1 +ancestor /foo /foo/bar -1 +ancestor /foo /foo:/bar/ -1 +ancestor /foo /foo/:/bar/ -1 +ancestor /foo /foo::/bar/ -1 +ancestor /foo /:/foo:/bar/ 0 +ancestor /foo /foo:/:/bar/ 0 +ancestor /foo /:/bar/:/foo 0 +ancestor /foo/bar "" -1 +ancestor /foo/bar / 0 +ancestor /foo/bar /fo -1 +ancestor /foo/bar foo -1 +ancestor /foo/bar /foo 4 +ancestor /foo/bar /foo/ 4 +ancestor /foo/bar /foo/ba -1 +ancestor /foo/bar /:/fo 0 +ancestor /foo/bar /foo:/foo/ba 4 +ancestor /foo/bar /bar -1 +ancestor /foo/bar /bar/ -1 +ancestor /foo/bar /fo: -1 +ancestor /foo/bar :/fo -1 +ancestor /foo/bar /foo:/bar/ 4 +ancestor /foo/bar /:/foo:/bar/ 4 +ancestor /foo/bar /foo:/:/bar/ 4 +ancestor /foo/bar /:/bar/:/fo 0 +ancestor /foo/bar /:/bar/ 0 +ancestor /foo/bar .:/foo/. 4 +ancestor /foo/bar .:/foo/.:.: 4 +ancestor /foo/bar /foo/./:.:/bar 4 +ancestor /foo/bar .:/bar -1 + +test_expect_success 'strip_path_suffix' ' + test c:/msysgit = $(test-path-utils strip_path_suffix \ + c:/msysgit/libexec//git-core libexec/git-core) +' +test_done diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh new file mode 100755 index 0000000000..10b26e4d8e --- /dev/null +++ b/t/t0061-run-command.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Copyright (c) 2009 Ilari Liusvaara +# + +test_description='Test run command' + +. ./test-lib.sh + +test_expect_success 'start_command reports ENOENT' ' + test-run-command start-command-ENOENT ./does-not-exist +' + +test_done diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh new file mode 100755 index 0000000000..680d7d6861 --- /dev/null +++ b/t/t0070-fundamental.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +test_description='check that the most basic functions work + + +Verify wrappers and compatibility functions. +' + +. ./test-lib.sh + +test_expect_success 'character classes (isspace, isalpha etc.)' ' + test-ctype +' + +test_done diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh new file mode 100755 index 0000000000..315b9b3f10 --- /dev/null +++ b/t/t0100-previous.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='previous branch syntax @{-n}' + +. ./test-lib.sh + +test_expect_success 'branch -d @{-1}' ' + test_commit A && + git checkout -b junk && + git checkout - && + test "$(git symbolic-ref HEAD)" = refs/heads/master && + git branch -d @{-1} && + test_must_fail git rev-parse --verify refs/heads/junk +' + +test_expect_success 'branch -d @{-12} when there is not enough switches yet' ' + git reflog expire --expire=now && + git checkout -b junk2 && + git checkout - && + test "$(git symbolic-ref HEAD)" = refs/heads/master && + test_must_fail git branch -d @{-12} && + git rev-parse --verify refs/heads/master +' + +test_expect_success 'merge @{-1}' ' + git checkout A && + test_commit B && + git checkout A && + test_commit C && + git branch -f master B && + git branch -f other && + git checkout other && + git checkout master && + git merge @{-1} && + git cat-file commit HEAD | grep "Merge branch '\''other'\''" +' + +test_expect_success 'merge @{-1} when there is not enough switches yet' ' + git reflog expire --expire=now && + git checkout -f master && + git reset --hard B && + git branch -f other C && + git checkout other && + git checkout master && + test_must_fail git merge @{-12} +' + +test_done + diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh new file mode 100755 index 0000000000..a1998b558f --- /dev/null +++ b/t/t0101-at-syntax.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='various @{whatever} syntax tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit one && + test_commit two +' + +check_at() { + echo "$2" >expect && + git log -1 --format=%s "$1" >actual && + test_cmp expect actual +} + +test_expect_success '@{0} shows current' ' + check_at @{0} two +' + +test_expect_success '@{1} shows old' ' + check_at @{1} one +' + +test_expect_success '@{now} shows current' ' + check_at @{now} two +' + +test_expect_success '@{2001-09-17} (before the first commit) shows old' ' + check_at @{2001-09-17} one +' + +test_expect_success 'silly approxidates work' ' + check_at @{3.hot.dogs.on.2001-09-17} one +' + +test_expect_success 'notice misspelled upstream' ' + test_must_fail git log -1 --format=%s @{usptream} +' + +test_expect_success 'complain about total nonsense' ' + test_must_fail git log -1 --format=%s @{utter.bogosity} +' + +test_done diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh index d0af8c3d52..4f171722d9 100755 --- a/t/t1000-read-tree-m-3way.sh +++ b/t/t1000-read-tree-m-3way.sh @@ -72,7 +72,7 @@ In addition: ' . ./test-lib.sh -. ../lib-read-tree-m-3way.sh +. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh ################################################################ # Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT @@ -126,32 +126,29 @@ cat >expected <<\EOF 100644 X 0 Z/NN EOF -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" - check_result () { - git-ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current && - diff -u expected current + git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current && + test_cmp expected current } # This is done on an empty work directory, which is the normal # merge person behaviour. test_expect_success \ - '3-way merge with git-read-tree -m, empty cache' \ + '3-way merge with git read-tree -m, empty cache' \ "rm -fr [NDMALTS][NDMALTSF] Z && rm .git/index && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" # This starts out with the first head, which is the normal # patch submitter behaviour. test_expect_success \ - '3-way merge with git-read-tree -m, match H' \ + '3-way merge with git read-tree -m, match H' \ "rm -fr [NDMALTS][NDMALTSF] Z && rm .git/index && - git-read-tree $tree_A && - git-checkout-index -f -u -a && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree $tree_A && + git checkout-index -f -u -a && + git read-tree -m $tree_O $tree_A $tree_B && check_result" : <<\END_OF_CASE_TABLE @@ -160,7 +157,7 @@ We have so far tested only empty index and clean-and-matching-A index case which are trivial. Make sure index requirements are also checked. -"git-read-tree -m O A B" +"git read-tree -m O A B" O A B result index requirements ------------------------------------------------------------------- @@ -184,7 +181,7 @@ checked. 9 exists O!=A missing no merge must match A and be up-to-date, if exists. ------------------------------------------------------------------ - 10 exists O==A missing remove ditto + 10 exists O==A missing no merge must match A ------------------------------------------------------------------ 11 exists O!=A O!=B no merge must match A and be A!=B up-to-date, if exists. @@ -210,305 +207,322 @@ DF (file) when tree B require DF to be a directory by having DF/DF END_OF_CASE_TABLE -test_expect_failure \ - '1 - must not have an entry not in A.' \ - "rm -f .git/index XX && +test_expect_success '1 - must not have an entry not in A.' " + rm -f .git/index XX && echo XX >XX && - git-update-index --add XX && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add XX && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '2 - must match B in !O && !A && B case.' \ "rm -f .git/index NA && cp .orig-B/NA NA && - git-update-index --add NA && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add NA && + git read-tree -m $tree_O $tree_A $tree_B" test_expect_success \ '2 - matching B alone is OK in !O && !A && B case.' \ "rm -f .git/index NA && cp .orig-B/NA NA && - git-update-index --add NA && + git update-index --add NA && echo extra >>NA && - git-read-tree -m $tree_O $tree_A $tree_B" + git read-tree -m $tree_O $tree_A $tree_B" test_expect_success \ '3 - must match A in !O && A && !B case.' \ "rm -f .git/index AN && cp .orig-A/AN AN && - git-update-index --add AN && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add AN && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '3 - matching A alone is OK in !O && A && !B case.' \ "rm -f .git/index AN && cp .orig-A/AN AN && - git-update-index --add AN && + git update-index --add AN && echo extra >>AN && - git-read-tree -m $tree_O $tree_A $tree_B" + git read-tree -m $tree_O $tree_A $tree_B" -test_expect_failure \ - '3 (fail) - must match A in !O && A && !B case.' \ - "rm -f .git/index AN && +test_expect_success \ + '3 (fail) - must match A in !O && A && !B case.' " + rm -f .git/index AN && cp .orig-A/AN AN && echo extra >>AN && - git-update-index --add AN && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add AN && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '4 - must match and be up-to-date in !O && A && B && A!=B case.' \ "rm -f .git/index AA && cp .orig-A/AA AA && - git-update-index --add AA && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add AA && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \ - "rm -f .git/index AA && +test_expect_success \ + '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' " + rm -f .git/index AA && cp .orig-A/AA AA && - git-update-index --add AA && + git update-index --add AA && echo extra >>AA && - git-read-tree -m $tree_O $tree_A $tree_B" + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \ - "rm -f .git/index AA && +test_expect_success \ + '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' " + rm -f .git/index AA && cp .orig-A/AA AA && echo extra >>AA && - git-update-index --add AA && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add AA && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '5 - must match in !O && A && B && A==B case.' \ "rm -f .git/index LL && cp .orig-A/LL LL && - git-update-index --add LL && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add LL && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '5 - must match in !O && A && B && A==B case.' \ "rm -f .git/index LL && cp .orig-A/LL LL && - git-update-index --add LL && + git update-index --add LL && echo extra >>LL && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '5 (fail) - must match A in !O && A && B && A==B case.' \ - "rm -f .git/index LL && +test_expect_success \ + '5 (fail) - must match A in !O && A && B && A==B case.' " + rm -f .git/index LL && cp .orig-A/LL LL && echo extra >>LL && - git-update-index --add LL && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add LL && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '6 - must not exist in O && !A && !B case' \ - "rm -f .git/index DD && +test_expect_success \ + '6 - must not exist in O && !A && !B case' " + rm -f .git/index DD && echo DD >DD - git-update-index --add DD && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add DD && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '7 - must not exist in O && !A && B && O!=B case' \ - "rm -f .git/index DM && +test_expect_success \ + '7 - must not exist in O && !A && B && O!=B case' " + rm -f .git/index DM && cp .orig-B/DM DM && - git-update-index --add DM && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add DM && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '8 - must not exist in O && !A && B && O==B case' \ - "rm -f .git/index DN && +test_expect_success \ + '8 - must not exist in O && !A && B && O==B case' " + rm -f .git/index DN && cp .orig-B/DN DN && - git-update-index --add DN && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add DN && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '9 - must match and be up-to-date in O && A && !B && O!=A case' \ "rm -f .git/index MD && cp .orig-A/MD MD && - git-update-index --add MD && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add MD && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \ - "rm -f .git/index MD && +test_expect_success \ + '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' " + rm -f .git/index MD && cp .orig-A/MD MD && - git-update-index --add MD && + git update-index --add MD && echo extra >>MD && - git-read-tree -m $tree_O $tree_A $tree_B" + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \ - "rm -f .git/index MD && +test_expect_success \ + '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' " + rm -f .git/index MD && cp .orig-A/MD MD && echo extra >>MD && - git-update-index --add MD && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add MD && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '10 - must match and be up-to-date in O && A && !B && O==A case' \ "rm -f .git/index ND && cp .orig-A/ND ND && - git-update-index --add ND && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add ND && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \ - "rm -f .git/index ND && +test_expect_success \ + '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' " + rm -f .git/index ND && cp .orig-A/ND ND && - git-update-index --add ND && + git update-index --add ND && echo extra >>ND && - git-read-tree -m $tree_O $tree_A $tree_B" + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \ - "rm -f .git/index ND && +test_expect_success \ + '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' " + rm -f .git/index ND && cp .orig-A/ND ND && echo extra >>ND && - git-update-index --add ND && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add ND && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ "rm -f .git/index MM && cp .orig-A/MM MM && - git-update-index --add MM && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add MM && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ - "rm -f .git/index MM && +test_expect_success \ + '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' " + rm -f .git/index MM && cp .orig-A/MM MM && - git-update-index --add MM && + git update-index --add MM && echo extra >>MM && - git-read-tree -m $tree_O $tree_A $tree_B" + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ - "rm -f .git/index MM && +test_expect_success \ + '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' " + rm -f .git/index MM && cp .orig-A/MM MM && echo extra >>MM && - git-update-index --add MM && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add MM && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '12 - must match A in O && A && B && O!=A && A==B case' \ "rm -f .git/index SS && cp .orig-A/SS SS && - git-update-index --add SS && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add SS && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '12 - must match A in O && A && B && O!=A && A==B case' \ "rm -f .git/index SS && cp .orig-A/SS SS && - git-update-index --add SS && + git update-index --add SS && echo extra >>SS && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '12 (fail) - must match A in O && A && B && O!=A && A==B case' \ - "rm -f .git/index SS && +test_expect_success \ + '12 (fail) - must match A in O && A && B && O!=A && A==B case' " + rm -f .git/index SS && cp .orig-A/SS SS && echo extra >>SS && - git-update-index --add SS && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add SS && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '13 - must match A in O && A && B && O!=A && O==B case' \ "rm -f .git/index MN && cp .orig-A/MN MN && - git-update-index --add MN && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add MN && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '13 - must match A in O && A && B && O!=A && O==B case' \ "rm -f .git/index MN && cp .orig-A/MN MN && - git-update-index --add MN && + git update-index --add MN && echo extra >>MN && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' \ "rm -f .git/index NM && cp .orig-A/NM NM && - git-update-index --add NM && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add NM && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '14 - may match B in O && A && B && O==A && O!=B case' \ "rm -f .git/index NM && cp .orig-B/NM NM && - git-update-index --add NM && + git update-index --add NM && echo extra >>NM && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \ - "rm -f .git/index NM && +test_expect_success \ + '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' " + rm -f .git/index NM && cp .orig-A/NM NM && - git-update-index --add NM && + git update-index --add NM && echo extra >>NM && - git-read-tree -m $tree_O $tree_A $tree_B" + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" -test_expect_failure \ - '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \ - "rm -f .git/index NM && +test_expect_success \ + '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' " + rm -f .git/index NM && cp .orig-A/NM NM && echo extra >>NM && - git-update-index --add NM && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add NM && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" test_expect_success \ '15 - must match A in O && A && B && O==A && O==B case' \ "rm -f .git/index NN && cp .orig-A/NN NN && - git-update-index --add NN && - git-read-tree -m $tree_O $tree_A $tree_B && + git update-index --add NN && + git read-tree -m $tree_O $tree_A $tree_B && check_result" test_expect_success \ '15 - must match A in O && A && B && O==A && O==B case' \ "rm -f .git/index NN && cp .orig-A/NN NN && - git-update-index --add NN && + git update-index --add NN && echo extra >>NN && - git-read-tree -m $tree_O $tree_A $tree_B && + git read-tree -m $tree_O $tree_A $tree_B && check_result" -test_expect_failure \ - '15 (fail) - must match A in O && A && B && O==A && O==B case' \ - "rm -f .git/index NN && +test_expect_success \ + '15 (fail) - must match A in O && A && B && O==A && O==B case' " + rm -f .git/index NN && cp .orig-A/NN NN && echo extra >>NN && - git-update-index --add NN && - git-read-tree -m $tree_O $tree_A $tree_B" + git update-index --add NN && + test_must_fail git read-tree -m $tree_O $tree_A $tree_B +" # #16 test_expect_success \ '16 - A matches in one and B matches in another.' \ 'rm -f .git/index F16 && echo F16 >F16 && - git-update-index --add F16 && - tree0=`git-write-tree` && + git update-index --add F16 && + tree0=`git write-tree` && echo E16 >F16 && - git-update-index F16 && - tree1=`git-write-tree` && - git-read-tree -m $tree0 $tree1 $tree1 $tree0 && - git-ls-files --stage' + git update-index F16 && + tree1=`git write-tree` && + git read-tree -m $tree0 $tree1 $tree1 $tree0 && + git ls-files --stage' test_done diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 75e4c9a886..0c562bb820 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -5,13 +5,13 @@ test_description='Two way merge with read-tree -m $H $M -This test tries two-way merge (aka fast forward with carry forward). +This test tries two-way merge (aka fast-forward with carry forward). There is the head (called H) and another commit (called M), which is simply ahead of H. The index and the work tree contains a state that is derived from H, but may also have local changes. This test checks all the combinations described in the two-tree merge "carry forward" -rules, found in <Documentation/git-read-tree.txt>. +rules, found in <Documentation/git read-tree.txt>. In the test, these paths are used: bozbar - in H, stays in M, modified from bozbar to gnusto @@ -23,21 +23,19 @@ In the test, these paths are used: . ./test-lib.sh read_tree_twoway () { - git-read-tree -m "$1" "$2" && git-ls-files --stage + git read-tree -m "$1" "$2" && git ls-files --stage } -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" compare_change () { sed -n >current \ -e '/^--- /d; /^+++ /d; /^@@ /d;' \ -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \ "$1" - diff -u expected current + test_cmp expected current } check_cache_at () { - clean_if_empty=`git-diff-files -- "$1"` + clean_if_empty=`git diff-files -- "$1"` case "$clean_if_empty" in '') echo "$1: clean" ;; ?*) echo "$1: dirty" ;; @@ -51,7 +49,7 @@ check_cache_at () { } cat >bozbar-old <<\EOF -This is a sample file used in two-way fast forward merge +This is a sample file used in two-way fast-forward merge tests. Its second line ends with a magic word bozbar which will be modified by the merged head to gnusto. It has some extra lines so that external tools can @@ -68,25 +66,25 @@ test_expect_success \ cat bozbar-old >bozbar && echo rezrov >rezrov && echo yomin >yomin && - git-update-index --add nitfol bozbar rezrov && - treeH=`git-write-tree` && + git update-index --add nitfol bozbar rezrov && + treeH=`git write-tree` && echo treeH $treeH && - git-ls-tree $treeH && + git ls-tree $treeH && cat bozbar-new >bozbar && - git-update-index --add frotz bozbar --force-remove rezrov && - git-ls-files --stage >M.out && - treeM=`git-write-tree` && + git update-index --add frotz bozbar --force-remove rezrov && + git ls-files --stage >M.out && + treeM=`git write-tree` && echo treeM $treeM && - git-ls-tree $treeM && - git-diff-tree $treeH $treeM' + git ls-tree $treeM && + git diff-tree $treeH $treeM' test_expect_success \ '1, 2, 3 - no carry forward' \ 'rm -f .git/index && read_tree_twoway $treeH $treeM && - git-ls-files --stage >1-3.out && - diff -u M.out 1-3.out && + git ls-files --stage >1-3.out && + test_cmp M.out 1-3.out && check_cache_at bozbar dirty && check_cache_at frotz dirty && check_cache_at nitfol dirty' @@ -96,109 +94,109 @@ echo '+100644 X 0 yomin' >expected test_expect_success \ '4 - carry forward local addition.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && - git-update-index --add yomin && + git read-tree $treeH && + git checkout-index -u -f -q -a && + git update-index --add yomin && read_tree_twoway $treeH $treeM && - git-ls-files --stage >4.out || return 1 - diff -u M.out 4.out >4diff.out + git ls-files --stage >4.out || return 1 + git diff --no-index M.out 4.out >4diff.out compare_change 4diff.out expected && check_cache_at yomin clean' test_expect_success \ '5 - carry forward local addition.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo yomin >yomin && - git-update-index --add yomin && + git update-index --add yomin && echo yomin yomin >yomin && read_tree_twoway $treeH $treeM && - git-ls-files --stage >5.out || return 1 - diff -u M.out 5.out >5diff.out + git ls-files --stage >5.out || return 1 + git diff --no-index M.out 5.out >5diff.out compare_change 5diff.out expected && check_cache_at yomin dirty' test_expect_success \ '6 - local addition already has the same.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && - git-update-index --add frotz && + git read-tree $treeH && + git checkout-index -u -f -q -a && + git update-index --add frotz && read_tree_twoway $treeH $treeM && - git-ls-files --stage >6.out && - diff -u M.out 6.out && + git ls-files --stage >6.out && + test_cmp M.out 6.out && check_cache_at frotz clean' test_expect_success \ '7 - local addition already has the same.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo frotz >frotz && - git-update-index --add frotz && + git update-index --add frotz && echo frotz frotz >frotz && read_tree_twoway $treeH $treeM && - git-ls-files --stage >7.out && - diff -u M.out 7.out && + git ls-files --stage >7.out && + test_cmp M.out 7.out && check_cache_at frotz dirty' test_expect_success \ '8 - conflicting addition.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo frotz frotz >frotz && - git-update-index --add frotz && + git update-index --add frotz && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '9 - conflicting addition.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo frotz frotz >frotz && - git-update-index --add frotz && + git update-index --add frotz && echo frotz >frotz && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '10 - path removed.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && read_tree_twoway $treeH $treeM && - git-ls-files --stage >10.out && - diff -u M.out 10.out' + git ls-files --stage >10.out && + test_cmp M.out 10.out' test_expect_success \ '11 - dirty path removed.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && echo rezrov rezrov >rezrov && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '12 - unmatching local changes being removed.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo rezrov rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '13 - unmatching local changes being removed.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo rezrov rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && echo rezrov >rezrov && if read_tree_twoway $treeH $treeM; then false; else :; fi' @@ -210,104 +208,104 @@ EOF test_expect_success \ '14 - unchanged in two heads.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo nitfol nitfol >nitfol && - git-update-index --add nitfol && + git update-index --add nitfol && read_tree_twoway $treeH $treeM && - git-ls-files --stage >14.out || return 1 - diff -u M.out 14.out >14diff.out + git ls-files --stage >14.out || return 1 + git diff --no-index M.out 14.out >14diff.out compare_change 14diff.out expected && check_cache_at nitfol clean' test_expect_success \ '15 - unchanged in two heads.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo nitfol nitfol >nitfol && - git-update-index --add nitfol && + git update-index --add nitfol && echo nitfol nitfol nitfol >nitfol && read_tree_twoway $treeH $treeM && - git-ls-files --stage >15.out || return 1 - diff -u M.out 15.out >15diff.out + git ls-files --stage >15.out || return 1 + git diff --no-index M.out 15.out >15diff.out compare_change 15diff.out expected && check_cache_at nitfol dirty' test_expect_success \ '16 - conflicting local change.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo bozbar bozbar >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '17 - conflicting local change.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && echo bozbar bozbar >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo bozbar bozbar bozbar >bozbar && if read_tree_twoway $treeH $treeM; then false; else :; fi' test_expect_success \ '18 - local change already having a good result.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && cat bozbar-new >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && read_tree_twoway $treeH $treeM && - git-ls-files --stage >18.out && - diff -u M.out 18.out && + git ls-files --stage >18.out && + test_cmp M.out 18.out && check_cache_at bozbar clean' test_expect_success \ '19 - local change already having a good result, further modified.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && cat bozbar-new >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo gnusto gnusto >bozbar && read_tree_twoway $treeH $treeM && - git-ls-files --stage >19.out && - diff -u M.out 19.out && + git ls-files --stage >19.out && + test_cmp M.out 19.out && check_cache_at bozbar dirty' test_expect_success \ '20 - no local change, use new tree.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && cat bozbar-old >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && read_tree_twoway $treeH $treeM && - git-ls-files --stage >20.out && - diff -u M.out 20.out && + git ls-files --stage >20.out && + test_cmp M.out 20.out && check_cache_at bozbar dirty' test_expect_success \ '21 - no local change, dirty cache.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && cat bozbar-old >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo gnusto gnusto >bozbar && if read_tree_twoway $treeH $treeM; then false; else :; fi' -# This fails with straight two-way fast forward. +# This fails with straight two-way fast-forward. test_expect_success \ '22 - local change cache updated.' \ 'rm -f .git/index && - git-read-tree $treeH && - git-checkout-index -u -f -q -a && + git read-tree $treeH && + git checkout-index -u -f -q -a && sed -e "s/such as/SUCH AS/" bozbar-old >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && if read_tree_twoway $treeH $treeM; then false; else :; fi' # Also make sure we did not break DF vs DF/DF case. @@ -315,30 +313,97 @@ test_expect_success \ 'DF vs DF/DF case setup.' \ 'rm -f .git/index && echo DF >DF && - git-update-index --add DF && - treeDF=`git-write-tree` && + git update-index --add DF && + treeDF=`git write-tree` && echo treeDF $treeDF && - git-ls-tree $treeDF && + git ls-tree $treeDF && rm -f DF && mkdir DF && echo DF/DF >DF/DF && - git-update-index --add --remove DF DF/DF && - treeDFDF=`git-write-tree` && + git update-index --add --remove DF DF/DF && + treeDFDF=`git write-tree` && echo treeDFDF $treeDFDF && - git-ls-tree $treeDFDF && - git-ls-files --stage >DFDF.out' + git ls-tree $treeDFDF && + git ls-files --stage >DFDF.out' test_expect_success \ 'DF vs DF/DF case test.' \ 'rm -f .git/index && rm -fr DF && echo DF >DF && - git-update-index --add DF && + git update-index --add DF && read_tree_twoway $treeDF $treeDFDF && - git-ls-files --stage >DFDFcheck.out && - diff -u DFDF.out DFDFcheck.out && + git ls-files --stage >DFDFcheck.out && + test_cmp DFDF.out DFDFcheck.out && check_cache_at DF/DF dirty && :' +test_expect_success \ + 'a/b (untracked) vs a case setup.' \ + 'rm -f .git/index && + : >a && + git update-index --add a && + treeM=`git write-tree` && + echo treeM $treeM && + git ls-tree $treeM && + git ls-files --stage >treeM.out && + + rm -f a && + git update-index --remove a && + mkdir a && + : >a/b && + treeH=`git write-tree` && + echo treeH $treeH && + git ls-tree $treeH' + +test_expect_success \ + 'a/b (untracked) vs a, plus c/d case test.' \ + '! git read-tree -u -m "$treeH" "$treeM" && + git ls-files --stage && + test -f a/b' + +test_expect_success \ + 'a/b vs a, plus c/d case setup.' \ + 'rm -f .git/index && + rm -fr a && + : >a && + mkdir c && + : >c/d && + git update-index --add a c/d && + treeM=`git write-tree` && + echo treeM $treeM && + git ls-tree $treeM && + git ls-files --stage >treeM.out && + + rm -f a && + mkdir a + : >a/b && + git update-index --add --remove a a/b && + treeH=`git write-tree` && + echo treeH $treeH && + git ls-tree $treeH' + +test_expect_success \ + 'a/b vs a, plus c/d case test.' \ + 'git read-tree -u -m "$treeH" "$treeM" && + 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/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh index da3c81357b..0241329a08 100755 --- a/t/t1002-read-tree-m-u-2way.sh +++ b/t/t1002-read-tree-m-u-2way.sh @@ -10,17 +10,17 @@ This is identical to t1001, but uses -u to update the work tree as well. ' . ./test-lib.sh -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" compare_change () { sed >current \ + -e '1{/^diff --git /d;}' \ + -e '2{/^index /d;}' \ -e '/^--- /d; /^+++ /d; /^@@ /d;' \ -e 's/^\(.[0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /' "$1" - diff -u expected current + test_cmp expected current } check_cache_at () { - clean_if_empty=`git-diff-files -- "$1"` + clean_if_empty=`git diff-files -- "$1"` case "$clean_if_empty" in '') echo "$1: clean" ;; ?*) echo "$1: dirty" ;; @@ -39,26 +39,26 @@ test_expect_success \ echo nitfol >nitfol && echo bozbar >bozbar && echo rezrov >rezrov && - git-update-index --add nitfol bozbar rezrov && - treeH=`git-write-tree` && + git update-index --add nitfol bozbar rezrov && + treeH=`git write-tree` && echo treeH $treeH && - git-ls-tree $treeH && + git ls-tree $treeH && echo gnusto >bozbar && - git-update-index --add frotz bozbar --force-remove rezrov && - git-ls-files --stage >M.out && - treeM=`git-write-tree` && + git update-index --add frotz bozbar --force-remove rezrov && + git ls-files --stage >M.out && + treeM=`git write-tree` && echo treeM $treeM && - git-ls-tree $treeM && + git ls-tree $treeM && sum bozbar frotz nitfol >M.sum && - git-diff-tree $treeH $treeM' + git diff-tree $treeH $treeM' test_expect_success \ '1, 2, 3 - no carry forward' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >1-3.out && + git read-tree --reset -u $treeH && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >1-3.out && cmp M.out 1-3.out && sum bozbar frotz nitfol >actual3.sum && cmp M.sum actual3.sum && @@ -69,13 +69,13 @@ test_expect_success \ test_expect_success \ '4 - carry forward local addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo "+100644 X 0 yomin" >expected && echo yomin >yomin && - git-update-index --add yomin && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >4.out || return 1 - diff -U0 M.out 4.out >4diff.out + git update-index --add yomin && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >4.out || return 1 + git diff -U0 --no-index M.out 4.out >4diff.out compare_change 4diff.out expected && check_cache_at yomin clean && sum bozbar frotz nitfol >actual4.sum && @@ -87,14 +87,14 @@ test_expect_success \ test_expect_success \ '5 - carry forward local addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && - git-read-tree -m -u $treeH && + git read-tree --reset -u $treeH && + git read-tree -m -u $treeH && echo yomin >yomin && - git-update-index --add yomin && + git update-index --add yomin && echo yomin yomin >yomin && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >5.out || return 1 - diff -U0 M.out 5.out >5diff.out + git read-tree -m -u $treeH $treeM && + git ls-files --stage >5.out || return 1 + git diff -U0 --no-index M.out 5.out >5diff.out compare_change 5diff.out expected && check_cache_at yomin dirty && sum bozbar frotz nitfol >actual5.sum && @@ -107,12 +107,12 @@ test_expect_success \ test_expect_success \ '6 - local addition already has the same.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo frotz >frotz && - git-update-index --add frotz && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >6.out && - diff -U0 M.out 6.out && + git update-index --add frotz && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >6.out && + test_cmp M.out 6.out && check_cache_at frotz clean && sum bozbar frotz nitfol >actual3.sum && cmp M.sum actual3.sum && @@ -123,13 +123,13 @@ test_expect_success \ test_expect_success \ '7 - local addition already has the same.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo frotz >frotz && - git-update-index --add frotz && + git update-index --add frotz && echo frotz frotz >frotz && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >7.out && - diff -U0 M.out 7.out && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >7.out && + test_cmp M.out 7.out && check_cache_at frotz dirty && sum bozbar frotz nitfol >actual7.sum && if cmp M.sum actual7.sum; then false; else :; fi && @@ -141,28 +141,28 @@ test_expect_success \ test_expect_success \ '8 - conflicting addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo frotz frotz >frotz && - git-update-index --add frotz && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + git update-index --add frotz && + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '9 - conflicting addition.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo frotz frotz >frotz && - git-update-index --add frotz && + git update-index --add frotz && echo frotz >frotz && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '10 - path removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo rezrov >rezrov && - git-update-index --add rezrov && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >10.out && + git update-index --add rezrov && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >10.out && cmp M.out 10.out && sum bozbar frotz nitfol >actual10.sum && cmp M.sum actual10.sum' @@ -170,28 +170,28 @@ test_expect_success \ test_expect_success \ '11 - dirty path removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && echo rezrov rezrov >rezrov && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '12 - unmatching local changes being removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo rezrov rezrov >rezrov && - git-update-index --add rezrov && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + git update-index --add rezrov && + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '13 - unmatching local changes being removed.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo rezrov rezrov >rezrov && - git-update-index --add rezrov && + git update-index --add rezrov && echo rezrov >rezrov && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + if git read-tree -m -u $treeH $treeM; then false; else :; fi' cat >expected <<EOF -100644 X 0 nitfol @@ -201,12 +201,12 @@ EOF test_expect_success \ '14 - unchanged in two heads.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo nitfol nitfol >nitfol && - git-update-index --add nitfol && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >14.out || return 1 - diff -U0 M.out 14.out >14diff.out + git update-index --add nitfol && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >14.out || return 1 + git diff -U0 --no-index M.out 14.out >14diff.out compare_change 14diff.out expected && sum bozbar frotz >actual14.sum && grep -v nitfol M.sum > expected14.sum && @@ -221,13 +221,13 @@ test_expect_success \ test_expect_success \ '15 - unchanged in two heads.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo nitfol nitfol >nitfol && - git-update-index --add nitfol && + git update-index --add nitfol && echo nitfol nitfol nitfol >nitfol && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >15.out || return 1 - diff -U0 M.out 15.out >15diff.out + git read-tree -m -u $treeH $treeM && + git ls-files --stage >15.out || return 1 + git diff -U0 --no-index M.out 15.out >15diff.out compare_change 15diff.out expected && check_cache_at nitfol dirty && sum bozbar frotz >actual15.sum && @@ -242,29 +242,29 @@ test_expect_success \ test_expect_success \ '16 - conflicting local change.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo bozbar bozbar >bozbar && - git-update-index --add bozbar && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + git update-index --add bozbar && + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '17 - conflicting local change.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo bozbar bozbar >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo bozbar bozbar bozbar >bozbar && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + if git read-tree -m -u $treeH $treeM; then false; else :; fi' test_expect_success \ '18 - local change already having a good result.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo gnusto >bozbar && - git-update-index --add bozbar && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >18.out && - diff -U0 M.out 18.out && + git update-index --add bozbar && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >18.out && + test_cmp M.out 18.out && check_cache_at bozbar clean && sum bozbar frotz nitfol >actual18.sum && cmp M.sum actual18.sum' @@ -272,13 +272,13 @@ test_expect_success \ test_expect_success \ '19 - local change already having a good result, further modified.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo gnusto >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo gnusto gnusto >bozbar && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >19.out && - diff -U0 M.out 19.out && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >19.out && + test_cmp M.out 19.out && check_cache_at bozbar dirty && sum frotz nitfol >actual19.sum && grep -v bozbar M.sum > expected19.sum && @@ -292,12 +292,12 @@ test_expect_success \ test_expect_success \ '20 - no local change, use new tree.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo bozbar >bozbar && - git-update-index --add bozbar && - git-read-tree -m -u $treeH $treeM && - git-ls-files --stage >20.out && - diff -U0 M.out 20.out && + git update-index --add bozbar && + git read-tree -m -u $treeH $treeM && + git ls-files --stage >20.out && + test_cmp M.out 20.out && check_cache_at bozbar clean && sum bozbar frotz nitfol >actual20.sum && cmp M.sum actual20.sum' @@ -305,40 +305,40 @@ test_expect_success \ test_expect_success \ '21 - no local change, dirty cache.' \ 'rm -f .git/index nitfol bozbar rezrov frotz && - git-read-tree --reset -u $treeH && + git read-tree --reset -u $treeH && echo bozbar >bozbar && - git-update-index --add bozbar && + git update-index --add bozbar && echo gnusto gnusto >bozbar && - if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + if git read-tree -m -u $treeH $treeM; then false; else :; fi' # Also make sure we did not break DF vs DF/DF case. test_expect_success \ 'DF vs DF/DF case setup.' \ 'rm -f .git/index echo DF >DF && - git-update-index --add DF && - treeDF=`git-write-tree` && + git update-index --add DF && + treeDF=`git write-tree` && echo treeDF $treeDF && - git-ls-tree $treeDF && + git ls-tree $treeDF && rm -f DF && mkdir DF && echo DF/DF >DF/DF && - git-update-index --add --remove DF DF/DF && - treeDFDF=`git-write-tree` && + git update-index --add --remove DF DF/DF && + treeDFDF=`git write-tree` && echo treeDFDF $treeDFDF && - git-ls-tree $treeDFDF && - git-ls-files --stage >DFDF.out' + git ls-tree $treeDFDF && + git ls-files --stage >DFDF.out' test_expect_success \ 'DF vs DF/DF case test.' \ 'rm -f .git/index && rm -fr DF && echo DF >DF && - git-update-index --add DF && - git-read-tree -m -u $treeDF $treeDFDF && - git-ls-files --stage >DFDFcheck.out && - diff -U0 DFDF.out DFDFcheck.out && + git update-index --add DF && + git read-tree -m -u $treeDF $treeDFDF && + git ls-files --stage >DFDFcheck.out && + test_cmp DFDF.out DFDFcheck.out && check_cache_at DF/DF clean' test_done diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh index 48ab117d75..8c6d67edda 100755 --- a/t/t1003-read-tree-prefix.sh +++ b/t/t1003-read-tree-prefix.sh @@ -3,15 +3,15 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='git-read-tree --prefix test. +test_description='git read-tree --prefix test. ' . ./test-lib.sh test_expect_success setup ' echo hello >one && - git-update-index --add one && - tree=`git-write-tree` && + git update-index --add one && + tree=`git write-tree` && echo tree is $tree ' @@ -19,8 +19,8 @@ echo 'one two/one' >expect test_expect_success 'read-tree --prefix' ' - git-read-tree --prefix=two/ $tree && - git-ls-files >actual && + git read-tree --prefix=two/ $tree && + git ls-files >actual && cmp expect actual ' diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index c11420a8b6..f19b4a2a4a 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -84,7 +84,7 @@ test_expect_success 'three-way not complaining on an untracked path in both' ' echo >file2 file two is untracked on the master side && echo >subdir/file2 file two is untracked on the master side && - git-read-tree -m -u branch-point master side + git read-tree -m -u branch-point master side ' test_expect_success 'three-way not clobbering a working tree file' ' @@ -116,4 +116,126 @@ test_expect_success 'three-way not complaining on an untracked file' ' git read-tree -m -u --exclude-per-directory=.gitignore branch-point master side ' +test_expect_success '3-way not overwriting local changes (setup)' ' + + git reset --hard && + git checkout -b side-a branch-point && + echo >>file1 "new line to be kept in the merge result" && + git commit -a -m "side-a changes file1" && + git checkout -b side-b branch-point && + echo >>file2 "new line to be kept in the merge result" && + git commit -a -m "side-b changes file2" && + git checkout side-a + +' + +test_expect_success '3-way not overwriting local changes (our side)' ' + + # At this point, file1 from side-a should be kept as side-b + # did not touch it. + + git reset --hard && + + echo >>file1 "local changes" && + git read-tree -m -u branch-point side-a side-b && + grep "new line to be kept" file1 && + grep "local changes" file1 + +' + +test_expect_success '3-way not overwriting local changes (their side)' ' + + # At this point, file2 from side-b should be taken as side-a + # did not touch it. + + git reset --hard && + + echo >>file2 "local changes" && + test_must_fail git read-tree -m -u branch-point side-a side-b && + ! grep "new line to be kept" file2 && + grep "local changes" file2 + +' + +test_expect_success SYMLINKS 'funny symlink in work tree' ' + + git reset --hard && + git checkout -b sym-b side-b && + mkdir -p a && + >a/b && + git add a/b && + git commit -m "side adds a/b" && + + rm -fr a && + git checkout -b sym-a side-a && + mkdir -p a && + ln -s ../b a/b && + git add a/b && + git commit -m "we add a/b" && + + git read-tree -m -u sym-a sym-a sym-b + +' + +test_expect_success SYMLINKS 'funny symlink in work tree, un-unlink-able' ' + + rm -fr a b && + git reset --hard && + + git checkout sym-a && + chmod a-w a && + test_must_fail git read-tree -m -u sym-a sym-a sym-b + +' + +# clean-up from the above test +chmod a+w a 2>/dev/null +rm -fr a b + +test_expect_success 'D/F setup' ' + + git reset --hard && + + git checkout side-a && + rm -f subdir/file2 && + mkdir subdir/file2 && + echo qfwfq >subdir/file2/another && + git add subdir/file2/another && + test_tick && + git commit -m "side-a changes file2 to directory" + +' + +test_expect_success 'D/F' ' + + git checkout side-b && + git read-tree -m -u branch-point side-b side-a && + git ls-files -u >actual && + ( + a=$(git rev-parse branch-point:subdir/file2) + b=$(git rev-parse side-a:subdir/file2/another) + echo "100644 $a 1 subdir/file2" + echo "100644 $a 2 subdir/file2" + echo "100644 $b 3 subdir/file2/another" + ) >expect && + test_cmp actual expect + +' + +test_expect_success 'D/F resolve' ' + + git reset --hard && + git checkout side-b && + git merge-resolve branch-point -- side-b side-a + +' + +test_expect_success 'D/F recursive' ' + + git reset --hard && + git checkout side-b && + git merge-recursive branch-point -- side-b side-a + +' + test_done diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh new file mode 100755 index 0000000000..849911683a --- /dev/null +++ b/t/t1005-read-tree-reset.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='read-tree -u --reset' + +. ./test-lib.sh + +# two-tree test + +test_expect_success 'setup' ' + git init && + mkdir df && + echo content >df/file && + git add df/file && + git commit -m one && + git ls-files >expect && + rm -rf df && + echo content >df && + git add df && + echo content >new && + git add new && + git commit -m two +' + +test_expect_success 'reset should work' ' + git read-tree -u --reset HEAD^ && + git ls-files >actual && + test_cmp expect actual +' + +test_expect_success 'reset should remove remnants from a failed merge' ' + git read-tree --reset -u HEAD && + git ls-files -s >expect && + sha1=$(git rev-parse :new) && + ( + echo "100644 $sha1 1 old" + echo "100644 $sha1 3 old" + ) | git update-index --index-info && + >old && + git ls-files -s && + git read-tree --reset -u HEAD && + git ls-files -s >actual && + ! test -f old +' + +test_expect_success 'Porcelain reset should remove remnants too' ' + git read-tree --reset -u HEAD && + git ls-files -s >expect && + sha1=$(git rev-parse :new) && + ( + echo "100644 $sha1 1 old" + echo "100644 $sha1 3 old" + ) | git update-index --index-info && + >old && + git ls-files -s && + git reset --hard && + git ls-files -s >actual && + ! test -f old +' + +test_expect_success 'Porcelain checkout -f should remove remnants too' ' + git read-tree --reset -u HEAD && + git ls-files -s >expect && + sha1=$(git rev-parse :new) && + ( + echo "100644 $sha1 1 old" + echo "100644 $sha1 3 old" + ) | git update-index --index-info && + >old && + git ls-files -s && + git checkout -f && + git ls-files -s >actual && + ! test -f old +' + +test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' ' + git read-tree --reset -u HEAD && + git ls-files -s >expect && + sha1=$(git rev-parse :new) && + ( + echo "100644 $sha1 1 old" + echo "100644 $sha1 3 old" + ) | git update-index --index-info && + >old && + git ls-files -s && + git checkout -f HEAD && + git ls-files -s >actual && + ! test -f old +' + +test_done diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh new file mode 100755 index 0000000000..d8b7f2ffbc --- /dev/null +++ b/t/t1006-cat-file.sh @@ -0,0 +1,244 @@ +#!/bin/sh + +test_description='git cat-file' + +. ./test-lib.sh + +echo_without_newline () { + printf '%s' "$*" +} + +strlen () { + echo_without_newline "$1" | wc -c | sed -e 's/^ *//' +} + +maybe_remove_timestamp () { + if test -z "$2"; then + echo_without_newline "$1" + else + echo_without_newline "$(printf '%s\n' "$1" | sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//')" + fi +} + +run_tests () { + type=$1 + sha1=$2 + size=$3 + content=$4 + pretty_content=$5 + no_ts=$6 + + batch_output="$sha1 $type $size +$content" + + test_expect_success "$type exists" ' + git cat-file -e $sha1 + ' + + test_expect_success "Type of $type is correct" ' + test $type = "$(git cat-file -t $sha1)" + ' + + test_expect_success "Size of $type is correct" ' + test $size = "$(git cat-file -s $sha1)" + ' + + test -z "$content" || + test_expect_success "Content of $type is correct" ' + expect="$(maybe_remove_timestamp "$content" $no_ts)" + actual="$(maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts)" + + if test "z$expect" = "z$actual" + then + : happy + else + echo "Oops: expected $expect" + echo "but got $actual" + false + fi + ' + + test_expect_success "Pretty content of $type is correct" ' + expect="$(maybe_remove_timestamp "$pretty_content" $no_ts)" + actual="$(maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts)" + if test "z$expect" = "z$actual" + then + : happy + else + echo "Oops: expected $expect" + echo "but got $actual" + false + fi + ' + + test -z "$content" || + test_expect_success "--batch output of $type is correct" ' + expect="$(maybe_remove_timestamp "$batch_output" $no_ts)" + actual="$(maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts)" + if test "z$expect" = "z$actual" + then + : happy + else + echo "Oops: expected $expect" + echo "but got $actual" + false + fi + ' + + test_expect_success "--batch-check output of $type is correct" ' + expect="$sha1 $type $size" + actual="$(echo_without_newline $sha1 | git cat-file --batch-check)" + if test "z$expect" = "z$actual" + then + : happy + else + echo "Oops: expected $expect" + echo "but got $actual" + false + fi + ' +} + +hello_content="Hello World" +hello_size=$(strlen "$hello_content") +hello_sha1=$(echo_without_newline "$hello_content" | git hash-object --stdin) + +test_expect_success "setup" ' + echo_without_newline "$hello_content" > hello && + git update-index --add hello +' + +run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content" + +tree_sha1=$(git write-tree) +tree_size=33 +tree_pretty_content="100644 blob $hello_sha1 hello" + +run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content" + +commit_message="Intial commit" +commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1) +commit_size=176 +commit_content="tree $tree_sha1 +author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000 + +$commit_message" + +run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1 + +tag_header_without_timestamp="object $hello_sha1 +type blob +tag hellotag +tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +tag_description="This is a tag" +tag_content="$tag_header_without_timestamp 0000000000 +0000 + +$tag_description" +tag_pretty_content="$tag_header_without_timestamp Thu Jan 1 00:00:00 1970 +0000 + +$tag_description" + +tag_sha1=$(echo_without_newline "$tag_content" | git mktag) +tag_size=$(strlen "$tag_content") + +run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_pretty_content" 1 + +test_expect_success \ + "Reach a blob from a tag pointing to it" \ + "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\"" + +for batch in batch batch-check +do + for opt in t s e p + do + test_expect_success "Passing -$opt with --$batch fails" ' + test_must_fail git cat-file --$batch -$opt $hello_sha1 + ' + + test_expect_success "Passing --$batch with -$opt fails" ' + test_must_fail git cat-file -$opt --$batch $hello_sha1 + ' + done + + test_expect_success "Passing <type> with --$batch fails" ' + test_must_fail git cat-file --$batch blob $hello_sha1 + ' + + test_expect_success "Passing --$batch with <type> fails" ' + test_must_fail git cat-file blob --$batch $hello_sha1 + ' + + test_expect_success "Passing sha1 with --$batch fails" ' + test_must_fail git cat-file --$batch $hello_sha1 + ' +done + +test_expect_success "--batch-check for a non-existent named object" ' + test "foobar42 missing +foobar84 missing" = \ + "$( ( echo foobar42; echo_without_newline foobar84; ) | git cat-file --batch-check)" +' + +test_expect_success "--batch-check for a non-existent hash" ' + test "0000000000000000000000000000000000000042 missing +0000000000000000000000000000000000000084 missing" = \ + "$( ( echo 0000000000000000000000000000000000000042; + echo_without_newline 0000000000000000000000000000000000000084; ) \ + | git cat-file --batch-check)" +' + +test_expect_success "--batch for an existent and a non-existent hash" ' + test "$tag_sha1 tag $tag_size +$tag_content +0000000000000000000000000000000000000000 missing" = \ + "$( ( echo $tag_sha1; + echo_without_newline 0000000000000000000000000000000000000000; ) \ + | git cat-file --batch)" +' + +test_expect_success "--batch-check for an emtpy line" ' + test " missing" = "$(echo | git cat-file --batch-check)" +' + +batch_input="$hello_sha1 +$commit_sha1 +$tag_sha1 +deadbeef + +" + +batch_output="$hello_sha1 blob $hello_size +$hello_content +$commit_sha1 commit $commit_size +$commit_content +$tag_sha1 tag $tag_size +$tag_content +deadbeef missing + missing" + +test_expect_success '--batch with multiple sha1s gives correct format' ' + test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)" +' + +batch_check_input="$hello_sha1 +$tree_sha1 +$commit_sha1 +$tag_sha1 +deadbeef + +" + +batch_check_output="$hello_sha1 blob $hello_size +$tree_sha1 tree $tree_size +$commit_sha1 commit $commit_size +$tag_sha1 tag $tag_size +deadbeef missing + missing" + +test_expect_success "--batch-check with multiple sha1s gives correct format" ' + test "$batch_check_output" = \ + "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)" +' + +test_done diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh new file mode 100755 index 0000000000..dd32432d62 --- /dev/null +++ b/t/t1007-hash-object.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +test_description="git hash-object" + +. ./test-lib.sh + +echo_without_newline() { + printf '%s' "$*" +} + +test_blob_does_not_exist() { + test_expect_success 'blob does not exist in database' " + test_must_fail git cat-file blob $1 + " +} + +test_blob_exists() { + test_expect_success 'blob exists in database' " + git cat-file blob $1 + " +} + +hello_content="Hello World" +hello_sha1=5e1c309dae7f45e0f39b1bf3ac3cd9db12e7d689 + +example_content="This is an example" +example_sha1=ddd3f836d3e3fbb7ae289aa9ae83536f76956399 + +setup_repo() { + echo_without_newline "$hello_content" > hello + echo_without_newline "$example_content" > example +} + +test_repo=test +push_repo() { + test_create_repo $test_repo + cd $test_repo + + setup_repo +} + +pop_repo() { + cd .. + rm -rf $test_repo +} + +setup_repo + +# Argument checking + +test_expect_success "multiple '--stdin's are rejected" ' + echo example | test_must_fail git hash-object --stdin --stdin +' + +test_expect_success "Can't use --stdin and --stdin-paths together" ' + echo example | test_must_fail git hash-object --stdin --stdin-paths && + echo example | test_must_fail git hash-object --stdin-paths --stdin +' + +test_expect_success "Can't pass filenames as arguments with --stdin-paths" ' + echo example | test_must_fail git hash-object --stdin-paths hello +' + +test_expect_success "Can't use --path with --stdin-paths" ' + echo example | test_must_fail git hash-object --stdin-paths --path=foo +' + +test_expect_success "Can't use --path with --no-filters" ' + test_must_fail git hash-object --no-filters --path=foo +' + +# Behavior + +push_repo + +test_expect_success 'hash a file' ' + test $hello_sha1 = $(git hash-object hello) +' + +test_blob_does_not_exist $hello_sha1 + +test_expect_success 'hash from stdin' ' + test $example_sha1 = $(git hash-object --stdin < example) +' + +test_blob_does_not_exist $example_sha1 + +test_expect_success 'hash a file and write to database' ' + test $hello_sha1 = $(git hash-object -w hello) +' + +test_blob_exists $hello_sha1 + +test_expect_success 'git hash-object --stdin file1 <file0 first operates on file0, then file1' ' + echo foo > file1 && + obname0=$(echo bar | git hash-object --stdin) && + obname1=$(git hash-object file1) && + obname0new=$(echo bar | git hash-object --stdin file1 | sed -n -e 1p) && + obname1new=$(echo bar | git hash-object --stdin file1 | sed -n -e 2p) && + test "$obname0" = "$obname0new" && + test "$obname1" = "$obname1new" +' + +test_expect_success 'check that appropriate filter is invoke when --path is used' ' + echo fooQ | tr Q "\\015" >file0 && + cp file0 file1 && + echo "file0 -crlf" >.gitattributes && + echo "file1 crlf" >>.gitattributes && + git config core.autocrlf true && + file0_sha=$(git hash-object file0) && + file1_sha=$(git hash-object file1) && + test "$file0_sha" != "$file1_sha" && + path1_sha=$(git hash-object --path=file1 file0) && + path0_sha=$(git hash-object --path=file0 file1) && + test "$file0_sha" = "$path0_sha" && + test "$file1_sha" = "$path1_sha" && + path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) && + path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) && + test "$file0_sha" = "$path0_sha" && + test "$file1_sha" = "$path1_sha" && + git config --unset core.autocrlf +' + +test_expect_success 'check that --no-filters option works' ' + echo fooQ | tr Q "\\015" >file0 && + cp file0 file1 && + echo "file0 -crlf" >.gitattributes && + echo "file1 crlf" >>.gitattributes && + git config core.autocrlf true && + file0_sha=$(git hash-object file0) && + file1_sha=$(git hash-object file1) && + test "$file0_sha" != "$file1_sha" && + nofilters_file1=$(git hash-object --no-filters file1) && + test "$file0_sha" = "$nofilters_file1" && + nofilters_file1=$(cat file1 | git hash-object --stdin) && + test "$file0_sha" = "$nofilters_file1" && + git config --unset core.autocrlf +' + +test_expect_success 'check that --no-filters option works with --stdin-paths' ' + echo fooQ | tr Q "\\015" >file0 && + cp file0 file1 && + echo "file0 -crlf" >.gitattributes && + echo "file1 crlf" >>.gitattributes && + git config core.autocrlf true && + file0_sha=$(git hash-object file0) && + file1_sha=$(git hash-object file1) && + test "$file0_sha" != "$file1_sha" && + nofilters_file1=$(echo "file1" | git hash-object --stdin-paths --no-filters) && + test "$file0_sha" = "$nofilters_file1" && + git config --unset core.autocrlf +' + +pop_repo + +for args in "-w --stdin" "--stdin -w"; do + push_repo + + test_expect_success "hash from stdin and write to database ($args)" ' + test $example_sha1 = $(git hash-object $args < example) + ' + + test_blob_exists $example_sha1 + + pop_repo +done + +filenames="hello +example" + +sha1s="$hello_sha1 +$example_sha1" + +test_expect_success "hash two files with names on stdin" ' + test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object --stdin-paths)" +' + +for args in "-w --stdin-paths" "--stdin-paths -w"; do + push_repo + + test_expect_success "hash two files with names on stdin and write to database ($args)" ' + test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object $args)" + ' + + test_blob_exists $hello_sha1 + test_blob_exists $example_sha1 + + pop_repo +done + +test_done diff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh new file mode 100755 index 0000000000..f9e00285db --- /dev/null +++ b/t/t1008-read-tree-overlay.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='test multi-tree read-tree without merging' + +. ./test-lib.sh + +test_expect_success setup ' + echo one >a && + git add a && + git commit -m initial && + git tag initial && + echo two >b && + git add b && + git commit -m second && + git checkout -b side initial && + echo three >a && + mkdir b && + echo four >b/c && + git add b/c && + git commit -m third +' + +test_expect_success 'multi-read' ' + git read-tree initial master side && + (echo a; echo b/c) >expect && + git ls-files >actual && + test_cmp expect actual +' + +test_done + diff --git a/t/t1009-read-tree-new-index.sh b/t/t1009-read-tree-new-index.sh new file mode 100755 index 0000000000..59b3aa4bc4 --- /dev/null +++ b/t/t1009-read-tree-new-index.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +test_description='test read-tree into a fresh index file' + +. ./test-lib.sh + +test_expect_success setup ' + echo one >a && + git add a && + git commit -m initial +' + +test_expect_success 'non-existent index file' ' + rm -f new-index && + GIT_INDEX_FILE=new-index git read-tree master +' + +test_expect_success 'empty index file' ' + rm -f new-index && + > new-index && + GIT_INDEX_FILE=new-index git read-tree master +' + +test_done + diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh new file mode 100755 index 0000000000..b946f87686 --- /dev/null +++ b/t/t1010-mktree.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='git mktree' + +. ./test-lib.sh + +test_expect_success setup ' + for d in a a. a0 + do + mkdir "$d" && echo "$d/one" >"$d/one" && + git add "$d" + done && + echo zero >one && + git update-index --add --info-only one && + git write-tree --missing-ok >tree.missing && + git ls-tree $(cat tree.missing) >top.missing && + git ls-tree -r $(cat tree.missing) >all.missing && + echo one >one && + git add one && + git write-tree >tree && + git ls-tree $(cat tree) >top && + git ls-tree -r $(cat tree) >all && + test_tick && + git commit -q -m one && + H=$(git rev-parse HEAD) && + git update-index --add --cacheinfo 160000 $H sub && + test_tick && + git commit -q -m two && + git rev-parse HEAD^{tree} >tree.withsub && + git ls-tree HEAD >top.withsub && + git ls-tree -r HEAD >all.withsub +' + +test_expect_success 'ls-tree piped to mktree (1)' ' + git mktree <top >actual && + test_cmp tree actual +' + +test_expect_success 'ls-tree piped to mktree (2)' ' + git mktree <top.withsub >actual && + test_cmp tree.withsub actual +' + +test_expect_success 'ls-tree output in wrong order given to mktree (1)' ' + perl -e "print reverse <>" <top | + git mktree >actual && + test_cmp tree actual +' + +test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' + perl -e "print reverse <>" <top.withsub | + git mktree >actual && + test_cmp tree.withsub actual +' + +test_expect_success 'allow missing object with --missing' ' + git mktree --missing <top.missing >actual && + test_cmp tree.missing actual +' + +test_expect_success 'mktree refuses to read ls-tree -r output (1)' ' + test_must_fail git mktree <all >actual +' + +test_expect_success 'mktree refuses to read ls-tree -r output (2)' ' + test_must_fail git mktree <all.withsub >actual +' + +test_done diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh new file mode 100755 index 0000000000..62246dbf95 --- /dev/null +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -0,0 +1,150 @@ +#!/bin/sh + +test_description='sparse checkout tests' + +. ./test-lib.sh + +cat >expected <<EOF +100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t +100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added +EOF +test_expect_success 'setup' ' + test_commit init && + echo modified >> init.t && + mkdir sub && + touch sub/added && + git add init.t sub/added && + git commit -m "modified and added" && + git tag top && + git rm sub/added && + git commit -m removed && + git tag removed && + git checkout top && + 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 && + test_cmp expected 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 + git read-tree -m -u HEAD && + git ls-files -t > result && + test_cmp expected.swt result && + test -f init.t && + test -f sub/added +' + +test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' ' + git config core.sparsecheckout true && + echo > .git/info/sparse-checkout && + git read-tree --no-sparse-checkout -m -u HEAD && + git ls-files -t > result && + test_cmp expected.swt result && + test -f init.t && + test -f sub/added +' + +test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' + git config core.sparsecheckout true && + echo > .git/info/sparse-checkout && + test_must_fail git read-tree -m -u HEAD && + git ls-files --stage > result && + test_cmp expected 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' ' + echo sub/ > .git/info/sparse-checkout && + git read-tree -m -u HEAD && + 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 +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 && + git read-tree -m -u HEAD && + 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 && + git read-tree -m -u HEAD && + git ls-files -t > result && + test_cmp expected.swt 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 && + 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 && + git checkout -f top && + 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 && + git checkout -f top && + 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 && + 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 && + git checkout -f removed && + mkdir sub && + echo dirty > sub/added && + git read-tree -u -m HEAD^ && + grep -q dirty sub/added +' + +test_done diff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh new file mode 100755 index 0000000000..9811d467da --- /dev/null +++ b/t/t1012-read-tree-df.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='read-tree D/F conflict corner cases' + +. ./test-lib.sh + +maketree () { + ( + rm -f .git/index .git/index.lock && + git clean -d -f -f -q -x && + name="$1" && + shift && + for it + do + path=$(expr "$it" : '\([^:]*\)') && + mkdir -p $(dirname "$path") && + echo "$it" >"$path" && + git update-index --add "$path" || exit + done && + git tag "$name" $(git write-tree) + ) +} + +settree () { + rm -f .git/index .git/index.lock && + git clean -d -f -f -q -x && + git read-tree "$1" && + git checkout-index -f -q -u -a && + git update-index --refresh +} + +checkindex () { + git ls-files -s | + sed "s|^[0-7][0-7]* $_x40 \([0-3]\) |\1 |" >current && + cat >expect && + test_cmp expect current +} + +test_expect_success setup ' + maketree O-000 a/b-2/c/d a/b/c/d a/x && + maketree A-000 a/b-2/c/d a/b/c/d a/x && + maketree A-001 a/b-2/c/d a/b/c/d a/b/c/e a/x && + maketree B-000 a/b-2/c/d a/b a/x && + + maketree O-010 t-0 t/1 t/2 t=3 && + maketree A-010 t-0 t t=3 && + maketree B-010 t/1: t=3: && + + maketree O-020 ds/dma/ioat.c ds/dma/ioat_dca.c && + maketree A-020 ds/dma/ioat/Makefile ds/dma/ioat/registers.h && + : +' + +test_expect_success '3-way (1)' ' + settree A-000 && + git read-tree -m -u O-000 A-000 B-000 && + checkindex <<-EOF + 3 a/b + 0 a/b-2/c/d + 1 a/b/c/d + 2 a/b/c/d + 0 a/x + EOF +' + +test_expect_success '3-way (2)' ' + settree A-001 && + git read-tree -m -u O-000 A-001 B-000 && + checkindex <<-EOF + 3 a/b + 0 a/b-2/c/d + 1 a/b/c/d + 2 a/b/c/d + 2 a/b/c/e + 0 a/x + EOF +' + +test_expect_success '3-way (3)' ' + settree A-010 && + git read-tree -m -u O-010 A-010 B-010 && + checkindex <<-EOF + 2 t + 1 t-0 + 2 t-0 + 1 t/1 + 3 t/1 + 1 t/2 + 0 t=3 + EOF +' + +test_expect_success '2-way (1)' ' + settree O-020 && + git read-tree -m -u O-020 A-020 && + checkindex <<-EOF + 0 ds/dma/ioat/Makefile + 0 ds/dma/ioat/registers.h + EOF +' + +test_done diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 1e8f9e59df..56874996a6 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -21,113 +21,113 @@ 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 ;; + cd "$HERE" && + git update-index --add one && + case "`git ls-files`" in + one) echo pass one ;; *) echo bad one; exit 1 ;; esac && cd dir && - git-update-index --add two && - case "`git-ls-files`" in - two) echo ok two ;; + git update-index --add two && + case "`git ls-files`" in + two) echo pass two ;; *) echo bad two; exit 1 ;; esac && cd .. && - case "`git-ls-files`" in - dir/two"$LF"one) echo ok both ;; + case "`git ls-files`" in + 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` && + 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 && + git cat-file -p "$two" >actual && cmp dir/two actual && cd dir && - git-cat-file -p "$two" >actual && + git cat-file -p "$two" >actual && cmp two actual ' rm -f actual dir/actual test_expect_success 'diff-files' ' - cd $HERE && + cd "$HERE" && echo a >>one && echo d >>dir/two && - case "`git-diff-files --name-only`" in - dir/two"$LF"one) echo ok top ;; + case "`git diff-files --name-only`" in + 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 ;; + 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 ok subdir limited ;; + 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` && + cd "$HERE" && + top=`git write-tree` && echo $top && cd dir && - sub=`git-write-tree` && + sub=`git write-tree` && echo $sub && test "z$top" = "z$sub" ' test_expect_success 'checkout-index' ' - cd $HERE && - git-checkout-index -f -u one && + cd "$HERE" && + git checkout-index -f -u one && cmp one original.one && cd dir && - git-checkout-index -f -u two && + git checkout-index -f -u two && cmp two ../original.two ' test_expect_success 'read-tree' ' - cd $HERE && + cd "$HERE" && rm -f one dir/two && - tree=`git-write-tree` && - git-read-tree --reset -u "$tree" && + 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" && + 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 && + cd "$HERE" && git commit -a -m 1 && - cd $HERE/.git && + cd "$HERE"/.git && git show -s HEAD ' test_expect_success 'no file/rev ambiguity check inside a bare repo' ' - cd $HERE && + cd "$HERE" && git clone -s --bare .git foo.git && 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 && + cd "$HERE" && git clone -s --bare .git foo.git && cd foo.git && git show -s HEAD ' -test_expect_success 'detection should not be fooled by a symlink' ' - cd $HERE && +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 && diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index 19a0ed4d20..c4414ff576 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -3,9 +3,9 @@ # Copyright (C) 2005 Rene Scharfe # -test_description='git-commit-tree options test +test_description='git commit-tree options test -This test checks that git-commit-tree can create a specific commit +This test checks that git commit-tree can create a specific commit object by defining all environment variables that it understands. ' @@ -21,7 +21,7 @@ EOF test_expect_success \ 'test preparation: write empty tree' \ - 'git-write-tree >treeid' + 'git write-tree >treeid' test_expect_success \ 'construct commit' \ @@ -32,14 +32,14 @@ test_expect_success \ GIT_COMMITTER_NAME="Committer Name" \ GIT_COMMITTER_EMAIL="committer@email" \ GIT_COMMITTER_DATE="2005-05-26 23:30" \ - TZ=GMT git-commit-tree `cat treeid` >commitid 2>/dev/null' + TZ=GMT git commit-tree `cat treeid` >commitid 2>/dev/null' test_expect_success \ 'read commit' \ - 'git-cat-file commit `cat commitid` >commit' + 'git cat-file commit `cat commitid` >commit' test_expect_success \ 'compare commit' \ - 'diff expected commit' + 'test_cmp expected commit' test_done diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index ca2c30f7af..ab55eda158 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -7,14 +7,18 @@ test_description='A simple turial in the form of a test case' . ./test-lib.sh -echo "Hello World" > hello -echo "Silly example" > example +test_expect_success 'blob' ' + echo "Hello World" > hello && + echo "Silly example" > example && -git-update-index --add hello example + git update-index --add hello example && -test_expect_success 'blob' "test blob = \"$(git-cat-file -t 557db03)\"" + test blob = "$(git cat-file -t 557db03)" +' -test_expect_success 'blob 557db03' "test \"Hello World\" = \"$(git-cat-file blob 557db03)\"" +test_expect_success 'blob 557db03' ' + test "Hello World" = "$(git cat-file blob 557db03)" +' echo "It's a new day for git" >>hello cat > diff.expect << EOF @@ -26,25 +30,35 @@ index 557db03..263414f 100644 Hello World +It's a new day for git EOF -git-diff-files -p > diff.output -test_expect_success 'git-diff-files -p' 'cmp diff.expect diff.output' -git diff > diff.output -test_expect_success 'git diff' 'cmp diff.expect diff.output' - -tree=$(git-write-tree 2>/dev/null) -test_expect_success 'tree' "test 8988da15d077d4829fc51d8544c097def6644dbb = $tree" +test_expect_success 'git diff-files -p' ' + git diff-files -p > diff.output && + test_cmp diff.expect diff.output +' -output="$(echo "Initial commit" | git-commit-tree $(git-write-tree) 2>&1 > .git/refs/heads/master)" +test_expect_success 'git diff' ' + git diff > diff.output && + test_cmp diff.expect diff.output +' -git-diff-index -p HEAD > diff.output -test_expect_success 'git-diff-index -p HEAD' 'cmp diff.expect diff.output' +test_expect_success 'tree' ' + tree=$(git write-tree 2>/dev/null) + test 8988da15d077d4829fc51d8544c097def6644dbb = $tree +' -git diff HEAD > diff.output -test_expect_success 'git diff HEAD' 'cmp diff.expect diff.output' +test_expect_success 'git diff-index -p HEAD' ' + test_tick && + tree=$(git write-tree) && + commit=$(echo "Initial commit" | git commit-tree $tree) && + git update-ref HEAD $commit && + git diff-index -p HEAD > diff.output && + test_cmp diff.expect diff.output +' -#rm hello -#test_expect_success 'git-read-tree --reset HEAD' "git-read-tree --reset HEAD ; test \"hello: needs update\" = \"$(git-update-index --refresh)\"" +test_expect_success 'git diff HEAD' ' + git diff HEAD > diff.output && + test_cmp diff.expect diff.output +' cat > whatchanged.expect << EOF commit VARIABLE @@ -69,40 +83,48 @@ index 0000000..557db03 +Hello World EOF -git-whatchanged -p --root | \ - sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \ +test_expect_success 'git whatchanged -p --root' ' + git whatchanged -p --root | + sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \ -e "2,3s/^\(.\{8\}\).*$/\1VARIABLE/" \ -> whatchanged.output -test_expect_success 'git-whatchanged -p --root' 'cmp whatchanged.expect whatchanged.output' - -git tag my-first-tag -test_expect_success 'git tag my-first-tag' 'cmp .git/refs/heads/master .git/refs/tags/my-first-tag' + > whatchanged.output && + test_cmp whatchanged.expect whatchanged.output +' -# TODO: test git-clone +test_expect_success 'git tag my-first-tag' ' + git tag my-first-tag && + test_cmp .git/refs/heads/master .git/refs/tags/my-first-tag +' -git checkout -b mybranch -test_expect_success 'git checkout -b mybranch' 'cmp .git/refs/heads/master .git/refs/heads/mybranch' +test_expect_success 'git checkout -b mybranch' ' + git checkout -b mybranch && + test_cmp .git/refs/heads/master .git/refs/heads/mybranch +' cat > branch.expect <<EOF master * mybranch EOF -git branch > branch.output -test_expect_success 'git branch' 'cmp branch.expect branch.output' +test_expect_success 'git branch' ' + git branch > branch.output && + test_cmp branch.expect branch.output +' -git checkout mybranch -echo "Work, work, work" >>hello -git commit -m 'Some work.' -i hello +test_expect_success 'git resolve now fails' ' + git checkout mybranch && + echo "Work, work, work" >>hello && + test_tick && + git commit -m "Some work." -i hello && -git checkout master + git checkout master && -echo "Play, play, play" >>hello -echo "Lots of fun" >>example -git commit -m 'Some fun.' -i hello example + echo "Play, play, play" >>hello && + echo "Lots of fun" >>example && + test_tick && + git commit -m "Some fun." -i hello example && -test_expect_failure 'git resolve now fails' ' - git merge -m "Merge work in mybranch" mybranch + test_must_fail git merge -m "Merge work in mybranch" mybranch ' cat > hello << EOF @@ -112,51 +134,132 @@ Play, play, play Work, work, work EOF -git commit -m 'Merged "mybranch" changes.' -i hello - -test_done - cat > show-branch.expect << EOF -* [master] Merged "mybranch" changes. +* [master] Merge work in mybranch ! [mybranch] Some work. -- -- [master] Merged "mybranch" changes. +- [master] Merge work in mybranch *+ [mybranch] Some work. +* [master^] Some fun. EOF -git show-branch --topo-order master mybranch > show-branch.output -test_expect_success 'git show-branch' 'cmp show-branch.expect show-branch.output' - -git checkout mybranch +test_expect_success 'git show-branch' ' + test_tick && + git commit -m "Merge work in mybranch" -i hello && + git show-branch --topo-order --more=1 master mybranch \ + > show-branch.output && + test_cmp show-branch.expect show-branch.output +' cat > resolve.expect << EOF -Updating from VARIABLE to VARIABLE +Updating VARIABLE..VARIABLE +FASTFORWARD (no commit created; -m option ignored) example | 1 + hello | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) EOF -git merge -s "Merge upstream changes." master | \ - sed -e "1s/[0-9a-f]\{40\}/VARIABLE/g" >resolve.output -test_expect_success 'git resolve' 'cmp resolve.expect resolve.output' +test_expect_success 'git resolve' ' + git checkout mybranch && + git merge -m "Merge upstream changes." master | + sed -e "1s/[0-9a-f]\{7\}/VARIABLE/g" \ + -e "s/^Fast[- ]forward /FASTFORWARD /" >resolve.output && + test_cmp resolve.expect resolve.output +' cat > show-branch2.expect << EOF -! [master] Merged "mybranch" changes. - * [mybranch] Merged "mybranch" changes. +! [master] Merge work in mybranch + * [mybranch] Merge work in mybranch +-- +-- [master] Merge work in mybranch +EOF + +test_expect_success 'git show-branch (part 2)' ' + git show-branch --topo-order master mybranch > show-branch2.output && + test_cmp show-branch2.expect show-branch2.output +' + +cat > show-branch3.expect << EOF +! [master] Merge work in mybranch + * [mybranch] Merge work in mybranch -- --- [master] Merged "mybranch" changes. +-- [master] Merge work in mybranch ++* [master^2] Some work. ++* [master^] Some fun. EOF -git show-branch --topo-order master mybranch > show-branch2.output -test_expect_success 'git show-branch' 'cmp show-branch2.expect show-branch2.output' +test_expect_success 'git show-branch (part 3)' ' + git show-branch --topo-order --more=2 master mybranch \ + > show-branch3.output && + test_cmp show-branch3.expect show-branch3.output +' + +test_expect_success 'rewind to "Some fun." and "Some work."' ' + git checkout mybranch && + git reset --hard master^2 && + git checkout master && + git reset --hard master^ +' + +cat > show-branch4.expect << EOF +* [master] Some fun. + ! [mybranch] Some work. +-- +* [master] Some fun. + + [mybranch] Some work. +*+ [master^] Initial commit +EOF + +test_expect_success 'git show-branch (part 4)' ' + git show-branch --topo-order > show-branch4.output && + test_cmp show-branch4.expect show-branch4.output +' + +test_expect_success 'manual merge' ' + mb=$(git merge-base HEAD mybranch) && + git name-rev --name-only --tags $mb > name-rev.output && + test "my-first-tag" = $(cat name-rev.output) && + + git read-tree -m -u $mb HEAD mybranch +' -# TODO: test git fetch +cat > ls-files.expect << EOF +100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example +100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello +100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello +EOF + +test_expect_success 'git ls-files --stage' ' + git ls-files --stage > ls-files.output && + test_cmp ls-files.expect ls-files.output +' + +cat > ls-files-unmerged.expect << EOF +100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello +100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello +EOF + +test_expect_success 'git ls-files --unmerged' ' + git ls-files --unmerged > ls-files-unmerged.output && + test_cmp ls-files-unmerged.expect ls-files-unmerged.output +' + +test_expect_success 'git-merge-index' ' + test_must_fail git merge-index git-merge-one-file hello +' -# TODO: test git push +test_expect_success 'git ls-files --stage (part 2)' ' + git ls-files --stage > ls-files.output2 && + test_cmp ls-files.expect ls-files.output2 +' test_expect_success 'git repack' 'git repack' test_expect_success 'git prune-packed' 'git prune-packed' -test_expect_failure '-> only packed objects' 'find -type f .git/objects/[0-9a-f][0-9a-f]' +test_expect_success '-> only packed objects' ' + git prune && # Remove conflict marked blobs + test $(find .git/objects/[0-9a-f][0-9a-f] -type f -print 2>/dev/null | wc -l) = 0 +' test_done - diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 49b5666b33..074f2f2e3e 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -3,13 +3,13 @@ # Copyright (c) 2005 Johannes Schindelin # -test_description='Test git-config in different settings' +test_description='Test git config in different settings' . ./test-lib.sh test -f .git/config && rm .git/config -git-config core.penguin "little blue" +git config core.penguin "little blue" cat > expect << EOF [core] @@ -18,7 +18,7 @@ EOF test_expect_success 'initial' 'cmp .git/config expect' -git-config Core.Movie BadPhysics +git config Core.Movie BadPhysics cat > expect << EOF [core] @@ -28,7 +28,7 @@ EOF test_expect_success 'mixed case' 'cmp .git/config expect' -git-config Cores.WhatEver Second +git config Cores.WhatEver Second cat > expect << EOF [core] @@ -40,7 +40,7 @@ EOF test_expect_success 'similar section' 'cmp .git/config expect' -git-config CORE.UPPERCASE true +git config CORE.UPPERCASE true cat > expect << EOF [core] @@ -54,10 +54,10 @@ EOF test_expect_success 'similar section' 'cmp .git/config expect' test_expect_success 'replace with non-match' \ - 'git-config core.penguin kingpin !blue' + 'git config core.penguin kingpin !blue' test_expect_success 'replace with non-match (actually matching)' \ - 'git-config core.penguin "very blue" !kingpin' + 'git config core.penguin "very blue" !kingpin' cat > expect << EOF [core] @@ -71,6 +71,25 @@ EOF test_expect_success 'non-match result' 'cmp .git/config expect' +cat > .git/config <<\EOF +[alpha] +bar = foo +[beta] +baz = multiple \ +lines +EOF + +test_expect_success 'unset with cont. lines' \ + 'git config --unset beta.baz' + +cat > expect <<\EOF +[alpha] +bar = foo +[beta] +EOF + +test_expect_success 'unset with cont. lines is correct' 'cmp .git/config expect' + cat > .git/config << EOF [beta] ; silly comment # another comment noIndent= sillyValue ; 'nother silly comment @@ -86,7 +105,7 @@ EOF cp .git/config .git/config2 test_expect_success 'multiple unset' \ - 'git-config --unset-all beta.haha' + 'git config --unset-all beta.haha' cat > expect << EOF [beta] ; silly comment # another comment @@ -99,10 +118,17 @@ EOF test_expect_success 'multiple unset is correct' 'cmp .git/config expect' -mv .git/config2 .git/config +cp .git/config2 .git/config + +test_expect_success '--replace-all missing value' ' + test_must_fail git config --replace-all beta.haha && + test_cmp .git/config2 .git/config +' + +rm .git/config2 test_expect_success '--replace-all' \ - 'git-config --replace-all beta.haha gamma' + 'git config --replace-all beta.haha gamma' cat > expect << EOF [beta] ; silly comment # another comment @@ -116,7 +142,7 @@ EOF test_expect_success 'all replaced' 'cmp .git/config expect' -git-config beta.haha alpha +git config beta.haha alpha cat > expect << EOF [beta] ; silly comment # another comment @@ -130,7 +156,7 @@ EOF test_expect_success 'really mean test' 'cmp .git/config expect' -git-config nextsection.nonewline wow +git config nextsection.nonewline wow cat > expect << EOF [beta] ; silly comment # another comment @@ -145,8 +171,8 @@ EOF test_expect_success 'really really mean test' 'cmp .git/config expect' -test_expect_success 'get value' 'test alpha = $(git-config beta.haha)' -git-config --unset beta.haha +test_expect_success 'get value' 'test alpha = $(git config beta.haha)' +git config --unset beta.haha cat > expect << EOF [beta] ; silly comment # another comment @@ -160,7 +186,7 @@ EOF test_expect_success 'unset' 'cmp .git/config expect' -git-config nextsection.NoNewLine "wow2 for me" "for me$" +git config nextsection.NoNewLine "wow2 for me" "for me$" cat > expect << EOF [beta] ; silly comment # another comment @@ -176,18 +202,19 @@ EOF test_expect_success 'multivar' 'cmp .git/config expect' test_expect_success 'non-match' \ - 'git-config --get nextsection.nonewline !for' + 'git config --get nextsection.nonewline !for' test_expect_success 'non-match value' \ - 'test wow = $(git-config --get nextsection.nonewline !for)' + 'test wow = $(git config --get nextsection.nonewline !for)' -test_expect_failure 'ambiguous get' \ - 'git-config --get nextsection.nonewline' +test_expect_success 'ambiguous get' ' + test_must_fail git config --get nextsection.nonewline +' test_expect_success 'get multivar' \ - 'git-config --get-all nextsection.nonewline' + 'git config --get-all nextsection.nonewline' -git-config nextsection.nonewline "wow3" "wow$" +git config nextsection.nonewline "wow3" "wow$" cat > expect << EOF [beta] ; silly comment # another comment @@ -202,15 +229,19 @@ EOF test_expect_success 'multivar replace' 'cmp .git/config expect' -test_expect_failure 'ambiguous value' 'git-config nextsection.nonewline' +test_expect_success 'ambiguous value' ' + test_must_fail git config nextsection.nonewline +' -test_expect_failure 'ambiguous unset' \ - 'git-config --unset nextsection.nonewline' +test_expect_success 'ambiguous unset' ' + test_must_fail git config --unset nextsection.nonewline +' -test_expect_failure 'invalid unset' \ - 'git-config --unset somesection.nonewline' +test_expect_success 'invalid unset' ' + test_must_fail git config --unset somesection.nonewline +' -git-config --unset nextsection.nonewline "wow3$" +git config --unset nextsection.nonewline "wow3$" cat > expect << EOF [beta] ; silly comment # another comment @@ -224,12 +255,12 @@ EOF test_expect_success 'multivar unset' 'cmp .git/config expect' -test_expect_failure 'invalid key' 'git-config inval.2key blabla' +test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla' -test_expect_success 'correct key' 'git-config 123456.a123 987' +test_expect_success 'correct key' 'git config 123456.a123 987' test_expect_success 'hierarchical section' \ - 'git-config Version.1.2.3eX.Alpha beta' + 'git config Version.1.2.3eX.Alpha beta' cat > expect << EOF [beta] ; silly comment # another comment @@ -255,7 +286,7 @@ version.1.2.3eX.alpha=beta EOF test_expect_success 'working --list' \ - 'git-config --list > output && cmp output expect' + 'git config --list > output && cmp output expect' cat > expect << EOF beta.noindent sillyValue @@ -263,9 +294,9 @@ nextsection.nonewline wow2 for me EOF test_expect_success '--get-regexp' \ - 'git-config --get-regexp in > output && cmp output expect' + 'git config --get-regexp in > output && cmp output expect' -git-config --add nextsection.nonewline "wow4 for you" +git config --add nextsection.nonewline "wow4 for you" cat > expect << EOF wow2 for me @@ -273,27 +304,56 @@ wow4 for you EOF test_expect_success '--add' \ - 'git-config --get-all nextsection.nonewline > output && cmp output expect' + 'git config --get-all nextsection.nonewline > output && cmp output expect' cat > .git/config << EOF [novalue] variable +[emptyvalue] + variable = EOF test_expect_success 'get variable with no value' \ - 'git-config --get novalue.variable ^$' + 'git config --get novalue.variable ^$' + +test_expect_success 'get variable with empty value' \ + 'git config --get emptyvalue.variable ^$' + +echo novalue.variable > expect + +test_expect_success 'get-regexp variable with no value' \ + 'git config --get-regexp novalue > output && + cmp output expect' -git-config > output 2>&1 +echo 'emptyvalue.variable ' > expect -test_expect_success 'no arguments, but no crash' \ - "test $? = 129 && grep usage output" +test_expect_success 'get-regexp variable with empty value' \ + 'git config --get-regexp emptyvalue > output && + cmp output expect' + +echo true > expect + +test_expect_success 'get bool variable with no value' \ + 'git config --bool novalue.variable > output && + cmp output expect' + +echo false > expect + +test_expect_success 'get bool variable with empty value' \ + 'git config --bool emptyvalue.variable > output && + cmp output expect' + +test_expect_success 'no arguments, but no crash' ' + test_must_fail git config >output 2>&1 && + grep usage output +' cat > .git/config << EOF [a.b] c = d EOF -git-config a.x y +git config a.x y cat > expect << EOF [a.b] @@ -304,8 +364,8 @@ EOF test_expect_success 'new section is partial match of another' 'cmp .git/config expect' -git-config b.x y -git-config a.b c +git config b.x y +git config a.b c cat > expect << EOF [a.b] @@ -319,6 +379,9 @@ EOF test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect' +test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' \ + 'test_must_fail git config --file non-existing-config -l' + cat > other-config << EOF [ein] bahn = strasse @@ -328,11 +391,25 @@ cat > expect << EOF ein.bahn=strasse EOF -GIT_CONFIG=other-config git-config -l > output +GIT_CONFIG=other-config git config -l > output test_expect_success 'alternative GIT_CONFIG' 'cmp output expect' -GIT_CONFIG=other-config git-config anwohner.park ausweis +test_expect_success 'alternative GIT_CONFIG (--file)' \ + 'git config --file other-config -l > output && cmp output expect' + +test_expect_success 'refer config from subdirectory' ' + mkdir x && + ( + cd x && + echo strasse >expect + git config --get --file ../other-config ein.bahn >actual && + test_cmp expect actual + ) + +' + +GIT_CONFIG=other-config git config anwohner.park ausweis cat > expect << EOF [ein] @@ -355,7 +432,7 @@ weird EOF test_expect_success "rename section" \ - "git-config --rename-section branch.eins branch.zwei" + "git config --rename-section branch.eins branch.zwei" cat > expect << EOF # Hallo @@ -368,15 +445,17 @@ cat > expect << EOF weird EOF -test_expect_success "rename succeeded" "diff -u expect .git/config" +test_expect_success "rename succeeded" "test_cmp expect .git/config" -test_expect_failure "rename non-existing section" \ - 'git-config --rename-section branch."world domination" branch.drei' +test_expect_success "rename non-existing section" ' + test_must_fail git config --rename-section \ + branch."world domination" branch.drei +' -test_expect_success "rename succeeded" "diff -u expect .git/config" +test_expect_success "rename succeeded" "test_cmp expect .git/config" test_expect_success "rename another section" \ - 'git-config --rename-section branch."1 234 blabl/a" branch.drei' + 'git config --rename-section branch."1 234 blabl/a" branch.drei' cat > expect << EOF # Hallo @@ -389,24 +468,286 @@ cat > expect << EOF weird EOF -test_expect_success "rename succeeded" "diff -u expect .git/config" +test_expect_success "rename succeeded" "test_cmp expect .git/config" + +cat >> .git/config << EOF +[branch "vier"] z = 1 +EOF + +test_expect_success "rename a section with a var on the same line" \ + 'git config --rename-section branch.vier branch.zwei' + +cat > expect << EOF +# Hallo + #Bello +[branch "zwei"] + x = 1 +[branch "zwei"] + y = 1 +[branch "drei"] +weird +[branch "zwei"] + z = 1 +EOF + +test_expect_success "rename succeeded" "test_cmp expect .git/config" + +cat >> .git/config << EOF + [branch "zwei"] a = 1 [branch "vier"] +EOF + +test_expect_success "remove section" "git config --remove-section branch.zwei" + +cat > expect << EOF +# Hallo + #Bello +[branch "drei"] +weird +EOF + +test_expect_success "section was removed properly" \ + "test_cmp expect .git/config" + +rm .git/config + +cat > expect << EOF +[gitcvs] + enabled = true + dbname = %Ggitcvs2.%a.%m.sqlite +[gitcvs "ext"] + dbname = %Ggitcvs1.%a.%m.sqlite +EOF + +test_expect_success 'section ending' ' + + git config gitcvs.enabled true && + git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && + git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && + cmp .git/config expect + +' test_expect_success numbers ' - git-config kilo.gram 1k && - git-config mega.ton 1m && - k=$(git-config --int --get kilo.gram) && + git config kilo.gram 1k && + git config mega.ton 1m && + k=$(git config --int --get kilo.gram) && test z1024 = "z$k" && - m=$(git-config --int --get mega.ton) && + m=$(git config --int --get mega.ton) && test z1048576 = "z$m" ' +cat > expect <<EOF +fatal: bad config value for 'aninvalid.unit' in .git/config +EOF + +test_expect_success 'invalid unit' ' + + git config aninvalid.unit "1auto" && + s=$(git config aninvalid.unit) && + test "z1auto" = "z$s" && + if git config --int --get aninvalid.unit 2>actual + then + echo config should have failed + false + fi && + cmp actual expect +' + +cat > expect << EOF +true +false +true +false +true +false +true +false +EOF + +test_expect_success bool ' + + git config bool.true1 01 && + git config bool.true2 -1 && + git config bool.true3 YeS && + git config bool.true4 true && + git config bool.false1 000 && + git config bool.false2 "" && + git config bool.false3 nO && + git config bool.false4 FALSE && + rm -f result && + for i in 1 2 3 4 + do + git config --bool --get bool.true$i >>result + git config --bool --get bool.false$i >>result + done && + cmp expect result' + +test_expect_success 'invalid bool (--get)' ' + + git config bool.nobool foobar && + test_must_fail git config --bool --get bool.nobool' + +test_expect_success 'invalid bool (set)' ' + + test_must_fail git config --bool bool.nobool foobar' + rm .git/config -git-config quote.leading " test" -git-config quote.ending "test " -git-config quote.semicolon "test;test" -git-config quote.hash "test#test" +cat > expect <<\EOF +[bool] + true1 = true + true2 = true + true3 = true + true4 = true + false1 = false + false2 = false + false3 = false + false4 = false +EOF + +test_expect_success 'set --bool' ' + + git config --bool bool.true1 01 && + git config --bool bool.true2 -1 && + git config --bool bool.true3 YeS && + git config --bool bool.true4 true && + git config --bool bool.false1 000 && + git config --bool bool.false2 "" && + git config --bool bool.false3 nO && + git config --bool bool.false4 FALSE && + cmp expect .git/config' + +rm .git/config + +cat > expect <<\EOF +[int] + val1 = 1 + val2 = -1 + val3 = 5242880 +EOF + +test_expect_success 'set --int' ' + + git config --int int.val1 01 && + git config --int int.val2 -1 && + git config --int int.val3 5m && + cmp expect .git/config' + +rm .git/config + +cat >expect <<\EOF +[bool] + true1 = true + true2 = true + false1 = false + false2 = false +[int] + int1 = 0 + int2 = 1 + int3 = -1 +EOF + +test_expect_success 'get --bool-or-int' ' + ( + echo "[bool]" + echo true1 + echo true2 = true + echo false = false + echo "[int]" + echo int1 = 0 + echo int2 = 1 + echo int3 = -1 + ) >>.git/config && + test $(git config --bool-or-int bool.true1) = true && + test $(git config --bool-or-int bool.true2) = true && + test $(git config --bool-or-int bool.false) = false && + test $(git config --bool-or-int int.int1) = 0 && + test $(git config --bool-or-int int.int2) = 1 && + test $(git config --bool-or-int int.int3) = -1 + +' + +rm .git/config +cat >expect <<\EOF +[bool] + true1 = true + false1 = false + true2 = true + false2 = false +[int] + int1 = 0 + int2 = 1 + int3 = -1 +EOF + +test_expect_success 'set --bool-or-int' ' + git config --bool-or-int bool.true1 true && + git config --bool-or-int bool.false1 false && + git config --bool-or-int bool.true2 yes && + git config --bool-or-int bool.false2 no && + git config --bool-or-int int.int1 0 && + git config --bool-or-int int.int2 1 && + git config --bool-or-int int.int3 -1 && + test_cmp expect .git/config +' + +rm .git/config + +cat >expect <<\EOF +[path] + home = ~/ + normal = /dev/null + trailingtilde = foo~ +EOF + +test_expect_success '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 "${HOME+set}" +then + test_set_prereq HOMEVAR +fi + +cat >expect <<EOF +$HOME/ +/dev/null +foo~ +EOF + +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 '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" +git config quote.ending "test " +git config quote.semicolon "test;test" +git config quote.hash "test#test" cat > expect << EOF [quote] @@ -418,8 +759,9 @@ EOF test_expect_success 'quoting' 'cmp .git/config expect' -test_expect_failure 'key with newline' 'git config key.with\\\ -newline 123' +test_expect_success 'key with newline' ' + test_must_fail git config "key.with +newline" 123' test_expect_success 'value with newline' 'git config key.sub value.with\\\ newline' @@ -444,5 +786,72 @@ git config --list > result test_expect_success 'value continued on next line' 'cmp result expect' -test_done +cat > .git/config <<\EOF +[section "sub=section"] + val1 = foo=bar + val2 = foo\nbar + val3 = \n\n + val4 = + val5 +EOF + +cat > expect <<\EOF +section.sub=section.val1 +foo=barQsection.sub=section.val2 +foo +barQsection.sub=section.val3 + + +Qsection.sub=section.val4 +Qsection.sub=section.val5Q +EOF + +git config --null --list | perl -pe 'y/\000/Q/' > result +echo >>result +test_expect_success '--null --list' 'cmp result expect' + +git config --null --get-regexp 'val[0-9]' | perl -pe 'y/\000/Q/' > result +echo >>result + +test_expect_success '--null --get-regexp' 'cmp result expect' + +test_expect_success 'inner whitespace kept verbatim' ' + git config section.val "foo bar" && + test "z$(git config section.val)" = "zfoo bar" +' + +test_expect_success SYMLINKS 'symlinked configuration' ' + + ln -s notyet myconfig && + GIT_CONFIG=myconfig git config test.frotz nitfol && + test -h myconfig && + test -f notyet && + test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol && + GIT_CONFIG=myconfig git config test.xyzzy rezrov && + test -h myconfig && + test -f notyet && + test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol && + test "z$(GIT_CONFIG=notyet git config test.xyzzy)" = zrezrov + +' + +test_expect_success 'check split_cmdline return' " + git config alias.split-cmdline-fix 'echo \"' && + test_must_fail git split-cmdline-fix && + echo foo > foo && + git add foo && + git commit -m 'initial commit' && + git config branch.master.mergeoptions 'echo \"' && + 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/t1301-shared-repo.sh b/t/t1301-shared-repo.sh new file mode 100755 index 0000000000..de42d21c92 --- /dev/null +++ b/t/t1301-shared-repo.sh @@ -0,0 +1,170 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes Schindelin +# + +test_description='Test shared repository initialization' + +. ./test-lib.sh + +# Remove a default ACL from the test dir if possible. +setfacl -k . 2>/dev/null + +# User must have read permissions to the repo -> failure on --shared=0400 +test_expect_success 'shared = 0400 (faulty permission u-w)' ' + mkdir sub && ( + cd sub && git init --shared=0400 + ) + ret="$?" + rm -rf sub + test $ret != "0" +' + +modebits () { + ls -l "$1" | sed -e 's|^\(..........\).*|\1|' +} + +for u in 002 022 +do + test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" ' + mkdir sub && ( + cd sub && + umask $u && + git init --shared=1 && + test 1 = "$(git config core.sharedrepository)" + ) && + actual=$(ls -l sub/.git/HEAD) + case "$actual" in + -rw-rw-r--*) + : happy + ;; + *) + echo Oops, .git/HEAD is not 0664 but $actual + false + ;; + esac + ' + rm -rf sub +done + +test_expect_success 'shared=all' ' + mkdir sub && + cd sub && + git init --shared=all && + test 2 = $(git config core.sharedrepository) +' + +test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' ' + : > a1 && + git add a1 && + test_tick && + git commit -m a1 && + umask 0277 && + git update-server-info && + actual="$(ls -l .git/info/refs)" && + case "$actual" in + -r--r--r--*) + : happy + ;; + *) + echo Oops, .git/info/refs is not 0444 + false + ;; + esac +' + +for u in 0660:rw-rw---- \ + 0640:rw-r----- \ + 0600:rw------- \ + 0666:rw-rw-rw- \ + 0664:rw-rw-r-- +do + x=$(expr "$u" : ".*:\([rw-]*\)") && + y=$(echo "$x" | sed -e "s/w/-/g") && + u=$(expr "$u" : "\([0-7]*\)") && + git config core.sharedrepository "$u" && + umask 0277 && + + test_expect_success POSIXPERM "shared = $u ($y) ro" ' + + rm -f .git/info/refs && + git update-server-info && + actual="$(modebits .git/info/refs)" && + test "x$actual" = "x-$y" || { + ls -lt .git/info + false + } + ' + + umask 077 && + test_expect_success POSIXPERM "shared = $u ($x) rw" ' + + rm -f .git/info/refs && + git update-server-info && + actual="$(modebits .git/info/refs)" && + test "x$actual" = "x-$x" || { + ls -lt .git/info + false + } + + ' + +done + +test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' ' + git config core.sharedRepository group && + git reflog expire --all && + actual="$(ls -l .git/logs/refs/heads/master)" && + case "$actual" in + -rw-rw-*) + : happy + ;; + *) + echo Ooops, .git/logs/refs/heads/master is not 0662 [$actual] + false + ;; + esac +' + +test_expect_success POSIXPERM 'forced modes' ' + mkdir -p templates/hooks && + echo update-server-info >templates/hooks/post-update && + chmod +x templates/hooks/post-update && + echo : >random-file && + mkdir new && + ( + cd new && + umask 002 && + git init --shared=0660 --template=../templates && + >frotz && + git add frotz && + git commit -a -m initial && + git repack + ) && + # List repository files meant to be protected; note that + # COMMIT_EDITMSG does not matter---0mode is not about a + # repository with a work tree. + find new/.git -type f -name COMMIT_EDITMSG -prune -o -print | + xargs ls -ld >actual && + + # Everything must be unaccessible to others + test -z "$(sed -e "/^.......---/d" actual)" && + + # All directories must have either 2770 or 770 + test -z "$(sed -n -e "/^drwxrw[sx]---/d" -e "/^d/p" actual)" && + + # post-update hook must be 0770 + test -z "$(sed -n -e "/post-update/{ + /^-rwxrwx---/d + p + }" actual)" && + + # All files inside objects must be accessible by us + test -z "$(sed -n -e "/objects\//{ + /^d/d + /^-r.-r.----/d + p + }" actual)" +' + +test_done diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh new file mode 100755 index 0000000000..8d305b4372 --- /dev/null +++ b/t/t1302-repo-version.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# Copyright (c) 2007 Nguyá»…n Thái Ngá»c Duy +# + +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_create_repo "test" +test_create_repo "test2" + +GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99 || exit 1 + +test_expect_success 'gitdir selection on normal repos' ' + (test "$(git config core.repositoryformatversion)" = 0 && + cd test && + test "$(git config core.repositoryformatversion)" = 0)' + +# 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)' + +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)' + +test_expect_success 'gitdir required mode on unsupported repo' ' + (cd test2 && test_must_fail git apply --check --index ../test.patch) +' + +test_done diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh new file mode 100755 index 0000000000..080117c6bc --- /dev/null +++ b/t/t1303-wacky-config.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='Test wacky input to git config' +. ./test-lib.sh + +setup() { + (printf "[section]\n" && + printf " key = foo") >.git/config +} + +check() { + echo "$2" >expected + git config --get "$1" >actual 2>&1 + test_cmp actual expected +} + +test_expect_success 'modify same key' ' + setup && + git config section.key bar && + check section.key bar +' + +test_expect_success 'add key in same section' ' + setup && + git config section.other bar && + check section.key foo && + check section.other bar +' + +test_expect_success 'add key in different section' ' + setup && + git config section2.key bar && + check section.key foo && + check section2.key bar +' + +SECTION="test.q\"s\\sq'sp e.key" +test_expect_success 'make sure git config escapes section names properly' ' + git config "$SECTION" bar && + check "$SECTION" bar +' + +LONG_VALUE=$(printf "x%01021dx a" 7) +test_expect_success 'do not crash on special long config line' ' + setup && + git config section.key "$LONG_VALUE" && + check section.key "fatal: bad config file line 2 in .git/config" +' + +test_done diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh new file mode 100755 index 0000000000..97ab02aceb --- /dev/null +++ b/t/t1304-default-acl.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Copyright (c) 2010 Matthieu Moy +# + +test_description='Test repository with default ACL' + +# Create the test repo with restrictive umask +# => this must come before . ./test-lib.sh +umask 077 + +. ./test-lib.sh + +# We need an arbitrary other user give permission to using ACLs. root +# is a good candidate: exists on all unices, and it has permission +# anyway, so we don't create a security hole running the testsuite. + +setfacl_out="$(setfacl -m u:root:rwx . 2>&1)" +setfacl_ret=$? + +if [ $setfacl_ret != 0 ]; then + skip_all="Skipping ACL tests: unable to use setfacl (output: '$setfacl_out'; return code: '$setfacl_ret')" + test_done +fi + +check_perms_and_acl () { + test -r "$1" && + getfacl "$1" > actual && + grep -q "user:root:rwx" actual && + grep -q "user:${LOGNAME}:rwx" actual && + egrep "mask::?r--" actual > /dev/null 2>&1 && + grep -q "group::---" actual || false +} + +dirs_to_set="./ .git/ .git/objects/ .git/objects/pack/" + +test_expect_success '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 && + setfacl -m d:u:"$LOGNAME":rwx $dirs_to_set && + setfacl -m d:u:root:rwx $dirs_to_set && + + touch file.txt && + git add file.txt && + git commit -m "init" +' + +test_expect_success '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' ' + git gc && + check_perms_and_acl .git/objects/pack/*.pack +' + +test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index d0aba2c2ae..54ba3df95f 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -3,64 +3,113 @@ # Copyright (c) 2006 Shawn Pearce # -test_description='Test git-update-ref and basic ref logging' +test_description='Test git update-ref and basic ref logging' . ./test-lib.sh Z=0000000000000000000000000000000000000000 -A=1111111111111111111111111111111111111111 -B=2222222222222222222222222222222222222222 -C=3333333333333333333333333333333333333333 -D=4444444444444444444444444444444444444444 -E=5555555555555555555555555555555555555555 -F=6666666666666666666666666666666666666666 + +test_expect_success setup ' + + for name in A B C D E F + do + test_tick && + T=$(git write-tree) && + sha1=$(echo $name | git commit-tree $T) && + eval $name=$sha1 + done + +' + m=refs/heads/master n_dir=refs/heads/gu n=$n_dir/fixes test_expect_success \ "create $m" \ - "git-update-ref $m $A && + "git update-ref $m $A && test $A"' = $(cat .git/'"$m"')' test_expect_success \ "create $m" \ - "git-update-ref $m $B $A && + "git update-ref $m $B $A && test $B"' = $(cat .git/'"$m"')' +test_expect_success "fail to delete $m with stale ref" ' + test_must_fail git update-ref -d $m $A && + test $B = "$(cat .git/$m)" +' +test_expect_success "delete $m" ' + git update-ref -d $m $B && + ! test -f .git/$m +' +rm -f .git/$m + +test_expect_success "delete $m without oldvalue verification" " + git update-ref $m $A && + test $A = \$(cat .git/$m) && + git update-ref -d $m && + ! test -f .git/$m +" rm -f .git/$m test_expect_success \ "fail to create $n" \ "touch .git/$n_dir - git-update-ref $n $A >out 2>err"' + git update-ref $n $A >out 2>err"' test $? != 0' rm -f .git/$n_dir out err test_expect_success \ "create $m (by HEAD)" \ - "git-update-ref HEAD $A && + "git update-ref HEAD $A && test $A"' = $(cat .git/'"$m"')' test_expect_success \ "create $m (by HEAD)" \ - "git-update-ref HEAD $B $A && + "git update-ref HEAD $B $A && test $B"' = $(cat .git/'"$m"')' +test_expect_success "fail to delete $m (by HEAD) with stale ref" ' + test_must_fail git update-ref -d HEAD $A && + test $B = $(cat .git/$m) +' +test_expect_success "delete $m (by HEAD)" ' + git update-ref -d HEAD $B && + ! test -f .git/$m +' rm -f .git/$m -test_expect_failure \ - '(not) create HEAD with old sha1' \ - "git-update-ref HEAD $A $B" -test_expect_failure \ - "(not) prior created .git/$m" \ - "test -f .git/$m" +cp -f .git/HEAD .git/HEAD.orig +test_expect_success "delete symref without dereference" ' + git update-ref --no-deref -d HEAD && + ! test -f .git/HEAD +' +cp -f .git/HEAD.orig .git/HEAD + +test_expect_success "delete symref without dereference when the referred ref is packed" ' + echo foo >foo.c && + git add foo.c && + git commit -m foo && + git pack-refs --all && + git update-ref --no-deref -d HEAD && + ! test -f .git/HEAD +' +cp -f .git/HEAD.orig .git/HEAD +git update-ref -d $m + +test_expect_success '(not) create HEAD with old sha1' " + test_must_fail git update-ref HEAD $A $B +" +test_expect_success "(not) prior created .git/$m" " + ! test -f .git/$m +" rm -f .git/$m test_expect_success \ "create HEAD" \ - "git-update-ref HEAD $A" -test_expect_failure \ - '(not) change HEAD with wrong SHA1' \ - "git-update-ref HEAD $B $Z" -test_expect_failure \ - "(not) changed .git/$m" \ - "test $B"' = $(cat .git/'"$m"')' + "git update-ref HEAD $A" +test_expect_success '(not) change HEAD with wrong SHA1' " + test_must_fail git update-ref HEAD $B $Z +" +test_expect_success "(not) changed .git/$m" " + ! test $B"' = $(cat .git/'"$m"') +' rm -f .git/$m : a repository with working tree always has reflog these days... @@ -68,17 +117,17 @@ rm -f .git/$m test_expect_success \ "create $m (logged by touch)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ - git-update-ref HEAD '"$A"' -m "Initial Creation" && + git update-ref HEAD '"$A"' -m "Initial Creation" && test '"$A"' = $(cat .git/'"$m"')' test_expect_success \ "update $m (logged by touch)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:31" \ - git-update-ref HEAD'" $B $A "'-m "Switch" && + git update-ref HEAD'" $B $A "'-m "Switch" && test '"$B"' = $(cat .git/'"$m"')' test_expect_success \ "set $m (logged by touch)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:41" \ - git-update-ref HEAD'" $A && + git update-ref HEAD'" $A && test $A"' = $(cat .git/'"$m"')' cat >expect <<EOF @@ -88,28 +137,28 @@ $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000 EOF test_expect_success \ "verifying $m's log" \ - "diff expect .git/logs/$m" + "test_cmp expect .git/logs/$m" rm -rf .git/$m .git/logs expect test_expect_success \ 'enable core.logAllRefUpdates' \ - 'git-config core.logAllRefUpdates true && - test true = $(git-config --bool --get core.logAllRefUpdates)' + 'git config core.logAllRefUpdates true && + test true = $(git config --bool --get core.logAllRefUpdates)' test_expect_success \ "create $m (logged by config)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:32" \ - git-update-ref HEAD'" $A "'-m "Initial Creation" && + git update-ref HEAD'" $A "'-m "Initial Creation" && test '"$A"' = $(cat .git/'"$m"')' test_expect_success \ "update $m (logged by config)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:33" \ - git-update-ref HEAD'" $B $A "'-m "Switch" && + git update-ref HEAD'" $B $A "'-m "Switch" && test '"$B"' = $(cat .git/'"$m"')' test_expect_success \ "set $m (logged by config)" \ 'GIT_COMMITTER_DATE="2005-05-26 23:43" \ - git-update-ref HEAD '"$A && + git update-ref HEAD '"$A && test $A"' = $(cat .git/'"$m"')' cat >expect <<EOF @@ -119,12 +168,13 @@ $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 +0000 EOF test_expect_success \ "verifying $m's log" \ - 'diff expect .git/logs/$m' + 'test_cmp expect .git/logs/$m' rm -f .git/$m .git/logs/$m expect -git-update-ref $m $D +git update-ref $m $D cat >.git/logs/$m <<EOF -$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 +0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 +$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 @@ -136,49 +186,55 @@ ld="Thu, 26 May 2005 18:43:00 -0500" test_expect_success \ 'Query "master@{May 25 2005}" (before history)' \ 'rm -f o e - git-rev-parse --verify "master@{May 25 2005}" >o 2>e && + git rev-parse --verify "master@{May 25 2005}" >o 2>e && test '"$C"' = $(cat o) && test "warning: Log for '\'master\'' only goes back to $ed." = "$(cat e)"' test_expect_success \ "Query master@{2005-05-25} (before history)" \ 'rm -f o e - git-rev-parse --verify master@{2005-05-25} >o 2>e && + git rev-parse --verify master@{2005-05-25} >o 2>e && test '"$C"' = $(cat o) && echo test "warning: Log for '\'master\'' only goes back to $ed." = "$(cat e)"' test_expect_success \ 'Query "master@{May 26 2005 23:31:59}" (1 second before history)' \ 'rm -f o e - git-rev-parse --verify "master@{May 26 2005 23:31:59}" >o 2>e && + git rev-parse --verify "master@{May 26 2005 23:31:59}" >o 2>e && test '"$C"' = $(cat o) && test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)"' test_expect_success \ 'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \ 'rm -f o e - git-rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e && + git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e && + test '"$C"' = $(cat o) && + test "" = "$(cat e)"' +test_expect_success \ + 'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \ + 'rm -f o e + git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e && test '"$A"' = $(cat o) && test "" = "$(cat e)"' test_expect_success \ 'Query "master@{2005-05-26 23:33:01}" (middle of history with gap)' \ 'rm -f o e - git-rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e && + git rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e && test '"$B"' = $(cat o) && test "warning: Log .git/logs/'"$m has gap after $gd"'." = "$(cat e)"' test_expect_success \ 'Query "master@{2005-05-26 23:38:00}" (middle of history)' \ 'rm -f o e - git-rev-parse --verify "master@{2005-05-26 23:38:00}" >o 2>e && + git rev-parse --verify "master@{2005-05-26 23:38:00}" >o 2>e && test '"$Z"' = $(cat o) && test "" = "$(cat e)"' test_expect_success \ 'Query "master@{2005-05-26 23:43:00}" (exact end of history)' \ 'rm -f o e - git-rev-parse --verify "master@{2005-05-26 23:43:00}" >o 2>e && + git rev-parse --verify "master@{2005-05-26 23:43:00}" >o 2>e && test '"$E"' = $(cat o) && test "" = "$(cat e)"' test_expect_success \ 'Query "master@{2005-05-28}" (past end of history)' \ 'rm -f o e - git-rev-parse --verify "master@{2005-05-28}" >o 2>e && + git rev-parse --verify "master@{2005-05-28}" >o 2>e && test '"$D"' = $(cat o) && test "warning: Log .git/logs/'"$m unexpectedly ended on $ld"'." = "$(cat e)"' @@ -188,26 +244,24 @@ rm -f .git/$m .git/logs/$m expect test_expect_success \ 'creating initial files' \ 'echo TEST >F && - git-add F && + git add F && GIT_AUTHOR_DATE="2005-05-26 23:30" \ - GIT_COMMITTER_DATE="2005-05-26 23:30" git-commit -m add -a && - h_TEST=$(git-rev-parse --verify HEAD) + GIT_COMMITTER_DATE="2005-05-26 23:30" git commit -m add -a && + h_TEST=$(git rev-parse --verify HEAD) echo The other day this did not work. >M && echo And then Bob told me how to fix it. >>M && echo OTHER >F && GIT_AUTHOR_DATE="2005-05-26 23:41" \ - GIT_COMMITTER_DATE="2005-05-26 23:41" git-commit -F M -a && - h_OTHER=$(git-rev-parse --verify HEAD) && - echo FIXED >F && + GIT_COMMITTER_DATE="2005-05-26 23:41" git commit -F M -a && + h_OTHER=$(git rev-parse --verify HEAD) && GIT_AUTHOR_DATE="2005-05-26 23:44" \ - GIT_COMMITTER_DATE="2005-05-26 23:44" git-commit --amend && - h_FIXED=$(git-rev-parse --verify HEAD) && - echo TEST+FIXED >F && + GIT_COMMITTER_DATE="2005-05-26 23:44" git commit --amend && + h_FIXED=$(git rev-parse --verify HEAD) && echo Merged initial commit and a later commit. >M && echo $h_TEST >.git/MERGE_HEAD && GIT_AUTHOR_DATE="2005-05-26 23:45" \ - GIT_COMMITTER_DATE="2005-05-26 23:45" git-commit -F M && - h_MERGED=$(git-rev-parse --verify HEAD) + GIT_COMMITTER_DATE="2005-05-26 23:45" git commit -F M && + h_MERGED=$(git rev-parse --verify HEAD) && rm -f M' cat >expect <<EOF @@ -217,18 +271,18 @@ $h_OTHER $h_FIXED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151040 +0000 co $h_FIXED $h_MERGED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151100 +0000 commit (merge): Merged initial commit and a later commit. EOF test_expect_success \ - 'git-commit logged updates' \ - "diff expect .git/logs/$m" + 'git commit logged updates' \ + "test_cmp expect .git/logs/$m" unset h_TEST h_OTHER h_FIXED h_MERGED test_expect_success \ - 'git-cat-file blob master:F (expect OTHER)' \ - 'test OTHER = $(git-cat-file blob master:F)' + 'git cat-file blob master:F (expect OTHER)' \ + 'test OTHER = $(git cat-file blob master:F)' test_expect_success \ - 'git-cat-file blob master@{2005-05-26 23:30}:F (expect TEST)' \ - 'test TEST = $(git-cat-file blob "master@{2005-05-26 23:30}:F")' + 'git cat-file blob master@{2005-05-26 23:30}:F (expect TEST)' \ + 'test TEST = $(git cat-file blob "master@{2005-05-26 23:30}:F")' test_expect_success \ - 'git-cat-file blob master@{2005-05-26 23:42}:F (expect OTHER)' \ - 'test OTHER = $(git-cat-file blob "master@{2005-05-26 23:42}:F")' + 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER)' \ + 'test OTHER = $(git cat-file blob "master@{2005-05-26 23:42}:F")' test_done diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh new file mode 100755 index 0000000000..7fa5f5b22a --- /dev/null +++ b/t/t1401-symbolic-ref.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +test_description='basic symbolic-ref tests' +. ./test-lib.sh + +# If the tests munging HEAD fail, they can break detection of +# the git repo, meaning that further tests will operate on +# the surrounding git repo instead of the trash directory. +reset_to_sane() { + echo ref: refs/heads/foo >.git/HEAD +} + +test_expect_success 'symbolic-ref writes HEAD' ' + git symbolic-ref HEAD refs/heads/foo && + echo ref: refs/heads/foo >expect && + test_cmp expect .git/HEAD +' + +test_expect_success 'symbolic-ref reads HEAD' ' + echo refs/heads/foo >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'symbolic-ref refuses non-ref for HEAD' ' + test_must_fail git symbolic-ref HEAD foo +' +reset_to_sane + +test_expect_success 'symbolic-ref refuses bare sha1' ' + echo content >file && git add file && git commit -m one + test_must_fail git symbolic-ref HEAD `git rev-parse HEAD` +' +reset_to_sane + +test_done diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh new file mode 100755 index 0000000000..782e75d000 --- /dev/null +++ b/t/t1402-check-ref-format.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +test_description='Test git check-ref-format' + +. ./test-lib.sh + +valid_ref() { + test_expect_success "ref name '$1' is valid" \ + "git check-ref-format '$1'" +} +invalid_ref() { + test_expect_success "ref name '$1' is not valid" \ + "test_must_fail git check-ref-format '$1'" +} + +valid_ref 'heads/foo' +invalid_ref 'foo' +valid_ref 'foo/bar/baz' +valid_ref 'refs///heads/foo' +invalid_ref 'heads/foo/' +invalid_ref './foo' +invalid_ref '.refs/foo' +invalid_ref 'heads/foo..bar' +invalid_ref 'heads/foo?bar' +valid_ref 'foo./bar' +invalid_ref 'heads/foo.lock' +valid_ref 'heads/foo@bar' +invalid_ref 'heads/v@{ation' +invalid_ref 'heads/foo\bar' + +test_expect_success "check-ref-format --branch @{-1}" ' + 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=$(git check-ref-format --branch @{-1}) && + test "$refname" = "$sha1" && + 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') && + test \"\$refname\" = '$2'" +} +invalid_ref_normalized() { + test_expect_success "check-ref-format --print rejects '$1'" " + test_must_fail git check-ref-format --print '$1'" +} + +valid_ref_normalized 'heads/foo' 'heads/foo' +valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo' +invalid_ref_normalized 'foo' +invalid_ref_normalized 'heads/foo/../bar' +invalid_ref_normalized 'heads/./foo' +invalid_ref_normalized 'heads\foo' + +test_done diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index e5bbc384f7..25046c4208 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -70,9 +70,7 @@ test_expect_success setup ' E=`git rev-parse --verify HEAD:A/B/E` && check_fsck && - chmod +x C && - ( test "`git config --bool core.filemode`" != false || - echo executable >>C ) && + test_chmod +x C && git add C && test_tick && git commit -m dragon && L=`git rev-parse --verify HEAD` && @@ -175,4 +173,86 @@ test_expect_success 'recover and check' ' ' +test_expect_success 'delete' ' + echo 1 > C && + test_tick && + git commit -m rat C && + + echo 2 > C && + test_tick && + git commit -m ox C && + + echo 3 > C && + test_tick && + git commit -m tiger C && + + HEAD_entry_count=$(git reflog | wc -l) + master_entry_count=$(git reflog show master | wc -l) + + test $HEAD_entry_count = 5 && + test $master_entry_count = 5 && + + + git reflog delete master@{1} && + git reflog show master > output && + test $(($master_entry_count - 1)) = $(wc -l < output) && + test $HEAD_entry_count = $(git reflog | wc -l) && + ! grep ox < output && + + master_entry_count=$(wc -l < output) + + git reflog delete HEAD@{1} && + test $(($HEAD_entry_count -1)) = $(git reflog | wc -l) && + test $master_entry_count = $(git reflog show master | wc -l) && + + HEAD_entry_count=$(git reflog | wc -l) + + git reflog delete master@{07.04.2005.15:15:00.-0700} && + git reflog show master > output && + test $(($master_entry_count - 1)) = $(wc -l < output) && + ! grep dragon < output + +' + +test_expect_success 'rewind2' ' + + test_tick && git reset --hard HEAD~2 && + loglen=$(wc -l <.git/logs/refs/heads/master) && + test $loglen = 4 + +' + +test_expect_success '--expire=never' ' + + git reflog expire --verbose \ + --expire=never \ + --expire-unreachable=never \ + --all && + loglen=$(wc -l <.git/logs/refs/heads/master) && + test $loglen = 4 + +' + +test_expect_success 'gc.reflogexpire=never' ' + + git config gc.reflogexpire never && + git config gc.reflogexpireunreachable never && + git reflog expire --verbose --all && + loglen=$(wc -l <.git/logs/refs/heads/master) && + test $loglen = 4 +' + +test_expect_success 'gc.reflogexpire=false' ' + + git config gc.reflogexpire false && + git config gc.reflogexpireunreachable false && + git reflog expire --verbose --all && + loglen=$(wc -l <.git/logs/refs/heads/master) && + test $loglen = 4 && + + git config --unset gc.reflogexpire && + git config --unset gc.reflogexpireunreachable + +' + test_done diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh new file mode 100755 index 0000000000..ba25ff354d --- /dev/null +++ b/t/t1411-reflog-show.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +test_description='Test reflog display routines' +. ./test-lib.sh + +test_expect_success 'setup' ' + echo content >file && + git add file && + test_tick && + git commit -m one +' + +cat >expect <<'EOF' +Reflog: HEAD@{0} (C O Mitter <committer@example.com>) +Reflog message: commit (initial): one +EOF +test_expect_success 'log -g shows reflog headers' ' + git log -g -1 >tmp && + grep ^Reflog <tmp >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{0}: commit (initial): one +EOF +test_expect_success 'oneline reflog format' ' + git log -g -1 --oneline >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>) +Reflog message: commit (initial): one +EOF +test_expect_success 'using @{now} syntax shows reflog date (multiline)' ' + git log -g -1 HEAD@{now} >tmp && + grep ^Reflog <tmp >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one +EOF +test_expect_success 'using @{now} syntax shows reflog date (oneline)' ' + git log -g -1 --oneline HEAD@{now} >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>) +Reflog message: commit (initial): one +EOF +test_expect_success 'using --date= shows reflog date (multiline)' ' + git log -g -1 --date=raw >tmp && + grep ^Reflog <tmp >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +e46513e HEAD@{1112911993 -0700}: commit (initial): one +EOF +test_expect_success 'using --date= shows reflog date (oneline)' ' + git log -g -1 --oneline --date=raw >actual && + test_cmp expect actual +' + +: >expect +test_expect_success 'empty reflog file' ' + git branch empty && + : >.git/logs/refs/heads/empty && + + git log -g empty >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t1420-lost-found.sh b/t/t1420-lost-found.sh new file mode 100755 index 0000000000..dc9e402c55 --- /dev/null +++ b/t/t1420-lost-found.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test fsck --lost-found' +. ./test-lib.sh + +test_expect_success setup ' + git config core.logAllRefUpdates 0 && + : > file1 && + git add file1 && + test_tick && + git commit -m initial && + echo 1 > file1 && + echo 2 > file2 && + git add file1 file2 && + test_tick && + git commit -m second && + echo 3 > file3 && + git add file3 +' + +test_expect_success 'lost and found something' ' + git rev-parse HEAD > lost-commit && + git rev-parse :file3 > lost-other && + test_tick && + git reset --hard HEAD^ && + git fsck --lost-found && + test 2 = $(ls .git/lost-found/*/* | wc -l) && + test -f .git/lost-found/commit/$(cat lost-commit) && + test -f .git/lost-found/other/$(cat lost-other) +' + +test_done diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh new file mode 100755 index 0000000000..759cf12e16 --- /dev/null +++ b/t/t1450-fsck.sh @@ -0,0 +1,134 @@ +#!/bin/sh + +test_description='git fsck random collection of tests' + +. ./test-lib.sh + +test_expect_success setup ' + 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) +' + +test_expect_success 'loose objects borrowed from alternate are not missing' ' + mkdir another && + ( + cd another && + git init && + echo ../../../.git/objects >.git/objects/info/alternates && + test_commit C fileC one && + git fsck >out && + ! grep "missing blob" out + ) +' + +test_expect_success 'valid objects appear valid' ' + { git fsck 2>out; true; } && + ! grep error out && + ! grep fatal out +' + +# 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 '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 && + git update-index --add --cacheinfo 100644 $sha foo && + tree=$(git write-tree) && + cmt=$(echo bogus | git commit-tree $tree) && + 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_expect_success 'branch pointing to non-commit' ' + git rev-parse HEAD^{tree} > .git/refs/heads/invalid && + git fsck 2>out && + grep "not a commit" out && + git update-ref -d refs/heads/invalid +' + +new=nothing +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) && + echo "$new" && + git update-ref refs/heads/bogus "$new" && + git fsck 2>out && + cat out && + ! grep "error in commit $new" out +' +git update-ref -d refs/heads/bogus +rm -f ".git/objects/$new" + +new=nothing +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) && + echo "$new" && + git update-ref refs/heads/bogus "$new" && + git fsck 2>out && + cat out && + grep "error in commit $new" out +' +git update-ref -d refs/heads/bogus +rm -f ".git/objects/$new" + +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 + +test_expect_success 'tag pointing to nonexistent' ' + tag=$(git hash-object -t tag -w --stdin < invalid-tag) && + echo $tag > .git/refs/tags/invalid && + test_must_fail git fsck --tags >out && + cat out && + grep "broken link" out && + rm .git/refs/tags/invalid +' + +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 && + test_must_fail git fsck --tags 2>out && + cat out && + grep "error in tag.*broken links" out && + rm .git/refs/tags/wrong +' + + + +test_done diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh new file mode 100755 index 0000000000..48ee07779d --- /dev/null +++ b/t/t1500-rev-parse.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='test git rev-parse' +. ./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 + + test_expect_success "$name: git-dir" \ + "test '$1' = \"\$(git rev-parse --git-dir)\"" + shift + [ $# -eq 0 ] && return +} + +# label is-bare is-inside-git is-inside-work prefix git-dir + +ROOT=$(pwd) + +test_rev_parse toplevel false false true '' .git + +cd .git || exit 1 +test_rev_parse .git/ false true false '' . +cd objects || exit 1 +test_rev_parse .git/objects/ false true false '' "$ROOT/.git" +cd ../.. || exit 1 + +mkdir -p sub/dir || exit 1 +cd sub/dir || exit 1 +test_rev_parse subdirectory false false true sub/dir/ "$ROOT/.git" +cd ../.. || exit 1 + +git config core.bare true +test_rev_parse 'core.bare = true' true false false + +git config --unset core.bare +test_rev_parse 'core.bare undefined' false false true + +mkdir work || exit 1 +cd work || exit 1 +GIT_DIR=../.git +GIT_CONFIG="$(pwd)"/../.git/config +export GIT_DIR GIT_CONFIG + +git config core.bare false +test_rev_parse 'GIT_DIR=../.git, core.bare = false' false false true '' + +git config core.bare true +test_rev_parse 'GIT_DIR=../.git, core.bare = true' true false false '' + +git config --unset core.bare +test_rev_parse 'GIT_DIR=../.git, core.bare undefined' false false true '' + +mv ../.git ../repo.git || exit 1 +GIT_DIR=../repo.git +GIT_CONFIG="$(pwd)"/../repo.git/config + +git config core.bare false +test_rev_parse 'GIT_DIR=../repo.git, core.bare = false' false false true '' + +git config core.bare true +test_rev_parse 'GIT_DIR=../repo.git, core.bare = true' true false false '' + +git config --unset core.bare +test_rev_parse 'GIT_DIR=../repo.git, core.bare undefined' false false true '' + +test_done diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh new file mode 100755 index 0000000000..bd8b60732b --- /dev/null +++ b/t/t1501-worktree.sh @@ -0,0 +1,206 @@ +#!/bin/sh + +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 +mkdir -p work2 || 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 work2 +test_rev_parse 'outside2' 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 work2 +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 +mv work2 repo.git/work2 + +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 ../work2 || exit 1 +test_rev_parse 'in repo.git/work2' 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 '_gently() groks relative GIT_DIR & GIT_WORK_TREE' ' + (cd repo.git/work/sub/dir && + 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 +' + +test_expect_success 'git grep' ' + (cd repo.git/work/sub && + GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked) +' + +test_expect_success 'git commit' ' + ( + cd repo.git && + GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done + ) +' + +test_expect_success 'absolute pathspec should fail gracefully' ' + ( + cd repo.git || exit 1 + 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 + 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 +' + +test_done diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh new file mode 100755 index 0000000000..b3195c4707 --- /dev/null +++ b/t/t1502-rev-parse-parseopt.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='test git rev-parse --parseopt' +. ./test-lib.sh + +cat > expect <<\END_EXPECT +cat <<\EOF +usage: some-command [options] <args>... + + some-command does foo and bar! + + -h, --help show the help + --foo some nifty option --foo + --bar ... some cool option --bar with an argument + +An option group Header + -C[...] option C with an optional argument + +Extras + --extra1 line above used to cause a segfault but no longer does + +EOF +END_EXPECT + +cat > optionspec << EOF +some-command [options] <args>... + +some-command does foo and bar! +-- +h,help show the help + +foo some nifty option --foo +bar= some cool option --bar with an argument + + An option group Header +C? option C with an optional argument + +Extras +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 > output < optionspec + test_cmp expect output +' + +cat > expect <<EOF +set -- --foo --bar 'ham' -- 'arg' +EOF + +test_expect_success 'test --parseopt' ' + git rev-parse --parseopt -- --foo --bar=ham arg < optionspec > output && + test_cmp expect output +' + +test_expect_success 'test --parseopt with mixed options and arguments' ' + git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output && + test_cmp expect output +' + +cat > expect <<EOF +set -- --foo -- 'arg' '--bar=ham' +EOF + +test_expect_success 'test --parseopt with --' ' + git rev-parse --parseopt -- --foo -- arg --bar=ham < optionspec > output && + test_cmp expect output +' + +test_expect_success 'test --parseopt --stop-at-non-option' ' + git rev-parse --parseopt --stop-at-non-option -- --foo arg --bar=ham < optionspec > output && + test_cmp expect output +' + +cat > expect <<EOF +set -- --foo -- '--' 'arg' '--bar=ham' +EOF + +test_expect_success 'test --parseopt --keep-dashdash' ' + git rev-parse --parseopt --keep-dashdash -- --foo -- arg --bar=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 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 new file mode 100755 index 0000000000..cc65394947 --- /dev/null +++ b/t/t1503-rev-parse-verify.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# +# Copyright (c) 2008 Christian Couder +# +test_description='test git rev-parse --verify' + +exec </dev/null + +. ./test-lib.sh + +add_line_into_file() +{ + _line=$1 + _file=$2 + + if [ -f "$_file" ]; then + echo "$_line" >> $_file || return $? + MSG="Add <$_line> into <$_file>." + else + echo "$_line" > $_file || return $? + git add $_file || return $? + MSG="Create file <$_file> with <$_line> inside." + fi + + test_tick + git commit --quiet -m "$MSG" $_file +} + +HASH1= +HASH2= +HASH3= +HASH4= + +test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' ' + add_line_into_file "1: Hello World" hello && + HASH1=$(git rev-parse --verify HEAD) && + add_line_into_file "2: A new day for git" hello && + HASH2=$(git rev-parse --verify HEAD) && + add_line_into_file "3: Another new day for git" hello && + HASH3=$(git rev-parse --verify HEAD) && + add_line_into_file "4: Ciao for now" hello && + HASH4=$(git rev-parse --verify HEAD) +' + +test_expect_success 'works with one good rev' ' + rev_hash1=$(git rev-parse --verify $HASH1) && + test "$rev_hash1" = "$HASH1" && + rev_hash2=$(git rev-parse --verify $HASH2) && + test "$rev_hash2" = "$HASH2" && + rev_hash3=$(git rev-parse --verify $HASH3) && + test "$rev_hash3" = "$HASH3" && + rev_hash4=$(git rev-parse --verify $HASH4) && + test "$rev_hash4" = "$HASH4" && + rev_master=$(git rev-parse --verify master) && + test "$rev_master" = "$HASH4" && + rev_head=$(git rev-parse --verify HEAD) && + test "$rev_head" = "$HASH4" +' + +test_expect_success 'fails with any bad rev or many good revs' ' + test_must_fail git rev-parse --verify 2>error && + grep "single revision" error && + test_must_fail git rev-parse --verify foo 2>error && + grep "single revision" error && + test_must_fail git rev-parse --verify HEAD bar 2>error && + grep "single revision" error && + test_must_fail git rev-parse --verify baz HEAD 2>error && + grep "single revision" error && + test_must_fail git rev-parse --verify $HASH2 HEAD 2>error && + grep "single revision" error +' + +test_expect_success 'fails silently when using -q' ' + test_must_fail git rev-parse --verify --quiet 2>error && + test -z "$(cat error)" && + test_must_fail git rev-parse -q --verify foo 2>error && + test -z "$(cat error)" && + test_must_fail git rev-parse --verify -q HEAD bar 2>error && + test -z "$(cat error)" && + test_must_fail git rev-parse --quiet --verify baz HEAD 2>error && + test -z "$(cat error)" && + test_must_fail git rev-parse -q --verify $HASH2 HEAD 2>error && + test -z "$(cat error)" +' + +test_expect_success 'no stdout output on error' ' + test -z "$(git rev-parse --verify)" && + test -z "$(git rev-parse --verify foo)" && + test -z "$(git rev-parse --verify baz HEAD)" && + test -z "$(git rev-parse --verify HEAD bar)" && + test -z "$(git rev-parse --verify $HASH2 HEAD)" +' + +test_expect_success 'use --default' ' + git rev-parse --verify --default master && + git rev-parse --verify --default master HEAD && + git rev-parse --default master --verify && + git rev-parse --default master --verify HEAD && + git rev-parse --verify HEAD --default master && + test_must_fail git rev-parse --verify foo --default master && + test_must_fail git rev-parse --default HEAD --verify bar && + test_must_fail git rev-parse --verify --default HEAD baz && + test_must_fail git rev-parse --default foo --verify && + test_must_fail git rev-parse --verify --default bar +' + +test_done diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh new file mode 100755 index 0000000000..df5ad8c686 --- /dev/null +++ b/t/t1504-ceiling-dirs.sh @@ -0,0 +1,163 @@ +#!/bin/sh + +test_description='test GIT_CEILING_DIRECTORIES' +. ./test-lib.sh + +test_prefix() { + test_expect_success "$1" \ + "test '$2' = \"\$(git rev-parse --show-prefix)\"" +} + +test_fail() { + test_expect_code 128 "$1: prefix" \ + "git rev-parse --show-prefix" +} + +TRASH_ROOT="$PWD" +ROOT_PARENT=$(dirname "$TRASH_ROOT") + + +unset GIT_CEILING_DIRECTORIES +test_prefix no_ceil "" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix ceil_empty "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT" +test_prefix ceil_at_parent "" + +GIT_CEILING_DIRECTORIES="$ROOT_PARENT/" +test_prefix ceil_at_parent_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_prefix ceil_at_trash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_prefix ceil_at_trash_slash "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_prefix ceil_at_sub "" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_prefix ceil_at_sub_slash "" + + +mkdir -p sub/dir || exit 1 +cd sub/dir || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix subdir_no_ceil "sub/dir/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix subdir_ceil_empty "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail subdir_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail subdir_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +test_fail subdir_ceil_at_sub + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/" +test_fail subdir_ceil_at_sub_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir" +test_prefix subdir_ceil_at_subdir "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/" +test_prefix subdir_ceil_at_subdir_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix subdir_ceil_at_su "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix subdir_ceil_at_su_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di" +test_prefix subdir_ceil_at_sub_di_slash "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi "sub/dir/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" +test_prefix subdir_ceil_at_subdi_slash "sub/dir/" + + +GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub" +test_fail second_of_two + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:/bar" +test_fail first_of_two + +GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub:/bar" +test_fail second_of_three + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub" +GIT_DIR=../../.git +export GIT_DIR +test_prefix git_dir_specified "" +unset GIT_DIR + + +cd ../.. || exit 1 +mkdir -p s/d || exit 1 +cd s/d || exit 1 + +unset GIT_CEILING_DIRECTORIES +test_prefix sd_no_ceil "s/d/" + +export GIT_CEILING_DIRECTORIES + +GIT_CEILING_DIRECTORIES="" +test_prefix sd_ceil_empty "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT" +test_fail sd_ceil_at_trash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/" +test_fail sd_ceil_at_trash_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s" +test_fail sd_ceil_at_s + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/" +test_fail sd_ceil_at_s_slash + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d" +test_prefix sd_ceil_at_sd "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/" +test_prefix sd_ceil_at_sd_slash "s/d/" + + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su" +test_prefix sd_ceil_at_su "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/" +test_prefix sd_ceil_at_su_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di" +test_prefix sd_ceil_at_s_di_slash "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi "s/d/" + +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi" +test_prefix sd_ceil_at_sdi_slash "s/d/" + + +test_done diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh new file mode 100755 index 0000000000..d709ecf8df --- /dev/null +++ b/t/t1505-rev-parse-last.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='test @{-N} syntax' + +. ./test-lib.sh + + +make_commit () { + echo "$1" > "$1" && + git add "$1" && + git commit -m "$1" +} + + +test_expect_success 'setup' ' + + make_commit 1 && + git branch side && + make_commit 2 && + make_commit 3 && + git checkout side && + make_commit 4 && + git merge master && + git checkout master + +' + +# 1 -- 2 -- 3 master +# \ \ +# \ \ +# --- 4 --- 5 side +# +# and 'side' should be the last branch + +test_rev_equivalent () { + + git rev-parse "$1" > expect && + git rev-parse "$2" > output && + test_cmp expect output + +} + +test_expect_success '@{-1} works' ' + test_rev_equivalent side @{-1} +' + +test_expect_success '@{-1}~2 works' ' + test_rev_equivalent side~2 @{-1}~2 +' + +test_expect_success '@{-1}^2 works' ' + test_rev_equivalent side^2 @{-1}^2 +' + +test_expect_success '@{-1}@{1} works' ' + test_rev_equivalent side@{1} @{-1}@{1} +' + +test_expect_success '@{-2} works' ' + test_rev_equivalent master @{-2} +' + +test_expect_success '@{-3} fails' ' + test_must_fail git rev-parse @{-3} +' + +test_done + + diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh new file mode 100755 index 0000000000..af721f9719 --- /dev/null +++ b/t/t1506-rev-parse-diagnosis.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='test git rev-parse diagnosis for invalid argument' + +exec </dev/null + +. ./test-lib.sh + +HASH_file= + +test_expect_success 'set up basic repo' ' + echo one > file.txt && + mkdir subdir && + echo two > subdir/file.txt && + echo three > subdir/file2.txt && + git add . && + git commit -m init && + echo four > index-only.txt && + git add index-only.txt && + echo five > disk-only.txt +' + +test_expect_success 'correct file objects' ' + HASH_file=$(git rev-parse HEAD:file.txt) && + git rev-parse HEAD:subdir/file.txt && + git rev-parse :index-only.txt && + (cd subdir && + git rev-parse HEAD:subdir/file2.txt && + test $HASH_file = $(git rev-parse HEAD:file.txt) && + test $HASH_file = $(git rev-parse :file.txt) && + test $HASH_file = $(git rev-parse :0:file.txt) ) +' + +test_expect_success 'incorrect revision id' ' + test_must_fail git rev-parse foobar:file.txt 2>error && + grep "Invalid object name '"'"'foobar'"'"'." error && + test_must_fail git rev-parse foobar 2> error && + grep "unknown revision or path not in the working tree." error +' + +test_expect_success 'incorrect file in sha1:path' ' + test_must_fail git rev-parse HEAD:nothing.txt 2> error && + grep "fatal: Path '"'"'nothing.txt'"'"' does not exist in '"'"'HEAD'"'"'" error && + test_must_fail git rev-parse HEAD:index-only.txt 2> error && + grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error && + (cd subdir && + test_must_fail git rev-parse HEAD:file2.txt 2> error && + grep "Did you mean '"'"'HEAD:subdir/file2.txt'"'"'?" error ) +' + +test_expect_success 'incorrect file in :path and :N:path' ' + test_must_fail git rev-parse :nothing.txt 2> error && + grep "fatal: Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error && + test_must_fail git rev-parse :1:nothing.txt 2> error && + grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error && + test_must_fail git rev-parse :1:file.txt 2> error && + grep "Did you mean '"'"':0:file.txt'"'"'?" error && + (cd subdir && + test_must_fail git rev-parse :1:file.txt 2> error && + grep "Did you mean '"'"':0:file.txt'"'"'?" error && + test_must_fail git rev-parse :file2.txt 2> error && + grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error && + test_must_fail git rev-parse :2:file2.txt 2> error && + grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error) && + test_must_fail git rev-parse :disk-only.txt 2> error && + grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error +' + +test_done diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh new file mode 100755 index 0000000000..8c8dfdaf9f --- /dev/null +++ b/t/t1507-rev-parse-upstream.sh @@ -0,0 +1,139 @@ +#!/bin/sh + +test_description='test <branch>@{upstream} syntax' + +. ./test-lib.sh + + +test_expect_success 'setup' ' + + test_commit 1 && + git checkout -b side && + test_commit 2 && + git checkout master && + git clone . clone && + test_commit 3 && + (cd clone && + test_commit 4 && + git branch --track my-side origin/side) + +' + +full_name () { + (cd clone && + git rev-parse --symbolic-full-name "$@") +} + +commit_subject () { + (cd clone && + git show -s --pretty=format:%s "$@") +} + +test_expect_success '@{upstream} resolves to correct full name' ' + test refs/remotes/origin/master = "$(full_name @{upstream})" +' + +test_expect_success '@{u} resolves to correct full name' ' + test refs/remotes/origin/master = "$(full_name @{u})" +' + +test_expect_success 'my-side@{upstream} resolves to correct full name' ' + test refs/remotes/origin/side = "$(full_name my-side@{u})" +' + +test_expect_success 'my-side@{u} resolves to correct commit' ' + git checkout side && + test_commit 5 && + (cd clone && git fetch) && + test 2 = "$(commit_subject my-side)" && + test 5 = "$(commit_subject my-side@{u})" +' + +test_expect_success 'not-tracking@{u} fails' ' + test_must_fail full_name non-tracking@{u} && + (cd clone && git checkout --no-track -b non-tracking) && + test_must_fail full_name non-tracking@{u} +' + +test_expect_success '<branch>@{u}@{1} resolves correctly' ' + test_commit 6 && + (cd clone && git fetch) && + test 5 = $(commit_subject my-side@{u}@{1}) +' + +test_expect_success '@{u} without specifying branch fails on a detached HEAD' ' + git checkout HEAD^0 && + test_must_fail git rev-parse @{u} +' + +test_expect_success 'checkout -b new my-side@{u} forks from the same' ' +( + cd clone && + git checkout -b new my-side@{u} && + git rev-parse --symbolic-full-name my-side@{u} >expect && + git rev-parse --symbolic-full-name new@{u} >actual && + test_cmp expect actual +) +' + +test_expect_success 'merge my-side@{u} records the correct name' ' +( + sq="'\''" && + cd clone || exit + git checkout master || exit + git branch -D new ;# can fail but is ok + git branch -t new my-side@{u} && + git merge -s ours new@{u} && + git show -s --pretty=format:%s >actual && + echo "Merge remote branch ${sq}origin/side${sq}" >expect && + test_cmp expect actual +) +' + +test_expect_success 'branch -d other@{u}' ' + git checkout -t -b other master && + git branch -d @{u} && + git for-each-ref refs/heads/master >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'checkout other@{u}' ' + git branch -f master HEAD && + git checkout -t -b another master && + git checkout @{u} && + git symbolic-ref HEAD >actual && + echo refs/heads/master >expect && + test_cmp expect actual +' + +cat >expect <<EOF +commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 +Reflog: master@{0} (C O Mitter <committer@example.com>) +Reflog message: branch: Created from HEAD +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 +EOF +test_expect_success 'log -g other@{u}' ' + git log -1 -g other@{u} >actual && + test_cmp expect actual +' + +cat >expect <<EOF +commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 +Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>) +Reflog message: branch: Created from HEAD +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 +EOF + +test_expect_success 'log -g other@{u}@{now}' ' + git log -1 -g other@{u}@{now} >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh new file mode 100755 index 0000000000..d5d6244178 --- /dev/null +++ b/t/t1508-at-combinations.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +test_description='test various @{X} syntax combinations together' +. ./test-lib.sh + +check() { +test_expect_${3:-success} "$1 = $2" " + echo '$2' >expect && + git log -1 --format=%s '$1' >actual && + test_cmp expect actual +" +} +nonsense() { +test_expect_${2:-success} "$1 is nonsensical" " + test_must_fail git log -1 '$1' +" +} +fail() { + "$@" failure +} + +test_expect_success 'setup' ' + test_commit master-one && + test_commit master-two && + git checkout -b upstream-branch && + test_commit upstream-one && + test_commit upstream-two && + git checkout -b old-branch && + test_commit old-one && + test_commit old-two && + git checkout -b new-branch && + test_commit new-one && + test_commit new-two && + git config branch.old-branch.remote . && + git config branch.old-branch.merge refs/heads/master && + git config branch.new-branch.remote . && + git config branch.new-branch.merge refs/heads/upstream-branch +' + +check HEAD new-two +check "@{1}" new-one +check "@{-1}" old-two +check "@{-1}@{1}" old-one +check "@{u}" upstream-two +check "@{u}@{1}" upstream-one +check "@{-1}@{u}" master-two +check "@{-1}@{u}@{1}" master-one +nonsense "@{u}@{-1}" +nonsense "@{1}@{u}" + +test_done diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh new file mode 100755 index 0000000000..7f60fd0b2e --- /dev/null +++ b/t/t1509-root-worktree.sh @@ -0,0 +1,249 @@ +#!/bin/sh + +test_description='Test Git when git repository is located at root + +This test requires write access in root. Do not bother if you do not +have a throwaway chroot or VM. + +Script t1509/prepare-chroot.sh may help you setup chroot, then you +can chroot in and execute this test from there. +' + +. ./test-lib.sh + +test_cmp_val() { + echo "$1" > expected + echo "$2" > result + test_cmp expected result +} + +test_vars() { + test_expect_success "$1: gitdir" ' + test_cmp_val "'"$2"'" "$(git rev-parse --git-dir)" + ' + + test_expect_success "$1: worktree" ' + test_cmp_val "'"$3"'" "$(git rev-parse --show-toplevel)" + ' + + test_expect_success "$1: prefix" ' + test_cmp_val "'"$4"'" "$(git rev-parse --show-prefix)" + ' +} + +test_foobar_root() { + test_expect_success 'add relative' ' + test -z "$(cd / && git ls-files)" && + git add foo/foome && + git add foo/bar/barme && + git add me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' + + test_expect_success 'add absolute' ' + test -z "$(cd / && git ls-files)" && + git add /foo/foome && + git add /foo/bar/barme && + git add /me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' + +} + +test_foobar_foo() { + test_expect_success 'add relative' ' + test -z "$(cd / && git ls-files)" && + git add foome && + git add bar/barme && + git add ../me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' + + test_expect_success 'add absolute' ' + test -z "$(cd / && git ls-files)" && + git add /foo/foome && + git add /foo/bar/barme && + git add /me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' +} + +test_foobar_foobar() { + test_expect_success 'add relative' ' + test -z "$(cd / && git ls-files)" && + git add ../foome && + git add barme && + git add ../../me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' + + test_expect_success 'add absolute' ' + test -z "$(cd / && git ls-files)" && + git add /foo/foome && + git add /foo/bar/barme && + git add /me && + ( cd / && git ls-files --stage ) > result && + test_cmp /ls.expected result && + rm "$(git rev-parse --git-dir)/index" + ' +} + +if ! test_have_prereq POSIXPERM || ! [ -w / ]; then + skip_all="Dangerous test skipped. Read this test if you want to execute it" + test_done +fi + +if [ "$IKNOWWHATIAMDOING" != "YES" ]; then + skip_all="You must set env var IKNOWWHATIAMDOING=YES in order to run this test" + test_done +fi + +if [ "$UID" = 0 ]; then + skip_all="No you can't run this with root" + test_done +fi + +ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d + +test_expect_success 'setup' ' + rm -rf /foo + mkdir /foo && + mkdir /foo/bar && + echo 1 > /foo/foome && + echo 1 > /foo/bar/barme && + echo 1 > /me +' + +say "GIT_DIR absolute, GIT_WORK_TREE set" + +test_expect_success 'go to /' 'cd /' + +cat >ls.expected <<EOF +100644 $ONE_SHA1 0 foo/bar/barme +100644 $ONE_SHA1 0 foo/foome +100644 $ONE_SHA1 0 me +EOF + +export GIT_DIR="$TRASH_DIRECTORY/.git" +export GIT_WORK_TREE=/ + +test_vars 'abs gitdir, root' "$GIT_DIR" "/" "" +test_foobar_root + +test_expect_success 'go to /foo' 'cd /foo' + +test_vars 'abs gitdir, foo' "$GIT_DIR" "/" "foo/" +test_foobar_foo + +test_expect_success 'go to /foo/bar' 'cd /foo/bar' + +test_vars 'abs gitdir, foo/bar' "$GIT_DIR" "/" "foo/bar/" +test_foobar_foobar + +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=/ + +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=/ + +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=/ + +test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/" +test_foobar_foobar + +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=. + +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=.. + +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=../.. + +test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/" +test_foobar_foobar + +say ".git at root" + +unset GIT_DIR +unset GIT_WORK_TREE + +test_expect_success 'go to /' 'cd /' +test_expect_success 'setup' ' + rm -rf /.git + echo "Initialized empty Git repository in /.git/" > expected && + git init > result && + test_cmp expected result +' + +test_vars 'auto gitdir, root' ".git" "/" "" +test_foobar_root + +test_expect_success 'go to /foo' 'cd /foo' +test_vars 'auto gitdir, foo' "/.git" "/" "foo/" +test_foobar_foo + +test_expect_success 'go to /foo/bar' 'cd /foo/bar' +test_vars 'auto gitdir, foo/bar' "/.git" "/" "foo/bar/" +test_foobar_foobar + +test_expect_success 'cleanup' 'rm -rf /.git' + +say "auto bare gitdir" + +# DESTROYYYYY!!!!! +test_expect_success 'setup' ' + rm -rf /refs /objects /info /hooks + rm /* + cd / && + echo "Initialized empty Git repository in /" > expected && + git init --bare > result && + test_cmp expected result +' + +test_vars 'auto gitdir, root' "." "" "" + +test_expect_success 'go to /foo' 'cd /foo' + +test_vars 'auto gitdir, root' "/" "" "" + +test_done diff --git a/t/t1509/excludes b/t/t1509/excludes new file mode 100644 index 0000000000..d4d21d31a9 --- /dev/null +++ b/t/t1509/excludes @@ -0,0 +1,14 @@ +*.o +*~ +*.bak +*.c +*.h +.git +contrib +Documentation +git-gui +gitk-git +gitweb +t/t4013 +t/t5100 +t/t5515 diff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh new file mode 100755 index 0000000000..c5334a8fa4 --- /dev/null +++ b/t/t1509/prepare-chroot.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +die() { + echo >&2 "$@" + exit 1 +} + +xmkdir() { + while [ -n "$1" ]; do + [ -d "$1" ] || mkdir "$1" || die "Unable to mkdir $1" + shift + done +} + +R="$1" + +[ -n "$R" ] || die "Usage: prepare-chroot.sh <root>" +[ -x git ] || die "This script needs to be executed at git source code's top directory" +[ -x /bin/busybox ] || die "You need busybox" + +xmkdir "$R" "$R/bin" "$R/etc" "$R/lib" "$R/dev" +[ -c "$R/dev/null" ] || die "/dev/null is missing. Do mknod $R/dev/null c 1 3 && chmod 666 $R/dev/null" +echo "root:x:0:0:root:/:/bin/sh" > "$R/etc/passwd" +echo "$(id -nu):x:$(id -u):$(id -g)::$(pwd)/t:/bin/sh" >> "$R/etc/passwd" +echo "root::0:root" > "$R/etc/group" +echo "$(id -ng)::$(id -g):$(id -nu)" >> "$R/etc/group" + +[ -x "$R/bin/busybox" ] || cp /bin/busybox "$R/bin/busybox" +[ -x "$R/bin/sh" ] || ln -s /bin/busybox "$R/bin/sh" +[ -x "$R/bin/su" ] || ln -s /bin/busybox "$R/bin/su" + +mkdir -p "$R$(pwd)" +rsync --exclude-from t/t1509/excludes -Ha . "$R$(pwd)" +ldd git | grep '/' | sed 's,.*\s\(/[^ ]*\).*,\1,' | while read i; do + mkdir -p "$R$(dirname $i)" + cp "$i" "$R/$i" +done +echo "Execute this in root: 'chroot $R /bin/su - $(id -nu)'" diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh index 03ea4dece4..de3edb5d57 100755 --- a/t/t2000-checkout-cache-clash.sh +++ b/t/t2000-checkout-cache-clash.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-checkout-index test. +test_description='git checkout-index test. This test registers the following filesystem structure in the cache: @@ -16,7 +16,7 @@ And then tries to checkout in a work tree that has the following: path0/file0 - a file in a directory path1 - a file -The git-checkout-index command should fail when attempting to checkout +The git checkout-index command should fail when attempting to checkout path0, finding it is occupied by a directory, and path1/file1, finding path1 is occupied by a non-directory. With "-f" flag, it should remove the conflicting paths and succeed. @@ -28,26 +28,33 @@ mkdir path1 date >path1/file1 test_expect_success \ - 'git-update-index --add various paths.' \ - 'git-update-index --add path0 path1/file1' + 'git update-index --add various paths.' \ + 'git update-index --add path0 path1/file1' rm -fr path0 path1 mkdir path0 date >path0/file0 date >path1 -test_expect_failure \ - 'git-checkout-index without -f should fail on conflicting work tree.' \ - 'git-checkout-index -a' +test_expect_success \ + 'git checkout-index without -f should fail on conflicting work tree.' \ + 'test_must_fail git checkout-index -a' test_expect_success \ - 'git-checkout-index with -f should succeed.' \ - 'git-checkout-index -f -a' + 'git checkout-index with -f should succeed.' \ + 'git checkout-index -f -a' test_expect_success \ - 'git-checkout-index conflicting paths.' \ + 'git checkout-index conflicting paths.' \ 'test -f path0 && test -d path1 && test -f path1/file1' -test_done - +test_expect_success SYMLINKS 'checkout-index -f twice with --prefix' ' + mkdir -p tar/get && + ln -s tar/get there && + echo first && + git checkout-index -a -f --prefix=there/ && + echo second && + git checkout-index -a -f --prefix=there/ +' +test_done diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh index 0dcab8f1de..98aa73e823 100755 --- a/t/t2001-checkout-cache-clash.sh +++ b/t/t2001-checkout-cache-clash.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-checkout-index test. +test_description='git checkout-index test. This test registers the following filesystem structure in the cache: @@ -26,46 +26,46 @@ show_files() { find path? -ls | sed -e 's/^[0-9]* * [0-9]* * \([-bcdl]\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \1 /' # what's in the cache, just mode and name - git-ls-files --stage | + git ls-files --stage | sed -e 's/^\([0-9]*\) [0-9a-f]* [0-3] /ca: \1 /' # what's in the tree, just mode and name. - git-ls-tree -r "$1" | + git ls-tree -r "$1" | sed -e 's/^\([0-9]*\) [^ ]* [0-9a-f]* /tr: \1 /' } mkdir path0 date >path0/file0 test_expect_success \ - 'git-update-index --add path0/file0' \ - 'git-update-index --add path0/file0' + 'git update-index --add path0/file0' \ + 'git update-index --add path0/file0' test_expect_success \ - 'writing tree out with git-write-tree' \ - 'tree1=$(git-write-tree)' + 'writing tree out with git write-tree' \ + 'tree1=$(git write-tree)' test_debug 'show_files $tree1' mkdir path1 date >path1/file1 test_expect_success \ - 'git-update-index --add path1/file1' \ - 'git-update-index --add path1/file1' + 'git update-index --add path1/file1' \ + 'git update-index --add path1/file1' test_expect_success \ - 'writing tree out with git-write-tree' \ - 'tree2=$(git-write-tree)' + 'writing tree out with git write-tree' \ + 'tree2=$(git write-tree)' test_debug 'show_files $tree2' rm -fr path1 test_expect_success \ 'read previously written tree and checkout.' \ - 'git-read-tree -m $tree1 && git-checkout-index -f -a' + 'git read-tree -m $tree1 && git checkout-index -f -a' test_debug 'show_files $tree1' -ln -s path0 path1 +test_expect_success SYMLINKS \ + 'git update-index --add a symlink.' \ + 'ln -s path0 path1 && + git update-index --add path1' test_expect_success \ - 'git-update-index --add a symlink.' \ - 'git-update-index --add path1' -test_expect_success \ - 'writing tree out with git-write-tree' \ - 'tree3=$(git-write-tree)' + 'writing tree out with git write-tree' \ + 'tree3=$(git write-tree)' test_debug 'show_files $tree3' # Morten says "Got that?" here. @@ -73,7 +73,7 @@ test_debug 'show_files $tree3' test_expect_success \ 'read previously written tree and checkout.' \ - 'git-read-tree $tree2 && git-checkout-index -f -a' + 'git read-tree $tree2 && git checkout-index -f -a' test_debug 'show_files $tree2' test_expect_success \ @@ -84,4 +84,3 @@ test_expect_success \ test ! -h path1/file1 && test -f path1/file1' test_done - diff --git a/t/t2002-checkout-cache-u.sh b/t/t2002-checkout-cache-u.sh index 4352ddb1cb..70361c806e 100755 --- a/t/t2002-checkout-cache-u.sh +++ b/t/t2002-checkout-cache-u.sh @@ -3,31 +3,31 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-checkout-index -u test. +test_description='git checkout-index -u test. -With -u flag, git-checkout-index internally runs the equivalent of -git-update-index --refresh on the checked out entry.' +With -u flag, git checkout-index internally runs the equivalent of +git update-index --refresh on the checked out entry.' . ./test-lib.sh test_expect_success \ 'preparation' ' echo frotz >path0 && -git-update-index --add path0 && -t=$(git-write-tree)' +git update-index --add path0 && +t=$(git write-tree)' -test_expect_failure \ -'without -u, git-checkout-index smudges stat information.' ' +test_expect_success \ +'without -u, git checkout-index smudges stat information.' ' rm -f path0 && -git-read-tree $t && -git-checkout-index -f -a && -git-diff-files | diff - /dev/null' +git read-tree $t && +git checkout-index -f -a && +test_must_fail git diff-files --exit-code' test_expect_success \ -'with -u, git-checkout-index picks up stat information from new files.' ' +'with -u, git checkout-index picks up stat information from new files.' ' rm -f path0 && -git-read-tree $t && -git-checkout-index -u -f -a && -git-diff-files | diff - /dev/null' +git read-tree $t && +git checkout-index -u -f -a && +git diff-files --exit-code' test_done diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh index f9bc90aee4..02a4fc5d36 100755 --- a/t/t2003-checkout-cache-mkdir.sh +++ b/t/t2003-checkout-cache-mkdir.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-checkout-index --prefix test. +test_description='git checkout-index --prefix test. This test makes sure that --prefix option works as advertised, and also verifies that such leading path may contain symlinks, unlike @@ -17,14 +17,14 @@ test_expect_success \ 'mkdir path1 && echo frotz >path0 && echo rezrov >path1/file1 && - git-update-index --add path0 path1/file1' + git update-index --add path0 path1/file1' -test_expect_success \ +test_expect_success SYMLINKS \ 'have symlink in place where dir is expected.' \ 'rm -fr path0 path1 && mkdir path2 && ln -s path2 path1 && - git-checkout-index -f -a && + git checkout-index -f -a && test ! -h path1 && test -d path1 && test -f path1/file1 && test ! -f path2/file1' @@ -32,7 +32,7 @@ test_expect_success \ 'use --prefix=path2/' \ 'rm -fr path0 path1 path2 && mkdir path2 && - git-checkout-index --prefix=path2/ -f -a && + git checkout-index --prefix=path2/ -f -a && test -f path2/path0 && test -f path2/path1/file1 && test ! -f path0 && @@ -41,7 +41,7 @@ test_expect_success \ test_expect_success \ 'use --prefix=tmp-' \ 'rm -fr path0 path1 path2 tmp* && - git-checkout-index --prefix=tmp- -f -a && + git checkout-index --prefix=tmp- -f -a && test -f tmp-path0 && test -f tmp-path1/file1 && test ! -f path0 && @@ -52,42 +52,42 @@ test_expect_success \ 'rm -fr path0 path1 path2 tmp* && echo nitfol >tmp-path1 && mkdir tmp-path0 && - git-checkout-index --prefix=tmp- -f -a && + git checkout-index --prefix=tmp- -f -a && test -f tmp-path0 && test -f tmp-path1/file1 && test ! -f path0 && test ! -f path1/file1' # Linus fix #1 -test_expect_success \ +test_expect_success SYMLINKS \ 'use --prefix=tmp/orary/ where tmp is a symlink' \ 'rm -fr path0 path1 path2 tmp* && mkdir tmp1 tmp1/orary && ln -s tmp1 tmp && - git-checkout-index --prefix=tmp/orary/ -f -a && + git checkout-index --prefix=tmp/orary/ -f -a && test -d tmp1/orary && test -f tmp1/orary/path0 && test -f tmp1/orary/path1/file1 && test -h tmp' # Linus fix #2 -test_expect_success \ +test_expect_success SYMLINKS \ 'use --prefix=tmp/orary- where tmp is a symlink' \ 'rm -fr path0 path1 path2 tmp* && mkdir tmp1 && ln -s tmp1 tmp && - git-checkout-index --prefix=tmp/orary- -f -a && + git checkout-index --prefix=tmp/orary- -f -a && test -f tmp1/orary-path0 && test -f tmp1/orary-path1/file1 && test -h tmp' # Linus fix #3 -test_expect_success \ +test_expect_success SYMLINKS \ 'use --prefix=tmp- where tmp-path1 is a symlink' \ 'rm -fr path0 path1 path2 tmp* && mkdir tmp1 && ln -s tmp1 tmp-path1 && - git-checkout-index --prefix=tmp- -f -a && + git checkout-index --prefix=tmp- -f -a && test -f tmp-path0 && test ! -h tmp-path1 && test -d tmp-path1 && diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index c100959cad..36cca14d95 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -3,9 +3,9 @@ # Copyright (c) 2006 Shawn Pearce # -test_description='git-checkout-index --temp test. +test_description='git checkout-index --temp test. -With --temp flag, git-checkout-index writes to temporary merge files +With --temp flag, git checkout-index writes to temporary merge files rather than the tracked path.' . ./test-lib.sh @@ -18,28 +18,28 @@ echo tree1path1 >path1 && echo tree1path3 >path3 && echo tree1path4 >path4 && echo tree1asubdir/path5 >asubdir/path5 && -git-update-index --add path0 path1 path3 path4 asubdir/path5 && -t1=$(git-write-tree) && +git update-index --add path0 path1 path3 path4 asubdir/path5 && +t1=$(git write-tree) && rm -f path* .merge_* out .git/index && echo tree2path0 >path0 && echo tree2path1 >path1 && echo tree2path2 >path2 && echo tree2path4 >path4 && -git-update-index --add path0 path1 path2 path4 && -t2=$(git-write-tree) && +git update-index --add path0 path1 path2 path4 && +t2=$(git write-tree) && rm -f path* .merge_* out .git/index && echo tree2path0 >path0 && echo tree3path1 >path1 && echo tree3path2 >path2 && echo tree3path3 >path3 && -git-update-index --add path0 path1 path2 path3 && -t3=$(git-write-tree)' +git update-index --add path0 path1 path2 path3 && +t3=$(git write-tree)' test_expect_success \ 'checkout one stage 0 to temporary file' ' rm -f path* .merge_* out .git/index && -git-read-tree $t1 && -git-checkout-index --temp -- path1 >out && +git read-tree $t1 && +git checkout-index --temp -- path1 >out && test $(wc -l <out) = 1 && test $(cut "-d " -f2 out) = path1 && p=$(cut "-d " -f1 out) && @@ -49,8 +49,8 @@ test $(cat $p) = tree1path1' test_expect_success \ 'checkout all stage 0 to temporary files' ' rm -f path* .merge_* out .git/index && -git-read-tree $t1 && -git-checkout-index -a --temp >out && +git read-tree $t1 && +git checkout-index -a --temp >out && test $(wc -l <out) = 5 && for f in path0 path1 path3 path4 asubdir/path5 do @@ -63,12 +63,12 @@ done' test_expect_success \ 'prepare 3-way merge' ' rm -f path* .merge_* out .git/index && -git-read-tree -m $t1 $t2 $t3' +git read-tree -m $t1 $t2 $t3' test_expect_success \ 'checkout one stage 2 to temporary file' ' rm -f path* .merge_* out && -git-checkout-index --stage=2 --temp -- path1 >out && +git checkout-index --stage=2 --temp -- path1 >out && test $(wc -l <out) = 1 && test $(cut "-d " -f2 out) = path1 && p=$(cut "-d " -f1 out) && @@ -78,7 +78,7 @@ test $(cat $p) = tree2path1' test_expect_success \ 'checkout all stage 2 to temporary files' ' rm -f path* .merge_* out && -git-checkout-index --all --stage=2 --temp >out && +git checkout-index --all --stage=2 --temp >out && test $(wc -l <out) = 3 && for f in path1 path2 path4 do @@ -91,13 +91,13 @@ done' test_expect_success \ 'checkout all stages/one file to nothing' ' rm -f path* .merge_* out && -git-checkout-index --stage=all --temp -- path0 >out && +git checkout-index --stage=all --temp -- path0 >out && test $(wc -l <out) = 0' test_expect_success \ 'checkout all stages/one file to temporary files' ' rm -f path* .merge_* out && -git-checkout-index --stage=all --temp -- path1 >out && +git checkout-index --stage=all --temp -- path1 >out && test $(wc -l <out) = 1 && test $(cut "-d " -f2 out) = path1 && cut "-d " -f1 out | (read s1 s2 s3 && @@ -111,7 +111,7 @@ test $(cat $s3) = tree3path1)' test_expect_success \ 'checkout some stages/one file to temporary files' ' rm -f path* .merge_* out && -git-checkout-index --stage=all --temp -- path2 >out && +git checkout-index --stage=all --temp -- path2 >out && test $(wc -l <out) = 1 && test $(cut "-d " -f2 out) = path2 && cut "-d " -f1 out | (read s1 s2 s3 && @@ -124,7 +124,7 @@ test $(cat $s3) = tree3path2)' test_expect_success \ 'checkout all stages/all files to temporary files' ' rm -f path* .merge_* out && -git-checkout-index -a --stage=all --temp >out && +git checkout-index -a --stage=all --temp >out && test $(wc -l <out) = 5' test_expect_success \ @@ -184,7 +184,7 @@ test $(cat $s1) = tree1asubdir/path5)' test_expect_success \ 'checkout --temp within subdir' ' (cd asubdir && - git-checkout-index -a --stage=all >out && + git checkout-index -a --stage=all >out && test $(wc -l <out) = 1 && test $(grep path5 out | cut "-d " -f2) = path5 && grep path5 out | cut "-d " -f1 | (read s1 s2 s3 && @@ -194,15 +194,15 @@ test_expect_success \ test $(cat ../$s1) = tree1asubdir/path5) )' -test_expect_success \ +test_expect_success SYMLINKS \ 'checkout --temp symlink' ' rm -f path* .merge_* out .git/index && ln -s b a && -git-update-index --add a && -t4=$(git-write-tree) && +git update-index --add a && +t4=$(git write-tree) && rm -f .git/index && -git-read-tree $t4 && -git-checkout-index --temp -a >out && +git read-tree $t4 && +git checkout-index --temp -a >out && test $(wc -l <out) = 1 && test $(cut "-d " -f2 out) = a && p=$(cut "-d " -f1 out) && diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh index e34a515333..9fa5610474 100755 --- a/t/t2005-checkout-index-symlinks.sh +++ b/t/t2005-checkout-index-symlinks.sh @@ -3,26 +3,26 @@ # Copyright (c) 2007 Johannes Sixt # -test_description='git-checkout-index on filesystem w/o symlinks test. +test_description='git checkout-index on filesystem w/o symlinks test. -This tests that git-checkout-index creates a symbolic link as a plain +This tests that git checkout-index creates a symbolic link as a plain file if core.symlinks is false.' . ./test-lib.sh test_expect_success \ 'preparation' ' -git-config core.symlinks false && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git-update-index --index-info' +git config core.symlinks false && +l=$(printf file | git hash-object -t blob -w --stdin) && +echo "120000 $l symlink" | git update-index --index-info' test_expect_success \ 'the checked-out symlink must be a file' ' -git-checkout-index symlink && +git checkout-index symlink && test -f symlink' test_expect_success \ 'the file must be the blob we added during the setup' ' -test "$(git-hash-object -t blob symlink)" = $l' +test "$(git hash-object -t blob symlink)" = $l' test_done diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh new file mode 100755 index 0000000000..05cc8fdd01 --- /dev/null +++ b/t/t2007-checkout-symlink.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# +# Copyright (c) 2007 Junio C Hamano + +test_description='git checkout to switch between branches with symlink<->dir' + +. ./test-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all="symbolic links not supported - skipping tests" + test_done +fi + +test_expect_success setup ' + + mkdir frotz && + echo hello >frotz/filfre && + git add frotz/filfre && + test_tick && + git commit -m "master has file frotz/filfre" && + + git branch side && + + echo goodbye >nitfol && + git add nitfol + test_tick && + git commit -m "master adds file nitfol" && + + git checkout side && + + git rm --cached frotz/filfre && + mv frotz xyzzy && + ln -s xyzzy frotz && + git add xyzzy/filfre frotz && + test_tick && + git commit -m "side moves frotz/ to xyzzy/ and adds frotz->xyzzy/" + +' + +test_expect_success 'switch from symlink to dir' ' + + git checkout master + +' + +test_expect_success 'Remove temporary directories & switch to master' ' + rm -fr frotz xyzzy nitfol && + git checkout -f master +' + +test_expect_success 'switch from dir to symlink' ' + + git checkout side + +' + +test_done diff --git a/t/t2008-checkout-subdir.sh b/t/t2008-checkout-subdir.sh new file mode 100755 index 0000000000..3e098ab31e --- /dev/null +++ b/t/t2008-checkout-subdir.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# +# Copyright (c) 2007 David Symonds + +test_description='git checkout from subdirectories' + +. ./test-lib.sh + +test_expect_success setup ' + + echo "base" > file0 && + git add file0 && + mkdir dir1 && + echo "hello" > dir1/file1 && + git add dir1/file1 && + mkdir dir2 && + echo "bonjour" > dir2/file2 && + git add dir2/file2 && + test_tick && + git commit -m "populate tree" + +' + +test_expect_success 'remove and restore with relative path' ' + + ( + cd dir1 && + rm ../file0 && + git checkout HEAD -- ../file0 && + test "base" = "$(cat ../file0)" && + rm ../dir2/file2 && + git checkout HEAD -- ../dir2/file2 && + test "bonjour" = "$(cat ../dir2/file2)" && + rm ../file0 ./file1 && + git checkout HEAD -- .. && + test "base" = "$(cat ../file0)" && + test "hello" = "$(cat file1)" + ) + +' + +test_expect_success 'checkout with empty prefix' ' + + rm file0 && + git checkout HEAD -- file0 && + test "base" = "$(cat file0)" + +' + +test_expect_success 'checkout with simple prefix' ' + + rm dir1/file1 && + git checkout HEAD -- dir1 && + test "hello" = "$(cat dir1/file1)" && + rm dir1/file1 && + git checkout HEAD -- dir1/file1 && + test "hello" = "$(cat dir1/file1)" + +' + +# This is not expected to work as ls-files was not designed +# to deal with such. Enable it when ls-files is updated. +: test_expect_success 'checkout with complex relative path' ' + + rm file1 && + git checkout HEAD -- ../dir1/../dir1/file1 && test -f ./file1 + +' + +test_expect_success 'relative path outside tree should fail' \ + 'test_must_fail git checkout HEAD -- ../../Makefile' + +test_expect_success 'incorrect relative path to file should fail (1)' \ + 'test_must_fail git checkout HEAD -- ../file0' + +test_expect_success 'incorrect relative path should fail (2)' \ + '( cd dir1 && test_must_fail git checkout HEAD -- ./file0 )' + +test_expect_success 'incorrect relative path should fail (3)' \ + '( cd dir1 && test_must_fail git checkout HEAD -- ../../file0 )' + +test_done diff --git a/t/t2009-checkout-statinfo.sh b/t/t2009-checkout-statinfo.sh new file mode 100755 index 0000000000..f3c2152087 --- /dev/null +++ b/t/t2009-checkout-statinfo.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='checkout should leave clean stat info' + +. ./test-lib.sh + +test_expect_success 'setup' ' + + echo hello >world && + git update-index --add world && + git commit -m initial && + git branch side && + echo goodbye >world && + git update-index --add world && + git commit -m second + +' + +test_expect_success 'branch switching' ' + + git reset --hard && + test "$(git diff-files --raw)" = "" && + + git checkout master && + test "$(git diff-files --raw)" = "" && + + git checkout side && + test "$(git diff-files --raw)" = "" && + + git checkout master && + test "$(git diff-files --raw)" = "" + +' + +test_expect_success 'path checkout' ' + + git reset --hard && + test "$(git diff-files --raw)" = "" && + + git checkout master world && + test "$(git diff-files --raw)" = "" && + + git checkout side world && + test "$(git diff-files --raw)" = "" && + + git checkout master world && + test "$(git diff-files --raw)" = "" + +' + +test_done + diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh new file mode 100755 index 0000000000..7cc0a3582e --- /dev/null +++ b/t/t2010-checkout-ambiguous.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='checkout and pathspecs/refspecs ambiguities' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo hello >world && + echo hello >all && + git add all world && + git commit -m initial && + git branch world +' + +test_expect_success 'reference must be a tree' ' + test_must_fail git checkout $(git hash-object ./all) -- +' + +test_expect_success 'branch switching' ' + test "refs/heads/master" = "$(git symbolic-ref HEAD)" && + git checkout world -- && + test "refs/heads/world" = "$(git symbolic-ref HEAD)" +' + +test_expect_success 'checkout world from the index' ' + echo bye > world && + git checkout -- world && + git diff --exit-code --quiet +' + +test_expect_success 'non ambiguous call' ' + git checkout all +' + +test_expect_success 'allow the most common case' ' + git checkout world && + test "refs/heads/world" = "$(git symbolic-ref HEAD)" +' + +test_expect_success 'check ambiguity' ' + test_must_fail git checkout world all +' + +test_expect_success 'disambiguate checking out from a tree-ish' ' + echo bye > world && + git checkout world -- world && + git diff --exit-code --quiet +' + +test_done diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh new file mode 100755 index 0000000000..15ebdc26eb --- /dev/null +++ b/t/t2011-checkout-invalid-head.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +test_description='checkout switching away from an invalid branch' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo hello >world && + git add world && + git commit -m initial +' + +test_expect_success 'checkout should not start branch from a tree' ' + test_must_fail git checkout -b newbranch master^{tree} +' + +test_expect_success 'checkout master from invalid HEAD' ' + echo 0000000000000000000000000000000000000000 >.git/HEAD && + git checkout master -- +' + +test_done diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh new file mode 100755 index 0000000000..b44de9dc62 --- /dev/null +++ b/t/t2012-checkout-last.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +test_description='checkout can switch to last branch and merge base' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo hello >world && + git add world && + git commit -m initial && + git branch other && + echo "hello again" >>world && + git add world && + git commit -m second +' + +test_expect_success '"checkout -" does not work initially' ' + test_must_fail git checkout - +' + +test_expect_success 'first branch switch' ' + git checkout other +' + +test_expect_success '"checkout -" switches back' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master" +' + +test_expect_success '"checkout -" switches forth' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other" +' + +test_expect_success 'detach HEAD' ' + git checkout $(git rev-parse HEAD) +' + +test_expect_success '"checkout -" attaches again' ' + git checkout - && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other" +' + +test_expect_success '"checkout -" detaches again' ' + git checkout - && + test "z$(git rev-parse HEAD)" = "z$(git rev-parse other)" && + test_must_fail git symbolic-ref HEAD +' + +test_expect_success 'more switches' ' + for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 + do + git checkout -b branch$i + done +' + +more_switches () { + for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 + do + git checkout branch$i + done +} + +test_expect_success 'switch to the last' ' + more_switches && + git checkout @{-1} && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch2" +' + +test_expect_success 'switch to second from the last' ' + more_switches && + git checkout @{-2} && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch3" +' + +test_expect_success 'switch to third from the last' ' + more_switches && + git checkout @{-3} && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch4" +' + +test_expect_success 'switch to fourth from the last' ' + more_switches && + git checkout @{-4} && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch5" +' + +test_expect_success 'switch to twelfth from the last' ' + more_switches && + git checkout @{-12} && + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch13" +' + +test_expect_success 'merge base test setup' ' + git checkout -b another other && + echo "hello again" >>world && + git add world && + git commit -m third +' + +test_expect_success 'another...master' ' + git checkout another && + git checkout another...master && + test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)" +' + +test_expect_success '...master' ' + git checkout another && + git checkout ...master && + test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)" +' + +test_expect_success 'master...' ' + git checkout another && + git checkout master... && + test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)" +' + +test_done diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh new file mode 100755 index 0000000000..fda3f0af7e --- /dev/null +++ b/t/t2013-checkout-submodule.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='checkout can handle submodules' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir submodule && + (cd submodule && + git init && + test_commit first) && + git add submodule && + test_tick && + git commit -m superproject && + (cd submodule && + test_commit second) && + git add submodule && + test_tick && + git commit -m updated.superproject +' + +test_expect_success '"reset <submodule>" updates the index' ' + git update-index --refresh && + git diff-files --quiet && + git diff-index --quiet --cached HEAD && + test_must_fail git reset HEAD^ submodule && + test_must_fail git diff-files --quiet && + git reset submodule && + git diff-files --quiet +' + +test_expect_success '"checkout <submodule>" updates the index only' ' + git update-index --refresh && + git diff-files --quiet && + git diff-index --quiet --cached HEAD && + git checkout HEAD^ submodule && + test_must_fail git diff-files --quiet && + git checkout HEAD submodule && + git diff-files --quiet +' + +test_done diff --git a/t/t2014-switch.sh b/t/t2014-switch.sh new file mode 100755 index 0000000000..ccfb147113 --- /dev/null +++ b/t/t2014-switch.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +test_description='Peter MacMillan' +. ./test-lib.sh + +test_expect_success setup ' + echo Hello >file && + git add file && + test_tick && + git commit -m V1 && + echo Hello world >file && + git add file && + git checkout -b other +' + +test_expect_success 'check all changes are staged' ' + git diff --exit-code +' + +test_expect_success 'second commit' ' + git commit -m V2 +' + +test_expect_success 'check' ' + git diff --cached --exit-code +' + +test_done diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh new file mode 100755 index 0000000000..c551d39a66 --- /dev/null +++ b/t/t2015-checkout-unborn.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +test_description='checkout from unborn branch protects contents' +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir parent && + (cd parent && + git init && + echo content >file && + git add file && + git commit -m base + ) && + git fetch parent master:origin +' + +test_expect_success 'checkout from unborn preserves untracked files' ' + echo precious >expect && + echo precious >file && + test_must_fail git checkout -b new origin && + test_cmp expect file +' + +test_expect_success 'checkout from unborn preserves index contents' ' + echo precious >expect && + echo precious >file && + git add file && + test_must_fail git checkout -b new origin && + test_cmp expect file && + git show :file >file && + test_cmp expect file +' + +test_expect_success 'checkout from unborn merges identical index contents' ' + echo content >file && + git add file && + git checkout -b new origin +' + +test_done diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh new file mode 100755 index 0000000000..2144184d79 --- /dev/null +++ b/t/t2016-checkout-patch.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +test_description='git checkout --patch' + +. ./lib-patch-mode.sh + +test_expect_success 'setup' ' + mkdir dir && + echo parent > dir/foo && + echo dummy > bar && + git add bar dir/foo && + git commit -m initial && + test_tick && + test_commit second dir/foo head && + set_and_save_state bar bar_work bar_index && + save_head +' + +# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' + +test_expect_success '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' ' + (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' ' + 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' ' + 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' ' + (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 + # 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^' ' + # 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' ' + set_state dir/foo work index && + rm dir/foo && + (echo n; echo y) | git checkout -p && + verify_saved_state bar && + verify_state dir/foo index index +' + +# The idea in the rest is that bar sorts first, so we always say 'y' +# first and if the path limiter fails it'll apply to bar instead of +# 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' ' + 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' ' + 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' ' + # 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' ' + 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) && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success 'none of this moved HEAD' ' + verify_saved_head +' + +test_done 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/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh new file mode 100755 index 0000000000..cb7effe0a3 --- /dev/null +++ b/t/t2030-unresolve-info.sh @@ -0,0 +1,170 @@ +#!/bin/sh + +test_description='undoing resolution' + +. ./test-lib.sh + +check_resolve_undo () { + msg=$1 + shift + while case $# in + 0) break ;; + 1|2|3) die "Bug in check-resolve-undo test" ;; + esac + do + path=$1 + shift + for stage in 1 2 3 + do + sha1=$1 + shift + case "$sha1" in + '') continue ;; + esac + sha1=$(git rev-parse --verify "$sha1") + printf "100644 %s %s\t%s\n" $sha1 $stage $path + done + done >"$msg.expect" && + git ls-files --resolve-undo >"$msg.actual" && + test_cmp "$msg.expect" "$msg.actual" +} + +prime_resolve_undo () { + git reset --hard && + git checkout second^0 && + test_tick && + test_must_fail git merge third^0 && + echo merge does not leave anything && + check_resolve_undo empty && + echo different >fi/le && + git add fi/le && + echo resolving records && + check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le +} + +test_expect_success setup ' + mkdir fi && + test_commit initial fi/le first && + git branch side && + git branch another && + test_commit second fi/le second && + git checkout side && + test_commit third fi/le third && + git checkout another && + test_commit fourth fi/le fourth && + git checkout master +' + +test_expect_success 'add records switch clears' ' + prime_resolve_undo && + test_tick && + git commit -m merged && + echo committing keeps && + check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le && + git checkout second^0 && + echo switching clears && + check_resolve_undo cleared +' + +test_expect_success 'rm records reset clears' ' + prime_resolve_undo && + test_tick && + git commit -m merged && + echo committing keeps && + check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le && + + echo merge clears upfront && + test_must_fail git merge fourth^0 && + check_resolve_undo nuked && + + git rm -f fi/le && + echo resolving records && + check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le && + + git reset --hard && + echo resetting discards && + check_resolve_undo discarded +' + +test_expect_success 'plumbing clears' ' + prime_resolve_undo && + test_tick && + git commit -m merged && + echo committing keeps && + check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le && + + echo plumbing clear && + git update-index --clear-resolve-undo && + check_resolve_undo cleared +' + +test_expect_success 'add records checkout -m undoes' ' + prime_resolve_undo && + git diff HEAD && + git checkout --conflict=merge fi/le && + echo checkout used the record and removed it && + check_resolve_undo removed && + echo the index and the work tree is unmerged again && + git diff >actual && + grep "^++<<<<<<<" actual +' + +test_expect_success 'unmerge with plumbing' ' + prime_resolve_undo && + git update-index --unresolve fi/le && + git ls-files -u >actual && + test $(wc -l <actual) = 3 +' + +test_expect_success 'rerere and rerere forget' ' + mkdir .git/rr-cache && + prime_resolve_undo && + echo record the resolution && + git rerere && + rerere_id=$(cd .git/rr-cache && echo */postimage) && + rerere_id=${rerere_id%/postimage} && + test -f .git/rr-cache/$rerere_id/postimage && + git checkout -m fi/le && + echo resurrect the conflict && + grep "^=======" fi/le && + echo reresolve the conflict && + git rerere && + test "z$(cat fi/le)" = zdifferent && + echo register the resolution again && + git add fi/le && + check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le && + test -z "$(git ls-files -u)" && + git rerere forget fi/le && + ! test -f .git/rr-cache/$rerere_id/postimage && + tr "\0" "\n" <.git/MERGE_RR >actual && + echo "$rerere_id fi/le" >expect && + test_cmp expect actual +' + +test_expect_success 'rerere and rerere forget (subdirectory)' ' + rm -fr .git/rr-cache && + mkdir .git/rr-cache && + prime_resolve_undo && + echo record the resolution && + (cd fi && git rerere) && + rerere_id=$(cd .git/rr-cache && echo */postimage) && + rerere_id=${rerere_id%/postimage} && + test -f .git/rr-cache/$rerere_id/postimage && + (cd fi && git checkout -m le) && + echo resurrect the conflict && + grep "^=======" fi/le && + echo reresolve the conflict && + (cd fi && git rerere) && + test "z$(cat fi/le)" = zdifferent && + echo register the resolution again && + (cd fi && git add le) && + check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le && + test -z "$(git ls-files -u)" && + (cd fi && git rerere forget le) && + ! test -f .git/rr-cache/$rerere_id/postimage && + tr "\0" "\n" <.git/MERGE_RR >actual && + echo "$rerere_id fi/le" >expect && + test_cmp expect actual +' + +test_done diff --git a/t/t2050-git-dir-relative.sh b/t/t2050-git-dir-relative.sh new file mode 100755 index 0000000000..b7131d8c08 --- /dev/null +++ b/t/t2050-git-dir-relative.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='check problems with relative GIT_DIR + +This test creates a working tree state with a file and subdir: + + top (committed several times) + subdir (a subdirectory) + +It creates a commit-hook and tests it, then moves .git +into the subdir while keeping the worktree location, +and tries commits from the top and the subdir, checking +that the commit-hook still gets called.' + +. ./test-lib.sh + +COMMIT_FILE="$(pwd)/output" +export COMMIT_FILE + +test_expect_success 'Setting up post-commit hook' ' +mkdir -p .git/hooks && +echo >.git/hooks/post-commit "#!/bin/sh +touch \"\${COMMIT_FILE}\" +echo Post commit hook was called." && +chmod +x .git/hooks/post-commit' + +test_expect_success 'post-commit hook used ordinarily' ' +echo initial >top && +git add top +git commit -m initial && +test -r "${COMMIT_FILE}" +' + +rm -rf "${COMMIT_FILE}" +mkdir subdir +mv .git subdir + +test_expect_success 'post-commit-hook created and used from top dir' ' +echo changed >top && +git --git-dir subdir/.git add top && +git --git-dir subdir/.git commit -m topcommit && +test -r "${COMMIT_FILE}" +' + +rm -rf "${COMMIT_FILE}" + +test_expect_success 'post-commit-hook from sub dir' ' +echo changed again >top +cd subdir && +git --git-dir .git --work-tree .. add ../top && +git --git-dir .git --work-tree .. commit -m subcommit && +test -r "${COMMIT_FILE}" +' + +test_done diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh index 5bc0a3bed3..2df3fdde8b 100755 --- a/t/t2100-update-cache-badpath.sh +++ b/t/t2100-update-cache-badpath.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-update-index nonsense-path test. +test_description='git update-index nonsense-path test. This test creates the following structure in the cache: @@ -12,7 +12,7 @@ This test creates the following structure in the cache: path2/file2 - a file in a directory path3/file3 - a file in a directory -and tries to git-update-index --add the following: +and tries to git update-index --add the following: path0/file0 - a file in a directory path1/file1 - a file in a directory @@ -26,26 +26,36 @@ All of the attempts should fail. mkdir path2 path3 date >path0 -ln -s xyzzy path1 +if test_have_prereq SYMLINKS +then + ln -s xyzzy path1 +else + date > path1 +fi date >path2/file2 date >path3/file3 test_expect_success \ - 'git-update-index --add to add various paths.' \ - 'git-update-index --add -- path0 path1 path2/file2 path3/file3' + 'git update-index --add to add various paths.' \ + 'git update-index --add -- path0 path1 path2/file2 path3/file3' rm -fr path? mkdir path0 path1 date >path2 -ln -s frotz path3 +if test_have_prereq SYMLINKS +then + ln -s frotz path3 +else + date > path3 +fi date >path0/file0 date >path1/file1 for p in path0/file0 path1/file1 path2 path3 do - test_expect_failure \ - "git-update-index to add conflicting path $p should fail." \ - "git-update-index --add -- $p" + test_expect_success \ + "git update-index to add conflicting path $p should fail." \ + "test_must_fail git update-index --add -- $p" done test_done diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh index a78ea7f0b0..648184fd98 100755 --- a/t/t2101-update-index-reupdate.sh +++ b/t/t2101-update-index-reupdate.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='git-update-index --again test. +test_description='git update-index --again test. ' . ./test-lib.sh @@ -15,32 +15,32 @@ EOF test_expect_success 'update-index --add' \ 'echo hello world >file1 && echo goodbye people >file2 && - git-update-index --add file1 file2 && - git-ls-files -s >current && + git update-index --add file1 file2 && + git ls-files -s >current && cmp current expected' test_expect_success 'update-index --again' \ 'rm -f file1 && echo hello everybody >file2 && - if git-update-index --again + if git update-index --again then echo should have refused to remove file1 exit 1 else echo happy - failed as expected fi && - git-ls-files -s >current && + git ls-files -s >current && cmp current expected' cat > expected <<\EOF 100644 0f1ae1422c2bf43f117d3dbd715c988a9ed2103f 0 file2 EOF test_expect_success 'update-index --remove --again' \ - 'git-update-index --remove --again && - git-ls-files -s >current && + 'git update-index --remove --again && + git ls-files -s >current && cmp current expected' -test_expect_success 'first commit' 'git-commit -m initial' +test_expect_success 'first commit' 'git commit -m initial' cat > expected <<\EOF 100644 53ab446c3f4e42ce9bb728a0ccb283a101be4979 0 dir1/file3 @@ -50,11 +50,11 @@ test_expect_success 'update-index again' \ 'mkdir -p dir1 && echo hello world >dir1/file3 && echo goodbye people >file2 && - git-update-index --add file2 dir1/file3 && + git update-index --add file2 dir1/file3 && echo hello everybody >file2 echo happy >dir1/file3 && - git-update-index --again && - git-ls-files -s >current && + git update-index --again && + git ls-files -s >current && cmp current expected' cat > expected <<\EOF @@ -65,9 +65,9 @@ test_expect_success 'update-index --update from subdir' \ 'echo not so happy >file2 && cd dir1 && cat ../file2 >file3 && - git-update-index --again && + git update-index --again && cd .. && - git-ls-files -s >current && + git ls-files -s >current && cmp current expected' cat > expected <<\EOF @@ -77,8 +77,8 @@ EOF test_expect_success 'update-index --update with pathspec' \ 'echo very happy >file2 && cat file2 >dir1/file3 && - git-update-index --again dir1/ && - git-ls-files -s >current && + git update-index --again dir1/ && + git ls-files -s >current && cmp current expected' test_done diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh index 969ef891d3..4d0d0a3515 100755 --- a/t/t2102-update-index-symlinks.sh +++ b/t/t2102-update-index-symlinks.sh @@ -3,29 +3,29 @@ # Copyright (c) 2007 Johannes Sixt # -test_description='git-update-index on filesystem w/o symlinks test. +test_description='git update-index on filesystem w/o symlinks test. -This tests that git-update-index keeps the symbolic link property +This tests that git update-index keeps the symbolic link property even if a plain file is in the working tree if core.symlinks is false.' . ./test-lib.sh test_expect_success \ 'preparation' ' -git-config core.symlinks false && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git-update-index --index-info' +git config core.symlinks false && +l=$(printf file | git hash-object -t blob -w --stdin) && +echo "120000 $l symlink" | git update-index --index-info' test_expect_success \ 'modify the symbolic link' ' -echo -n new-file > symlink && -git-update-index symlink' +printf new-file > symlink && +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;; -*) echo fail; git-ls-files --stage --cached symlink; (exit 1);; +case "`git ls-files --stage --cached symlink`" in +120000" "*symlink) echo pass;; +*) echo fail; git ls-files --stage --cached symlink; (exit 1);; esac' test_done diff --git a/t/t2103-update-index-ignore-missing.sh b/t/t2103-update-index-ignore-missing.sh new file mode 100755 index 0000000000..332694e7d3 --- /dev/null +++ b/t/t2103-update-index-ignore-missing.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +test_description='update-index with options' + +. ./test-lib.sh + +test_expect_success basics ' + >one && + >two && + >three && + + # need --add when adding + test_must_fail git update-index one && + test -z "$(git ls-files)" && + git update-index --add one && + test zone = "z$(git ls-files)" && + + # update-index is atomic + echo 1 >one && + test_must_fail git update-index one two && + echo "M one" >expect && + git diff-files --name-status >actual && + test_cmp expect actual && + + git update-index --add one two three && + for i in one three two; do echo $i; done >expect && + git ls-files >actual && + test_cmp expect actual && + + test_tick && + ( + test_create_repo xyzzy && + cd xyzzy && + >file && + git add file + git commit -m "sub initial" + ) && + git add xyzzy && + + test_tick && + git commit -m initial && + git tag initial +' + +test_expect_success '--ignore-missing --refresh' ' + git reset --hard initial && + echo 2 >one && + test_must_fail git update-index --refresh && + echo 1 >one && + git update-index --refresh && + rm -f two && + test_must_fail git update-index --refresh && + git update-index --ignore-missing --refresh + +' + +test_expect_success '--unmerged --refresh' ' + git reset --hard initial && + info=$(git ls-files -s one | sed -e "s/ 0 / 1 /") && + git rm --cached one && + echo "$info" | git update-index --index-info && + test_must_fail git update-index --refresh && + git update-index --unmerged --refresh && + echo 2 >two && + test_must_fail git update-index --unmerged --refresh >actual && + grep two actual && + ! grep one actual && + ! grep three actual +' + +test_expect_success '--ignore-submodules --refresh (1)' ' + git reset --hard initial && + rm -f two && + test_must_fail git update-index --ignore-submodules --refresh +' + +test_expect_success '--ignore-submodules --refresh (2)' ' + git reset --hard initial && + test_tick && + ( + cd xyzzy && + git commit -m "sub second" --allow-empty + ) && + test_must_fail git update-index --refresh && + test_must_fail git update-index --ignore-missing --refresh && + git update-index --ignore-submodules --refresh +' + +test_done diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh new file mode 100755 index 0000000000..1d0879be06 --- /dev/null +++ b/t/t2104-update-index-skip-worktree.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy +# + +test_description='skip-worktree bit test' + +. ./test-lib.sh + +cat >expect.full <<EOF +H 1 +H 2 +H sub/1 +H sub/2 +EOF + +cat >expect.skip <<EOF +S 1 +H 2 +S sub/1 +H sub/2 +EOF + +test_expect_success 'setup' ' + mkdir sub && + touch ./1 ./2 sub/1 sub/2 && + git add 1 2 sub/1 sub/2 && + git ls-files -t | test_cmp expect.full - +' + +test_expect_success 'index is at version 2' ' + test "$(test-index-version < .git/index)" = 2 +' + +test_expect_success 'update-index --skip-worktree' ' + git update-index --skip-worktree 1 sub/1 && + git ls-files -t | test_cmp expect.skip - +' + +test_expect_success 'index is at version 3 after having some skip-worktree entries' ' + test "$(test-index-version < .git/index)" = 3 +' + +test_expect_success 'ls-files -t' ' + git ls-files -t | test_cmp expect.skip - +' + +test_expect_success 'update-index --no-skip-worktree' ' + git update-index --no-skip-worktree 1 sub/1 && + git ls-files -t | test_cmp expect.full - +' + +test_expect_success 'index version is back to 2 when there is no skip-worktree entry' ' + test "$(test-index-version < .git/index)" = 2 +' + +test_done diff --git a/t/t2105-update-index-gitfile.sh b/t/t2105-update-index-gitfile.sh new file mode 100755 index 0000000000..641607d89a --- /dev/null +++ b/t/t2105-update-index-gitfile.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# Copyright (c) 2010 Brad King +# + +test_description='git update-index for gitlink to .git file. +' + +. ./test-lib.sh + +test_expect_success 'submodule with absolute .git file' ' + mkdir sub1 && + (cd sub1 && + git init && + REAL="$(pwd)/.real" && + mv .git "$REAL" + echo "gitdir: $REAL" >.git && + test_commit first) +' + +test_expect_success 'add gitlink to absolute .git file' ' + git update-index --add -- sub1 +' + +test_expect_success 'submodule with relative .git file' ' + mkdir sub2 && + (cd sub2 && + git init && + mv .git .real && + echo "gitdir: .real" >.git && + test_commit first) +' + +test_expect_success 'add gitlink to relative .git file' ' + git update-index --add -- sub2 +' + +test_done 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/t2200-add-update.sh b/t/t2200-add-update.sh new file mode 100755 index 0000000000..2ad2819a34 --- /dev/null +++ b/t/t2200-add-update.sh @@ -0,0 +1,184 @@ +#!/bin/sh + +test_description='git add -u + +This test creates a working tree state with three files: + + top (previously committed, modified) + dir/sub (previously committed, modified) + dir/other (untracked) + +and issues a git add -u with path limiting on "dir" to add +only the updates to dir/sub. + +Also tested are "git add -u" without limiting, and "git add -u" +without contents changes, and other conditions' + +. ./test-lib.sh + +test_expect_success setup ' + echo initial >check && + echo initial >top && + echo initial >foo && + mkdir dir1 dir2 && + echo initial >dir1/sub1 && + echo initial >dir1/sub2 && + echo initial >dir2/sub3 && + git add check dir1 dir2 top foo && + test_tick + git commit -m initial && + + echo changed >check && + echo changed >top && + echo changed >dir2/sub3 && + rm -f dir1/sub1 && + echo other >dir2/other +' + +test_expect_success update ' + git add -u dir1 dir2 +' + +test_expect_success 'update noticed a removal' ' + test "$(git ls-files dir1/sub1)" = "" +' + +test_expect_success 'update touched correct path' ' + test "$(git diff-files --name-status dir2/sub3)" = "" +' + +test_expect_success 'update did not touch other tracked files' ' + test "$(git diff-files --name-status check)" = "M check" && + test "$(git diff-files --name-status top)" = "M top" +' + +test_expect_success 'update did not touch untracked files' ' + test "$(git ls-files dir2/other)" = "" +' + +test_expect_success 'cache tree has not been corrupted' ' + + git ls-files -s | + sed -e "s/ 0 / /" >expect && + git ls-tree -r $(git write-tree) | + sed -e "s/ blob / /" >current && + test_cmp expect current + +' + +test_expect_success 'update from a subdirectory' ' + ( + cd dir1 && + echo more >sub2 && + git add -u sub2 + ) +' + +test_expect_success 'change gets noticed' ' + + test "$(git diff-files --name-status dir1)" = "" + +' + +test_expect_success SYMLINKS 'replace a file with a symlink' ' + + rm foo && + ln -s top foo && + git add -u -- foo + +' + +test_expect_success 'add everything changed' ' + + git add -u && + test -z "$(git diff-files)" + +' + +test_expect_success 'touch and then add -u' ' + + touch check && + git add -u && + test -z "$(git diff-files)" + +' + +test_expect_success 'touch and then add explicitly' ' + + touch check && + git add check && + test -z "$(git diff-files)" + +' + +test_expect_success 'add -n -u should not add but just report' ' + + ( + echo "add '\''check'\''" && + echo "remove '\''top'\''" + ) >expect && + before=$(git ls-files -s check top) && + echo changed >>check && + rm -f top && + git add -n -u >actual && + after=$(git ls-files -s check top) && + + test "$before" = "$after" && + test_cmp expect actual + +' + +test_expect_success 'add -u resolves unmerged paths' ' + git reset --hard && + one=$(echo 1 | git hash-object -w --stdin) && + two=$(echo 2 | git hash-object -w --stdin) && + three=$(echo 3 | git hash-object -w --stdin) && + { + for path in path1 path2 + do + echo "100644 $one 1 $path" + echo "100644 $two 2 $path" + echo "100644 $three 3 $path" + done + echo "100644 $one 1 path3" + echo "100644 $one 1 path4" + echo "100644 $one 3 path5" + echo "100644 $one 3 path6" + } | + git update-index --index-info && + echo 3 >path1 && + echo 2 >path3 && + echo 2 >path5 && + git add -u && + git ls-files -s path1 path2 path3 path4 path5 path6 >actual && + { + echo "100644 $three 0 path1" + echo "100644 $one 1 path3" + echo "100644 $one 1 path4" + echo "100644 $one 3 path5" + echo "100644 $one 3 path6" + } >expect && + test_cmp expect actual && + + # Bonus tests. Explicit resolving + git add path3 path5 && + test_must_fail git add path4 && + test_must_fail git add path6 && + git rm path4 && + git rm path6 && + + git ls-files -s "path?" >actual && + { + echo "100644 $three 0 path1" + echo "100644 $two 0 path3" + echo "100644 $two 0 path5" + } >expect + +' + +test_expect_success '"add -u non-existent" should fail' ' + test_must_fail git add -u non-existent && + ! (git ls-files | grep "non-existent") +' + +test_done diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh new file mode 100755 index 0000000000..2e8f702452 --- /dev/null +++ b/t/t2201-add-update-typechange.sh @@ -0,0 +1,150 @@ +#!/bin/sh + +test_description='more git add -u' + +. ./test-lib.sh + +_z40=0000000000000000000000000000000000000000 + +test_expect_success setup ' + >xyzzy && + _empty=$(git hash-object --stdin <xyzzy) && + >yomin && + >caskly && + if test_have_prereq SYMLINKS; then + ln -s frotz nitfol && + T_letter=T + else + printf %s frotz > nitfol && + T_letter=M + fi && + mkdir rezrov && + >rezrov/bozbar && + git add caskly xyzzy yomin nitfol rezrov/bozbar && + + test_tick && + git commit -m initial + +' + +test_expect_success modify ' + rm -f xyzzy yomin nitfol caskly && + # caskly disappears (not a submodule) + mkdir caskly && + # nitfol changes from symlink to regular + >nitfol && + # rezrov/bozbar disappears + rm -fr rezrov && + if test_have_prereq SYMLINKS; then + ln -s xyzzy rezrov + else + printf %s xyzzy > rezrov + fi && + # xyzzy disappears (not a submodule) + mkdir xyzzy && + echo gnusto >xyzzy/bozbar && + # yomin gets replaced with a submodule + mkdir yomin && + >yomin/yomin && + ( + cd yomin && + git init && + git add yomin && + git commit -m "sub initial" + ) && + yomin=$(GIT_DIR=yomin/.git git rev-parse HEAD) && + # yonk is added and then turned into a submodule + # this should appear as T in diff-files and as A in diff-index + >yonk && + git add yonk && + rm -f yonk && + mkdir yonk && + >yonk/yonk && + ( + cd yonk && + git init && + git add yonk && + git commit -m "sub initial" + ) && + yonk=$(GIT_DIR=yonk/.git git rev-parse HEAD) && + # zifmia is added and then removed + # this should appear in diff-files but not in diff-index. + >zifmia && + git add zifmia && + rm -f zifmia && + mkdir zifmia && + { + git ls-tree -r HEAD | + sed -e "s/^/:/" -e " + / caskly/{ + s/ caskly/ $_z40 D&/ + s/blob/000000/ + } + / nitfol/{ + s/ nitfol/ $_z40 $T_letter&/ + s/blob/100644/ + } + / rezrov.bozbar/{ + s/ rezrov.bozbar/ $_z40 D&/ + s/blob/000000/ + } + / xyzzy/{ + s/ xyzzy/ $_z40 D&/ + s/blob/000000/ + } + / yomin/{ + s/ yomin/ $_z40 T&/ + s/blob/160000/ + } + " + } >expect && + { + cat expect + echo ":100644 160000 $_empty $_z40 T yonk" + echo ":100644 000000 $_empty $_z40 D zifmia" + } >expect-files && + { + cat expect + echo ":000000 160000 $_z40 $_z40 A yonk" + } >expect-index && + { + echo "100644 $_empty 0 nitfol" + echo "160000 $yomin 0 yomin" + echo "160000 $yonk 0 yonk" + } >expect-final +' + +test_expect_success diff-files ' + git diff-files --raw >actual && + test_cmp expect-files actual +' + +test_expect_success diff-index ' + git diff-index --raw HEAD -- >actual && + test_cmp expect-index actual +' + +test_expect_success 'add -u' ' + rm -f ".git/saved-index" && + cp -p ".git/index" ".git/saved-index" && + git add -u && + git ls-files -s >actual && + test_cmp expect-final actual +' + +test_expect_success 'commit -a' ' + if test -f ".git/saved-index" + then + rm -f ".git/index" && + mv ".git/saved-index" ".git/index" + fi && + git commit -m "second" -a && + git ls-files -s >actual && + test_cmp expect-final actual && + rm -f .git/index && + git read-tree HEAD && + git ls-files -s >actual && + test_cmp expect-final actual +' + +test_done diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh new file mode 100755 index 0000000000..6a8151064c --- /dev/null +++ b/t/t2202-add-addremove.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='git add --all' + +. ./test-lib.sh + +test_expect_success setup ' + ( + echo .gitignore + echo will-remove + ) >expect && + ( + echo actual + echo expect + echo ignored + ) >.gitignore && + >will-remove && + git add --all && + test_tick && + git commit -m initial && + git ls-files >actual && + test_cmp expect actual +' + +test_expect_success 'git add --all' ' + ( + echo .gitignore + echo not-ignored + echo "M .gitignore" + echo "A not-ignored" + echo "D will-remove" + ) >expect && + >ignored && + >not-ignored && + echo modification >>.gitignore && + rm -f will-remove && + git add --all && + git update-index --refresh && + git ls-files >actual && + git diff-index --name-status --cached HEAD >>actual && + test_cmp expect actual +' + +test_done diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh new file mode 100755 index 0000000000..58a329961e --- /dev/null +++ b/t/t2203-add-intent.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +test_description='Intent to add' + +. ./test-lib.sh + +test_expect_success 'intent to add' ' + echo hello >file && + echo hello >elif && + git add -N file && + git add elif +' + +test_expect_success 'check result of "add -N"' ' + git ls-files -s file >actual && + empty=$(git hash-object --stdin </dev/null) && + echo "100644 $empty 0 file" >expect && + test_cmp expect actual +' + +test_expect_success 'intent to add is just an ordinary empty blob' ' + git add -u && + git ls-files -s file >actual && + git ls-files -s elif | sed -e "s/elif/file/" >expect && + test_cmp expect actual +' + +test_expect_success 'intent to add does not clobber existing paths' ' + git add -N file elif && + empty=$(git hash-object --stdin </dev/null) && + git ls-files -s >actual && + ! grep "$empty" actual +' + +test_expect_success 'cannot commit with i-t-a entry' ' + test_tick && + git commit -a -m initial && + git reset --hard && + + echo xyzzy >rezrov && + echo frotz >nitfol && + git add rezrov && + git add -N nitfol && + test_must_fail git commit +' + +test_expect_success 'can commit with an unrelated i-t-a entry in index' ' + git reset --hard && + echo xyzzy >rezrov && + echo frotz >nitfol && + git add rezrov && + git add -N nitfol && + git commit -m partial rezrov +' + +test_expect_success 'can "commit -a" with an i-t-a entry' ' + git reset --hard && + : >nitfol && + git add -N nitfol && + git commit -a -m all +' + +test_done + diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh new file mode 100755 index 0000000000..24afdabab7 --- /dev/null +++ b/t/t2204-add-ignored.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +test_description='giving ignored paths to git add' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir sub dir dir/sub && + echo sub >.gitignore && + echo ign >>.gitignore && + for p in . sub dir dir/sub + do + >"$p/ign" && + >"$p/file" || exit 1 + done +' + +for i in file dir/file dir 'd*' +do + test_expect_success "no complaints for unignored $i" ' + rm -f .git/index && + git add "$i" && + git ls-files "$i" >out && + test -s out + ' +done + +for i in ign dir/ign dir/sub dir/sub/*ign sub/file sub sub/* +do + test_expect_success "complaints for ignored $i" ' + rm -f .git/index && + test_must_fail git add "$i" 2>err && + git ls-files "$i" >out && + ! test -s out && + grep -e "Use -f if" err && + cat err + ' + + test_expect_success "complaints for ignored $i with unignored file" ' + rm -f .git/index && + test_must_fail git add "$i" file 2>err && + git ls-files "$i" >out && + ! test -s out && + grep -e "Use -f if" err && + cat err + ' +done + +for i in sub sub/* +do + test_expect_success "complaints for ignored $i in dir" ' + rm -f .git/index && + ( + cd dir && + test_must_fail git add "$i" 2>err && + git ls-files "$i" >out && + ! test -s out && + grep -e "Use -f if" err && + cat err + ) + ' +done + +for i in ign file +do + test_expect_success "complaints for ignored $i in sub" ' + rm -f .git/index && + ( + cd sub && + test_must_fail git add "$i" 2>err && + git ls-files "$i" >out && + ! test -s out && + grep -e "Use -f if" err && + cat err + ) + ' +done + +test_done diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh new file mode 100755 index 0000000000..9965bc5c92 --- /dev/null +++ b/t/t2300-cd-to-toplevel.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='cd_to_toplevel' + +. ./test-lib.sh + +test_cd_to_toplevel () { + test_expect_success $3 "$2" ' + ( + cd '"'$1'"' && + . "$(git --exec-path)"/git-sh-setup && + cd_to_toplevel && + [ "$(pwd -P)" = "$TOPLEVEL" ] + ) + ' +} + +TOPLEVEL="$(pwd -P)/repo" +mkdir -p repo/sub/dir +mv .git repo/ +SUBDIRECTORY_OK=1 + +test_cd_to_toplevel repo 'at physical root' + +test_cd_to_toplevel repo/sub/dir 'at physical subdir' + +ln -s repo symrepo 2>/dev/null +test_cd_to_toplevel symrepo 'at symbolic root' SYMLINKS + +ln -s repo/sub/dir subdir-link 2>/dev/null +test_cd_to_toplevel subdir-link 'at symbolic subdir' SYMLINKS + +cd repo +ln -s sub/dir internal-link 2>/dev/null +test_cd_to_toplevel internal-link 'at internal symbolic subdir' SYMLINKS + +test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index adcbe03d56..2eec0118c4 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -3,9 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-ls-files test (--others should pick up symlinks). +test_description='git ls-files test (--others should pick up symlinks). -This test runs git-ls-files --others with the following on the +This test runs git ls-files --others with the following on the filesystem. path0 - a file @@ -13,44 +13,56 @@ filesystem. path2/file2 - a file in a directory path3-junk - a file to confuse things path3/file3 - a file in a directory + path4 - an empty directory ' . ./test-lib.sh -date >path0 -ln -s xyzzy path1 -mkdir path2 path3 -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 -output -path0 -path1 -path2-junk -path2/file2 -EOF -sed -e 's|path2/file2|path2/|' <expected1 >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.' \ - 'diff output expected1' - -test_expect_success \ - 'git-ls-files --others --directory to show output.' \ - 'git-ls-files --others --directory >output' - - -test_expect_success \ - 'git-ls-files --others --directory should not get confused.' \ - 'diff output expected2' +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 '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 'ls-files --others' ' + git ls-files --others >output && + test_cmp expected1 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' ' + git ls-files --others --directory --no-empty-directory >output && + test_cmp expected3 output +' test_done diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh index 6979b7c1c0..6d2f2b67ee 100755 --- a/t/t3001-ls-files-others-exclude.sh +++ b/t/t3001-ls-files-others-exclude.sh @@ -3,9 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-ls-files --others --exclude +test_description='git ls-files --others --exclude -This test runs git-ls-files --others and tests --exclude patterns. +This test runs git ls-files --others and tests --exclude patterns. ' . ./test-lib.sh @@ -19,6 +19,9 @@ do >$dir/a.$i done done +>"#ignore1" +>"#ignore2" +>"#hidden" cat >expect <<EOF a.2 @@ -42,6 +45,9 @@ three/a.8 EOF echo '.gitignore +\#ignore1 +\#ignore2* +\#hid*n output expect .gitignore @@ -58,25 +64,154 @@ two/*.4 echo '!*.2 !*.8' >one/two/.gitignore +allignores='.gitignore one/.gitignore one/two/.gitignore' + test_expect_success \ - 'git-ls-files --others with various exclude options.' \ - 'git-ls-files --others \ + 'git ls-files --others with various exclude options.' \ + 'git ls-files --others \ --exclude=\*.6 \ --exclude-per-directory=.gitignore \ --exclude-from=.git/ignore \ >output && - diff -u expect output' + test_cmp expect output' # Test \r\n (MSDOS-like systems) printf '*.1\r\n/*.3\r\n!*.6\r\n' >.gitignore test_expect_success \ - 'git-ls-files --others with \r\n line endings.' \ - 'git-ls-files --others \ + 'git ls-files --others with \r\n line endings.' \ + 'git ls-files --others \ + --exclude=\*.6 \ + --exclude-per-directory=.gitignore \ + --exclude-from=.git/ignore \ + >output && + test_cmp expect output' + +test_expect_success 'setup skip-worktree gitignore' ' + git add $allignores && + git update-index --skip-worktree $allignores && + rm $allignores +' + +test_expect_success \ + 'git ls-files --others with various exclude options.' \ + 'git ls-files --others \ --exclude=\*.6 \ --exclude-per-directory=.gitignore \ --exclude-from=.git/ignore \ >output && - diff -u expect output' + test_cmp expect output' + +test_expect_success 'restore gitignore' ' + git checkout $allignores && + rm .git/index +' + +cat > excludes-file <<\EOF +*.[1-8] +e* +\#* +EOF + +git config core.excludesFile excludes-file + +git status | grep "^# " > output + +cat > expect << EOF +# .gitignore +# a.6 +# one/ +# output +# three/ +EOF + +test_expect_success 'git status honors core.excludesfile' \ + 'test_cmp expect output' + +test_expect_success 'trailing slash in exclude allows directory match(1)' ' + + git ls-files --others --exclude=one/ >output && + if grep "^one/" output + then + echo Ooops + false + else + : happy + fi + +' + +test_expect_success 'trailing slash in exclude allows directory match (2)' ' + + git ls-files --others --exclude=one/two/ >output && + if grep "^one/two/" output + then + echo Ooops + false + else + : happy + fi + +' + +test_expect_success 'trailing slash in exclude forces directory match (1)' ' + + >two + git ls-files --others --exclude=two/ >output && + grep "^two" output + +' + +test_expect_success 'trailing slash in exclude forces directory match (2)' ' + + git ls-files --others --exclude=one/a.1/ >output && + grep "^one/a.1" output + +' + +test_expect_success 'negated exclude matches can override previous ones' ' + + git ls-files --others --exclude="a.*" --exclude="!a.1" >output && + grep "^a.1" output +' + +test_expect_success 'subdirectory ignore (setup)' ' + mkdir -p top/l1/l2 && + ( + cd top && + git init && + echo /.gitignore >.gitignore && + echo l1 >>.gitignore && + echo l2 >l1/.gitignore && + >l1/l2/l1 + ) +' + +test_expect_success 'subdirectory ignore (toplevel)' ' + ( + cd top && + git ls-files -o --exclude-standard + ) >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'subdirectory ignore (l1/l2)' ' + ( + cd top/l1/l2 && + git ls-files -o --exclude-standard + ) >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'subdirectory ignore (l1)' ' + ( + cd top/l1 && + git ls-files -o --exclude-standard + ) >actual && + >expect && + test_cmp expect actual +' test_done diff --git a/t/t3002-ls-files-dashpath.sh b/t/t3002-ls-files-dashpath.sh index b42f1382bc..8704b04e1b 100755 --- a/t/t3002-ls-files-dashpath.sh +++ b/t/t3002-ls-files-dashpath.sh @@ -3,9 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-ls-files test (-- to terminate the path list). +test_description='git ls-files test (-- to terminate the path list). -This test runs git-ls-files --others with the following on the +This test runs git ls-files --others with the following on the filesystem. path0 - a file @@ -21,9 +21,9 @@ test_expect_success \ echo frotz >./--' test_expect_success \ - 'git-ls-files without path restriction.' \ - 'git-ls-files --others >output && - diff -u output - <<EOF + 'git ls-files without path restriction.' \ + 'git ls-files --others >output && + test_cmp output - <<EOF -- -foo output @@ -32,33 +32,33 @@ EOF ' test_expect_success \ - 'git-ls-files with path restriction.' \ - 'git-ls-files --others path0 >output && - diff -u output - <<EOF + 'git ls-files with path restriction.' \ + 'git ls-files --others path0 >output && + test_cmp output - <<EOF path0 EOF ' test_expect_success \ - 'git-ls-files with path restriction with --.' \ - 'git-ls-files --others -- path0 >output && - diff -u output - <<EOF + 'git ls-files with path restriction with --.' \ + 'git ls-files --others -- path0 >output && + test_cmp output - <<EOF path0 EOF ' test_expect_success \ - 'git-ls-files with path restriction with -- --.' \ - 'git-ls-files --others -- -- >output && - diff -u output - <<EOF + 'git ls-files with path restriction with -- --.' \ + 'git ls-files --others -- -- >output && + test_cmp output - <<EOF -- EOF ' test_expect_success \ - 'git-ls-files with no path restriction.' \ - 'git-ls-files --others -- >output && - diff -u output - <<EOF + 'git ls-files with no path restriction.' \ + 'git ls-files --others -- >output && + test_cmp output - <<EOF -- -foo output diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh new file mode 100755 index 0000000000..d5ec333131 --- /dev/null +++ b/t/t3003-ls-files-exclude.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +test_description='ls-files --exclude does not affect index files' +. ./test-lib.sh + +test_expect_success 'create repo with file' ' + echo content >file && + git add file && + git commit -m file && + echo modification >file +' + +check_output() { +test_expect_success "ls-files output contains file ($1)" " + echo '$2' >expect && + git ls-files --exclude-standard --$1 >output && + test_cmp expect output +" +} + +check_all_output() { + check_output 'cached' 'file' + check_output 'modified' 'file' +} + +check_all_output +test_expect_success 'add file to gitignore' ' + echo file >.gitignore +' +check_all_output + +test_expect_success 'ls-files -i lists only tracked-but-ignored files' ' + echo content >other-file && + git add other-file && + echo file >expect && + git ls-files -i --exclude-standard >output && + test_cmp expect output +' + +test_done diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh index 5fc1976711..95671c2053 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-ls-files -k and -m flags test. +test_description='git ls-files -k and -m flags test. This test prepares the following in the cache: @@ -22,7 +22,7 @@ and the following on the filesystem: path5 - a symlink path6/file6 - a file in a directory -git-ls-files -k should report that existing filesystem +git ls-files -k should report that existing filesystem objects except path4, path5 and path6/file6 to be killed. Also for modification test, the cache and working tree have: @@ -38,7 +38,12 @@ modified without reporting path9 and path10. . ./test-lib.sh date >path0 -ln -s xyzzy path1 +if test_have_prereq SYMLINKS +then + ln -s xyzzy path1 +else + date > path1 +fi mkdir path2 path3 date >path2/file2 date >path3/file3 @@ -47,13 +52,19 @@ date >path8 : >path9 date >path10 test_expect_success \ - 'git-update-index --add to add various paths.' \ - "git-update-index --add -- path0 path1 path?/file? path7 path8 path9 path10" + 'git update-index --add to add various paths.' \ + "git update-index --add -- path0 path1 path?/file? path7 path8 path9 path10" rm -fr path? ;# leave path10 alone date >path2 -ln -s frotz path3 -ln -s nitfol path5 +if test_have_prereq SYMLINKS +then + ln -s frotz path3 + ln -s nitfol path5 +else + date > path3 + date > path5 +fi mkdir path0 path1 path6 date >path0/file0 date >path1/file1 @@ -64,8 +75,8 @@ date >path7 touch path10 test_expect_success \ - 'git-ls-files -k to show killed files.' \ - 'git-ls-files -k >.output' + 'git ls-files -k to show killed files.' \ + 'git ls-files -k >.output' cat >.expected <<EOF path0/file0 path1/file1 @@ -74,12 +85,12 @@ path3 EOF test_expect_success \ - 'validate git-ls-files -k output.' \ - 'diff .output .expected' + 'validate git ls-files -k output.' \ + 'test_cmp .expected .output' test_expect_success \ - 'git-ls-files -m to show modified files.' \ - 'git-ls-files -m >.output' + 'git ls-files -m to show modified files.' \ + 'git ls-files -m >.output' cat >.expected <<EOF path0 path1 @@ -90,7 +101,7 @@ path8 EOF test_expect_success \ - 'validate git-ls-files -m output.' \ - 'diff .output .expected' + 'validate git ls-files -m output.' \ + 'test_cmp .expected .output' test_done diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh index d55559e553..a7d8187169 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -3,25 +3,27 @@ # Copyright (c) 2006 Carl D. Worth # -test_description='git-ls-files test for --error-unmatch option +test_description='git ls-files test for --error-unmatch option -This test runs git-ls-files --error-unmatch to ensure it correctly +This test runs git ls-files --error-unmatch to ensure it correctly returns an error when a non-existent path is provided on the command line. ' . ./test-lib.sh -touch foo bar -git-update-index --add foo bar -git-commit -m "add foo bar" +test_expect_success 'setup' ' + touch foo bar && + git update-index --add foo bar && + git commit -m "add foo bar" +' -test_expect_failure \ - 'git-ls-files --error-unmatch should fail with unmatched path.' \ - 'git-ls-files --error-unmatch foo bar-does-not-match' +test_expect_success \ + 'git ls-files --error-unmatch should fail with unmatched path.' \ + 'test_must_fail git ls-files --error-unmatch foo bar-does-not-match' test_expect_success \ - 'git-ls-files --error-unmatch should succeed eith matched paths.' \ - 'git-ls-files --error-unmatch foo bar' + 'git ls-files --error-unmatch should succeed eith matched paths.' \ + 'git ls-files --error-unmatch foo bar' test_done 1 diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh new file mode 100755 index 0000000000..d541544537 --- /dev/null +++ b/t/t3030-merge-recursive.sh @@ -0,0 +1,583 @@ +#!/bin/sh + +test_description='merge-recursive backend test' + +. ./test-lib.sh + +test_expect_success 'setup 1' ' + + echo hello >a && + o0=$(git hash-object a) && + cp a b && + cp a c && + mkdir d && + cp a d/e && + + test_tick && + git add a b c d/e && + git commit -m initial && + c0=$(git rev-parse --verify HEAD) && + git branch side && + git branch df-1 && + git branch df-2 && + git branch df-3 && + git branch remove && + git branch submod && + + echo hello >>a && + cp a d/e && + o1=$(git hash-object a) && + + git add a d/e && + + test_tick && + git commit -m "master modifies a and d/e" && + c1=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o1 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o1 d/e" + echo "100644 $o1 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'setup 2' ' + + rm -rf [abcd] && + git checkout side && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual && + + echo goodbye >>a && + o2=$(git hash-object a) && + + git add a && + + test_tick && + git commit -m "side modifies a" && + c2=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o2 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o2 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'setup 3' ' + + rm -rf [abcd] && + git checkout df-1 && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual && + + rm -f b && mkdir b && echo df-1 >b/c && git add b/c && + o3=$(git hash-object b/c) && + + test_tick && + git commit -m "df-1 makes b/c" && + c3=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o3 b/c" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o3 0 b/c" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'setup 4' ' + + rm -rf [abcd] && + git checkout df-2 && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual && + + rm -f a && mkdir a && echo df-2 >a/c && git add a/c && + o4=$(git hash-object a/c) && + + test_tick && + git commit -m "df-2 makes a/c" && + c4=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o4 a/c" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o4 0 a/c" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'setup 5' ' + + rm -rf [abcd] && + git checkout remove && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual && + + rm -f b && + echo remove-conflict >a && + + git add a && + git rm b && + o5=$(git hash-object a) && + + test_tick && + git commit -m "remove removes b and modifies a" && + c5=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o5 a" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o5 0 a" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'setup 6' ' + + rm -rf [abcd] && + git checkout df-3 && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o0 d/e" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o0 0 d/e" + ) >expected && + test_cmp expected actual && + + rm -fr d && echo df-3 >d && git add d && + o6=$(git hash-object d) && + + test_tick && + git commit -m "df-3 makes d" && + c6=$(git rev-parse --verify HEAD) && + ( git ls-tree -r HEAD ; git ls-files -s ) >actual && + ( + echo "100644 blob $o0 a" + echo "100644 blob $o0 b" + echo "100644 blob $o0 c" + echo "100644 blob $o6 d" + echo "100644 $o0 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o6 0 d" + ) >expected && + 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 'merge-recursive simple' ' + + rm -fr [abcd] && + git checkout -f "$c2" && + + git merge-recursive "$c0" -- "$c2" "$c1" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive result' ' + + git ls-files -s >actual && + ( + echo "100644 $o0 1 a" + echo "100644 $o2 2 a" + echo "100644 $o1 3 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'fail if the index has unresolved entries' ' + + rm -fr [abcd] && + git checkout -f "$c1" && + + test_must_fail git merge "$c5" && + test_must_fail git merge "$c5" 2> out && + grep "not possible because you have unmerged files" out && + git add -u && + test_must_fail git merge "$c5" 2> out && + grep "You have not concluded your merge" out && + rm -f .git/MERGE_HEAD && + test_must_fail git merge "$c5" 2> out && + grep "Your local changes to .* would be overwritten by merge." out +' + +test_expect_success 'merge-recursive remove conflict' ' + + rm -fr [abcd] && + git checkout -f "$c1" && + + git merge-recursive "$c0" -- "$c1" "$c5" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive remove conflict' ' + + git ls-files -s >actual && + ( + echo "100644 $o0 1 a" + echo "100644 $o1 2 a" + echo "100644 $o5 3 a" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge-recursive d/f simple' ' + rm -fr [abcd] && + git reset --hard && + git checkout -f "$c1" && + + git merge-recursive "$c0" -- "$c1" "$c3" +' + +test_expect_success 'merge-recursive result' ' + + git ls-files -s >actual && + ( + echo "100644 $o1 0 a" + echo "100644 $o3 0 b/c" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge-recursive d/f conflict' ' + + rm -fr [abcd] && + git reset --hard && + git checkout -f "$c1" && + + git merge-recursive "$c0" -- "$c1" "$c4" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive d/f conflict result' ' + + git ls-files -s >actual && + ( + echo "100644 $o0 1 a" + echo "100644 $o1 2 a" + echo "100644 $o4 0 a/c" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge-recursive d/f conflict the other way' ' + + rm -fr [abcd] && + git reset --hard && + git checkout -f "$c4" && + + git merge-recursive "$c0" -- "$c4" "$c1" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive d/f conflict result the other way' ' + + git ls-files -s >actual && + ( + echo "100644 $o0 1 a" + echo "100644 $o1 3 a" + echo "100644 $o4 0 a/c" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge-recursive d/f conflict' ' + + rm -fr [abcd] && + git reset --hard && + git checkout -f "$c1" && + + git merge-recursive "$c0" -- "$c1" "$c6" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive d/f conflict result' ' + + git ls-files -s >actual && + ( + echo "100644 $o1 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o6 3 d" + echo "100644 $o0 1 d/e" + echo "100644 $o1 2 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge-recursive d/f conflict' ' + + rm -fr [abcd] && + git reset --hard && + git checkout -f "$c6" && + + git merge-recursive "$c0" -- "$c6" "$c1" + status=$? + case "$status" in + 1) + : happy + ;; + *) + echo >&2 "why status $status!!!" + false + ;; + esac +' + +test_expect_success 'merge-recursive d/f conflict result' ' + + git ls-files -s >actual && + ( + echo "100644 $o1 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o6 2 d" + echo "100644 $o0 1 d/e" + echo "100644 $o1 3 d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'reset and 3-way merge' ' + + git reset --hard "$c2" && + git read-tree -m "$c0" "$c2" "$c1" + +' + +test_expect_success 'reset and bind merge' ' + + git reset --hard master && + git read-tree --prefix=M/ master && + git ls-files -s >actual && + ( + echo "100644 $o1 0 M/a" + echo "100644 $o0 0 M/b" + echo "100644 $o0 0 M/c" + echo "100644 $o1 0 M/d/e" + echo "100644 $o1 0 a" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual && + + git read-tree --prefix=a1/ master && + git ls-files -s >actual && + ( + echo "100644 $o1 0 M/a" + echo "100644 $o0 0 M/b" + echo "100644 $o0 0 M/c" + echo "100644 $o1 0 M/d/e" + echo "100644 $o1 0 a" + echo "100644 $o1 0 a1/a" + echo "100644 $o0 0 a1/b" + echo "100644 $o0 0 a1/c" + echo "100644 $o1 0 a1/d/e" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + ) >expected && + test_cmp expected actual + + git read-tree --prefix=z/ master && + git ls-files -s >actual && + ( + echo "100644 $o1 0 M/a" + echo "100644 $o0 0 M/b" + echo "100644 $o0 0 M/c" + echo "100644 $o1 0 M/d/e" + echo "100644 $o1 0 a" + echo "100644 $o1 0 a1/a" + echo "100644 $o0 0 a1/b" + echo "100644 $o0 0 a1/c" + echo "100644 $o1 0 a1/d/e" + echo "100644 $o0 0 b" + echo "100644 $o0 0 c" + echo "100644 $o1 0 d/e" + echo "100644 $o1 0 z/a" + echo "100644 $o0 0 z/b" + echo "100644 $o0 0 z/c" + echo "100644 $o1 0 z/d/e" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'merge removes empty directories' ' + + git reset --hard master && + git checkout -b rm && + git rm d/e && + git commit -mremoved-d/e && + git checkout master && + git merge -s recursive rm && + 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_done diff --git a/t/t3031-merge-criscross.sh b/t/t3031-merge-criscross.sh new file mode 100755 index 0000000000..7f41607c56 --- /dev/null +++ b/t/t3031-merge-criscross.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +test_description='merge-recursive backend test' + +. ./test-lib.sh + +# A <- create some files +# / \ +# B C <- cause rename/delete conflicts between B and C +# / \ +# |\ /| +# | D E | +# | \ / | +# | X | +# | / \ | +# | / \ | +# |/ \| +# F G <- merge E into B, D into C +# \ / +# \ / +# \ / +# H <- recursive merge crashes +# + +# initialize +test_expect_success 'setup repo with criss-cross history' ' + mkdir data && + + # create a bunch of files + n=1 && + while test $n -le 10 + do + echo $n > data/$n && + n=$(($n+1)) || + break + done && + + # check them in + git add data && + git commit -m A && + git branch A && + + # a file in one branch + git checkout -b B A && + git rm data/9 && + git add data && + git commit -m B && + + # with a branch off of it + git branch D && + + # put some commits on D + git checkout D && + echo testD > data/testD && + git add data && + git commit -m D && + + # back up to the top, create another branch and cause + # a rename conflict with the file we deleted earlier + git checkout -b C A && + git mv data/9 data/new-9 && + git add data && + git commit -m C && + + # with a branch off of it + git branch E && + + # put a commit on E + git checkout E && + echo testE > data/testE && + git add data && + git commit -m E && + + # now, merge E into B + git checkout B && + test_must_fail git merge E && + # force-resolve + git add data && + git commit -m F && + git branch F && + + # and merge D into C + git checkout C && + test_must_fail git merge D && + # force-resolve + git add data && + git commit -m G && + git branch G +' + +test_expect_success 'recursive merge between F and G, causes segfault' ' + git merge F +' + +test_done diff --git a/t/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh new file mode 100755 index 0000000000..f6973e96a5 --- /dev/null +++ b/t/t3040-subprojects-basic.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +test_description='Basic subproject functionality' +. ./test-lib.sh + +test_expect_success 'Super project creation' \ + ': >Makefile && + git add Makefile && + git commit -m "Superproject created"' + + +cat >expected <<EOF +:000000 160000 00000... A sub1 +:000000 160000 00000... A sub2 +EOF +test_expect_success 'create subprojects' \ + 'mkdir sub1 && + ( cd sub1 && git init && : >Makefile && git add * && + git commit -q -m "subproject 1" ) && + mkdir sub2 && + ( cd sub2 && git init && : >Makefile && git add * && + git commit -q -m "subproject 2" ) && + git update-index --add sub1 && + git add sub2 && + git commit -q -m "subprojects added" && + git diff-tree --abbrev=5 HEAD^ HEAD |cut -d" " -f-3,5- >current && + test_cmp expected current' + +git branch save HEAD + +test_expect_success 'check if fsck ignores the subprojects' \ + 'git fsck --full' + +test_expect_success 'check if commit in a subproject detected' \ + '( cd sub1 && + echo "all:" >>Makefile && + echo " true" >>Makefile && + git commit -q -a -m "make all" ) && { + git diff-files --exit-code + test $? = 1 + }' + +test_expect_success 'check if a changed subproject HEAD can be committed' \ + 'git commit -q -a -m "sub1 changed" && { + git diff-tree --exit-code HEAD^ HEAD + test $? = 1 + }' + +test_expect_success 'check if diff-index works for subproject elements' \ + 'git diff-index --exit-code --cached save -- sub1 + test $? = 1' + +test_expect_success 'check if diff-tree works for subproject elements' \ + 'git diff-tree --exit-code HEAD^ HEAD -- sub1 + test $? = 1' + +test_expect_success 'check if git diff works for subproject elements' \ + 'git diff --exit-code HEAD^ HEAD + test $? = 1' + +test_expect_success 'check if clone works' \ + 'git ls-files -s >expected && + git clone -l -s . cloned && + ( cd cloned && git ls-files -s ) >current && + test_cmp expected current' + +test_expect_success 'removing and adding subproject' \ + 'git update-index --force-remove -- sub2 && + mv sub2 sub3 && + git add sub3 && + git commit -q -m "renaming a subproject" && { + git diff -M --name-status --exit-code HEAD^ HEAD + test $? = 1 + }' + +# the index must contain the object name the HEAD of the +# subproject sub1 was at the point "save" +test_expect_success 'checkout in superproject' \ + 'git checkout save && + git diff-index --exit-code --raw --cached save -- sub1' + +# just interesting what happened... +# git diff --name-status -M save master + +test_done diff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh new file mode 100755 index 0000000000..4261e9641e --- /dev/null +++ b/t/t3050-subprojects-fetch.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='fetching and pushing project with subproject' + +. ./test-lib.sh + +test_expect_success setup ' + test_tick && + mkdir -p sub && ( + cd sub && + git init && + >subfile && + git add subfile + git commit -m "subproject commit #1" + ) && + >mainfile + git add sub mainfile && + test_tick && + git commit -m "superproject commit #1" +' + +test_expect_success clone ' + git clone "file://$(pwd)/.git" cloned && + (git rev-parse HEAD; git ls-files -s) >expected && + ( + cd cloned && + (git rev-parse HEAD; git ls-files -s) >../actual + ) && + test_cmp expected actual +' + +test_expect_success advance ' + echo more >mainfile && + git update-index --force-remove sub && + mv sub/.git sub/.git-disabled && + git add sub/subfile mainfile && + mv sub/.git-disabled sub/.git && + test_tick && + git commit -m "superproject commit #2" +' + +test_expect_success fetch ' + (git rev-parse HEAD; git ls-files -s) >expected && + ( + cd cloned && + git pull && + (git rev-parse HEAD; git ls-files -s) >../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 new file mode 100755 index 0000000000..3ce501bb97 --- /dev/null +++ b/t/t3060-ls-files-with-tree.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# +# Copyright (c) 2007 Carl D. Worth +# + +test_description='git ls-files test (--with-tree). + +This test runs git ls-files --with-tree and in particular in +a scenario known to trigger a crash with some versions of git. +' +. ./test-lib.sh + +test_expect_success setup ' + + # The bug we are exercising requires a fair number of entries + # in a sub-directory so that add_index_entry will trigger a + # realloc. + + echo file >expected && + mkdir sub && + bad= && + for n in 0 1 2 3 4 5 + do + for m in 0 1 2 3 4 5 6 7 8 9 + do + num=00$n$m && + >sub/file-$num && + echo file-$num >>expected || { + bad=t + break + } + done && test -z "$bad" || { + bad=t + break + } + done && test -z "$bad" && + git add . && + git commit -m "add a bunch of files" && + + # We remove them all so that we will have something to add + # back with --with-tree and so that we will definitely be + # under the realloc size to trigger the bug. + rm -rf sub && + git commit -a -m "remove them all" && + + # The bug also requires some entry before our directory so that + # prune_path will modify the_index.cache + + mkdir a_directory_that_sorts_before_sub && + >a_directory_that_sorts_before_sub/file && + mkdir sub && + >sub/file && + 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 + +' + +cd .. +test_expect_success \ + 'git -ls-files --with-tree should add entries from named tree.' \ + 'test_cmp expected output' + +test_done diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index 2ec06d3d39..eee0d344d2 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -3,9 +3,9 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-ls-tree test. +test_description='git ls-tree test. -This test runs git-ls-tree with the following in a tree. +This test runs git ls-tree with the following in a tree. path0 - a file path1 - a symlink @@ -22,26 +22,36 @@ test_expect_success \ 'setup' \ 'mkdir path2 path2/baz && echo Hi >path0 && - ln -s path0 path1 && + if test_have_prereq SYMLINKS + then + ln -s path0 path1 && + ln -s ../path1 path2/bazbo + make_expected () { + cat >expected + } + else + printf path0 > path1 && + printf ../path1 > path2/bazbo + make_expected () { + sed -e "s/120000 /100644 /" >expected + } + fi && echo Lo >path2/foo && - ln -s ../path1 path2/bazbo && echo Mi >path2/baz/b && find path? \( -type f -o -type l \) -print | - xargs git-update-index --add && - tree=`git-write-tree` && + xargs git update-index --add && + tree=`git write-tree` && echo $tree' -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" test_output () { sed -e "s/ $_x40 / X /" <current >check - diff -u expected check + test_cmp expected check } test_expect_success \ 'ls-tree plain' \ - 'git-ls-tree $tree >current && - cat >expected <<\EOF && + 'git ls-tree $tree >current && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -50,8 +60,8 @@ EOF test_expect_success \ 'ls-tree recursive' \ - 'git-ls-tree -r $tree >current && - cat >expected <<\EOF && + 'git ls-tree -r $tree >current && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 100644 blob X path2/baz/b @@ -62,8 +72,8 @@ EOF test_expect_success \ 'ls-tree recursive with -t' \ - 'git-ls-tree -r -t $tree >current && - cat >expected <<\EOF && + 'git ls-tree -r -t $tree >current && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -76,8 +86,8 @@ EOF test_expect_success \ 'ls-tree recursive with -d' \ - 'git-ls-tree -r -d $tree >current && - cat >expected <<\EOF && + 'git ls-tree -r -d $tree >current && + make_expected <<\EOF && 040000 tree X path2 040000 tree X path2/baz EOF @@ -85,8 +95,8 @@ EOF test_expect_success \ 'ls-tree filtered with path' \ - 'git-ls-tree $tree path >current && - cat >expected <<\EOF && + 'git ls-tree $tree path >current && + make_expected <<\EOF && EOF test_output' @@ -95,8 +105,8 @@ EOF # they are shown in canonical order. test_expect_success \ 'ls-tree filtered with path1 path0' \ - 'git-ls-tree $tree path1 path0 >current && - cat >expected <<\EOF && + 'git ls-tree $tree path1 path0 >current && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 EOF @@ -104,8 +114,8 @@ EOF test_expect_success \ 'ls-tree filtered with path0/' \ - 'git-ls-tree $tree path0/ >current && - cat >expected <<\EOF && + 'git ls-tree $tree path0/ >current && + make_expected <<\EOF && EOF test_output' @@ -113,8 +123,8 @@ EOF # with pathspec semantics it shows only path2 test_expect_success \ 'ls-tree filtered with path2' \ - 'git-ls-tree $tree path2 >current && - cat >expected <<\EOF && + 'git ls-tree $tree path2 >current && + make_expected <<\EOF && 040000 tree X path2 EOF test_output' @@ -122,8 +132,8 @@ EOF # ... and path2/ shows the children. test_expect_success \ 'ls-tree filtered with path2/' \ - 'git-ls-tree $tree path2/ >current && - cat >expected <<\EOF && + 'git ls-tree $tree path2/ >current && + make_expected <<\EOF && 040000 tree X path2/baz 120000 blob X path2/bazbo 100644 blob X path2/foo @@ -134,23 +144,23 @@ EOF # path2/baz test_expect_success \ 'ls-tree filtered with path2/baz' \ - 'git-ls-tree $tree path2/baz >current && - cat >expected <<\EOF && + 'git ls-tree $tree path2/baz >current && + make_expected <<\EOF && 040000 tree X path2/baz EOF test_output' test_expect_success \ 'ls-tree filtered with path2/bak' \ - 'git-ls-tree $tree path2/bak >current && - cat >expected <<\EOF && + 'git ls-tree $tree path2/bak >current && + make_expected <<\EOF && EOF test_output' test_expect_success \ 'ls-tree -t filtered with path2/bak' \ - 'git-ls-tree -t $tree path2/bak >current && - cat >expected <<\EOF && + 'git ls-tree -t $tree path2/bak >current && + make_expected <<\EOF && 040000 tree X path2 EOF test_output' diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index d78deb1e71..06654c6f82 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -4,9 +4,9 @@ # Copyright (c) 2005 Robert Fitzsimons # -test_description='git-ls-tree directory and filenames handling. +test_description='git ls-tree directory and filenames handling. -This test runs git-ls-tree with the following in a tree. +This test runs git ls-tree with the following in a tree. 1.txt - a file 2.txt - a file @@ -35,20 +35,18 @@ test_expect_success \ 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` && + xargs git update-index --add && + tree=`git write-tree` && echo $tree' -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" test_output () { sed -e "s/ $_x40 / X /" <current >check - diff -u expected check + test_cmp expected check } test_expect_success \ 'ls-tree plain' \ - 'git-ls-tree $tree >current && + 'git ls-tree $tree >current && cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X 2.txt @@ -62,7 +60,7 @@ EOF # Recursive does not show tree nodes anymore... test_expect_success \ 'ls-tree recursive' \ - 'git-ls-tree -r $tree >current && + 'git ls-tree -r $tree >current && cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X 2.txt @@ -76,7 +74,7 @@ EOF test_expect_success \ 'ls-tree filter 1.txt' \ - 'git-ls-tree $tree 1.txt >current && + 'git ls-tree $tree 1.txt >current && cat >expected <<\EOF && 100644 blob X 1.txt EOF @@ -84,7 +82,7 @@ EOF test_expect_success \ 'ls-tree filter path1/b/c/1.txt' \ - 'git-ls-tree $tree path1/b/c/1.txt >current && + 'git ls-tree $tree path1/b/c/1.txt >current && cat >expected <<\EOF && 100644 blob X path1/b/c/1.txt EOF @@ -92,7 +90,7 @@ 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 && + '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 @@ -107,7 +105,7 @@ EOF # 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 && + '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 @@ -120,7 +118,7 @@ EOF # 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//1.txt path3 /path3/ path3// >current && + '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 @@ -130,9 +128,100 @@ EOF 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 && + '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 is leading path match' ' + git ls-tree $tree pa path3/a >current && + >expected && + test_output +' + +test_expect_success 'ls-tree --full-name' ' + ( + cd path0 && + git ls-tree --full-name $tree a + ) >current && + cat >expected <<\EOF && +040000 tree X path0/a +EOF + test_output +' + +test_expect_success 'ls-tree --full-tree' ' + ( + cd path1/b/c && + git ls-tree --full-tree $tree + ) >current && + cat >expected <<\EOF && +100644 blob X 1.txt +100644 blob X 2.txt +040000 tree X path0 +040000 tree X path1 +040000 tree X path2 +040000 tree X path3 +EOF + test_output +' + +test_expect_success 'ls-tree --full-tree -r' ' + ( + cd path3/ && + git ls-tree --full-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 +100644 blob X path1/b/c/1.txt +100644 blob X path2/1.txt +100644 blob X path3/1.txt +100644 blob X path3/2.txt +EOF + test_output +' + +test_expect_success 'ls-tree --abbrev=5' ' + git ls-tree --abbrev=5 $tree >current && + sed -e "s/ $_x05[0-9a-f]* / X /" <current >check && + cat >expected <<\EOF && +100644 blob X 1.txt +100644 blob X 2.txt +040000 tree X path0 +040000 tree X path1 +040000 tree X path2 +040000 tree X path3 +EOF + test_cmp expected check +' + +test_expect_success 'ls-tree --name-only' ' + git ls-tree --name-only $tree >current + cat >expected <<\EOF && +1.txt +2.txt +path0 +path1 +path2 +path3 +EOF + test_output +' + +test_expect_success 'ls-tree --name-only -r' ' + git ls-tree --name-only -r $tree >current + cat >expected <<\EOF && +1.txt +2.txt +path0/a/b/c/1.txt +path1/b/c/1.txt +path2/1.txt +path3/1.txt +path3/2.txt +EOF + test_output +' + test_done diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 5565c27033..f54a533456 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -11,24 +11,28 @@ handled. Specifically, that a bogus branch is not created. . ./test-lib.sh test_expect_success \ - 'prepare an trivial repository' \ + 'prepare a trivial repository' \ 'echo Hello > A && - git-update-index --add A && - git-commit -m "Initial commit." && - HEAD=$(git-rev-parse --verify HEAD)' + git update-index --add A && + git commit -m "Initial commit." && + echo World >> A && + git update-index --add A && + git commit -m "Second commit." && + HEAD=$(git rev-parse --verify HEAD)' -test_expect_failure \ - 'git branch --help should not have created a bogus branch' \ - 'git-branch --help </dev/null >/dev/null 2>/dev/null || : - test -f .git/refs/heads/--help' +test_expect_success \ + 'git branch --help should not have created a bogus branch' ' + git branch --help </dev/null >/dev/null 2>/dev/null; + ! test -f .git/refs/heads/--help +' test_expect_success \ 'git branch abc should create a branch' \ - 'git-branch abc && test -f .git/refs/heads/abc' + 'git branch abc && test -f .git/refs/heads/abc' test_expect_success \ 'git branch a/b/c should create a branch' \ - 'git-branch a/b/c && test -f .git/refs/heads/a/b/c' + 'git branch a/b/c && test -f .git/refs/heads/a/b/c' cat >expect <<EOF 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master @@ -36,85 +40,479 @@ EOF test_expect_success \ 'git branch -l d/e/f should create a branch and a log' \ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ - git-branch -l d/e/f && + 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' \ - 'git-branch -d d/e/f && + 'git branch -d d/e/f && test ! -f .git/refs/heads/d/e/f && test ! -f .git/logs/refs/heads/d/e/f' -cat >expect <<EOF -0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 checkout: Created from master -EOF -test_expect_success \ - 'git checkout -b g/h/i -l should create a branch and a log' \ - 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ - git-checkout -b g/h/i -l master && - test -f .git/refs/heads/g/h/i && - test -f .git/logs/refs/heads/g/h/i && - diff expect .git/logs/refs/heads/g/h/i' - test_expect_success \ 'git branch j/k should work after branch j has been deleted' \ - 'git-branch j && - git-branch -d j && - git-branch j/k' + 'git branch j && + git branch -d j && + git branch j/k' test_expect_success \ 'git branch l should work after branch l/m has been deleted' \ - 'git-branch l/m && - git-branch -d l/m && - git-branch l' + 'git branch l/m && + git branch -d l/m && + git branch l' test_expect_success \ 'git branch -m m m/m should work' \ - 'git-branch -l m && - git-branch -m m m/m && + 'git branch -l m && + git branch -m m m/m && test -f .git/logs/refs/heads/m/m' test_expect_success \ 'git branch -m n/n n should work' \ - 'git-branch -l n/n && - git-branch -m n/n n + 'git branch -l n/n && + git branch -m n/n n test -f .git/logs/refs/heads/n' -test_expect_failure \ - 'git branch -m o/o o should fail when o/p exists' \ - 'git-branch o/o && - git-branch o/p && - git-branch -m o/o o' +test_expect_success 'git branch -m o/o o should fail when o/p exists' ' + git branch o/o && + git branch o/p && + test_must_fail git branch -m o/o o +' + +test_expect_success 'git branch -m q r/q should fail when r exists' ' + git branch q && + git branch r && + test_must_fail git branch -m q r/q +' + +mv .git/config .git/config-saved + +test_expect_success 'git branch -m q q2 without config should succeed' ' + git branch -m q q2 && + git branch -m q2 q +' -test_expect_failure \ - 'git branch -m q r/q should fail when r exists' \ - 'git-branch q && - git-branch r && - git-branch -m q r/q' +mv .git/config-saved .git/config -git-config branch.s/s.dummy Hello +git config branch.s/s.dummy Hello test_expect_success \ 'git branch -m s/s s should work when s/t is deleted' \ - 'git-branch -l s/s && + 'git branch -l s/s && test -f .git/logs/refs/heads/s/s && - git-branch -l s/t && + git branch -l s/t && test -f .git/logs/refs/heads/s/t && - git-branch -d s/t && - git-branch -m s/s s && + git branch -d s/t && + git branch -m s/s s && test -f .git/logs/refs/heads/s' test_expect_success 'config information was renamed, too' \ - "test $(git-config branch.s.dummy) = Hello && - ! git-config branch.s/s/dummy" + "test $(git config branch.s.dummy) = Hello && + test_must_fail git config branch.s/s/dummy" -test_expect_failure \ - 'git-branch -m u v should fail when the reflog for u is a symlink' \ - 'git-branch -l u && +test_expect_success 'renaming a symref is not allowed' \ +' + git symbolic-ref refs/heads/master2 refs/heads/master && + test_must_fail git branch -m master2 master3 && + git symbolic-ref refs/heads/master2 && + test -f .git/refs/heads/master && + ! test -f .git/refs/heads/master3 +' + +test_expect_success SYMLINKS \ + 'git branch -m u v should fail when the reflog for u is a symlink' ' + git branch -l u && mv .git/logs/refs/heads/u real-u && ln -s real-u .git/logs/refs/heads/u && - git-branch -m u v' + test_must_fail git branch -m u v +' + +test_expect_success 'test tracking setup via --track' \ + 'git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track my1 local/master && + test $(git config branch.my1.remote) = local && + test $(git config branch.my1.merge) = refs/heads/master' + +test_expect_success 'test tracking setup (non-wildcard, matching)' \ + 'git config remote.local.url . && + git config remote.local.fetch refs/heads/master:refs/remotes/local/master && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track my4 local/master && + test $(git config branch.my4.remote) = local && + test $(git config branch.my4.merge) = refs/heads/master' + +test_expect_success 'test tracking setup (non-wildcard, not matching)' \ + 'git config remote.local.url . && + git config remote.local.fetch refs/heads/s:refs/remotes/local/s && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track my5 local/master && + ! test "$(git config branch.my5.remote)" = local && + ! test "$(git config branch.my5.merge)" = refs/heads/master' + +test_expect_success 'test tracking setup via config' \ + 'git config branch.autosetupmerge true && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch my3 local/master && + test $(git config branch.my3.remote) = local && + test $(git config branch.my3.merge) = refs/heads/master' + +test_expect_success 'test overriding tracking setup via --no-track' \ + 'git config branch.autosetupmerge true && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track my2 local/master && + git config branch.autosetupmerge false && + ! test "$(git config branch.my2.remote)" = local && + ! test "$(git config branch.my2.merge)" = refs/heads/master' + +test_expect_success 'no tracking without .fetch entries' \ + 'git config branch.autosetupmerge true && + git branch my6 s && + git config branch.automsetupmerge false && + test -z "$(git config branch.my6.remote)" && + test -z "$(git config branch.my6.merge)"' + +test_expect_success 'test tracking setup via --track but deeper' \ + 'git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/o/o || git fetch local) && + git branch --track my7 local/o/o && + test "$(git config branch.my7.remote)" = local && + test "$(git config branch.my7.merge)" = refs/heads/o/o' + +test_expect_success 'test deleting branch deletes branch config' \ + 'git branch -d my7 && + test -z "$(git config branch.my7.remote)" && + test -z "$(git config branch.my7.merge)"' + +test_expect_success 'test deleting branch without config' \ + 'git branch my7 s && + sha1=$(git rev-parse my7 | cut -c 1-7) && + test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."' + +test_expect_success 'test --track without .fetch entries' \ + 'git branch --track my8 && + test "$(git config branch.my8.remote)" && + test "$(git config branch.my8.merge)"' + +test_expect_success \ + 'branch from non-branch HEAD w/autosetupmerge=always' \ + 'git config branch.autosetupmerge always && + git branch my9 HEAD^ && + git config branch.autosetupmerge false' + +test_expect_success \ + 'branch from non-branch HEAD w/--track causes failure' \ + 'test_must_fail git branch --track my10 HEAD^' + +# Keep this test last, as it changes the current branch +cat >expect <<EOF +0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master +EOF +test_expect_success \ + 'git checkout -b g/h/i -l should create a branch and a log' \ + 'GIT_COMMITTER_DATE="2005-05-26 23:30" \ + git checkout -b g/h/i -l master && + test -f .git/refs/heads/g/h/i && + test -f .git/logs/refs/heads/g/h/i && + test_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 && + git config remote.ambi1.url lalala && + git config remote.ambi1.fetch refs/heads/lalala:refs/heads/master && + git config remote.ambi2.url lilili && + git config remote.ambi2.fetch refs/heads/lilili:refs/heads/master && + git branch all1 master && + test -z "$(git config branch.all1.merge)" +' + +test_expect_success 'autosetuprebase local on a tracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase local && + (git show-ref -q refs/remotes/local/o || git fetch local) && + git branch mybase && + git branch --track myr1 mybase && + test "$(git config branch.myr1.remote)" = . && + test "$(git config branch.myr1.merge)" = refs/heads/mybase && + test "$(git config branch.myr1.rebase)" = true +' + +test_expect_success 'autosetuprebase always on a tracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase always && + (git show-ref -q refs/remotes/local/o || git fetch local) && + git branch mybase2 && + git branch --track myr2 mybase && + test "$(git config branch.myr2.remote)" = . && + test "$(git config branch.myr2.merge)" = refs/heads/mybase && + test "$(git config branch.myr2.rebase)" = true +' + +test_expect_success 'autosetuprebase remote on a tracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase remote && + (git show-ref -q refs/remotes/local/o || git fetch local) && + git branch mybase3 && + git branch --track myr3 mybase2 && + test "$(git config branch.myr3.remote)" = . && + test "$(git config branch.myr3.merge)" = refs/heads/mybase2 && + ! test "$(git config branch.myr3.rebase)" = true +' + +test_expect_success 'autosetuprebase never on a tracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase never && + (git show-ref -q refs/remotes/local/o || git fetch local) && + git branch mybase4 && + git branch --track myr4 mybase2 && + test "$(git config branch.myr4.remote)" = . && + test "$(git config branch.myr4.merge)" = refs/heads/mybase2 && + ! test "$(git config branch.myr4.rebase)" = true +' + +test_expect_success 'autosetuprebase local on a tracked remote branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase local && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track myr5 local/master && + test "$(git config branch.myr5.remote)" = local && + test "$(git config branch.myr5.merge)" = refs/heads/master && + ! test "$(git config branch.myr5.rebase)" = true +' + +test_expect_success 'autosetuprebase never on a tracked remote branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase never && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track myr6 local/master && + test "$(git config branch.myr6.remote)" = local && + test "$(git config branch.myr6.merge)" = refs/heads/master && + ! test "$(git config branch.myr6.rebase)" = true +' + +test_expect_success 'autosetuprebase remote on a tracked remote branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase remote && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track myr7 local/master && + test "$(git config branch.myr7.remote)" = local && + test "$(git config branch.myr7.merge)" = refs/heads/master && + test "$(git config branch.myr7.rebase)" = true +' + +test_expect_success 'autosetuprebase always on a tracked remote branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + git config branch.autosetuprebase remote && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track myr8 local/master && + test "$(git config branch.myr8.remote)" = local && + test "$(git config branch.myr8.merge)" = refs/heads/master && + test "$(git config branch.myr8.rebase)" = true +' + +test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' ' + git config --unset branch.autosetuprebase && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --track myr9 local/master && + test "$(git config branch.myr9.remote)" = local && + test "$(git config branch.myr9.merge)" = refs/heads/master && + test "z$(git config branch.myr9.rebase)" = z +' + +test_expect_success 'autosetuprebase unconfigured on a tracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/o || git fetch local) && + git branch mybase10 && + git branch --track myr10 mybase2 && + test "$(git config branch.myr10.remote)" = . && + test "$(git config branch.myr10.merge)" = refs/heads/mybase2 && + test "z$(git config branch.myr10.rebase)" = z +' + +test_expect_success 'autosetuprebase unconfigured on untracked local branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr11 mybase2 && + test "z$(git config branch.myr11.remote)" = z && + test "z$(git config branch.myr11.merge)" = z && + test "z$(git config branch.myr11.rebase)" = z +' + +test_expect_success 'autosetuprebase unconfigured on untracked remote branch' ' + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr12 local/master && + test "z$(git config branch.myr12.remote)" = z && + test "z$(git config branch.myr12.merge)" = z && + test "z$(git config branch.myr12.rebase)" = z +' + +test_expect_success 'autosetuprebase never on an untracked local branch' ' + git config branch.autosetuprebase never && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr13 mybase2 && + test "z$(git config branch.myr13.remote)" = z && + test "z$(git config branch.myr13.merge)" = z && + test "z$(git config branch.myr13.rebase)" = z +' + +test_expect_success 'autosetuprebase local on an untracked local branch' ' + git config branch.autosetuprebase local && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr14 mybase2 && + test "z$(git config branch.myr14.remote)" = z && + test "z$(git config branch.myr14.merge)" = z && + test "z$(git config branch.myr14.rebase)" = z +' + +test_expect_success 'autosetuprebase remote on an untracked local branch' ' + git config branch.autosetuprebase remote && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr15 mybase2 && + test "z$(git config branch.myr15.remote)" = z && + test "z$(git config branch.myr15.merge)" = z && + test "z$(git config branch.myr15.rebase)" = z +' + +test_expect_success 'autosetuprebase always on an untracked local branch' ' + git config branch.autosetuprebase always && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr16 mybase2 && + test "z$(git config branch.myr16.remote)" = z && + test "z$(git config branch.myr16.merge)" = z && + test "z$(git config branch.myr16.rebase)" = z +' + +test_expect_success 'autosetuprebase never on an untracked remote branch' ' + git config branch.autosetuprebase never && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr17 local/master && + test "z$(git config branch.myr17.remote)" = z && + test "z$(git config branch.myr17.merge)" = z && + test "z$(git config branch.myr17.rebase)" = z +' + +test_expect_success 'autosetuprebase local on an untracked remote branch' ' + git config branch.autosetuprebase local && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr18 local/master && + test "z$(git config branch.myr18.remote)" = z && + test "z$(git config branch.myr18.merge)" = z && + test "z$(git config branch.myr18.rebase)" = z +' + +test_expect_success 'autosetuprebase remote on an untracked remote branch' ' + git config branch.autosetuprebase remote && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr19 local/master && + test "z$(git config branch.myr19.remote)" = z && + test "z$(git config branch.myr19.merge)" = z && + test "z$(git config branch.myr19.rebase)" = z +' + +test_expect_success 'autosetuprebase always on an untracked remote branch' ' + git config branch.autosetuprebase always && + git config remote.local.url . && + git config remote.local.fetch refs/heads/*:refs/remotes/local/* && + (git show-ref -q refs/remotes/local/master || git fetch local) && + git branch --no-track myr20 local/master && + test "z$(git config branch.myr20.remote)" = z && + test "z$(git config branch.myr20.merge)" = z && + test "z$(git config branch.myr20.rebase)" = z +' + +test_expect_success 'detect misconfigured autosetuprebase (bad value)' ' + git config branch.autosetuprebase garbage && + test_must_fail git branch +' + +test_expect_success 'detect misconfigured autosetuprebase (no value)' ' + git config --unset branch.autosetuprebase && + echo "[branch] autosetuprebase" >> .git/config && + test_must_fail git branch && + git config --unset branch.autosetuprebase +' + +test_expect_success 'attempt to delete a branch without base and unmerged to HEAD' ' + git checkout my9 && + git config --unset branch.my8.merge && + test_must_fail git branch -d my8 +' + +test_expect_success 'attempt to delete a branch merged to its base' ' + # we are on my9 which is the initial commit; traditionally + # we would not have allowed deleting my8 that is not merged + # to my9, but it is set to track master that already has my8 + git config branch.my8.merge refs/heads/master && + git branch -d my8 +' + +test_expect_success 'attempt to delete a branch merged to its base' ' + git checkout master && + echo Third >>A && + git commit -m "Third commit" A && + git branch -t my10 my9 && + git branch -f my10 HEAD^ && + # we are on master which is at the third commit, and my10 + # is behind us, so traditionally we would have allowed deleting + # it; but my10 is set to track my9 that is further behind. + test_must_fail git branch -d my10 +' test_done diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh new file mode 100755 index 0000000000..f86f4bc5eb --- /dev/null +++ b/t/t3201-branch-contains.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='branch --contains <commit>, --merged, and --no-merged' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + test_tick && + git commit -m initial && + git branch side && + + echo 1 >file && + test_tick && + git commit -a -m "second on master" && + + git checkout side && + echo 1 >file && + test_tick && + git commit -a -m "second on side" && + + git merge master + +' + +test_expect_success 'branch --contains=master' ' + + git branch --contains=master >actual && + { + echo " master" && echo "* side" + } >expect && + test_cmp expect actual + +' + +test_expect_success 'branch --contains master' ' + + git branch --contains master >actual && + { + echo " master" && echo "* side" + } >expect && + test_cmp expect actual + +' + +test_expect_success 'branch --contains=side' ' + + git branch --contains=side >actual && + { + echo "* side" + } >expect && + test_cmp expect actual + +' + +test_expect_success 'side: branch --merged' ' + + git branch --merged >actual && + { + echo " master" && + echo "* side" + } >expect && + test_cmp expect actual + +' + +test_expect_success 'side: branch --no-merged' ' + + git branch --no-merged >actual && + >expect && + test_cmp expect actual + +' + +test_expect_success 'master: branch --merged' ' + + git checkout master && + git branch --merged >actual && + { + echo "* master" + } >expect && + test_cmp expect actual + +' + +test_expect_success 'master: branch --no-merged' ' + + git branch --no-merged >actual && + { + echo " side" + } >expect && + test_cmp expect actual + +' + +test_done diff --git a/t/t3202-show-branch-octopus.sh b/t/t3202-show-branch-octopus.sh new file mode 100755 index 0000000000..0a5d5e669f --- /dev/null +++ b/t/t3202-show-branch-octopus.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='test show-branch with more than 8 heads' + +. ./test-lib.sh + +numbers="1 2 3 4 5 6 7 8 9 10" + +test_expect_success 'setup' ' + + > file && + git add file && + test_tick && + git commit -m initial && + + for i in $numbers + do + git checkout -b branch$i master && + > file$i && + git add file$i && + test_tick && + git commit -m branch$i || break + done + +' + +cat > expect << EOF +! [branch1] branch1 + ! [branch2] branch2 + ! [branch3] branch3 + ! [branch4] branch4 + ! [branch5] branch5 + ! [branch6] branch6 + ! [branch7] branch7 + ! [branch8] branch8 + ! [branch9] branch9 + * [branch10] branch10 +---------- + * [branch10] branch10 + + [branch9] branch9 + + [branch8] branch8 + + [branch7] branch7 + + [branch6] branch6 + + [branch5] branch5 + + [branch4] branch4 + + [branch3] branch3 + + [branch2] branch2 ++ [branch1] branch1 ++++++++++* [branch10^] initial +EOF + +test_expect_success 'show-branch with more than 8 branches' ' + + git show-branch $(for i in $numbers; do echo branch$i; done) > out && + test_cmp expect out + +' + +test_expect_success 'show-branch with showbranch.default' ' + for i in $numbers; do + git config --add showbranch.default branch$i + done && + git show-branch >out && + test_cmp expect out +' + +test_done diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh new file mode 100755 index 0000000000..809d1c4ed4 --- /dev/null +++ b/t/t3203-branch-output.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +test_description='git branch display tests' +. ./test-lib.sh + +test_expect_success 'make commits' ' + echo content >file && + git add file && + git commit -m one && + echo content >>file && + git commit -a -m two +' + +test_expect_success 'make branches' ' + git branch branch-one + git branch branch-two HEAD^ +' + +test_expect_success 'make remote branches' ' + git update-ref refs/remotes/origin/branch-one branch-one + git update-ref refs/remotes/origin/branch-two branch-two + git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/branch-one +' + +cat >expect <<'EOF' + branch-one + branch-two +* master +EOF +test_expect_success 'git branch shows local branches' ' + git branch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' + origin/HEAD -> origin/branch-one + origin/branch-one + origin/branch-two +EOF +test_expect_success 'git branch -r shows remote branches' ' + git branch -r >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' + branch-one + branch-two +* master + remotes/origin/HEAD -> origin/branch-one + remotes/origin/branch-one + remotes/origin/branch-two +EOF +test_expect_success 'git branch -a shows local and remote branches' ' + git branch -a >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +two +one +two +EOF +test_expect_success 'git branch -v shows branch summaries' ' + git branch -v >tmp && + awk "{print \$NF}" <tmp >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +* (no branch) + branch-one + branch-two + master +EOF +test_expect_success 'git branch shows detached HEAD properly' ' + git checkout HEAD^0 && + git branch >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index f0c7e22b36..525174013c 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -16,93 +16,100 @@ echo '[core] logallrefupdates = true' >>.git/config test_expect_success \ 'prepare a trivial repository' \ 'echo Hello > A && - git-update-index --add A && - git-commit -m "Initial commit." && - HEAD=$(git-rev-parse --verify HEAD)' + git update-index --add A && + git commit -m "Initial commit." && + HEAD=$(git rev-parse --verify HEAD)' SHA1= test_expect_success \ 'see if git show-ref works as expected' \ - 'git-branch a && + 'git branch a && SHA1=`cat .git/refs/heads/a` && echo "$SHA1 refs/heads/a" >expect && - git-show-ref a >result && - diff expect result' + git show-ref a >result && + test_cmp expect result' test_expect_success \ 'see if a branch still exists when packed' \ - 'git-branch b && - git-pack-refs --all && + 'git branch b && + git pack-refs --all && rm -f .git/refs/heads/b && echo "$SHA1 refs/heads/b" >expect && - git-show-ref b >result && - diff expect result' - -test_expect_failure \ - 'git branch c/d should barf if branch c exists' \ - 'git-branch c && - git-pack-refs --all && - rm .git/refs/heads/c && - git-branch c/d' + git show-ref b >result && + test_cmp expect result' + +test_expect_success 'git branch c/d should barf if branch c exists' ' + git branch c && + git pack-refs --all && + rm -f .git/refs/heads/c && + test_must_fail git branch c/d +' test_expect_success \ 'see if a branch still exists after git pack-refs --prune' \ - 'git-branch e && - git-pack-refs --all --prune && + 'git branch e && + git pack-refs --all --prune && echo "$SHA1 refs/heads/e" >expect && - git-show-ref e >result && - diff expect result' + git show-ref e >result && + test_cmp expect result' -test_expect_failure \ - 'see if git pack-refs --prune remove ref files' \ - 'git-branch f && - git-pack-refs --all --prune && - ls .git/refs/heads/f' +test_expect_success 'see if git pack-refs --prune remove ref files' ' + git branch f && + git pack-refs --all --prune && + ! test -f .git/refs/heads/f +' test_expect_success \ 'git branch g should work when git branch g/h has been deleted' \ - 'git-branch g/h && - git-pack-refs --all --prune && - git-branch -d g/h && - git-branch g && - git-pack-refs --all && - git-branch -d g' - -test_expect_failure \ - 'git branch i/j/k should barf if branch i exists' \ - 'git-branch i && - git-pack-refs --all --prune && - git-branch i/j/k' + 'git branch g/h && + git pack-refs --all --prune && + git branch -d g/h && + git branch g && + git pack-refs --all && + git branch -d g' + +test_expect_success 'git branch i/j/k should barf if branch i exists' ' + git branch i && + git pack-refs --all --prune && + test_must_fail git branch i/j/k +' test_expect_success \ 'test git branch k after branch k/l/m and k/lm have been deleted' \ - 'git-branch k/l && - git-branch k/lm && - git-branch -d k/l && - git-branch k/l/m && - git-branch -d k/l/m && - git-branch -d k/lm && - git-branch k' + 'git branch k/l && + git branch k/lm && + git branch -d k/l && + git branch k/l/m && + git branch -d k/l/m && + git branch -d k/lm && + git branch k' test_expect_success \ 'test git branch n after some branch deletion and pruning' \ - 'git-branch n/o && - git-branch n/op && - git-branch -d n/o && - git-branch n/o/p && - git-branch -d n/op && - git-pack-refs --all --prune && - git-branch -d n/o/p && - git-branch n' + 'git branch n/o && + git branch n/op && + git branch -d n/o && + git branch n/o/p && + git branch -d n/op && + git pack-refs --all --prune && + git branch -d n/o/p && + git branch n' + +test_expect_success \ + 'see if up-to-date packed refs are preserved' \ + 'git branch q && + git pack-refs --all --prune && + git update-ref refs/heads/q refs/heads/q && + ! test -f .git/refs/heads/q' test_expect_success 'pack, prune and repack' ' - git-tag foo && - git-pack-refs --all --prune && - git-show-ref >all-of-them && - git-pack-refs && - git-show-ref >again && - diff all-of-them again + git tag foo && + git pack-refs --all --prune && + git show-ref >all-of-them && + git pack-refs && + git show-ref >again && + test_cmp all-of-them again ' test_done diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index c12270efab..a99e4d8b92 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -21,23 +21,23 @@ cat >"$p0" <<\EOF 3. A quick brown fox jumps over the lazy cat, oops dog. EOF -cat >"$p1" "$p0" +cat 2>/dev/null >"$p1" "$p0" echo 'Foo Bar Baz' >"$p2" test -f "$p1" && cmp "$p0" "$p1" || { # since FAT/NTFS does not allow tabs in filenames, skip this test - say 'Your filesystem does not allow tabs in filenames, test skipped.' + skip_all='Your filesystem does not allow tabs in filenames, test skipped.' test_done } echo 'just space no-funny' >expected -test_expect_success 'git-ls-files no-funny' \ - 'git-update-index --add "$p0" "$p2" && - git-ls-files >current && - diff -u expected current' +test_expect_success 'git ls-files no-funny' \ + 'git update-index --add "$p0" "$p2" && + git ls-files >current && + test_cmp expected current' -t0=`git-write-tree` +t0=`git write-tree` echo "$t0" >t0 cat > expected <<\EOF @@ -45,19 +45,19 @@ just space no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-ls-files with-funny' \ - 'git-update-index --add "$p1" && - git-ls-files >current && - diff -u expected current' +test_expect_success 'git ls-files with-funny' \ + 'git update-index --add "$p1" && + git ls-files >current && + test_cmp expected current' echo 'just space no-funny tabs ," (dq) and spaces' >expected -test_expect_success 'git-ls-files -z with-funny' \ - 'git-ls-files -z | tr \\0 \\012 >current && - diff -u expected current' +test_expect_success 'git ls-files -z with-funny' \ + 'git ls-files -z | perl -pe y/\\000/\\012/ >current && + test_cmp expected current' -t1=`git-write-tree` +t1=`git write-tree` echo "$t1" >t1 cat > expected <<\EOF @@ -65,47 +65,47 @@ just space no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-ls-tree with funny' \ - 'git-ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current && - diff -u expected current' +test_expect_success 'git ls-tree with funny' \ + 'git ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current && + test_cmp expected current' cat > expected <<\EOF A "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-diff-index with-funny' \ - 'git-diff-index --name-status $t0 >current && - diff -u expected current' +test_expect_success 'git diff-index with-funny' \ + 'git diff-index --name-status $t0 >current && + test_cmp expected current' -test_expect_success 'git-diff-tree with-funny' \ - 'git-diff-tree --name-status $t0 $t1 >current && - diff -u expected current' +test_expect_success 'git diff-tree with-funny' \ + 'git diff-tree --name-status $t0 $t1 >current && + test_cmp expected current' echo 'A tabs ," (dq) and spaces' >expected -test_expect_success 'git-diff-index -z with-funny' \ - 'git-diff-index -z --name-status $t0 | tr \\0 \\012 >current && - diff -u expected current' +test_expect_success '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' \ - 'git-diff-tree -z --name-status $t0 $t1 | tr \\0 \\012 >current && - diff -u expected current' +test_expect_success 'git diff-tree -z with-funny' \ + 'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\000/\\012/ >current && + test_cmp expected current' cat > expected <<\EOF CNUM no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-diff-tree -C with-funny' \ - 'git-diff-tree -C --find-copies-harder --name-status \ +test_expect_success '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 && - diff -u expected current' + test_cmp expected current' cat > expected <<\EOF RNUM no-funny "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-diff-tree delete with-funny' \ - 'git-update-index --force-remove "$p0" && - git-diff-index -M --name-status \ +test_expect_success '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 && - diff -u expected current' + test_cmp expected current' cat > expected <<\EOF diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" @@ -113,10 +113,10 @@ similarity index NUM% rename from no-funny rename to "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-diff-tree delete with-funny' \ - 'git-diff-index -M -p $t0 | +test_expect_success 'git diff-tree delete with-funny' \ + 'git diff-index -M -p $t0 | sed -e "s/index [0-9]*%/index NUM%/" >current && - diff -u expected current' + test_cmp expected current' chmod +x "$p1" cat > expected <<\EOF @@ -127,34 +127,34 @@ similarity index NUM% rename from no-funny rename to "tabs\t,\" (dq) and spaces" EOF -test_expect_success 'git-diff-tree delete with-funny' \ - 'git-diff-index -M -p $t0 | +test_expect_success 'git diff-tree delete with-funny' \ + 'git diff-index -M -p $t0 | sed -e "s/index [0-9]*%/index NUM%/" >current && - diff -u expected current' + test_cmp expected current' 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' \ - 'git-diff-index -M -p $t0 | - git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - diff -u expected current' +test_expect_success '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' 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' \ - 'git-diff-index -p $t0 | - git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - diff -u expected current' +test_expect_success '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' \ - 'git-diff-index -p $t0 | +test_expect_success 'git apply non-git diff' \ + 'git diff-index -p $t0 | sed -ne "/^[-+@]/p" | - git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && - diff -u expected current' + git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current && + test_cmp expected current' test_done diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh new file mode 100755 index 0000000000..1d82f79ee0 --- /dev/null +++ b/t/t3301-notes.sh @@ -0,0 +1,1057 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test commit notes' + +. ./test-lib.sh + +cat > fake_editor.sh << \EOF +#!/bin/sh +echo "$MSG" > "$1" +echo "$MSG" >& 2 +EOF +chmod a+x fake_editor.sh +GIT_EDITOR=./fake_editor.sh +export GIT_EDITOR + +test_expect_success 'cannot annotate non-existing HEAD' ' + (MSG=3 && export MSG && test_must_fail git notes add) +' + +test_expect_success setup ' + : > a1 && + git add a1 && + test_tick && + git commit -m 1st && + : > a2 && + git add a2 && + test_tick && + git commit -m 2nd +' + +test_expect_success 'need valid notes ref' ' + (MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF && + test_must_fail git notes add) && + (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF && + test_must_fail git notes show) +' + +test_expect_success 'refusing to add notes in refs/heads/' ' + (MSG=1 GIT_NOTES_REF=refs/heads/bogus && + export MSG GIT_NOTES_REF && + test_must_fail git notes add) +' + +test_expect_success 'refusing to edit notes in refs/remotes/' ' + (MSG=1 GIT_NOTES_REF=refs/remotes/bogus && + export MSG GIT_NOTES_REF && + test_must_fail git notes edit) +' + +# 1 indicates caught gracefully by die, 128 means git-show barked +test_expect_success 'handle empty notes gracefully' ' + git notes show ; test 1 = $? +' + +test_expect_success 'show non-existent notes entry with %N' ' + for l in A B + do + echo "$l" + done >expect && + git show -s --format='A%n%NB' >output && + test_cmp expect output +' + +test_expect_success 'create notes' ' + git config core.notesRef refs/notes/commits && + MSG=b4 git notes add && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b4 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + +test_expect_success 'show notes entry with %N' ' + for l in A b4 B + do + echo "$l" + done >expect && + git show -s --format='A%n%NB' >output && + test_cmp expect output +' + +cat >expect <<EOF +d423f8c refs/notes/commits@{0}: notes: Notes added by 'git notes add' +EOF + +test_expect_success 'create reflog entry' ' + git reflog show refs/notes/commits >output && + test_cmp expect output +' + +test_expect_success 'edit existing notes' ' + MSG=b3 git notes edit && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b3 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + +test_expect_success 'cannot add note where one exists' ' + ! MSG=b2 git notes add && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b3 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + +test_expect_success 'can overwrite existing note with "git notes add -f"' ' + MSG=b1 git notes add -f && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b1 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ +' + +cat > expect << EOF +commit 268048bfb8a1fb38e703baceb8ab235421bf80c5 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:14:13 2005 -0700 + + 2nd + +Notes: + b1 +EOF + +test_expect_success 'show notes' ' + ! (git cat-file commit HEAD | grep b1) && + git log -1 > output && + test_cmp expect output +' + +test_expect_success 'create multi-line notes (setup)' ' + : > a3 && + git add a3 && + test_tick && + git commit -m 3rd && + MSG="b3 +c3c3c3c3 +d3d3d3" git notes add +' + +cat > expect-multiline << EOF +commit 1584215f1d29c65e99c6c6848626553fdd07fd75 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3rd + +Notes: + b3 + c3c3c3c3 + d3d3d3 +EOF + +printf "\n" >> expect-multiline +cat expect >> expect-multiline + +test_expect_success 'show multi-line notes' ' + git log -2 > output && + test_cmp expect-multiline output +' +test_expect_success 'create -F notes (setup)' ' + : > a4 && + git add a4 && + test_tick && + git commit -m 4th && + echo "xyzzy" > note5 && + git notes add -F note5 +' + +cat > expect-F << EOF +commit 15023535574ded8b1a89052b32673f84cf9582b8 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:16:13 2005 -0700 + + 4th + +Notes: + xyzzy +EOF + +printf "\n" >> expect-F +cat expect-multiline >> expect-F + +test_expect_success 'show -F notes' ' + git log -3 > output && + test_cmp expect-F output +' + +cat >expect << EOF +commit 15023535574ded8b1a89052b32673f84cf9582b8 +tree e070e3af51011e47b183c33adf9736736a525709 +parent 1584215f1d29c65e99c6c6848626553fdd07fd75 +author A U Thor <author@example.com> 1112912173 -0700 +committer C O Mitter <committer@example.com> 1112912173 -0700 + + 4th +EOF +test_expect_success 'git log --pretty=raw does not show notes' ' + git log -1 --pretty=raw >output && + test_cmp expect output +' + +cat >>expect <<EOF + +Notes: + xyzzy +EOF +test_expect_success 'git log --show-notes' ' + git log -1 --pretty=raw --show-notes >output && + test_cmp expect output +' + +test_expect_success 'git log --no-notes' ' + git log -1 --no-notes >output && + ! grep xyzzy output +' + +test_expect_success 'git format-patch does not show notes' ' + git format-patch -1 --stdout >output && + ! grep xyzzy output +' + +test_expect_success 'git format-patch --show-notes does show notes' ' + git format-patch --show-notes -1 --stdout >output && + grep xyzzy output +' + +for pretty in \ + "" --pretty --pretty=raw --pretty=short --pretty=medium \ + --pretty=full --pretty=fuller --pretty=format:%s --oneline +do + case "$pretty" in + "") p= not= negate="" ;; + ?*) p="$pretty" not=" not" negate="!" ;; + esac + test_expect_success "git show $pretty does$not show notes" ' + git show $p >output && + eval "$negate grep xyzzy output" + ' +done + +test_expect_success 'create -m notes (setup)' ' + : > a5 && + git add a5 && + test_tick && + git commit -m 5th && + git notes add -m spam -m "foo +bar +baz" +' + +whitespace=" " +cat > expect-m << EOF +commit bd1753200303d0a0344be813e504253b3d98e74d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + +Notes: + spam +$whitespace + foo + bar + baz +EOF + +printf "\n" >> expect-m +cat expect-F >> expect-m + +test_expect_success 'show -m notes' ' + git log -4 > output && + test_cmp expect-m output +' + +test_expect_success 'remove note with add -f -F /dev/null (setup)' ' + git notes add -f -F /dev/null +' + +cat > expect-rm-F << EOF +commit bd1753200303d0a0344be813e504253b3d98e74d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th +EOF + +printf "\n" >> expect-rm-F +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_expect_success 'do not create empty note with -m "" (setup)' ' + git notes add -m "" +' + +test_expect_success 'verify non-creation of note with -m ""' ' + git log -4 > output && + test_cmp expect-rm-F output && + ! git notes show +' + +cat > expect-combine_m_and_F << EOF +foo + +xyzzy + +bar + +zyxxy + +baz +EOF + +test_expect_success 'create note with combination of -m and -F' ' + echo "xyzzy" > note_a && + echo "zyxxy" > note_b && + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" && + git notes show > output && + test_cmp expect-combine_m_and_F output +' + +test_expect_success 'remove note with "git notes remove" (setup)' ' + git notes remove HEAD^ && + git notes remove +' + +cat > expect-rm-remove << EOF +commit bd1753200303d0a0344be813e504253b3d98e74d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + +commit 15023535574ded8b1a89052b32673f84cf9582b8 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:16:13 2005 -0700 + + 4th +EOF + +printf "\n" >> expect-rm-remove +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^ +' + +cat > expect << EOF +c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75 +c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5 +EOF + +test_expect_success 'list notes with "git notes list"' ' + git notes list > output && + test_cmp expect output +' + +test_expect_success 'list notes with "git notes"' ' + git notes > output && + test_cmp expect output +' + +cat > expect << EOF +c18dc024e14f08d18d14eea0d747ff692d66d6a3 +EOF + +test_expect_success 'list specific note with "git notes list <object>"' ' + git notes list HEAD^^ > output && + test_cmp expect output +' + +cat > expect << EOF +EOF + +test_expect_success 'listing non-existing notes fails' ' + test_must_fail git notes list HEAD > output && + test_cmp expect output +' + +cat > expect << EOF +Initial set of notes + +More notes appended with git notes append +EOF + +test_expect_success 'append to existing note with "git notes append"' ' + git notes add -m "Initial set of notes" && + git notes append -m "More notes appended with git notes append" && + git notes show > output && + test_cmp expect output +' + +cat > expect_list << EOF +c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75 +c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5 +4b6ad22357cc8a1296720574b8d2fbc22fab0671 bd1753200303d0a0344be813e504253b3d98e74d +EOF + +test_expect_success '"git notes list" does not expand to "git notes list HEAD"' ' + git notes list > output && + test_cmp expect_list output +' + +test_expect_success 'appending empty string does not change existing note' ' + git notes append -m "" && + git notes show > output && + test_cmp expect output +' + +test_expect_success 'git notes append == add when there is no existing note' ' + git notes remove HEAD && + test_must_fail git notes list HEAD && + git notes append -m "Initial set of notes + +More notes appended with git notes append" && + git notes show > output && + test_cmp expect output +' + +test_expect_success 'appending empty string to non-existing note does not create note' ' + git notes remove HEAD && + test_must_fail git notes list HEAD && + git notes append -m "" && + test_must_fail git notes list HEAD +' + +test_expect_success 'create other note on a different notes ref (setup)' ' + : > a6 && + git add a6 && + test_tick && + git commit -m 6th && + GIT_NOTES_REF="refs/notes/other" git notes add -m "other note" +' + +cat > expect-other << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + +Notes (other): + other note +EOF + +cat > expect-not-other << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th +EOF + +test_expect_success 'Do not show note on other ref by default' ' + git log -1 > output && + test_cmp expect-not-other output +' + +test_expect_success 'Do show note when ref is given in GIT_NOTES_REF' ' + GIT_NOTES_REF="refs/notes/other" git log -1 > output && + test_cmp expect-other output +' + +test_expect_success 'Do show note when ref is given in core.notesRef config' ' + git config core.notesRef "refs/notes/other" && + git log -1 > output && + test_cmp expect-other output +' + +test_expect_success 'Do not show note when core.notesRef is overridden' ' + GIT_NOTES_REF="refs/notes/wrong" git log -1 > output && + test_cmp expect-not-other output +' + +cat > expect-both << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + +Notes: + order test + +Notes (other): + other note + +commit bd1753200303d0a0344be813e504253b3d98e74d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + +Notes: + replacement for deleted note +EOF + +test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' ' + GIT_NOTES_REF=refs/notes/commits git notes add \ + -m"replacement for deleted note" HEAD^ && + GIT_NOTES_REF=refs/notes/commits git notes add -m"order test" && + git config --unset core.notesRef && + git config notes.displayRef "refs/notes/*" && + git log -2 > output && + test_cmp expect-both output +' + +test_expect_success 'core.notesRef is implicitly in notes.displayRef' ' + git config core.notesRef refs/notes/commits && + git config notes.displayRef refs/notes/other && + git log -2 > output && + test_cmp expect-both output +' + +test_expect_success 'notes.displayRef can be given more than once' ' + git config --unset core.notesRef && + git config notes.displayRef refs/notes/commits && + git config --add notes.displayRef refs/notes/other && + git log -2 > output && + test_cmp expect-both output +' + +cat > expect-both-reversed << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + +Notes (other): + other note + +Notes: + order test +EOF + +test_expect_success 'notes.displayRef respects order' ' + git config core.notesRef refs/notes/other && + git config --unset-all notes.displayRef && + git config notes.displayRef refs/notes/commits && + git log -1 > output && + test_cmp expect-both-reversed output +' + +test_expect_success 'GIT_NOTES_DISPLAY_REF works' ' + git config --unset-all core.notesRef && + git config --unset-all notes.displayRef && + GIT_NOTES_DISPLAY_REF=refs/notes/commits:refs/notes/other \ + git log -2 > output && + test_cmp expect-both output +' + +cat > expect-none << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + +commit bd1753200303d0a0344be813e504253b3d98e74d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th +EOF + +test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' ' + git config notes.displayRef "refs/notes/*" && + GIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 > output && + test_cmp expect-none output +' + +test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' ' + GIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 > output && + test_cmp expect-both output +' + +cat > expect-commits << EOF +commit 387a89921c73d7ed72cd94d179c1c7048ca47756 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + +Notes: + order test +EOF + +test_expect_success '--no-standard-notes' ' + git log --no-standard-notes --show-notes=commits -1 > output && + test_cmp expect-commits output +' + +test_expect_success '--standard-notes' ' + git log --no-standard-notes --show-notes=commits \ + --standard-notes -2 > output && + test_cmp expect-both output +' + +test_expect_success '--show-notes=ref accumulates' ' + git log --show-notes=other --show-notes=commits \ + --no-standard-notes -1 > output && + test_cmp expect-both-reversed output +' + +test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' ' + git config core.notesRef refs/notes/other && + echo "Note on a tree" > expect + git notes add -m "Note on a tree" HEAD: && + git notes show HEAD: > actual && + test_cmp expect actual && + echo "Note on a blob" > expect + filename=$(git ls-tree --name-only HEAD | head -n1) && + git notes add -m "Note on a blob" HEAD:$filename && + git notes show HEAD:$filename > actual && + test_cmp expect actual && + echo "Note on a tag" > expect + git tag -a -m "This is an annotated tag" foobar HEAD^ && + git notes add -m "Note on a tag" foobar && + git notes show foobar > actual && + test_cmp expect actual +' + +cat > expect << EOF +commit 2ede89468182a62d0bde2583c736089bcf7d7e92 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:19:13 2005 -0700 + + 7th + +Notes (other): + other note +EOF + +test_expect_success 'create note from other note with "git notes add -C"' ' + : > a7 && + git add a7 && + test_tick && + git commit -m 7th && + git notes add -C $(git notes list HEAD^) && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" +' + +test_expect_success 'create note from non-existing note with "git notes add -C" fails' ' + : > a8 && + git add a8 && + test_tick && + git commit -m 8th && + test_must_fail git notes add -C deadbeef && + test_must_fail git notes list HEAD +' + +cat > expect << EOF +commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:21:13 2005 -0700 + + 9th + +Notes (other): + yet another note +EOF + +test_expect_success 'create note from other note with "git notes add -c"' ' + : > a9 && + git add a9 && + test_tick && + git commit -m 9th && + MSG="yet another note" git notes add -c $(git notes list HEAD^^) && + git log -1 > actual && + test_cmp expect actual +' + +test_expect_success 'create note from non-existing note with "git notes add -c" fails' ' + : > a10 && + git add a10 && + test_tick && + git commit -m 10th && + ( + MSG="yet another note" && + export MSG && + test_must_fail git notes add -c deadbeef + ) && + test_must_fail git notes list HEAD +' + +cat > expect << EOF +commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:21:13 2005 -0700 + + 9th + +Notes (other): + yet another note +$whitespace + yet another note +EOF + +test_expect_success 'append to note from other note with "git notes append -C"' ' + git notes append -C $(git notes list HEAD^) HEAD^ && + git log -1 HEAD^ > actual && + test_cmp expect actual +' + +cat > expect << EOF +commit ffed603236bfa3891c49644257a83598afe8ae5a +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:22:13 2005 -0700 + + 10th + +Notes (other): + other note +EOF + +test_expect_success 'create note from other note with "git notes append -c"' ' + MSG="other note" git notes append -c $(git notes list HEAD^) && + git log -1 > actual && + test_cmp expect actual +' + +cat > expect << EOF +commit ffed603236bfa3891c49644257a83598afe8ae5a +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:22:13 2005 -0700 + + 10th + +Notes (other): + other note +$whitespace + yet another note +EOF + +test_expect_success 'append to note from other note with "git notes append -c"' ' + MSG="yet another note" git notes append -c $(git notes list HEAD) && + git log -1 > actual && + test_cmp expect actual +' + +cat > expect << EOF +commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:23:13 2005 -0700 + + 11th + +Notes (other): + other note +$whitespace + yet another note +EOF + +test_expect_success 'copy note with "git notes copy"' ' + : > a11 && + git add a11 && + test_tick && + git commit -m 11th && + git notes copy HEAD^ HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" +' + +test_expect_success 'prevent overwrite with "git notes copy"' ' + test_must_fail git notes copy HEAD~2 HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" +' + +cat > expect << EOF +commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:23:13 2005 -0700 + + 11th + +Notes (other): + yet another note +$whitespace + yet another note +EOF + +test_expect_success 'allow overwrite with "git notes copy -f"' ' + git notes copy -f HEAD~2 HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD~2)" +' + +test_expect_success 'cannot copy note from object without notes' ' + : > a12 && + git add a12 && + test_tick && + git commit -m 12th && + : > a13 && + git add a13 && + test_tick && + git commit -m 13th && + test_must_fail git notes copy HEAD^ HEAD +' + +cat > expect << EOF +commit e5d4fb5698d564ab8c73551538ecaf2b0c666185 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:25:13 2005 -0700 + + 13th + +Notes (other): + yet another note +$whitespace + yet another note + +commit 7038787dfe22a14c3867ce816dbba39845359719 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:24:13 2005 -0700 + + 12th + +Notes (other): + other note +$whitespace + yet another note +EOF + +test_expect_success 'git notes copy --stdin' ' + (echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \ + echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) | + git notes copy --stdin && + git log -2 > output && + test_cmp expect output && + test "$(git notes list HEAD)" = "$(git notes list HEAD~2)" && + test "$(git notes list HEAD^)" = "$(git notes list HEAD~3)" +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +commit be28d8b4d9951ad940d229ee3b0b9ee3b1ec273d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:26:13 2005 -0700 + + 14th +EOF + +test_expect_success 'git notes copy --for-rewrite (unconfigured)' ' + test_commit 14th && + test_commit 15th && + (echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \ + echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) | + git notes copy --for-rewrite=foo && + git log -2 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + yet another note +$whitespace + yet another note + +commit be28d8b4d9951ad940d229ee3b0b9ee3b1ec273d +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:26:13 2005 -0700 + + 14th + +Notes (other): + other note +$whitespace + yet another note +EOF + +test_expect_success 'git notes copy --for-rewrite (enabled)' ' + git config notes.rewriteMode overwrite && + git config notes.rewriteRef "refs/notes/*" && + (echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \ + echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) | + git notes copy --for-rewrite=foo && + git log -2 > output && + test_cmp expect output +' + +test_expect_success 'git notes copy --for-rewrite (disabled)' ' + git config notes.rewrite.bar false && + echo $(git rev-parse HEAD~3) $(git rev-parse HEAD) | + git notes copy --for-rewrite=bar && + git log -2 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + a fresh note +EOF + +test_expect_success 'git notes copy --for-rewrite (overwrite)' ' + git notes add -f -m"a fresh note" HEAD^ && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +test_expect_success 'git notes copy --for-rewrite (ignore)' ' + git config notes.rewriteMode ignore && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + a fresh note + another fresh note +EOF + +test_expect_success 'git notes copy --for-rewrite (append)' ' + git notes add -f -m"another fresh note" HEAD^ && + git config notes.rewriteMode concatenate && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + a fresh note + another fresh note + append 1 + append 2 +EOF + +test_expect_success 'git notes copy --for-rewrite (append two to one)' ' + git notes add -f -m"append 1" HEAD^ && + git notes add -f -m"append 2" HEAD^^ && + (echo $(git rev-parse HEAD^) $(git rev-parse HEAD); + echo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) | + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +test_expect_success 'git notes copy --for-rewrite (append empty)' ' + git notes remove HEAD^ && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + replacement note 1 +EOF + +test_expect_success 'GIT_NOTES_REWRITE_MODE works' ' + git notes add -f -m"replacement note 1" HEAD^ && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + GIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +cat > expect << EOF +commit 37a0d4cba38afef96ba54a3ea567e6dac575700b +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:27:13 2005 -0700 + + 15th + +Notes (other): + replacement note 2 +EOF + +test_expect_success 'GIT_NOTES_REWRITE_REF works' ' + git config notes.rewriteMode overwrite && + git notes add -f -m"replacement note 2" HEAD^ && + git config --unset-all notes.rewriteRef && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + GIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \ + git notes copy --for-rewrite=foo && + git log -1 > output && + test_cmp expect output +' + +test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' ' + git config notes.rewriteRef refs/notes/other && + git notes add -f -m"replacement note 3" HEAD^ && + echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | + GIT_NOTES_REWRITE_REF= git notes copy --for-rewrite=foo && + 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 new file mode 100755 index 0000000000..361a10aeb1 --- /dev/null +++ b/t/t3302-notes-index-expensive.sh @@ -0,0 +1,118 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test commit notes index (expensive!)' + +. ./test-lib.sh + +test -z "$GIT_NOTES_TIMING_TESTS" && { + skip_all="Skipping timing tests" + test_done + exit +} + +create_repo () { + number_of_commits=$1 + nr=0 + test -d .git || { + git init && + ( + while [ $nr -lt $number_of_commits ]; do + nr=$(($nr+1)) + mark=$(($nr+$nr)) + notemark=$(($mark+1)) + test_tick && + cat <<INPUT_END && +commit refs/heads/master +mark :$mark +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit #$nr +COMMIT + +M 644 inline file +data <<EOF +file in commit #$nr +EOF + +blob +mark :$notemark +data <<EOF +note for commit #$nr +EOF + +INPUT_END + + echo "N :$notemark :$mark" >> note_commit + done && + test_tick && + cat <<INPUT_END && +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes +COMMIT + +INPUT_END + + cat note_commit + ) | + git fast-import --quiet && + git config core.notesRef refs/notes/commits + } +} + +test_notes () { + count=$1 && + git config core.notesRef refs/notes/commits && + git log | grep "^ " > output && + i=$count && + while [ $i -gt 0 ]; do + echo " commit #$i" && + echo " note for commit #$i" && + i=$(($i-1)); + done > expect && + test_cmp expect output +} + +cat > time_notes << \EOF + mode=$1 + i=1 + while [ $i -lt $2 ]; do + case $1 in + no-notes) + GIT_NOTES_REF=non-existing; export GIT_NOTES_REF + ;; + notes) + unset GIT_NOTES_REF + ;; + esac + git log >/dev/null + i=$(($i+1)) + done +EOF + +time_notes () { + for mode in no-notes notes + do + echo $mode + /usr/bin/time sh ../time_notes $mode $1 + done +} + +for count in 10 100 1000 10000; do + + mkdir $count + (cd $count; + + test_expect_success "setup $count" "create_repo $count" + + test_expect_success 'notes work' "test_notes $count" + + test_expect_success 'notes timing' "time_notes 100" + ) +done + +test_done diff --git a/t/t3303-notes-subtrees.sh b/t/t3303-notes-subtrees.sh new file mode 100755 index 0000000000..75ec18778e --- /dev/null +++ b/t/t3303-notes-subtrees.sh @@ -0,0 +1,194 @@ +#!/bin/sh + +test_description='Test commit notes organized in subtrees' + +. ./test-lib.sh + +number_of_commits=100 + +start_note_commit () { + test_tick && + cat <<INPUT_END +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes +COMMIT + +from refs/notes/commits^0 +deleteall +INPUT_END + +} + +verify_notes () { + git log | grep "^ " > output && + i=$number_of_commits && + while [ $i -gt 0 ]; do + echo " commit #$i" && + echo " note for commit #$i" && + i=$(($i-1)); + done > expect && + test_cmp expect output +} + +test_expect_success "setup: create $number_of_commits commits" ' + + ( + nr=0 && + while [ $nr -lt $number_of_commits ]; do + nr=$(($nr+1)) && + test_tick && + cat <<INPUT_END +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit #$nr +COMMIT + +M 644 inline file +data <<EOF +file in commit #$nr +EOF + +INPUT_END + + done && + test_tick && + cat <<INPUT_END +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +no notes +COMMIT + +deleteall + +INPUT_END + + ) | + git fast-import --quiet && + git config core.notesRef refs/notes/commits +' + +test_sha1_based () { + ( + start_note_commit && + nr=$number_of_commits && + git rev-list refs/heads/master | + while read sha1; do + note_path=$(echo "$sha1" | sed "$1") + cat <<INPUT_END && +M 100644 inline $note_path +data <<EOF +note for commit #$nr +EOF + +INPUT_END + + nr=$(($nr-1)) + done + ) | + git fast-import --quiet +} + +test_expect_success 'test notes in 2/38-fanout' 'test_sha1_based "s|^..|&/|"' +test_expect_success 'verify notes in 2/38-fanout' 'verify_notes' + +test_expect_success 'test notes in 2/2/36-fanout' 'test_sha1_based "s|^\(..\)\(..\)|\1/\2/|"' +test_expect_success 'verify notes in 2/2/36-fanout' 'verify_notes' + +test_expect_success 'test notes in 2/2/2/34-fanout' 'test_sha1_based "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|"' +test_expect_success 'verify notes in 2/2/2/34-fanout' 'verify_notes' + +test_same_notes () { + ( + start_note_commit && + nr=$number_of_commits && + git rev-list refs/heads/master | + while read sha1; do + first_note_path=$(echo "$sha1" | sed "$1") + second_note_path=$(echo "$sha1" | sed "$2") + cat <<INPUT_END && +M 100644 inline $second_note_path +data <<EOF +note for commit #$nr +EOF + +M 100644 inline $first_note_path +data <<EOF +note for commit #$nr +EOF + +INPUT_END + + nr=$(($nr-1)) + done + ) | + git fast-import --quiet +} + +test_expect_success 'test same notes in no fanout and 2/38-fanout' 'test_same_notes "s|^..|&/|" ""' +test_expect_success 'verify same notes in no fanout and 2/38-fanout' 'verify_notes' + +test_expect_success 'test same notes in no fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" ""' +test_expect_success 'verify same notes in no fanout and 2/2/36-fanout' 'verify_notes' + +test_expect_success 'test same notes in 2/38-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"' +test_expect_success 'verify same notes in 2/38-fanout and 2/2/36-fanout' 'verify_notes' + +test_expect_success 'test same notes in 2/2/2/34-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|"' +test_expect_success 'verify same notes in 2/2/2/34-fanout and 2/2/36-fanout' 'verify_notes' + +test_concatenated_notes () { + ( + start_note_commit && + nr=$number_of_commits && + git rev-list refs/heads/master | + while read sha1; do + first_note_path=$(echo "$sha1" | sed "$1") + second_note_path=$(echo "$sha1" | sed "$2") + cat <<INPUT_END && +M 100644 inline $second_note_path +data <<EOF +second note for commit #$nr +EOF + +M 100644 inline $first_note_path +data <<EOF +first note for commit #$nr +EOF + +INPUT_END + + nr=$(($nr-1)) + done + ) | + git fast-import --quiet +} + +verify_concatenated_notes () { + git log | grep "^ " > output && + i=$number_of_commits && + while [ $i -gt 0 ]; do + echo " commit #$i" && + echo " first note for commit #$i" && + echo " second note for commit #$i" && + i=$(($i-1)); + done > expect && + test_cmp expect output +} + +test_expect_success 'test notes in no fanout concatenated with 2/38-fanout' 'test_concatenated_notes "s|^..|&/|" ""' +test_expect_success 'verify notes in no fanout concatenated with 2/38-fanout' 'verify_concatenated_notes' + +test_expect_success 'test notes in no fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" ""' +test_expect_success 'verify notes in no fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes' + +test_expect_success 'test notes in 2/38-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"' +test_expect_success 'verify notes in 2/38-fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes' + +test_expect_success 'test notes in 2/2/36-fanout concatenated with 2/2/2/34-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|" "s|^\(..\)\(..\)|\1/\2/|"' +test_expect_success 'verify notes in 2/2/36-fanout concatenated with 2/2/2/34-fanout' 'verify_concatenated_notes' + +test_done diff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh new file mode 100755 index 0000000000..1709e8c00b --- /dev/null +++ b/t/t3304-notes-mixed.sh @@ -0,0 +1,206 @@ +#!/bin/sh + +test_description='Test notes trees that also contain non-notes' + +. ./test-lib.sh + +number_of_commits=100 + +start_note_commit () { + test_tick && + cat <<INPUT_END +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes +COMMIT + +from refs/notes/commits^0 +deleteall +INPUT_END + +} + +verify_notes () { + git log | grep "^ " > output && + i=$number_of_commits && + while [ $i -gt 0 ]; do + echo " commit #$i" && + echo " note for commit #$i" && + i=$(($i-1)); + done > expect && + test_cmp expect output +} + +test_expect_success "setup: create a couple of commits" ' + + test_tick && + cat <<INPUT_END >input && +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit #1 +COMMIT + +M 644 inline file +data <<EOF +file in commit #1 +EOF + +INPUT_END + + test_tick && + cat <<INPUT_END >>input && +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit #2 +COMMIT + +M 644 inline file +data <<EOF +file in commit #2 +EOF + +INPUT_END + git fast-import --quiet <input +' + +test_expect_success "create a notes tree with both notes and non-notes" ' + + commit1=$(git rev-parse refs/heads/master^) && + commit2=$(git rev-parse refs/heads/master) && + test_tick && + cat <<INPUT_END >input && +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes commit #1 +COMMIT + +N inline $commit1 +data <<EOF +note for commit #1 +EOF + +N inline $commit2 +data <<EOF +note for commit #2 +EOF + +INPUT_END + test_tick && + cat <<INPUT_END >>input && +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes commit #2 +COMMIT + +M 644 inline foobar/non-note.txt +data <<EOF +A non-note in a notes tree +EOF + +N inline $commit2 +data <<EOF +edited note for commit #2 +EOF + +INPUT_END + test_tick && + cat <<INPUT_END >>input && +commit refs/notes/commits +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes commit #3 +COMMIT + +N inline $commit1 +data <<EOF +edited note for commit #1 +EOF + +M 644 inline deadbeef +data <<EOF +non-note with SHA1-like name +EOF + +M 644 inline de/adbeef +data <<EOF +another non-note with SHA1-like name +EOF + +M 644 inline de/adbeefdeadbeefdeadbeefdeadbeefdeadbeef +data <<EOF +This is actually a valid note, albeit to a non-existing object. +It is needed in order to trigger the "mishandling" of the dead/beef non-note. +EOF + +M 644 inline dead/beef +data <<EOF +yet another non-note with SHA1-like name +EOF + +INPUT_END + git fast-import --quiet <input && + git config core.notesRef refs/notes/commits +' + +cat >expect <<EXPECT_END + commit #2 + edited note for commit #2 + commit #1 + edited note for commit #1 +EXPECT_END + +test_expect_success "verify contents of notes" ' + + git log | grep "^ " > actual && + test_cmp expect actual +' + +cat >expect_nn1 <<EXPECT_END +A non-note in a notes tree +EXPECT_END +cat >expect_nn2 <<EXPECT_END +non-note with SHA1-like name +EXPECT_END +cat >expect_nn3 <<EXPECT_END +another non-note with SHA1-like name +EXPECT_END +cat >expect_nn4 <<EXPECT_END +yet another non-note with SHA1-like name +EXPECT_END + +test_expect_success "verify contents of non-notes" ' + + git cat-file -p refs/notes/commits:foobar/non-note.txt > actual_nn1 && + test_cmp expect_nn1 actual_nn1 && + git cat-file -p refs/notes/commits:deadbeef > actual_nn2 && + test_cmp expect_nn2 actual_nn2 && + git cat-file -p refs/notes/commits:de/adbeef > actual_nn3 && + test_cmp expect_nn3 actual_nn3 && + git cat-file -p refs/notes/commits:dead/beef > actual_nn4 && + test_cmp expect_nn4 actual_nn4 +' + +test_expect_success "git-notes preserves non-notes" ' + + test_tick && + git notes add -f -m "foo bar" +' + +test_expect_success "verify contents of non-notes after git-notes" ' + + git cat-file -p refs/notes/commits:foobar/non-note.txt > actual_nn1 && + test_cmp expect_nn1 actual_nn1 && + git cat-file -p refs/notes/commits:deadbeef > actual_nn2 && + test_cmp expect_nn2 actual_nn2 && + git cat-file -p refs/notes/commits:de/adbeef > actual_nn3 && + test_cmp expect_nn3 actual_nn3 && + git cat-file -p refs/notes/commits:dead/beef > actual_nn4 && + test_cmp expect_nn4 actual_nn4 +' + +test_done diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh new file mode 100755 index 0000000000..b1ea64b213 --- /dev/null +++ b/t/t3305-notes-fanout.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +test_description='Test that adding/removing many notes triggers automatic fanout restructuring' + +. ./test-lib.sh + +test_expect_success 'creating many notes with git-notes' ' + num_notes=300 && + i=0 && + while test $i -lt $num_notes + do + i=$(($i + 1)) && + test_tick && + echo "file for commit #$i" > file && + git add file && + git commit -q -m "commit #$i" && + git notes add -m "note #$i" || return 1 + done +' + +test_expect_success 'many notes created correctly with git-notes' ' + git log | grep "^ " > output && + i=300 && + while test $i -gt 0 + do + echo " commit #$i" && + echo " note #$i" && + i=$(($i - 1)); + done > expect && + test_cmp expect output +' + +test_expect_success 'many notes created with git-notes triggers fanout' ' + # Expect entire notes tree to have a fanout == 1 + git ls-tree -r --name-only refs/notes/commits | + while read path + do + case "$path" in + ??/??????????????????????????????????????) + : true + ;; + *) + echo "Invalid path \"$path\"" && + return 1 + ;; + esac + done +' + +test_expect_success 'deleting most notes with git-notes' ' + num_notes=250 && + i=0 && + git rev-list HEAD | + while read sha1 + do + i=$(($i + 1)) && + if test $i -gt $num_notes + then + break + fi && + test_tick && + git notes remove "$sha1" + done +' + +test_expect_success 'most notes deleted correctly with git-notes' ' + git log HEAD~250 | grep "^ " > output && + i=50 && + while test $i -gt 0 + do + echo " commit #$i" && + echo " note #$i" && + i=$(($i - 1)); + done > expect && + test_cmp expect output +' + +test_expect_success 'deleting most notes triggers fanout consolidation' ' + # Expect entire notes tree to have a fanout == 0 + git ls-tree -r --name-only refs/notes/commits | + while read path + do + case "$path" in + ????????????????????????????????????????) + : true + ;; + *) + echo "Invalid path \"$path\"" && + return 1 + ;; + esac + done +' + +test_done diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh new file mode 100755 index 0000000000..b4554041b4 --- /dev/null +++ b/t/t3306-notes-prune.sh @@ -0,0 +1,138 @@ +#!/bin/sh + +test_description='Test git notes prune' + +. ./test-lib.sh + +test_expect_success 'setup: create a few commits with notes' ' + + : > file1 && + git add file1 && + test_tick && + git commit -m 1st && + git notes add -m "Note #1" && + : > file2 && + git add file2 && + test_tick && + git commit -m 2nd && + git notes add -m "Note #2" && + : > file3 && + git add file3 && + test_tick && + git commit -m 3rd && + git notes add -m "Note #3" +' + +cat > expect <<END_OF_LOG +commit 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3rd + +Notes: + Note #3 + +commit 08341ad9e94faa089d60fd3f523affb25c6da189 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:14:13 2005 -0700 + + 2nd + +Notes: + Note #2 + +commit ab5f302035f2e7aaf04265f08b42034c23256e1f +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:13:13 2005 -0700 + + 1st + +Notes: + Note #1 +END_OF_LOG + +test_expect_success 'verify commits and notes' ' + + git log > actual && + test_cmp expect actual +' + +test_expect_success 'remove some commits' ' + + 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 && + git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f +' + +test_expect_success 'verify that notes are still present' ' + + git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && + 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 +' + +test_expect_success 'verify that notes are gone' ' + + ! 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' ' + + ! git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + ! git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && + git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f +' + +test_done 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 b9d3131cc2..d98c7b5571 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -3,32 +3,185 @@ # Copyright (c) 2005 Amos Waterland # -test_description='git rebase should not destroy author information +test_description='git rebase assorted tests -This test runs git rebase and checks that the author information is not lost. +This test runs git rebase and checks that the author information is not lost +among other things. ' . ./test-lib.sh -export GIT_AUTHOR_EMAIL=bogus_email_address +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 branch, then rebase against master' \ - 'echo First > A && - git-update-index --add A && - git-commit -m "Add A." && + '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 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 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' + +test_expect_success 'rebase on dirty cache' ' + git add A && + test_must_fail git rebase master' + +test_expect_success 'rebase against master' ' + git reset --hard HEAD && git rebase master' -test_expect_failure \ +test_expect_success 'rebase against master twice' ' + 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 +' + +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 +' + +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 +' + +test_expect_success \ 'the rebase operation should not have destroyed author information' \ - 'git log | grep "Author:" | grep "<>"' + '! (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_expect_success 'rebase after merge master' ' + 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) +' + +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 +' + +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 +' +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' ' + 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' ' + ( + echo "One" + echo "TwoQ" + echo "Three" + echo "FQur" + echo "Five" + ) | q_to_cr >CR && + git add CR && + test_tick && + git commit -a -m "A file with a line with CR" && + git tag file-with-cr && + git checkout HEAD^0 && + git rebase --onto HEAD^^ HEAD^ && + git diff --exit-code file-with-cr:CR HEAD:CR +' + +test_expect_success 'rebase can copy notes' ' + git config notes.rewrite.rebase true && + git config notes.rewriteRef "refs/notes/*" && + test_commit n1 && + test_commit n2 && + test_commit n3 && + git notes add -m"a note" n3 && + git rebase --onto n1 n2 && + test "a note" = "$(git notes show HEAD)" +' + +test_expect_success 'rebase -m can copy notes' ' + git reset --hard n3 && + git rebase -m --onto n1 n2 && + test "a note" = "$(git notes show HEAD)" +' test_done diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh index 8b19d3ccea..aea6685984 100755 --- a/t/t3401-rebase-partial.sh +++ b/t/t3401-rebase-partial.sh @@ -14,48 +14,48 @@ local branch. test_expect_success \ 'prepare repository with topic branch' \ 'echo First > A && - git-update-index --add A && - git-commit -m "Add A." && + git update-index --add A && + git commit -m "Add A." && - git-checkout -b my-topic-branch && + git checkout -b my-topic-branch && echo Second > B && - git-update-index --add B && - git-commit -m "Add B." && + git update-index --add B && + git commit -m "Add B." && echo AnotherSecond > C && - git-update-index --add C && - git-commit -m "Add C." && + git update-index --add C && + git commit -m "Add C." && - git-checkout -f master && + git checkout -f master && echo Third >> A && - git-update-index A && - git-commit -m "Modify A." + git update-index A && + git commit -m "Modify A." ' test_expect_success \ 'pick top patch from topic branch into master' \ - 'git-cherry-pick my-topic-branch^0 && - git-checkout -f my-topic-branch && - git-branch master-merge master && - git-branch my-topic-branch-merge my-topic-branch + 'git cherry-pick my-topic-branch^0 && + git checkout -f my-topic-branch && + git branch master-merge master && + git branch my-topic-branch-merge my-topic-branch ' test_debug \ - 'git-cherry master && - git-format-patch -k --stdout --full-index master >/dev/null && + 'git cherry master && + git format-patch -k --stdout --full-index master >/dev/null && gitk --all & sleep 1 ' test_expect_success \ - 'rebase topic branch against new master and check git-am did not get halted' \ - 'git-rebase master && test ! -d .dotest' + 'rebase topic branch against new master and check git am did not get halted' \ + 'git rebase master && test ! -d .git/rebase-apply' test_expect_success \ 'rebase --merge topic branch that was partially merged upstream' \ - 'git-checkout -f my-topic-branch-merge && - git-rebase --merge master-merge && - test ! -d .git/.dotest-merge' + 'git checkout -f my-topic-branch-merge && + git rebase --merge master-merge && + test ! -d .git/rebase-merge' test_done diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index 0779aaa9ab..7b7d07269a 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -48,9 +48,14 @@ test_expect_success 'reference merge' ' git merge -s recursive "reference merge" HEAD master ' +PRE_REBASE=$(git rev-parse test-rebase) test_expect_success rebase ' git checkout test-rebase && - git rebase --merge master + GIT_TRACE=1 git rebase --merge master +' + +test_expect_success 'test-rebase@{1} is pre rebase' ' + test $PRE_REBASE = $(git rev-parse test-rebase@{1}) ' test_expect_success 'merge and rebase should match' ' diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 977c498f00..64446e3db3 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -7,7 +7,7 @@ test_description='git rebase --merge --skip tests' . ./test-lib.sh -# we assume the default git-am -3 --skip strategy is tested independently +# we assume the default git am -3 --skip strategy is tested independently # and always works :) test_expect_success setup ' @@ -31,27 +31,43 @@ test_expect_success setup ' git branch skip-merge skip-reference ' -test_expect_failure 'rebase with git am -3 (default)' ' - git rebase master +test_expect_success 'rebase with git am -3 (default)' ' + test_must_fail git rebase master ' test_expect_success 'rebase --skip with am -3' ' - git reset --hard HEAD && git rebase --skip ' + +test_expect_success 'rebase moves back to skip-reference' ' + test refs/heads/skip-reference = $(git symbolic-ref HEAD) && + git branch post-rebase && + git reset --hard pre-rebase && + test_must_fail git rebase master && + echo "hello" > hello && + git add hello && + git rebase --continue && + test refs/heads/skip-reference = $(git symbolic-ref HEAD) && + git reset --hard post-rebase +' + test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge' -test_expect_failure 'rebase with --merge' 'git rebase --merge master' +test_expect_success 'rebase with --merge' ' + test_must_fail git rebase --merge master +' test_expect_success 'rebase --skip with --merge' ' - git reset --hard HEAD && git rebase --skip ' test_expect_success 'merge and reference trees equal' \ - 'test -z "`git-diff-tree skip-merge skip-reference`"' + 'test -z "`git diff-tree skip-merge skip-reference`"' + +test_expect_success 'moved back to branch correctly' ' + test refs/heads/skip-merge = $(git symbolic-ref HEAD) +' test_debug 'gitk --all & sleep 1' test_done - diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh new file mode 100755 index 0000000000..9f03ce699e --- /dev/null +++ b/t/t3404-rebase-interactive.sh @@ -0,0 +1,657 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='git rebase interactive + +This test runs git rebase "interactively", by faking an edit, and verifies +that the result still makes sense. +' +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +# Set up the repository like this: +# +# one - two - three - four (conflict-branch) +# / +# A - B - C - D - E (master) +# | \ +# | F - G - H (branch1) +# | \ +# |\ I (branch2) +# | \ +# | J - K - L - M (no-conflict-branch) +# \ +# N - O - P (no-ff-branch) +# +# where A, B, D and G all touch file1, and one, two, three, four all +# touch file "conflict". +# +# WARNING: Modifications to the initial repository can change the SHA ID used +# in the expect2 file for the 'stop on conflicting pick' test. + + +test_expect_success 'setup' ' + test_commit A file1 && + test_commit B file1 && + test_commit C file2 && + test_commit D file1 && + test_commit E file3 && + git checkout -b branch1 A && + test_commit F file4 && + test_commit G file1 && + test_commit H file5 && + git checkout -b branch2 F && + test_commit I file6 + git checkout -b conflict-branch A && + for n in one two three four + do + test_commit $n conflict + done && + git checkout -b no-conflict-branch A && + for n in J K L M + do + test_commit $n file$n + done && + git checkout -b no-ff-branch A && + for n in N O P + do + test_commit $n file$n + done +' + +test_expect_success 'no changes are a nop' ' + git checkout branch2 && + git rebase -i F && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && + test $(git rev-parse I) = $(git rev-parse HEAD) +' + +test_expect_success 'test the [branch] option' ' + git checkout -b dead-end && + git rm file6 && + git commit -m "stop here" && + git rebase -i F branch2 && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && + test $(git rev-parse I) = $(git rev-parse branch2) && + test $(git rev-parse I) = $(git rev-parse HEAD) +' + +test_expect_success 'test --onto <branch>' ' + git checkout -b test-onto branch2 && + git rebase -i --onto branch1 F && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && + test $(git rev-parse HEAD^) = $(git rev-parse branch1) && + test $(git rev-parse I) = $(git rev-parse branch2) +' + +test_expect_success 'rebase on top of a non-conflicting commit' ' + git checkout branch1 && + git tag original-branch1 && + git rebase -i branch2 && + test file6 = $(git diff --name-only original-branch1) && + test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && + test $(git rev-parse I) = $(git rev-parse branch2) && + test $(git rev-parse I) = $(git rev-parse HEAD~2) +' + +test_expect_success 'reflog for the branch shows state before rebase' ' + test $(git rev-parse branch1@{1}) = $(git rev-parse original-branch1) +' + +test_expect_success 'exchange two commits' ' + FAKE_LINES="2 1" git rebase -i HEAD~2 && + test H = $(git cat-file commit HEAD^ | sed -ne \$p) && + test G = $(git cat-file commit HEAD | sed -ne \$p) +' + +cat > expect << EOF +diff --git a/file1 b/file1 +index f70f10e..fd79235 100644 +--- a/file1 ++++ b/file1 +@@ -1 +1 @@ +-A ++G +EOF + +cat > expect2 << EOF +<<<<<<< HEAD +D +======= +G +>>>>>>> 5d18e54... G +EOF + +test_expect_success 'stop on conflicting pick' ' + git tag new-branch1 && + test_must_fail git rebase -i master && + test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" && + test_cmp expect .git/rebase-merge/patch && + test_cmp expect2 file1 && + test "$(git diff --name-status | + sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 && + test 4 = $(grep -v "^#" < .git/rebase-merge/done | wc -l) && + test 0 = $(grep -c "^[^#]" < .git/rebase-merge/git-rebase-todo) +' + +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_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 "Untracked working tree file .file1. would be overwritten" \ + output && + ! test -d .git/rebase-merge && + git reset --hard HEAD^ +' + +test_expect_success 'retain authorship' ' + echo A > file7 && + git add file7 && + test_tick && + GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && + git tag twerp && + git rebase -i --onto master HEAD^ && + git show HEAD | grep "^Author: Twerp Snog" +' + +test_expect_success 'squash' ' + git reset --hard twerp && + echo B > file7 && + test_tick && + GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 && + echo "******************************" && + FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \ + git rebase -i --onto master HEAD~2 && + test B = $(cat file7) && + test $(git rev-parse HEAD^) = $(git rev-parse master) +' + +test_expect_success 'retain authorship when squashing' ' + git show HEAD | grep "^Author: Twerp Snog" +' + +test_expect_success '-p handles "no changes" gracefully' ' + HEAD=$(git rev-parse HEAD) && + git rebase -i -p HEAD^ && + git update-index --refresh && + git diff-files --quiet && + git diff-index --quiet --cached HEAD -- && + 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 && + git add unrelated-file && + test_tick && + git commit -m "unrelated" && + git checkout -b another-branch master && + echo B > file1 && + test_tick && + git commit -m J file1 && + test_tick && + git merge to-be-preserved && + echo C > file1 && + test_tick && + git commit -m K file1 && + echo D > file1 && + test_tick && + git commit -m L1 file1 && + git checkout HEAD^ && + echo 1 > unrelated-file && + test_tick && + git commit -m L2 unrelated-file && + test_tick && + git merge another-branch && + echo E > file1 && + test_tick && + git commit -m M file1 && + git checkout -b to-be-rebased && + test_tick && + git rebase -i -p --onto branch1 master && + git update-index --refresh && + git diff-files --quiet && + git diff-index --quiet --cached HEAD -- && + test $(git rev-parse HEAD~6) = $(git rev-parse branch1) && + test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) && + test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) && + test $(git show HEAD~5:file1) = B && + test $(git show HEAD~3:file1) = C && + test $(git show HEAD:file1) = E && + test $(git show HEAD:unrelated-file) = 1 +' + +test_expect_success 'edit ancestor with -p' ' + FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 && + echo 2 > unrelated-file && + test_tick && + git commit -m L2-modified --amend unrelated-file && + git rebase --continue && + git update-index --refresh && + git diff-files --quiet && + git diff-index --quiet --cached HEAD -- && + test $(git show HEAD:unrelated-file) = 2 +' + +test_expect_success '--continue tries to commit' ' + test_tick && + test_must_fail git rebase -i --onto new-branch1 HEAD^ && + echo resolved > file1 && + git add file1 && + FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue && + test $(git rev-parse HEAD^) = $(git rev-parse new-branch1) && + git show HEAD | grep chouette +' + +test_expect_success 'verbose flag is heeded, even after --continue' ' + git reset --hard HEAD@{1} && + test_tick && + test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && + echo resolved > file1 && + git add file1 && + git rebase --continue > output && + grep "^ file1 | 2 +-$" output +' + +test_expect_success 'multi-squash only fires up editor once' ' + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base && + test $base = $(git rev-parse HEAD^) && + test 1 = $(git show | grep ONCE | wc -l) +' + +test_expect_success 'multi-fixup does not fire up editor' ' + git checkout -b multi-fixup E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="NEVER" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ + git rebase -i $base && + test $base = $(git rev-parse HEAD^) && + test 0 = $(git show | grep NEVER | wc -l) && + git checkout to-be-rebased && + git branch -D multi-fixup +' + +test_expect_success 'commit message used after conflict' ' + git checkout -b conflict-fixup conflict-branch && + base=$(git rev-parse HEAD~4) && + ( + FAKE_LINES="1 fixup 3 fixup 4" && + export FAKE_LINES && + test_must_fail git rebase -i $base + ) && + echo three > conflict && + git add conflict && + FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \ + git rebase --continue && + test $base = $(git rev-parse HEAD^) && + test 1 = $(git show | grep ONCE | wc -l) && + git checkout to-be-rebased && + git branch -D conflict-fixup +' + +test_expect_success 'commit message retained after conflict' ' + git checkout -b conflict-squash conflict-branch && + base=$(git rev-parse HEAD~4) && + ( + FAKE_LINES="1 fixup 3 squash 4" && + export FAKE_LINES && + test_must_fail git rebase -i $base + ) && + echo three > conflict && + git add conflict && + FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \ + git rebase --continue && + test $base = $(git rev-parse HEAD^) && + test 2 = $(git show | grep TWICE | wc -l) && + git checkout to-be-rebased && + git branch -D conflict-squash +' + +cat > expect-squash-fixup << EOF +B + +D + +ONCE +EOF + +test_expect_success 'squash and fixup generate correct log messages' ' + git checkout -b squash-fixup E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base && + git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && + test_cmp expect-squash-fixup actual-squash-fixup && + git checkout to-be-rebased && + git branch -D squash-fixup +' + +test_expect_success 'squash ignores comments' ' + git checkout -b skip-comments E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base && + test $base = $(git rev-parse HEAD^) && + test 1 = $(git show | grep ONCE | wc -l) && + git checkout to-be-rebased && + git branch -D skip-comments +' + +test_expect_success 'squash ignores blank lines' ' + git checkout -b skip-blank-lines E && + base=$(git rev-parse HEAD~4) && + FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base && + test $base = $(git rev-parse HEAD^) && + test 1 = $(git show | grep ONCE | wc -l) && + git checkout to-be-rebased && + git branch -D skip-blank-lines +' + +test_expect_success 'squash works as expected' ' + git checkout -b squash-works no-conflict-branch && + one=$(git rev-parse HEAD~3) && + FAKE_LINES="1 squash 3 2" EXPECT_HEADER_COUNT=2 \ + git rebase -i HEAD~3 && + test $one = $(git rev-parse HEAD~2) +' + +test_expect_success 'interrupted squash works as expected' ' + git checkout -b interrupted-squash conflict-branch && + one=$(git rev-parse HEAD~3) && + ( + FAKE_LINES="1 squash 3 2" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD~3 + ) && + (echo one; echo two; echo four) > conflict && + git add conflict && + test_must_fail git rebase --continue && + echo resolved > conflict && + git add conflict && + git rebase --continue && + test $one = $(git rev-parse HEAD~2) +' + +test_expect_success 'interrupted squash works as expected (case 2)' ' + git checkout -b interrupted-squash2 conflict-branch && + one=$(git rev-parse HEAD~3) && + ( + FAKE_LINES="3 squash 1 2" && + export FAKE_LINES && + test_must_fail git rebase -i HEAD~3 + ) && + (echo one; echo four) > conflict && + git add conflict && + test_must_fail git rebase --continue && + (echo one; echo two; echo four) > conflict && + git add conflict && + test_must_fail git rebase --continue && + echo resolved > conflict && + git add conflict && + git rebase --continue && + test $one = $(git rev-parse HEAD~2) +' + +test_expect_success 'ignore patch if in upstream' ' + HEAD=$(git rev-parse HEAD) && + git checkout -b has-cherry-picked HEAD^ && + echo unrelated > file7 && + git add file7 && + test_tick && + git commit -m "unrelated change" && + git cherry-pick $HEAD && + EXPECT_COUNT=1 git rebase -i $HEAD && + test $HEAD = $(git rev-parse HEAD^) +' + +test_expect_success '--continue tries to commit, even for "edit"' ' + parent=$(git rev-parse HEAD^) && + test_tick && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo edited > file7 && + git add file7 && + FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue && + test edited = $(git show HEAD:file7) && + git show HEAD | grep chouette && + test $parent = $(git rev-parse HEAD^) +' + +test_expect_success 'aborted --continue does not squash commits after "edit"' ' + old=$(git rev-parse HEAD) && + test_tick && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo "edited again" > file7 && + git add file7 && + ( + FAKE_COMMIT_MESSAGE=" " && + export FAKE_COMMIT_MESSAGE && + test_must_fail git rebase --continue + ) && + test $old = $(git rev-parse HEAD) && + git rebase --abort +' + +test_expect_success 'auto-amend only edited commits after "edit"' ' + test_tick && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo "edited again" > file7 && + git add file7 && + FAKE_COMMIT_MESSAGE="edited file7 again" git commit && + echo "and again" > file7 && + git add file7 && + test_tick && + ( + FAKE_COMMIT_MESSAGE="and again" && + export FAKE_COMMIT_MESSAGE && + test_must_fail git rebase --continue + ) && + git rebase --abort +' + +test_expect_success 'rebase a detached HEAD' ' + grandparent=$(git rev-parse HEAD~2) && + git checkout $(git rev-parse HEAD) && + test_tick && + FAKE_LINES="2 1" git rebase -i HEAD~2 && + test $grandparent = $(git rev-parse HEAD~2) +' + +test_expect_success 'rebase a commit violating pre-commit' ' + + mkdir -p .git/hooks && + PRE_COMMIT=.git/hooks/pre-commit && + echo "#!/bin/sh" > $PRE_COMMIT && + echo "test -z \"\$(git diff --cached --check)\"" >> $PRE_COMMIT && + chmod a+x $PRE_COMMIT && + echo "monde! " >> file1 && + test_tick && + test_must_fail git commit -m doesnt-verify file1 && + git commit -m doesnt-verify --no-verify file1 && + test_tick && + FAKE_LINES=2 git rebase -i HEAD~2 + +' + +test_expect_success 'rebase with a file named HEAD in worktree' ' + + rm -fr .git/hooks && + git reset --hard && + git checkout -b branch3 A && + + ( + GIT_AUTHOR_NAME="Squashed Away" && + export GIT_AUTHOR_NAME && + >HEAD && + git add HEAD && + git commit -m "Add head" && + >BODY && + git add BODY && + git commit -m "Add body" + ) && + + FAKE_LINES="1 squash 2" git rebase -i to-be-rebased && + test "$(git show -s --pretty=format:%an)" = "Squashed Away" + +' + +test_expect_success 'do "noop" when there is nothing to cherry-pick' ' + + git checkout -b branch4 HEAD && + GIT_EDITOR=: git commit --amend \ + --author="Somebody else <somebody@else.com>" + test $(git rev-parse branch3) != $(git rev-parse branch4) && + git rebase -i branch3 && + test $(git rev-parse branch3) = $(git rev-parse branch4) + +' + +test_expect_success 'submodule rebase setup' ' + git checkout A && + mkdir sub && + ( + cd sub && git init && >elif && + git add elif && git commit -m "submodule initial" + ) && + echo 1 >file1 && + git add file1 sub + test_tick && + git commit -m "One" && + echo 2 >file1 && + test_tick && + git commit -a -m "Two" && + ( + cd sub && echo 3 >elif && + git commit -a -m "submodule second" + ) && + test_tick && + git commit -a -m "Three changes submodule" +' + +test_expect_success 'submodule rebase -i' ' + FAKE_LINES="1 squash 2 3" git rebase -i A +' + +test_expect_success 'avoid unnecessary reset' ' + git checkout master && + test-chmtime =123456789 file3 && + git update-index --refresh && + HEAD=$(git rev-parse HEAD) && + git rebase -i HEAD~4 && + test $HEAD = $(git rev-parse HEAD) && + MTIME=$(test-chmtime -v +0 file3 | sed 's/[^0-9].*$//') && + test 123456789 = $MTIME +' + +test_expect_success 'reword' ' + git checkout -b reword-branch master && + FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" git rebase -i A && + git show HEAD | grep "E changed" && + test $(git rev-parse master) != $(git rev-parse HEAD) && + test $(git rev-parse master^) = $(git rev-parse HEAD^) && + FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" git rebase -i A && + git show HEAD^ | grep "D changed" && + FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" git rebase -i A && + git show HEAD~3 | grep "B changed" && + FAKE_LINES="1 reword 2 3 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A && + git show HEAD~2 | grep "C changed" +' + +test_expect_success 'rebase -i can copy notes' ' + git config notes.rewrite.rebase true && + git config notes.rewriteRef "refs/notes/*" && + test_commit n1 && + test_commit n2 && + test_commit n3 && + git notes add -m"a note" n3 && + git rebase --onto n1 n2 && + test "a note" = "$(git notes show HEAD)" +' + +cat >expect <<EOF +an earlier note +a note +EOF + +test_expect_success 'rebase -i can copy notes over a fixup' ' + git reset --hard n3 && + git notes add -m"an earlier note" n2 && + GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 fixup 2" git rebase -i n1 && + git notes show > output && + test_cmp expect output +' + +test_expect_success 'rebase while detaching HEAD' ' + git symbolic-ref HEAD && + grandparent=$(git rev-parse HEAD~2) && + test_tick && + FAKE_LINES="2 1" git rebase -i HEAD~2 HEAD^0 && + test $grandparent = $(git rev-parse HEAD~2) && + test_must_fail git symbolic-ref HEAD +' + +test_tick # Ensure that the rebased commits get a different timestamp. +test_expect_success 'always cherry-pick with --no-ff' ' + git checkout no-ff-branch && + git tag original-no-ff-branch && + git rebase -i --no-ff A && + touch empty && + for p in 0 1 2 + do + test ! $(git rev-parse HEAD~$p) = $(git rev-parse original-no-ff-branch~$p) && + git diff HEAD~$p original-no-ff-branch~$p > out && + test_cmp empty out + done && + test $(git rev-parse HEAD~3) = $(git rev-parse original-no-ff-branch~3) && + git diff HEAD~3 original-no-ff-branch~3 > out && + 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/t3405-rebase-malformed.sh b/t/t3405-rebase-malformed.sh new file mode 100755 index 0000000000..e5ad67c643 --- /dev/null +++ b/t/t3405-rebase-malformed.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +test_description='rebase should not insist on git message convention' + +. ./test-lib.sh + +cat >F <<\EOF +This is an example of a commit log message +that does not conform to git commit convention. + +It has two paragraphs, but its first paragraph is not friendly +to oneline summary format. +EOF + +test_expect_success setup ' + + >file1 && + >file2 && + git add file1 file2 && + test_tick && + git commit -m "Initial commit" && + + git checkout -b side && + cat F >file2 && + git add file2 && + test_tick && + git commit -F F && + + git cat-file commit HEAD | sed -e "1,/^\$/d" >F0 && + + git checkout master && + + echo One >file1 && + test_tick && + git add file1 && + git commit -m "Second commit" +' + +test_expect_success rebase ' + + git rebase master side && + git cat-file commit HEAD | sed -e "1,/^\$/d" >F1 && + + test_cmp F0 F1 && + test_cmp F F0 +' + +test_done diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh new file mode 100755 index 0000000000..85fc7c4af8 --- /dev/null +++ b/t/t3406-rebase-message.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +test_description='messages from rebase operation' + +. ./test-lib.sh + +quick_one () { + echo "$1" >"file$1" && + git add "file$1" && + test_tick && + git commit -m "$1" +} + +test_expect_success setup ' + quick_one O && + git branch topic && + quick_one X && + quick_one A && + quick_one B && + quick_one Y && + + git checkout topic && + quick_one A && + quick_one B && + quick_one Z && + git tag start + +' + +cat >expect <<\EOF +Already applied: 0001 A +Already applied: 0002 B +Committed: 0003 Z +EOF + +test_expect_success 'rebase -m' ' + + git rebase -m master >report && + sed -n -e "/^Already applied: /p" \ + -e "/^Committed: /p" report >actual && + test_cmp expect actual + +' + +test_expect_success 'rebase --stat' ' + git reset --hard start + git rebase --stat master >diffstat.txt && + grep "^ fileX | *1 +$" diffstat.txt +' + +test_expect_success 'rebase w/config rebase.stat' ' + git reset --hard start + git config rebase.stat true && + git rebase master >diffstat.txt && + grep "^ fileX | *1 +$" diffstat.txt +' + +test_expect_success 'rebase -n overrides config rebase.stat config' ' + git reset --hard start + git config rebase.stat true && + git rebase -n master >diffstat.txt && + ! grep "^ fileX | *1 +$" diffstat.txt +' + +test_done diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh new file mode 100755 index 0000000000..2999e78937 --- /dev/null +++ b/t/t3407-rebase-abort.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +test_description='git rebase --abort tests' + +. ./test-lib.sh + +### Test that we handle space characters properly +work_dir="$(pwd)/test dir" + +test_expect_success setup ' + mkdir -p "$work_dir" && + cd "$work_dir" && + git init && + echo a > a && + git add a && + git commit -m a && + git branch to-rebase && + + echo b > a && + git commit -a -m b && + echo c > a && + git commit -a -m c && + + git checkout to-rebase && + echo d > a && + git commit -a -m "merge should fail on this" && + echo e > a && + git commit -a -m "merge should fail on this, too" && + git branch pre-rebase +' + +testrebase() { + type=$1 + dotest=$2 + + test_expect_success "rebase$type --abort" ' + cd "$work_dir" && + # Clean up the state from the previous one + git reset --hard pre-rebase && + test_must_fail git rebase$type master && + test -d "$dotest" && + git rebase --abort && + test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && + test ! -d "$dotest" + ' + + test_expect_success "rebase$type --abort after --skip" ' + cd "$work_dir" && + # Clean up the state from the previous one + git reset --hard pre-rebase && + test_must_fail git rebase$type master && + test -d "$dotest" && + test_must_fail git rebase --skip && + test $(git rev-parse HEAD) = $(git rev-parse master) && + git rebase --abort && + test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && + test ! -d "$dotest" + ' + + test_expect_success "rebase$type --abort after --continue" ' + cd "$work_dir" && + # Clean up the state from the previous one + git reset --hard pre-rebase && + test_must_fail git rebase$type master && + test -d "$dotest" && + echo c > a && + echo d >> a && + git add a && + test_must_fail git rebase --continue && + test $(git rev-parse HEAD) != $(git rev-parse master) && + git rebase --abort && + test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && + test ! -d "$dotest" + ' +} + +testrebase "" .git/rebase-apply +testrebase " --merge" .git/rebase-merge + +test_done diff --git a/t/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh new file mode 100755 index 0000000000..2062b858bb --- /dev/null +++ b/t/t3408-rebase-multi-line.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='rebasing a commit with multi-line first paragraph.' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + test_tick && + git commit -m initial && + + echo hello >file && + test_tick && + git commit -a -m "A sample commit log message that has a long +summary that spills over multiple lines. + +But otherwise with a sane description." + + git branch side && + + git reset --hard HEAD^ && + >elif && + git add elif && + test_tick && + git commit -m second + +' + +test_expect_success rebase ' + + git checkout side && + git rebase master && + git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && + git cat-file commit side@{1} | sed -e "1,/^\$/d" >expect && + test_cmp expect actual + +' + +test_done diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh new file mode 100755 index 0000000000..8f785e7957 --- /dev/null +++ b/t/t3409-rebase-preserve-merges.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# +# Copyright(C) 2008 Stephen Habermann & Andreas Ericsson +# +test_description='git rebase -p should preserve merges + +Run "git rebase -p" and check that merges are properly carried along +' +. ./test-lib.sh + +GIT_AUTHOR_EMAIL=bogus_email_address +export GIT_AUTHOR_EMAIL + +# Clone 1 (trivial merge): +# +# A1--A2 <-- origin/master +# \ \ +# B1--M <-- topic +# \ +# B2 <-- origin/topic +# +# Clone 2 (conflicting merge): +# +# A1--A2--B3 <-- origin/master +# \ \ +# B1------M <-- topic +# \ +# B2 <-- origin/topic +# +# In both cases, 'topic' is rebased onto 'origin/topic'. + +test_expect_success 'setup for merge-preserving rebase' \ + 'echo First > A && + git add A && + git commit -m "Add A1" && + git checkout -b topic && + echo Second > B && + git add B && + git commit -m "Add B1" && + git checkout -f master && + echo Third >> A && + git commit -a -m "Modify A2" && + + git clone ./. clone1 && + cd clone1 && + git checkout -b topic origin/topic && + git merge origin/master && + cd .. && + + 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 .. && + + git checkout topic && + echo Fourth >> B && + git commit -a -m "Modify B2" +' + +test_expect_success 'rebase -p fakes interactive rebase' ' + ( + cd clone1 && + git fetch && + git rebase -p origin/topic && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote branch " | wc -l) + ) +' + +test_expect_success '--continue works after a conflict' ' + ( + cd clone2 && + git fetch && + test_must_fail git rebase -p origin/topic && + test 2 = $(git ls-files B | wc -l) && + echo Resolved again > B && + test_must_fail git rebase --continue && + grep "^@@@ " .git/rebase-merge/patch && + git add B && + git rebase --continue && + test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Add different" | wc -l) && + test 1 = $(git rev-list --all --pretty=oneline | grep "Merge origin" | wc -l) + ) +' + +test_done diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh new file mode 100755 index 0000000000..c49143a1a4 --- /dev/null +++ b/t/t3410-rebase-preserve-dropped-merges.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# +# Copyright (c) 2008 Stephen Haberman +# + +test_description='git rebase preserve merges + +This test runs git rebase with preserve merges and ensures commits +dropped by the --cherry-pick flag have their childrens parents +rewritten. +' +. ./test-lib.sh + +# set up two branches like this: +# +# A - B - C - D - E +# \ +# F - G - H +# \ +# I +# +# where B, D and G touch the same file. + +test_expect_success 'setup' ' + test_commit A file1 && + test_commit B file1 1 && + test_commit C file2 && + test_commit D file1 2 && + test_commit E file3 && + git checkout A && + test_commit F file4 && + test_commit G file1 3 && + test_commit H file5 && + git checkout F && + test_commit I file6 +' + +# A - B - C - D - E +# \ \ \ +# F - G - H -- L \ --> L +# \ | \ +# I -- G2 -- J -- K I -- K +# G2 = same changes as G +test_expect_success 'skip same-resolution merges with -p' ' + git checkout H && + ! git merge E && + test_commit L file1 23 && + git checkout I && + test_commit G2 file1 3 && + ! git merge E && + test_commit J file1 23 && + test_commit K file7 file7 && + git rebase -i -p L && + test $(git rev-parse HEAD^^) = $(git rev-parse L) && + test "23" = "$(cat file1)" && + test "I" = "$(cat file6)" && + test "file7" = "$(cat file7)" +' + +# A - B - C - D - E +# \ \ \ +# F - G - H -- L2 \ --> L2 +# \ | \ +# I -- G3 --- J2 -- K2 I -- G3 -- K2 +# G2 = different changes as G +test_expect_success 'keep different-resolution merges with -p' ' + git checkout H && + ! git merge E && + test_commit L2 file1 23 && + git checkout I && + test_commit G3 file1 4 && + ! git merge E && + test_commit J2 file1 24 && + test_commit K2 file7 file7 && + test_must_fail git rebase -i -p L2 && + echo 234 > file1 && + git add file1 && + git rebase --continue && + test $(git rev-parse HEAD^^^) = $(git rev-parse L2) && + test "234" = "$(cat file1)" && + test "I" = "$(cat file6)" && + test "file7" = "$(cat file7)" +' + +test_done diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh new file mode 100755 index 0000000000..14a23cd872 --- /dev/null +++ b/t/t3411-rebase-preserve-around-merges.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# +# Copyright (c) 2008 Stephen Haberman +# + +test_description='git rebase preserve merges + +This test runs git rebase with -p and tries to squash a commit from after +a merge to before the merge. +' +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +# set up two branches like this: +# +# A1 - B1 - D1 - E1 - F1 +# \ / +# -- C1 -- + +test_expect_success 'setup' ' + test_commit A1 && + test_commit B1 && + test_commit C1 && + git reset --hard B1 && + test_commit D1 && + test_merge E1 C1 && + test_commit F1 +' + +# Should result in: +# +# A1 - B1 - D2 - E2 +# \ / +# -- C1 -- +# +test_expect_success 'squash F1 into D1' ' + FAKE_LINES="1 squash 3 2" git rebase -i -p B1 && + test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" && + test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" && + git tag E2 +' + +# Start with: +# +# A1 - B1 - D2 - E2 +# \ +# G1 ---- L1 ---- M1 +# \ / +# H1 -- J1 -- K1 +# \ / +# -- I1 -- +# +# And rebase G1..M1 onto E2 + +test_expect_success 'rebase two levels of merge' ' + test_commit G1 && + test_commit H1 && + test_commit I1 && + git checkout -b branch3 H1 && + test_commit J1 && + test_merge K1 I1 && + git checkout -b branch2 G1 && + test_commit L1 && + test_merge M1 K1 && + GIT_EDITOR=: git rebase -i -p E2 && + test "$(git rev-parse HEAD~3)" = "$(git rev-parse E2)" && + test "$(git rev-parse HEAD~2)" = "$(git rev-parse HEAD^2^2~2)" && + test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse HEAD^2^2^1)" +' + +test_done diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh new file mode 100755 index 0000000000..5869061c5b --- /dev/null +++ b/t/t3412-rebase-root.sh @@ -0,0 +1,280 @@ +#!/bin/sh + +test_description='git rebase --root + +Tests if git rebase --root --onto <newparent> can rebase the root commit. +' +. ./test-lib.sh + +log_with_names () { + git rev-list --topo-order --parents --pretty="tformat:%s" HEAD | + git name-rev --stdin --name-only --refs=refs/heads/$1 +} + + +test_expect_success 'prepare repository' ' + test_commit 1 A && + test_commit 2 A && + git symbolic-ref HEAD refs/heads/other && + rm .git/index && + test_commit 3 B && + test_commit 1b A 1 && + test_commit 4 B +' + +test_expect_success 'rebase --root expects --onto' ' + test_must_fail git rebase --root +' + +test_expect_success 'setup pre-rebase hook' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <<EOF && +#!$SHELL_PATH +echo "\$1,\$2" >.git/PRE-REBASE-INPUT +EOF + chmod +x .git/hooks/pre-rebase +' +cat > expect <<EOF +4 +3 +2 +1 +EOF + +test_expect_success 'rebase --root --onto <newbase>' ' + git checkout -b work && + git rebase --root --onto master && + git log --pretty=tformat:"%s" > rebased && + test_cmp expect rebased +' + +test_expect_success 'pre-rebase got correct input (1)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'rebase --root --onto <newbase> <branch>' ' + git branch work2 other && + git rebase --root --onto master work2 && + git log --pretty=tformat:"%s" > rebased2 && + test_cmp expect rebased2 +' + +test_expect_success 'pre-rebase got correct input (2)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2 +' + +test_expect_success 'rebase -i --root --onto <newbase>' ' + git checkout -b work3 other && + git rebase -i --root --onto master && + git log --pretty=tformat:"%s" > rebased3 && + test_cmp expect rebased3 +' + +test_expect_success 'pre-rebase got correct input (3)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'rebase -i --root --onto <newbase> <branch>' ' + git branch work4 other && + git rebase -i --root --onto master work4 && + git log --pretty=tformat:"%s" > rebased4 && + test_cmp expect rebased4 +' + +test_expect_success 'pre-rebase got correct input (4)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4 +' + +test_expect_success 'rebase -i -p with linear history' ' + git checkout -b work5 other && + git rebase -i -p --root --onto master && + git log --pretty=tformat:"%s" > rebased5 && + test_cmp expect rebased5 +' + +test_expect_success 'pre-rebase got correct input (5)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'set up merge history' ' + git checkout other^ && + git checkout -b side && + test_commit 5 C && + git checkout other && + git merge side +' + +cat > expect-side <<'EOF' +commit work6 work6~1 work6^2 +Merge branch 'side' into other +commit work6^2 work6~2 +5 +commit work6~1 work6~2 +4 +commit work6~2 work6~3 +3 +commit work6~3 work6~4 +2 +commit work6~4 +1 +EOF + +test_expect_success 'rebase -i -p with merge' ' + git checkout -b work6 other && + git rebase -i -p --root --onto master && + log_with_names work6 > rebased6 && + test_cmp expect-side rebased6 +' + +test_expect_success 'set up second root and merge' ' + git symbolic-ref HEAD refs/heads/third && + rm .git/index && + rm A B C && + test_commit 6 D && + git checkout other && + git merge third +' + +cat > expect-third <<'EOF' +commit work7 work7~1 work7^2 +Merge branch 'third' into other +commit work7^2 work7~4 +6 +commit work7~1 work7~2 work7~1^2 +Merge branch 'side' into other +commit work7~1^2 work7~3 +5 +commit work7~2 work7~3 +4 +commit work7~3 work7~4 +3 +commit work7~4 work7~5 +2 +commit work7~5 +1 +EOF + +test_expect_success 'rebase -i -p with two roots' ' + git checkout -b work7 other && + git rebase -i -p --root --onto master && + log_with_names work7 > rebased7 && + test_cmp expect-third rebased7 +' + +test_expect_success 'setup pre-rebase hook that fails' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <<EOF && +#!$SHELL_PATH +false +EOF + chmod +x .git/hooks/pre-rebase +' + +test_expect_success 'pre-rebase hook stops rebase' ' + git checkout -b stops1 other && + test_must_fail git rebase --root --onto master && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops1 + test 0 = $(git rev-list other...stops1 | wc -l) +' + +test_expect_success 'pre-rebase hook stops rebase -i' ' + git checkout -b stops2 other && + test_must_fail git rebase --root --onto master && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops2 + test 0 = $(git rev-list other...stops2 | wc -l) +' + +test_expect_success 'remove pre-rebase hook' ' + rm -f .git/hooks/pre-rebase +' + +test_expect_success 'set up a conflict' ' + git checkout master && + echo conflict > B && + git add B && + git commit -m conflict +' + +test_expect_success 'rebase --root with conflict (first part)' ' + git checkout -b conflict1 other && + test_must_fail git rebase --root --onto master && + git ls-files -u | grep "B$" +' + +test_expect_success 'fix the conflict' ' + echo 3 > B && + git add B +' + +cat > expect-conflict <<EOF +6 +5 +4 +3 +conflict +2 +1 +EOF + +test_expect_success 'rebase --root with conflict (second part)' ' + git rebase --continue && + git log --pretty=tformat:"%s" > conflict1 && + test_cmp expect-conflict conflict1 +' + +test_expect_success 'rebase -i --root with conflict (first part)' ' + git checkout -b conflict2 other && + test_must_fail git rebase -i --root --onto master && + git ls-files -u | grep "B$" +' + +test_expect_success 'fix the conflict' ' + echo 3 > B && + git add B +' + +test_expect_success 'rebase -i --root with conflict (second part)' ' + git rebase --continue && + git log --pretty=tformat:"%s" > conflict2 && + test_cmp expect-conflict conflict2 +' + +cat >expect-conflict-p <<\EOF +commit conflict3 conflict3~1 conflict3^2 +Merge branch 'third' into other +commit conflict3^2 conflict3~4 +6 +commit conflict3~1 conflict3~2 conflict3~1^2 +Merge branch 'side' into other +commit conflict3~1^2 conflict3~3 +5 +commit conflict3~2 conflict3~3 +4 +commit conflict3~3 conflict3~4 +3 +commit conflict3~4 conflict3~5 +conflict +commit conflict3~5 conflict3~6 +2 +commit conflict3~6 +1 +EOF + +test_expect_success 'rebase -i -p --root with conflict (first part)' ' + git checkout -b conflict3 other && + test_must_fail git rebase -i -p --root --onto master && + git ls-files -u | grep "B$" +' + +test_expect_success 'fix the conflict' ' + echo 3 > B && + git add B +' + +test_expect_success 'rebase -i -p --root with conflict (second part)' ' + git rebase --continue && + log_with_names conflict3 >out && + test_cmp expect-conflict-p out +' + +test_done diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh new file mode 100755 index 0000000000..098b75507b --- /dev/null +++ b/t/t3413-rebase-hook.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +test_description='git rebase with its hook(s)' + +. ./test-lib.sh + +test_expect_success setup ' + echo hello >file && + git add file && + test_tick && + git commit -m initial && + echo goodbye >file && + git add file && + test_tick && + git commit -m second && + git checkout -b side HEAD^ && + echo world >git && + git add git && + test_tick && + git commit -m side && + git checkout master && + git log --pretty=oneline --abbrev-commit --graph --all && + git branch test side +' + +test_expect_success 'rebase' ' + git checkout test && + git reset --hard side && + git rebase master && + test "z$(cat git)" = zworld +' + +test_expect_success 'rebase -i' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master && + test "z$(cat git)" = zworld +' + +test_expect_success 'setup pre-rebase hook' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <<EOF && +#!$SHELL_PATH +echo "\$1,\$2" >.git/PRE-REBASE-INPUT +EOF + chmod +x .git/hooks/pre-rebase +' + +test_expect_success 'pre-rebase hook gets correct input (1)' ' + git checkout test && + git reset --hard side && + git rebase master && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster, + +' + +test_expect_success 'pre-rebase hook gets correct input (2)' ' + git checkout test && + git reset --hard side && + git rebase master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (3)' ' + git checkout test && + git reset --hard side && + git checkout master && + git rebase master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (4)' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster, + +' + +test_expect_success 'pre-rebase hook gets correct input (5)' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (6)' ' + git checkout test && + git reset --hard side && + git checkout master && + EDITOR=true git rebase -i master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'setup pre-rebase hook that fails' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <<EOF && +#!$SHELL_PATH +false +EOF + chmod +x .git/hooks/pre-rebase +' + +test_expect_success 'pre-rebase hook stops rebase (1)' ' + git checkout test && + git reset --hard side && + test_must_fail git rebase master && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/test && + test 0 = $(git rev-list HEAD...side | wc -l) +' + +test_expect_success 'pre-rebase hook stops rebase (2)' ' + git checkout test && + git reset --hard side && + ( + EDITOR=: + export EDITOR + test_must_fail git rebase -i master + ) && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/test && + test 0 = $(git rev-list HEAD...side | wc -l) +' + +test_expect_success 'rebase --no-verify overrides pre-rebase (1)' ' + git checkout test && + git reset --hard side && + git rebase --no-verify master && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/test && + test "z$(cat git)" = zworld +' + +test_expect_success 'rebase --no-verify overrides pre-rebase (2)' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase --no-verify -i master && + test "z$(git symbolic-ref HEAD)" = zrefs/heads/test && + test "z$(cat git)" = zworld +' + +test_done diff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh new file mode 100755 index 0000000000..ee0a6cccfd --- /dev/null +++ b/t/t3414-rebase-preserve-onto.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Copyright (c) 2009 Greg Price +# + +test_description='git rebase -p should respect --onto + +In a rebase with --onto, we should rewrite all the commits that +aren'"'"'t on top of $ONTO, even if they are on top of $UPSTREAM. +' +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +# Set up branches like this: +# A1---B1---E1---F1---G1 +# \ \ / +# \ \--C1---D1--/ +# H1 + +test_expect_success 'setup' ' + test_commit A1 && + test_commit B1 && + test_commit C1 && + test_commit D1 && + git reset --hard B1 && + test_commit E1 && + test_commit F1 && + test_merge G1 D1 && + git reset --hard A1 && + test_commit H1 +' + +# Now rebase merge G1 from both branches' base B1, both should move: +# A1---B1---E1---F1---G1 +# \ \ / +# \ \--C1---D1--/ +# \ +# H1---E2---F2---G2 +# \ / +# \--C2---D2--/ + +test_expect_success 'rebase from B1 onto H1' ' + git checkout G1 && + git rebase -p --onto H1 B1 && + test "$(git rev-parse HEAD^1^1^1)" = "$(git rev-parse H1)" && + test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse H1)" +' + +# On the other hand if rebase from E1 which is within one branch, +# then the other branch stays: +# A1---B1---E1---F1---G1 +# \ \ / +# \ \--C1---D1--/ +# \ \ +# H1-----F3-----G3 + +test_expect_success 'rebase from E1 onto H1' ' + git checkout G1 && + git rebase -p --onto H1 E1 && + test "$(git rev-parse HEAD^1^1)" = "$(git rev-parse H1)" && + test "$(git rev-parse HEAD^2)" = "$(git rev-parse D1)" +' + +# And the same if we rebase from a commit in the second-parent branch. +# A1---B1---E1---F1----G1 +# \ \ \ / +# \ \--C1---D1-\-/ +# \ \ +# H1------D3------G4 + +test_expect_success 'rebase from C1 onto H1' ' + git checkout G1 && + git rev-list --first-parent --pretty=oneline C1..G1 && + git rebase -p --onto H1 C1 && + test "$(git rev-parse HEAD^2^1)" = "$(git rev-parse H1)" && + test "$(git rev-parse HEAD^1)" = "$(git rev-parse F1)" +' + +test_done diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh new file mode 100755 index 0000000000..b63f4e2d67 --- /dev/null +++ b/t/t3415-rebase-autosquash.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='auto squash' + +. ./test-lib.sh + +test_expect_success setup ' + echo 0 >file0 && + git add . && + test_tick && + git commit -m "initial commit" && + echo 0 >file1 && + echo 2 >file2 && + git add . && + test_tick && + git commit -m "first commit" && + echo 3 >file3 && + git add . && + test_tick && + git commit -m "second commit" && + git tag base +' + +test_expect_success 'auto fixup' ' + git reset --hard base && + echo 1 >file1 && + git add -u && + test_tick && + git commit -m "fixup! first" + + git tag final-fixup && + test_tick && + git rebase --autosquash -i HEAD^^^ && + git log --oneline >actual && + test 3 = $(wc -l <actual) && + git diff --exit-code final-fixup && + test 1 = "$(git cat-file blob HEAD^:file1)" && + test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) +' + +test_expect_success 'auto squash' ' + git reset --hard base && + echo 1 >file1 && + git add -u && + test_tick && + git commit -m "squash! first" + + git tag final-squash && + test_tick && + git rebase --autosquash -i HEAD^^^ && + git log --oneline >actual && + test 3 = $(wc -l <actual) && + git diff --exit-code final-squash && + test 1 = "$(git cat-file blob HEAD^:file1)" && + test 2 = $(git cat-file commit HEAD^ | grep first | wc -l) +' + +test_expect_success 'misspelled auto squash' ' + git reset --hard base && + echo 1 >file1 && + git add -u && + test_tick && + git commit -m "squash! forst" + git tag final-missquash && + test_tick && + git rebase --autosquash -i HEAD^^^ && + git log --oneline >actual && + test 4 = $(wc -l <actual) && + git diff --exit-code final-missquash && + test 0 = $(git rev-list final-missquash...HEAD | wc -l) +' + +test_done diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh new file mode 100755 index 0000000000..ddf2f64853 --- /dev/null +++ b/t/t3416-rebase-onto-threedots.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +test_description='git rebase --onto A...B' + +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-rebase.sh" + +# Rebase only the tip commit of "topic" on merge base between "master" +# and "topic". Cannot do this for "side" with "master" because there +# is no single merge base. +# +# +# F---G topic G' +# / / +# A---B---C---D---E master --> A---B---C---D---E +# \ \ / +# \ x +# \ / \ +# H---I---J---K side + +test_expect_success setup ' + test_commit A && + test_commit B && + git branch side && + test_commit C && + git branch topic && + git checkout side && + test_commit H && + git checkout master && + test_tick && + git merge H && + git tag D && + test_commit E && + git checkout topic && + test_commit F && + test_commit G && + git checkout side && + test_tick && + git merge C && + git tag I && + test_commit J && + test_commit K +' + +test_expect_success 'rebase --onto master...topic' ' + git reset --hard && + git checkout topic && + git reset --hard G && + + git rebase --onto master...topic F && + git rev-parse HEAD^1 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase --onto master...' ' + git reset --hard && + git checkout topic && + git reset --hard G && + + git rebase --onto master... F && + git rev-parse HEAD^1 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase --onto master...side' ' + git reset --hard && + git checkout side && + git reset --hard K && + + test_must_fail git rebase --onto master...side J +' + +test_expect_success 'rebase -i --onto master...topic' ' + git reset --hard && + git checkout topic && + git reset --hard G && + set_fake_editor && + EXPECT_COUNT=1 git rebase -i --onto master...topic F && + git rev-parse HEAD^1 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase -i --onto master...' ' + git reset --hard && + git checkout topic && + git reset --hard G && + set_fake_editor && + EXPECT_COUNT=1 git rebase -i --onto master... F && + git rev-parse HEAD^1 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase -i --onto master...side' ' + git reset --hard && + git checkout side && + git reset --hard K && + + test_must_fail git rebase -i --onto master...side J +' + +test_done diff --git a/t/t3417-rebase-whitespace-fix.sh b/t/t3417-rebase-whitespace-fix.sh new file mode 100755 index 0000000000..220a740ee8 --- /dev/null +++ b/t/t3417-rebase-whitespace-fix.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +test_description='git rebase --whitespace=fix + +This test runs git rebase --whitespace=fix and make sure that it works. +' + +. ./test-lib.sh + +# prepare initial revision of "file" with a blank line at the end +cat >file <<EOF +a +b +c + +EOF + +# expected contents in "file" after rebase +cat >expect-first <<EOF +a +b +c +EOF + +# prepare second revision of "file" +cat >second <<EOF +a +b +c + +d +e +f + + + + +EOF + +# expected contents in second revision after rebase +cat >expect-second <<EOF +a +b +c + +d +e +f +EOF + +test_expect_success 'blank line at end of file; extend at end of file' ' + git commit --allow-empty -m "Initial empty commit" && + git add file && git commit -m first && + mv second file && + git add file && git commit -m second && + git rebase --whitespace=fix HEAD^^ && + git diff --exit-code HEAD^:file expect-first && + test_cmp file expect-second +' + +# prepare third revision of "file" +sed -e's/Z//' >third <<EOF +a +b +c + +d +e +f + Z + Z +h +i +j +k +l +EOF + +sed -e's/ //g' <third >expect-third + +test_expect_success 'two blanks line at end of file; extend at end of file' ' + cp third file && git add file && git commit -m third && + git rebase --whitespace=fix HEAD^^ && + git diff --exit-code HEAD^:file expect-second && + test_cmp file expect-third +' + +test_expect_success 'same, but do not remove trailing spaces' ' + git config core.whitespace "-blank-at-eol" && + git reset --hard HEAD^ && + cp third file && git add file && git commit -m third && + git rebase --whitespace=fix HEAD^^ + git diff --exit-code HEAD^:file expect-second && + test_cmp file third +' + +sed -e's/Z//' >beginning <<EOF +a + Z + Z +EOF + +cat >expect-beginning <<EOF +a + + +1 +2 +3 +4 +5 +EOF + +test_expect_success 'at beginning of file' ' + git config core.whitespace "blank-at-eol" && + cp beginning file && + git commit -m beginning file && + for i in 1 2 3 4 5; do + echo $i + done >> file && + git commit -m more file && + git rebase --whitespace=fix HEAD^^ && + test_cmp file expect-beginning +' + +test_done 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 e83bbee074..f038f34b7c 100755 --- a/t/t3500-cherry.sh +++ b/t/t3500-cherry.sh @@ -3,52 +3,56 @@ # Copyright (c) 2006 Yann Dirson, based on t3400 by Amos Waterland # -test_description='git-cherry should detect patches integrated upstream +test_description='git cherry should detect patches integrated upstream This test cherry-picks one local change of two into master branch, and -checks that git-cherry only returns the second patch in the local branch +checks that git cherry only returns the second patch in the local branch ' . ./test-lib.sh -export GIT_AUTHOR_EMAIL=bogus_email_address +GIT_AUTHOR_EMAIL=bogus_email_address +export GIT_AUTHOR_EMAIL 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 && - git-commit -m "Add A." && + git update-index --add A && + test_tick && + git commit -m "Add A." && - git-checkout -b my-topic-branch && + git checkout -b my-topic-branch && echo Second > B && - git-update-index --add B && - git-commit -m "Add B." && + git update-index --add B && + test_tick && + git commit -m "Add B." && - sleep 2 && echo AnotherSecond > C && - git-update-index --add C && - git-commit -m "Add C." && + git update-index --add C && + test_tick && + git commit -m "Add C." && - git-checkout -f master && + git checkout -f master && rm -f B C && echo Third >> A && - git-update-index A && - git-commit -m "Modify A." && + git update-index A && + test_tick && + git commit -m "Modify A." && - expr "$(echo $(git-cherry master my-topic-branch) )" : "+ [^ ]* + .*" + expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* + .*" ' test_expect_success \ 'check that cherry with limit returns only the top patch'\ - 'expr "$(echo $(git-cherry master my-topic-branch my-topic-branch^1) )" : "+ [^ ]*" + 'expr "$(echo $(git cherry master my-topic-branch my-topic-branch^1) )" : "+ [^ ]*" ' test_expect_success \ 'cherry-pick one of the 2 patches, and check cherry recognized one and only one as new' \ - 'git-cherry-pick my-topic-branch^0 && - echo $(git-cherry master my-topic-branch) && - expr "$(echo $(git-cherry master my-topic-branch) )" : "+ [^ ]* - .*" + 'git cherry-pick my-topic-branch^0 && + echo $(git cherry master my-topic-branch) && + expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* - .*" ' test_done diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 552af1c4d2..bc7aedd048 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -41,21 +41,52 @@ 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 && - EDITOR=: VISUAL=: git cherry-pick added && + 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 ' test_expect_success 'revert after renaming branch' ' git checkout rename1 && - EDITOR=: VISUAL=: git revert added && + 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 + +' + +test_expect_success 'revert forbidden on dirty working tree' ' + + echo content >extra_file && + git add extra_file && + test_must_fail git revert HEAD 2>errors && + grep "Your local changes would be overwritten by " errors ' diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh new file mode 100755 index 0000000000..0ab52da902 --- /dev/null +++ b/t/t3502-cherry-pick-merge.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +test_description='cherry picking and reverting a merge + + b---c + / / + initial---a + +' + +. ./test-lib.sh + +test_expect_success setup ' + + >A && + >B && + git add A B && + git commit -m "Initial" && + git tag initial && + git branch side && + echo new line >A && + git commit -m "add line to A" A && + git tag a && + git checkout side && + echo new line >B && + git commit -m "add line to B" B && + git tag b && + git checkout master && + git merge side && + git tag c + +' + +test_expect_success 'cherry-pick a non-merge with -m should fail' ' + + git reset --hard && + git checkout a^0 && + test_must_fail git cherry-pick -m 1 b && + git diff --exit-code a -- + +' + +test_expect_success 'cherry pick a merge without -m should fail' ' + + git reset --hard && + git checkout a^0 && + test_must_fail git cherry-pick c && + git diff --exit-code a -- + +' + +test_expect_success 'cherry pick a merge (1)' ' + + git reset --hard && + git checkout a^0 && + git cherry-pick -m 1 c && + git diff --exit-code c + +' + +test_expect_success 'cherry pick a merge (2)' ' + + git reset --hard && + git checkout b^0 && + git cherry-pick -m 2 c && + git diff --exit-code c + +' + +test_expect_success 'cherry pick a merge relative to nonexistent parent should fail' ' + + git reset --hard && + git checkout b^0 && + test_must_fail git cherry-pick -m 3 c + +' + +test_expect_success 'revert a non-merge with -m should fail' ' + + git reset --hard && + git checkout c^0 && + test_must_fail git revert -m 1 b && + git diff --exit-code c + +' + +test_expect_success 'revert a merge without -m should fail' ' + + git reset --hard && + git checkout c^0 && + test_must_fail git revert c && + git diff --exit-code c + +' + +test_expect_success 'revert a merge (1)' ' + + git reset --hard && + git checkout c^0 && + git revert -m 1 c && + git diff --exit-code a -- + +' + +test_expect_success 'revert a merge (2)' ' + + git reset --hard && + git checkout c^0 && + git revert -m 2 c && + git diff --exit-code b -- + +' + +test_expect_success 'revert a merge relative to nonexistent parent should fail' ' + + git reset --hard && + git checkout c^0 && + test_must_fail git revert -m 3 c && + git diff --exit-code c + +' + +test_done diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh new file mode 100755 index 0000000000..b0faa29918 --- /dev/null +++ b/t/t3503-cherry-pick-root.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='test cherry-picking a root commit' + +. ./test-lib.sh + +test_expect_success setup ' + + echo first > file1 && + git add file1 && + test_tick && + git commit -m "first" && + + git symbolic-ref HEAD refs/heads/second && + rm .git/index file1 && + echo second > file2 && + git add file2 && + test_tick && + git commit -m "second" + +' + +test_expect_success 'cherry-pick a root commit' ' + + git cherry-pick master && + test first = $(cat file1) + +' + +test_done diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh new file mode 100755 index 0000000000..f7b3518a32 --- /dev/null +++ b/t/t3504-cherry-pick-rerere.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='cherry-pick should rerere for conflicts' + +. ./test-lib.sh + +test_expect_success setup ' + echo foo >foo && + git add foo && test_tick && git commit -q -m 1 && + echo foo-master >foo && + git add foo && test_tick && git commit -q -m 2 && + + git checkout -b dev HEAD^ && + echo foo-dev >foo && + git add foo && test_tick && git commit -q -m 3 && + git config rerere.enabled true +' + +test_expect_success 'conflicting merge' ' + test_must_fail git merge master +' + +test_expect_success 'fixup' ' + echo foo-dev >foo && + git add foo && test_tick && git commit -q -m 4 && + git reset --hard HEAD^ + echo foo-dev >expect +' + +test_expect_success 'cherry-pick conflict' ' + test_must_fail git cherry-pick master && + test_cmp expect foo +' + +test_expect_success 'reconfigure' ' + git config rerere.enabled false + git reset --hard +' + +test_expect_success 'cherry-pick conflict without rerere' ' + test_must_fail git cherry-pick master && + test_must_fail test_cmp expect foo +' + +test_done diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh new file mode 100755 index 0000000000..e51e505a9f --- /dev/null +++ b/t/t3505-cherry-pick-empty.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +test_description='test cherry-picking an empty commit' + +. ./test-lib.sh + +test_expect_success setup ' + + echo first > file1 && + git add file1 && + test_tick && + git commit -m "first" && + + git checkout -b empty-branch && + test_tick && + git commit --allow-empty -m "empty" + +' + +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_done diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh new file mode 100755 index 0000000000..e17ae712b1 --- /dev/null +++ b/t/t3506-cherry-pick-ff.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='test cherry-picking with --ff option' + +. ./test-lib.sh + +test_expect_success setup ' + echo first > file1 && + git add file1 && + test_tick && + git commit -m "first" && + git tag first && + + git checkout -b other && + echo second >> file1 && + git add file1 && + test_tick && + git commit -m "second" && + git tag second +' + +test_expect_success 'cherry-pick using --ff fast forwards' ' + git checkout master && + git reset --hard first && + test_tick && + git cherry-pick --ff second && + test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify second)" +' + +test_expect_success 'cherry-pick not using --ff does not fast forwards' ' + git checkout master && + git reset --hard first && + test_tick && + git cherry-pick second && + test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify second)" +' + +# +# We setup the following graph: +# +# B---C +# / / +# first---A +# +# (This has been taken from t3502-cherry-pick-merge.sh) +# +test_expect_success 'merge setup' ' + git checkout master && + git reset --hard first && + echo new line >A && + git add A && + test_tick && + git commit -m "add line to A" A && + git tag A && + git checkout -b side first && + echo new line >B && + git add B && + test_tick && + git commit -m "add line to B" B && + git tag B && + git checkout master && + git merge side && + git tag C && + git checkout -b new A +' + +test_expect_success 'cherry-pick a non-merge with --ff and -m should fail' ' + git reset --hard A -- && + test_must_fail git cherry-pick --ff -m 1 B && + git diff --exit-code A -- +' + +test_expect_success 'cherry pick a merge with --ff but without -m should fail' ' + git reset --hard A -- && + test_must_fail git cherry-pick --ff C && + git diff --exit-code A -- +' + +test_expect_success 'cherry pick with --ff a merge (1)' ' + git reset --hard A -- && + git cherry-pick --ff -m 1 C && + git diff --exit-code C && + test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify C)" +' + +test_expect_success 'cherry pick with --ff a merge (2)' ' + git reset --hard B -- && + git cherry-pick --ff -m 2 C && + git diff --exit-code C && + test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify C)" +' + +test_expect_success 'cherry pick a merge relative to nonexistent parent with --ff should fail' ' + git reset --hard B -- && + test_must_fail git cherry-pick --ff -m 3 C +' + +test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh new file mode 100755 index 0000000000..e25cf8039a --- /dev/null +++ b/t/t3507-cherry-pick-conflict.sh @@ -0,0 +1,198 @@ +#!/bin/sh + +test_description='test cherry-pick and revert with conflicts + + - + + picked: rewrites foo to c + + base: rewrites foo to b + + initial: writes foo as a, unrelated as unrelated + +' + +. ./test-lib.sh + +test_expect_success setup ' + + echo unrelated >unrelated && + git add unrelated && + test_commit initial foo a && + test_commit base foo b && + test_commit picked foo c && + git config advice.detachedhead false + +' + +test_expect_success 'failed cherry-pick does not advance HEAD' ' + + git checkout -f initial^0 && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + + git update-index --refresh && + git diff-index --exit-code HEAD && + + head=$(git rev-parse HEAD) && + test_must_fail git cherry-pick picked && + newhead=$(git rev-parse HEAD) && + + test "$head" = "$newhead" +' + +test_expect_success 'failed cherry-pick produces dirty index' ' + + 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 && + + test_must_fail git cherry-pick picked && + + test_must_fail git update-index --refresh -q && + test_must_fail git diff-index --exit-code HEAD +' + +test_expect_success 'failed cherry-pick registers participants in index' ' + + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + { + git checkout base -- foo && + git ls-files --stage foo && + git checkout initial -- foo && + git ls-files --stage foo && + git checkout picked -- foo && + git ls-files --stage foo + } > stages && + sed " + 1 s/ 0 / 1 / + 2 s/ 0 / 2 / + 3 s/ 0 / 3 / + " < stages > expected && + git checkout -f initial^0 && + + git update-index --refresh && + git diff-index --exit-code HEAD && + + test_must_fail git cherry-pick picked && + git ls-files --stage --unmerged > actual && + + test_cmp expected actual +' + +test_expect_success 'failed cherry-pick describes conflict in work tree' ' + + git checkout -f initial^0 && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + cat <<-EOF > expected && + <<<<<<< HEAD + a + ======= + c + >>>>>>> objid picked + EOF + + git update-index --refresh && + git diff-index --exit-code HEAD && + + test_must_fail git cherry-pick picked && + + sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + test_cmp expected actual +' + +test_expect_success 'diff3 -m style' ' + + git config merge.conflictstyle diff3 && + git checkout -f initial^0 && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + cat <<-EOF > expected && + <<<<<<< HEAD + a + ||||||| parent of objid picked + b + ======= + c + >>>>>>> objid picked + EOF + + git update-index --refresh && + git diff-index --exit-code HEAD && + + test_must_fail git cherry-pick picked && + + sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + test_cmp expected actual +' + +test_expect_success 'revert also handles conflicts sanely' ' + + git config --unset merge.conflictstyle && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + cat <<-EOF > expected && + <<<<<<< HEAD + a + ======= + b + >>>>>>> parent of objid picked + EOF + { + git checkout picked -- foo && + git ls-files --stage foo && + git checkout initial -- foo && + git ls-files --stage foo && + git checkout base -- foo && + git ls-files --stage foo + } > stages && + sed " + 1 s/ 0 / 1 / + 2 s/ 0 / 2 / + 3 s/ 0 / 3 / + " < stages > expected-stages && + git checkout -f initial^0 && + + git update-index --refresh && + git diff-index --exit-code HEAD && + + head=$(git rev-parse HEAD) && + test_must_fail git revert picked && + newhead=$(git rev-parse HEAD) && + git ls-files --stage --unmerged > actual-stages && + + test "$head" = "$newhead" && + test_must_fail git update-index --refresh -q && + test_must_fail git diff-index --exit-code HEAD && + test_cmp expected-stages actual-stages && + sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + test_cmp expected actual +' + +test_expect_success 'revert conflict, diff3 -m style' ' + git config merge.conflictstyle diff3 && + git checkout -f initial^0 && + git read-tree -u --reset HEAD && + git clean -d -f -f -q -x && + cat <<-EOF > expected && + <<<<<<< HEAD + a + ||||||| objid picked + c + ======= + b + >>>>>>> parent of objid picked + EOF + + git update-index --refresh && + git diff-index --exit-code HEAD && + + test_must_fail git revert picked && + + sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + test_cmp expected actual +' + +test_done diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh new file mode 100755 index 0000000000..f90ed3da3e --- /dev/null +++ b/t/t3508-cherry-pick-many-commits.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +test_description='test cherry-picking many commits' + +. ./test-lib.sh + +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' ' + git checkout -f master && + git reset --hard first && + test_tick && + git cherry-pick first..fourth && + git diff --quiet other && + git diff --quiet HEAD other && + test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify 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 && + test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify 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 && + test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify 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 && + test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)" +' + +test_done diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index e31cf93a00..b514cbb606 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Carl D. Worth # -test_description='Test of the various options to git-rm.' +test_description='Test of the various options to git rm.' . ./test-lib.sh @@ -11,78 +11,140 @@ test_description='Test of the various options to git-rm.' test_expect_success \ 'Initialize test directory' \ "touch -- foo bar baz 'space embedded' -q && - git-add -- foo bar baz 'space embedded' -q && - git-commit -m 'add normal files' && - test_tabs=y && - if touch -- 'tab embedded' 'newline -embedded' - then - git-add -- 'tab embedded' 'newline + git add -- foo bar baz 'space embedded' -q && + git commit -m 'add normal files'" + +if touch -- 'tab embedded' 'newline +embedded' 2>/dev/null +then + test_set_prereq FUNNYNAMES +else + say 'Your filesystem does not allow tabs in filenames.' +fi + +test_expect_success FUNNYNAMES 'add files with funny names' " + git add -- 'tab embedded' 'newline embedded' && - git-commit -m 'add files with tabs and newlines' - else - say 'Your filesystem does not allow tabs in filenames.' - test_tabs=n - fi" + 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 +# 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 + skip_all='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' + test_expect_success \ - 'Determine rm behavior' \ - ': >test-file - chmod a-w . - rm -f test-file - test -f test-file && test_failed_remove=y - chmod 775 . - rm -f test-file' + 'Test that git rm foo succeeds' \ + 'git rm --cached foo' test_expect_success \ - 'Pre-check that foo exists and is in index before git-rm foo' \ - '[ -f foo ] && git-ls-files --error-unmatch foo' + 'Test that git rm --cached foo succeeds if the index matches the file' \ + 'echo content > foo + git add foo + git rm --cached foo' test_expect_success \ - 'Test that git-rm foo succeeds' \ - 'git-rm --cached foo' + 'Test that git rm --cached foo succeeds if the index matches the file' \ + 'echo content > foo + git add foo + git commit -m foo + echo "other content" > foo + git rm --cached foo' test_expect_success \ - 'Post-check that foo exists but is not in index after git-rm foo' \ - '[ -f foo ] && ! git-ls-files --error-unmatch foo' + 'Test that git rm --cached foo fails if the index matches neither the file nor HEAD' ' + echo content > foo + git add foo + git commit -m foo + echo "other content" > foo + git add foo + echo "yet another content" > foo + test_must_fail git rm --cached foo +' + +test_expect_success \ + 'Test that git rm --cached -f foo works in case where --cached only did not' \ + 'echo content > foo + git add foo + git commit -m foo + echo "other content" > foo + git add foo + echo "yet another content" > foo + git rm --cached -f foo' test_expect_success \ - 'Pre-check that bar exists and is in index before "git-rm bar"' \ - '[ -f bar ] && git-ls-files --error-unmatch bar' + 'Post-check that foo exists but is not in index after git rm foo' \ + '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo' test_expect_success \ - 'Test that "git-rm bar" succeeds' \ - 'git-rm bar' + 'Pre-check that bar exists and is in index before "git rm bar"' \ + '[ -f bar ] && git ls-files --error-unmatch bar' test_expect_success \ - 'Post-check that bar does not exist and is not in index after "git-rm -f bar"' \ - '! [ -f bar ] && ! git-ls-files --error-unmatch bar' + 'Test that "git rm bar" succeeds' \ + 'git rm bar' test_expect_success \ - 'Test that "git-rm -- -q" succeeds (remove a file that looks like an option)' \ - 'git-rm -- -q' + 'Post-check that bar does not exist and is not in index after "git rm -f bar"' \ + '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar' -test "$test_tabs" = y && test_expect_success \ - "Test that \"git-rm -f\" succeeds with embedded space, tab, or newline characters." \ - "git-rm -f 'space embedded' 'tab embedded' 'newline +test_expect_success \ + 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \ + 'git rm -- -q' + +test_expect_success FUNNYNAMES \ + "Test that \"git rm -f\" succeeds with embedded space, tab, or newline characters." \ + "git rm -f 'space embedded' 'tab embedded' 'newline embedded'" -if test "$test_failed_remove" = y; then -chmod a-w . -test_expect_failure \ - 'Test that "git-rm -f" fails if its rm fails' \ - 'git-rm -f baz' -chmod 775 . -else - test_expect_success 'skipping removal failure (perhaps running as root?)' : -fi +test_expect_success RO_DIR 'Test that "git rm -f" fails if its rm fails' ' + chmod a-w . && + test_must_fail git rm -f baz && + chmod 775 . +' test_expect_success \ - 'When the rm in "git-rm -f" fails, it should not remove the file from the index' \ - 'git-ls-files --error-unmatch baz' + 'When the rm in "git rm -f" fails, it should not remove the file from the index' \ + 'git ls-files --error-unmatch baz' + +test_expect_success 'Remove nonexistent file with --ignore-unmatch' ' + git rm --ignore-unmatch nonexistent +' + +test_expect_success '"rm" command printed' ' + echo frotz > test-file && + git add test-file && + git commit -m "add file for rm test" && + git rm test-file > rm-output && + test `grep "^rm " rm-output | wc -l` = 1 && + rm -f test-file rm-output && + git commit -m "remove file from rm test" +' + +test_expect_success '"rm" command suppressed with --quiet' ' + echo frotz > test-file && + git add test-file && + git commit -m "add file for rm --quiet test" && + git rm --quiet test-file > rm-output && + test `wc -l < rm-output` = 0 && + rm -f test-file rm-output && + git commit -m "remove file from rm --quiet test" +' # Now, failure cases. test_expect_success 'Re-add foo and baz' ' @@ -92,7 +154,7 @@ test_expect_success 'Re-add foo and baz' ' test_expect_success 'Modify foo -- rm should refuse' ' echo >>foo && - ! git rm foo baz && + test_must_fail git rm foo baz && test -f foo && test -f baz && git ls-files --error-unmatch foo baz @@ -102,8 +164,8 @@ test_expect_success 'Modified foo -- rm -f should work' ' git rm -f foo baz && test ! -f foo && test ! -f baz && - ! git ls-files --error-unmatch foo && - ! git ls-files --error-unmatch bar + test_must_fail git ls-files --error-unmatch foo && + test_must_fail git ls-files --error-unmatch bar ' test_expect_success 'Re-add foo and baz for HEAD tests' ' @@ -114,7 +176,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' ' ' test_expect_success 'foo is different in index from HEAD -- rm should refuse' ' - ! git rm foo baz && + test_must_fail git rm foo baz && test -f foo && test -f baz && git ls-files --error-unmatch foo baz @@ -124,8 +186,21 @@ test_expect_success 'but with -f it should work.' ' git rm -f foo baz && test ! -f foo && test ! -f baz && - ! git ls-files --error-unmatch foo - ! git ls-files --error-unmatch baz + test_must_fail git ls-files --error-unmatch foo + test_must_fail git ls-files --error-unmatch baz +' + +test_expect_success 'refuse to remove cached empty file with modifications' ' + >empty && + git add empty && + echo content >empty && + test_must_fail git rm --cached empty +' + +test_expect_success 'remove intent-to-add file without --force' ' + echo content >intent-to-add && + git add -N intent-to-add + git rm --cached intent-to-add ' test_expect_success 'Recursive test setup' ' @@ -136,14 +211,14 @@ test_expect_success 'Recursive test setup' ' ' test_expect_success 'Recursive without -r fails' ' - ! git rm frotz && + test_must_fail git rm frotz && test -d frotz && test -f frotz/nitfol ' test_expect_success 'Recursive with -r but dirty' ' echo qfwfq >>frotz/nitfol - ! git rm -r frotz && + test_must_fail git rm -r frotz && test -d frotz && test -f frotz/nitfol ' @@ -154,4 +229,54 @@ test_expect_success 'Recursive with -r -f' ' ! test -d frotz ' +test_expect_success 'Remove nonexistent file returns nonzero exit status' ' + test_must_fail git rm nonexistent +' + +test_expect_success 'Call "rm" from outside the work tree' ' + mkdir repo && + (cd repo && + git init && + echo something > somefile && + git add somefile && + git commit -m "add a file" && + (cd .. && + git --git-dir=repo/.git --work-tree=repo rm somefile) && + test_must_fail git ls-files --error-unmatch somefile) +' + +test_expect_success 'refresh index before checking if it is up-to-date' ' + + git reset --hard && + test-chmtime -86400 frotz/nitfol && + git rm frotz/nitfol && + test ! -f frotz/nitfol + +' + +test_expect_success 'choking "git rm" should not let it die with cruft' ' + git reset -q --hard && + H=0000000000000000000000000000000000000000 && + i=0 && + while test $i -lt 12000 + do + echo "100644 $H 0 some-file-$i" + i=$(( $i + 1 )) + done | git update-index --index-info && + git rm -n "some-file-*" | :; + test -f .git/index.lock + status=$? + rm -f .git/index.lock + git reset -q --hard + test "$status" != 0 +' + +test_expect_success 'rm removes subdirectories recursively' ' + mkdir -p dir/subdir/subsubdir && + echo content >dir/subdir/subsubdir/file && + git add dir/subdir/subsubdir/file && + git rm -f dir/subdir/subsubdir/file && + ! test -d dir +' + test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 08e035220c..7d7140db38 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -3,72 +3,72 @@ # Copyright (c) 2006 Carl D. Worth # -test_description='Test of git-add, including the -- option.' +test_description='Test of git add, including the -- option.' . ./test-lib.sh test_expect_success \ - 'Test of git-add' \ - 'touch foo && git-add foo' + 'Test of git add' \ + 'touch foo && git add foo' test_expect_success \ 'Post-check that foo is in the index' \ - 'git-ls-files foo | grep foo' + 'git ls-files foo | grep foo' test_expect_success \ - 'Test that "git-add -- -q" works' \ - 'touch -- -q && git-add -- -q' + 'Test that "git add -- -q" works' \ + 'touch -- -q && git add -- -q' test_expect_success \ - 'git-add: Test that executable bit is not used if core.filemode=0' \ + 'git add: Test that executable bit is not used if core.filemode=0' \ 'git config core.filemode 0 && echo foo >xfoo1 && chmod 755 xfoo1 && - git-add xfoo1 && - case "`git-ls-files --stage xfoo1`" in - 100644" "*xfoo1) echo ok;; - *) echo fail; git-ls-files --stage xfoo1; (exit 1);; + git add xfoo1 && + case "`git ls-files --stage xfoo1`" in + 100644" "*xfoo1) echo pass;; + *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac' -test_expect_success 'git-add: filemode=0 should not get confused by symlink' ' +test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo1 && ln -s foo xfoo1 && - git-add xfoo1 && - case "`git-ls-files --stage xfoo1`" in - 120000" "*xfoo1) echo ok;; - *) echo fail; git-ls-files --stage xfoo1; (exit 1);; + git add xfoo1 && + case "`git ls-files --stage xfoo1`" in + 120000" "*xfoo1) echo pass;; + *) echo fail; git ls-files --stage xfoo1; (exit 1);; esac ' test_expect_success \ - 'git-update-index --add: Test that executable bit is not used...' \ + 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && echo foo >xfoo2 && chmod 755 xfoo2 && - git-update-index --add xfoo2 && - case "`git-ls-files --stage xfoo2`" in - 100644" "*xfoo2) echo ok;; - *) echo fail; git-ls-files --stage xfoo2; (exit 1);; + git update-index --add xfoo2 && + case "`git ls-files --stage xfoo2`" in + 100644" "*xfoo2) echo pass;; + *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac' -test_expect_success 'git-add: filemode=0 should not get confused by symlink' ' +test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo2 && ln -s foo xfoo2 && git update-index --add xfoo2 && - case "`git-ls-files --stage xfoo2`" in - 120000" "*xfoo2) echo ok;; - *) echo fail; git-ls-files --stage xfoo2; (exit 1);; + case "`git ls-files --stage xfoo2`" in + 120000" "*xfoo2) echo pass;; + *) echo fail; git ls-files --stage xfoo2; (exit 1);; esac ' -test_expect_success \ - 'git-update-index --add: Test that executable bit is not used...' \ +test_expect_success SYMLINKS \ + 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && ln -s xfoo2 xfoo3 && - git-update-index --add xfoo3 && - case "`git-ls-files --stage xfoo3`" in - 120000" "*xfoo3) echo ok;; - *) echo fail; git-ls-files --stage xfoo3; (exit 1);; + git update-index --add xfoo3 && + case "`git ls-files --stage xfoo3`" in + 120000" "*xfoo3) echo pass;; + *) echo fail; git ls-files --stage xfoo3; (exit 1);; esac' test_expect_success '.gitignore test setup' ' @@ -80,28 +80,212 @@ test_expect_success '.gitignore test setup' ' ' test_expect_success '.gitignore is honored' ' - git-add . && - ! git-ls-files | grep "\\.ig" + git add . && + ! (git ls-files | grep "\\.ig") ' test_expect_success 'error out when attempting to add ignored ones without -f' ' - ! git-add a.?? && - ! git-ls-files | grep "\\.ig" + test_must_fail git add a.?? && + ! (git ls-files | grep "\\.ig") ' test_expect_success 'error out when attempting to add ignored ones without -f' ' - ! git-add d.?? && - ! git-ls-files | grep "\\.ig" + test_must_fail git add d.?? && + ! (git ls-files | grep "\\.ig") ' test_expect_success 'add ignored ones with -f' ' - git-add -f a.?? && - git-ls-files --error-unmatch a.ig + git add -f a.?? && + git ls-files --error-unmatch a.ig ' test_expect_success 'add ignored ones with -f' ' - git-add -f d.??/* && - git-ls-files --error-unmatch d.ig/d.if d.ig/d.ig + git add -f d.??/* && + git ls-files --error-unmatch d.ig/d.if d.ig/d.ig +' + +test_expect_success 'add ignored ones with -f' ' + rm -f .git/index && + git add -f d.?? && + git ls-files --error-unmatch d.ig/d.if d.ig/d.ig +' + +test_expect_success '.gitignore with subdirectory' ' + + rm -f .git/index && + mkdir -p sub/dir && + echo "!dir/a.*" >sub/.gitignore && + >sub/a.ig && + >sub/dir/a.ig && + git add sub/dir && + git ls-files --error-unmatch sub/dir/a.ig && + rm -f .git/index && + ( + cd sub/dir && + git add . + ) && + git ls-files --error-unmatch sub/dir/a.ig +' + +mkdir 1 1/2 1/3 +touch 1/2/a 1/3/b 1/2/c +test_expect_success 'check correct prefix detection' ' + rm -f .git/index && + git add 1/2/a 1/3/b 1/2/c +' + +test_expect_success 'git add with filemode=0, symlinks=0, and unmerged entries' ' + for s in 1 2 3 + do + echo $s > stage$s + echo "100755 $(git hash-object -w stage$s) $s file" + echo "120000 $(printf $s | git hash-object -w -t blob --stdin) $s symlink" + done | git update-index --index-info && + git config core.filemode 0 && + git config core.symlinks 0 && + echo new > file && + echo new > symlink && + git add file symlink && + git ls-files --stage | grep "^100755 .* 0 file$" && + git ls-files --stage | grep "^120000 .* 0 symlink$" +' + +test_expect_success 'git add with filemode=0, symlinks=0 prefers stage 2 over stage 1' ' + git rm --cached -f file symlink && + ( + echo "100644 $(git hash-object -w stage1) 1 file" + echo "100755 $(git hash-object -w stage2) 2 file" + echo "100644 $(printf 1 | git hash-object -w -t blob --stdin) 1 symlink" + echo "120000 $(printf 2 | git hash-object -w -t blob --stdin) 2 symlink" + ) | git update-index --index-info && + git config core.filemode 0 && + git config core.symlinks 0 && + echo new > file && + echo new > symlink && + git add file symlink && + git ls-files --stage | grep "^100755 .* 0 file$" && + git ls-files --stage | grep "^120000 .* 0 symlink$" +' + +test_expect_success 'git add --refresh' ' + >foo && git add foo && git commit -a -m "commit all" && + test -z "`git diff-index HEAD -- foo`" && + git read-tree HEAD && + case "`git diff-index HEAD -- foo`" in + :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' ' + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose . && + ! ( git ls-files foo1 | grep foo1 ) +' + +rm -f foo2 + +test_expect_success POSIXPERM 'git add --ignore-errors' ' + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose --ignore-errors . && + git ls-files foo1 | grep foo1 +' + +rm -f foo2 + +test_expect_success POSIXPERM 'git add (add.ignore-errors)' ' + git config add.ignore-errors 1 && + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose . && + git ls-files foo1 | grep foo1 +' +rm -f foo2 + +test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' ' + git config add.ignore-errors 0 && + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose . && + ! ( git ls-files foo1 | grep foo1 ) +' +rm -f foo2 + +test_expect_success POSIXPERM '--no-ignore-errors overrides config' ' + git config add.ignore-errors 1 && + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose --no-ignore-errors . && + ! ( git ls-files foo1 | grep foo1 ) && + git config add.ignore-errors 0 +' +rm -f foo2 + +test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" ' + git reset --hard && + touch fo\[ou\]bar foobar && + git add '\''fo\[ou\]bar'\'' && + git ls-files fo\[ou\]bar | fgrep fo\[ou\]bar && + ! ( git ls-files foobar | grep foobar ) +' + +test_expect_success 'git add to resolve conflicts on otherwise ignored path' ' + git reset --hard && + H=$(git rev-parse :1/2/a) && + ( + echo "100644 $H 1 track-this" + echo "100644 $H 3 track-this" + ) | git update-index --index-info && + echo track-this >>.gitignore && + echo resolved >track-this && + git add track-this +' + +test_expect_success '"add non-existent" should fail' ' + test_must_fail git add non-existent && + ! (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 new file mode 100755 index 0000000000..7ad8465f8f --- /dev/null +++ b/t/t3701-add-interactive.sh @@ -0,0 +1,268 @@ +#!/bin/sh + +test_description='add -i basic tests' +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping git add -i tests, perl not available' + test_done +fi + +test_expect_success 'setup (initial)' ' + echo content >file && + git add file && + echo more >>file && + echo lines >>file +' +test_expect_success 'status works (initial)' ' + git add -i </dev/null >output && + grep "+1/-0 *+2/-0 file" output +' +cat >expected <<EOF +new file mode 100644 +index 0000000..d95f3ad +--- /dev/null ++++ b/file +@@ -0,0 +1 @@ ++content +EOF +test_expect_success '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)' ' + git add file && + (echo r; echo 1) | git add -i && + git ls-files >output && + ! grep . output +' + +test_expect_success 'setup (commit)' ' + echo baseline >file && + git add file && + git commit -m commit && + echo content >>file && + git add file && + echo more >>file && + echo lines >>file +' +test_expect_success 'status works (commit)' ' + git add -i </dev/null >output && + grep "+1/-0 *+2/-0 file" output +' +cat >expected <<EOF +index 180b47c..b6f2c08 100644 +--- a/file ++++ b/file +@@ -1 +1,2 @@ + baseline ++content +EOF +test_expect_success '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)' ' + git add file && + (echo r; echo 1) | git add -i && + git add -i </dev/null >output && + grep "unchanged *+3/-0 file" output +' + +cat >expected <<EOF +EOF +cat >fake_editor.sh <<EOF +EOF +chmod a+x fake_editor.sh +test_set_editor "$(pwd)/fake_editor.sh" +test_expect_success 'dummy edit works' ' + (echo e; echo a) | git add -p && + git diff > diff && + test_cmp expected diff +' + +cat >patch <<EOF +@@ -1,1 +1,4 @@ + this ++patch +-doesn't + apply +EOF +echo "#!$SHELL_PATH" >fake_editor.sh +cat >>fake_editor.sh <<\EOF +mv -f "$1" oldpatch && +mv -f patch "$1" +EOF +chmod a+x fake_editor.sh +test_set_editor "$(pwd)/fake_editor.sh" +test_expect_success 'bad edit rejected' ' + git reset && + (echo e; echo n; echo d) | git add -p >output && + grep "hunk does not apply" output +' + +cat >patch <<EOF +this patch +is garbage +EOF +test_expect_success 'garbage edit rejected' ' + git reset && + (echo e; echo n; echo d) | git add -p >output && + grep "hunk does not apply" output +' + +cat >patch <<EOF +@@ -1,0 +1,0 @@ + baseline ++content ++newcontent ++lines +EOF +cat >expected <<EOF +diff --git a/file b/file +index b5dd6c9..f910ae9 100644 +--- a/file ++++ b/file +@@ -1,4 +1,4 @@ + baseline + content +-newcontent ++more + lines +EOF +test_expect_success 'real edit works' ' + (echo e; echo n; echo d) | git add -p && + git diff >output && + test_cmp expected output +' + +test_expect_success 'skip files similarly as commit -a' ' + git reset && + echo file >.gitignore && + echo changed >file && + echo y | git add -p file && + git diff >output && + git reset && + git commit -am commit && + git diff >expected && + test_cmp expected output && + git reset --hard HEAD^ +' +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' ' + git reset --hard && + echo content >>file && + chmod +x file && + printf "n\\ny\\n" | git add -p && + git show :file | grep content && + git diff file | grep "new mode" +' + +test_expect_success FILEMODE 'stage mode but not hunk' ' + git reset --hard && + echo content >>file && + chmod +x file && + printf "y\\nn\\n" | git add -p && + git diff --cached file | grep "new mode" && + git diff file | grep "+content" +' + + +test_expect_success FILEMODE 'stage mode and hunk' ' + git reset --hard && + echo content >>file && + chmod +x file && + printf "y\\ny\\n" | git add -p && + git diff --cached file | grep "new mode" && + git diff --cached file | grep "+content" && + test -z "$(git diff file)" +' + +# end of tests disabled when filemode is not usable + +test_expect_success '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 +cat >patch <<EOF +index 180b47c..b6f2c08 100644 +--- a/file ++++ b/file +@@ -1,2 +1,4 @@ ++firstline + baseline + content ++lastline +EOF +# Expected output, similar to the patch but w/ diff at the top +cat >expected <<EOF +diff --git a/file b/file +index b6f2c08..61b9053 100755 +--- a/file ++++ b/file +@@ -1,2 +1,4 @@ ++firstline + baseline + content ++lastline +EOF +# Test splitting the first patch, then adding both +test_expect_success 'add first line works' ' + git commit -am "clear local changes" && + git apply patch && + (echo s; echo y; echo y) | git add -p file && + git diff --cached > diff && + test_cmp expected diff +' + +cat >expected <<EOF +diff --git a/non-empty b/non-empty +deleted file mode 100644 +index d95f3ad..0000000 +--- a/non-empty ++++ /dev/null +@@ -1 +0,0 @@ +-content +EOF +test_expect_success 'deleting a non-empty file' ' + git reset --hard && + echo content >non-empty && + git add non-empty && + git commit -m non-empty && + rm non-empty && + echo y | git add -p non-empty && + git diff --cached >diff && + test_cmp expected diff +' + +cat >expected <<EOF +diff --git a/empty b/empty +deleted file mode 100644 +index e69de29..0000000 +EOF + +test_expect_success 'deleting an empty file' ' + git reset --hard && + > empty && + git add empty && + git commit -m empty && + rm empty && + echo y | git add -p empty && + git diff --cached >diff && + test_cmp expected diff +' + +test_done diff --git a/t/t3702-add-edit.sh b/t/t3702-add-edit.sh new file mode 100755 index 0000000000..4ee47cc9a8 --- /dev/null +++ b/t/t3702-add-edit.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='add -e basic tests' +. ./test-lib.sh + + +cat > file << EOF +LO, praise of the prowess of people-kings +of spear-armed Danes, in days long sped, +we have heard, and what honor the athelings won! +Oft Scyld the Scefing from squadroned foes, +from many a tribe, the mead-bench tore, +awing the earls. Since erst he lay +friendless, a foundling, fate repaid him: +for he waxed under welkin, in wealth he throve, +till before him the folk, both far and near, +who house by the whale-path, heard his mandate, +gave him gifts: a good king he! +EOF + +cat > second-part << EOF +To him an heir was afterward born, +a son in his halls, whom heaven sent +to favor the folk, feeling their woe +that erst they had lacked an earl for leader +so long a while; the Lord endowed him, +the Wielder of Wonder, with world's renown. +EOF + +test_expect_success 'setup' ' + + git add file && + test_tick && + git commit -m initial file + +' + +cat > expected-patch << EOF +diff --git a/file b/file +index b9834b5..9020acb 100644 +--- a/file ++++ b/file +@@ -1,11 +1,6 @@ +-LO, praise of the prowess of people-kings +-of spear-armed Danes, in days long sped, +-we have heard, and what honor the athelings won! +-Oft Scyld the Scefing from squadroned foes, +-from many a tribe, the mead-bench tore, +-awing the earls. Since erst he lay +-friendless, a foundling, fate repaid him: +-for he waxed under welkin, in wealth he throve, +-till before him the folk, both far and near, +-who house by the whale-path, heard his mandate, +-gave him gifts: a good king he! ++To him an heir was afterward born, ++a son in his halls, whom heaven sent ++to favor the folk, feeling their woe ++that erst they had lacked an earl for leader ++so long a while; the Lord endowed him, ++the Wielder of Wonder, with world's renown. +EOF + +cat > patch << EOF +diff --git a/file b/file +index b9834b5..ef6e94c 100644 +--- a/file ++++ b/file +@@ -3,1 +3,333 @@ of spear-armed Danes, in days long sped, + we have heard, and what honor the athelings won! ++ + Oft Scyld the Scefing from squadroned foes, +@@ -2,7 +1,5 @@ awing the earls. Since erst he lay + friendless, a foundling, fate repaid him: ++ + for he waxed under welkin, in wealth he throve, +EOF + +cat > expected << EOF +diff --git a/file b/file +index b9834b5..ef6e94c 100644 +--- a/file ++++ b/file +@@ -1,10 +1,12 @@ + LO, praise of the prowess of people-kings + of spear-armed Danes, in days long sped, + we have heard, and what honor the athelings won! ++ + Oft Scyld the Scefing from squadroned foes, + from many a tribe, the mead-bench tore, + awing the earls. Since erst he lay + friendless, a foundling, fate repaid him: ++ + for he waxed under welkin, in wealth he throve, + till before him the folk, both far and near, + who house by the whale-path, heard his mandate, +EOF + +echo "#!$SHELL_PATH" >fake-editor.sh +cat >> fake-editor.sh <<\EOF +mv -f "$1" orig-patch && +mv -f patch "$1" +EOF + +test_set_editor "$(pwd)/fake-editor.sh" +chmod a+x fake-editor.sh + +test_expect_success 'add -e' ' + + cp second-part file && + git add -e && + test_cmp second-part file && + test_cmp orig-patch expected-patch && + git diff --cached > out && + test_cmp out expected + +' + +test_done diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index 7c7e4335d6..8eb47942e2 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -2,7 +2,7 @@ # # -test_description='git-mktag: tag object verify test' +test_description='git mktag: tag object verify test' . ./test-lib.sh @@ -12,19 +12,22 @@ test_description='git-mktag: tag object verify test' # given in the expect.pat file. check_verify_failure () { - test_expect_success \ - "$1" \ - 'git-mktag <tag.sig 2>message || - egrep -q -f expect.pat message' + expect="$2" + test_expect_success "$1" ' + ( test_must_fail git mktag <tag.sig 2>message ) && + grep "$expect" message + ' } ########################################################### # first create a commit, so we have a valid object/type # for the tag. -echo Hello >A -git-update-index --add A -git-commit -m "Initial commit" -head=$(git-rev-parse --verify HEAD) +test_expect_success 'setup' ' + echo Hello >A && + git update-index --add A && + git commit -m "Initial commit" && + head=$(git rev-parse --verify HEAD) +' ############################################################ # 1. length check @@ -33,11 +36,8 @@ cat >tag.sig <<EOF too short for a tag EOF -cat >expect.pat <<EOF -^error: .*size wrong.*$ -EOF - -check_verify_failure 'Tag object length check' +check_verify_failure 'Tag object length check' \ + '^error: .*size wrong.*$' ############################################################ # 2. object line label check @@ -46,13 +46,11 @@ cat >tag.sig <<EOF xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895 type tag tag mytag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char0: .*"object "$ EOF -check_verify_failure '"object" line label check' +check_verify_failure '"object" line label check' '^error: char0: .*"object "$' ############################################################ # 3. object line SHA1 check @@ -61,13 +59,11 @@ cat >tag.sig <<EOF object zz9e9b33986b1c2670fff52c5067603117b3e895 type tag tag mytag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char7: .*SHA1 hash$ EOF -check_verify_failure '"object" line SHA1 check' +check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$' ############################################################ # 4. type line label check @@ -76,13 +72,11 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 xxxx tag tag mytag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char47: .*"[\]ntype "$ EOF -check_verify_failure '"type" line label check' +check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$' ############################################################ # 5. type line eol check @@ -90,11 +84,7 @@ check_verify_failure '"type" line label check' echo "object 779e9b33986b1c2670fff52c5067603117b3e895" >tag.sig printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig -cat >expect.pat <<EOF -^error: char48: .*"[\]n"$ -EOF - -check_verify_failure '"type" line eol check' +check_verify_failure '"type" line eol check' '^error: char48: .*"\\n"$' ############################################################ # 6. tag line label check #1 @@ -103,13 +93,12 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 type tag xxx mytag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char57: no "tag " found$ EOF -check_verify_failure '"tag" line label check #1' +check_verify_failure '"tag" line label check #1' \ + '^error: char57: no "tag " found$' ############################################################ # 7. tag line label check #2 @@ -120,11 +109,8 @@ type taggggggggggggggggggggggggggggggg tag EOF -cat >expect.pat <<EOF -^error: char87: no "tag " found$ -EOF - -check_verify_failure '"tag" line label check #2' +check_verify_failure '"tag" line label check #2' \ + '^error: char87: no "tag " found$' ############################################################ # 8. type line type-name length check @@ -135,11 +121,8 @@ type taggggggggggggggggggggggggggggggg tag mytag EOF -cat >expect.pat <<EOF -^error: char53: type too long$ -EOF - -check_verify_failure '"type" line type-name length check' +check_verify_failure '"type" line type-name length check' \ + '^error: char53: type too long$' ############################################################ # 9. verify object (SHA1/type) check @@ -148,13 +131,12 @@ cat >tag.sig <<EOF object 779e9b33986b1c2670fff52c5067603117b3e895 type tagggg tag mytag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char7: could not verify object.*$ EOF -check_verify_failure 'verify object (SHA1/type) check' +check_verify_failure 'verify object (SHA1/type) check' \ + '^error: char7: could not verify object.*$' ############################################################ # 10. verify tag-name check @@ -163,13 +145,12 @@ cat >tag.sig <<EOF object $head type commit tag my tag -EOF +tagger . <> 0 +0000 -cat >expect.pat <<EOF -^error: char67: could not verify tag name$ EOF -check_verify_failure 'verify tag-name check' +check_verify_failure 'verify tag-name check' \ + '^error: char67: could not verify tag name$' ############################################################ # 11. tagger line label check #1 @@ -178,13 +159,12 @@ cat >tag.sig <<EOF object $head type commit tag mytag -EOF -cat >expect.pat <<EOF -^error: char70: could not find "tagger"$ +This is filler EOF -check_verify_failure '"tagger" line label check #1' +check_verify_failure '"tagger" line label check #1' \ + '^error: char70: could not find "tagger "$' ############################################################ # 12. tagger line label check #2 @@ -194,34 +174,192 @@ object $head type commit tag mytag tagger + +This is filler EOF -cat >expect.pat <<EOF -^error: char70: could not find "tagger"$ +check_verify_failure '"tagger" line label check #2' \ + '^error: char70: could not find "tagger "$' + +############################################################ +# 13. disallow missing tag author name + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger <> 0 +0000 + +This is filler EOF -check_verify_failure '"tagger" line label check #2' +check_verify_failure 'disallow missing tag author name' \ + '^error: char77: missing tagger name$' ############################################################ -# 13. create valid tag +# 14. disallow missing tag author name cat >tag.sig <<EOF object $head type commit tag mytag -tagger another@example.com +tagger T A Gger < + > 0 +0000 + +EOF + +check_verify_failure 'disallow malformed tagger' \ + '^error: char77: malformed tagger field$' + +############################################################ +# 15. allow empty tag email + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <> 0 +0000 + +EOF + +test_expect_success \ + 'allow empty tag email' \ + 'git mktag <tag.sig >.git/refs/tags/mytag 2>message' + +############################################################ +# 16. disallow spaces in tag email + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tag ger@example.com> 0 +0000 + +EOF + +check_verify_failure 'disallow spaces in tag email' \ + '^error: char77: malformed tagger field$' + +############################################################ +# 17. disallow missing tag timestamp + +tr '_' ' ' >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com>__ + +EOF + +check_verify_failure 'disallow missing tag timestamp' \ + '^error: char107: missing tag timestamp$' + +############################################################ +# 18. detect invalid tag timestamp1 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008 + +EOF + +check_verify_failure 'detect invalid tag timestamp1' \ + '^error: char107: missing tag timestamp$' + +############################################################ +# 19. detect invalid tag timestamp2 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500 + +EOF + +check_verify_failure 'detect invalid tag timestamp2' \ + '^error: char111: malformed tag timestamp$' + +############################################################ +# 20. detect invalid tag timezone1 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 GMT + +EOF + +check_verify_failure 'detect invalid tag timezone1' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 21. detect invalid tag timezone2 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 + 30 + +EOF + +check_verify_failure 'detect invalid tag timezone2' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 22. detect invalid tag timezone3 + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -1430 + +EOF + +check_verify_failure 'detect invalid tag timezone3' \ + '^error: char118: malformed tag timezone$' + +############################################################ +# 23. detect invalid header entry + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -0500 +this line should not be here + +EOF + +check_verify_failure 'detect invalid header entry' \ + '^error: char124: trailing garbage in tag header$' + +############################################################ +# 24. create valid tag + +cat >tag.sig <<EOF +object $head +type commit +tag mytag +tagger T A Gger <tagger@example.com> 1206478233 -0500 + EOF test_expect_success \ 'create valid tag' \ - 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message' + 'git mktag <tag.sig >.git/refs/tags/mytag 2>message' ############################################################ -# 14. check mytag +# 25. check mytag test_expect_success \ 'check mytag' \ - 'git-tag -l | grep mytag' + 'git tag -l | grep mytag' test_done diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index e54fe0f401..256c4c9701 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -8,68 +8,76 @@ test_description='commit and log output encodings' . ./test-lib.sh compare_with () { - git-show -s $1 | sed -e '1,/^$/d' -e 's/^ //' -e '$d' >current && - diff -u current "$2" + git show -s $1 | sed -e '1,/^$/d' -e 's/^ //' >current && + case "$3" in + '') + test_cmp "$2" current ;; + ?*) + iconv -f "$3" -t UTF-8 >current.utf8 <current && + iconv -f "$3" -t UTF-8 >expect.utf8 <"$2" && + test_cmp expect.utf8 current.utf8 + ;; + esac } test_expect_success setup ' : >F && - git-add F && - T=$(git-write-tree) && - C=$(git-commit-tree $T <../t3900/1-UTF-8.txt) && - git-update-ref HEAD $C && - git-tag C0 + git add F && + T=$(git write-tree) && + C=$(git commit-tree $T <"$TEST_DIRECTORY"/t3900/1-UTF-8.txt) && + git update-ref HEAD $C && + git tag C0 ' test_expect_success 'no encoding header for base case' ' - E=$(git-cat-file commit C0 | sed -ne "s/^encoding //p") && + E=$(git cat-file commit C0 | sed -ne "s/^encoding //p") && test z = "z$E" ' -for H in ISO-8859-1 EUCJP ISO-2022-JP +for H in ISO8859-1 eucJP ISO-2022-JP do test_expect_success "$H setup" ' - git-config i18n.commitencoding $H && - git-checkout -b $H C0 && + git config i18n.commitencoding $H && + git checkout -b $H C0 && echo $H >F && - git-commit -a -F ../t3900/$H.txt + git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt ' done -for H in ISO-8859-1 EUCJP ISO-2022-JP +for H in ISO8859-1 eucJP ISO-2022-JP do test_expect_success "check encoding header for $H" ' - E=$(git-cat-file commit '$H' | sed -ne "s/^encoding //p") && + E=$(git cat-file commit '$H' | sed -ne "s/^encoding //p") && test "z$E" = "z'$H'" ' done test_expect_success 'config to remove customization' ' - git-config --unset-all i18n.commitencoding && - if Z=$(git-config --get-all i18n.commitencoding) + git config --unset-all i18n.commitencoding && + if Z=$(git config --get-all i18n.commitencoding) then echo Oops, should have failed. false else test z = "z$Z" fi && - git-config i18n.commitencoding utf-8 + git config i18n.commitencoding UTF-8 ' -test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' ' - compare_with ISO-8859-1 ../t3900/1-UTF-8.txt +test_expect_success 'ISO8859-1 should be shown in UTF-8 now' ' + compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt ' -for H in EUCJP ISO-2022-JP +for H in eucJP ISO-2022-JP do test_expect_success "$H should be shown in UTF-8 now" ' - compare_with '$H' ../t3900/2-UTF-8.txt + compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt ' done test_expect_success 'config to add customization' ' - git-config --unset-all i18n.commitencoding && - if Z=$(git-config --get-all i18n.commitencoding) + git config --unset-all i18n.commitencoding && + if Z=$(git config --get-all i18n.commitencoding) then echo Oops, should have failed. false @@ -78,44 +86,50 @@ test_expect_success 'config to add customization' ' fi ' -for H in ISO-8859-1 EUCJP ISO-2022-JP +for H in ISO8859-1 eucJP ISO-2022-JP do test_expect_success "$H should be shown in itself now" ' - git-config i18n.commitencoding '$H' && - compare_with '$H' ../t3900/'$H'.txt + git config i18n.commitencoding '$H' && + compare_with '$H' "$TEST_DIRECTORY"/t3900/'$H'.txt ' done test_expect_success 'config to tweak customization' ' - git-config i18n.logoutputencoding utf-8 + git config i18n.logoutputencoding UTF-8 ' -test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' ' - compare_with ISO-8859-1 ../t3900/1-UTF-8.txt +test_expect_success 'ISO8859-1 should be shown in UTF-8 now' ' + compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt ' -for H in EUCJP ISO-2022-JP +for H in eucJP ISO-2022-JP do test_expect_success "$H should be shown in UTF-8 now" ' - compare_with '$H' ../t3900/2-UTF-8.txt + compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt ' done -for J in EUCJP ISO-2022-JP +for J in eucJP ISO-2022-JP do - git-config i18n.logoutputencoding $J - for H in EUCJP ISO-2022-JP + if test "$J" = ISO-2022-JP + then + ICONV=$J + else + ICONV= + fi + git config i18n.logoutputencoding $J + for H in eucJP ISO-2022-JP do test_expect_success "$H should be shown in $J now" ' - compare_with '$H' ../t3900/'$J'.txt + compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt $ICONV ' done done -for H in ISO-8859-1 EUCJP ISO-2022-JP +for H in ISO8859-1 eucJP ISO-2022-JP do test_expect_success "No conversion with $H" ' - compare_with "--encoding=none '$H'" ../t3900/'$H'.txt + compare_with "--encoding=none '$H'" "$TEST_DIRECTORY"/t3900/'$H'.txt ' done diff --git a/t/t3900/ISO-8859-1.txt b/t/t3900/ISO8859-1.txt index 7cbef0ee6f..7cbef0ee6f 100644 --- a/t/t3900/ISO-8859-1.txt +++ b/t/t3900/ISO8859-1.txt diff --git a/t/t3900/EUCJP.txt b/t/t3900/eucJP.txt index 546f2aac01..546f2aac01 100644 --- a/t/t3900/EUCJP.txt +++ b/t/t3900/eucJP.txt diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh index a881797bc7..31a5770b34 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -13,13 +13,13 @@ check_encoding () { while test "$i" -le $cnt do git format-patch --encoding=UTF-8 --stdout HEAD~$i..HEAD~$j | - grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD_=C3=B3=C3=BA?=" && - git-cat-file commit HEAD~$j | + grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD=20=C3=B3=C3=BA?=" && + git cat-file commit HEAD~$j | case "$header" in 8859) - grep "^encoding ISO-8859-1" ;; + grep "^encoding ISO8859-1" ;; *) - ! grep "^encoding ISO-8859-1" ;; + grep "^encoding ISO8859-1"; test "$?" != 0 ;; esac || { bad=1 break @@ -31,11 +31,11 @@ check_encoding () { } test_expect_success setup ' - git-config i18n.commitencoding UTF-8 && + git config i18n.commitencoding UTF-8 && # use UTF-8 in author and committer name to match the # i18n.commitencoding settings - . ../t3901-utf8.txt && + . "$TEST_DIRECTORY"/t3901-utf8.txt && test_tick && echo "$GIT_AUTHOR_NAME" >mine && @@ -55,27 +55,27 @@ test_expect_success setup ' git commit -s -m "Second on side" && # the second one on the side branch is ISO-8859-1 - git-config i18n.commitencoding ISO-8859-1 && + git config i18n.commitencoding ISO8859-1 && # use author and committer name in ISO-8859-1 to match it. - . ../t3901-8859-1.txt && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && test_tick && echo Yet another >theirs && git add theirs && git commit -s -m "Third on side" && # Back to default - git-config i18n.commitencoding UTF-8 + git config i18n.commitencoding UTF-8 ' test_expect_success 'format-patch output (ISO-8859-1)' ' - git-config i18n.logoutputencoding ISO-8859-1 && + git config i18n.logoutputencoding ISO8859-1 && git format-patch --stdout master..HEAD^ >out-l1 && git format-patch --stdout HEAD^ >out-l2 && - grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l1 && - grep "^From: =?ISO-8859-1?q?=C1=E9=ED_=F3=FA?=" out-l1 && - grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l2 && - grep "^From: =?ISO-8859-1?q?=C1=E9=ED_=F3=FA?=" out-l2 + grep "^Content-Type: text/plain; charset=ISO8859-1" out-l1 && + grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l1 && + grep "^Content-Type: text/plain; charset=ISO8859-1" out-l2 && + grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l2 ' test_expect_success 'format-patch output (UTF-8)' ' @@ -84,14 +84,14 @@ test_expect_success 'format-patch output (UTF-8)' ' git format-patch --stdout master..HEAD^ >out-u1 && git format-patch --stdout HEAD^ >out-u2 && grep "^Content-Type: text/plain; charset=UTF-8" out-u1 && - grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD_=C3=B3=C3=BA?=" out-u1 && + grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD=20=C3=B3=C3=BA?=" out-u1 && grep "^Content-Type: text/plain; charset=UTF-8" out-u2 && - grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD_=C3=B3=C3=BA?=" out-u2 + grep "^From: =?UTF-8?q?=C3=81=C3=A9=C3=AD=20=C3=B3=C3=BA?=" out-u2 ' test_expect_success 'rebase (U/U)' ' # We want the result of rebase in UTF-8 - git-config i18n.commitencoding UTF-8 && + git config i18n.commitencoding UTF-8 && # The test is about logoutputencoding not affecting the # final outcome -- it is used internally to generate the @@ -101,32 +101,32 @@ test_expect_success 'rebase (U/U)' ' # The result will be committed by GIT_COMMITTER_NAME -- # we want UTF-8 encoded name. - . ../t3901-utf8.txt && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git checkout -b test && - git-rebase master && + git rebase master && check_encoding 2 ' test_expect_success 'rebase (U/L)' ' - git-config i18n.commitencoding UTF-8 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-utf8.txt && + git config i18n.commitencoding UTF-8 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard side && - git-rebase master && + git rebase master && check_encoding 2 ' test_expect_success 'rebase (L/L)' ' # In this test we want ISO-8859-1 encoded commits as the result - git-config i18n.commitencoding ISO-8859-1 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-8859-1.txt && + git config i18n.commitencoding ISO8859-1 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard side && - git-rebase master && + git rebase master && check_encoding 2 8859 ' @@ -134,12 +134,12 @@ test_expect_success 'rebase (L/L)' ' test_expect_success 'rebase (L/U)' ' # This is pathological -- use UTF-8 as intermediate form # to get ISO-8859-1 results. - git-config i18n.commitencoding ISO-8859-1 && + git config i18n.commitencoding ISO8859-1 && git config i18n.logoutputencoding UTF-8 && - . ../t3901-8859-1.txt && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard side && - git-rebase master && + git rebase master && check_encoding 2 8859 ' @@ -147,14 +147,14 @@ test_expect_success 'rebase (L/U)' ' test_expect_success 'cherry-pick(U/U)' ' # Both the commitencoding and logoutputencoding is set to UTF-8. - git-config i18n.commitencoding UTF-8 && + git config i18n.commitencoding UTF-8 && git config i18n.logoutputencoding UTF-8 && - . ../t3901-utf8.txt && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 ' @@ -162,14 +162,14 @@ test_expect_success 'cherry-pick(U/U)' ' test_expect_success 'cherry-pick(L/L)' ' # Both the commitencoding and logoutputencoding is set to ISO-8859-1 - git-config i18n.commitencoding ISO-8859-1 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-8859-1.txt && + git config i18n.commitencoding ISO8859-1 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 8859 ' @@ -177,14 +177,14 @@ test_expect_success 'cherry-pick(L/L)' ' test_expect_success 'cherry-pick(U/L)' ' # Commitencoding is set to UTF-8 but logoutputencoding is ISO-8859-1 - git-config i18n.commitencoding UTF-8 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-utf8.txt && + git config i18n.commitencoding UTF-8 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 ' @@ -193,48 +193,48 @@ test_expect_success 'cherry-pick(L/U)' ' # Again, the commitencoding is set to ISO-8859-1 but # logoutputencoding is set to UTF-8. - git-config i18n.commitencoding ISO-8859-1 && + git config i18n.commitencoding ISO8859-1 && git config i18n.logoutputencoding UTF-8 && - . ../t3901-8859-1.txt && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 8859 ' test_expect_success 'rebase --merge (U/U)' ' - git-config i18n.commitencoding UTF-8 && + git config i18n.commitencoding UTF-8 && git config i18n.logoutputencoding UTF-8 && - . ../t3901-utf8.txt && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard side && - git-rebase --merge master && + git rebase --merge master && check_encoding 2 ' test_expect_success 'rebase --merge (U/L)' ' - git-config i18n.commitencoding UTF-8 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-utf8.txt && + git config i18n.commitencoding UTF-8 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard side && - git-rebase --merge master && + git rebase --merge master && check_encoding 2 ' test_expect_success 'rebase --merge (L/L)' ' # In this test we want ISO-8859-1 encoded commits as the result - git-config i18n.commitencoding ISO-8859-1 && - git config i18n.logoutputencoding ISO-8859-1 && - . ../t3901-8859-1.txt && + git config i18n.commitencoding ISO8859-1 && + git config i18n.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard side && - git-rebase --merge master && + git rebase --merge master && check_encoding 2 8859 ' @@ -242,12 +242,12 @@ test_expect_success 'rebase --merge (L/L)' ' test_expect_success 'rebase --merge (L/U)' ' # This is pathological -- use UTF-8 as intermediate form # to get ISO-8859-1 results. - git-config i18n.commitencoding ISO-8859-1 && + git config i18n.commitencoding ISO8859-1 && git config i18n.logoutputencoding UTF-8 && - . ../t3901-8859-1.txt && + . "$TEST_DIRECTORY"/t3901-8859-1.txt && git reset --hard side && - git-rebase --merge master && + git rebase --merge master && check_encoding 2 8859 ' diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh new file mode 100755 index 0000000000..147e634cd6 --- /dev/null +++ b/t/t3902-quoted.sh @@ -0,0 +1,150 @@ +#!/bin/sh +# +# Copyright (c) 2006 Junio C Hamano +# + +test_description='quoted output' + +. ./test-lib.sh + +FN='濱野' +GN='ç´”' +HT=' ' +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 + skip_all='Your filesystem does not allow tabs in filenames, test skipped.' + test_done +} + +for_each_name () { + for name in \ + Name "Name and a${LF}LF" "Name and an${HT}HT" "Name${DQ}" \ + "$FN$HT$GN" "$FN$LF$GN" "$FN $GN" "$FN$GN" "$FN$DQ$GN" \ + "With SP in it" "$FN/file" + do + eval "$1" + done +} + +test_expect_success setup ' + + mkdir "$FN" && + for_each_name "echo initial >\"\$name\"" + git add . && + git commit -q -m Initial && + + for_each_name "echo second >\"\$name\"" && + git commit -a -m Second + + for_each_name "echo modified >\"\$name\"" + +' + +cat >expect.quoted <<\EOF +Name +"Name and a\nLF" +"Name and an\tHT" +"Name\"" +With SP in it +"\346\277\261\351\207\216\t\347\264\224" +"\346\277\261\351\207\216\n\347\264\224" +"\346\277\261\351\207\216 \347\264\224" +"\346\277\261\351\207\216\"\347\264\224" +"\346\277\261\351\207\216/file" +"\346\277\261\351\207\216\347\264\224" +EOF + +cat >expect.raw <<\EOF +Name +"Name and a\nLF" +"Name and an\tHT" +"Name\"" +With SP in it +"濱野\tç´”" +"濱野\nç´”" +濱野 ç´” +"濱野\"ç´”" +濱野/file +濱野純 +EOF + +test_expect_success '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' ' + + git diff --name-only >current && + test_cmp expect.quoted current + +' + +test_expect_success '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' ' + + git diff --name-only HEAD^ HEAD >current && + test_cmp expect.quoted current + +' + +test_expect_success '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' ' + + git config --bool core.quotepath false + +' + +test_expect_success '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' ' + + git diff --name-only >current && + test_cmp expect.raw current + +' + +test_expect_success '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' ' + + git diff --name-only HEAD^ HEAD >current && + test_cmp expect.raw current + +' + +test_expect_success 'check fully quoted output from ls-tree' ' + + git ls-tree --name-only -r HEAD >current && + test_cmp expect.raw current + +' + +test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh new file mode 100755 index 0000000000..62e208aadd --- /dev/null +++ b/t/t3903-stash.sh @@ -0,0 +1,381 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E Schindelin +# + +test_description='Test git stash' + +. ./test-lib.sh + +test_expect_success 'stash some dirty working directory' ' + echo 1 > file && + git add file && + test_tick && + git commit -m initial && + echo 2 > file && + git add file && + echo 3 > file && + test_tick && + git stash && + git diff-files --quiet && + git diff-index --cached --quiet HEAD +' + +cat > expect << EOF +diff --git a/file b/file +index 0cfbf08..00750ed 100644 +--- a/file ++++ b/file +@@ -1 +1 @@ +-2 ++3 +EOF + +test_expect_success 'parents of stash' ' + test $(git rev-parse stash^) = $(git rev-parse HEAD) && + git diff stash^2..stash > output && + test_cmp output expect +' + +test_expect_success 'apply needs clean working directory' ' + echo 4 > other-file && + git add other-file && + echo 5 > other-file && + test_must_fail git stash apply +' + +test_expect_success 'apply stashed changes' ' + git add other-file && + test_tick && + git commit -m other-file && + git stash apply && + test 3 = $(cat file) && + test 1 = $(git show :file) && + test 1 = $(git show HEAD:file) +' + +test_expect_success 'apply stashed changes (including index)' ' + git reset --hard HEAD^ && + echo 6 > other-file && + git add other-file && + test_tick && + git commit -m other-file && + git stash apply --index && + test 3 = $(cat file) && + test 2 = $(git show :file) && + test 1 = $(git show HEAD:file) +' + +test_expect_success 'unstashing in a subdirectory' ' + git reset --hard HEAD && + mkdir subdir && + cd subdir && + git stash apply && + cd .. +' + +test_expect_success 'drop top stash' ' + git reset --hard && + git stash list > stashlist1 && + echo 7 > file && + git stash && + git stash drop && + git stash list > stashlist2 && + test_cmp stashlist1 stashlist2 && + git stash apply && + test 3 = $(cat file) && + test 1 = $(git show :file) && + test 1 = $(git show HEAD:file) +' + +test_expect_success 'drop middle stash' ' + git reset --hard && + echo 8 > file && + git stash && + echo 9 > file && + git stash && + git stash drop stash@{1} && + test 2 = $(git stash list | wc -l) && + git stash apply && + test 9 = $(cat file) && + test 1 = $(git show :file) && + test 1 = $(git show HEAD:file) && + git reset --hard && + git stash drop && + git stash apply && + test 3 = $(cat file) && + test 1 = $(git show :file) && + test 1 = $(git show HEAD:file) +' + +test_expect_success 'stash pop' ' + git reset --hard && + git stash pop && + test 3 = $(cat file) && + test 1 = $(git show :file) && + test 1 = $(git show HEAD:file) && + test 0 = $(git stash list | wc -l) +' + +cat > expect << EOF +diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..1fe912c +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++bar2 +EOF + +cat > expect1 << EOF +diff --git a/file b/file +index 257cc56..5716ca5 100644 +--- a/file ++++ b/file +@@ -1 +1 @@ +-foo ++bar +EOF + +cat > expect2 << EOF +diff --git a/file b/file +index 7601807..5716ca5 100644 +--- a/file ++++ b/file +@@ -1 +1 @@ +-baz ++bar +diff --git a/file2 b/file2 +new file mode 100644 +index 0000000..1fe912c +--- /dev/null ++++ b/file2 +@@ -0,0 +1 @@ ++bar2 +EOF + +test_expect_success 'stash branch' ' + echo foo > file && + git commit file -m first + echo bar > file && + echo bar2 > file2 && + git add file2 && + git stash && + echo baz > file && + git commit file -m second && + git stash branch stashbranch && + test refs/heads/stashbranch = $(git symbolic-ref HEAD) && + test $(git rev-parse HEAD) = $(git rev-parse master^) && + git diff --cached > output && + test_cmp output expect && + git diff > output && + test_cmp output expect1 && + git add file && + git commit -m alternate\ second && + git diff master..stashbranch > output && + test_cmp output expect2 && + test 0 = $(git stash list | wc -l) +' + +test_expect_success 'apply -q is quiet' ' + echo foo > file && + git stash && + git stash apply -q > output.out 2>&1 && + test ! -s output.out +' + +test_expect_success 'save -q is quiet' ' + git stash save --quiet > output.out 2>&1 && + test ! -s output.out +' + +test_expect_success 'pop -q is quiet' ' + git stash pop -q > output.out 2>&1 && + test ! -s output.out +' + +test_expect_success 'pop -q --index works and is quiet' ' + echo foo > file && + git add file && + git stash save --quiet && + git stash pop -q --index > output.out 2>&1 && + test foo = "$(git show :file)" && + test ! -s output.out +' + +test_expect_success 'drop -q is quiet' ' + git stash && + git stash drop -q > output.out 2>&1 && + test ! -s output.out +' + +test_expect_success 'stash -k' ' + echo bar3 > file && + echo bar4 > file2 && + git add file2 && + git stash -k && + test bar,bar4 = $(cat file),$(cat file2) +' + +test_expect_success 'stash --invalid-option' ' + echo bar5 > file && + echo bar6 > file2 && + git add file2 && + test_must_fail git stash --invalid-option && + test_must_fail git stash save --invalid-option && + test bar5,bar6 = $(cat file),$(cat file2) && + git stash -- -message-starting-with-dash && + 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_done diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh new file mode 100755 index 0000000000..f37e3bc6ec --- /dev/null +++ b/t/t3904-stash-patch.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='git checkout --patch' +. ./lib-patch-mode.sh + +test_expect_success 'setup' ' + mkdir dir && + echo parent > dir/foo && + echo dummy > bar && + git add bar dir/foo && + git commit -m initial && + test_tick && + test_commit second dir/foo head && + echo index > dir/foo && + git add dir/foo && + set_and_save_state bar bar_work bar_index && + save_head +' + +# note: bar sorts before dir, so the first 'n' is always to skip 'bar' + +test_expect_success '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' ' + (echo n; echo y) | git stash save -p && + verify_state dir/foo head index && + verify_saved_state bar && + git reset --hard && + git stash apply && + verify_state dir/foo work head && + verify_state bar dummy dummy +' + +test_expect_success '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 && + verify_state dir/foo head head && + verify_state bar bar_work dummy && + git reset --hard && + git stash apply --index && + verify_state dir/foo work index && + verify_state bar dummy bar_index +' + +test_expect_success 'none of this moved HEAD' ' + verify_saved_head +' + +test_done diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index 9c58d77cc2..6ddd46915d 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -7,7 +7,7 @@ test_description='Test built-in diff output engine. ' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh echo >path0 'Line 1 Line 2 @@ -16,16 +16,16 @@ cat path0 >path1 chmod +x path1 test_expect_success \ - 'update-cache --add two files with and without +x.' \ - 'git-update-index --add path0 path1' + 'update-index --add two files with and without +x.' \ + 'git update-index --add path0 path1' mv path0 path0- sed -e 's/line/Line/' <path0- >path0 chmod +x path0 rm -f path1 test_expect_success \ - 'git-diff-files -p after editing work tree.' \ - 'git-diff-files -p >current' + 'git diff-files -p after editing work tree.' \ + 'git diff-files -p >current' # that's as far as it comes if [ "$(git config --get core.filemode)" = false ] @@ -56,7 +56,7 @@ deleted file mode 100755 EOF test_expect_success \ - 'validate git-diff-files -p output.' \ + 'validate git diff-files -p output.' \ 'compare_diff_patch current expected' test_done diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 2e3c20d6b9..71bac83dd5 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -7,7 +7,7 @@ test_description='Test rename detection in diff engine. ' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh echo >path0 'Line 1 Line 2 @@ -27,22 +27,22 @@ Line 15 ' test_expect_success \ - 'update-cache --add a file.' \ - 'git-update-index --add path0' + 'update-index --add a file.' \ + 'git update-index --add path0' test_expect_success \ 'write that tree.' \ - 'tree=$(git-write-tree) && echo $tree' + 'tree=$(git write-tree) && echo $tree' sed -e 's/line/Line/' <path0 >path1 rm -f path0 test_expect_success \ 'renamed and edited the file.' \ - 'git-update-index --add --remove path0 path1' + 'git update-index --add --remove path0 path1' test_expect_success \ - 'git-diff-index -p -M after rename and editing.' \ - 'git-diff-index -p -M $tree >current' + 'git diff-index -p -M after rename and editing.' \ + 'git diff-index -p -M $tree >current' cat >expected <<\EOF diff --git a/path0 b/path1 rename from path0 @@ -64,4 +64,17 @@ test_expect_success \ 'validate the output.' \ 'compare_diff_patch current expected' +test_expect_success 'favour same basenames over different ones' ' + cp path1 another-path && + git add another-path && + git commit -m 1 && + git rm path1 && + mkdir subdir && + git mv another-path subdir/path1 && + git status | grep "renamed: .*path1 -> subdir/path1"' + +test_expect_success 'favour same basenames even with minor differences' ' + git show HEAD:path1 | sed "s/15/16/" > subdir/path1 && + git status | grep "renamed: .*path1 -> subdir/path1"' + test_done diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index 56eda63fc2..73441a5165 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -7,7 +7,7 @@ test_description='Test diff raw-output. ' . ./test-lib.sh -. ../lib-read-tree-m-3way.sh +. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh cat >.test-plain-OA <<\EOF :000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA @@ -135,85 +135,99 @@ 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-tree of known trees.' \ - 'git-diff-tree $tree_O $tree_A >.test-a && + 'git diff-tree $tree_O $tree_A >.test-a && cmp -s .test-a .test-plain-OA' test_expect_success \ 'diff-tree of known trees.' \ - 'git-diff-tree -r $tree_O $tree_A >.test-a && + 'git diff-tree -r $tree_O $tree_A >.test-a && cmp -s .test-a .test-recursive-OA' test_expect_success \ 'diff-tree of known trees.' \ - 'git-diff-tree $tree_O $tree_B >.test-a && + 'git diff-tree $tree_O $tree_B >.test-a && cmp -s .test-a .test-plain-OB' test_expect_success \ 'diff-tree of known trees.' \ - 'git-diff-tree -r $tree_O $tree_B >.test-a && + 'git diff-tree -r $tree_O $tree_B >.test-a && cmp -s .test-a .test-recursive-OB' test_expect_success \ 'diff-tree of known trees.' \ - 'git-diff-tree $tree_A $tree_B >.test-a && + 'git diff-tree $tree_A $tree_B >.test-a && cmp -s .test-a .test-plain-AB' test_expect_success \ 'diff-tree of known trees.' \ - 'git-diff-tree -r $tree_A $tree_B >.test-a && + 'git diff-tree -r $tree_A $tree_B >.test-a && cmp -s .test-a .test-recursive-AB' test_expect_success \ + 'diff-tree --stdin of known trees.' \ + 'echo $tree_A $tree_B | git diff-tree --stdin > .test-a && + echo $tree_A $tree_B > .test-plain-ABx && + cat .test-plain-AB >> .test-plain-ABx && + cmp -s .test-a .test-plain-ABx' + +test_expect_success \ + 'diff-tree --stdin of known trees.' \ + 'echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a && + echo $tree_A $tree_B > .test-recursive-ABx && + cat .test-recursive-AB >> .test-recursive-ABx && + cmp -s .test-a .test-recursive-ABx' + +test_expect_success \ 'diff-cache O with A in cache' \ - 'git-read-tree $tree_A && - git-diff-index --cached $tree_O >.test-a && + 'git read-tree $tree_A && + git diff-index --cached $tree_O >.test-a && cmp -s .test-a .test-recursive-OA' test_expect_success \ 'diff-cache O with B in cache' \ - 'git-read-tree $tree_B && - git-diff-index --cached $tree_O >.test-a && + 'git read-tree $tree_B && + git diff-index --cached $tree_O >.test-a && cmp -s .test-a .test-recursive-OB' test_expect_success \ 'diff-cache A with B in cache' \ - 'git-read-tree $tree_B && - git-diff-index --cached $tree_A >.test-a && + 'git read-tree $tree_B && + git diff-index --cached $tree_A >.test-a && cmp -s .test-a .test-recursive-AB' test_expect_success \ 'diff-files with O in cache and A checked out' \ 'rm -fr Z [A-Z][A-Z] && - git-read-tree $tree_A && - git-checkout-index -f -a && - git-read-tree --reset $tree_O || return 1 - git-update-index --refresh >/dev/null ;# this can exit non-zero - git-diff-files >.test-a && + git read-tree $tree_A && + git checkout-index -f -a && + git read-tree --reset $tree_O || return 1 + git update-index --refresh >/dev/null ;# this can exit non-zero + git diff-files >.test-a && cmp_diff_files_output .test-a .test-recursive-OA' test_expect_success \ 'diff-files with O in cache and B checked out' \ 'rm -fr Z [A-Z][A-Z] && - git-read-tree $tree_B && - git-checkout-index -f -a && - git-read-tree --reset $tree_O || return 1 - git-update-index --refresh >/dev/null ;# this can exit non-zero - git-diff-files >.test-a && + git read-tree $tree_B && + git checkout-index -f -a && + git read-tree --reset $tree_O || return 1 + git update-index --refresh >/dev/null ;# this can exit non-zero + git diff-files >.test-a && cmp_diff_files_output .test-a .test-recursive-OB' test_expect_success \ 'diff-files with A in cache and B checked out' \ 'rm -fr Z [A-Z][A-Z] && - git-read-tree $tree_B && - git-checkout-index -f -a && - git-read-tree --reset $tree_A || return 1 - git-update-index --refresh >/dev/null ;# this can exit non-zero - git-diff-files >.test-a && + git read-tree $tree_B && + git checkout-index -f -a && + git read-tree --reset $tree_A || return 1 + git update-index --refresh >/dev/null ;# this can exit non-zero + git diff-files >.test-a && cmp_diff_files_output .test-a .test-recursive-AB' ################################################################ @@ -222,26 +236,34 @@ test_expect_success \ test_expect_success \ 'diff-tree O A == diff-tree -R A O' \ - 'git-diff-tree $tree_O $tree_A >.test-a && - git-diff-tree -R $tree_A $tree_O >.test-b && + 'git diff-tree $tree_O $tree_A >.test-a && + git diff-tree -R $tree_A $tree_O >.test-b && cmp -s .test-a .test-b' test_expect_success \ 'diff-tree -r O A == diff-tree -r -R A O' \ - 'git-diff-tree -r $tree_O $tree_A >.test-a && - git-diff-tree -r -R $tree_A $tree_O >.test-b && + 'git diff-tree -r $tree_O $tree_A >.test-a && + git diff-tree -r -R $tree_A $tree_O >.test-b && cmp -s .test-a .test-b' test_expect_success \ 'diff-tree B A == diff-tree -R A B' \ - 'git-diff-tree $tree_B $tree_A >.test-a && - git-diff-tree -R $tree_A $tree_B >.test-b && + 'git diff-tree $tree_B $tree_A >.test-a && + git diff-tree -R $tree_A $tree_B >.test-b && cmp -s .test-a .test-b' test_expect_success \ 'diff-tree -r B A == diff-tree -r -R A B' \ - 'git-diff-tree -r $tree_B $tree_A >.test-a && - git-diff-tree -r -R $tree_A $tree_B >.test-b && + 'git diff-tree -r $tree_B $tree_A >.test-a && + git diff-tree -r -R $tree_A $tree_B >.test-b && cmp -s .test-a .test-b' +test_expect_success \ + 'diff can read from stdin' \ + 'test_must_fail git diff --no-index -- MN - < NN | + grep -v "^index" | sed "s#/-#/NN#" >.test-a && + test_must_fail git diff --no-index -- MN NN | + grep -v "^index" >.test-b && + test_cmp .test-a .test-b' + test_done diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh index 27519704d4..c6130c4019 100755 --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -7,14 +7,14 @@ test_description='More rename detection ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ - 'cat ../../COPYING >COPYING && + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && echo frotz >rezrov && - git-update-index --add COPYING rezrov && - tree=$(git-write-tree) && + git update-index --add COPYING rezrov && + tree=$(git write-tree) && echo $tree' test_expect_success \ @@ -22,14 +22,14 @@ test_expect_success \ 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && rm -f COPYING && - git-update-index --add --remove COPYING COPYING.?' + git update-index --add --remove COPYING COPYING.?' # tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, # both are slightly edited, and unchanged rezrov. So we say you # copy-and-edit one, and rename-and-edit the other. We do not say # anything about rezrov. -GIT_DIFF_OPTS=--unified=0 git-diff-index -M -p $tree >current +GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current cat >expected <<\EOF diff --git a/COPYING b/COPYING.1 copy from COPYING @@ -62,14 +62,14 @@ test_expect_success \ test_expect_success \ 'prepare work tree again' \ 'mv COPYING.2 COPYING && - git-update-index --add --remove COPYING COPYING.1 COPYING.2' + git update-index --add --remove COPYING COPYING.1 COPYING.2' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # both are slightly edited, and unchanged rezrov. So we say you # edited one, and copy-and-edit the other. We do not say # anything about rezrov. -GIT_DIFF_OPTS=--unified=0 git-diff-index -C -p $tree >current +GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current cat >expected <<\EOF diff --git a/COPYING b/COPYING --- a/COPYING @@ -99,17 +99,17 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && - git-update-index --add --remove COPYING COPYING.1' + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && + git update-index --add --remove COPYING COPYING.1' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # but COPYING is not edited. We say you copy-and-edit COPYING.1; this # is only possible because -C mode now reports the unmodified file to # the diff-core. Unchanged rezrov, although being fed to -# git-diff-index as well, should not be mentioned. +# git diff-index as well, should not be mentioned. GIT_DIFF_OPTS=--unified=0 \ - git-diff-index -C --find-copies-harder -p $tree >current + git diff-index -C --find-copies-harder -p $tree >current cat >expected <<\EOF diff --git a/COPYING b/COPYING.1 copy from COPYING diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index a23aaa0a94..1a09e8db40 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -10,14 +10,20 @@ copy of symbolic links, but should not produce rename/copy followed by an edit for them. ' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi test_expect_success \ 'prepare reference tree' \ 'echo xyzzy | tr -d '\\\\'012 >yomin && ln -s xyzzy frotz && - git-update-index --add frotz yomin && - tree=$(git-write-tree) && + git update-index --add frotz yomin && + tree=$(git write-tree) && echo $tree' test_expect_success \ @@ -26,7 +32,7 @@ test_expect_success \ rm -f yomin && ln -s xyzzy nitfol && ln -s xzzzy bozbar && - git-update-index --add --remove frotz rezrov nitfol bozbar yomin' + git update-index --add --remove frotz rezrov nitfol bozbar yomin' # tree has frotz pointing at xyzzy, and yomin that contains xyzzy to # confuse things. work tree has rezrov (xyzzy) nitfol (xyzzy) and @@ -34,7 +40,7 @@ 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 +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 diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh index 684fd23a41..1ba359d478 100755 --- a/t/t4005-diff-rename-2.sh +++ b/t/t4005-diff-rename-2.sh @@ -7,14 +7,14 @@ test_description='Same rename detection as t4003 but testing diff-raw. ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ - 'cat ../../COPYING >COPYING && + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && echo frotz >rezrov && - git-update-index --add COPYING rezrov && - tree=$(git-write-tree) && + git update-index --add COPYING rezrov && + tree=$(git write-tree) && echo $tree' test_expect_success \ @@ -22,14 +22,14 @@ test_expect_success \ 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && rm -f COPYING && - git-update-index --add --remove COPYING COPYING.?' + git update-index --add --remove COPYING COPYING.?' # tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, # both are slightly edited, and unchanged rezrov. We say COPYING.1 # and COPYING.2 are based on COPYING, and do not say anything about # rezrov. -git-diff-index -M $tree >current +git diff-index -M $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 @@ -45,14 +45,14 @@ test_expect_success \ test_expect_success \ 'prepare work tree again' \ 'mv COPYING.2 COPYING && - git-update-index --add --remove COPYING COPYING.1 COPYING.2' + git update-index --add --remove COPYING COPYING.1 COPYING.2' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # both are slightly edited, and unchanged rezrov. We say COPYING.1 # is based on COPYING and COPYING is still there, and do not say anything # about rezrov. -git-diff-index -C $tree >current +git diff-index -C $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M COPYING :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 @@ -71,10 +71,10 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && - git-update-index --add --remove COPYING COPYING.1' + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && + git update-index --add --remove COPYING COPYING.1' -git-diff-index -C --find-copies-harder $tree >current +git diff-index -C --find-copies-harder $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 EOF diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index ca342f48a1..ff8c2f7532 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -11,34 +11,20 @@ test_description='Test mode change diffs. test_expect_success \ 'setup' \ 'echo frotz >rezrov && - git-update-index --add rezrov && - tree=`git-write-tree` && + git update-index --add rezrov && + tree=`git write-tree` && echo $tree' -if [ "$(git config --get core.filemode)" = false ] -then - say 'filemode disabled on the filesystem, using update-index --chmod=+x' - test_expect_success \ - 'git-update-index --chmod=+x' \ - 'git-update-index rezrov && - git-update-index --chmod=+x rezrov && - git-diff-index $tree >current' -else - test_expect_success \ - 'chmod' \ - 'chmod +x rezrov && - git-update-index rezrov && - git-diff-index $tree >current' -fi +test_expect_success \ + 'chmod' \ + 'test_chmod +x rezrov && + git diff-index $tree >current' -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" sed -e 's/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' <current >check echo ":100644 100755 X X M rezrov" >expected test_expect_success \ 'verify' \ - 'diff -u expected check' + 'test_cmp expected check' test_done - diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh index bb6ba69258..11502b7509 100755 --- a/t/t4007-rename-3.sh +++ b/t/t4007-rename-3.sh @@ -7,34 +7,38 @@ test_description='Rename interaction with pathspec. ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash - -test_expect_success \ - 'prepare reference tree' \ - 'mkdir path0 path1 && - cp ../../COPYING path0/COPYING && - git-update-index --add path0/COPYING && - tree=$(git-write-tree) && - echo $tree' +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success 'prepare reference tree' ' + mkdir path0 path1 && + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && + git update-index --add path0/COPYING && + tree=$(git write-tree) && + echo $tree +' -test_expect_success \ - 'prepare work tree' \ - 'cp path0/COPYING path1/COPYING && - git-update-index --add --remove path0/COPYING path1/COPYING' +test_expect_success 'prepare work tree' ' + cp path0/COPYING path1/COPYING && + git update-index --add --remove path0/COPYING path1/COPYING +' # In the tree, there is only path0/COPYING. In the cache, path0 and # path1 both have COPYING and the latter is a copy of path0/COPYING. # Comparing the full tree with cache should tell us so. -git-diff-index -C --find-copies-harder $tree >current - cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 C100 path0/COPYING path1/COPYING EOF -test_expect_success \ - 'validate the result (#1)' \ - 'compare_diff_raw current expected' +test_expect_success 'copy detection' ' + git diff-index -C --find-copies-harder $tree >current && + compare_diff_raw current expected +' + +test_expect_success 'copy detection, cached' ' + git diff-index -C --find-copies-harder --cached $tree >current && + compare_diff_raw current expected +' # In the tree, there is only path0/COPYING. In the cache, path0 and # path1 both have COPYING and the latter is a copy of path0/COPYING. @@ -42,49 +46,45 @@ test_expect_success \ # path1/COPYING suddenly appearing from nowhere, not detected as # a copy from path0/COPYING. -git-diff-index -C $tree path1 >current - cat >expected <<\EOF :000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING EOF -test_expect_success \ - 'validate the result (#2)' \ - 'compare_diff_raw current expected' - -test_expect_success \ - 'tweak work tree' \ - 'rm -f path0/COPYING && - git-update-index --remove path0/COPYING' +test_expect_success 'copy, limited to a subtree' ' + git diff-index -C --find-copies-harder $tree path1 >current && + compare_diff_raw current expected +' +test_expect_success 'tweak work tree' ' + rm -f path0/COPYING && + git update-index --remove path0/COPYING +' # In the tree, there is only path0/COPYING. In the cache, path0 does # not have COPYING anymore and path1 has COPYING which is a copy of # path0/COPYING. Showing the full tree with cache should tell us about # the rename. -git-diff-index -C $tree >current - cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 R100 path0/COPYING path1/COPYING EOF -test_expect_success \ - 'validate the result (#3)' \ - 'compare_diff_raw current expected' +test_expect_success 'rename detection' ' + git diff-index -C --find-copies-harder $tree >current && + compare_diff_raw current expected +' # In the tree, there is only path0/COPYING. In the cache, path0 does # not have COPYING anymore and path1 has COPYING which is a copy of # path0/COPYING. When we say we care only about path1, we should just # see path1/COPYING appearing from nowhere. -git-diff-index -C $tree path1 >current - cat >expected <<\EOF :000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING EOF -test_expect_success \ - 'validate the result (#4)' \ - 'compare_diff_raw current expected' +test_expect_success 'rename, limited to a subtree' ' + git diff-index -C --find-copies-harder $tree path1 >current && + compare_diff_raw current expected +' test_done diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh index 263ac1ebf7..e19ca65885 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -22,25 +22,25 @@ four changes in total. Further, with -B and -M together, these should turn into two renames. ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ setup \ - 'cat ../../README >file0 && - cat ../../COPYING >file1 && - git-update-index --add file0 file1 && - tree=$(git-write-tree) && + 'cat "$TEST_DIRECTORY"/../README >file0 && + cat "$TEST_DIRECTORY"/../COPYING >file1 && + git update-index --add file0 file1 && + tree=$(git write-tree) && echo "$tree"' test_expect_success \ 'change file1 with copy-edit of file0 and remove file0' \ 'sed -e "s/git/GIT/" file0 >file1 && rm -f file0 && - git-update-index --remove file0 file1' + git update-index --remove file0 file1' test_expect_success \ 'run diff with -B' \ - 'git-diff-index -B --cached "$tree" >current' + 'git diff-index -B --cached "$tree" >current' cat >expected <<\EOF :100644 000000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 0000000000000000000000000000000000000000 D file0 @@ -53,7 +53,7 @@ test_expect_success \ test_expect_success \ 'run diff with -B and -M' \ - 'git-diff-index -B -M "$tree" >current' + 'git diff-index -B -M "$tree" >current' cat >expected <<\EOF :100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c R100 file0 file1 @@ -66,16 +66,16 @@ test_expect_success \ test_expect_success \ 'swap file0 and file1' \ 'rm -f file0 file1 && - git-read-tree -m $tree && - git-checkout-index -f -u -a && + git read-tree -m $tree && + git checkout-index -f -u -a && mv file0 tmp && mv file1 file0 && mv tmp file1 && - git-update-index file0 file1' + git update-index file0 file1' test_expect_success \ 'run diff with -B' \ - 'git-diff-index -B "$tree" >current' + 'git diff-index -B "$tree" >current' cat >expected <<\EOF :100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 6ff87c4664981e4397625791c8ea3bbb5f2279a3 M100 file0 @@ -88,7 +88,7 @@ test_expect_success \ test_expect_success \ 'run diff with -B and -M' \ - 'git-diff-index -B -M "$tree" >current' + 'git diff-index -B -M "$tree" >current' cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 R100 file1 file0 @@ -99,43 +99,43 @@ test_expect_success \ 'validate result of -B -M (#4)' \ 'compare_diff_raw expected current' -test_expect_success \ +test_expect_success SYMLINKS \ 'make file0 into something completely different' \ 'rm -f file0 && ln -s frotz file0 && - git-update-index file0 file1' + git update-index file0 file1' test_expect_success \ 'run diff with -B' \ - 'git-diff-index -B "$tree" >current' + 'git diff-index -B "$tree" >current' cat >expected <<\EOF :100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T file0 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'validate result of -B (#5)' \ 'compare_diff_raw expected current' test_expect_success \ - 'run diff with -B' \ - 'git-diff-index -B -M "$tree" >current' + 'run diff with -B -M' \ + 'git diff-index -B -M "$tree" >current' -# This should not mistake file0 as the copy source of new file1 -# due to type differences. +# file0 changed from regular to symlink. file1 is very close to the preimage of file0. +# because we break file0, file1 can become a rename of it. cat >expected <<\EOF :100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T file0 -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R file0 file1 EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'validate result of -B -M (#6)' \ 'compare_diff_raw expected current' test_expect_success \ 'run diff with -M' \ - 'git-diff-index -M "$tree" >current' + 'git diff-index -M "$tree" >current' # This should not mistake file0 as the copy source of new file1 # due to type differences. @@ -144,23 +144,23 @@ cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M file1 EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'validate result of -M (#7)' \ 'compare_diff_raw expected current' test_expect_success \ 'file1 edited to look like file0 and file0 rename-edited to file2' \ 'rm -f file0 file1 && - git-read-tree -m $tree && - git-checkout-index -f -u -a && + git read-tree -m $tree && + git checkout-index -f -u -a && sed -e "s/git/GIT/" file0 >file1 && sed -e "s/git/GET/" file0 >file2 && rm -f file0 - git-update-index --add --remove file0 file1 file2' + git update-index --add --remove file0 file1 file2' test_expect_success \ 'run diff with -B' \ - 'git-diff-index -B "$tree" >current' + 'git diff-index -B "$tree" >current' cat >expected <<\EOF :100644 000000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 0000000000000000000000000000000000000000 D file0 @@ -174,7 +174,7 @@ test_expect_success \ test_expect_success \ 'run diff with -B -M' \ - 'git-diff-index -B -M "$tree" >current' + 'git diff-index -B -M "$tree" >current' cat >expected <<\EOF :100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095 file0 file1 diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh index 2f2f8b1216..de3f17478e 100755 --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -7,14 +7,14 @@ test_description='Same rename detection as t4003 but testing diff-raw -z. ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ - 'cat ../../COPYING >COPYING && + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && echo frotz >rezrov && - git-update-index --add COPYING rezrov && - tree=$(git-write-tree) && + git update-index --add COPYING rezrov && + tree=$(git write-tree) && echo $tree' test_expect_success \ @@ -22,14 +22,14 @@ test_expect_success \ 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && rm -f COPYING && - git-update-index --add --remove COPYING COPYING.?' + git update-index --add --remove COPYING COPYING.?' # tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, # both are slightly edited, and unchanged rezrov. We say COPYING.1 # and COPYING.2 are based on COPYING, and do not say anything about # rezrov. -git-diff-index -z -M $tree >current +git diff-index -z -M $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 @@ -49,14 +49,14 @@ test_expect_success \ test_expect_success \ 'prepare work tree again' \ 'mv COPYING.2 COPYING && - git-update-index --add --remove COPYING COPYING.1 COPYING.2' + git update-index --add --remove COPYING COPYING.1 COPYING.2' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # both are slightly edited, and unchanged rezrov. We say COPYING.1 # is based on COPYING and COPYING is still there, and do not say anything # about rezrov. -git-diff-index -z -C $tree >current +git diff-index -z -C $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M COPYING @@ -78,10 +78,10 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && - git-update-index --add --remove COPYING COPYING.1' + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && + git update-index --add --remove COPYING COPYING.1' -git-diff-index -z -C --find-copies-harder $tree >current +git diff-index -z -C --find-copies-harder $tree >current cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 9e1544df9d..94df7ae53a 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -10,25 +10,25 @@ Prepare: path1/file1 ' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ setup \ 'echo frotz >file0 && mkdir path1 && echo rezrov >path1/file1 && - git-update-index --add file0 path1/file1 && - tree=`git-write-tree` && + git update-index --add file0 path1/file1 && + tree=`git write-tree` && echo "$tree" && echo nitfol >file0 && echo yomin >path1/file1 && - git-update-index file0 path1/file1' + git update-index file0 path1/file1' cat >expected <<\EOF EOF test_expect_success \ 'limit to path should show nothing' \ - 'git-diff-index --cached $tree -- path >current && + 'git diff-index --cached $tree -- path >current && compare_diff_raw current expected' cat >expected <<\EOF @@ -36,7 +36,7 @@ cat >expected <<\EOF EOF test_expect_success \ 'limit to path1 should show path1/file1' \ - 'git-diff-index --cached $tree -- path1 >current && + 'git diff-index --cached $tree -- path1 >current && compare_diff_raw current expected' cat >expected <<\EOF @@ -44,7 +44,7 @@ cat >expected <<\EOF EOF test_expect_success \ 'limit to path1/ should show path1/file1' \ - 'git-diff-index --cached $tree -- path1/ >current && + 'git diff-index --cached $tree -- path1/ >current && compare_diff_raw current expected' cat >expected <<\EOF @@ -52,14 +52,22 @@ cat >expected <<\EOF EOF test_expect_success \ 'limit to file0 should show file0' \ - 'git-diff-index --cached $tree -- file0 >current && + 'git diff-index --cached $tree -- file0 >current && compare_diff_raw current expected' cat >expected <<\EOF EOF test_expect_success \ 'limit to file0/ should emit nothing.' \ - 'git-diff-index --cached $tree -- file0/ >current && + 'git diff-index --cached $tree -- file0/ >current && compare_diff_raw current expected' +test_expect_success 'diff-tree pathspec' ' + tree2=$(git write-tree) && + echo "$tree2" && + git diff-tree -r --name-only $tree $tree2 -- pa path1/a >current && + >expected && + test_cmp expected current +' + test_done diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index 379a831f0b..918a21a2f4 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -7,7 +7,13 @@ test_description='Test diff of symlinks. ' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi cat > expected << EOF diff --git a/frotz b/frotz @@ -23,17 +29,17 @@ EOF test_expect_success \ 'diff new symlink' \ 'ln -s xyzzy frotz && - git-update-index && - tree=$(git-write-tree) && - git-update-index --add frotz && - GIT_DIFF_OPTS=--unified=0 git-diff-index -M -p $tree > current && + git update-index && + tree=$(git write-tree) && + git update-index --add frotz && + GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree > current && compare_diff_patch current expected' test_expect_success \ 'diff unchanged symlink' \ - 'tree=$(git-write-tree) && - git-update-index frotz && - test -z "$(git-diff-index --name-only $tree)"' + 'tree=$(git write-tree) && + git update-index frotz && + test -z "$(git diff-index --name-only $tree)"' cat > expected << EOF diff --git a/frotz b/frotz @@ -48,8 +54,8 @@ EOF test_expect_success \ 'diff removed symlink' \ - 'rm frotz && - git-diff-index -M -p $tree > current && + 'mv frotz frotz2 && + git diff-index -M -p $tree > current && compare_diff_patch current expected' cat > expected << EOF @@ -58,9 +64,8 @@ EOF test_expect_success \ 'diff identical, but newly created symlink' \ - 'sleep 3 && - ln -s xyzzy frotz && - git-diff-index -M -p $tree > current && + 'ln -s xyzzy frotz && + git diff-index -M -p $tree > current && compare_diff_patch current expected' cat > expected << EOF @@ -79,7 +84,14 @@ test_expect_success \ 'diff different symlink' \ 'rm frotz && ln -s yxyyz frotz && - git-diff-index -M -p $tree > current && + git diff-index -M -p $tree > current && compare_diff_patch current expected' +test_expect_success \ + 'diff symlinks with non-existing targets' \ + 'ln -s narf pinky && + ln -s take\ over brain && + test_must_fail git diff --no-index pinky brain > output 2> output.err && + grep narf output && + ! grep error output.err' test_done diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 323606c65c..bc46563afc 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -10,9 +10,9 @@ test_description='Binary diff and apply test_expect_success 'prepare repository' \ 'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d && - git-update-index --add a b c d && + git update-index --add a b c d && echo git >a && - cat ../test4012.png >b && + cat "$TEST_DIRECTORY"/test4012.png >b && echo git >c && cat b b >d' @@ -24,18 +24,18 @@ cat > expected <<\EOF 4 files changed, 2 insertions(+), 2 deletions(-) EOF test_expect_success 'diff without --binary' \ - 'git-diff | git-apply --stat --summary >current && - cmp current expected' + 'git diff | git apply --stat --summary >current && + test_cmp expected current' test_expect_success 'diff with --binary' \ - 'git-diff --binary | git-apply --stat --summary >current && - cmp current expected' + 'git diff --binary | git apply --stat --summary >current && + test_cmp expected current' # apply needs to be able to skip the binary material correctly # in order to report the line number of a corrupt patch. test_expect_success 'apply detecting corrupt patch correctly' \ - 'git-diff | sed -e 's/-CIT/xCIT/' >broken && - if git-apply --stat --summary broken 2>detected + 'git diff | sed -e 's/-CIT/xCIT/' >broken && + if git apply --stat --summary broken 2>detected then echo unhappy - should have detected an error (exit 1) @@ -48,8 +48,8 @@ test_expect_success 'apply detecting corrupt patch correctly' \ test "$detected" = xCIT' test_expect_success 'apply detecting corrupt patch correctly' \ - 'git-diff --binary | sed -e 's/-CIT/xCIT/' >broken && - if git-apply --stat --summary broken 2>detected + 'git diff --binary | sed -e 's/-CIT/xCIT/' >broken && + if git apply --stat --summary broken 2>detected then echo unhappy - should have detected an error (exit 1) @@ -61,20 +61,37 @@ test_expect_success 'apply detecting corrupt patch correctly' \ detected=`sed -ne "${detected}p" broken` && test "$detected" = xCIT' -test_expect_success 'initial commit' 'git-commit -a -m initial' +test_expect_success 'initial commit' 'git commit -a -m initial' # Try removal (b), modification (d), and creation (e). test_expect_success 'diff-index with --binary' \ 'echo AIT >a && mv b e && echo CIT >c && cat e >d && - git-update-index --add --remove a b c d e && - tree0=`git-write-tree` && - git-diff --cached --binary >current && - git-apply --stat --summary current' + git update-index --add --remove a b c d e && + tree0=`git write-tree` && + git diff --cached --binary >current && + git apply --stat --summary current' test_expect_success 'apply binary patch' \ - 'git-reset --hard && - git-apply --binary --index <current && - tree1=`git-write-tree` && + 'git reset --hard && + git apply --binary --index <current && + tree1=`git write-tree` && test "$tree1" = "$tree0"' +nul_to_q() { + perl -pe 'y/\000/Q/' +} + +test_expect_success 'diff --no-index with binary creation' ' + echo Q | q_to_nul >binary && + (: hide error code from diff, which just indicates differences + git diff --binary --no-index /dev/null binary >current || + true + ) && + rm binary && + git apply --binary <current && + echo Q >expected && + nul_to_q <binary >actual && + test_cmp expected actual +' + test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 3d85ceaae9..dae6358516 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -17,6 +17,7 @@ test_expect_success setup ' export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && mkdir dir && + mkdir dir2 && for i in 1 2 3; do echo $i; done >file0 && for i in A B; do echo $i; done >dir/sub && cat file0 >file2 && @@ -73,6 +74,10 @@ test_expect_success setup ' for i in 1 2; do echo $i; done >>dir/sub && git update-index file0 dir/sub && + mkdir dir3 && + cp dir/sub dir3/sub && + test-chmtime +1 dir3/sub && + git config log.showroot false && git commit --amend && git show-branch @@ -96,9 +101,8 @@ do '' | '#'*) continue ;; esac test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'` - cnt=`expr $test_count + 1` - pfx=`printf "%04d" $cnt` - expect="../t4013/diff.$test" + pfx=`printf "%04d" $test_count` + expect="$TEST_DIRECTORY/t4013/diff.$test" actual="$pfx-diff.$test" test_expect_success "git $cmd" ' @@ -106,12 +110,12 @@ do echo "\$ git $cmd" git $cmd | sed -e "s/^\\(-*\\)$V\\(-*\\)\$/\\1g-i-t--v-e-r-s-i-o-n\2/" \ - -e "s/^\\( *boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/" + -e "s/^\\(.*mixed; boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/" echo "\$" } >"$actual" && if test -f "$expect" then - diff -u "$expect" "$actual" && + test_cmp "$expect" "$actual" && rm -f "$actual" else # this is to help developing new tests. @@ -200,8 +204,16 @@ log --root --patch-with-stat --summary master log --root -c --patch-with-stat --summary master # improved by Timo's patch log --root --cc --patch-with-stat --summary master +log -p --first-parent master +log -m -p --first-parent master +log -m -p master log -SF master log -SF -p master +log --decorate --all +log --decorate=full --all + +rev-list --parents HEAD +rev-list --children HEAD whatchanged master whatchanged -p master @@ -226,6 +238,9 @@ show initial show --root initial show side show master +show -c master +show -m master +show --first-parent master show --stat side show --stat --summary side show --patch-with-stat side @@ -235,9 +250,20 @@ show --patch-with-stat --summary side format-patch --stdout initial..side format-patch --stdout initial..master^ format-patch --stdout initial..master +format-patch --stdout --no-numbered initial..master +format-patch --stdout --numbered initial..master format-patch --attach --stdout initial..side +format-patch --attach --stdout --suffix=.diff initial..side format-patch --attach --stdout initial..master^ format-patch --attach --stdout initial..master +format-patch --inline --stdout initial..side +format-patch --inline --stdout initial..master^ +format-patch --inline --stdout --numbered-files initial..master +format-patch --inline --stdout initial..master +format-patch --inline --stdout --subject-prefix=TESTCASE initial..master +config format.subjectprefix DIFFERENT_PREFIX +format-patch --inline --stdout initial..master^^ +format-patch --stdout --cover-letter -n initial..master^ diff --abbrev initial..side diff -r initial..side @@ -248,6 +274,12 @@ diff --patch-with-stat initial..side diff --patch-with-raw initial..side diff --patch-with-stat -r initial..side diff --patch-with-raw -r initial..side +diff --name-status dir2 dir +diff --no-index --name-status dir2 dir +diff --no-index --name-status -- dir2 dir +diff --no-index dir dir3 +diff master master^ side +diff --dirstat master~1 master~2 EOF test_done diff --git a/t/t4013/diff.config_format.subjectprefix_DIFFERENT_PREFIX b/t/t4013/diff.config_format.subjectprefix_DIFFERENT_PREFIX new file mode 100644 index 0000000000..78f8970e2b --- /dev/null +++ b/t/t4013/diff.config_format.subjectprefix_DIFFERENT_PREFIX @@ -0,0 +1,2 @@ +$ git config format.subjectprefix DIFFERENT_PREFIX +$ diff --git a/t/t4013/diff.diff_--dirstat_master~1_master~2 b/t/t4013/diff.diff_--dirstat_master~1_master~2 new file mode 100644 index 0000000000..b672e1ca63 --- /dev/null +++ b/t/t4013/diff.diff_--dirstat_master~1_master~2 @@ -0,0 +1,3 @@ +$ git diff --dirstat master~1 master~2 + 40.0% dir/ +$ diff --git a/t/t4013/diff.diff_--name-status_dir2_dir b/t/t4013/diff.diff_--name-status_dir2_dir new file mode 100644 index 0000000000..d0d96aaa91 --- /dev/null +++ b/t/t4013/diff.diff_--name-status_dir2_dir @@ -0,0 +1,2 @@ +$ git diff --name-status dir2 dir +$ diff --git a/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir b/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir new file mode 100644 index 0000000000..6756f8de67 --- /dev/null +++ b/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir @@ -0,0 +1,3 @@ +$ git diff --no-index --name-status -- dir2 dir +A dir/sub +$ diff --git a/t/t4013/diff.diff_--no-index_--name-status_dir2_dir b/t/t4013/diff.diff_--no-index_--name-status_dir2_dir new file mode 100644 index 0000000000..6a47584777 --- /dev/null +++ b/t/t4013/diff.diff_--no-index_--name-status_dir2_dir @@ -0,0 +1,3 @@ +$ git diff --no-index --name-status dir2 dir +A dir/sub +$ diff --git a/t/t4013/diff.diff_--no-index_dir_dir3 b/t/t4013/diff.diff_--no-index_dir_dir3 new file mode 100644 index 0000000000..2142c2b9ad --- /dev/null +++ b/t/t4013/diff.diff_--no-index_dir_dir3 @@ -0,0 +1,2 @@ +$ git diff --no-index dir dir3 +$ diff --git a/t/t4013/diff.diff_master_master^_side b/t/t4013/diff.diff_master_master^_side new file mode 100644 index 0000000000..50ec9cadd6 --- /dev/null +++ b/t/t4013/diff.diff_master_master^_side @@ -0,0 +1,29 @@ +$ git diff master master^ side +diff --cc dir/sub +index cead32e,7289e35..992913c +--- a/dir/sub ++++ b/dir/sub +@@@ -1,6 -1,4 +1,8 @@@ + A + B + +C + +D + +E + +F ++ 1 ++ 2 +diff --cc file0 +index b414108,f4615da..10a8a9f +--- a/file0 ++++ b/file0 +@@@ -1,6 -1,6 +1,9 @@@ + 1 + 2 + 3 + +4 + +5 + +6 ++ A ++ B ++ C +$ diff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side new file mode 100644 index 0000000000..52116d3ead --- /dev/null +++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side @@ -0,0 +1,61 @@ +$ git format-patch --attach --stdout --suffix=.diff initial..side +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH] Side +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Side.diff" +Content-Transfer-Encoding: 8bit +Content-Disposition: attachment; filename="0001-Side.diff" + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master index e5ddd6fcbb..ce49bd676e 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master @@ -2,10 +2,9 @@ $ git format-patch --attach --stdout initial..master 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 -Subject: [PATCH] Second +Subject: [PATCH 1/3] Second MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -20,12 +19,12 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Type: text/x-patch; name="0001-Second.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Disposition: attachment; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -64,10 +63,9 @@ index 01e79c3..0000000 From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:02:00 +0000 -Subject: [PATCH] Third +Subject: [PATCH 2/3] Third MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -79,12 +77,12 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" +Content-Type: text/x-patch; name="0002-Third.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" +Content-Disposition: attachment; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -113,10 +111,9 @@ index 0000000..b1e6722 From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:03:00 +0000 -Subject: [PATCH] Side +Subject: [PATCH 3/3] Side MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -129,12 +126,12 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" +Content-Type: text/x-patch; name="0003-Side.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" +Content-Disposition: attachment; filename="0003-Side.patch" diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ index d0dd19b623..5f1b23863b 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ @@ -2,10 +2,9 @@ $ git format-patch --attach --stdout initial..master^ 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 -Subject: [PATCH] Second +Subject: [PATCH 1/2] Second MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -20,12 +19,12 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Type: text/x-patch; name="0001-Second.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Disposition: attachment; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -64,10 +63,9 @@ index 01e79c3..0000000 From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:02:00 +0000 -Subject: [PATCH] Third +Subject: [PATCH 2/2] Third MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -79,12 +77,12 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" +Content-Type: text/x-patch; name="0002-Third.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" +Content-Disposition: attachment; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side index 67a95c5cba..4a2364abc2 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side @@ -4,8 +4,7 @@ From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:03:00 +0000 Subject: [PATCH] Side MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="------------g-i-t--v-e-r-s-i-o-n" +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" This is a multi-part message in MIME format. --------------g-i-t--v-e-r-s-i-o-n @@ -18,12 +17,12 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n -Content-Type: text/x-patch; - name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" +Content-Type: text/x-patch; name="0001-Side.patch" Content-Transfer-Encoding: 8bit -Content-Disposition: inline; - filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" +Content-Disposition: attachment; filename="0001-Side.patch" diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master new file mode 100644 index 0000000000..43b81eba54 --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master @@ -0,0 +1,170 @@ +$ git format-patch --inline --stdout --numbered-files initial..master +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 +Subject: [PATCH 1/3] Second +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="1" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="1" + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [PATCH 2/3] Third +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="2" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="2" + +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 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH 3/3] Side +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="3" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="3" + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master new file mode 100644 index 0000000000..ca3f60bf0e --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master @@ -0,0 +1,170 @@ +$ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..master +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 +Subject: [TESTCASE 1/3] Second +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Second.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0001-Second.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [TESTCASE 2/3] Third +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0002-Third.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0002-Third.patch" + +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 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [TESTCASE 3/3] Side +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0003-Side.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0003-Side.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master new file mode 100644 index 0000000000..08f23014bc --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master @@ -0,0 +1,170 @@ +$ git format-patch --inline --stdout initial..master +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 +Subject: [PATCH 1/3] Second +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Second.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0001-Second.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [PATCH 2/3] Third +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0002-Third.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0002-Third.patch" + +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 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH 3/3] Side +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0003-Side.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0003-Side.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ new file mode 100644 index 0000000000..07f1230d31 --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ @@ -0,0 +1,110 @@ +$ git format-patch --inline --stdout initial..master^ +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 +Subject: [PATCH 1/2] Second +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Second.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0001-Second.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +--------------g-i-t--v-e-r-s-i-o-n-- + + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [PATCH 2/2] Third +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0002-Third.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0002-Third.patch" + +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 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ new file mode 100644 index 0000000000..29e00ab8af --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ @@ -0,0 +1,62 @@ +$ git format-patch --inline --stdout initial..master^^ +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 +Subject: [DIFFERENT_PREFIX] Second +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Second.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0001-Second.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side new file mode 100644 index 0000000000..67633d424a --- /dev/null +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side @@ -0,0 +1,61 @@ +$ git format-patch --inline --stdout initial..side +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH] Side +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" + +This is a multi-part message in MIME format. +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/plain; charset=UTF-8; format=fixed +Content-Transfer-Encoding: 8bit + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + + +--------------g-i-t--v-e-r-s-i-o-n +Content-Type: text/x-patch; name="0001-Side.patch" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline; filename="0001-Side.patch" + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +--------------g-i-t--v-e-r-s-i-o-n-- + + +$ 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^ new file mode 100644 index 0000000000..1f0f9ad44b --- /dev/null +++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ @@ -0,0 +1,103 @@ +$ git format-patch --stdout --cover-letter -n initial..master^ +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: C O Mitter <committer@example.com> +Date: Mon, 26 Jun 2006 00:05:00 +0000 +Subject: [DIFFERENT_PREFIX 0/2] *** SUBJECT HERE *** + +*** BLURB HERE *** + +A U Thor (2): + Second + Third + + dir/sub | 4 ++++ + file0 | 3 +++ + file1 | 3 +++ + file2 | 3 --- + 4 files changed, 10 insertions(+), 3 deletions(-) + 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 +Subject: [DIFFERENT_PREFIX 1/2] Second + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 +-- +g-i-t--v-e-r-s-i-o-n + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [DIFFERENT_PREFIX 2/2] Third + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + +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 +-- +g-i-t--v-e-r-s-i-o-n + +$ diff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master new file mode 100644 index 0000000000..f7752ebbea --- /dev/null +++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master @@ -0,0 +1,127 @@ +$ git format-patch --stdout --no-numbered initial..master +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 +Subject: [PATCH] Second + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 +-- +g-i-t--v-e-r-s-i-o-n + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [PATCH] Third + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + +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 +-- +g-i-t--v-e-r-s-i-o-n + + +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH] Side + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 +-- +g-i-t--v-e-r-s-i-o-n + +$ diff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master new file mode 100644 index 0000000000..8e67dbf76f --- /dev/null +++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master @@ -0,0 +1,127 @@ +$ git format-patch --stdout --numbered initial..master +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 +Subject: [PATCH 1/3] Second + +This is the second commit. +--- + dir/sub | 2 ++ + file0 | 3 +++ + file2 | 3 --- + 3 files changed, 5 insertions(+), 3 deletions(-) + delete mode 100644 file2 + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 +-- +g-i-t--v-e-r-s-i-o-n + + +From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:02:00 +0000 +Subject: [PATCH 2/3] Third + +--- + dir/sub | 2 ++ + file1 | 3 +++ + 2 files changed, 5 insertions(+), 0 deletions(-) + create mode 100644 file1 + +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 +-- +g-i-t--v-e-r-s-i-o-n + + +From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 +From: A U Thor <author@example.com> +Date: Mon, 26 Jun 2006 00:03:00 +0000 +Subject: [PATCH 3/3] Side + +--- + dir/sub | 2 ++ + file0 | 3 +++ + file3 | 4 ++++ + 3 files changed, 9 insertions(+), 0 deletions(-) + create mode 100644 file3 + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 +-- +g-i-t--v-e-r-s-i-o-n + +$ diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master index 8b88ca4927..7b89978e32 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--stdout_initial..master @@ -2,7 +2,7 @@ $ git format-patch --stdout initial..master 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 -Subject: [PATCH] Second +Subject: [PATCH 1/3] Second This is the second commit. --- @@ -48,7 +48,7 @@ g-i-t--v-e-r-s-i-o-n From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:02:00 +0000 -Subject: [PATCH] Third +Subject: [PATCH 2/3] Third --- dir/sub | 2 ++ @@ -82,7 +82,7 @@ g-i-t--v-e-r-s-i-o-n From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:03:00 +0000 -Subject: [PATCH] Side +Subject: [PATCH 3/3] Side --- dir/sub | 2 ++ diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^ index 47a4b88637..b7f9725dc4 100644 --- a/t/t4013/diff.format-patch_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--stdout_initial..master^ @@ -2,7 +2,7 @@ $ git format-patch --stdout initial..master^ 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 -Subject: [PATCH] Second +Subject: [PATCH 1/2] Second This is the second commit. --- @@ -48,7 +48,7 @@ g-i-t--v-e-r-s-i-o-n From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001 From: A U Thor <author@example.com> Date: Mon, 26 Jun 2006 00:02:00 +0000 -Subject: [PATCH] Third +Subject: [PATCH 2/2] Third --- dir/sub | 2 ++ diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all new file mode 100644 index 0000000000..d155e0bab2 --- /dev/null +++ b/t/t4013/diff.log_--decorate=full_--all @@ -0,0 +1,34 @@ +$ git log --decorate=full --all +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, refs/heads/master) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:03:00 2006 +0000 + + Side + +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third + +commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:01:00 2006 +0000 + + Second + + This is the second commit. + +commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:00:00 2006 +0000 + + Initial +$ diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all new file mode 100644 index 0000000000..fd7c3e6439 --- /dev/null +++ b/t/t4013/diff.log_--decorate_--all @@ -0,0 +1,34 @@ +$ git log --decorate --all +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, master) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:03:00 2006 +0000 + + Side + +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:02:00 2006 +0000 + + Third + +commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:01:00 2006 +0000 + + Second + + This is the second commit. + +commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:00:00 2006 +0000 + + Initial +$ diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ index 3ceb8e73c5..bd7f5c0f70 100644 --- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ @@ -1,6 +1,6 @@ $ git log --patch-with-stat --summary master -- dir/ commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master index 43d77761f9..14595a614c 100644 --- a/t/t4013/diff.log_--patch-with-stat_master +++ b/t/t4013/diff.log_--patch-with-stat_master @@ -1,6 +1,6 @@ $ git log --patch-with-stat master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ index 5187a26816..5a4e72765d 100644 --- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ +++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_ @@ -1,6 +1,6 @@ $ git log --patch-with-stat master -- dir/ commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master index c9640976a8..df0aaa9f2c 100644 --- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master @@ -1,6 +1,6 @@ $ git log --root --cc --patch-with-stat --summary master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master index ad050af55f..c11b5f2c7f 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master @@ -1,6 +1,6 @@ $ git log --root --patch-with-stat --summary master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master index 628c6c03bc..5f0c98f9ce 100644 --- a/t/t4013/diff.log_--root_--patch-with-stat_master +++ b/t/t4013/diff.log_--root_--patch-with-stat_master @@ -1,6 +1,6 @@ $ git log --root --patch-with-stat master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master index 5d4e0f13b5..e62c368dc6 100644 --- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master +++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master @@ -1,6 +1,6 @@ $ git log --root -c --patch-with-stat --summary master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_master index 217a2eb203..b42c334439 100644 --- a/t/t4013/diff.log_--root_-p_master +++ b/t/t4013/diff.log_--root_-p_master @@ -1,6 +1,6 @@ $ git log --root -p master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master index e17ccfc234..e8f46159da 100644 --- a/t/t4013/diff.log_--root_master +++ b/t/t4013/diff.log_--root_master @@ -1,6 +1,6 @@ $ git log --root master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_-SF_master b/t/t4013/diff.log_-SF_master index 6162ed2018..c1599f2f52 100644 --- a/t/t4013/diff.log_-SF_master +++ b/t/t4013/diff.log_-SF_master @@ -4,5 +4,4 @@ Author: A U Thor <author@example.com> Date: Mon Jun 26 00:02:00 2006 +0000 Third - $ diff --git a/t/t4013/diff.log_-m_-p_--first-parent_master b/t/t4013/diff.log_-m_-p_--first-parent_master new file mode 100644 index 0000000000..7a0073f529 --- /dev/null +++ b/t/t4013/diff.log_-m_-p_--first-parent_master @@ -0,0 +1,100 @@ +$ git log -m -p --first-parent master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index cead32e..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -4,3 +4,5 @@ C + D + E + F ++1 ++2 +diff --git a/file0 b/file0 +index b414108..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -4,3 +4,6 @@ + 4 + 5 + 6 ++A ++B ++C + +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 + +commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:01:00 2006 +0000 + + Second + + This is the second commit. + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +commit 444ac553ac7612cc88969031b02b3767fb8a353a +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:00:00 2006 +0000 + + Initial +$ diff --git a/t/t4013/diff.log_-m_-p_master b/t/t4013/diff.log_-m_-p_master new file mode 100644 index 0000000000..9ca62a01ed --- /dev/null +++ b/t/t4013/diff.log_-m_-p_master @@ -0,0 +1,200 @@ +$ git log -m -p master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index cead32e..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -4,3 +4,5 @@ C + D + E + F ++1 ++2 +diff --git a/file0 b/file0 +index b414108..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -4,3 +4,6 @@ + 4 + 5 + 6 ++A ++B ++C + +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index 7289e35..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,4 +1,8 @@ + A + B ++C ++D ++E ++F + 1 + 2 +diff --git a/file0 b/file0 +index f4615da..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -1,6 +1,9 @@ + 1 + 2 + 3 ++4 ++5 ++6 + A + B + C +diff --git a/file1 b/file1 +new file mode 100644 +index 0000000..b1e6722 +--- /dev/null ++++ b/file1 +@@ -0,0 +1,3 @@ ++A ++B ++C +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 +diff --git a/file3 b/file3 +deleted file mode 100644 +index 7289e35..0000000 +--- a/file3 ++++ /dev/null +@@ -1,4 +0,0 @@ +-A +-B +-1 +-2 + +commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:03:00 2006 +0000 + + Side + +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 + +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 + +commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:01:00 2006 +0000 + + Second + + This is the second commit. + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +commit 444ac553ac7612cc88969031b02b3767fb8a353a +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:00:00 2006 +0000 + + Initial +$ diff --git a/t/t4013/diff.log_-p_--first-parent_master b/t/t4013/diff.log_-p_--first-parent_master new file mode 100644 index 0000000000..3fc896d424 --- /dev/null +++ b/t/t4013/diff.log_-p_--first-parent_master @@ -0,0 +1,78 @@ +$ git log -p --first-parent master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +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 + +commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:01:00 2006 +0000 + + Second + + This is the second commit. + +diff --git a/dir/sub b/dir/sub +index 35d242b..8422d40 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++C ++D +diff --git a/file0 b/file0 +index 01e79c3..b414108 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++4 ++5 ++6 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 + +commit 444ac553ac7612cc88969031b02b3767fb8a353a +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:00:00 2006 +0000 + + Initial +$ diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_master index f8fefef2c3..bf1326dc36 100644 --- a/t/t4013/diff.log_-p_master +++ b/t/t4013/diff.log_-p_master @@ -1,6 +1,6 @@ $ git log -p master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_master index e9d9e7b40a..a8f6ce5abd 100644 --- a/t/t4013/diff.log_master +++ b/t/t4013/diff.log_master @@ -1,6 +1,6 @@ $ git log master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.rev-list_--children_HEAD b/t/t4013/diff.rev-list_--children_HEAD new file mode 100644 index 0000000000..e7f17d5aa0 --- /dev/null +++ b/t/t4013/diff.rev-list_--children_HEAD @@ -0,0 +1,7 @@ +$ git rev-list --children HEAD +59d314ad6f356dd08601a4cd5e530381da3e3c64 +c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a 59d314ad6f356dd08601a4cd5e530381da3e3c64 +9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 59d314ad6f356dd08601a4cd5e530381da3e3c64 +1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +444ac553ac7612cc88969031b02b3767fb8a353a 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a +$ diff --git a/t/t4013/diff.rev-list_--parents_HEAD b/t/t4013/diff.rev-list_--parents_HEAD new file mode 100644 index 0000000000..65d2a80208 --- /dev/null +++ b/t/t4013/diff.rev-list_--parents_HEAD @@ -0,0 +1,7 @@ +$ git rev-list --parents HEAD +59d314ad6f356dd08601a4cd5e530381da3e3c64 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a +c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a 444ac553ac7612cc88969031b02b3767fb8a353a +9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 +1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 444ac553ac7612cc88969031b02b3767fb8a353a +444ac553ac7612cc88969031b02b3767fb8a353a +$ diff --git a/t/t4013/diff.show_--first-parent_master b/t/t4013/diff.show_--first-parent_master new file mode 100644 index 0000000000..3dcbe473a0 --- /dev/null +++ b/t/t4013/diff.show_--first-parent_master @@ -0,0 +1,30 @@ +$ git show --first-parent master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index cead32e..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -4,3 +4,5 @@ C + D + E + F ++1 ++2 +diff --git a/file0 b/file0 +index b414108..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -4,3 +4,6 @@ + 4 + 5 + 6 ++A ++B ++C +$ diff --git a/t/t4013/diff.show_-c_master b/t/t4013/diff.show_-c_master new file mode 100644 index 0000000000..81aba8da96 --- /dev/null +++ b/t/t4013/diff.show_-c_master @@ -0,0 +1,36 @@ +$ git show -c master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --combined dir/sub +index cead32e,7289e35..992913c +--- a/dir/sub ++++ b/dir/sub +@@@ -1,6 -1,4 +1,8 @@@ + A + B + +C + +D + +E + +F ++ 1 ++ 2 +diff --combined file0 +index b414108,f4615da..10a8a9f +--- a/file0 ++++ b/file0 +@@@ -1,6 -1,6 +1,9 @@@ + 1 + 2 + 3 + +4 + +5 + +6 ++ A ++ B ++ C +$ diff --git a/t/t4013/diff.show_-m_master b/t/t4013/diff.show_-m_master new file mode 100644 index 0000000000..4ea2ee453d --- /dev/null +++ b/t/t4013/diff.show_-m_master @@ -0,0 +1,93 @@ +$ git show -m master +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index cead32e..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -4,3 +4,5 @@ C + D + E + F ++1 ++2 +diff --git a/file0 b/file0 +index b414108..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -4,3 +4,6 @@ + 4 + 5 + 6 ++A ++B ++C + +commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (from c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a) +Merge: 9a6d494 c7a2ab9 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:04:00 2006 +0000 + + Merge branch 'side' + +diff --git a/dir/sub b/dir/sub +index 7289e35..992913c 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,4 +1,8 @@ + A + B ++C ++D ++E ++F + 1 + 2 +diff --git a/file0 b/file0 +index f4615da..10a8a9f 100644 +--- a/file0 ++++ b/file0 +@@ -1,6 +1,9 @@ + 1 + 2 + 3 ++4 ++5 ++6 + A + B + C +diff --git a/file1 b/file1 +new file mode 100644 +index 0000000..b1e6722 +--- /dev/null ++++ b/file1 +@@ -0,0 +1,3 @@ ++A ++B ++C +diff --git a/file2 b/file2 +deleted file mode 100644 +index 01e79c3..0000000 +--- a/file2 ++++ /dev/null +@@ -1,3 +0,0 @@ +-1 +-2 +-3 +diff --git a/file3 b/file3 +deleted file mode 100644 +index 7289e35..0000000 +--- a/file3 ++++ /dev/null +@@ -1,4 +0,0 @@ +-A +-B +-1 +-2 +$ diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_master index 9e6e1f2710..fb08ce0e46 100644 --- a/t/t4013/diff.show_master +++ b/t/t4013/diff.show_master @@ -1,6 +1,6 @@ $ git show master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master index 5facf2543d..e96ff1fb8c 100644 --- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master @@ -1,6 +1,6 @@ $ git whatchanged --root --cc --patch-with-stat --summary master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master index 10f6767e49..c0aff68ef6 100644 --- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master +++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master @@ -1,6 +1,6 @@ $ git whatchanged --root -c --patch-with-stat --summary master commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 -Merge: 9a6d494... c7a2ab9... +Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> Date: Mon Jun 26 00:04:00 2006 +0000 diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 4795872a77..f87434b9f8 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -3,29 +3,30 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='Format-patch skipping already incorporated patches' +test_description='various format-patch tests' . ./test-lib.sh test_expect_success setup ' for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file && - git add file && + cat file >elif && + git add file elif && 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 && - git update-index file && - git commit -m "Side change #1" && + test_chmod +x elif && + git commit -m "Side changes #1" && for i in D E F; do echo "$i"; done >>file && git update-index file && - git commit -m "Side change #2" && + 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 && - git commit -m "Side change #3" && + git commit -m "Side changes #3 with \\n backslash-n in it." && git checkout master && git diff-tree -p C2 | git apply --index && @@ -66,4 +67,602 @@ test_expect_success "format-patch --ignore-if-in-upstream result applies" ' test $cnt = 2 ' +test_expect_success 'commit did not screw up the log message' ' + + git cat-file commit side | grep "^Side .* with .* backslash-n" + +' + +test_expect_success 'format-patch did not screw up the log message' ' + + grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 && + grep "^Subject: .*Side changes #3 with .* backslash-n" patch1 + +' + +test_expect_success 'replay did not screw up the log message' ' + + git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n" + +' + +test_expect_success 'extra headers' ' + + git config format.headers "To: R. E. Cipient <rcipient@example.com> +" && + git config --add format.headers "Cc: S. E. Cipient <scipient@example.com> +" && + git format-patch --stdout master..side > patch2 && + sed -e "/^\$/q" patch2 > hdrs2 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 && + grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2 + +' + +test_expect_success 'extra headers without newlines' ' + + git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" && + git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" && + git format-patch --stdout master..side >patch3 && + sed -e "/^\$/q" patch3 > hdrs3 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 && + grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3 + +' + +test_expect_success 'extra headers with multiple To:s' ' + + git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" && + git config --add format.headers "To: S. E. Cipient <scipient@example.com>" && + git format-patch --stdout master..side > patch4 && + sed -e "/^\$/q" patch4 > hdrs4 && + grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 && + grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4 +' + +test_expect_success 'additional command line cc' ' + + git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" && + git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 && + grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 && + grep "^ *S. E. Cipient <scipient@example.com>\$" patch5 +' + +test_expect_success 'command line headers' ' + + git config --unset-all format.headers && + git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 && + grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6 +' + +test_expect_success 'configuration headers and command line headers' ' + + git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" && + git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 && + grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 && + grep "^ *S. E. Cipient <scipient@example.com>\$" patch7 +' + +test_expect_success 'command line To: header' ' + + git config --unset-all format.headers && + git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8 +' + +test_expect_success 'configuration To: header' ' + + git config format.to "R. E. Cipient <rcipient@example.com>" && + git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9 +' + +test_expect_success '--no-to overrides config.to' ' + + git config --replace-all format.to \ + "R. E. Cipient <rcipient@example.com>" && + git format-patch --no-to --stdout master..side | + sed -e "/^\$/q" >patch10 && + ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10 +' + +test_expect_success '--no-to and --to replaces config.to' ' + + git config --replace-all format.to \ + "Someone <someone@out.there>" && + git format-patch --no-to --to="Someone Else <else@out.there>" \ + --stdout master..side | + sed -e "/^\$/q" >patch11 && + ! grep "^To: Someone <someone@out.there>\$" patch11 && + grep "^To: Someone Else <else@out.there>\$" patch11 +' + +test_expect_success '--no-cc overrides config.cc' ' + + git config --replace-all format.cc \ + "C. E. Cipient <rcipient@example.com>" && + git format-patch --no-cc --stdout master..side | + sed -e "/^\$/q" >patch12 && + ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12 +' + +test_expect_success '--no-add-headers overrides config.headers' ' + + git config --replace-all format.headers \ + "Header1: B. E. Cipient <rcipient@example.com>" && + git format-patch --no-add-headers --stdout master..side | + sed -e "/^\$/q" >patch13 && + ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13 +' + +test_expect_success 'multiple files' ' + + rm -rf patches/ && + git checkout side && + git format-patch -o patches/ master && + ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch +' + +check_threading () { + expect="$1" && + shift && + (git format-patch --stdout "$@"; echo $? > status.out) | + # Prints everything between the Message-ID and In-Reply-To, + # and replaces all Message-ID-lookalikes by a sequence number + perl -ne ' + if (/^(message-id|references|in-reply-to)/i) { + $printing = 1; + } elsif (/^\S/) { + $printing = 0; + } + if ($printing) { + $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1}); + for $k (keys %h) {s/$k/$h{$k}/}; + print; + } + print "---\n" if /^From /i; + ' > actual && + test 0 = "$(cat status.out)" && + test_cmp "$expect" actual +} + +cat >> expect.no-threading <<EOF +--- +--- +--- +EOF + +test_expect_success 'no threading' ' + git checkout side && + check_threading expect.no-threading master +' + +cat > expect.thread <<EOF +--- +Message-Id: <0> +--- +Message-Id: <1> +In-Reply-To: <0> +References: <0> +--- +Message-Id: <2> +In-Reply-To: <0> +References: <0> +EOF + +test_expect_success 'thread' ' + check_threading expect.thread --thread master +' + +cat > expect.in-reply-to <<EOF +--- +Message-Id: <0> +In-Reply-To: <1> +References: <1> +--- +Message-Id: <2> +In-Reply-To: <1> +References: <1> +--- +Message-Id: <3> +In-Reply-To: <1> +References: <1> +EOF + +test_expect_success 'thread in-reply-to' ' + check_threading expect.in-reply-to --in-reply-to="<test.message>" \ + --thread master +' + +cat > expect.cover-letter <<EOF +--- +Message-Id: <0> +--- +Message-Id: <1> +In-Reply-To: <0> +References: <0> +--- +Message-Id: <2> +In-Reply-To: <0> +References: <0> +--- +Message-Id: <3> +In-Reply-To: <0> +References: <0> +EOF + +test_expect_success 'thread cover-letter' ' + check_threading expect.cover-letter --cover-letter --thread master +' + +cat > expect.cl-irt <<EOF +--- +Message-Id: <0> +In-Reply-To: <1> +References: <1> +--- +Message-Id: <2> +In-Reply-To: <0> +References: <1> + <0> +--- +Message-Id: <3> +In-Reply-To: <0> +References: <1> + <0> +--- +Message-Id: <4> +In-Reply-To: <0> +References: <1> + <0> +EOF + +test_expect_success 'thread cover-letter in-reply-to' ' + check_threading expect.cl-irt --cover-letter \ + --in-reply-to="<test.message>" --thread master +' + +test_expect_success 'thread explicit shallow' ' + check_threading expect.cl-irt --cover-letter \ + --in-reply-to="<test.message>" --thread=shallow master +' + +cat > expect.deep <<EOF +--- +Message-Id: <0> +--- +Message-Id: <1> +In-Reply-To: <0> +References: <0> +--- +Message-Id: <2> +In-Reply-To: <1> +References: <0> + <1> +EOF + +test_expect_success 'thread deep' ' + check_threading expect.deep --thread=deep master +' + +cat > expect.deep-irt <<EOF +--- +Message-Id: <0> +In-Reply-To: <1> +References: <1> +--- +Message-Id: <2> +In-Reply-To: <0> +References: <1> + <0> +--- +Message-Id: <3> +In-Reply-To: <2> +References: <1> + <0> + <2> +EOF + +test_expect_success 'thread deep in-reply-to' ' + check_threading expect.deep-irt --thread=deep \ + --in-reply-to="<test.message>" master +' + +cat > expect.deep-cl <<EOF +--- +Message-Id: <0> +--- +Message-Id: <1> +In-Reply-To: <0> +References: <0> +--- +Message-Id: <2> +In-Reply-To: <1> +References: <0> + <1> +--- +Message-Id: <3> +In-Reply-To: <2> +References: <0> + <1> + <2> +EOF + +test_expect_success 'thread deep cover-letter' ' + check_threading expect.deep-cl --cover-letter --thread=deep master +' + +cat > expect.deep-cl-irt <<EOF +--- +Message-Id: <0> +In-Reply-To: <1> +References: <1> +--- +Message-Id: <2> +In-Reply-To: <0> +References: <1> + <0> +--- +Message-Id: <3> +In-Reply-To: <2> +References: <1> + <0> + <2> +--- +Message-Id: <4> +In-Reply-To: <3> +References: <1> + <0> + <2> + <3> +EOF + +test_expect_success 'thread deep cover-letter in-reply-to' ' + check_threading expect.deep-cl-irt --cover-letter \ + --in-reply-to="<test.message>" --thread=deep master +' + +test_expect_success 'thread via config' ' + git config format.thread true && + check_threading expect.thread master +' + +test_expect_success 'thread deep via config' ' + git config format.thread deep && + check_threading expect.deep master +' + +test_expect_success 'thread config + override' ' + git config format.thread deep && + check_threading expect.thread --thread master +' + +test_expect_success 'thread config + --no-thread' ' + git config format.thread deep && + check_threading expect.no-threading --no-thread master +' + +test_expect_success 'excessive subject' ' + + rm -rf patches/ && + git checkout side && + 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 && + git commit -m "This is an excessively long subject line for a message due to the habit some projects have of not having a short, one-line subject at the start of the commit message, but rather sticking a whole paragraph right at the start as the only thing in the commit message. It had better not become the filename for the patch." && + git format-patch -o patches/ master..side && + ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch +' + +test_expect_success 'cover-letter inherits diff options' ' + + git mv file foo && + git commit -m foo && + git format-patch --cover-letter -1 && + ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch && + git format-patch --cover-letter -1 -M && + grep "file => foo .* 0 *\$" 0000-cover-letter.patch + +' + +cat > expect << EOF + This is an excessively long subject line for a message due to the + habit some projects have of not having a short, one-line subject at + the start of the commit message, but rather sticking a whole + paragraph right at the start as the only thing in the commit + message. It had better not become the filename for the patch. + foo + +EOF + +test_expect_success 'shortlog of cover-letter wraps overly-long onelines' ' + + git format-patch --cover-letter -2 && + sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output && + test_cmp expect output + +' + +cat > expect << EOF +--- + file | 16 ++++++++++++++++ + 1 files changed, 16 insertions(+), 0 deletions(-) + +diff --git a/file b/file +index 40f36c6..2dc5c23 100644 +--- a/file ++++ b/file +@@ -13,4 +13,20 @@ C + 10 + D + E + F ++5 +EOF + +test_expect_success 'format-patch respects -U' ' + + git format-patch -U4 -2 && + sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output && + test_cmp expect output + +' + +cat > expect << EOF + +diff --git a/file b/file +index 40f36c6..2dc5c23 100644 +--- a/file ++++ b/file +@@ -14,3 +14,19 @@ C + D + E + F ++5 +EOF + +test_expect_success 'format-patch -p suppresses stat' ' + + git format-patch -p -2 && + sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output && + test_cmp expect output + +' + +test_expect_success 'format-patch from a subdirectory (1)' ' + filename=$( + rm -rf sub && + mkdir -p sub/dir && + cd sub/dir && + git format-patch -1 + ) && + case "$filename" in + 0*) + ;; # ok + *) + echo "Oops? $filename" + false + ;; + esac && + test -f "$filename" +' + +test_expect_success 'format-patch from a subdirectory (2)' ' + filename=$( + rm -rf sub && + mkdir -p sub/dir && + cd sub/dir && + git format-patch -1 -o .. + ) && + case "$filename" in + ../0*) + ;; # ok + *) + echo "Oops? $filename" + false + ;; + esac && + basename=$(expr "$filename" : ".*/\(.*\)") && + test -f "sub/$basename" +' + +test_expect_success 'format-patch from a subdirectory (3)' ' + rm -f 0* && + filename=$( + rm -rf sub && + mkdir -p sub/dir && + cd sub/dir && + git format-patch -1 -o "$TRASH_DIRECTORY" + ) && + basename=$(expr "$filename" : ".*/\(.*\)") && + test -f "$basename" +' + +test_expect_success 'format-patch --in-reply-to' ' + git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 && + grep "^In-Reply-To: <baz@foo.bar>" patch8 && + grep "^References: <baz@foo.bar>" patch8 +' + +test_expect_success 'format-patch --signoff' ' + git format-patch -1 --signoff --stdout | + grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +' + +echo "fatal: --name-only does not make sense" > expect.name-only +echo "fatal: --name-status does not make sense" > expect.name-status +echo "fatal: --check does not make sense" > expect.check + +test_expect_success 'options no longer allowed for format-patch' ' + test_must_fail git format-patch --name-only 2> output && + test_cmp expect.name-only output && + test_must_fail git format-patch --name-status 2> output && + test_cmp expect.name-status output && + test_must_fail git format-patch --check 2> output && + test_cmp expect.check output' + +test_expect_success 'format-patch --numstat should produce a patch' ' + git format-patch --numstat --stdout master..side > output && + test 6 = $(grep "^diff --git a/" output | wc -l)' + +test_expect_success 'format-patch -- <path>' ' + git format-patch master..side -- file 2>error && + ! grep "Use .--" error +' + +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 adf4993bac..935d101fe8 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -7,7 +7,7 @@ test_description='Test special whitespace in diff engine. ' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh # Ray Lehtiniemi's example @@ -17,7 +17,7 @@ do { } while (0); EOF -git-update-index --add x +git update-index --add x cat << EOF > x do @@ -42,14 +42,14 @@ index adf3937..6edc172 100644 +while (0); EOF -git-diff > out -test_expect_success "Ray's example without options" 'diff -u expect out' +git diff > out +test_expect_success "Ray's example without options" 'test_cmp expect out' -git-diff -w > out -test_expect_success "Ray's example with -w" 'diff -u expect out' +git diff -w > out +test_expect_success "Ray's example with -w" 'test_cmp expect out' -git-diff -b > out -test_expect_success "Ray's example with -b" 'diff -u expect out' +git diff -b > out +test_expect_success "Ray's example with -b" 'test_cmp expect out' tr 'Q' '\015' << EOF > x whitespace at beginning @@ -60,18 +60,18 @@ unchanged line CR at endQ EOF -git-update-index x +git update-index x -cat << EOF > x +tr '_' ' ' << EOF > x whitespace at beginning whitespace change white space in the middle -whitespace at end +whitespace at end__ unchanged line CR at end EOF -tr 'Q' '\015' << EOF > expect +tr 'Q_' '\015 ' << EOF > expect diff --git a/x b/x index d99af23..8b32fb5 100644 --- a/x @@ -84,20 +84,24 @@ index d99af23..8b32fb5 100644 + whitespace at beginning +whitespace change +white space in the middle -+whitespace at end ++whitespace at end__ unchanged line -CR at endQ +CR at end EOF -git-diff > out -test_expect_success 'another test, without options' 'diff -u expect out' +git diff > out +test_expect_success 'another test, without options' 'test_cmp expect out' cat << EOF > expect -diff --git a/x b/x -index d99af23..8b32fb5 100644 EOF -git-diff -w > out -test_expect_success 'another test, with -w' 'diff -u expect out' +git diff -w > out +test_expect_success 'another test, with -w' 'test_cmp expect out' +git diff -w -b > out +test_expect_success 'another test, with -w -b' 'test_cmp expect out' +git diff -w --ignore-space-at-eol > out +test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expect out' +git diff -w -b --ignore-space-at-eol > out +test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out' tr 'Q' '\015' << EOF > expect diff --git a/x b/x @@ -114,7 +118,377 @@ index d99af23..8b32fb5 100644 unchanged line CR at endQ EOF -git-diff -b > out -test_expect_success 'another test, with -b' 'diff -u expect out' +git diff -b > out +test_expect_success 'another test, with -b' 'test_cmp expect out' +git diff -b --ignore-space-at-eol > out +test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out' + +tr 'Q' '\015' << EOF > expect +diff --git a/x b/x +index d99af23..8b32fb5 100644 +--- a/x ++++ b/x +@@ -1,6 +1,6 @@ +-whitespace at beginning +-whitespace change +-whitespace in the middle ++ whitespace at beginning ++whitespace change ++white space in the middle + whitespace at end + unchanged line + CR at endQ +EOF +git diff --ignore-space-at-eol > out +test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out' + +test_expect_success 'check mixed spaces and tabs in indent' ' + + # This is indented with SP HT SP. + echo " foo();" > x && + git diff --check | grep "space before tab in indent" + +' + +test_expect_success 'check mixed tabs and spaces in indent' ' + + # This is indented with HT SP HT. + echo " foo();" > x && + git diff --check | grep "space before tab in indent" + +' + +test_expect_success 'check with no whitespace errors' ' + + git commit -m "snapshot" && + echo "foo();" > x && + git diff --check + +' + +test_expect_success 'check with trailing whitespace' ' + + echo "foo(); " > x && + test_must_fail git diff --check + +' + +test_expect_success 'check with space before tab in indent' ' + + # indent has space followed by hard tab + echo " foo();" > x && + test_must_fail git diff --check + +' + +test_expect_success '--check and --exit-code are not exclusive' ' + + git checkout x && + git diff --check --exit-code + +' + +test_expect_success '--check and --quiet are not exclusive' ' + + git diff --check --quiet + +' + +test_expect_success 'check staged with no whitespace errors' ' + + echo "foo();" > x && + git add x && + git diff --cached --check + +' + +test_expect_success 'check staged with trailing whitespace' ' + + echo "foo(); " > x && + git add x && + test_must_fail git diff --cached --check + +' + +test_expect_success 'check staged with space before tab in indent' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + test_must_fail git diff --cached --check + +' + +test_expect_success 'check with no whitespace errors (diff-index)' ' + + echo "foo();" > x && + git add x && + git diff-index --check HEAD + +' + +test_expect_success 'check with trailing whitespace (diff-index)' ' + + echo "foo(); " > x && + git add x && + test_must_fail git diff-index --check HEAD + +' + +test_expect_success 'check with space before tab in indent (diff-index)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + test_must_fail git diff-index --check HEAD + +' + +test_expect_success 'check staged with no whitespace errors (diff-index)' ' + + echo "foo();" > x && + git add x && + git diff-index --cached --check HEAD + +' + +test_expect_success 'check staged with trailing whitespace (diff-index)' ' + + echo "foo(); " > x && + git add x && + test_must_fail git diff-index --cached --check HEAD + +' + +test_expect_success 'check staged with space before tab in indent (diff-index)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + test_must_fail git diff-index --cached --check HEAD + +' + +test_expect_success 'check with no whitespace errors (diff-tree)' ' + + echo "foo();" > x && + git commit -m "new commit" x && + git diff-tree --check HEAD^ HEAD + +' + +test_expect_success 'check with trailing whitespace (diff-tree)' ' + + echo "foo(); " > x && + git commit -m "another commit" x && + test_must_fail git diff-tree --check HEAD^ HEAD + +' + +test_expect_success 'check with space before tab in indent (diff-tree)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git commit -m "yet another" x && + test_must_fail git diff-tree --check HEAD^ HEAD + +' + +test_expect_success 'check trailing whitespace (trailing-space: off)' ' + + git config core.whitespace "-trailing-space" && + echo "foo (); " > x && + git diff --check + +' + +test_expect_success 'check trailing whitespace (trailing-space: on)' ' + + git config core.whitespace "trailing-space" && + echo "foo (); " > x && + test_must_fail git diff --check + +' + +test_expect_success 'check space before tab in indent (space-before-tab: off)' ' + + # indent contains space followed by HT + git config core.whitespace "-space-before-tab" && + echo " foo ();" > x && + git diff --check + +' + +test_expect_success 'check space before tab in indent (space-before-tab: on)' ' + + # indent contains space followed by HT + git config core.whitespace "space-before-tab" && + echo " foo (); " > x && + test_must_fail git diff --check + +' + +test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' ' + + git config core.whitespace "-indent-with-non-tab" + echo " foo ();" > x && + git diff --check + +' + +test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' ' + + git config core.whitespace "indent-with-non-tab" && + echo " foo ();" > x && + test_must_fail git diff --check + +' + +test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' ' + + git config core.whitespace "indent-with-non-tab" && + echo " foo ();" > x && + test_must_fail git diff --check + +' + +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 && + echo "foo(); " >> x && + git diff --check | grep "x:2:" + +' + +test_expect_success 'checkdiff detects new trailing blank lines (1)' ' + echo "foo();" >x && + echo "" >>x && + git diff --check | grep "new blank line" +' + +test_expect_success 'checkdiff detects new trailing blank lines (2)' ' + { echo a; echo b; echo; echo; } >x && + git add x && + { echo a; echo; echo; echo; echo; } >x && + git diff --check | grep "new blank line" +' + +test_expect_success 'checkdiff allows new blank lines' ' + git checkout x && + mv x y && + ( + echo "/* This is new */" && + echo "" && + cat y + ) >x && + git diff --check +' + +cat <<EOF >expect +EOF +test_expect_success 'whitespace-only changes not reported' ' + git reset --hard && + echo >x "hello world" && + git add x && + git commit -m "hello 1" && + echo >x "hello world" && + git diff -b >actual && + 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 && + echo >x hello && + git commit -m "one side" x && + git checkout HEAD^ && + echo >x goodbye && + git commit -m "the other side" x && + git config core.autocrlf true && + test_must_fail git merge master && + + git diff | sed -e "1,/^@@@/d" >actual && + ! grep "^-" actual + +' test_done diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index 2e7cd5f255..34e5144eed 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -13,8 +13,8 @@ P1='pathname with HT' P2='pathname with SP' P3='pathname with LF' -: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || { - echo >&2 'Filesystem does not support tabs in names' +: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || { + skip_all='Your filesystem does not allow tabs in filenames, test skipped.' test_done } @@ -49,22 +49,22 @@ cat >expect <<\EOF EOF test_expect_success 'git diff --summary -M HEAD' ' git diff --summary -M HEAD >actual && - diff -u expect actual + test_cmp expect actual ' cat >expect <<\EOF - pathname.1 => "Rpathname\twith HT.0" | 0 - pathname.3 => "Rpathname\nwith LF.0" | 0 - "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 - pathname.2 => Rpathname with SP.0 | 0 - "pathname\twith HT.2" => Rpathname with SP.1 | 0 - pathname.0 => Rpathname.0 | 0 - "pathname\twith HT.0" => Rpathname.1 | 0 + pathname.1 => "Rpathname\twith HT.0" | 0 + pathname.3 => "Rpathname\nwith LF.0" | 0 + "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 + pathname.2 => Rpathname with SP.0 | 0 + "pathname\twith HT.2" => Rpathname with SP.1 | 0 + pathname.0 => Rpathname.0 | 0 + "pathname\twith HT.0" => Rpathname.1 | 0 7 files changed, 0 insertions(+), 0 deletions(-) EOF test_expect_success 'git diff --stat -M HEAD' ' git diff --stat -M HEAD >actual && - diff -u expect actual + test_cmp expect actual ' test_done diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh new file mode 100755 index 0000000000..61589853df --- /dev/null +++ b/t/t4017-diff-retval.sh @@ -0,0 +1,166 @@ +#!/bin/sh + +test_description='Return value of diffs' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo "1 " >a && + git add . && + git commit -m zeroth && + echo 1 >a && + git add . && + git commit -m first && + echo 2 >b && + git add . && + git commit -a -m second +' + +test_expect_success 'git diff --quiet -w HEAD^^ HEAD^' ' + git diff --quiet -w HEAD^^ HEAD^ +' + +test_expect_success 'git diff --quiet HEAD^^ HEAD^' ' + test_must_fail git diff --quiet HEAD^^ HEAD^ +' + +test_expect_success 'git diff --quiet -w HEAD^ HEAD' ' + test_must_fail git diff --quiet -w HEAD^ HEAD +' + +test_expect_success 'git diff-tree HEAD^ HEAD' ' + git diff-tree --exit-code HEAD^ HEAD + test $? = 1 +' +test_expect_success 'git diff-tree HEAD^ HEAD -- a' ' + git diff-tree --exit-code HEAD^ HEAD -- a + test $? = 0 +' +test_expect_success 'git diff-tree HEAD^ HEAD -- b' ' + git diff-tree --exit-code HEAD^ HEAD -- b + test $? = 1 +' +test_expect_success 'echo HEAD | git diff-tree --stdin' ' + echo $(git rev-parse HEAD) | git diff-tree --exit-code --stdin + test $? = 1 +' +test_expect_success 'git diff-tree HEAD HEAD' ' + git diff-tree --exit-code HEAD HEAD + test $? = 0 +' +test_expect_success 'git diff-files' ' + git diff-files --exit-code + test $? = 0 +' +test_expect_success 'git diff-index --cached HEAD' ' + git diff-index --exit-code --cached HEAD + test $? = 0 +' +test_expect_success 'git diff-index --cached HEAD^' ' + git diff-index --exit-code --cached HEAD^ + test $? = 1 +' +test_expect_success 'git diff-index --cached HEAD^' ' + echo text >>b && + echo 3 >c && + git add . && { + git diff-index --exit-code --cached HEAD^ + test $? = 1 + } +' +test_expect_success 'git diff-tree -Stext HEAD^ HEAD -- b' ' + git commit -m "text in b" && { + git diff-tree -p --exit-code -Stext HEAD^ HEAD -- b + test $? = 1 + } +' +test_expect_success 'git diff-tree -Snot-found HEAD^ HEAD -- b' ' + git diff-tree -p --exit-code -Snot-found HEAD^ HEAD -- b + test $? = 0 +' +test_expect_success 'git diff-files' ' + echo 3 >>c && { + git diff-files --exit-code + test $? = 1 + } +' +test_expect_success 'git diff-index --cached HEAD' ' + git update-index c && { + git diff-index --exit-code --cached HEAD + test $? = 1 + } +' + +test_expect_success '--check --exit-code returns 0 for no difference' ' + + git diff --check --exit-code + +' + +test_expect_success '--check --exit-code returns 1 for a clean difference' ' + + echo "good" > a && + git diff --check --exit-code + test $? = 1 + +' + +test_expect_success '--check --exit-code returns 3 for a dirty difference' ' + + echo "bad " >> a && + git diff --check --exit-code + test $? = 3 + +' + +test_expect_success '--check with --no-pager returns 2 for dirty difference' ' + + git --no-pager diff --check + test $? = 2 + +' + +test_expect_success 'check should test not just the last line' ' + echo "" >>a && + git --no-pager diff --check + test $? = 2 + +' + +test_expect_success 'check detects leftover conflict markers' ' + git reset --hard && + git checkout HEAD^ && + echo binary >>b && + git commit -m "side" b && + test_must_fail git merge master && + git add b && ( + git --no-pager diff --cached --check >test.out + test $? = 2 + ) && + test 3 = $(grep "conflict marker" test.out | wc -l) && + git reset --hard +' + +test_expect_success 'check honors conflict marker length' ' + git reset --hard && + echo ">>>>>>> boo" >>b && + echo "======" >>a && + git diff --check a && + ( + git diff --check b + test $? = 2 + ) && + git reset --hard && + echo ">>>>>>>> boo" >>b && + echo "========" >>a && + git diff --check && + echo "b conflict-marker-size=8" >.gitattributes && + ( + git diff --check b + test $? = 2 + ) && + git diff --check a && + git reset --hard +' + +test_done diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh new file mode 100755 index 0000000000..5b10e976a3 --- /dev/null +++ b/t/t4018-diff-funcname.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test custom diff function name patterns' + +. ./test-lib.sh + +LF=' +' + +cat > Beer.java << EOF +public class Beer +{ + int special; + public static void main(String args[]) + { + String s=" "; + for(int x = 99; x > 0; x--) + { + System.out.print(x + " bottles of beer on the wall " + + x + " bottles of beer\n" + + "Take one down, pass it around, " + (x - 1) + + " bottles of beer on the wall.\n"); + } + System.out.print("Go to the store, buy some more,\n" + + "99 bottles of beer on the wall.\n"); + } +} +EOF + +sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java + +builtin_patterns="bibtex cpp 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 ) + ' +done + +test_expect_success 'default behaviour' ' + rm -f .gitattributes && + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ public class Beer" +' + +test_expect_success 'preset java pattern' ' + echo "*.java diff=java" >.gitattributes && + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ public static void main(" +' + +git config diff.java.funcname '!static +!String +[^ ].*s.*' + +test_expect_success 'custom pattern' ' + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ int special;$" +' + +test_expect_success 'last regexp must not be negated' ' + git config diff.java.funcname "!static" && + git diff --no-index Beer.java Beer-correct.java 2>&1 | + grep "fatal: Last expression must not be negated:" +' + +test_expect_success 'pattern which matches to end of line' ' + git config diff.java.funcname "Beer$" && + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ Beer" +' + +test_expect_success 'alternation in pattern' ' + git config diff.java.xfuncname "^[ ]*((public|static).*)$" && + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ public static void main(" +' + +test_done diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh new file mode 100755 index 0000000000..f6d1f1ebab --- /dev/null +++ b/t/t4019-diff-wserror.sh @@ -0,0 +1,202 @@ +#!/bin/sh + +test_description='diff whitespace error detection' + +. ./test-lib.sh + +test_expect_success setup ' + + git config diff.color.whitespace "blue reverse" && + >F && + git add F && + echo " Eight SP indent" >>F && + echo " HT and SP indent" >>F && + echo "With trailing SP " >>F && + echo "Carriage ReturnQ" | tr Q "\015" >>F && + echo "No problem" >>F && + echo >>F + +' + +blue_grep='7;34m' ;# ESC [ 7 ; 3 4 m + +printf "\033[%s" "$blue_grep" >check-grep +if (grep "$blue_grep" <check-grep | grep "$blue_grep") >/dev/null 2>&1 +then + grep_a=grep +elif (grep -a "$blue_grep" <check-grep | grep -a "$blue_grep") >/dev/null 2>&1 +then + grep_a='grep -a' +else + grep_a=grep ;# expected to fail... +fi +rm -f check-grep + +prepare_output () { + git diff --color >output + $grep_a "$blue_grep" output >error + $grep_a -v "$blue_grep" output >normal +} + +test_expect_success default ' + + prepare_output + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With error >/dev/null && + grep Return error >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -trail' ' + + git config core.whitespace -trail + prepare_output + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With normal >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -trail (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=-trail" >.gitattributes + prepare_output + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With normal >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -space' ' + + rm -f .gitattributes + git config core.whitespace -space + prepare_output + + grep Eight normal >/dev/null && + grep HT normal >/dev/null && + grep With error >/dev/null && + grep Return error >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -space (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=-space" >.gitattributes + prepare_output + + grep Eight normal >/dev/null && + grep HT normal >/dev/null && + grep With error >/dev/null && + grep Return error >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'with indent-non-tab only' ' + + rm -f .gitattributes + git config core.whitespace indent,-trailing,-space + prepare_output + + grep Eight error >/dev/null && + grep HT normal >/dev/null && + grep With normal >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'with indent-non-tab only (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=indent,-trailing,-space" >.gitattributes + prepare_output + + grep Eight error >/dev/null && + grep HT normal >/dev/null && + grep With normal >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'with cr-at-eol' ' + + rm -f .gitattributes + git config core.whitespace cr-at-eol + prepare_output + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With error >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'with cr-at-eol (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=trailing,cr-at-eol" >.gitattributes + prepare_output + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With error >/dev/null && + grep Return normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'trailing empty lines (1)' ' + + rm -f .gitattributes && + test_must_fail git diff --check >output && + grep "new blank line at" output && + grep "trailing whitespace" output + +' + +test_expect_success 'trailing empty lines (2)' ' + + echo "F -whitespace" >.gitattributes && + git diff --check >output && + ! test -s output + +' + +test_expect_success 'do not color trailing cr in context' ' + git config --unset core.whitespace + rm -f .gitattributes && + echo AAAQ | tr Q "\015" >G && + git add G && + echo BBBQ | tr Q "\015" >>G + git diff --color G | tr "\015" Q >output && + grep "BBB.*${blue_grep}Q" output && + grep "AAA.*\[mQ" output + +' + +test_expect_success 'color new trailing blank lines' ' + { echo a; echo b; echo; echo; } >x && + git add x && + { echo a; echo; echo; echo; echo c; echo; echo; echo; echo; } >x && + git diff --color x >output && + cnt=$($grep_a "${blue_grep}" output | wc -l) && + test $cnt = 2 +' + +test_done diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh new file mode 100755 index 0000000000..a7602cf923 --- /dev/null +++ b/t/t4020-diff-external.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +test_description='external diff interface test' + +. ./test-lib.sh + +_z40=0000000000000000000000000000000000000000 + +test_expect_success setup ' + + test_tick && + echo initial >file && + git add file && + git commit -m initial && + + test_tick && + echo second >file && + git add file && + git commit -m second && + + test_tick && + echo third >file +' + +test_expect_success 'GIT_EXTERNAL_DIFF environment' ' + + GIT_EXTERNAL_DIFF=echo git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' ' + + GIT_EXTERNAL_DIFF=echo git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' ' + + GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute' ' + + git config diff.parrot.command echo && + + echo >.gitattributes "file diff=parrot" && + + git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'diff attribute should apply only to diff' ' + + git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute and --no-ext-diff' ' + + git diff --no-ext-diff | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute' ' + + git config --unset diff.parrot.command && + git config diff.color.command echo && + + echo >.gitattributes "file diff=color" && + + git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'diff attribute should apply only to diff' ' + + git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute and --no-ext-diff' ' + + git diff --no-ext-diff | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'no diff with -diff' ' + echo >.gitattributes "file -diff" && + git diff | grep Binary +' + +echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file + +test_expect_success 'force diff with "diff"' ' + echo >.gitattributes "file diff" && + git diff >actual && + test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual +' + +test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' ' + echo anotherfile > file2 && + git add file2 && + git commit -m "added 2nd file" && + echo modified >file2 && + GIT_EXTERNAL_DIFF=echo git diff +' + +test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' ' + touch file.ext && + git add file.ext && + echo with extension > file.ext && + GIT_EXTERNAL_DIFF=echo git diff file.ext | grep ......_file\.ext && + git update-index --force-remove file.ext && + rm file.ext +' + +echo "#!$SHELL_PATH" >fake-diff.sh +cat >> fake-diff.sh <<\EOF +cat $2 >> crlfed.txt +EOF +chmod a+x fake-diff.sh + +keep_only_cr () { + tr -dc '\015' +} + +test_expect_success 'external diff with autocrlf = true' ' + git config core.autocrlf true && + GIT_EXTERNAL_DIFF=./fake-diff.sh git diff && + test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c) +' + +test_expect_success 'diff --cached' ' + git add file && + git update-index --assume-unchanged file && + echo second >file && + git diff --cached >actual && + test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual +' + +test_done diff --git a/t/t4020/diff.NUL b/t/t4020/diff.NUL Binary files differnew file mode 100644 index 0000000000..db2f89090c --- /dev/null +++ b/t/t4020/diff.NUL diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh new file mode 100755 index 0000000000..709b3231ca --- /dev/null +++ b/t/t4021-format-patch-numbered.sh @@ -0,0 +1,124 @@ +#!/bin/sh +# +# Copyright (c) 2006 Brian C Gernhardt +# + +test_description='Format-patch numbering options' + +. ./test-lib.sh + +test_expect_success setup ' + + echo A > file && + git add file && + git commit -m First && + + echo B >> file && + git commit -a -m Second && + + echo C >> file && + git commit -a -m Third + +' + +# Each of these gets used multiple times. + +test_num_no_numbered() { + cnt=$(grep "^Subject: \[PATCH\]" $1 | wc -l) && + test $cnt = $2 +} + +test_single_no_numbered() { + test_num_no_numbered $1 1 +} + +test_no_numbered() { + test_num_no_numbered $1 2 +} + +test_single_numbered() { + grep "^Subject: \[PATCH 1/1\]" $1 +} + +test_numbered() { + grep "^Subject: \[PATCH 1/2\]" $1 && + grep "^Subject: \[PATCH 2/2\]" $1 +} + +test_expect_success 'single patch defaults to no numbers' ' + git format-patch --stdout HEAD~1 >patch0.single && + test_single_no_numbered patch0.single +' + +test_expect_success 'multiple patch defaults to numbered' ' + + git format-patch --stdout HEAD~2 >patch0.multiple && + test_numbered patch0.multiple + +' + +test_expect_success 'Use --numbered' ' + + git format-patch --numbered --stdout HEAD~1 >patch1 && + test_single_numbered patch1 + +' + +test_expect_success 'format.numbered = true' ' + + git config format.numbered true && + git format-patch --stdout HEAD~2 >patch2 && + test_numbered patch2 + +' + +test_expect_success 'format.numbered && single patch' ' + + git format-patch --stdout HEAD^ > patch3 && + test_single_numbered patch3 + +' + +test_expect_success 'format.numbered && --no-numbered' ' + + git format-patch --no-numbered --stdout HEAD~2 >patch4 && + test_no_numbered patch4 + +' + +test_expect_success 'format.numbered && --keep-subject' ' + + git format-patch --keep-subject --stdout HEAD^ >patch4a && + grep "^Subject: Third" patch4a + +' + +test_expect_success 'format.numbered = auto' ' + + git config format.numbered auto + git format-patch --stdout HEAD~2 > patch5 && + test_numbered patch5 + +' + +test_expect_success 'format.numbered = auto && single patch' ' + + git format-patch --stdout HEAD^ > patch6 && + test_single_no_numbered patch6 + +' + +test_expect_success 'format.numbered = auto && --no-numbered' ' + + git format-patch --no-numbered --stdout HEAD~2 > patch7 && + test_no_numbered patch7 + +' + +test_expect_success '--start-number && --numbered' ' + + git format-patch --start-number 3 --numbered --stdout HEAD~1 > patch8 && + grep "^Subject: \[PATCH 3/3\]" patch8 +' + +test_done diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh new file mode 100755 index 0000000000..2a537a21e8 --- /dev/null +++ b/t/t4022-diff-rewrite.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +test_description='rewrite diff' + +. ./test-lib.sh + +test_expect_success setup ' + + cat "$TEST_DIRECTORY"/../COPYING >test && + git add test && + tr \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \ + <"$TEST_DIRECTORY"/../COPYING >test + +' + +test_expect_success 'detect rewrite' ' + + actual=$(git diff-files -B --summary test) && + expr "$actual" : " rewrite test ([0-9]*%)$" || { + echo "Eh? <<$actual>>" + false + } + +' + +test_done + diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh new file mode 100755 index 0000000000..40a95a149e --- /dev/null +++ b/t/t4023-diff-rename-typechange.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='typechange rename detection' + +. ./test-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + +test_expect_success setup ' + + rm -f foo bar && + cat "$TEST_DIRECTORY"/../COPYING >foo && + ln -s linklink bar && + git add foo bar && + git commit -a -m Initial && + git tag one && + + rm -f foo bar && + cat "$TEST_DIRECTORY"/../COPYING >bar && + ln -s linklink foo && + git add foo bar && + git commit -a -m Second && + git tag two && + + rm -f foo bar && + cat "$TEST_DIRECTORY"/../COPYING >foo && + git add foo && + git commit -a -m Third && + git tag three && + + mv foo bar && + ln -s linklink foo && + git add foo bar && + git commit -a -m Fourth && + git tag four && + + # This is purely for sanity check + + rm -f foo bar && + cat "$TEST_DIRECTORY"/../COPYING >foo && + cat "$TEST_DIRECTORY"/../Makefile >bar && + git add foo bar && + git commit -a -m Fifth && + git tag five && + + rm -f foo bar && + cat "$TEST_DIRECTORY"/../Makefile >foo && + cat "$TEST_DIRECTORY"/../COPYING >bar && + git add foo bar && + git commit -a -m Sixth && + git tag six + +' + +test_expect_success 'cross renames to be detected for regular files' ' + + git diff-tree five six -r --name-status -B -M | sort >actual && + { + echo "R100 foo bar" + echo "R100 bar foo" + } | sort >expect && + test_cmp expect actual + +' + +test_expect_success 'cross renames to be detected for typechange' ' + + git diff-tree one two -r --name-status -B -M | sort >actual && + { + echo "R100 foo bar" + echo "R100 bar foo" + } | sort >expect && + test_cmp expect actual + +' + +test_expect_success 'moves and renames' ' + + git diff-tree three four -r --name-status -B -M | sort >actual && + { + echo "R100 foo bar" + echo "T100 foo" + } | sort >expect && + test_cmp expect actual + +' + +test_done diff --git a/t/t4024-diff-optimize-common.sh b/t/t4024-diff-optimize-common.sh new file mode 100755 index 0000000000..c4d733f5db --- /dev/null +++ b/t/t4024-diff-optimize-common.sh @@ -0,0 +1,157 @@ +#!/bin/sh + +test_description='common tail optimization' + +. ./test-lib.sh + +z=zzzzzzzz ;# 8 +z="$z$z$z$z$z$z$z$z" ;# 64 +z="$z$z$z$z$z$z$z$z" ;# 512 +z="$z$z$z$z" ;# 2048 +z2047=$(expr "$z" : '.\(.*\)') ; #2047 + +x=zzzzzzzzzz ;# 10 +y="$x$x$x$x$x$x$x$x$x$x" ;# 100 +z="$y$y$y$y$y$y$y$y$y$y" ;# 1000 +z1000=$z +z100=$y +z10=$x + +zs() { + count="$1" + while test "$count" -ge 1000 + do + count=$(($count - 1000)) + printf "%s" $z1000 + done + while test "$count" -ge 100 + do + count=$(($count - 100)) + printf "%s" $z100 + done + while test "$count" -ge 10 + do + count=$(($count - 10)) + printf "%s" $z10 + done + while test "$count" -ge 1 + do + count=$(($count - 1)) + printf "z" + done +} + +zc () { + sed -e "/^index/d" \ + -e "s/$z1000/Q/g" \ + -e "s/QQQQQQQQQ/Z9000/g" \ + -e "s/QQQQQQQQ/Z8000/g" \ + -e "s/QQQQQQQ/Z7000/g" \ + -e "s/QQQQQQ/Z6000/g" \ + -e "s/QQQQQ/Z5000/g" \ + -e "s/QQQQ/Z4000/g" \ + -e "s/QQQ/Z3000/g" \ + -e "s/QQ/Z2000/g" \ + -e "s/Q/Z1000/g" \ + -e "s/$z100/Q/g" \ + -e "s/QQQQQQQQQ/Z900/g" \ + -e "s/QQQQQQQQ/Z800/g" \ + -e "s/QQQQQQQ/Z700/g" \ + -e "s/QQQQQQ/Z600/g" \ + -e "s/QQQQQ/Z500/g" \ + -e "s/QQQQ/Z400/g" \ + -e "s/QQQ/Z300/g" \ + -e "s/QQ/Z200/g" \ + -e "s/Q/Z100/g" \ + -e "s/000Z//g" \ + -e "s/$z10/Q/g" \ + -e "s/QQQQQQQQQ/Z90/g" \ + -e "s/QQQQQQQQ/Z80/g" \ + -e "s/QQQQQQQ/Z70/g" \ + -e "s/QQQQQQ/Z60/g" \ + -e "s/QQQQQ/Z50/g" \ + -e "s/QQQQ/Z40/g" \ + -e "s/QQQ/Z30/g" \ + -e "s/QQ/Z20/g" \ + -e "s/Q/Z10/g" \ + -e "s/00Z//g" \ + -e "s/z/Q/g" \ + -e "s/QQQQQQQQQ/Z9/g" \ + -e "s/QQQQQQQQ/Z8/g" \ + -e "s/QQQQQQQ/Z7/g" \ + -e "s/QQQQQQ/Z6/g" \ + -e "s/QQQQQ/Z5/g" \ + -e "s/QQQQ/Z4/g" \ + -e "s/QQQ/Z3/g" \ + -e "s/QQ/Z2/g" \ + -e "s/Q/Z1/g" \ + -e "s/0Z//g" \ + ; +} + +expect_pattern () { + cnt="$1" + cat <<EOF +diff --git a/file-a$cnt b/file-a$cnt +--- a/file-a$cnt ++++ b/file-a$cnt +@@ -1 +1 @@ +-Z${cnt}a ++Z${cnt}A +diff --git a/file-b$cnt b/file-b$cnt +--- a/file-b$cnt ++++ b/file-b$cnt +@@ -1 +1 @@ +-b ++B +diff --git a/file-c$cnt b/file-c$cnt +--- a/file-c$cnt ++++ b/file-c$cnt +@@ -1 +1 @@ +-cZ$cnt +\ No newline at end of file ++CZ$cnt +\ No newline at end of file +diff --git a/file-d$cnt b/file-d$cnt +--- a/file-d$cnt ++++ b/file-d$cnt +@@ -1 +1 @@ +-d ++D +EOF +} + +sample='1023 1024 1025 2047 4095' + +test_expect_success setup ' + + for n in $sample + do + ( zs $n ; echo a ) >file-a$n && + ( echo b; zs $n; echo ) >file-b$n && + ( printf c; zs $n ) >file-c$n && + ( echo d; zs $n ) >file-d$n && + + git add file-a$n file-b$n file-c$n file-d$n && + + ( zs $n ; echo A ) >file-a$n && + ( echo B; zs $n; echo ) >file-b$n && + ( printf C; zs $n ) >file-c$n && + ( echo D; zs $n ) >file-d$n && + + expect_pattern $n || break + + done >expect +' + +test_expect_success 'diff -U0' ' + + for n in $sample + do + git diff -U0 file-?$n + done | zc >actual && + test_cmp expect actual + +' + +test_done diff --git a/t/t4025-hunk-header.sh b/t/t4025-hunk-header.sh new file mode 100755 index 0000000000..7a3dbc1ea2 --- /dev/null +++ b/t/t4025-hunk-header.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='diff hunk header truncation' + +. ./test-lib.sh + +N='日本語' +N1='æ—¥' +N2='日本' +NS="$N$N$N$N$N$N$N$N$N$N$N$N$N" + +test_expect_success setup ' + + ( + echo "A $NS" + for c in B C D E F G H I J K + do + echo " $c" + done + echo "L $NS" + for c in M N O P Q R S T U V + do + echo " $c" + done + ) >file && + git add file && + + sed -e "/^ [EP]/s/$/ modified/" <file >file+ && + mv file+ file + +' + +test_expect_success 'hunk header truncation with an overly long line' ' + + git diff | sed -n -e "s/^.*@@//p" >actual && + ( + echo " A $N$N$N$N$N$N$N$N$N2" + echo " L $N$N$N$N$N$N$N$N$N1" + ) >expected && + test_cmp actual expected + +' + +test_done diff --git a/t/t4026-color.sh b/t/t4026-color.sh new file mode 100755 index 0000000000..d5ccdd0cf8 --- /dev/null +++ b/t/t4026-color.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# +# Copyright (c) 2008 Timo Hirvonen +# + +test_description='Test diff/status color escape codes' +. ./test-lib.sh + +color() +{ + actual=$(git config --get-color no.such.slot "$1") && + test "$actual" = "$2" +} + +invalid_color() +{ + test_must_fail git config --get-color no.such.slot "$1" +} + +test_expect_success 'reset' ' + color "reset" "[m" +' + +test_expect_success 'attribute before color name' ' + color "bold red" "[1;31m" +' + +test_expect_success 'color name before attribute' ' + color "red bold" "[1;31m" +' + +test_expect_success 'attr fg bg' ' + color "ul blue red" "[4;34;41m" +' + +test_expect_success 'fg attr bg' ' + color "blue ul red" "[4;34;41m" +' + +test_expect_success 'fg bg attr' ' + color "blue red ul" "[4;34;41m" +' + +test_expect_success 'fg bg attr...' ' + color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m" +' + +test_expect_success 'long color specification' ' + color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m" +' + +test_expect_success '256 colors' ' + color "254 bold 255" "[1;38;5;254;48;5;255m" +' + +test_expect_success 'color too small' ' + invalid_color "-2" +' + +test_expect_success 'color too big' ' + invalid_color "256" +' + +test_expect_success 'extra character after color number' ' + invalid_color "3X" +' + +test_expect_success 'extra character after color name' ' + invalid_color "redX" +' + +test_expect_success 'extra character after attribute' ' + invalid_color "dimX" +' + +test_expect_success 'unknown color slots are ignored (diff)' ' + git config --unset diff.color.new + git config color.diff.nosuchslotwilleverbedefined white && + git diff --color +' + +test_expect_success 'unknown color slots are ignored (branch)' ' + git config color.branch.nosuchslotwilleverbedefined white && + git branch -a +' + +test_expect_success 'unknown color slots are ignored (status)' ' + git config color.status.nosuchslotwilleverbedefined white || exit + git status + case $? in 0|1) : ok ;; *) false ;; esac +' + +test_done diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh new file mode 100755 index 0000000000..1bd8e5ee3a --- /dev/null +++ b/t/t4027-diff-submodule.sh @@ -0,0 +1,195 @@ +#!/bin/sh + +test_description='difference in submodules' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh + +_z40=0000000000000000000000000000000000000000 +test_expect_success setup ' + test_tick && + test_create_repo sub && + ( + cd sub && + echo hello >world && + git add world && + git commit -m submodule + ) && + + test_tick && + echo frotz >nitfol && + git add nitfol sub && + git commit -m superproject && + + ( + cd sub && + echo goodbye >world && + git add world && + git commit -m "submodule #2" + ) && + + set x $( + cd sub && + git rev-list HEAD + ) && + echo ":160000 160000 $3 $_z40 M sub" >expect && + subtip=$3 subprev=$2 +' + +test_expect_success 'git diff --raw HEAD' ' + git diff --raw --abbrev=40 HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'git diff-index --raw HEAD' ' + git diff-index --raw HEAD >actual.index && + test_cmp expect actual.index +' + +test_expect_success 'git diff-files --raw' ' + git diff-files --raw >actual.files && + test_cmp expect actual.files +' + +expect_from_to () { + printf "%sSubproject commit %s\n+Subproject commit %s\n" \ + "-" "$1" "$2" +} + +test_expect_success 'git diff HEAD' ' + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body +' + +test_expect_success 'git diff HEAD with dirty submodule (work tree)' ' + echo >>sub/world && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev-dirty && + test_cmp expect.body actual.body +' + +test_expect_success 'git diff HEAD with dirty submodule (index)' ' + ( + cd sub && + git reset --hard && + echo >>world && + git add world + ) && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev-dirty && + test_cmp expect.body actual.body +' + +test_expect_success 'git diff HEAD with dirty submodule (untracked)' ' + ( + cd sub && + git reset --hard && + git clean -qfdx && + >cruft + ) && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev-dirty && + test_cmp expect.body actual.body +' + +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' ' + git commit -m "x" sub && + echo >>sub/world && + 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 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 (index, refs match)' ' + ( + cd sub && + git reset --hard && + echo >>world && + git add world + ) && + 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_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)' ' + ( + cd sub && + git reset --hard && + git clean -qfdx && + >cruft + ) && + 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 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 (empty submodule dir)' ' + : >empty && + rm -rf sub/* sub/.git && + git diff > actual.empty && + test_cmp empty actual.empty +' + +test_expect_success 'conflicted submodule setup' ' + + # 39 efs + c=fffffffffffffffffffffffffffffffffffffff + ( + echo "000000 $_z40 0 sub" + echo "160000 1$c 1 sub" + echo "160000 2$c 2 sub" + echo "160000 3$c 3 sub" + ) | git update-index --index-info && + echo >expect.nosub '\''diff --cc sub +index 2ffffff,3ffffff..0000000 +--- a/sub ++++ b/sub +@@@ -1,1 -1,1 +1,1 @@@ +- Subproject commit 2fffffffffffffffffffffffffffffffffffffff + -Subproject commit 3fffffffffffffffffffffffffffffffffffffff +++Subproject commit 0000000000000000000000000000000000000000'\'' && + + hh=$(git rev-parse HEAD) && + sed -e "s/$_z40/$hh/" expect.nosub >expect.withsub + +' + +test_expect_success 'combined (empty submodule)' ' + rm -fr sub && mkdir sub && + git diff >actual && + test_cmp expect.nosub actual +' + +test_expect_success 'combined (with submodule)' ' + rm -fr sub && + git clone --no-checkout . sub && + git diff >actual && + test_cmp expect.withsub actual +' + + + +test_done diff --git a/t/t4028-format-patch-mime-headers.sh b/t/t4028-format-patch-mime-headers.sh new file mode 100755 index 0000000000..204ba673cb --- /dev/null +++ b/t/t4028-format-patch-mime-headers.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='format-patch mime headers and extra headers do not conflict' +. ./test-lib.sh + +test_expect_success 'create commit with utf-8 body' ' + echo content >file && + git add file && + git commit -m one && + echo more >>file && + git commit -a -m "two + + utf-8 body: ñ" +' + +test_expect_success 'patch has mime headers' ' + rm -f 0001-two.patch && + git format-patch HEAD^ && + grep -i "content-type: text/plain; charset=utf-8" 0001-two.patch +' + +test_expect_success 'patch has mime and extra headers' ' + rm -f 0001-two.patch && + git config format.headers "x-foo: bar" && + git format-patch HEAD^ && + grep -i "x-foo: bar" 0001-two.patch && + grep -i "content-type: text/plain; charset=utf-8" 0001-two.patch +' + +test_done diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh new file mode 100755 index 0000000000..3ccc237a8d --- /dev/null +++ b/t/t4029-diff-trailing-space.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +# Copyright (c) Jim Meyering +# +test_description='diff honors config option, diff.suppressBlankEmpty' + +. ./test-lib.sh + +cat <<\EOF > exp || +diff --git a/f b/f +index 5f6a263..8cb8bae 100644 +--- a/f ++++ b/f +@@ -1,2 +1,2 @@ + +-x ++y +EOF +exit 1 + +test_expect_success \ + "$test_description" \ + 'printf "\nx\n" > f && + git add f && + git commit -q -m. f && + printf "\ny\n" > f && + git config --bool diff.suppressBlankEmpty true && + git diff f > actual && + test_cmp exp actual && + perl -i.bak -p -e "s/^\$/ /" exp && + git config --bool diff.suppressBlankEmpty false && + git diff f > actual && + test_cmp exp actual && + git config --bool --unset diff.suppressBlankEmpty && + git diff f > actual && + test_cmp exp actual + ' + +test_done diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh new file mode 100755 index 0000000000..88c5619ae7 --- /dev/null +++ b/t/t4030-diff-textconv.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +test_description='diff.*.textconv tests' +. ./test-lib.sh + +find_diff() { + sed '1,/^index /d' | sed '/^-- $/,$d' +} + +cat >expect.binary <<'EOF' +Binary files a/file and b/file differ +EOF + +cat >expect.text <<'EOF' +--- a/file ++++ b/file +@@ -1 +1,2 @@ + 0 ++1 +EOF + +cat >hexdump <<'EOF' +#!/bin/sh +perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" +EOF +chmod +x hexdump + +test_expect_success 'setup binary file with history' ' + printf "\\0\\n" >file && + git add file && + git commit -m one && + printf "\\01\\n" >>file && + git add file && + git commit -m two +' + +test_expect_success 'file is considered binary by porcelain' ' + git diff HEAD^ HEAD >diff && + find_diff <diff >actual && + test_cmp expect.binary actual +' + +test_expect_success 'file is considered binary by plumbing' ' + git diff-tree -p HEAD^ HEAD >diff && + find_diff <diff >actual && + test_cmp expect.binary actual +' + +test_expect_success 'setup textconv filters' ' + echo file diff=foo >.gitattributes && + git config diff.foo.textconv "\"$(pwd)\""/hexdump && + git config diff.fail.textconv false +' + +test_expect_success 'diff produces text' ' + git diff HEAD^ HEAD >diff && + find_diff <diff >actual && + test_cmp expect.text actual +' + +test_expect_success 'diff-tree produces binary' ' + git diff-tree -p HEAD^ HEAD >diff && + find_diff <diff >actual && + test_cmp expect.binary actual +' + +test_expect_success 'log produces text' ' + git log -1 -p >log && + find_diff <log >actual && + test_cmp expect.text actual +' + +test_expect_success 'format-patch produces binary' ' + git format-patch --no-binary --stdout HEAD^ >patch && + find_diff <patch >actual && + test_cmp expect.binary actual +' + +test_expect_success 'status -v produces text' ' + git reset --soft HEAD^ && + git status -v >diff && + find_diff <diff >actual && + test_cmp expect.text actual && + git reset --soft HEAD@{1} +' + +cat >expect.stat <<'EOF' + file | Bin 2 -> 4 bytes + 1 files changed, 0 insertions(+), 0 deletions(-) +EOF +test_expect_success 'diffstat does not run textconv' ' + echo file diff=fail >.gitattributes && + git diff --stat HEAD^ HEAD >actual && + test_cmp expect.stat actual +' +# restore working setup +echo file diff=foo >.gitattributes + +cat >expect.typechange <<'EOF' +--- a/file ++++ /dev/null +@@ -1,2 +0,0 @@ +-0 +-1 +diff --git a/file b/file +new file mode 120000 +index 0000000..67be421 +--- /dev/null ++++ b/file +@@ -0,0 +1 @@ ++frotz +\ No newline at end of file +EOF +# make a symlink the hard way that works on symlink-challenged file systems +test_expect_success 'textconv does not act on symlinks' ' + printf frotz > file && + git add file && + git ls-files -s | sed -e s/100644/120000/ | + git update-index --index-info && + git commit -m typechange && + git show >diff && + find_diff <diff >actual && + test_cmp expect.typechange actual +' + +test_done diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh new file mode 100755 index 0000000000..7e7b307a24 --- /dev/null +++ b/t/t4031-diff-rewrite-binary.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='rewrite diff on binary file' + +. ./test-lib.sh + +# We must be large enough to meet the MINIMUM_BREAK_SIZE +# requirement. +make_file() { + # common first line to help identify rewrite versus regular diff + printf "=\n" >file + for i in 1 2 3 4 5 6 7 8 9 10 + do + for j in 1 2 3 4 5 6 7 8 9 + do + for k in 1 2 3 4 5 + do + printf "$1\n" + done + done + done >>file +} + +test_expect_success 'create binary file with changes' ' + make_file "\\0" && + git add file && + make_file "\\01" +' + +test_expect_success 'vanilla diff is binary' ' + git diff >diff && + grep "Binary files a/file and b/file differ" diff +' + +test_expect_success 'rewrite diff is binary' ' + git diff -B >diff && + grep "dissimilarity index" diff && + grep "Binary files a/file and b/file differ" diff +' + +test_expect_success 'rewrite diff can show binary patch' ' + git diff -B --binary >diff && + grep "dissimilarity index" diff && + grep "GIT binary patch" diff +' + +{ + echo "#!$SHELL_PATH" + cat <<'EOF' +perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" +EOF +} >dump +chmod +x dump + +test_expect_success 'setup textconv' ' + echo file diff=foo >.gitattributes && + git config diff.foo.textconv "\"$(pwd)\""/dump +' + +test_expect_success 'rewrite diff respects textconv' ' + git diff -B >diff && + grep "dissimilarity index" diff && + grep "^-61" diff && + grep "^-0" diff +' + +test_done diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh new file mode 100755 index 0000000000..e4e3e28fc7 --- /dev/null +++ b/t/t4032-diff-inter-hunk-context.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='diff hunk fusing' + +. ./test-lib.sh + +f() { + echo $1 + i=1 + while test $i -le $2 + do + echo $i + i=$(expr $i + 1) + done + echo $3 +} + +t() { + case $# in + 4) hunks=$4; cmd="diff -U$3";; + 5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";; + esac + label="$cmd, $1 common $2" + file=f$1 + expected=expected.$file.$3.$hunks + + if ! test -f $file + then + f A $1 B >$file + git add $file + git commit -q -m. $file + f X $1 Y >$file + fi + + test_expect_success "$label: count hunks ($hunks)" " + test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks + " + + test -f $expected && + test_expect_success "$label: check output" " + git $cmd $file | grep -v '^index ' >actual && + test_cmp $expected actual + " +} + +cat <<EOF >expected.f1.0.1 || exit 1 +diff --git a/f1 b/f1 +--- a/f1 ++++ b/f1 +@@ -1,3 +1,3 @@ +-A ++X + 1 +-B ++Y +EOF + +cat <<EOF >expected.f1.0.2 || exit 1 +diff --git a/f1 b/f1 +--- a/f1 ++++ b/f1 +@@ -1 +1 @@ +-A ++X +@@ -3 +3 @@ A +-B ++Y +EOF + +# common lines ctx intrctx hunks +t 1 line 0 2 +t 1 line 0 0 2 +t 1 line 0 1 1 +t 1 line 0 2 1 +t 1 line 1 1 + +t 2 lines 0 2 +t 2 lines 0 0 2 +t 2 lines 0 1 2 +t 2 lines 0 2 1 +t 2 lines 1 1 + +t 3 lines 1 2 +t 3 lines 1 0 2 +t 3 lines 1 1 1 +t 3 lines 1 2 1 + +t 9 lines 3 2 +t 9 lines 3 2 2 +t 9 lines 3 3 1 + +test_done diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh new file mode 100755 index 0000000000..1eb14989df --- /dev/null +++ b/t/t4033-diff-patience.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +test_description='patience diff algorithm' + +. ./test-lib.sh + +cat >file1 <<\EOF +#include <stdio.h> + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("Your answer is: "); + printf("%d\n", foo); + } +} + +int fact(int n) +{ + if(n > 1) + { + return fact(n-1) * n; + } + return 1; +} + +int main(int argc, char **argv) +{ + frobnitz(fact(10)); +} +EOF + +cat >file2 <<\EOF +#include <stdio.h> + +int fib(int n) +{ + if(n > 2) + { + return fib(n-1) + fib(n-2); + } + return 1; +} + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("%d\n", foo); + } +} + +int main(int argc, char **argv) +{ + frobnitz(fib(10)); +} +EOF + +cat >expect <<\EOF +diff --git a/file1 b/file2 +index 6faa5a3..e3af329 100644 +--- a/file1 ++++ b/file2 +@@ -1,26 +1,25 @@ + #include <stdio.h> + ++int fib(int n) ++{ ++ if(n > 2) ++ { ++ return fib(n-1) + fib(n-2); ++ } ++ return 1; ++} ++ + // Frobs foo heartily + int frobnitz(int foo) + { + int i; + for(i = 0; i < 10; i++) + { +- printf("Your answer is: "); + printf("%d\n", foo); + } + } + +-int fact(int n) +-{ +- if(n > 1) +- { +- return fact(n-1) * n; +- } +- return 1; +-} +- + int main(int argc, char **argv) + { +- frobnitz(fact(10)); ++ frobnitz(fib(10)); + } +EOF + +test_expect_success 'patience diff' ' + + test_must_fail git diff --no-index --patience file1 file2 > output && + test_cmp expect output + +' + +test_expect_success 'patience diff output is valid' ' + + mv file2 expect && + git apply < output && + test_cmp expect file2 + +' + +cat >uniq1 <<\EOF +1 +2 +3 +4 +5 +6 +EOF + +cat >uniq2 <<\EOF +a +b +c +d +e +f +EOF + +cat >expect <<\EOF +diff --git a/uniq1 b/uniq2 +index b414108..0fdf397 100644 +--- a/uniq1 ++++ b/uniq2 +@@ -1,6 +1,6 @@ +-1 +-2 +-3 +-4 +-5 +-6 ++a ++b ++c ++d ++e ++f +EOF + +test_expect_success 'completely different files' ' + + test_must_fail git diff --no-index --patience uniq1 uniq2 > output && + test_cmp expect output + +' + +test_done diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh new file mode 100755 index 0000000000..6f7548c3a1 --- /dev/null +++ b/t/t4034-diff-words.sh @@ -0,0 +1,334 @@ +#!/bin/sh + +test_description='word diff colors' + +. ./test-lib.sh + +test_expect_success setup ' + + git config diff.color.old red + git config diff.color.new green + git config diff.color.func magenta + +' + +word_diff () { + test_must_fail git diff --no-index "$@" pre post > output && + test_decode_color <output >output.decrypted && + test_cmp expect output.decrypted +} + +cat > pre <<\EOF +h(4) + +a = b + c +EOF + +cat > post <<\EOF +h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +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 with runs of whitespace' ' + + word_diff --color-words + +' + +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> +<WHITE>--- a/pre<RESET> +<WHITE>+++ b/post<RESET> +<CYAN>@@ -1 +1 @@<RESET> +<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET> +<CYAN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET> + +<GREEN>aa = a<RESET> + +<GREEN>aeff = aeff * ( aaa )<RESET> +EOF + +test_expect_success 'word diff without context' ' + + word_diff --color-words --unified=0 + +' + +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 +cp expect expect.letter-runs-are-words + +test_expect_success 'word diff with a regular expression' ' + + word_diff --color-words="[a-z]+" + +' + +test_expect_success 'set a diff driver' ' + git config diff.testdriver.wordRegex "[^[:space:]]" && + cat <<EOF > .gitattributes +pre diff=testdriver +post diff=testdriver +EOF +' + +test_expect_success 'option overrides .gitattributes' ' + + 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[44]<RESET> + +a = b + c<RESET> + +<GREEN>aa = a<RESET> + +<GREEN>aeff = aeff * ( aaa )<RESET> +EOF +cp expect expect.non-whitespace-is-word + +test_expect_success 'use regex supplied by driver' ' + + word_diff --color-words + +' + +test_expect_success 'set diff.wordRegex option' ' + git config diff.wordRegex "[[:alnum:]]+" +' + +cp expect.letter-runs-are-words expect + +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' ' + word_diff --color-words +' + +test_expect_success 'remove diff driver regex' ' + git config --unset diff.testdriver.wordRegex +' + +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[44<RESET>] + +a = b + c<RESET> + +<GREEN>aa = a<RESET> + +<GREEN>aeff = aeff * ( aaa<RESET> ) +EOF + +test_expect_success 'use configured regex' ' + word_diff --color-words +' + +echo 'aaa (aaa)' > pre +echo 'aaa (aaa) aaa' > post + +cat > expect <<\EOF +<WHITE>diff --git a/pre b/post<RESET> +<WHITE>index c29453b..be22f37 100644<RESET> +<WHITE>--- a/pre<RESET> +<WHITE>+++ b/post<RESET> +<CYAN>@@ -1 +1 @@<RESET> +aaa (aaa) <GREEN>aaa<RESET> +EOF + +test_expect_success 'test parsing words for newline' ' + + word_diff --color-words="a+" + + +' + +echo '(:' > pre +echo '(' > post + +cat > expect <<\EOF +<WHITE>diff --git a/pre b/post<RESET> +<WHITE>index 289cb9d..2d06f37 100644<RESET> +<WHITE>--- a/pre<RESET> +<WHITE>+++ b/post<RESET> +<CYAN>@@ -1 +1 @@<RESET> +(<RED>:<RESET> +EOF + +test_expect_success 'test when words are only removed at the end' ' + + word_diff --color-words=. + +' + +cat > expect <<\EOF +diff --git a/pre b/post +index 289cb9d..2d06f37 100644 +--- a/pre ++++ b/post +@@ -1 +1 @@ +-(: ++( +EOF + +test_expect_success '--word-diff=none' ' + + word_diff --word-diff=plain --word-diff=none + +' + +test_done diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh new file mode 100755 index 0000000000..e747e84227 --- /dev/null +++ b/t/t4035-diff-quiet.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +test_description='Return value of diffs' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo 1 >a && + git add . && + git commit -m first && + echo 2 >b && + git add . && + git commit -a -m second +' + +test_expect_success 'git diff-tree HEAD^ HEAD' ' + git diff-tree --quiet HEAD^ HEAD >cnt + test $? = 1 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-tree HEAD^ HEAD -- a' ' + git diff-tree --quiet HEAD^ HEAD -- a >cnt + test $? = 0 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-tree HEAD^ HEAD -- b' ' + git diff-tree --quiet HEAD^ HEAD -- b >cnt + test $? = 1 && test $(wc -l <cnt) = 0 +' +# this diff outputs one line: sha1 of the given head +test_expect_success 'echo HEAD | git diff-tree --stdin' ' + echo $(git rev-parse HEAD) | git diff-tree --quiet --stdin >cnt + test $? = 1 && test $(wc -l <cnt) = 1 +' +test_expect_success 'git diff-tree HEAD HEAD' ' + git diff-tree --quiet HEAD HEAD >cnt + test $? = 0 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-files' ' + git diff-files --quiet >cnt + test $? = 0 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-index --cached HEAD' ' + git diff-index --quiet --cached HEAD >cnt + test $? = 0 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-index --cached HEAD^' ' + git diff-index --quiet --cached HEAD^ >cnt + test $? = 1 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-index --cached HEAD^' ' + echo text >>b && + echo 3 >c && + git add . && { + git diff-index --quiet --cached HEAD^ >cnt + test $? = 1 && test $(wc -l <cnt) = 0 + } +' +test_expect_success 'git diff-tree -Stext HEAD^ HEAD -- b' ' + git commit -m "text in b" && { + git diff-tree --quiet -Stext HEAD^ HEAD -- b >cnt + test $? = 1 && test $(wc -l <cnt) = 0 + } +' +test_expect_success 'git diff-tree -Snot-found HEAD^ HEAD -- b' ' + git diff-tree --quiet -Snot-found HEAD^ HEAD -- b >cnt + test $? = 0 && test $(wc -l <cnt) = 0 +' +test_expect_success 'git diff-files' ' + echo 3 >>c && { + git diff-files --quiet >cnt + test $? = 1 && test $(wc -l <cnt) = 0 + } +' +test_expect_success 'git diff-index --cached HEAD' ' + git update-index c && { + git diff-index --quiet --cached HEAD >cnt + test $? = 1 && test $(wc -l <cnt) = 0 + } +' + +test_done diff --git a/t/t4036-format-patch-signer-mime.sh b/t/t4036-format-patch-signer-mime.sh new file mode 100755 index 0000000000..ba43f18549 --- /dev/null +++ b/t/t4036-format-patch-signer-mime.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='format-patch -s should force MIME encoding as needed' + +. ./test-lib.sh + +test_expect_success setup ' + + >F && + git add F && + git commit -m initial && + echo new line >F && + + test_tick && + git commit -m "This adds some lines to F" F + +' + +test_expect_success 'format normally' ' + + git format-patch --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with signoff without funny signer name' ' + + git format-patch -s --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with non ASCII signer name' ' + + GIT_COMMITTER_NAME="ã¯ã¾ã® ãµã«ãŠã†" \ + git format-patch -s --stdout -1 >output && + grep Content-Type output + +' + +test_expect_success 'attach and signoff do not duplicate mime headers' ' + + GIT_COMMITTER_NAME="ã¯ã¾ã® ãµã«ãŠã†" \ + git format-patch -s --stdout -1 --attach >output && + test `grep -ci ^MIME-Version: output` = 1 + +' + +test_done + diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh new file mode 100755 index 0000000000..f5ce3b29a2 --- /dev/null +++ b/t/t4037-diff-r-t-dirs.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description='diff -r -t shows directory additions and deletions' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir dc dr dt && + >dc/1 && + >dr/2 && + >dt/3 && + >fc && + >fr && + >ft && + git add . && + test_tick && + git commit -m initial && + + rm -fr dt dr ft fr && + mkdir da ft && + for p in dc/1 da/4 dt ft/5 fc + do + echo hello >$p || exit + done && + git add -u && + git add . && + test_tick && + git commit -m second +' + +cat >expect <<\EOF +A da +A da/4 +M dc +M dc/1 +D dr +D dr/2 +A dt +D dt +D dt/3 +M fc +D fr +D ft +A ft +A ft/5 +EOF + +test_expect_success verify ' + git diff-tree -r -t --name-status HEAD^ HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh new file mode 100755 index 0000000000..40277c77aa --- /dev/null +++ b/t/t4038-diff-combined.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='combined diff' + +. ./test-lib.sh + +setup_helper () { + one=$1 branch=$2 side=$3 && + + git branch $side $branch && + for l in $one two three fyra + do + echo $l + done >file && + git add file && + test_tick && + git commit -m $branch && + git checkout $side && + for l in $one two three quatro + do + echo $l + done >file && + git add file && + test_tick && + git commit -m $side && + test_must_fail git merge $branch && + for l in $one three four + do + echo $l + done >file && + git add file && + test_tick && + git commit -m "merge $branch into $side" +} + +verify_helper () { + it=$1 && + + # Ignore lines that were removed only from the other parent + sed -e ' + 1,/^@@@/d + /^ -/d + s/^\(.\)./\1/ + ' "$it" >"$it.actual.1" && + sed -e ' + 1,/^@@@/d + /^- /d + s/^.\(.\)/\1/ + ' "$it" >"$it.actual.2" && + + git diff "$it^" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.1" && + test_cmp "$it.expect.1" "$it.actual.1" && + + git diff "$it^2" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.2" && + test_cmp "$it.expect.2" "$it.actual.2" +} + +test_expect_success setup ' + >file && + git add file && + test_tick && + git commit -m initial && + + git branch withone && + git branch sansone && + + git checkout withone && + setup_helper one withone sidewithone && + + git checkout sansone && + setup_helper "" sansone sidesansone +' + +test_expect_success 'check combined output (1)' ' + git show sidewithone -- >sidewithone && + verify_helper sidewithone +' + +test_expect_success 'check combined output (2)' ' + git show sidesansone -- >sidesansone && + verify_helper sidesansone +' + +test_expect_success 'diagnose truncated file' ' + >file && + git add file && + git commit --amend -C HEAD && + git show >out && + grep "diff --cc file" out +' + +test_done diff --git a/t/t4039-diff-assume-unchanged.sh b/t/t4039-diff-assume-unchanged.sh new file mode 100755 index 0000000000..9d9498bd95 --- /dev/null +++ b/t/t4039-diff-assume-unchanged.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='diff with assume-unchanged entries' + +. ./test-lib.sh + +# external diff has been tested in t4020-diff-external.sh + +test_expect_success 'setup' ' + echo zero > zero && + git add zero && + git commit -m zero && + echo one > one && + echo two > two && + git add one two && + git commit -m onetwo && + git update-index --assume-unchanged one && + echo borked >> one && + test "$(git ls-files -v one)" = "h one" +' + +test_expect_success 'diff-index does not examine assume-unchanged entries' ' + git diff-index HEAD^ -- one | grep -q 5626abf0f72e58d7a153368ba57db4c673c0e171 +' + +test_expect_success 'diff-files does not examine assume-unchanged entries' ' + rm one && + test -z "$(git diff-files -- one)" +' + +test_done diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh new file mode 100755 index 0000000000..a30b03bcf2 --- /dev/null +++ b/t/t4040-whitespace-status.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +test_description='diff --exit-code with whitespace' +. ./test-lib.sh + +test_expect_success setup ' + mkdir a b && + echo >c && + echo >a/d && + echo >b/e && + git add . && + test_tick && + git commit -m initial && + echo " " >a/d && + test_tick && + git commit -a -m second && + echo " " >a/d && + echo " " >b/e && + git add a/d +' + +test_expect_success 'diff-tree --exit-code' ' + test_must_fail git diff --exit-code HEAD^ HEAD && + test_must_fail git diff-tree --exit-code HEAD^ HEAD +' + +test_expect_success 'diff-tree -b --exit-code' ' + git diff -b --exit-code HEAD^ HEAD && + git diff-tree -b -p --exit-code HEAD^ HEAD && + git diff-tree -b --exit-code HEAD^ HEAD +' + +test_expect_success 'diff-index --cached --exit-code' ' + test_must_fail git diff --cached --exit-code HEAD && + test_must_fail git diff-index --cached --exit-code HEAD +' + +test_expect_success 'diff-index -b -p --cached --exit-code' ' + git diff -b --cached --exit-code HEAD && + git diff-index -b -p --cached --exit-code HEAD +' + +test_expect_success 'diff-index --exit-code' ' + test_must_fail git diff --exit-code HEAD && + test_must_fail git diff-index --exit-code HEAD +' + +test_expect_success 'diff-index -b -p --exit-code' ' + git diff -b --exit-code HEAD && + git diff-index -b -p --exit-code HEAD +' + +test_expect_success 'diff-files --exit-code' ' + test_must_fail git diff --exit-code && + test_must_fail git diff-files --exit-code +' + +test_expect_success 'diff-files -b -p --exit-code' ' + git diff -b --exit-code && + git diff-files -b -p --exit-code +' + +test_done diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh new file mode 100755 index 0000000000..8e391cf9a7 --- /dev/null +++ b/t/t4041-diff-submodule-option.sh @@ -0,0 +1,428 @@ +#!/bin/sh +# +# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin +# + +test_description='Support for verbose submodule differences in git diff + +This test tries to verify the sanity of the --submodule option of git diff. +' + +. ./test-lib.sh + +add_file () { + sm=$1 + shift + owd=$(pwd) + cd "$sm" + for name; do + echo "$name" > "$name" && + git add "$name" && + test_tick && + git commit -m "Add $name" + done >/dev/null + git rev-parse --verify HEAD | cut -c1-7 + cd "$owd" +} +commit_file () { + test_tick && + git commit "$@" -m "Commit $*" >/dev/null +} + +test_create_repo sm1 && +add_file . foo >/dev/null + +head1=$(add_file sm1 foo1 foo2) + +test_expect_success 'added submodule' " + git add sm1 && + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 0000000...$head1 (new submodule) +EOF +" + +commit_file sm1 && +head2=$(add_file sm1 foo3) + +test_expect_success 'modified submodule(forward)' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head1..$head2: + > Add foo3 +EOF +" + +test_expect_success 'modified submodule(forward)' " + git diff --submodule=log >actual && + diff actual - <<-EOF +Submodule sm1 $head1..$head2: + > Add foo3 +EOF +" + +test_expect_success 'modified submodule(forward) --submodule' " + git diff --submodule >actual && + diff actual - <<-EOF +Submodule sm1 $head1..$head2: + > Add foo3 +EOF +" + +fullhead1=$(cd sm1; git rev-list --max-count=1 $head1) +fullhead2=$(cd sm1; git rev-list --max-count=1 $head2) +test_expect_success 'modified submodule(forward) --submodule=short' " + git diff --submodule=short >actual && + diff actual - <<-EOF +diff --git a/sm1 b/sm1 +index $head1..$head2 160000 +--- a/sm1 ++++ b/sm1 +@@ -1 +1 @@ +-Subproject commit $fullhead1 ++Subproject commit $fullhead2 +EOF +" + +commit_file sm1 && +cd sm1 && +git reset --hard HEAD~2 >/dev/null && +head3=$(git rev-parse --verify HEAD | cut -c1-7) && +cd .. + +test_expect_success 'modified submodule(backward)' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head2..$head3 (rewind): + < Add foo3 + < Add foo2 +EOF +" + +head4=$(add_file sm1 foo4 foo5) && +head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD) +test_expect_success 'modified submodule(backward and forward)' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head2...$head4: + > Add foo5 + > Add foo4 + < Add foo3 + < Add foo2 +EOF +" + +commit_file sm1 && +mv sm1 sm1-bak && +echo sm1 >sm1 && +head5=$(git hash-object sm1 | cut -c1-7) && +git add sm1 && +rm -f sm1 && +mv sm1-bak sm1 + +test_expect_success 'typechanged submodule(submodule->blob), --cached' " + git diff --submodule=log --cached >actual && + diff actual - <<-EOF +Submodule sm1 41fbea9...0000000 (submodule deleted) +diff --git a/sm1 b/sm1 +new file mode 100644 +index 0000000..9da5fb8 +--- /dev/null ++++ b/sm1 +@@ -0,0 +1 @@ ++sm1 +EOF +" + +test_expect_success 'typechanged submodule(submodule->blob)' " + git diff --submodule=log >actual && + diff actual - <<-EOF +diff --git a/sm1 b/sm1 +deleted file mode 100644 +index 9da5fb8..0000000 +--- a/sm1 ++++ /dev/null +@@ -1 +0,0 @@ +-sm1 +Submodule sm1 0000000...$head4 (new submodule) +EOF +" + +rm -rf sm1 && +git checkout-index sm1 +test_expect_success 'typechanged submodule(submodule->blob)' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head4...0000000 (submodule deleted) +diff --git a/sm1 b/sm1 +new file mode 100644 +index 0000000..$head5 +--- /dev/null ++++ b/sm1 +@@ -0,0 +1 @@ ++sm1 +EOF +" + +rm -f sm1 && +test_create_repo sm1 && +head6=$(add_file sm1 foo6 foo7) +fullhead6=$(cd sm1; git rev-list --max-count=1 $head6) +test_expect_success 'nonexistent commit' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head4...$head6 (commits not present) +EOF +" + +commit_file +test_expect_success 'typechanged submodule(blob->submodule)' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +diff --git a/sm1 b/sm1 +deleted file mode 100644 +index $head5..0000000 +--- a/sm1 ++++ /dev/null +@@ -1 +0,0 @@ +-sm1 +Submodule sm1 0000000...$head6 (new submodule) +EOF +" + +commit_file sm1 && +test_expect_success 'submodule is up to date' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +EOF +" + +test_expect_success 'submodule contains untracked content' " + echo new > sm1/new-file && + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +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 && + diff actual - <<-EOF +Submodule sm1 contains untracked content +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 && + diff actual - <<-EOF +Submodule sm1 contains modified content +EOF +" + +(cd sm1; git commit -mchange foo6 >/dev/null) && +head8=$(cd sm1; git rev-parse --verify HEAD | cut -c1-7) && +test_expect_success 'submodule is modified' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6..$head8: + > change +EOF +" + +test_expect_success 'modified submodule contains untracked content' " + echo new > sm1/new-file && + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 contains untracked content +Submodule sm1 $head6..$head8: + > change +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 && + diff actual - <<-EOF +Submodule sm1 contains untracked content +Submodule sm1 contains modified content +Submodule sm1 $head6..$head8: + > change +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 actual - <<-EOF +Submodule sm1 contains modified content +Submodule sm1 $head6..$head8: + > change +EOF +" + +rm -rf sm1 +test_expect_success 'deleted submodule' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6...0000000 (submodule deleted) +EOF +" + +test_create_repo sm2 && +head7=$(add_file sm2 foo8 foo9) && +git add sm2 + +test_expect_success 'multiple submodules' " + git diff-index -p --submodule=log HEAD >actual && + diff actual - <<-EOF +Submodule sm1 $head6...0000000 (submodule deleted) +Submodule sm2 0000000...$head7 (new submodule) +EOF +" + +test_expect_success 'path filter' " + git diff-index -p --submodule=log HEAD sm2 >actual && + diff actual - <<-EOF +Submodule sm2 0000000...$head7 (new submodule) +EOF +" + +commit_file sm2 +test_expect_success 'given commit' " + git diff-index -p --submodule=log HEAD^ >actual && + diff actual - <<-EOF +Submodule sm1 $head6...0000000 (submodule deleted) +Submodule sm2 0000000...$head7 (new submodule) +EOF +" + +test_expect_success 'given commit --submodule' " + git diff-index -p --submodule HEAD^ >actual && + diff actual - <<-EOF +Submodule sm1 $head6...0000000 (submodule deleted) +Submodule sm2 0000000...$head7 (new submodule) +EOF +" + +fullhead7=$(cd sm2; git rev-list --max-count=1 $head7) + +test_expect_success 'given commit --submodule=short' " + git diff-index -p --submodule=short HEAD^ >actual && + diff actual - <<-EOF +diff --git a/sm1 b/sm1 +deleted file mode 160000 +index $head6..0000000 +--- a/sm1 ++++ /dev/null +@@ -1 +0,0 @@ +-Subproject commit $fullhead6 +diff --git a/sm2 b/sm2 +new file mode 160000 +index 0000000..$head7 +--- /dev/null ++++ b/sm2 +@@ -0,0 +1 @@ ++Subproject commit $fullhead7 +EOF +" + +test_expect_success 'setup .git file for sm2' ' + (cd sm2 && + REAL="$(pwd)/../.real" && + mv .git "$REAL" + echo "gitdir: $REAL" >.git) +' + +test_expect_success 'diff --submodule with .git file' ' + git diff --submodule HEAD^ >actual && + diff actual - <<-EOF +Submodule sm1 $head6...0000000 (submodule deleted) +Submodule sm2 0000000...$head7 (new submodule) +EOF +' + +test_done 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/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 6579f06b05..9b433de836 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -3,45 +3,38 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply --stat --summary test. +test_description='git apply --stat --summary test, with --recount ' . ./test-lib.sh -test_expect_success \ - 'rename' \ - 'git-apply --stat --summary <../t4100/t-apply-1.patch >current && - diff -u ../t4100/t-apply-1.expect current' - -test_expect_success \ - 'copy' \ - 'git-apply --stat --summary <../t4100/t-apply-2.patch >current && - diff -u ../t4100/t-apply-2.expect current' - -test_expect_success \ - 'rewrite' \ - 'git-apply --stat --summary <../t4100/t-apply-3.patch >current && - diff -u ../t4100/t-apply-3.expect current' - -test_expect_success \ - 'mode' \ - 'git-apply --stat --summary <../t4100/t-apply-4.patch >current && - diff -u ../t4100/t-apply-4.expect current' - -test_expect_success \ - 'non git' \ - 'git-apply --stat --summary <../t4100/t-apply-5.patch >current && - diff -u ../t4100/t-apply-5.expect current' - -test_expect_success \ - 'non git' \ - 'git-apply --stat --summary <../t4100/t-apply-6.patch >current && - diff -u ../t4100/t-apply-6.expect current' - -test_expect_success \ - 'non git' \ - 'git-apply --stat --summary <../t4100/t-apply-7.patch >current && - diff -u ../t4100/t-apply-7.expect current' +UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/' + +num=0 +while read title +do + num=$(( $num + 1 )) + test_expect_success "$title" ' + git apply --stat --summary \ + <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current && + test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current + ' + + test_expect_success "$title with recount" ' + sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" | + git apply --recount --stat --summary >current && + test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current + ' +done <<\EOF +rename +copy +rewrite +mode +non git (1) +non git (2) +non git (3) +incomplete (1) +incomplete (2) +EOF test_done - diff --git a/t/t4100/t-apply-1.patch b/t/t4100/t-apply-1.patch index de587517f4..90ab54f0f5 100644 --- a/t/t4100/t-apply-1.patch +++ b/t/t4100/t-apply-1.patch @@ -90,7 +90,7 @@ diff --git a/Documentation/git.txt b/Documentation/git.txt diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile -@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files +@@ -30,7 +30,7 @@ PROG= git-update-index git-diff-files git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ git-check-files git-ls-tree git-merge-base git-merge-cache \ git-unpack-file git-export git-diff-cache git-convert-cache \ diff --git a/t/t4100/t-apply-2.patch b/t/t4100/t-apply-2.patch index cfdc80885b..f5c7d601fc 100644 --- a/t/t4100/t-apply-2.patch +++ b/t/t4100/t-apply-2.patch @@ -9,7 +9,7 @@ diff --git a/Makefile b/Makefile - git-deltafy-script + git-deltafy-script git-fetch-script - PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + PROG= git-update-index git-diff-files git-init-db git-write-tree \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \ diff --git a/git-pull-script b/git-fetch-script similarity index 87% diff --git a/t/t4100/t-apply-5.patch b/t/t4100/t-apply-5.patch index de11623d1b..5f6ddc1059 100644 --- a/t/t4100/t-apply-5.patch +++ b/t/t4100/t-apply-5.patch @@ -200,7 +200,7 @@ diff a/Documentation/git.txt b/Documentation/git.txt diff a/Makefile b/Makefile --- a/Makefile +++ b/Makefile -@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files +@@ -30,7 +30,7 @@ PROG= git-update-index git-diff-files git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ git-check-files git-ls-tree git-merge-base git-merge-cache \ git-unpack-file git-export git-diff-cache git-convert-cache \ diff --git a/t/t4100/t-apply-6.patch b/t/t4100/t-apply-6.patch index d9753637fc..a72729a712 100644 --- a/t/t4100/t-apply-6.patch +++ b/t/t4100/t-apply-6.patch @@ -8,7 +8,7 @@ diff a/Makefile b/Makefile - git-deltafy-script + git-deltafy-script git-fetch-script - PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + PROG= git-update-index git-diff-files git-init-db git-write-tree \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \ diff a/git-fetch-script b/git-fetch-script --- /dev/null diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect new file mode 100644 index 0000000000..eef7f2e65c --- /dev/null +++ b/t/t4100/t-apply-8.expect @@ -0,0 +1,2 @@ + t/t4100-apply-stat.sh | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/t/t4100/t-apply-8.patch b/t/t4100/t-apply-8.patch new file mode 100644 index 0000000000..5ca13e6594 --- /dev/null +++ b/t/t4100/t-apply-8.patch @@ -0,0 +1,11 @@ +diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh +index be837bb..0798c64 100755 +--- a/t/t4100-apply-stat.sh ++++ b/t/t4100-apply-stat.sh +@@ -35,4 +35,4 @@ non git (2) + non git (3) + EOF + +-test_done ++test_done +\ No newline at end of file diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect new file mode 100644 index 0000000000..eef7f2e65c --- /dev/null +++ b/t/t4100/t-apply-9.expect @@ -0,0 +1,2 @@ + t/t4100-apply-stat.sh | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/t/t4100/t-apply-9.patch b/t/t4100/t-apply-9.patch new file mode 100644 index 0000000000..875d57d567 --- /dev/null +++ b/t/t4100/t-apply-9.patch @@ -0,0 +1,11 @@ +diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh +index 0798c64..be837bb 100755 +--- a/t/t4100-apply-stat.sh ++++ b/t/t4100-apply-stat.sh +@@ -35,4 +35,4 @@ non git (2) + non git (3) + EOF + +-test_done +\ No newline at end of file ++test_done diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh index 026fac8c55..e3443d004d 100755 --- a/t/t4101-apply-nonl.sh +++ b/t/t4101-apply-nonl.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply should handle files with incomplete lines. +test_description='git apply should handle files with incomplete lines. ' . ./test-lib.sh @@ -21,9 +21,10 @@ do do test $i -eq $j && continue cat frotz.$i >frotz - test_expect_success \ - "apply diff between $i and $j" \ - "git-apply <../t4101/diff.$i-$j && diff frotz.$j frotz" + test_expect_success "apply diff between $i and $j" ' + git apply <"$TEST_DIRECTORY"/t4101/diff.$i-$j && + test_cmp frotz.$j frotz + ' done done diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh index b4662b0364..1597965241 100755 --- a/t/t4102-apply-rename.sh +++ b/t/t4102-apply-rename.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply handling copy/rename patch. +test_description='git apply handling copy/rename patch. ' . ./test-lib.sh @@ -26,21 +26,23 @@ echo 'This is foo' >foo chmod +x foo test_expect_success setup \ - 'git-update-index --add foo' + 'git update-index --add foo' test_expect_success apply \ - 'git-apply --index --stat --summary --apply test-patch' + 'git apply --index --stat --summary --apply test-patch' -if [ "$(git config --get core.filemode)" = false ] +if test "$(git config --bool core.filemode)" = false then say 'filemode disabled on the filesystem' else - test_expect_success validate \ - 'test -f bar && ls -l bar | grep "^-..x......"' + test_set_prereq FILEMODE fi +test_expect_success FILEMODE validate \ + 'test -f bar && ls -l bar | grep "^-..x......"' + test_expect_success 'apply reverse' \ - 'git-apply -R --index --stat --summary --apply test-patch && + 'git apply -R --index --stat --summary --apply test-patch && test "$(cat foo)" = "This is foo"' cat >test-patch <<\EOF @@ -56,7 +58,7 @@ copy to bar EOF test_expect_success 'apply copy' \ - 'git-apply --index --stat --summary --apply test-patch && + 'git apply --index --stat --summary --apply test-patch && test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"' test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index e2b1124c78..9692f16f35 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply handling binary patches +test_description='git apply handling binary patches ' . ./test-lib.sh @@ -20,96 +20,102 @@ EOF cat file1 >file2 cat file1 >file4 -git-update-index --add --remove file1 file2 file4 -git-commit -m 'Initial Version' 2>/dev/null +test_expect_success 'setup' " + git update-index --add --remove file1 file2 file4 && + git commit -m 'Initial Version' 2>/dev/null && -git-checkout -b binary -tr 'x' '\0' <file1 >file3 -cat file3 >file4 -git-add file2 -tr '\0' 'v' <file3 >file1 -rm -f file2 -git-update-index --add --remove file1 file2 file3 file4 -git-commit -m 'Second Version' + git checkout -b binary && + perl -pe 'y/x/\000/' <file1 >file3 && + cat file3 >file4 && + git add file2 && + perl -pe 'y/\000/v/' <file3 >file1 && + rm -f file2 && + git update-index --add --remove file1 file2 file3 file4 && + git commit -m 'Second Version' && -git-diff-tree -p master binary >B.diff -git-diff-tree -p -C master binary >C.diff + git diff-tree -p master binary >B.diff && + git diff-tree -p -C master binary >C.diff && -git-diff-tree -p --binary master binary >BF.diff -git-diff-tree -p --binary -C master binary >CF.diff + git diff-tree -p --binary master binary >BF.diff && + git diff-tree -p --binary -C master binary >CF.diff +" test_expect_success 'stat binary diff -- should not fail.' \ - 'git-checkout master - git-apply --stat --summary B.diff' + 'git checkout master + git apply --stat --summary B.diff' test_expect_success 'stat binary diff (copy) -- should not fail.' \ - 'git-checkout master - git-apply --stat --summary C.diff' + 'git checkout master + git apply --stat --summary C.diff' -test_expect_failure 'check binary diff -- should fail.' \ - 'git-checkout master - git-apply --check B.diff' +test_expect_success 'check binary diff -- should fail.' \ + 'git checkout master && + test_must_fail git apply --check B.diff' -test_expect_failure 'check binary diff (copy) -- should fail.' \ - 'git-checkout master - git-apply --check C.diff' +test_expect_success 'check binary diff (copy) -- should fail.' \ + 'git checkout master && + test_must_fail git apply --check C.diff' -test_expect_failure 'check incomplete binary diff with replacement -- should fail.' \ - 'git-checkout master - git-apply --check --allow-binary-replacement B.diff' +test_expect_success \ + 'check incomplete binary diff with replacement -- should fail.' ' + git checkout master && + test_must_fail git apply --check --allow-binary-replacement B.diff +' -test_expect_failure 'check incomplete binary diff with replacement (copy) -- should fail.' \ - 'git-checkout master - git-apply --check --allow-binary-replacement C.diff' +test_expect_success \ + 'check incomplete binary diff with replacement (copy) -- should fail.' ' + git checkout master && + test_must_fail git apply --check --allow-binary-replacement C.diff +' test_expect_success 'check binary diff with replacement.' \ - 'git-checkout master - git-apply --check --allow-binary-replacement BF.diff' + 'git checkout master + git apply --check --allow-binary-replacement BF.diff' test_expect_success 'check binary diff with replacement (copy).' \ - 'git-checkout master - git-apply --check --allow-binary-replacement CF.diff' + 'git checkout master + git apply --check --allow-binary-replacement CF.diff' # Now we start applying them. do_reset () { - rm -f file? - git-reset --hard - git-checkout -f master + rm -f file? && + git reset --hard && + git checkout -f master } -test_expect_failure 'apply binary diff -- should fail.' \ - 'do_reset - git-apply B.diff' +test_expect_success 'apply binary diff -- should fail.' \ + 'do_reset && + test_must_fail git apply B.diff' -test_expect_failure 'apply binary diff -- should fail.' \ - 'do_reset - git-apply --index B.diff' +test_expect_success 'apply binary diff -- should fail.' \ + 'do_reset && + test_must_fail git apply --index B.diff' -test_expect_failure 'apply binary diff (copy) -- should fail.' \ - 'do_reset - git-apply C.diff' +test_expect_success 'apply binary diff (copy) -- should fail.' \ + 'do_reset && + test_must_fail git apply C.diff' -test_expect_failure 'apply binary diff (copy) -- should fail.' \ - 'do_reset - git-apply --index C.diff' +test_expect_success 'apply binary diff (copy) -- should fail.' \ + 'do_reset && + test_must_fail git apply --index C.diff' test_expect_success 'apply binary diff without replacement.' \ - 'do_reset - git-apply BF.diff' + 'do_reset && + git apply BF.diff' test_expect_success 'apply binary diff without replacement (copy).' \ - 'do_reset - git-apply CF.diff' + 'do_reset && + git apply CF.diff' test_expect_success 'apply binary diff.' \ - 'do_reset - git-apply --allow-binary-replacement --index BF.diff && - test -z "$(git-diff --name-status binary)"' + 'do_reset && + git apply --allow-binary-replacement --index BF.diff && + test -z "$(git diff --name-status binary)"' test_expect_success 'apply binary diff (copy).' \ - 'do_reset - git-apply --allow-binary-replacement --index CF.diff && - test -z "$(git-diff --name-status binary)"' + 'do_reset && + git apply --allow-binary-replacement --index CF.diff && + test -z "$(git diff --name-status binary)"' test_done diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh index 2ff800c23f..c617c2a33d 100755 --- a/t/t4104-apply-boundary.sh +++ b/t/t4104-apply-boundary.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply boundary tests +test_description='git apply boundary tests ' . ./test-lib.sh @@ -27,6 +27,15 @@ test_expect_success setup ' git diff victim >add-a-patch.with && git diff --unified=0 >add-a-patch.without && + : insert at line two + for i in b a '"$L"' y + do + echo $i + done >victim && + cat victim >insert-a-expect && + git diff victim >insert-a-patch.with && + git diff --unified=0 >insert-a-patch.without && + : modify at the head for i in a '"$L"' y do @@ -55,7 +64,7 @@ test_expect_success setup ' git diff --unified=0 >add-z-patch.without && : modify at the tail - for i in a '"$L"' y + for i in b '"$L"' z do echo $i done >victim && @@ -81,7 +90,7 @@ do with) u= ;; without) u='--unidiff-zero ' ;; esac - for kind in add-a add-z mod-a mod-z del-a del-z + for kind in add-a add-z insert-a mod-a mod-z del-a del-z do test_expect_success "apply $kind-patch $with context" ' cat original >victim && @@ -90,12 +99,12 @@ do cat '"$kind-patch.$with"' (exit 1) } && - diff -u '"$kind"'-expect victim + test_cmp '"$kind"'-expect victim ' done done -for kind in add-a add-z mod-a mod-z del-a del-z +for kind in add-a add-z insert-a mod-a mod-z del-a del-z do rm -f $kind-ng.without sed -e "s/^diff --git /diff /" \ @@ -108,8 +117,30 @@ do cat '"$kind-ng.without"' (exit 1) } && - diff -u '"$kind"'-expect victim + test_cmp '"$kind"'-expect victim ' done +test_expect_success 'two lines' ' + + >file && + git add file && + echo aaa >file && + git diff >patch && + git add file && + echo bbb >file && + git add file && + test_must_fail git apply --check patch + +' + +test_expect_success 'apply patch with 3 context lines matching at end' ' + { echo a; echo b; echo c; echo d; } >file && + git add file && + echo e >>file && + git diff >patch && + >file && + test_must_fail git apply patch +' + test_done diff --git a/t/t4105-apply-fuzz.sh b/t/t4105-apply-fuzz.sh new file mode 100755 index 0000000000..3266e39400 --- /dev/null +++ b/t/t4105-apply-fuzz.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +test_description='apply with fuzz and offset' + +. ./test-lib.sh + +dotest () { + name="$1" && shift && + test_expect_success "$name" " + git checkout-index -f -q -u file && + git apply $* && + test_cmp expect file + " +} + +test_expect_success setup ' + + for i in 1 2 3 4 5 6 7 8 9 10 11 12 + do + echo $i + done >file && + git update-index --add file && + for i in 1 2 3 4 5 6 7 a b c d e 8 9 10 11 12 + do + echo $i + done >file && + cat file >expect && + git diff >O0.diff && + + sed -e "s/@@ -5,6 +5,11 @@/@@ -2,6 +2,11 @@/" >O1.diff O0.diff && + sed -e "s/@@ -5,6 +5,11 @@/@@ -7,6 +7,11 @@/" >O2.diff O0.diff && + sed -e "s/@@ -5,6 +5,11 @@/@@ -19,6 +19,11 @@/" >O3.diff O0.diff && + + sed -e "s/^ 5/ S/" >F0.diff O0.diff && + sed -e "s/^ 5/ S/" >F1.diff O1.diff && + sed -e "s/^ 5/ S/" >F2.diff O2.diff && + sed -e "s/^ 5/ S/" >F3.diff O3.diff + +' + +dotest 'unmodified patch' O0.diff + +dotest 'minus offset' O1.diff + +dotest 'plus offset' O2.diff + +dotest 'big offset' O3.diff + +dotest 'fuzz with no offset' -C2 F0.diff + +dotest 'fuzz with minus offset' -C2 F1.diff + +dotest 'fuzz with plus offset' -C2 F2.diff + +dotest 'fuzz with big offset' -C2 F3.diff + +test_done diff --git a/t/t4106-apply-stdin.sh b/t/t4106-apply-stdin.sh new file mode 100755 index 0000000000..72467a1e8e --- /dev/null +++ b/t/t4106-apply-stdin.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='git apply --numstat - <patch' + +. ./test-lib.sh + +test_expect_success setup ' + echo hello >text && + git add text && + echo goodbye >text && + git diff >patch +' + +test_expect_success 'git apply --numstat - < patch' ' + echo "1 1 text" >expect && + git apply --numstat - <patch >actual && + test_cmp expect actual +' + +test_expect_success 'git apply --numstat - < patch patch' ' + for i in 1 2; do echo "1 1 text"; done >expect && + git apply --numstat - < patch patch >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh new file mode 100755 index 0000000000..b04fc8fc12 --- /dev/null +++ b/t/t4107-apply-ignore-whitespace.sh @@ -0,0 +1,185 @@ +#!/bin/sh +# +# Copyright (c) 2009 Giuseppe Bilotta +# + +test_description='git-apply --ignore-whitespace. + +' +. ./test-lib.sh + +# This primes main.c file that indents without using HT at all. +# Various patches with HT and other spaces are attempted in the test. + +cat > patch1.patch <<\EOF +diff --git a/main.c b/main.c +new file mode 100644 +--- /dev/null ++++ b/main.c +@@ -0,0 +1,22 @@ ++#include <stdio.h> ++ ++void print_int(int num); ++int func(int num); ++ ++int main() { ++ int i; ++ ++ for (i = 0; i < 10; i++) { ++ print_int(func(i)); /* stuff */ ++ } ++ ++ return 0; ++} ++ ++int func(int num) { ++ return num * num; ++} ++ ++void print_int(int num) { ++ printf("%d", num); ++} +EOF + +# Since whitespace is very significant and we want to prevent whitespace +# mangling when creating this test from a patch, we protect 'fixable' +# whitespace by replacing spaces with Z and replacing them at patch +# creation time, hence the sed trick. + +# This patch will fail unless whitespace differences are being ignored + +sed -e 's/Z/ /g' > patch2.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -10,6 +10,8 @@ +Z print_int(func(i)); /* stuff */ +Z } +Z ++ printf("\n"); ++ +Z return 0; +Z} +Z +EOF + +# This patch will fail even if whitespace differences are being ignored, +# because of the missing string at EOL. TODO: this testcase should be +# improved by creating a line that has the same hash with and without +# the final string. + +sed -e 's/Z/ /g' > patch3.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -10,3 +10,4 @@ +Z for (i = 0; i < 10; i++) { +Z print_int(func(i));Z ++ /* stuff */ +Z } +EOF + +# This patch will fail even if whitespace differences are being ignored, +# because of the missing EOL at EOF. + +sed -e 's/Z/ /g' > patch4.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -21,1 +21,1 @@ +- };Z +\ No newline at end of file ++ }; +EOF + +# This patch will fail unless whitespace differences are being ignored. + +sed -e 's/Z/ /g' > patch5.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -2,2 +2,3 @@ +Z void print_int(int num); ++ /* a comment */ +Z int func(int num); +EOF + +# And this is how the final output should be. Patches introduce +# HTs but the original SP indents are mostly kept. + +sed -e 's/T/ /g' > main.c.final <<\EOF +#include <stdio.h> + +void print_int(int num); +T/* a comment */ +int func(int num); + +int main() { + int i; + + for (i = 0; i < 10; i++) { + print_int(func(i)); /* stuff */ + } + +Tprintf("\n"); + + return 0; +} + +int func(int num) { + return num * num; +} + +void print_int(int num) { + printf("%d", num); +} +EOF + +test_expect_success 'file creation' ' + git apply patch1.patch +' + +test_expect_success 'patch2 fails (retab)' ' + test_must_fail git apply patch2.patch +' + +test_expect_success 'patch2 applies with --ignore-whitespace' ' + git apply --ignore-whitespace patch2.patch +' + +test_expect_success 'patch2 reverse applies with --ignore-space-change' ' + git apply -R --ignore-space-change patch2.patch +' + +git config apply.ignorewhitespace change + +test_expect_success 'patch2 applies (apply.ignorewhitespace = change)' ' + git apply patch2.patch +' + +test_expect_success 'patch3 fails (missing string at EOL)' ' + test_must_fail git apply patch3.patch +' + +test_expect_success 'patch4 fails (missing EOL at EOF)' ' + test_must_fail git apply patch4.patch +' + +test_expect_success 'patch5 applies (leading whitespace)' ' + git apply patch5.patch +' + +test_expect_success 'patches do not mangle whitespace' ' + test_cmp main.c main.c.final +' + +test_expect_success 're-create file (with --ignore-whitespace)' ' + rm -f main.c && + git apply patch1.patch +' + +test_expect_success 'patch5 fails (--no-ignore-whitespace)' ' + test_must_fail git apply --no-ignore-whitespace patch5.patch +' + +test_done diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh index 5988e1ae4c..ac58083fe2 100755 --- a/t/t4109-apply-multifrag.sh +++ b/t/t4109-apply-multifrag.sh @@ -4,173 +4,32 @@ # Copyright (c) 2005 Robert Fitzsimons # -test_description='git-apply test patches with multiple fragments. +test_description='git apply test patches with multiple fragments.' -' . ./test-lib.sh -# setup - -cat > patch1.patch <<\EOF -diff --git a/main.c b/main.c -new file mode 100644 ---- /dev/null -+++ b/main.c -@@ -0,0 +1,23 @@ -+#include <stdio.h> -+ -+int func(int num); -+void print_int(int num); -+ -+int main() { -+ int i; -+ -+ for (i = 0; i < 10; i++) { -+ print_int(func(i)); -+ } -+ -+ return 0; -+} -+ -+int func(int num) { -+ return num * num; -+} -+ -+void print_int(int num) { -+ printf("%d", num); -+} -+ -EOF -cat > patch2.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,7 +1,9 @@ -+#include <stdlib.h> - #include <stdio.h> - - int func(int num); - void print_int(int num); -+void print_ln(); - - int main() { - int i; -@@ -10,6 +12,8 @@ - print_int(func(i)); - } - -+ print_ln(); -+ - return 0; - } - -@@ -21,3 +25,7 @@ - printf("%d", num); - } - -+void print_ln() { -+ printf("\n"); -+} -+ -EOF -cat > patch3.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,9 +1,7 @@ --#include <stdlib.h> - #include <stdio.h> - - int func(int num); - void print_int(int num); --void print_ln(); - - int main() { - int i; -@@ -12,8 +10,6 @@ - print_int(func(i)); - } - -- print_ln(); -- - return 0; - } - -@@ -25,7 +21,3 @@ - printf("%d", num); - } - --void print_ln() { -- printf("\n"); --} -- -EOF -cat > patch4.patch <<\EOF -diff --git a/main.c b/main.c ---- a/main.c -+++ b/main.c -@@ -1,13 +1,14 @@ - #include <stdio.h> - - int func(int num); --void print_int(int num); -+int func2(int num); - - int main() { - int i; - - for (i = 0; i < 10; i++) { -- print_int(func(i)); -+ printf("%d", func(i)); -+ printf("%d", func3(i)); - } - - return 0; -@@ -17,7 +18,7 @@ - return num * num; - } - --void print_int(int num) { -- printf("%d", num); -+int func2(int num) { -+ return num * num * num; - } - -EOF - -test_expect_success "S = git-apply (1)" \ - 'git-apply patch1.patch patch2.patch' -mv main.c main.c.git - -test_expect_success "S = patch (1)" \ - 'cat patch1.patch patch2.patch | patch -p1' - -test_expect_success "S = cmp (1)" \ - 'cmp main.c.git main.c' +cp "$TEST_DIRECTORY/t4109/patch1.patch" . +cp "$TEST_DIRECTORY/t4109/patch2.patch" . +cp "$TEST_DIRECTORY/t4109/patch3.patch" . +cp "$TEST_DIRECTORY/t4109/patch4.patch" . -rm -f main.c main.c.git - -test_expect_success "S = git-apply (2)" \ - 'git-apply patch1.patch patch2.patch patch3.patch' -mv main.c main.c.git - -test_expect_success "S = patch (2)" \ - 'cat patch1.patch patch2.patch patch3.patch | patch -p1' - -test_expect_success "S = cmp (2)" \ - 'cmp main.c.git main.c' +test_expect_success 'git apply (1)' ' + git apply patch1.patch patch2.patch && + test_cmp "$TEST_DIRECTORY/t4109/expect-1" main.c +' +rm -f main.c -rm -f main.c main.c.git +test_expect_success 'git apply (2)' ' + git apply patch1.patch patch2.patch patch3.patch && + test_cmp "$TEST_DIRECTORY/t4109/expect-2" main.c +' +rm -f main.c -test_expect_success "S = git-apply (3)" \ - 'git-apply patch1.patch patch4.patch' +test_expect_success 'git apply (3)' ' + git apply patch1.patch patch4.patch && + test_cmp "$TEST_DIRECTORY/t4109/expect-3" main.c +' mv main.c main.c.git -test_expect_success "S = patch (3)" \ - 'cat patch1.patch patch4.patch | patch -p1' - -test_expect_success "S = cmp (3)" \ - 'cmp main.c.git main.c' - test_done diff --git a/t/t4109/expect-1 b/t/t4109/expect-1 new file mode 100644 index 0000000000..1db5ff1050 --- /dev/null +++ b/t/t4109/expect-1 @@ -0,0 +1,31 @@ +#include <stdlib.h> +#include <stdio.h> + +int func(int num); +void print_int(int num); +void print_ln(); + +int main() { + int i; + + for (i = 0; i < 10; i++) { + print_int(func(i)); + } + + print_ln(); + + return 0; +} + +int func(int num) { + return num * num; +} + +void print_int(int num) { + printf("%d", num); +} + +void print_ln() { + printf("\n"); +} + diff --git a/t/t4109/expect-2 b/t/t4109/expect-2 new file mode 100644 index 0000000000..bc52924112 --- /dev/null +++ b/t/t4109/expect-2 @@ -0,0 +1,23 @@ +#include <stdio.h> + +int func(int num); +void print_int(int num); + +int main() { + int i; + + for (i = 0; i < 10; i++) { + print_int(func(i)); + } + + return 0; +} + +int func(int num) { + return num * num; +} + +void print_int(int num) { + printf("%d", num); +} + diff --git a/t/t4109/expect-3 b/t/t4109/expect-3 new file mode 100644 index 0000000000..cd2a475feb --- /dev/null +++ b/t/t4109/expect-3 @@ -0,0 +1,24 @@ +#include <stdio.h> + +int func(int num); +int func2(int num); + +int main() { + int i; + + for (i = 0; i < 10; i++) { + printf("%d", func(i)); + printf("%d", func3(i)); + } + + return 0; +} + +int func(int num) { + return num * num; +} + +int func2(int num) { + return num * num * num; +} + diff --git a/t/t4109/patch1.patch b/t/t4109/patch1.patch new file mode 100644 index 0000000000..1d411fc3cc --- /dev/null +++ b/t/t4109/patch1.patch @@ -0,0 +1,28 @@ +diff --git a/main.c b/main.c +new file mode 100644 +--- /dev/null ++++ b/main.c +@@ -0,0 +1,23 @@ ++#include <stdio.h> ++ ++int func(int num); ++void print_int(int num); ++ ++int main() { ++ int i; ++ ++ for (i = 0; i < 10; i++) { ++ print_int(func(i)); ++ } ++ ++ return 0; ++} ++ ++int func(int num) { ++ return num * num; ++} ++ ++void print_int(int num) { ++ printf("%d", num); ++} ++ diff --git a/t/t4109/patch2.patch b/t/t4109/patch2.patch new file mode 100644 index 0000000000..8c6b06d536 --- /dev/null +++ b/t/t4109/patch2.patch @@ -0,0 +1,30 @@ +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,7 +1,9 @@ ++#include <stdlib.h> + #include <stdio.h> + + int func(int num); + void print_int(int num); ++void print_ln(); + + int main() { + int i; +@@ -10,6 +12,8 @@ + print_int(func(i)); + } + ++ print_ln(); ++ + return 0; + } + +@@ -21,3 +25,7 @@ + printf("%d", num); + } + ++void print_ln() { ++ printf("\n"); ++} ++ diff --git a/t/t4109/patch3.patch b/t/t4109/patch3.patch new file mode 100644 index 0000000000..d696c55a75 --- /dev/null +++ b/t/t4109/patch3.patch @@ -0,0 +1,31 @@ +cat > patch3.patch <<\EOF +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,9 +1,7 @@ +-#include <stdlib.h> + #include <stdio.h> + + int func(int num); + void print_int(int num); +-void print_ln(); + + int main() { + int i; +@@ -12,8 +10,6 @@ + print_int(func(i)); + } + +- print_ln(); +- + return 0; + } + +@@ -25,7 +21,3 @@ + printf("%d", num); + } + +-void print_ln() { +- printf("\n"); +-} +- diff --git a/t/t4109/patch4.patch b/t/t4109/patch4.patch new file mode 100644 index 0000000000..4b085909b1 --- /dev/null +++ b/t/t4109/patch4.patch @@ -0,0 +1,30 @@ +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -1,13 +1,14 @@ + #include <stdio.h> + + int func(int num); +-void print_int(int num); ++int func2(int num); + + int main() { + int i; + + for (i = 0; i < 10; i++) { +- print_int(func(i)); ++ printf("%d", func(i)); ++ printf("%d", func3(i)); + } + + return 0; +@@ -17,7 +18,7 @@ + return num * num; + } + +-void print_int(int num) { +- printf("%d", num); ++int func2(int num) { ++ return num * num * num; + } + diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh index 005f744816..09f58112e0 100755 --- a/t/t4110-apply-scan.sh +++ b/t/t4110-apply-scan.sh @@ -4,98 +4,19 @@ # Copyright (c) 2005 Robert Fitzsimons # -test_description='git-apply test for patches which require scanning forwards and backwards. +test_description='git apply test for patches which require scanning forwards and backwards. ' . ./test-lib.sh -# setup - -cat > patch1.patch <<\EOF -diff --git a/new.txt b/new.txt -new file mode 100644 ---- /dev/null -+++ b/new.txt -@@ -0,0 +1,12 @@ -+a1 -+a11 -+a111 -+a1111 -+b1 -+b11 -+b111 -+b1111 -+c1 -+c11 -+c111 -+c1111 -EOF -cat > patch2.patch <<\EOF -diff --git a/new.txt b/new.txt ---- a/new.txt -+++ b/new.txt -@@ -1,7 +1,3 @@ --a1 --a11 --a111 --a1111 - b1 - b11 - b111 -EOF -cat > patch3.patch <<\EOF -diff --git a/new.txt b/new.txt ---- a/new.txt -+++ b/new.txt -@@ -6,6 +6,10 @@ - b11 - b111 - b1111 -+b2 -+b22 -+b222 -+b2222 - c1 - c11 - c111 -EOF -cat > patch4.patch <<\EOF -diff --git a/new.txt b/new.txt ---- a/new.txt -+++ b/new.txt -@@ -1,3 +1,7 @@ -+a1 -+a11 -+a111 -+a1111 - b1 - b11 - b111 -EOF -cat > patch5.patch <<\EOF -diff --git a/new.txt b/new.txt ---- a/new.txt -+++ b/new.txt -@@ -10,3 +10,7 @@ - c11 - c111 - c1111 -+c2 -+c22 -+c222 -+c2222 -EOF - -test_expect_success "S = git-apply scan" \ - 'git-apply patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch' -mv new.txt apply.txt - -test_expect_success "S = patch scan" \ - 'cat patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch | patch' -mv new.txt patch.txt - -test_expect_success "S = cmp" \ - 'cmp apply.txt patch.txt' +test_expect_success 'git apply scan' ' + git apply \ + "$TEST_DIRECTORY/t4110/patch1.patch" \ + "$TEST_DIRECTORY/t4110/patch2.patch" \ + "$TEST_DIRECTORY/t4110/patch3.patch" \ + "$TEST_DIRECTORY/t4110/patch4.patch" \ + "$TEST_DIRECTORY/t4110/patch5.patch" && + test_cmp new.txt "$TEST_DIRECTORY/t4110/expect" +' test_done - diff --git a/t/t4110/expect b/t/t4110/expect new file mode 100644 index 0000000000..87cc493ec8 --- /dev/null +++ b/t/t4110/expect @@ -0,0 +1,20 @@ +a1 +a11 +a111 +a1111 +b1 +b11 +b111 +b1111 +b2 +b22 +b222 +b2222 +c1 +c11 +c111 +c1111 +c2 +c22 +c222 +c2222 diff --git a/t/t4110/patch1.patch b/t/t4110/patch1.patch new file mode 100644 index 0000000000..56139080dc --- /dev/null +++ b/t/t4110/patch1.patch @@ -0,0 +1,17 @@ +diff --git a/new.txt b/new.txt +new file mode 100644 +--- /dev/null ++++ b/new.txt +@@ -0,0 +1,12 @@ ++a1 ++a11 ++a111 ++a1111 ++b1 ++b11 ++b111 ++b1111 ++c1 ++c11 ++c111 ++c1111 diff --git a/t/t4110/patch2.patch b/t/t4110/patch2.patch new file mode 100644 index 0000000000..04974247ec --- /dev/null +++ b/t/t4110/patch2.patch @@ -0,0 +1,11 @@ +diff --git a/new.txt b/new.txt +--- a/new.txt ++++ b/new.txt +@@ -1,7 +1,3 @@ +-a1 +-a11 +-a111 +-a1111 + b1 + b11 + b111 diff --git a/t/t4110/patch3.patch b/t/t4110/patch3.patch new file mode 100644 index 0000000000..26bd4427f8 --- /dev/null +++ b/t/t4110/patch3.patch @@ -0,0 +1,14 @@ +diff --git a/new.txt b/new.txt +--- a/new.txt ++++ b/new.txt +@@ -6,6 +6,10 @@ + b11 + b111 + b1111 ++b2 ++b22 ++b222 ++b2222 + c1 + c11 + c111 diff --git a/t/t4110/patch4.patch b/t/t4110/patch4.patch new file mode 100644 index 0000000000..9ffb9c2d7e --- /dev/null +++ b/t/t4110/patch4.patch @@ -0,0 +1,11 @@ +diff --git a/new.txt b/new.txt +--- a/new.txt ++++ b/new.txt +@@ -1,3 +1,7 @@ ++a1 ++a11 ++a111 ++a1111 + b1 + b11 + b111 diff --git a/t/t4110/patch5.patch b/t/t4110/patch5.patch new file mode 100644 index 0000000000..c5ac6914f9 --- /dev/null +++ b/t/t4110/patch5.patch @@ -0,0 +1,11 @@ +diff --git a/new.txt b/new.txt +--- a/new.txt ++++ b/new.txt +@@ -10,3 +10,7 @@ + c11 + c111 + c1111 ++c2 ++c22 ++c222 ++c2222 diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index 69e9603c78..f9ad183758 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply should not get confused with rename/copy. +test_description='git apply should not get confused with rename/copy. ' @@ -36,6 +36,9 @@ typedef struct __jmp_buf jmp_buf[1]; #endif /* _SETJMP_H */ EOF +cat >klibc/README <<\EOF +This is a simple readme file. +EOF cat >patch <<\EOF diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/cris/klibc/archsetjmp.h @@ -49,10 +52,10 @@ copy to include/arch/cris/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/cris/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -74,9 +77,9 @@ copy to include/arch/cris/klibc/archsetjmp.h + unsigned long __sp; + unsigned long __srp; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/m32r/klibc/archsetjmp.h @@ -90,10 +93,10 @@ rename to include/arch/m32r/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/m32r/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -108,17 +111,34 @@ rename to include/arch/m32r/klibc/archsetjmp.h unsigned long __r15; - unsigned long __rip; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ +diff --git a/klibc/README b/klibc/README +--- a/klibc/README ++++ b/klibc/README +@@ -1,1 +1,4 @@ + This is a simple readme file. ++And we add a few ++lines at the ++end of it. +diff --git a/klibc/README b/klibc/arch/README +copy from klibc/README +copy to klibc/arch/README +--- a/klibc/README ++++ b/klibc/arch/README +@@ -1,1 +1,3 @@ + This is a simple readme file. ++And we copy it to one level down, and ++add a few lines at the end of it. EOF -find klibc -type f -print | xargs git-update-index --add -- +find klibc -type f -print | xargs git update-index --add -- -test_expect_success 'check rename/copy patch' 'git-apply --check patch' +test_expect_success 'check rename/copy patch' 'git apply --check patch' -test_expect_success 'apply rename/copy patch' 'git-apply --index patch' +test_expect_success 'apply rename/copy patch' 'git apply --index patch' test_done diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh index 7fd0cf62ec..66fa51591e 100755 --- a/t/t4113-apply-ending.sh +++ b/t/t4113-apply-ending.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Catalin Marinas # -test_description='git-apply trying to add an ending line. +test_description='git apply trying to add an ending line. ' . ./test-lib.sh @@ -25,12 +25,12 @@ echo 'b' >>file echo 'c' >>file test_expect_success setup \ - 'git-update-index --add file' + 'git update-index --add file' # test -test_expect_failure 'apply at the end' \ - 'git-apply --index test-patch' +test_expect_success 'apply at the end' \ + 'test_must_fail git apply --index test-patch' cat >test-patch <<\EOF diff a/file b/file @@ -45,9 +45,9 @@ EOF echo >file 'a b c' -git-update-index file +git update-index file -test_expect_failure 'apply at the beginning' \ - 'git-apply --index test-patch' +test_expect_success 'apply at the beginning' \ + 'test_must_fail git apply --index test-patch' test_done diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index ca81d72157..164d58c222 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -3,12 +3,18 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-apply should not get confused with type changes. +test_description='git apply should not get confused with type changes. ' . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + test_expect_success 'setup repository and commits' ' echo "hello world" > foo && echo "hi planet" > bar && @@ -25,6 +31,10 @@ test_expect_success 'setup repository and commits' ' git update-index foo && git commit -m "foo back to file" && git branch foo-back-to-file && + printf "\0" > foo && + git update-index foo && + git commit -m "foo becomes binary" && + git branch foo-becomes-binary && rm -f foo && git update-index --remove foo && mkdir foo && @@ -85,6 +95,20 @@ test_expect_success 'symlink becomes file' ' ' test_debug 'cat patch' +test_expect_success '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' ' + git checkout -f foo-symlinked-to-bar && + git diff-tree -p --binary HEAD foo-becomes-binary > patch && + git apply --index < patch + ' +test_debug 'cat patch' + test_expect_success 'symlink becomes directory' ' git checkout -f foo-symlinked-to-bar && diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index d5f2cfb186..aff4348034 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -3,12 +3,18 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply symlinks and partial files +test_description='git apply symlinks and partial files ' . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + test_expect_success setup ' ln -s path1/path2/path3/path4/path5 link1 && @@ -33,7 +39,7 @@ test_expect_success 'apply symlink patch' ' git checkout side && git apply patch && git diff-files -p >patched && - diff -u patch patched + test_cmp patch patched ' @@ -42,7 +48,7 @@ test_expect_success 'apply --index symlink patch' ' git checkout -f side && git apply --index patch && git diff-index --cached -p HEAD >patched && - diff -u patch patched + test_cmp patch patched ' diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh index aa2c869e0e..2298ece801 100755 --- a/t/t4116-apply-reverse.sh +++ b/t/t4116-apply-reverse.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply in reverse +test_description='git apply in reverse ' @@ -12,14 +12,14 @@ test_description='git-apply in reverse test_expect_success setup ' for i in a b c d e f g h i j k l m n; do echo $i; done >file1 && - tr "[ijk]" '\''[\0\1\2]'\'' <file1 >file2 && + perl -pe "y/ijk/\\000\\001\\002/" <file1 >file2 && git add file1 file2 && git commit -m initial && git tag initial && for i in a b c g h i J K L m o n p q; do echo $i; done >file1 && - tr "[mon]" '\''[\0\1\2]'\'' <file1 >file2 && + perl -pe "y/mon/\\000\\001\\002/" <file1 >file2 && git commit -a -m second && git tag second && @@ -42,18 +42,18 @@ test_expect_success 'apply in reverse' ' git reset --hard second && git apply --reverse --binary --index patch && git diff >diff && - diff -u /dev/null diff + test_cmp /dev/null diff ' test_expect_success 'setup separate repository lacking postimage' ' - git tar-tree initial initial | tar xf - && + git tar-tree initial initial | $TAR xf - && ( cd initial && git init && git add . ) && - git tar-tree second second | tar xf - && + git tar-tree second second | $TAR xf - && ( cd second && git init && git add . ) @@ -82,4 +82,10 @@ test_expect_success 'apply in reverse without postimage' ' ) ' +test_expect_success 'reversing a whitespace introduction' ' + sed "s/a/a /" < file1 > file1.new && + mv file1.new file1 && + git diff | git apply --reverse --whitespace=error +' + test_done diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh index b4de075a3e..e9ccd161ee 100755 --- a/t/t4117-apply-reject.sh +++ b/t/t4117-apply-reject.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-apply with rejects +test_description='git apply with rejects ' @@ -54,7 +54,7 @@ test_expect_success 'apply without --reject should fail' ' exit 1 fi - diff -u file1 saved.file1 + test_cmp file1 saved.file1 ' test_expect_success 'apply without --reject should fail' ' @@ -65,7 +65,7 @@ test_expect_success 'apply without --reject should fail' ' exit 1 fi - diff -u file1 saved.file1 + test_cmp file1 saved.file1 ' test_expect_success 'apply with --reject should fail but update the file' ' @@ -79,7 +79,7 @@ test_expect_success 'apply with --reject should fail but update the file' ' exit 1 fi - diff -u file1 expected && + test_cmp file1 expected && cat file1.rej && @@ -105,7 +105,7 @@ test_expect_success 'apply with --reject should fail but update the file' ' echo "file1 still exists?" exit 1 } - diff -u file2 expected && + test_cmp file2 expected && cat file2.rej && @@ -132,7 +132,7 @@ test_expect_success 'the same test with --verbose' ' echo "file1 still exists?" exit 1 } - diff -u file2 expected && + test_cmp file2 expected && cat file2.rej && @@ -151,7 +151,7 @@ test_expect_success 'apply cleanly with --verbose' ' git apply --verbose patch.1 && - diff -u file1 clean + test_cmp file1 clean ' test_done diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 7309422fe5..65f2e4c3ef 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='git-apply with new style GNU diff with empty context +test_description='git apply with new style GNU diff with empty context ' @@ -20,10 +20,11 @@ test_expect_success setup ' cat file1 && echo Q | tr -d "\\012" } >file2 && - cat file2 >file2.orig + cat file2 >file2.orig && git add file1 file2 && sed -e "/^B/d" <file1.orig >file1 && - sed -e "/^B/d" <file2.orig >file2 && + cat file1 > file2 && + echo Q | tr -d "\\012" >>file2 && cat file1 >file1.mods && cat file2 >file2.mods && git diff | @@ -37,7 +38,7 @@ test_expect_success 'apply --numstat' ' echo "0 1 file1" && echo "0 1 file2" } >expect && - diff -u expect actual + test_cmp expect actual ' @@ -47,9 +48,8 @@ test_expect_success 'apply --apply' ' cat file2.orig >file2 && git update-index file1 file2 && git apply --index diff.output && - diff -u file1.mods file1 && - diff -u file2.mods file2 + test_cmp file1.mods file1 && + test_cmp file2.mods file2 ' test_done - diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index 620a9207bf..3c73a783a7 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Junio C Hamano # -test_description='git-apply --whitespace=strip and configuration file. +test_description='git apply --whitespace=strip and configuration file. ' @@ -19,12 +19,12 @@ test_expect_success setup ' ' # Also handcraft GNU diff output; note this has trailing whitespace. -cat >gpatch.file <<\EOF && +tr '_' ' ' >gpatch.file <<\EOF && --- file1 2007-02-21 01:04:24.000000000 -0800 +++ file1+ 2007-02-21 01:07:44.000000000 -0800 @@ -1 +1 @@ -A -+B ++B_ EOF sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file && diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh new file mode 100755 index 0000000000..b463b4f05c --- /dev/null +++ b/t/t4120-apply-popt.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Copyright (c) 2007 Shawn O. Pearce +# + +test_description='git apply -p handling.' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir sub && + echo A >sub/file1 && + cp sub/file1 file1 && + git add sub/file1 && + echo B >sub/file1 && + git diff >patch.file && + rm sub/file1 && + rmdir sub +' + +test_expect_success 'apply git diff with -p2' ' + git apply -p2 patch.file +' + +test_expect_success 'apply with too large -p' ' + test_must_fail git apply --stat -p3 patch.file 2>err && + grep "removing 3 leading" err +' + +test_done diff --git a/t/t4121-apply-diffs.sh b/t/t4121-apply-diffs.sh new file mode 100755 index 0000000000..aff551a1d7 --- /dev/null +++ b/t/t4121-apply-diffs.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='git apply for contextually independent diffs' +. ./test-lib.sh + +echo '1 +2 +3 +4 +5 +6 +7 +8' >file + +test_expect_success 'setup' \ + 'git add file && + git commit -q -m 1 && + git checkout -b test && + mv file file.tmp && + echo 0 >file && + cat file.tmp >>file && + rm file.tmp && + git commit -a -q -m 2 && + echo 9 >>file && + git commit -a -q -m 3 && + git checkout master' + +test_expect_success \ + 'check if contextually independent diffs for the same file apply' \ + '( git diff test~2 test~1; git diff test~1 test~0 )| git apply' + +test_done diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh new file mode 100755 index 0000000000..923fcab7f9 --- /dev/null +++ b/t/t4122-apply-symlink-inside.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='apply to deeper directory without getting fooled with symlink' +. ./test-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + +lecho () { + for l_ + do + echo "$l_" + done +} + +test_expect_success setup ' + + mkdir -p arch/i386/boot arch/x86_64 && + lecho 1 2 3 4 5 >arch/i386/boot/Makefile && + ln -s ../i386/boot arch/x86_64/boot && + git add . && + test_tick && + git commit -m initial && + git branch test && + + rm arch/x86_64/boot && + mkdir arch/x86_64/boot && + lecho 2 3 4 5 6 >arch/x86_64/boot/Makefile && + git add . && + test_tick && + git commit -a -m second && + + git format-patch --binary -1 --stdout >test.patch + +' + +test_expect_success apply ' + + git checkout test && + git diff --exit-code test && + git diff --exit-code --cached test && + git apply --index test.patch + +' + +test_expect_success 'check result' ' + + git diff --exit-code master && + git diff --exit-code --cached master && + test_tick && + git commit -m replay && + T1=$(git rev-parse "master^{tree}") && + T2=$(git rev-parse "HEAD^{tree}") && + test "z$T1" = "z$T2" + +' + +test_done diff --git a/t/t4123-apply-shrink.sh b/t/t4123-apply-shrink.sh new file mode 100755 index 0000000000..984157f03b --- /dev/null +++ b/t/t4123-apply-shrink.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +test_description='apply a patch that is larger than the preimage' + +. ./test-lib.sh + +cat >F <<\EOF +1 +2 +3 +4 +5 +6 +7 +8 +999999 +A +B +C +D +E +F +G +H +I +J + +EOF + +test_expect_success setup ' + + git add F && + mv F G && + sed -e "s/1/11/" -e "s/999999/9/" -e "s/H/HH/" <G >F && + git diff >patch && + sed -e "/^\$/d" <G >F && + git add F + +' + +test_expect_success 'apply should fail gracefully' ' + + if git apply --index patch + then + echo Oops, should not have succeeded + false + else + status=$? + echo "Status was $status" + if test -f .git/index.lock + then + echo Oops, should not have crashed + false + fi + fi +' + +test_done diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh new file mode 100755 index 0000000000..8a676a5dcd --- /dev/null +++ b/t/t4124-apply-ws-rule.sh @@ -0,0 +1,451 @@ +#!/bin/sh + +test_description='core.whitespace rules and git apply' + +. ./test-lib.sh + +prepare_test_file () { + + # A line that has character X is touched iff RULE is in effect: + # X RULE + # ! 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 (@%). + _______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 (@#%). + _______________Fifteen SP (#). + _______________>Fifteen SP and a HT (@#%). + ________________Sixteen SP (#). + ________________>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> + EOF +} + +apply_patch () { + >target && + sed -e "s|\([ab]\)/file|\1/target|" <patch | + git apply "$@" +} + +test_fix () { + # fix should not barf + apply_patch --whitespace=fix || return 1 + + # find touched lines + $DIFF file target | sed -n -e "s/^> //p" >fixed + + # the changed lines are all expeced to change + fixed_cnt=$(wc -l <fixed) + case "$1" in + '') expect_cnt=$fixed_cnt ;; + ?*) expect_cnt=$(grep "[$1]" <fixed | wc -l) ;; + esac + test $fixed_cnt -eq $expect_cnt || return 1 + + # and we are not missing anything + case "$1" in + '') expect_cnt=0 ;; + ?*) expect_cnt=$(grep "[$1]" <file | wc -l) ;; + esac + test $fixed_cnt -eq $expect_cnt || return 1 + + # Get the patch actually applied + git diff-files -p target >fixed-patch + test -s fixed-patch && return 0 + + # Make sure it is complaint-free + >target + git apply --whitespace=error-all <fixed-patch + +} + +test_expect_success setup ' + + >file && + git add file && + prepare_test_file >file && + git diff-files -p >patch && + >target && + git add target + +' + +test_expect_success 'whitespace=nowarn, default rule' ' + + apply_patch --whitespace=nowarn && + test_cmp file target + +' + +test_expect_success 'whitespace=warn, default rule' ' + + apply_patch --whitespace=warn && + test_cmp file target + +' + +test_expect_success 'whitespace=error-all, default rule' ' + + apply_patch --whitespace=error-all && return 1 + test -s target && return 1 + : happy + +' + +test_expect_success 'whitespace=error-all, no rule' ' + + git config core.whitespace -trailing,-space-before,-indent && + apply_patch --whitespace=error-all && + test_cmp file target + +' + +test_expect_success 'whitespace=error-all, no rule (attribute)' ' + + git config --unset core.whitespace && + echo "target -whitespace" >.gitattributes && + apply_patch --whitespace=error-all && + test_cmp file target + +' + +for t in - '' +do + case "$t" in '') tt='!' ;; *) tt= ;; esac + for s in - '' + do + case "$s" in '') ts='@' ;; *) ts= ;; esac + for i in - '' + do + case "$i" in '') ti='#' ;; *) ti= ;; esac + 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 + +create_patch () { + sed -e "s/_/ /" <<-\EOF + diff --git a/target b/target + index e69de29..8bd6648 100644 + --- a/target + +++ b/target + @@ -0,0 +1,3 @@ + +An empty line follows + + + +A line with trailing whitespace and no newline_ + \ No newline at end of file + EOF +} + +test_expect_success 'trailing whitespace & no newline at the end of file' ' + >target && + create_patch >patch-file && + git apply --whitespace=fix patch-file && + grep "newline$" target && + grep "^$" target +' + +test_expect_success 'blank at EOF with --whitespace=fix (1)' ' + : these can fail depending on what we did before + git config --unset core.whitespace + rm -f .gitattributes + + { echo a; echo b; echo c; } >one && + git add one && + { echo a; echo b; echo c; } >expect && + { cat expect; echo; } >one && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=fix patch && + test_cmp expect one +' + +test_expect_success 'blank at EOF with --whitespace=fix (2)' ' + { echo a; echo b; echo c; } >one && + git add one && + { echo a; echo c; } >expect && + { cat expect; echo; echo; } >one && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=fix patch && + test_cmp expect one +' + +test_expect_success 'blank at EOF with --whitespace=fix (3)' ' + { echo a; echo b; echo; } >one && + git add one && + { echo a; echo c; echo; } >expect && + { cat expect; echo; echo; } >one && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=fix patch && + test_cmp expect one +' + +test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' ' + { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one && + git add one && + { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect && + cp expect one && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=fix patch && + test_cmp expect one +' + +test_expect_success 'blank at EOF with --whitespace=warn' ' + { echo a; echo b; echo c; } >one && + git add one && + echo >>one && + cat one >expect && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=warn patch 2>error && + test_cmp expect one && + grep "new blank line at EOF" error +' + +test_expect_success 'blank at EOF with --whitespace=error' ' + { echo a; echo b; echo c; } >one && + git add one && + cat one >expect && + echo >>one && + git diff -- one >patch && + + git checkout one && + test_must_fail git apply --whitespace=error patch 2>error && + test_cmp expect one && + grep "new blank line at EOF" error +' + +test_expect_success 'blank but not empty at EOF' ' + { echo a; echo b; echo c; } >one && + git add one && + echo " " >>one && + cat one >expect && + git diff -- one >patch && + + git checkout one && + git apply --whitespace=warn patch 2>error && + test_cmp expect one && + grep "new blank line at EOF" error +' + +test_expect_success 'applying beyond EOF requires one non-blank context line' ' + { echo; echo; echo; echo; } >one && + git add one && + { echo b; } >>one && + git diff -- one >patch && + + git checkout one && + { echo a; echo; } >one && + cp one expect && + test_must_fail git apply --whitespace=fix patch && + test_cmp one expect && + test_must_fail git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_expect_success 'tons of blanks at EOF should not apply' ' + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + echo; echo; echo; echo; + done >one && + git add one && + echo a >>one && + git diff -- one >patch && + + >one && + test_must_fail git apply --whitespace=fix patch && + test_must_fail git apply --ignore-space-change --whitespace=fix patch +' + +test_expect_success 'missing blank line at end with --whitespace=fix' ' + echo a >one && + echo >>one && + git add one && + echo b >>one && + cp one expect && + git diff -- one >patch && + echo a >one && + cp one saved-one && + test_must_fail git apply patch && + git apply --whitespace=fix patch && + test_cmp one expect && + mv saved-one one && + git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_expect_success 'two missing blank lines at end with --whitespace=fix' ' + { echo a; echo; echo b; echo c; } >one && + cp one no-blank-lines && + { echo; echo; } >>one && + git add one && + echo d >>one && + cp one expect && + echo >>one && + git diff -- one >patch && + cp no-blank-lines one && + test_must_fail git apply patch && + git apply --whitespace=fix patch && + test_cmp one expect && + mv no-blank-lines one && + test_must_fail git apply patch && + git apply --ignore-space-change --whitespace=fix patch && + 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 && + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + echo; echo; echo; echo; + done >>one && + git add one && + echo a >one && + cp one expect && + git diff -- one >patch && + cp no-blank-lines one && + test_must_fail git apply patch && + git apply --whitespace=fix patch && + test_cmp one expect && + mv no-blank-lines one && + git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_expect_success 'missing blanks at EOF must only match blank lines' ' + { echo a; echo b; } >one && + git add one && + { echo c; echo d; } >>one && + git diff -- one >patch && + + echo a >one && + test_must_fail git apply patch + test_must_fail git apply --whitespace=fix patch && + test_must_fail git apply --ignore-space-change --whitespace=fix patch +' + +sed -e's/Z//' >one <<EOF +a +b +c + Z +EOF + +test_expect_success 'missing blank line should match context line with spaces' ' + git add one && + echo d >>one && + git diff -- one >patch && + { echo a; echo b; echo c; } >one && + cp one expect && + { echo; echo d; } >>expect && + git add one && + + git apply --whitespace=fix patch && + test_cmp one expect +' + +sed -e's/Z//' >one <<EOF +a +b +c + Z +EOF + +test_expect_success 'same, but with the --ignore-space-option' ' + git add one && + echo d >>one && + cp one expect && + git diff -- one >patch && + { echo a; echo b; echo c; } >one && + git add one && + + git checkout-index -f one && + git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' ' + git config core.whitespace cr-at-eol && + printf "a\r\n" >one && + printf "b\r\n" >>one && + printf "c\r\n" >>one && + cp one save-one && + printf " \r\n" >>one + git add one && + printf "d\r\n" >>one && + cp one expect && + git diff -- one >patch && + mv save-one one && + + git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' ' + git config --unset core.whitespace && + printf "a\r\n" >one && + printf "b\r\n" >>one && + printf "c\r\n" >>one && + cp one save-one && + printf " \r\n" >>one + git add one && + cp one expect && + printf "d\r\n" >>one && + git diff -- one >patch && + mv save-one one && + echo d >>expect && + + git apply --ignore-space-change --whitespace=fix patch && + test_cmp one expect +' + +test_done diff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh new file mode 100755 index 0000000000..9671de7999 --- /dev/null +++ b/t/t4125-apply-ws-fuzz.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='applying patch that has broken whitespaces in context' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + + # file-0 is full of whitespace breakages + for l in a bb c d eeee f ggg h + do + echo "$l " + done >file-0 && + + # patch-0 creates a whitespace broken file + cat file-0 >file && + git diff >patch-0 && + git add file && + + # file-1 is still full of whitespace breakages, + # but has one line updated, without fixing any + # whitespaces. + # patch-1 records that change. + sed -e "s/d/D/" file-0 >file-1 && + cat file-1 >file && + git diff >patch-1 && + + # patch-all is the effect of both patch-0 and patch-1 + >file && + git add file && + cat file-1 >file && + git diff >patch-all && + + # patch-2 is the same as patch-1 but is based + # on a version that already has whitespace fixed, + # and does not introduce whitespace breakages. + sed -e "s/ \$//" patch-1 >patch-2 && + + # If all whitespace breakages are fixed the contents + # should look like file-fixed + sed -e "s/ \$//" file-1 >file-fixed + +' + +test_expect_success nofix ' + + >file && + git add file && + + # Baseline. Applying without fixing any whitespace + # breakages. + git apply --whitespace=nowarn patch-0 && + git apply --whitespace=nowarn patch-1 && + + # The result should obviously match. + test_cmp file-1 file +' + +test_expect_success 'withfix (forward)' ' + + >file && + git add file && + + # The first application will munge the context lines + # the second patch depends on. We should be able to + # adjust and still apply. + git apply --whitespace=fix patch-0 && + git apply --whitespace=fix patch-1 && + + test_cmp file-fixed file +' + +test_expect_success 'withfix (backward)' ' + + >file && + git add file && + + # Now we have a whitespace breakages on our side. + git apply --whitespace=nowarn patch-0 && + + # And somebody sends in a patch based on image + # with whitespace already fixed. + git apply --whitespace=fix patch-2 && + + # The result should accept the whitespace fixed + # postimage. But the line with "h" is beyond context + # horizon and left unfixed. + + sed -e /h/d file-fixed >fixed-head && + sed -e /h/d file >file-head && + test_cmp fixed-head file-head && + + sed -n -e /h/p file-fixed >fixed-tail && + sed -n -e /h/p file >file-tail && + + ! test_cmp fixed-tail file-tail + +' + +test_done diff --git a/t/t4126-apply-empty.sh b/t/t4126-apply-empty.sh new file mode 100755 index 0000000000..ceb6a79fe0 --- /dev/null +++ b/t/t4126-apply-empty.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +test_description='apply empty' + +. ./test-lib.sh + +test_expect_success setup ' + >empty && + git add empty && + test_tick && + git commit -m initial && + for i in a b c d e + do + echo $i + done >empty && + cat empty >expect && + git diff | + sed -e "/^diff --git/d" \ + -e "/^index /d" \ + -e "s|a/empty|empty.orig|" \ + -e "s|b/empty|empty|" >patch0 && + sed -e "s|empty|missing|" patch0 >patch1 && + >empty && + git update-index --refresh +' + +test_expect_success 'apply empty' ' + git reset --hard && + rm -f missing && + git apply patch0 && + test_cmp expect empty +' + +test_expect_success 'apply --index empty' ' + git reset --hard && + rm -f missing && + git apply --index patch0 && + test_cmp expect empty && + git diff --exit-code +' + +test_expect_success 'apply create' ' + git reset --hard && + rm -f missing && + git apply patch1 && + test_cmp expect missing +' + +test_expect_success 'apply --index create' ' + git reset --hard && + rm -f missing && + git apply --index patch1 && + test_cmp expect missing && + git diff --exit-code +' + +test_done diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh new file mode 100755 index 0000000000..77200c0b2d --- /dev/null +++ b/t/t4127-apply-same-fn.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='apply same filename' + +. ./test-lib.sh + +modify () { + sed -e "$1" < "$2" > "$2".x && + mv "$2".x "$2" +} + +test_expect_success setup ' + for i in a b c d e f g h i j k l m + do + echo $i + done >same_fn && + cp same_fn other_fn && + git add same_fn other_fn && + git commit -m initial +' +test_expect_success 'apply same filename with independent changes' ' + modify "s/^d/z/" same_fn && + git diff > patch0 && + git add same_fn && + modify "s/^i/y/" same_fn && + git diff >> patch0 && + cp same_fn same_fn2 && + git reset --hard && + git apply patch0 && + test_cmp same_fn same_fn2 +' + +test_expect_success 'apply same filename with overlapping changes' ' + git reset --hard + modify "s/^d/z/" same_fn && + git diff > patch0 && + git add same_fn && + modify "s/^e/y/" same_fn && + git diff >> patch0 && + cp same_fn same_fn2 && + git reset --hard && + git apply patch0 && + test_cmp same_fn same_fn2 +' + +test_expect_success 'apply same new filename after rename' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + modify "s/^e/y/" new_fn && + git diff >> patch1 && + cp new_fn new_fn2 && + git reset --hard && + git apply --index patch1 && + test_cmp new_fn new_fn2 +' + +test_expect_success 'apply same old filename after rename -- should fail.' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + git mv new_fn same_fn + modify "s/^e/y/" same_fn && + git diff >> patch1 && + git reset --hard && + test_must_fail git apply patch1 +' + +test_expect_success 'apply A->B (rename), C->A (rename), A->A -- should pass.' ' + git reset --hard + git mv same_fn new_fn + modify "s/^d/z/" new_fn && + git add new_fn && + git diff -M --cached > patch1 && + git commit -m "a rename" && + git mv other_fn same_fn + modify "s/^e/y/" same_fn && + git add same_fn && + git diff -M --cached >> patch1 && + modify "s/^g/x/" same_fn && + git diff >> patch1 && + git reset --hard HEAD^ && + git apply patch1 +' + +test_done diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh new file mode 100755 index 0000000000..6cc741a634 --- /dev/null +++ b/t/t4128-apply-root.sh @@ -0,0 +1,112 @@ +#!/bin/sh + +test_description='apply same filename' + +. ./test-lib.sh + +test_expect_success 'setup' ' + + mkdir -p some/sub/dir && + echo Hello > some/sub/dir/file && + git add some/sub/dir/file && + git commit -m initial && + git tag initial + +' + +cat > patch << EOF +diff a/bla/blub/dir/file b/bla/blub/dir/file +--- a/bla/blub/dir/file ++++ b/bla/blub/dir/file +@@ -1,1 +1,1 @@ +-Hello ++Bello +EOF + +test_expect_success 'apply --directory -p (1)' ' + + git apply --directory=some/sub -p3 --index patch && + test Bello = $(git show :some/sub/dir/file) && + test Bello = $(cat some/sub/dir/file) + +' + +test_expect_success 'apply --directory -p (2) ' ' + + git reset --hard initial && + git apply --directory=some/sub/ -p3 --index patch && + test Bello = $(git show :some/sub/dir/file) && + test Bello = $(cat some/sub/dir/file) + +' + +cat > patch << EOF +diff --git a/newfile b/newfile +new file mode 100644 +index 0000000..d95f3ad +--- /dev/null ++++ b/newfile +@@ -0,0 +1 @@ ++content +EOF + +test_expect_success 'apply --directory (new file)' ' + git reset --hard initial && + git apply --directory=some/sub/dir/ --index patch && + test content = $(git show :some/sub/dir/newfile) && + test content = $(cat some/sub/dir/newfile) +' + +cat > patch << EOF +diff --git a/c/newfile2 b/c/newfile2 +new file mode 100644 +index 0000000..d95f3ad +--- /dev/null ++++ b/c/newfile2 +@@ -0,0 +1 @@ ++content +EOF + +test_expect_success 'apply --directory -p (new file)' ' + git reset --hard initial && + git apply -p2 --directory=some/sub/dir/ --index patch && + test content = $(git show :some/sub/dir/newfile2) && + test content = $(cat some/sub/dir/newfile2) +' + +cat > patch << EOF +diff --git a/delfile b/delfile +deleted file mode 100644 +index d95f3ad..0000000 +--- a/delfile ++++ /dev/null +@@ -1 +0,0 @@ +-content +EOF + +test_expect_success 'apply --directory (delete file)' ' + git reset --hard initial && + echo content >some/sub/dir/delfile && + git add some/sub/dir/delfile && + git apply --directory=some/sub/dir/ --index patch && + ! (git ls-files | grep delfile) +' + +cat > patch << 'EOF' +diff --git "a/qu\157tefile" "b/qu\157tefile" +new file mode 100644 +index 0000000..d95f3ad +--- /dev/null ++++ "b/qu\157tefile" +@@ -0,0 +1 @@ ++content +EOF + +test_expect_success 'apply --directory (quoted filename)' ' + git reset --hard initial && + git apply --directory=some/sub/dir/ --index patch && + test content = $(git show :some/sub/dir/quotefile) && + test content = $(cat some/sub/dir/quotefile) +' + +test_done diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh new file mode 100755 index 0000000000..fc7af04931 --- /dev/null +++ b/t/t4129-apply-samemode.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +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_expect_success setup ' + echo original >file && + git add file && + test_tick && + git commit -m initial && + git tag initial && + echo modified >file && + git diff --stat -p >patch-0.txt && + chmod +x file && + git diff --stat -p >patch-1.txt +' + +test_expect_success FILEMODE 'same mode (no index)' ' + git reset --hard && + chmod +x file && + git apply patch-0.txt && + test -x file +' + +test_expect_success FILEMODE 'same mode (with index)' ' + git reset --hard && + chmod +x file && + git add file && + git apply --index patch-0.txt && + test -x file && + git diff --exit-code +' + +test_expect_success FILEMODE 'same mode (index only)' ' + git reset --hard && + chmod +x file && + git add file && + git apply --cached patch-0.txt && + git ls-files -s file | grep "^100755" +' + +test_expect_success FILEMODE 'mode update (no index)' ' + git reset --hard && + git apply patch-1.txt && + test -x file +' + +test_expect_success FILEMODE 'mode update (with index)' ' + git reset --hard && + git apply --index patch-1.txt && + test -x file && + git diff --exit-code +' + +test_expect_success FILEMODE 'mode update (index only)' ' + git reset --hard && + git apply --cached patch-1.txt && + git ls-files -s file | grep "^100755" +' + +test_done diff --git a/t/t4130-apply-criss-cross-rename.sh b/t/t4130-apply-criss-cross-rename.sh new file mode 100755 index 0000000000..7cfa2d6287 --- /dev/null +++ b/t/t4130-apply-criss-cross-rename.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +test_description='git apply handling criss-cross rename patch.' +. ./test-lib.sh + +create_file() { + cnt=0 + while test $cnt -le 100 + do + cnt=$(($cnt + 1)) + echo "$2" >> "$1" + done +} + +test_expect_success 'setup' ' + create_file file1 "File1 contents" && + create_file file2 "File2 contents" && + create_file file3 "File3 contents" && + git add file1 file2 file3 && + git commit -m 1 +' + +test_expect_success 'criss-cross rename' ' + mv file1 tmp && + mv file2 file1 && + mv tmp file2 && + cp file1 file1-swapped && + cp file2 file2-swapped +' + +test_expect_success 'diff -M -B' ' + git diff -M -B > diff && + git reset --hard + +' + +test_expect_success 'apply' ' + git apply diff && + test_cmp file1 file1-swapped && + test_cmp file2 file2-swapped +' + +test_expect_success 'criss-cross rename' ' + git reset --hard && + mv file1 tmp && + mv file2 file1 && + mv file3 file2 + mv tmp file3 && + cp file1 file1-swapped && + cp file2 file2-swapped && + cp file3 file3-swapped +' + +test_expect_success 'diff -M -B' ' + git diff -M -B > diff && + git reset --hard +' + +test_expect_success 'apply' ' + git apply diff && + test_cmp file1 file1-swapped && + test_cmp file2 file2-swapped && + test_cmp file3 file3-swapped +' + +test_done diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh new file mode 100755 index 0000000000..94373ca9a0 --- /dev/null +++ b/t/t4131-apply-fake-ancestor.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2009 Stephen Boyd +# + +test_description='git apply --build-fake-ancestor handling.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit 1 && + test_commit 2 && + mkdir sub && + test_commit 3 sub/3 && + test_commit 4 +' + +test_expect_success 'apply --build-fake-ancestor' ' + git checkout 2 && + echo "A" > 1.t && + git diff > 1.patch && + git reset --hard && + git checkout 1 && + git apply --build-fake-ancestor 1.ancestor 1.patch +' + +test_expect_success 'apply --build-fake-ancestor in a subdirectory' ' + git checkout 3 && + echo "C" > sub/3.t && + git diff > 3.patch && + git reset --hard && + git checkout 4 && + ( + cd sub && + git apply --build-fake-ancestor 3.ancestor ../3.patch && + test -f 3.ancestor + ) && + git apply --build-fake-ancestor 3.ancestor 3.patch && + test_cmp sub/3.ancestor 3.ancestor +' + +test_done diff --git a/t/t4132-apply-removal.sh b/t/t4132-apply-removal.sh new file mode 100755 index 0000000000..bb1ffe3b6c --- /dev/null +++ b/t/t4132-apply-removal.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# +# Copyright (c) 2009 Junio C Hamano + +test_description='git-apply notices removal patches generated by GNU diff' + +. ./test-lib.sh + +test_expect_success setup ' + cat <<-EOF >c && + diff -ruN a/file b/file + --- a/file TS0 + +++ b/file TS1 + @@ -0,0 +1 @@ + +something + EOF + + cat <<-EOF >d && + diff -ruN a/file b/file + --- a/file TS0 + +++ b/file TS1 + @@ -1 +0,0 @@ + -something + EOF + + timeWest="1982-09-16 07:00:00.000000000 -0800" && + timeGMT="1982-09-16 15:00:00.000000000 +0000" && + timeEast="1982-09-17 00:00:00.000000000 +0900" && + + epocWest="1969-12-31 16:00:00.000000000 -0800" && + epocGMT="1970-01-01 00:00:00.000000000 +0000" && + epocEast="1970-01-01 09:00:00.000000000 +0900" && + + sed -e "s/TS0/$epocWest/" -e "s/TS1/$timeWest/" <c >createWest.patch && + sed -e "s/TS0/$epocEast/" -e "s/TS1/$timeEast/" <c >createEast.patch && + sed -e "s/TS0/$epocGMT/" -e "s/TS1/$timeGMT/" <c >createGMT.patch && + + sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <c >addWest.patch && + sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <c >addEast.patch && + sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <c >addGMT.patch && + + sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <d >emptyWest.patch && + sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <d >emptyEast.patch && + sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <d >emptyGMT.patch && + + sed -e "s/TS0/$timeWest/" -e "s/TS1/$epocWest/" <d >removeWest.patch && + sed -e "s/TS0/$timeEast/" -e "s/TS1/$epocEast/" <d >removeEast.patch && + sed -e "s/TS0/$timeGMT/" -e "s/TS1/$epocGMT/" <d >removeGMT.patch && + + echo something >something && + >empty +' + +for patch in *.patch +do + test_expect_success "test $patch" ' + rm -f file .git/index && + case "$patch" in + create*) + # must be able to create + git apply --index $patch && + test_cmp file something && + # must notice the file is already there + >file && + git add file && + test_must_fail git apply $patch + ;; + add*) + # must be able to create or patch + git apply $patch && + test_cmp file something && + >file && + git apply $patch && + test_cmp file something + ;; + empty*) + # must leave an empty file + cat something >file && + git add file && + git apply --index $patch && + test -f file && + test_cmp empty file + ;; + remove*) + # must remove the file + cat something >file && + git add file && + git apply --index $patch && + ! test -f file + ;; + esac + ' +done + +test_done diff --git a/t/t4133-apply-filenames.sh b/t/t4133-apply-filenames.sh new file mode 100755 index 0000000000..34218071b6 --- /dev/null +++ b/t/t4133-apply-filenames.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# Copyright (c) 2010 Andreas Gruenbacher +# + +test_description='git apply filename consistency check' + +. ./test-lib.sh + +test_expect_success setup ' + cat > bad1.patch <<EOF +diff --git a/f b/f +new file mode 100644 +index 0000000..d00491f +--- /dev/null ++++ b/f-blah +@@ -0,0 +1 @@ ++1 +EOF + cat > bad2.patch <<EOF +diff --git a/f b/f +deleted file mode 100644 +index d00491f..0000000 +--- b/f-blah ++++ /dev/null +@@ -1 +0,0 @@ +-1 +EOF +' + +test_expect_success 'apply diff with inconsistent filenames in headers' ' + test_must_fail git apply bad1.patch 2>err + grep "inconsistent new filename" err + test_must_fail git apply bad2.patch 2>err + grep "inconsistent old filename" err +' + +test_done 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/t4150-am.sh b/t/t4150-am.sh new file mode 100755 index 0000000000..810b04b817 --- /dev/null +++ b/t/t4150-am.sh @@ -0,0 +1,364 @@ +#!/bin/sh + +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 ' + echo hello >file && + git add file && + 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" && + echo "X-Fake-Field: Line Two" && + echo "X-Fake-Field: Line Three" && + git format-patch --stdout first | sed -e "1d" + } > patch1.eml && + { + echo "X-Fake-Field: Line One" && + echo "X-Fake-Field: Line Two" && + echo "X-Fake-Field: Line Three" && + git format-patch --stdout first | sed -e "1d" + } | 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 + +test_expect_success 'am applies patch correctly' ' + git checkout first && + test_tick && + git am <patch1 && + ! test -d .git/rebase-apply && + test -z "$(git diff 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' ' + git checkout first && + git am patch1.eml && + ! test -d .git/rebase-apply && + test -z "$(git diff 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' ' + git checkout first && + git am patch1-crlf.eml && + ! test -d .git/rebase-apply && + test -z "$(git diff 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 + +compare () { + test "$(git cat-file commit "$2" | grep "^$1 ")" = \ + "$(git cat-file commit "$3" | grep "^$1 ")" +} + +test_expect_success 'am changes committer and keeps author' ' + test_tick && + 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^)" && + compare author master HEAD && + compare author master^ HEAD^ && + test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \ + "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)" +' + +test_expect_success 'am --signoff adds Signed-off-by: line' ' + git checkout -b master2 first && + git am --signoff <patch2 && + 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 && + 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_expect_success 'am stays in branch' ' + test "refs/heads/master2" = "$(git symbolic-ref HEAD)" +' + +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 + git checkout HEAD^ && + git am --signoff patch4 && + test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1 +' + +test_expect_success 'am without --keep removes Re: and [PATCH] stuff' ' + test "$(git rev-parse HEAD)" = "$(git rev-parse master2)" +' + +test_expect_success 'am --keep really keeps the subject' ' + 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" +' + +test_expect_success 'am -3 falls back to 3-way merge' ' + git checkout -b lorem2 master2 && + sed -n -e "3,\$p" msg >file && + head -n 9 msg >>file && + git add file && + test_tick && + git commit -m "copied stuff" && + git am -3 lorem-move.patch && + ! test -d .git/rebase-apply && + test -z "$(git diff lorem)" +' + +test_expect_success 'am -3 -q is quiet' ' + 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 && + ! test -s output.out +' + +test_expect_success 'am pauses on conflict' ' + git checkout lorem2^^ && + test_must_fail git am lorem-move.patch && + test -d .git/rebase-apply +' + +test_expect_success 'am --skip works' ' + git am --skip && + ! test -d .git/rebase-apply && + test -z "$(git diff lorem2^^ -- file)" && + test goodbye = "$(cat another)" +' + +test_expect_success 'am --resolved works' ' + git checkout lorem2^^ && + test_must_fail git am lorem-move.patch && + test -d .git/rebase-apply && + echo resolved >>file && + git add file && + git am --resolved && + ! test -d .git/rebase-apply && + test goodbye = "$(cat another)" +' + +test_expect_success 'am takes patches from a Pine mailbox' ' + git checkout first && + cat pine patch1 | git am && + ! test -d .git/rebase-apply && + test -z "$(git diff master^..HEAD)" +' + +test_expect_success 'am fails on mail without patch' ' + test_must_fail git am <failmail && + rm -r .git/rebase-apply/ +' + +test_expect_success 'am fails on empty patch' ' + echo "---" >>failmail && + test_must_fail git am <failmail && + git am --skip && + ! test -d .git/rebase-apply +' + +test_expect_success 'am works from stdin in subdirectory' ' + rm -fr subdir && + git checkout first && + ( + mkdir -p subdir && + cd subdir && + git am <../patch1 + ) && + test -z "$(git diff second)" +' + +test_expect_success 'am works from file (relative path given) in subdirectory' ' + rm -fr subdir && + git checkout first && + ( + mkdir -p subdir && + cd subdir && + git am ../patch1 + ) && + test -z "$(git diff second)" +' + +test_expect_success 'am works from file (absolute path given) in subdirectory' ' + rm -fr subdir && + git checkout first && + P=$(pwd) && + ( + mkdir -p subdir && + cd subdir && + git am "$P/patch1" + ) && + test -z "$(git diff second)" +' + +test_expect_success 'am --committer-date-is-author-date' ' + 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" +' + +test_expect_success 'am without --committer-date-is-author-date' ' + 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" +' + +# This checks for +0000 because TZ is set to UTC and that should +# show up when the current time is used. The date in message is set +# 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' ' + 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" +' + +test_expect_success 'am into an unborn branch' ' + rm -fr subdir && + mkdir -p 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} + ) && + test "z$result" = "z$(git rev-parse first^{tree})" +' + +test_expect_success 'am newline in subject' ' + git checkout first && + test_tick && + sed -e "s/second/second \\\n foo/" patch1 > patchnl && + git am < patchnl > output.out 2>&1 && + grep "^Applying: second \\\n foo$" output.out +' + +test_expect_success 'am -q is quiet' ' + git checkout first && + test_tick && + git am -q < patch1 > output.out 2>&1 && + ! test -s output.out +' + +test_done diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh new file mode 100755 index 0000000000..b55c411788 --- /dev/null +++ b/t/t4151-am-abort.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +test_description='am --abort' + +. ./test-lib.sh + +test_expect_success setup ' + for i in a b c d e f g + do + echo $i + done >file-1 && + cp file-1 file-2 && + test_tick && + git add file-1 file-2 && + git commit -m initial && + git tag initial && + for i in 2 3 4 5 6 + do + echo $i >>file-1 && + echo $i >otherfile-$i && + git add otherfile-$i && + test_tick && + git commit -a -m $i || break + done && + git format-patch --no-numbered initial && + git checkout -b side initial && + echo local change >file-2-expect +' + +for with3 in '' ' -3' +do + test_expect_success "am$with3 stops at a patch that does not apply" ' + + git reset --hard initial && + cp file-2-expect file-2 && + + test_must_fail git am$with3 000[1245]-*.patch && + git log --pretty=tformat:%s >actual && + for i in 3 2 initial + do + echo $i + done >expect && + test_cmp expect actual + ' + + test_expect_success "am$with3 --skip continue after failed am$with3" ' + test_must_fail git am$with3 --skip >output && + test "$(grep "^Applying" output)" = "Applying: 6" && + test_cmp file-2-expect file-2 && + test ! -f .git/MERGE_RR + ' + + test_expect_success "am --abort goes back after failed am$with3" ' + git am --abort && + git rev-parse HEAD >actual && + git rev-parse initial >expect && + test_cmp expect actual && + test_cmp file-2-expect file-2 && + git diff-index --exit-code --cached HEAD && + test ! -f .git/MERGE_RR + ' + +done + +test_done diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 639d45fcec..70856d07ed 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -3,74 +3,121 @@ # Copyright (c) 2006 Johannes E. Schindelin # -test_description='git-rerere +test_description='git rerere ' . ./test-lib.sh -cat > a1 << EOF -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. -EOF - -git add a1 -git commit -q -a -m initial - -git checkout -b first -cat >> a1 << EOF -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; -EOF -git commit -q -a -m first - -git checkout -b second master -git show first:a1 | sed 's/To die, t/To die! T/' > a1 -git commit -q -a -m second - -# activate rerere -mkdir .git/rr-cache +test_expect_success 'setup' " + cat > a1 <<- EOF && + Some title + ========== + Whether 'tis nobler in the mind to suffer + The slings and arrows of outrageous fortune, + Or to take arms against a sea of troubles, + 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. + EOF + + git add a1 && + git commit -q -a -m initial && + + git checkout -b first && + cat >> a1 <<- EOF && + Some title + ========== + To die, to sleep; + To sleep: perchance to dream: ay, there's the rub; + For in that sleep of death what dreams may come + When we have shuffled off this mortal coil, + Must give us pause: there's the respect + That makes calamity of so long life; + EOF + 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 && + git commit -q -a -m second +" + +test_expect_success 'nothing recorded without rerere' ' + (rm -rf .git/rr-cache; git config rerere.enabled false) && + test_must_fail git merge first && + ! test -d .git/rr-cache +' -test_expect_failure 'conflicting merge' 'git pull . first' +# activate rerere, old style +test_expect_success 'conflicting merge' ' + git reset --hard && + mkdir .git/rr-cache && + git config --unset rerere.enabled && + test_must_fail git merge first +' -sha1=4f58849a60b4f969a2848966b6d02893b783e8fb +sha1=$(perl -pe 's/ .*//' .git/MERGE_RR) rr=.git/rr-cache/$sha1 -test_expect_success 'recorded preimage' "grep ======= $rr/preimage" +test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage" + +test_expect_success 'rerere.enabled works, too' ' + rm -rf .git/rr-cache && + git config rerere.enabled true && + git reset --hard && + test_must_fail git merge first && + grep ^=======$ $rr/preimage +' test_expect_success 'no postimage or thisimage yet' \ "test ! -f $rr/postimage -a ! -f $rr/thisimage" +test_expect_success 'preimage has right number of lines' ' + + cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) && + test $cnt = 13 + +' + git show first:a1 > a1 cat > expect << EOF --- a/a1 +++ b/a1 -@@ -6,11 +6,7 @@ +@@ -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' 'diff -u expect out' +test_expect_success 'rerere diff' 'test_cmp expect out' cat > expect << EOF a1 @@ -78,26 +125,27 @@ EOF git rerere status > out -test_expect_success 'rerere status' 'diff -u expect 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" -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_expect_failure 'another conflicting merge' 'git pull . first' +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 +' git show first:a1 | sed 's/To die: t/To die! T/' > expect -test_expect_success 'rerere kicked in' "! grep ======= a1" +test_expect_success 'rerere kicked in' "! grep ^=======$ a1" -test_expect_success 'rerere prefers first change' 'diff -u a1 expect' +test_expect_success 'rerere prefers first change' 'test_cmp a1 expect' rm $rr/postimage -echo "$sha1 a1" | tr '\012' '\0' > .git/rr-cache/MERGE_RR +echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR test_expect_success 'rerere clear' 'git rerere clear' @@ -133,6 +181,60 @@ test_expect_success 'garbage collection (part2)' 'git rerere gc' test_expect_success 'old records rest in peace' \ "test ! -f $rr/preimage && test ! -f $rr2/preimage" -test_done +test_expect_success 'file2 added differently in two branches' ' + git reset --hard && + git checkout -b fourth && + echo Hallo > file2 && + git add file2 && + git commit -m version1 && + git checkout third && + echo Bello > file2 && + git add file2 && + git commit -m version2 && + test_must_fail git merge fourth && + echo Cello > file2 && + git add file2 && + git commit -m resolution +' + +test_expect_success 'resolution was recorded properly' ' + git reset --hard HEAD~2 && + git checkout -b fifth && + echo Hallo > file3 && + git add file3 && + git commit -m version1 && + git checkout third && + echo Bello > file3 && + git add file3 && + 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_expect_success 'rerere.autoupdate' ' + git config rerere.autoupdate true + git reset --hard && + git checkout version2 && + test_must_fail git merge fifth && + test 0 = $(git ls-files -u | wc -l) +' +test_expect_success 'merge --rerere-autoupdate' ' + 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) +' +test_expect_success 'merge --no-rerere-autoupdate' ' + 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) +' + +test_done diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh new file mode 100755 index 0000000000..cdb70b4b33 --- /dev/null +++ b/t/t4201-shortlog.sh @@ -0,0 +1,151 @@ +#!/bin/sh +# +# Copyright (c) 2006 Johannes E. Schindelin +# + +test_description='git shortlog +' + +. ./test-lib.sh + +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 +' + +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_expect_success 'default output format' ' + git shortlog HEAD >log && + fuzz log >log.predictable && + test_cmp expect.template log.predictable +' + +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 +' + +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 +' + +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 +' + +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 + it is wrapped correctly + Thð„žs ð„žs a very, very long fð„žrst lð„žne for the commð„žt message to see ð„žf + ð„žt ð„žs wrapped correctly + Thø„žs ø„žs a very, very long fø„žrst lø„žne for the commø„žt + message to see ø„žf ø„žt ø„žs wrapped correctly + a 12 34 + 56 78 + +Someone else (1): + Commit by someone else + +EOF + git shortlog -w HEAD >out && + 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 +} + +DSCHO="Jöhännës \"Dschö\" Schindëlin" +DSCHOE="$DSCHO <Johannes.Schindelin@gmx.de>" +MSG1="set a1 to 2 and some non-ASCII chars: Äßø" +MSG2="set a1 to 3 and some non-ASCII chars: áæï" +cat > expect << EOF +$DSCHO (2): + $MSG1 + $MSG2 + +EOF + +test_expect_success 'shortlog encoding' ' + git reset --hard "$commit" && + git config --unset i18n.commitencoding && + echo 2 > a1 && + git commit --quiet -m "$MSG1" --author="$DSCHOE" a1 && + git config i18n.commitencoding "ISO8859-1" && + echo 3 > a1 && + git commit --quiet -m "$(iconvfromutf8toiso88591 "$MSG2")" \ + --author="$(iconvfromutf8toiso88591 "$DSCHOE")" a1 && + git config --unset i18n.commitencoding && + git shortlog HEAD~2.. > out && +test_cmp expect out' + +test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh new file mode 100755 index 0000000000..2230e606ed --- /dev/null +++ b/t/t4202-log.sh @@ -0,0 +1,440 @@ +#!/bin/sh + +test_description='git log' + +. ./test-lib.sh + +test_expect_success setup ' + + echo one >one && + git add one && + test_tick && + git commit -m initial && + + echo ichi >one && + git add one && + test_tick && + git commit -m second && + + git mv one ichi && + test_tick && + git commit -m third && + + cp ichi ein && + git add ein && + test_tick && + git commit -m fourth && + + mkdir a && + echo ni >a/two && + git add a/two && + test_tick && + git commit -m fifth && + + git rm a/two && + test_tick && + git commit -m sixth + +' + +printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial" > expect +test_expect_success 'pretty' ' + + git log --pretty="format:%s" > actual && + test_cmp expect actual +' + +printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial\n" > expect +test_expect_success 'pretty (tformat)' ' + + git log --pretty="tformat:%s" > actual && + test_cmp expect actual +' + +test_expect_success 'pretty (shortcut)' ' + + git log --pretty="%s" > actual && + test_cmp expect actual +' + +test_expect_success 'format' ' + + git log --format="%s" > actual && + test_cmp expect actual +' + +cat > expect << EOF + This is + the sixth + commit. + This is + the fifth + commit. +EOF + +test_expect_success 'format %w(12,1,2)' ' + + git log -2 --format="%w(12,1,2)This is the %s commit." > actual && + test_cmp expect actual +' + +test_expect_success 'format %w(,1,2)' ' + + git log -2 --format="%w(,1,2)This is%nthe %s%ncommit." > actual && + test_cmp expect actual +' + +cat > expect << EOF +804a787 sixth +394ef78 fifth +5d31159 fourth +2fbe8c0 third +f7dab8e second +3a2fdcb initial +EOF +test_expect_success 'oneline' ' + + git log --oneline > actual && + test_cmp expect actual +' + +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 + } + +' + +test_expect_success 'diff-filter=M' ' + + actual=$(git log --pretty="format:%s" --diff-filter=M HEAD) && + expect=$(echo second) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'diff-filter=D' ' + + actual=$(git log --pretty="format:%s" --diff-filter=D HEAD) && + expect=$(echo sixth ; echo third) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'diff-filter=R' ' + + actual=$(git log -M --pretty="format:%s" --diff-filter=R HEAD) && + expect=$(echo third) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'diff-filter=C' ' + + actual=$(git log -C -C --pretty="format:%s" --diff-filter=C HEAD) && + expect=$(echo fourth) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'git log --follow' ' + + actual=$(git log --follow --pretty="format:%s" ichi) && + expect=$(echo third ; echo second ; echo initial) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +cat > expect << EOF +804a787 sixth +394ef78 fifth +5d31159 fourth +EOF +test_expect_success 'git log --no-walk <commits> sorts by commit time' ' + git log --no-walk --oneline 5d31159 804a787 394ef78 > actual && + test_cmp expect actual +' + +cat > expect << EOF +5d31159 fourth +804a787 sixth +394ef78 fifth +EOF +test_expect_success 'git show <commits> leaves list of commits as given' ' + git show --oneline -s 5d31159 804a787 394ef78 > actual && + test_cmp expect actual +' + +test_expect_success 'setup case sensitivity tests' ' + echo case >one && + test_tick && + git add one + git commit -a -m Second +' + +test_expect_success 'log --grep' ' + echo second >expect && + git log -1 --pretty="tformat:%s" --grep=sec >actual && + test_cmp expect actual +' + +test_expect_success 'log -i --grep' ' + echo Second >expect && + git log -1 --pretty="tformat:%s" -i --grep=sec >actual && + test_cmp expect actual +' + +test_expect_success 'log --grep -i' ' + echo Second >expect && + git log -1 --pretty="tformat:%s" --grep=sec -i >actual && + test_cmp expect actual +' + +cat > expect <<EOF +* Second +* sixth +* fifth +* fourth +* third +* second +* initial +EOF + +test_expect_success 'simple log --graph' ' + git log --graph --pretty=tformat:%s >actual && + test_cmp expect actual +' + +test_expect_success 'set up merge history' ' + git checkout -b side HEAD~4 && + test_commit side-1 1 1 && + test_commit side-2 2 2 && + git checkout master && + git merge side +' + +cat > expect <<\EOF +* Merge branch 'side' +|\ +| * side-2 +| * side-1 +* | Second +* | sixth +* | fifth +* | fourth +|/ +* third +* second +* initial +EOF + +test_expect_success 'log --graph with merge' ' + git log --graph --date-order --pretty=tformat:%s | + sed "s/ *\$//" >actual && + test_cmp expect actual +' + +cat > expect <<\EOF +* commit master +|\ Merge: A B +| | Author: A U Thor <author@example.com> +| | +| | Merge branch 'side' +| | +| * commit side +| | Author: A U Thor <author@example.com> +| | +| | side-2 +| | +| * commit tags/side-1 +| | Author: A U Thor <author@example.com> +| | +| | side-1 +| | +* | commit master~1 +| | Author: A U Thor <author@example.com> +| | +| | Second +| | +* | commit master~2 +| | Author: A U Thor <author@example.com> +| | +| | sixth +| | +* | commit master~3 +| | Author: A U Thor <author@example.com> +| | +| | fifth +| | +* | commit master~4 +|/ Author: A U Thor <author@example.com> +| +| fourth +| +* commit tags/side-1~1 +| Author: A U Thor <author@example.com> +| +| third +| +* commit tags/side-1~2 +| Author: A U Thor <author@example.com> +| +| second +| +* commit tags/side-1~3 + Author: A U Thor <author@example.com> + + initial +EOF + +test_expect_success 'log --graph with full output' ' + git log --graph --date-order --pretty=short | + git name-rev --name-only --stdin | + sed "s/Merge:.*/Merge: A B/;s/ *\$//" >actual && + test_cmp expect actual +' + +test_expect_success 'set up more tangled history' ' + git checkout -b tangle HEAD~6 && + test_commit tangle-a tangle-a a && + git merge master~3 && + git merge side~1 && + git checkout master && + git merge tangle && + git checkout -b reach && + test_commit reach && + git checkout master && + git checkout -b octopus-a && + test_commit octopus-a && + git checkout master && + git checkout -b octopus-b && + test_commit octopus-b && + git checkout master && + test_commit seventh && + git merge octopus-a octopus-b + git merge reach +' + +cat > expect <<\EOF +* Merge commit 'reach' +|\ +| \ +| \ +*-. \ Merge commit 'octopus-a'; commit 'octopus-b' +|\ \ \ +* | | | seventh +| | * | octopus-b +| |/ / +|/| | +| * | octopus-a +|/ / +| * reach +|/ +* Merge branch 'tangle' +|\ +| * Merge branch 'side' (early part) into tangle +| |\ +| * \ Merge branch 'master' (early part) into tangle +| |\ \ +| * | | tangle-a +* | | | Merge branch 'side' +|\ \ \ \ +| * | | | side-2 +| | |_|/ +| |/| | +| * | | side-1 +* | | | Second +* | | | sixth +| |_|/ +|/| | +* | | fifth +* | | fourth +|/ / +* | third +|/ +* second +* initial +EOF + +test_expect_success 'log --graph with merge' ' + git log --graph --date-order --pretty=tformat:%s | + sed "s/ *\$//" >actual && + test_cmp expect actual +' + +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_done + diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh new file mode 100755 index 0000000000..9a7d1b4466 --- /dev/null +++ b/t/t4203-mailmap.sh @@ -0,0 +1,215 @@ +#!/bin/sh + +test_description='.mailmap configurations' + +. ./test-lib.sh + +test_expect_success setup ' + echo one >one && + git add one && + test_tick && + git commit -m initial && + echo two >>one && + git add one && + git commit --author "nick1 <bugs@company.xx>" -m second +' + +cat >expect <<\EOF +A U Thor (1): + initial + +nick1 (1): + second + +EOF + +test_expect_success 'No mailmap' ' + git shortlog HEAD >actual && + test_cmp expect actual +' + +cat >expect <<\EOF +Repo Guy (1): + initial + +nick1 (1): + second + +EOF + +test_expect_success 'default .mailmap' ' + echo "Repo Guy <author@example.com>" > .mailmap && + git shortlog HEAD >actual && + test_cmp expect actual +' + +# Using a mailmap file in a subdirectory of the repo here, but +# could just as well have been a file outside of the repository +cat >expect <<\EOF +Internal Guy (1): + second + +Repo Guy (1): + initial + +EOF +test_expect_success 'mailmap.file set' ' + mkdir internal_mailmap && + echo "Internal Guy <bugs@company.xx>" > internal_mailmap/.mailmap && + git config mailmap.file internal_mailmap/.mailmap && + git shortlog HEAD >actual && + test_cmp expect actual +' + +cat >expect <<\EOF +External Guy (1): + initial + +Internal Guy (1): + second + +EOF +test_expect_success 'mailmap.file override' ' + echo "External Guy <author@example.com>" >> internal_mailmap/.mailmap && + git config mailmap.file internal_mailmap/.mailmap && + git shortlog HEAD >actual && + test_cmp expect actual +' + +cat >expect <<\EOF +Repo Guy (1): + initial + +nick1 (1): + second + +EOF + +test_expect_success 'mailmap.file non-existant' ' + rm internal_mailmap/.mailmap && + rmdir internal_mailmap && + git shortlog HEAD >actual && + test_cmp expect actual +' + +cat >expect <<\EOF +A U Thor (1): + initial + +nick1 (1): + second + +EOF +test_expect_success 'No mailmap files, but configured' ' + rm .mailmap && + git shortlog HEAD >actual && + test_cmp expect actual +' + +# Extended mailmap configurations should give us the following output for shortlog +cat >expect <<\EOF +A U Thor <author@example.com> (1): + initial + +CTO <cto@company.xx> (1): + seventh + +Other Author <other@author.xx> (2): + third + fourth + +Santa Claus <santa.claus@northpole.xx> (2): + fifth + sixth + +Some Dude <some@dude.xx> (1): + second + +EOF + +test_expect_success 'Shortlog output (complex mapping)' ' + echo three >>one && + git add one && + test_tick && + git commit --author "nick2 <bugs@company.xx>" -m third && + + echo four >>one && + git add one && + test_tick && + git commit --author "nick2 <nick2@company.xx>" -m fourth && + + echo five >>one && + git add one && + test_tick && + git commit --author "santa <me@company.xx>" -m fifth && + + echo six >>one && + git add one && + test_tick && + git commit --author "claus <me@company.xx>" -m sixth && + + echo seven >>one && + git add one && + test_tick && + git commit --author "CTO <cto@coompany.xx>" -m seventh && + + mkdir internal_mailmap && + echo "Committed <committer@example.com>" > internal_mailmap/.mailmap && + echo "<cto@company.xx> <cto@coompany.xx>" >> internal_mailmap/.mailmap && + echo "Some Dude <some@dude.xx> nick1 <bugs@company.xx>" >> internal_mailmap/.mailmap && + echo "Other Author <other@author.xx> nick2 <bugs@company.xx>" >> internal_mailmap/.mailmap && + echo "Other Author <other@author.xx> <nick2@company.xx>" >> internal_mailmap/.mailmap && + echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap && + echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap && + + git shortlog -e HEAD >actual && + test_cmp expect actual + +' + +# git log with --pretty format which uses the name and email mailmap placemarkers +cat >expect <<\EOF +Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author claus <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author santa <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author nick2 <nick2@company.xx> maps to Other Author <other@author.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author nick2 <bugs@company.xx> maps to Other Author <other@author.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author nick1 <bugs@company.xx> maps to Some Dude <some@dude.xx> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> + +Author A U Thor <author@example.com> maps to A U Thor <author@example.com> +Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +EOF + +test_expect_success 'Log output (complex mapping)' ' + git log --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && + test_cmp expect actual +' + +# git blame +cat >expect <<\EOF +^3a2fdcb (A U Thor 2005-04-07 15:13:13 -0700 1) one +7de6f99b (Some Dude 2005-04-07 15:13:13 -0700 2) two +5815879d (Other Author 2005-04-07 15:14:13 -0700 3) three +ff859d96 (Other Author 2005-04-07 15:15:13 -0700 4) four +5ab6d4fa (Santa Claus 2005-04-07 15:16:13 -0700 5) five +38a42d8b (Santa Claus 2005-04-07 15:17:13 -0700 6) six +8ddc0386 (CTO 2005-04-07 15:18:13 -0700 7) seven +EOF + +test_expect_success 'Blame output (complex mapping)' ' + git blame one >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh new file mode 100755 index 0000000000..68e2652814 --- /dev/null +++ b/t/t4204-patch-id.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +test_description='git patch-id' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit initial foo a && + test_commit first foo b && + git checkout -b same HEAD^ && + test_commit same-msg foo b && + git checkout -b notsame HEAD^ && + test_commit notsame-msg foo c +' + +test_expect_success 'patch-id output is well-formed' ' + git log -p -1 | git patch-id > output && + 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" +} + +test_expect_success 'patch-id detects equality' ' + get_patch_id master && + get_patch_id same && + test_cmp patch-id_master patch-id_same +' + +test_expect_success 'patch-id detects inequality' ' + get_patch_id master && + get_patch_id notsame && + ! 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/t4252-am-options.sh b/t/t4252-am-options.sh new file mode 100755 index 0000000000..f603c1b133 --- /dev/null +++ b/t/t4252-am-options.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +test_description='git am with options and not losing them' +. ./test-lib.sh + +tm="$TEST_DIRECTORY/t4252" + +test_expect_success setup ' + cp "$tm/file-1-0" file-1 && + cp "$tm/file-2-0" file-2 && + git add file-1 file-2 && + test_tick && + git commit -m initial && + git tag initial +' + +test_expect_success 'interrupted am --whitespace=fix' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am --whitespace=fix "$tm"/am-test-1-? && + git am --skip && + grep 3 file-1 && + grep "^Six$" file-2 +' + +test_expect_success 'interrupted am -C1' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am -C1 "$tm"/am-test-2-? && + git am --skip && + grep 3 file-1 && + grep "^Three$" file-2 +' + +test_expect_success 'interrupted am -p2' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am -p2 "$tm"/am-test-3-? && + git am --skip && + grep 3 file-1 && + grep "^Three$" file-2 +' + +test_expect_success 'interrupted am -C1 -p2' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am -p2 -C1 "$tm"/am-test-4-? && + git am --skip && + grep 3 file-1 && + grep "^Three$" file-2 +' + +test_expect_success 'interrupted am --directory="frotz nitfol"' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am --directory="frotz nitfol" "$tm"/am-test-5-? && + git am --skip && + grep One "frotz nitfol/file-5" +' + +test_expect_success 'apply to a funny path' ' + with_sq="with'\''sq" + rm -fr .git/rebase-apply && + git reset --hard initial && + git am --directory="$with_sq" "$tm"/am-test-5-2 && + test -f "$with_sq/file-5" +' + +test_expect_success 'am --reject' ' + rm -rf .git/rebase-apply && + git reset --hard initial && + test_must_fail git am --reject "$tm"/am-test-6-1 && + grep "@@ -1,3 +1,3 @@" file-2.rej && + test_must_fail git diff-files --exit-code --quiet file-2 && + grep "[-]-reject" .git/rebase-apply/apply-opt +' + +test_done diff --git a/t/t4252/am-test-1-1 b/t/t4252/am-test-1-1 new file mode 100644 index 0000000000..b0c09dc965 --- /dev/null +++ b/t/t4252/am-test-1-1 @@ -0,0 +1,19 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Three + +Application of this should be rejected because the first line in the +context does not match. + +diff --git i/file-1 w/file-1 +index 06e567b..10f8342 100644 +--- i/file-1 ++++ w/file-1 +@@ -1,6 +1,6 @@ + One + 2 +-3 ++Three + 4 + 5 + 6 diff --git a/t/t4252/am-test-1-2 b/t/t4252/am-test-1-2 new file mode 100644 index 0000000000..1b874ae115 --- /dev/null +++ b/t/t4252/am-test-1-2 @@ -0,0 +1,21 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with --whitespace=fix should lose +the trailing whitespace after "Six". + +diff --git i/file-2 w/file-2 +index 06e567b..b6f3a16 100644 +--- i/file-2 ++++ w/file-2 +@@ -1,7 +1,7 @@ + 1 + 2 +-3 ++Three + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/am-test-2-1 b/t/t4252/am-test-2-1 new file mode 100644 index 0000000000..feda94a0cc --- /dev/null +++ b/t/t4252/am-test-2-1 @@ -0,0 +1,19 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Three + +Application of this should be rejected even with -C1 because the +preimage line in the context does not match. + +diff --git i/file-1 w/file-1 +index 06e567b..10f8342 100644 +--- i/file-1 ++++ w/file-1 +@@ -1,6 +1,6 @@ + 1 + 2 +-Tres ++Three + 4 + 5 + 6 diff --git a/t/t4252/am-test-2-2 b/t/t4252/am-test-2-2 new file mode 100644 index 0000000000..2ac6600976 --- /dev/null +++ b/t/t4252/am-test-2-2 @@ -0,0 +1,21 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with -C1 should be successful even though +the first line in the context does not match. + +diff --git i/file-2 w/file-2 +index 06e567b..b6f3a16 100644 +--- i/file-2 ++++ w/file-2 +@@ -1,7 +1,7 @@ + One + 2 +-3 ++Three + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/am-test-3-1 b/t/t4252/am-test-3-1 new file mode 100644 index 0000000000..608e5abba4 --- /dev/null +++ b/t/t4252/am-test-3-1 @@ -0,0 +1,19 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Three + +Application of this should be rejected even with -p2 because the +preimage line in the context does not match. + +diff --git i/junk/file-1 w/junk/file-1 +index 06e567b..10f8342 100644 +--- i/junk/file-1 ++++ w/junk/file-1 +@@ -1,6 +1,6 @@ + 1 + 2 +-Tres ++Three + 4 + 5 + 6 diff --git a/t/t4252/am-test-3-2 b/t/t4252/am-test-3-2 new file mode 100644 index 0000000000..0081b96f2a --- /dev/null +++ b/t/t4252/am-test-3-2 @@ -0,0 +1,21 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with -p2 should be successful even though +the patch is against a wrong level. + +diff --git i/junk/file-2 w/junk/file-2 +index 06e567b..b6f3a16 100644 +--- i/junk/file-2 ++++ w/junk/file-2 +@@ -1,7 +1,7 @@ + 1 + 2 +-3 ++Three + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/am-test-4-1 b/t/t4252/am-test-4-1 new file mode 100644 index 0000000000..e48cd6cbde --- /dev/null +++ b/t/t4252/am-test-4-1 @@ -0,0 +1,19 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Three + +Application of this should be rejected even with -C1 -p2 because +the preimage line in the context does not match. + +diff --git i/junk/file-1 w/junk/file-1 +index 06e567b..10f8342 100644 +--- i/junk/file-1 ++++ w/junk/file-1 +@@ -1,6 +1,6 @@ + 1 + 2 +-Tres ++Three + 4 + 5 + 6 diff --git a/t/t4252/am-test-4-2 b/t/t4252/am-test-4-2 new file mode 100644 index 0000000000..0e69bfa55b --- /dev/null +++ b/t/t4252/am-test-4-2 @@ -0,0 +1,22 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with -C1 -p2 should be successful even though +the patch is against a wrong level and the first context line does +not match. + +diff --git i/junk/file-2 w/junk/file-2 +index 06e567b..b6f3a16 100644 +--- i/junk/file-2 ++++ w/junk/file-2 +@@ -1,7 +1,7 @@ + One + 2 +-3 ++Three + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/am-test-5-1 b/t/t4252/am-test-5-1 new file mode 100644 index 0000000000..da7bf29cbe --- /dev/null +++ b/t/t4252/am-test-5-1 @@ -0,0 +1,20 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with --directory='frotz nitfol' should fail + +diff --git i/junk/file-2 w/junk/file-2 +index 06e567b..b6f3a16 100644 +--- i/junk/file-2 ++++ w/junk/file-2 +@@ -1,7 +1,7 @@ + One + 2 +-3 ++Three + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/am-test-5-2 b/t/t4252/am-test-5-2 new file mode 100644 index 0000000000..373025bcf6 --- /dev/null +++ b/t/t4252/am-test-5-2 @@ -0,0 +1,15 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Six + +Applying this patch with --directory='frotz nitfol' should succeed + +diff --git i/file-5 w/file-5 +new file mode 100644 +index 000000..1d6ed9f +--- /dev/null ++++ w/file-5 +@@ -0,0 +1,3 @@ ++One ++two ++three diff --git a/t/t4252/am-test-6-1 b/t/t4252/am-test-6-1 new file mode 100644 index 0000000000..a8859e9b8f --- /dev/null +++ b/t/t4252/am-test-6-1 @@ -0,0 +1,21 @@ +From: A U Thor <au.thor@example.com> +Date: Thu Dec 4 16:00:00 2008 -0800 +Subject: Huh + +Should fail and leave rejects + +diff --git i/file-2 w/file-2 +index 06e567b..b6f3a16 100644 +--- i/file-2 ++++ w/file-2 +@@ -1,3 +1,3 @@ +-0 ++One + 2 + 3 +@@ -4,4 +4,4 @@ + 4 + 5 +-6 ++Six + 7 diff --git a/t/t4252/file-1-0 b/t/t4252/file-1-0 new file mode 100644 index 0000000000..06e567b11d --- /dev/null +++ b/t/t4252/file-1-0 @@ -0,0 +1,7 @@ +1 +2 +3 +4 +5 +6 +7 diff --git a/t/t4252/file-2-0 b/t/t4252/file-2-0 new file mode 100644 index 0000000000..06e567b11d --- /dev/null +++ b/t/t4252/file-2-0 @@ -0,0 +1,7 @@ +1 +2 +3 +4 +5 +6 +7 diff --git a/t/t4253-am-keep-cr-dos.sh b/t/t4253-am-keep-cr-dos.sh new file mode 100755 index 0000000000..735e55d77c --- /dev/null +++ b/t/t4253-am-keep-cr-dos.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# +# Copyright (c) 2010 Stefan-W. Hahn +# + +test_description='git-am mbox with dos line ending. + +' +. ./test-lib.sh + +# Three patches which will be added as files with dos line ending. + +cat >file1 <<\EOF +line 1 +EOF + +cat >file1a <<\EOF +line 1 +line 4 +EOF + +cat >file2 <<\EOF +line 1 +line 2 +EOF + +cat >file3 <<\EOF +line 1 +line 2 +line 3 +EOF + +test_expect_success 'setup repository with dos files' ' + append_cr <file1 >file && + git add file && + git commit -m Initial && + git tag initial && + append_cr <file2 >file && + git commit -a -m Second && + append_cr <file3 >file && + git commit -a -m Third +' + +test_expect_success 'am with dos files without --keep-cr' ' + git checkout -b dosfiles initial && + git format-patch -k initial..master && + test_must_fail git am -k -3 000*.patch && + git am --abort && + rm -rf .git/rebase-apply 000*.patch +' + +test_expect_success 'am with dos files with --keep-cr' ' + git checkout -b dosfiles-keep-cr initial && + git format-patch -k --stdout initial..master | git am --keep-cr -k -3 && + git diff --exit-code master +' + +test_expect_success 'am with dos files config am.keepcr' ' + git config am.keepcr 1 && + git checkout -b dosfiles-conf-keepcr initial && + git format-patch -k --stdout initial..master | git am -k -3 && + git diff --exit-code master +' + +test_expect_success 'am with dos files config am.keepcr overriden by --no-keep-cr' ' + git config am.keepcr 1 && + git checkout -b dosfiles-conf-keepcr-override initial && + git format-patch -k initial..master && + test_must_fail git am -k -3 --no-keep-cr 000*.patch && + git am --abort && + rm -rf .git/rebase-apply 000*.patch +' + +test_expect_success 'am with dos files with --keep-cr continue' ' + git checkout -b dosfiles-keep-cr-continue initial && + git format-patch -k initial..master && + append_cr <file1a >file && + git commit -m "different patch" file && + test_must_fail git am --keep-cr -k -3 000*.patch && + append_cr <file2 >file && + git add file && + git am -3 --resolved && + git diff --exit-code master +' + +test_expect_success 'am with unix files config am.keepcr overriden by --no-keep-cr' ' + git config am.keepcr 1 && + git checkout -b unixfiles-conf-keepcr-override initial && + cp -f file1 file && + git commit -m "line ending to unix" file && + git format-patch -k initial..master && + git am -k -3 --no-keep-cr 000*.patch && + git diff --exit-code -w master +' + +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 ac835fe431..27bfba55bd 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -3,7 +3,7 @@ # Copyright (C) 2005 Rene Scharfe # -test_description='git-tar-tree and git-get-tar-commit-id test +test_description='git tar-tree and git get-tar-commit-id test This test covers the topics of file contents, commit date handling and commit id embedding: @@ -13,121 +13,243 @@ commit id embedding: binary file (/bin/sh). Only paths shorter than 99 characters are used. - git-tar-tree applies the commit date to every file in the archive it + git tar-tree applies the commit date to every file in the archive it creates. The test sets the commit date to a specific value and checks if the tar archive contains that value. - When giving git-tar-tree a commit id (in contrast to a tree id) it + When giving git tar-tree a commit id (in contrast to a tree id) it embeds this commit id into the tar archive as a comment. The test - checks the ability of git-get-tar-commit-id to figure it out from the + checks the ability of git get-tar-commit-id to figure it out from the tar file. ' . ./test-lib.sh -TAR=${TAR:-tar} UNZIP=${UNZIP:-unzip} +SUBSTFORMAT=%H%n + test_expect_success \ 'populate workdir' \ 'mkdir a b c && echo simple textfile >a/a && mkdir a/bin && cp /bin/sh a/bin && - ln -s a a/l1 && + printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 && + printf "A not substituted O" >a/substfile2 && + if test_have_prereq SYMLINKS; then + ln -s a a/l1 + else + printf %s a > a/l1 + fi && (p=long_path_to_a_file && cd a && for depth in 1 2 3 4 5; do mkdir $p && cd $p; done && echo text >file_with_long_path) && (cd a && find .) | sort >a.lst' test_expect_success \ + 'add ignored file' \ + 'echo ignore me >a/ignored && + echo ignored export-ignore >.git/info/attributes' + +test_expect_success \ 'add files to repository' \ - 'find a -type f | xargs git-update-index --add && - find a -type l | xargs git-update-index --add && - treeid=`git-write-tree` && + 'find a -type f | xargs git update-index --add && + find a -type l | xargs git update-index --add && + treeid=`git write-tree` && echo $treeid >treeid && - git-update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \ - git-commit-tree $treeid </dev/null)' + git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \ + git commit-tree $treeid </dev/null)' + +test_expect_success \ + 'create bare clone' \ + 'git clone --bare . bare.git && + cp .git/info/attributes bare.git/info/attributes' + +test_expect_success \ + 'remove ignored file' \ + 'rm a/ignored' + +test_expect_success \ + 'git archive' \ + 'git archive HEAD >b.tar' + +test_expect_success \ + 'git tar-tree' \ + 'git tar-tree HEAD >b2.tar' + +test_expect_success \ + 'git archive vs. git tar-tree' \ + 'test_cmp b.tar b2.tar' + +test_expect_success \ + 'git archive in a bare repo' \ + '(cd bare.git && git archive HEAD) >b3.tar' test_expect_success \ - 'git-tar-tree' \ - 'git-tar-tree HEAD >b.tar' + 'git archive vs. the same in a bare repo' \ + 'test_cmp b.tar b3.tar' + +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' \ + 'git archive --remote=. HEAD >b5.tar && + test_cmp b.tar b5.tar' test_expect_success \ 'validate file modification time' \ - 'TZ=GMT $TAR tvf b.tar a/a | - awk \{print\ \$4,\ \(length\(\$5\)\<7\)\ ?\ \$5\":00\"\ :\ \$5\} \ - >b.mtime && - echo "2005-05-27 22:00:00" >expected.mtime && - diff expected.mtime b.mtime' + 'mkdir extract && + "$TAR" xf b.tar -C extract a/a && + test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime && + echo "1117231200" >expected.mtime && + test_cmp expected.mtime b.mtime' test_expect_success \ - 'git-get-tar-commit-id' \ - 'git-get-tar-commit-id <b.tar >b.commitid && - diff .git/$(git-symbolic-ref HEAD) b.commitid' + 'git get-tar-commit-id' \ + 'git get-tar-commit-id <b.tar >b.commitid && + test_cmp .git/$(git symbolic-ref HEAD) b.commitid' test_expect_success \ 'extract tar archive' \ - '(cd b && $TAR xf -) <b.tar' + '(cd b && "$TAR" xf -) <b.tar' test_expect_success \ 'validate filenames' \ '(cd b/a && find .) | sort >b.lst && - diff a.lst b.lst' + test_cmp a.lst b.lst' test_expect_success \ 'validate file contents' \ 'diff -r a b/a' test_expect_success \ - 'git-tar-tree with prefix' \ - 'git-tar-tree HEAD prefix >c.tar' + 'git tar-tree with prefix' \ + 'git tar-tree HEAD prefix >c.tar' test_expect_success \ 'extract tar archive with prefix' \ - '(cd c && $TAR xf -) <c.tar' + '(cd c && "$TAR" xf -) <c.tar' test_expect_success \ 'validate filenames with prefix' \ '(cd c/prefix/a && find .) | sort >c.lst && - diff a.lst c.lst' + test_cmp a.lst c.lst' test_expect_success \ 'validate file contents with prefix' \ 'diff -r a c/prefix/a' test_expect_success \ - 'git-archive --format=zip' \ - 'git-archive --format=zip HEAD >d.zip' + 'create archives with substfiles' \ + 'cp .git/info/attributes .git/info/attributes.before && + echo "substfile?" export-subst >>.git/info/attributes && + git archive HEAD >f.tar && + git archive --prefix=prefix/ HEAD >g.tar && + mv .git/info/attributes.before .git/info/attributes' + +test_expect_success \ + 'extract substfiles' \ + '(mkdir f && cd f && "$TAR" xf -) <f.tar' + +test_expect_success \ + 'validate substfile contents' \ + 'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ + >f/a/substfile1.expected && + test_cmp f/a/substfile1.expected f/a/substfile1 && + test_cmp a/substfile2 f/a/substfile2 +' + +test_expect_success \ + 'extract substfiles from archive with prefix' \ + '(mkdir g && cd g && "$TAR" xf -) <g.tar' test_expect_success \ + 'validate substfile contents from archive with prefix' \ + 'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \ + >g/prefix/a/substfile1.expected && + test_cmp g/prefix/a/substfile1.expected g/prefix/a/substfile1 && + test_cmp a/substfile2 g/prefix/a/substfile2 +' + +test_expect_success \ + 'git archive --format=zip' \ + 'git archive --format=zip HEAD >d.zip' + +test_expect_success \ + 'git archive --format=zip in a bare repo' \ + '(cd bare.git && git archive --format=zip HEAD) >d1.zip' + +test_expect_success \ + 'git archive --format=zip vs. the same in a bare repo' \ + 'test_cmp d.zip d1.zip' + +test_expect_success 'git archive --format=zip with --output' \ + 'git archive --format=zip --output=d2.zip HEAD && + test_cmp d.zip d2.zip' + +test_expect_success 'git archive with --output, inferring format' ' + git archive --output=d3.zip HEAD && + test_cmp d.zip d3.zip +' + +test_expect_success 'git archive with --output, override inferred format' ' + git archive --format=tar --output=d4.zip HEAD && + test_cmp b.tar d4.zip +' + +$UNZIP -v >/dev/null 2>&1 +if [ $? -eq 127 ]; then + say "Skipping ZIP tests, because unzip was not found" +else + test_set_prereq UNZIP +fi + +test_expect_success UNZIP \ 'extract ZIP archive' \ '(mkdir d && cd d && $UNZIP ../d.zip)' -test_expect_success \ +test_expect_success UNZIP \ 'validate filenames' \ '(cd d/a && find .) | sort >d.lst && - diff a.lst d.lst' + test_cmp a.lst d.lst' -test_expect_success \ +test_expect_success UNZIP \ 'validate file contents' \ 'diff -r a d/a' test_expect_success \ - 'git-archive --format=zip with prefix' \ - 'git-archive --format=zip --prefix=prefix/ HEAD >e.zip' + 'git archive --format=zip with prefix' \ + 'git archive --format=zip --prefix=prefix/ HEAD >e.zip' -test_expect_success \ +test_expect_success UNZIP \ 'extract ZIP archive with prefix' \ '(mkdir e && cd e && $UNZIP ../e.zip)' -test_expect_success \ +test_expect_success UNZIP \ 'validate filenames with prefix' \ '(cd e/prefix/a && find .) | sort >e.lst && - diff a.lst e.lst' + test_cmp a.lst e.lst' -test_expect_success \ +test_expect_success UNZIP \ 'validate file contents with prefix' \ 'diff -r a e/prefix/a' +test_expect_success \ + 'git archive --list outside of a git repo' \ + 'GIT_DIR=some/non-existing/directory git archive --list' + +test_expect_success 'git-archive --prefix=olde-' ' + git archive --prefix=olde- >h.tar HEAD && + ( + mkdir h && + cd h && + "$TAR" xf - <../h.tar + ) && + test -d h/olde-a && + test -d h/olde-a/bin && + test -f h/olde-a/bin/sh +' + test_done diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh new file mode 100755 index 0000000000..426b319bd3 --- /dev/null +++ b/t/t5001-archive-attr.sh @@ -0,0 +1,91 @@ +#!/bin/sh + +test_description='git archive attribute tests' + +. ./test-lib.sh + +SUBSTFORMAT=%H%n + +test_expect_exists() { + test_expect_success " $1 exists" "test -e $1" +} + +test_expect_missing() { + test_expect_success " $1 does not exist" "test ! -e $1" +} + +test_expect_success 'setup' ' + echo ignored >ignored && + echo ignored export-ignore >>.git/info/attributes && + git add ignored && + + echo ignored by tree >ignored-by-tree && + echo ignored-by-tree export-ignore >.gitattributes && + git add ignored-by-tree .gitattributes && + + echo ignored by worktree >ignored-by-worktree && + echo ignored-by-worktree export-ignore >.gitattributes && + git add ignored-by-worktree && + + printf "A\$Format:%s\$O" "$SUBSTFORMAT" >nosubstfile && + printf "A\$Format:%s\$O" "$SUBSTFORMAT" >substfile1 && + printf "A not substituted O" >substfile2 && + echo "substfile?" export-subst >>.git/info/attributes && + git add nosubstfile substfile1 substfile2 && + + git commit -m. && + + git clone --bare . bare && + cp .git/info/attributes bare/info/attributes +' + +test_expect_success 'git archive' ' + git archive HEAD >archive.tar && + (mkdir archive && cd archive && "$TAR" xf -) <archive.tar +' + +test_expect_missing archive/ignored +test_expect_missing archive/ignored-by-tree +test_expect_exists archive/ignored-by-worktree + +test_expect_success 'git archive with worktree attributes' ' + git archive --worktree-attributes HEAD >worktree.tar && + (mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar +' + +test_expect_missing worktree/ignored +test_expect_exists worktree/ignored-by-tree +test_expect_missing worktree/ignored-by-worktree + +test_expect_success 'git archive vs. bare' ' + (cd bare && git archive HEAD) >bare-archive.tar && + test_cmp archive.tar bare-archive.tar +' + +test_expect_success 'git archive with worktree attributes, bare' ' + (cd bare && git archive --worktree-attributes HEAD) >bare-worktree.tar && + (mkdir bare-worktree && cd bare-worktree && "$TAR" xf -) <bare-worktree.tar +' + +test_expect_missing bare-worktree/ignored +test_expect_exists bare-worktree/ignored-by-tree +test_expect_exists bare-worktree/ignored-by-worktree + +test_expect_success 'export-subst' ' + git log "--pretty=format:A${SUBSTFORMAT}O" HEAD >substfile1.expected && + test_cmp nosubstfile archive/nosubstfile && + test_cmp substfile1.expected archive/substfile1 && + test_cmp substfile2 archive/substfile2 +' + +test_expect_success 'git tar-tree vs. git archive with worktree attributes' ' + git tar-tree HEAD >tar-tree.tar && + test_cmp worktree.tar tar-tree.tar +' + +test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' ' + (cd bare && git tar-tree HEAD) >bare-tar-tree.tar && + test_cmp bare-worktree.tar bare-tar-tree.tar +' + +test_done diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index 4d2b781a18..ebc36c1758 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -3,26 +3,90 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-mailinfo and git-mailsplit test' +test_description='git mailinfo and git mailsplit test' . ./test-lib.sh test_expect_success 'split sample box' \ - 'git-mailsplit -o. ../t5100/sample.mbox >last && + 'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last && last=`cat last` && echo total is $last && - test `cat last` = 6' + test `cat last` = 16' + +check_mailinfo () { + mail=$1 opt=$2 + mo="$mail$opt" + git mailinfo -u $opt msg$mo patch$mo <$mail >info$mo && + test_cmp "$TEST_DIRECTORY"/t5100/msg$mo msg$mo && + test_cmp "$TEST_DIRECTORY"/t5100/patch$mo patch$mo && + test_cmp "$TEST_DIRECTORY"/t5100/info$mo info$mo +} + for mail in `echo 00*` do - test_expect_success "mailinfo $mail" \ - "git-mailinfo -u msg$mail patch$mail <$mail >info$mail && + test_expect_success "mailinfo $mail" ' + check_mailinfo $mail "" && + if test -f "$TEST_DIRECTORY"/t5100/msg$mail--scissors + then + check_mailinfo $mail --scissors + fi && + if test -f "$TEST_DIRECTORY"/t5100/msg$mail--no-inbody-headers + then + check_mailinfo $mail --no-inbody-headers + fi + ' +done + + +test_expect_success 'split box with rfc2047 samples' \ + 'mkdir rfc2047 && + git mailsplit -orfc2047 "$TEST_DIRECTORY"/t5100/rfc2047-samples.mbox \ + >rfc2047/last && + last=`cat rfc2047/last` && + echo total is $last && + test `cat rfc2047/last` = 11' + +for mail in `echo rfc2047/00*` +do + test_expect_success "mailinfo $mail" ' + git mailinfo -u $mail-msg $mail-patch <$mail >$mail-info && echo msg && - diff ../t5100/msg$mail msg$mail && + test_cmp "$TEST_DIRECTORY"/t5100/empty $mail-msg && echo patch && - diff ../t5100/patch$mail patch$mail && + test_cmp "$TEST_DIRECTORY"/t5100/empty $mail-patch && echo info && - diff ../t5100/info$mail info$mail" + test_cmp "$TEST_DIRECTORY"/t5100/rfc2047-info-$(basename $mail) $mail-info + ' done +test_expect_success 'respect NULs' ' + + git mailsplit -d3 -o. "$TEST_DIRECTORY"/t5100/nul-plain && + test_cmp "$TEST_DIRECTORY"/t5100/nul-plain 001 && + (cat 001 | git mailinfo msg patch) && + test 4 = $(wc -l < patch) + +' + +test_expect_success 'Preserve NULs out of MIME encoded message' ' + + git mailsplit -d5 -o. "$TEST_DIRECTORY"/t5100/nul-b64.in && + test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.in 00001 && + git mailinfo msg patch <00001 && + test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.expect patch + +' + +test_expect_success 'mailinfo on from header without name works' ' + + mkdir info-from && + git mailsplit -oinfo-from "$TEST_DIRECTORY"/t5100/info-from.in && + test_cmp "$TEST_DIRECTORY"/t5100/info-from.in info-from/0001 && + git mailinfo info-from/msg info-from/patch \ + <info-from/0001 >info-from/out && + test_cmp "$TEST_DIRECTORY"/t5100/info-from.expect info-from/out + +' + test_done diff --git a/t/t5100/.gitattributes b/t/t5100/.gitattributes new file mode 100644 index 0000000000..c93f5142fa --- /dev/null +++ b/t/t5100/.gitattributes @@ -0,0 +1,4 @@ +msg* encoding=UTF-8 +info* encoding=UTF-8 +rfc2047-info-* encoding=UTF-8 +sample.mbox encoding=UTF-8 diff --git a/t/t5100/empty b/t/t5100/empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/t/t5100/empty diff --git a/t/t5100/info-from.expect b/t/t5100/info-from.expect new file mode 100644 index 0000000000..c31d2eb550 --- /dev/null +++ b/t/t5100/info-from.expect @@ -0,0 +1,5 @@ +Author: bare@example.com +Email: bare@example.com +Subject: testing bare address in from header +Date: Sun, 25 May 2008 00:38:18 -0700 + diff --git a/t/t5100/info-from.in b/t/t5100/info-from.in new file mode 100644 index 0000000000..4f082093fc --- /dev/null +++ b/t/t5100/info-from.in @@ -0,0 +1,8 @@ +From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001 +From: bare@example.com +Date: Sun, 25 May 2008 00:38:18 -0700 +Subject: [PATCH] testing bare address in from header + +commit message +--- +patch diff --git a/t/t5100/info0001 b/t/t5100/info0001 index 8c052777e0..f951538acc 100644 --- a/t/t5100/info0001 +++ b/t/t5100/info0001 @@ -1,4 +1,4 @@ -Author: A U Thor +Author: A (zzz) U Thor (Comment) Email: a.u.thor@example.com Subject: a commit. Date: Fri, 9 Jun 2006 00:44:16 -0700 diff --git a/t/t5100/info0007 b/t/t5100/info0007 new file mode 100644 index 0000000000..49bb0fec85 --- /dev/null +++ b/t/t5100/info0007 @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: another patch +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/info0008 b/t/t5100/info0008 new file mode 100644 index 0000000000..e8a2951383 --- /dev/null +++ b/t/t5100/info0008 @@ -0,0 +1,5 @@ +Author: Junio C Hamano +Email: junio@kernel.org +Subject: another patch +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/info0009 b/t/t5100/info0009 new file mode 100644 index 0000000000..2a66321c80 --- /dev/null +++ b/t/t5100/info0009 @@ -0,0 +1,5 @@ +Author: F U Bar +Email: f.u.bar@example.com +Subject: updates +Date: Mon, 17 Sep 2001 00:00:00 +0900 + diff --git a/t/t5100/info0010 b/t/t5100/info0010 new file mode 100644 index 0000000000..1791241e46 --- /dev/null +++ b/t/t5100/info0010 @@ -0,0 +1,5 @@ +Author: Lukas Sandström +Email: lukass@etek.chalmers.se +Subject: git-mailinfo: Fix getting the subject from the body +Date: Thu, 10 Jul 2008 23:41:33 +0200 + diff --git a/t/t5100/info0011 b/t/t5100/info0011 new file mode 100644 index 0000000000..da5a605a12 --- /dev/null +++ b/t/t5100/info0011 @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: Xyzzy +Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST) + diff --git a/t/t5100/info0012 b/t/t5100/info0012 new file mode 100644 index 0000000000..ac1216ff75 --- /dev/null +++ b/t/t5100/info0012 @@ -0,0 +1,5 @@ +Author: Dmitriy Blinov +Email: bda@mnsspb.ru +Subject: Изменён ÑпиÑок пакетов необходимых Ð´Ð»Ñ Ñборки +Date: Wed, 12 Nov 2008 17:54:41 +0300 + diff --git a/t/t5100/info0013 b/t/t5100/info0013 new file mode 100644 index 0000000000..bbe049e20e --- /dev/null +++ b/t/t5100/info0013 @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: a patch +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/info0014 b/t/t5100/info0014 new file mode 100644 index 0000000000..08566b34b9 --- /dev/null +++ b/t/t5100/info0014 @@ -0,0 +1,5 @@ +Author: Junio Hamano +Email: junkio@cox.net +Subject: BLAH ONE +Date: Thu, 20 Aug 2009 17:18:22 -0700 + diff --git a/t/t5100/info0014--scissors b/t/t5100/info0014--scissors new file mode 100644 index 0000000000..ab9c8d0905 --- /dev/null +++ b/t/t5100/info0014--scissors @@ -0,0 +1,5 @@ +Author: Junio C Hamano +Email: gitster@pobox.com +Subject: Teach mailinfo to ignore everything before -- >8 -- mark +Date: Thu, 20 Aug 2009 17:18:22 -0700 + diff --git a/t/t5100/info0015 b/t/t5100/info0015 new file mode 100644 index 0000000000..0114f106c5 --- /dev/null +++ b/t/t5100/info0015 @@ -0,0 +1,5 @@ +Author: +Email: +Subject: check bogus body header (from) +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/info0015--no-inbody-headers b/t/t5100/info0015--no-inbody-headers new file mode 100644 index 0000000000..c4d8d7720e --- /dev/null +++ b/t/t5100/info0015--no-inbody-headers @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: check bogus body header (from) +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/info0016 b/t/t5100/info0016 new file mode 100644 index 0000000000..38ccd0dcf2 --- /dev/null +++ b/t/t5100/info0016 @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: check bogus body header (date) +Date: bogus + diff --git a/t/t5100/info0016--no-inbody-headers b/t/t5100/info0016--no-inbody-headers new file mode 100644 index 0000000000..f4857d45df --- /dev/null +++ b/t/t5100/info0016--no-inbody-headers @@ -0,0 +1,5 @@ +Author: A U Thor +Email: a.u.thor@example.com +Subject: check bogus body header (date) +Date: Fri, 9 Jun 2006 00:44:16 -0700 + diff --git a/t/t5100/msg0007 b/t/t5100/msg0007 new file mode 100644 index 0000000000..71b23c0236 --- /dev/null +++ b/t/t5100/msg0007 @@ -0,0 +1,2 @@ +Here is an empty patch from A U Thor. + diff --git a/t/t5100/msg0008 b/t/t5100/msg0008 new file mode 100644 index 0000000000..a80ecb97ef --- /dev/null +++ b/t/t5100/msg0008 @@ -0,0 +1,4 @@ +>Here is an empty patch from A U Thor. + +Hey you forgot the patch! + diff --git a/t/t5100/msg0009 b/t/t5100/msg0009 new file mode 100644 index 0000000000..9ffe131489 --- /dev/null +++ b/t/t5100/msg0009 @@ -0,0 +1,2 @@ +This is to fix diff-format documentation. + diff --git a/t/t5100/msg0010 b/t/t5100/msg0010 new file mode 100644 index 0000000000..a96c230092 --- /dev/null +++ b/t/t5100/msg0010 @@ -0,0 +1,5 @@ +"Subject: " isn't in the static array "header", and thus +memcmp("Subject: ", header[i], 7) will never match. + +Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se> +Signed-off-by: Junio C Hamano <gitster@pobox.com> diff --git a/t/t5100/msg0011 b/t/t5100/msg0011 new file mode 100644 index 0000000000..4667f21007 --- /dev/null +++ b/t/t5100/msg0011 @@ -0,0 +1,2 @@ +Here comes a commit log message, and +its second line is here. diff --git a/t/t5100/msg0012 b/t/t5100/msg0012 new file mode 100644 index 0000000000..1dc2bf7f7f --- /dev/null +++ b/t/t5100/msg0012 @@ -0,0 +1,7 @@ +textlive-* иÑправлены на texlive-* +docutils заменён на python-docutils + +ДейÑтвительно, оказалоÑÑŒ, что rest2web вытÑгивает за Ñобой +python-docutils. Ð’ то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº Ñам rest2web не нужен. + +Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru> diff --git a/t/t5100/msg0013 b/t/t5100/msg0013 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/t/t5100/msg0013 diff --git a/t/t5100/msg0014 b/t/t5100/msg0014 new file mode 100644 index 0000000000..62e5cd2ecd --- /dev/null +++ b/t/t5100/msg0014 @@ -0,0 +1,18 @@ +In real life, we will see a discussion that inspired this patch +discussing related and unrelated things around >8 scissors mark +in this part of the message. + +Subject: [PATCH] BLAH TWO + +And then we will see the scissors. + + This line is not a scissors mark -- >8 -- but talks about it. + - - >8 - - please remove everything above this line - - >8 - - + +Subject: [PATCH] Teach mailinfo to ignore everything before -- >8 -- mark +From: Junio C Hamano <gitster@pobox.com> + +This teaches mailinfo the scissors -- >8 -- mark; the command ignores +everything before it in the message body. + +Signed-off-by: Junio C Hamano <gitster@pobox.com> diff --git a/t/t5100/msg0014--scissors b/t/t5100/msg0014--scissors new file mode 100644 index 0000000000..259c6a46d2 --- /dev/null +++ b/t/t5100/msg0014--scissors @@ -0,0 +1,4 @@ +This teaches mailinfo the scissors -- >8 -- mark; the command ignores +everything before it in the message body. + +Signed-off-by: Junio C Hamano <gitster@pobox.com> diff --git a/t/t5100/msg0015 b/t/t5100/msg0015 new file mode 100644 index 0000000000..4abb3d5c6c --- /dev/null +++ b/t/t5100/msg0015 @@ -0,0 +1,2 @@ + - a list + - of stuff diff --git a/t/t5100/msg0015--no-inbody-headers b/t/t5100/msg0015--no-inbody-headers new file mode 100644 index 0000000000..be5115b1c1 --- /dev/null +++ b/t/t5100/msg0015--no-inbody-headers @@ -0,0 +1,3 @@ +From: bogosity + - a list + - of stuff diff --git a/t/t5100/msg0016 b/t/t5100/msg0016 new file mode 100644 index 0000000000..0d9adada96 --- /dev/null +++ b/t/t5100/msg0016 @@ -0,0 +1,2 @@ +and some content + diff --git a/t/t5100/msg0016--no-inbody-headers b/t/t5100/msg0016--no-inbody-headers new file mode 100644 index 0000000000..1063f51178 --- /dev/null +++ b/t/t5100/msg0016--no-inbody-headers @@ -0,0 +1,4 @@ +Date: bogus + +and some content + diff --git a/t/t5100/nul-b64.expect b/t/t5100/nul-b64.expect Binary files differnew file mode 100644 index 0000000000..d7d680f631 --- /dev/null +++ b/t/t5100/nul-b64.expect diff --git a/t/t5100/nul-b64.in b/t/t5100/nul-b64.in new file mode 100644 index 0000000000..16540d961f --- /dev/null +++ b/t/t5100/nul-b64.in @@ -0,0 +1,37 @@ +From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001 +From: Junio C Hamano <gitster@pobox.com> +Date: Sun, 25 May 2008 00:38:18 -0700 +Subject: [PATCH] second +Content-Transfer-Encoding: base64 + +LS0tCiBmaWxlIHwgIEJpbiAxMzU3IC0+IDEzNTcgYnl0ZXMKIDEgZmlsZXMgY2hhbmdlZCwg +MCBpbnNlcnRpb25zKCspLCAwIGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2ZpbGUgYi9m +aWxlCmluZGV4IDc3MzYxZDguLjllMDJiZTYgMTAwNjQ0Ci0tLSBhL2ZpbGUKKysrIGIvZmls +ZQpAQCAtMSwxMiArMSwxMiBAQAogTG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNl +Y3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIFN1c3BlbmRpc3NlCiBzaXQgYW1ldCB0dXJwaXMg +ZWdldCBlc3QgY3Vyc3VzIGxhb3JlZXQuIEFsaXF1YW0gbWF1cmlzLiBQcmFlc2VudAotdm9s +dXRwYXQuIFByb2luIGluIHB1cnVzLiBOdWxsYSB1cm5hIHNhcGllbiwgZGFwaWJ1cyBzaXQg +YW1ldCwKK3ZvbHV0cGF0LiBQcm9pbiBpbiBwdXJ1cy4gTnVsbGEgdXJuYSBzYXBpZW4sIGRh +cGkAdXMgc2l0IGFtZXQsCiBoZW5kcmVyaXQgbmVjLCB0ZW1wdXMgZXUsIG1pLiBVdCBwb3J0 +YSwgbGVvIGlkIHRpbmNpZHVudCB1bGxhbWNvcnBlciwKLXZlbGl0IGZlbGlzIHRyaXN0aXF1 +ZSBhbnRlLCBhdCBsb2JvcnRpcyBkaWFtIHBlZGUgdXQgZHVpLiBQcm9pbiBhYwordmVsaXQg +ZmVsaXMgdHJpc3RpcXVlIGFudGUsIGF0IGxvAG9ydGlzIGRpYW0gcGVkZSB1dCBkdWkuIFBy +b2luIGFjCiBsZWN0dXMuIERvbmVjIGF0IG1hc3NhIGFjIGlwc3VtIGhlbmRyZXJpdCBzb2xs +aWNpdHVkaW4uIE5hbSBkaWN0dW0KIG5pc2kgc2VkIG1pLiBEdWlzIHNlZCBhbnRlLiBVdCB2 +aXRhZSBlc3QgdXQgZHVpIHVsdHJpY2llcyBkaWduaXNzaW0uCiAKLUluIHZlbCBvZGlvIGVn +ZXQgbmlzbCBjb252YWxsaXMgdm9sdXRwYXQuIE1vcmJpIHZpdGFlIG5pYmguIE51bGxhbQor +SW4gdmVsIG9kaW8gZWdldCBuaXNsIGNvbnZhbGxpcyB2b2x1dHBhdC4gTW9yAGkgdml0YWUg +bmkAaC4gTnVsbGFtCiBhY2N1bXNhbiwgZG9sb3IgcXVpcyBhbGlxdWFtIHNjZWxlcmlzcXVl +LCBlbGl0IGVuaW0gY29uZGltZW50dW0KIG1hdXJpcywgbm9uIHRyaXN0aXF1ZSBtYXVyaXMg +dHVycGlzIGV0IG1hdXJpcy4gVXQgbm9uIG5pc2wuIE5hbSBkaWFtCiBtaSwgc2VtcGVyIHBv +c3VlcmUsIGVsZWlmZW5kIHV0LCBhdWN0b3IgdmVsLCBlcmF0LiBTZWQgcG9zdWVyZQpAQCAt +MTYsNyArMTYsNyBAQCBzZWQgZXN0LiBFdGlhbSBkaWFtIGZlbGlzLCBmZXJtZW50dW0gZWdl +dCwgYWRpcGlzY2luZyBhdCwgcG9zdWVyZSBpbiwKIGR1aS4gRXRpYW0gbHVjdHVzLgogCiBO +dWxsYSBpZCBhdWd1ZS4gTmFtIGlhY3VsaXMgYWNjdW1zYW4gbmlzaS4gU3VzcGVuZGlzc2Ug +cG90ZW50aS4gTnVuYwotdmFyaXVzIGF1Z3VlIG5lYyBvcmNpLiBVdCBjb25kaW1lbnR1bSBk +b2xvciBzYWdpdHRpcyBuaWJoLiBTdXNwZW5kaXNzZQordmFyaXVzIGF1Z3VlIG5lYyBvcmNp +LiBVdCBjb25kaW1lbnR1bSBkb2xvciBzYWdpdHRpcyBuaQBoLiBTdXNwZW5kaXNzZQogdGVt +cG9yIGxlY3R1cyBzZWQgbWFnbmEuIFN1c3BlbmRpc3NlIHBvdGVudGkuIE51bGxhbSB0ZW1w +b3IgaXBzdW0uIFNlZAogbW9sZXN0aWUgdGVsbHVzLiBQaGFzZWxsdXMgbGlndWxhLiBJbiB2 +ZWhpY3VsYSB1bHRyaWNlcwogbmlzaS4gU3VzcGVuZGlzc2UgZmVsaXMgYXVndWUsIHBlbGxl +bnRlc3F1ZSBhdCwgZGljdHVtIHZpdmVycmEsCi0tIAoxLjUuNS4xLjU0MC5nNTc3ODAKCg== diff --git a/t/t5100/nul-plain b/t/t5100/nul-plain Binary files differnew file mode 100644 index 0000000000..3d40691787 --- /dev/null +++ b/t/t5100/nul-plain diff --git a/t/t5100/patch0007 b/t/t5100/patch0007 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/t/t5100/patch0007 diff --git a/t/t5100/patch0008 b/t/t5100/patch0008 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/t/t5100/patch0008 diff --git a/t/t5100/patch0009 b/t/t5100/patch0009 new file mode 100644 index 0000000000..65615c34af --- /dev/null +++ b/t/t5100/patch0009 @@ -0,0 +1,13 @@ +diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt +index b426a14..97756ec 100644 +--- a/Documentation/diff-format.txt ++++ b/Documentation/diff-format.txt +@@ -81,7 +81,7 @@ The "diff" formatting options can be customized via the + environment variable 'GIT_DIFF_OPTS'. For example, if you + prefer context diff: + +- GIT_DIFF_OPTS=-c git-diff-index -p $(cat .git/HEAD) ++ GIT_DIFF_OPTS=-c git-diff-index -p HEAD + + + 2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the diff --git a/t/t5100/patch0010 b/t/t5100/patch0010 new file mode 100644 index 0000000000..f055481d56 --- /dev/null +++ b/t/t5100/patch0010 @@ -0,0 +1,20 @@ +--- + builtin-mailinfo.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index 962aa34..2d1520f 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over + return 1; + if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) { + for (i = 0; header[i]; i++) { +- if (!memcmp("Subject: ", header[i], 9)) { ++ if (!memcmp("Subject", header[i], 7)) { + if (! handle_header(line, hdr_data[i], 0)) { + return 1; + } +-- +1.5.6.2.455.g1efb2 + diff --git a/t/t5100/patch0011 b/t/t5100/patch0011 new file mode 100644 index 0000000000..8841d3c139 --- /dev/null +++ b/t/t5100/patch0011 @@ -0,0 +1,22 @@ +--- + builtin-mailinfo.c | 4 ++-- + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index 3e5fe51..aabfe5c 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -758,8 +758,8 @@ static void handle_body(void) + /* process any boundary lines */ + if (*content_top && is_multipart_boundary(&line)) { + /* flush any leftover */ +- if (line.len) +- handle_filter(&line); ++ if (prev.len) ++ handle_filter(&prev); + + if (!handle_boundary()) + goto handle_body_out; +-- +1.6.0.rc2 + + diff --git a/t/t5100/patch0012 b/t/t5100/patch0012 new file mode 100644 index 0000000000..36a0b68161 --- /dev/null +++ b/t/t5100/patch0012 @@ -0,0 +1,30 @@ +--- + howto/build_navy.txt | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/howto/build_navy.txt b/howto/build_navy.txt +index 3fd3afb..0ee807e 100644 +--- a/howto/build_navy.txt ++++ b/howto/build_navy.txt +@@ -119,8 +119,8 @@ + - libxv-dev + - libusplash-dev + - latex-make +- - textlive-lang-cyrillic +- - textlive-latex-extra ++ - texlive-lang-cyrillic ++ - texlive-latex-extra + - dia + - python-pyrex + - libtool +@@ -128,7 +128,7 @@ + - sox + - cython + - imagemagick +- - docutils ++ - python-docutils + + #. на машине dinar: добавить Ñвой открытый ssh-ключ в authorized_keys2 Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ddev + #. на Ñвоей машине: отредактировать /etc/sudoers (команда ``visudo``) примерно Ñледующим образом:: +-- +1.5.6.5 diff --git a/t/t5100/patch0013 b/t/t5100/patch0013 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/t/t5100/patch0013 diff --git a/t/t5100/patch0014 b/t/t5100/patch0014 new file mode 100644 index 0000000000..124efd234f --- /dev/null +++ b/t/t5100/patch0014 @@ -0,0 +1,64 @@ +--- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + 1 files changed, 36 insertions(+), 1 deletions(-) + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index b0b5d8f..461c47e 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line) + return 0; + } + ++static int scissors(const struct strbuf *line) ++{ ++ size_t i, len = line->len; ++ int scissors_dashes_seen = 0; ++ const char *buf = line->buf; ++ ++ for (i = 0; i < len; i++) { ++ if (isspace(buf[i])) ++ continue; ++ if (buf[i] == '-') { ++ scissors_dashes_seen |= 02; ++ continue; ++ } ++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) { ++ scissors_dashes_seen |= 01; ++ i++; ++ continue; ++ } ++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) { ++ i += 7; ++ continue; ++ } ++ /* everything else --- not scissors */ ++ break; ++ } ++ return scissors_dashes_seen == 03; ++} ++ + static int handle_commit_msg(struct strbuf *line) + { + static int still_looking = 1; +@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line) + strbuf_ltrim(line); + if (!line->len) + return 0; +- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0) ++ still_looking = check_header(line, s_hdr_data, 0); ++ if (still_looking) + return 0; + } + ++ if (scissors(line)) { ++ fseek(cmitmsg, 0L, SEEK_SET); ++ still_looking = 1; ++ return 0; ++ } ++ + /* normalize the log message to UTF-8. */ + if (metainfo_charset) + convert_to_utf8(line, charset.buf); +-- +1.6.4.1 diff --git a/t/t5100/patch0014--scissors b/t/t5100/patch0014--scissors new file mode 100644 index 0000000000..124efd234f --- /dev/null +++ b/t/t5100/patch0014--scissors @@ -0,0 +1,64 @@ +--- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + 1 files changed, 36 insertions(+), 1 deletions(-) + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index b0b5d8f..461c47e 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line) + return 0; + } + ++static int scissors(const struct strbuf *line) ++{ ++ size_t i, len = line->len; ++ int scissors_dashes_seen = 0; ++ const char *buf = line->buf; ++ ++ for (i = 0; i < len; i++) { ++ if (isspace(buf[i])) ++ continue; ++ if (buf[i] == '-') { ++ scissors_dashes_seen |= 02; ++ continue; ++ } ++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) { ++ scissors_dashes_seen |= 01; ++ i++; ++ continue; ++ } ++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) { ++ i += 7; ++ continue; ++ } ++ /* everything else --- not scissors */ ++ break; ++ } ++ return scissors_dashes_seen == 03; ++} ++ + static int handle_commit_msg(struct strbuf *line) + { + static int still_looking = 1; +@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line) + strbuf_ltrim(line); + if (!line->len) + return 0; +- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0) ++ still_looking = check_header(line, s_hdr_data, 0); ++ if (still_looking) + return 0; + } + ++ if (scissors(line)) { ++ fseek(cmitmsg, 0L, SEEK_SET); ++ still_looking = 1; ++ return 0; ++ } ++ + /* normalize the log message to UTF-8. */ + if (metainfo_charset) + convert_to_utf8(line, charset.buf); +-- +1.6.4.1 diff --git a/t/t5100/patch0015 b/t/t5100/patch0015 new file mode 100644 index 0000000000..ad64848873 --- /dev/null +++ b/t/t5100/patch0015 @@ -0,0 +1,8 @@ +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + diff --git a/t/t5100/patch0015--no-inbody-headers b/t/t5100/patch0015--no-inbody-headers new file mode 100644 index 0000000000..ad64848873 --- /dev/null +++ b/t/t5100/patch0015--no-inbody-headers @@ -0,0 +1,8 @@ +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + diff --git a/t/t5100/patch0016 b/t/t5100/patch0016 new file mode 100644 index 0000000000..ad64848873 --- /dev/null +++ b/t/t5100/patch0016 @@ -0,0 +1,8 @@ +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + diff --git a/t/t5100/patch0016--no-inbody-headers b/t/t5100/patch0016--no-inbody-headers new file mode 100644 index 0000000000..ad64848873 --- /dev/null +++ b/t/t5100/patch0016--no-inbody-headers @@ -0,0 +1,8 @@ +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + diff --git a/t/t5100/rfc2047-info-0001 b/t/t5100/rfc2047-info-0001 new file mode 100644 index 0000000000..0a383b07e3 --- /dev/null +++ b/t/t5100/rfc2047-info-0001 @@ -0,0 +1,4 @@ +Author: Keith Moore +Email: moore@cs.utk.edu +Subject: If you can read this you understand the example. + diff --git a/t/t5100/rfc2047-info-0002 b/t/t5100/rfc2047-info-0002 new file mode 100644 index 0000000000..881be75d6f --- /dev/null +++ b/t/t5100/rfc2047-info-0002 @@ -0,0 +1,4 @@ +Author: Olle Järnefors +Email: ojarnef@admin.kth.se +Subject: Time for ISO 10646? + diff --git a/t/t5100/rfc2047-info-0003 b/t/t5100/rfc2047-info-0003 new file mode 100644 index 0000000000..d0f789177c --- /dev/null +++ b/t/t5100/rfc2047-info-0003 @@ -0,0 +1,4 @@ +Author: Patrik Fältström +Email: paf@nada.kth.se +Subject: RFC-HDR care and feeding + diff --git a/t/t5100/rfc2047-info-0004 b/t/t5100/rfc2047-info-0004 new file mode 100644 index 0000000000..f67a90a974 --- /dev/null +++ b/t/t5100/rfc2047-info-0004 @@ -0,0 +1,4 @@ +Author: Nathaniel Borenstein (×ולש ןב ×™×œ×˜×¤× ) +Email: nsb@thumper.bellcore.com +Subject: Test of new header generator + diff --git a/t/t5100/rfc2047-info-0005 b/t/t5100/rfc2047-info-0005 new file mode 100644 index 0000000000..c27be3bf24 --- /dev/null +++ b/t/t5100/rfc2047-info-0005 @@ -0,0 +1,2 @@ +Subject: (a) + diff --git a/t/t5100/rfc2047-info-0006 b/t/t5100/rfc2047-info-0006 new file mode 100644 index 0000000000..9dad474456 --- /dev/null +++ b/t/t5100/rfc2047-info-0006 @@ -0,0 +1,2 @@ +Subject: (a b) + diff --git a/t/t5100/rfc2047-info-0007 b/t/t5100/rfc2047-info-0007 new file mode 100644 index 0000000000..294f195a57 --- /dev/null +++ b/t/t5100/rfc2047-info-0007 @@ -0,0 +1,2 @@ +Subject: (ab) + diff --git a/t/t5100/rfc2047-info-0008 b/t/t5100/rfc2047-info-0008 new file mode 100644 index 0000000000..294f195a57 --- /dev/null +++ b/t/t5100/rfc2047-info-0008 @@ -0,0 +1,2 @@ +Subject: (ab) + diff --git a/t/t5100/rfc2047-info-0009 b/t/t5100/rfc2047-info-0009 new file mode 100644 index 0000000000..294f195a57 --- /dev/null +++ b/t/t5100/rfc2047-info-0009 @@ -0,0 +1,2 @@ +Subject: (ab) + diff --git a/t/t5100/rfc2047-info-0010 b/t/t5100/rfc2047-info-0010 new file mode 100644 index 0000000000..9dad474456 --- /dev/null +++ b/t/t5100/rfc2047-info-0010 @@ -0,0 +1,2 @@ +Subject: (a b) + diff --git a/t/t5100/rfc2047-info-0011 b/t/t5100/rfc2047-info-0011 new file mode 100644 index 0000000000..9dad474456 --- /dev/null +++ b/t/t5100/rfc2047-info-0011 @@ -0,0 +1,2 @@ +Subject: (a b) + diff --git a/t/t5100/rfc2047-samples.mbox b/t/t5100/rfc2047-samples.mbox new file mode 100644 index 0000000000..1fc224810d --- /dev/null +++ b/t/t5100/rfc2047-samples.mbox @@ -0,0 +1,48 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu> +To: =?ISO8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk> +CC: =?ISO8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be> +Subject: =?ISO8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= + =?ISO8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?= + +From nobody Mon Sep 17 00:00:00 2001 +From: =?ISO8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se> +To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se +Subject: Time for ISO 10646? + +From nobody Mon Sep 17 00:00:00 2001 +To: Dave Crocker <dcrocker@mordor.stanford.edu> +Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se +From: =?ISO8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se> +Subject: Re: RFC-HDR care and feeding + +From nobody Mon Sep 17 00:00:00 2001 +From: Nathaniel Borenstein <nsb@thumper.bellcore.com> + (=?ISO8859-8?b?7eXs+SDv4SDp7Oj08A==?=) +To: Greg Vaudreuil <gvaudre@NRI.Reston.VA.US>, Ned Freed + <ned@innosoft.com>, Keith Moore <moore@cs.utk.edu> +Subject: Test of new header generator +MIME-Version: 1.0 +Content-type: text/plain; charset=ISO8859-1 + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?=) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?= b) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?= + =?ISO8859-1?Q?b?=) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a_b?=) + +From nobody Mon Sep 17 00:00:00 2001 +Subject: (=?ISO8859-1?Q?a?= =?ISO8859-2?Q?_b?=) diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox index 86bfc27147..de1031241d 100644 --- a/t/t5100/sample.mbox +++ b/t/t5100/sample.mbox @@ -1,5 +1,11 @@ + + + From nobody Mon Sep 17 00:00:00 2001 -From: A U Thor <a.u.thor@example.com> +From: A (zzz) + U + Thor + <a.u.thor@example.com> (Comment) Date: Fri, 9 Jun 2006 00:44:16 -0700 Subject: [PATCH] a commit. @@ -93,7 +99,7 @@ index 9123cdc..918dcf8 100644 From nobody Sat Aug 27 23:07:49 2005 Path: news.gmane.org!not-for-mail Message-ID: <20050721.091036.01119516.yoshfuji@linux-ipv6.org> -From: YOSHIFUJI Hideaki / =?iso-2022-jp?B?GyRCNUhGIzFRTEAbKEI=?= +From: YOSHIFUJI Hideaki / =?ISO-2022-JP?B?GyRCNUhGIzFRTEAbKEI=?= <yoshfuji@linux-ipv6.org> Newsgroups: gmane.comp.version-control.git Subject: [PATCH 1/2] GIT: Try all addresses for given remote name @@ -212,7 +218,7 @@ GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA From nobody Sat Aug 27 23:07:49 2005 Path: news.gmane.org!not-for-mail Message-ID: <u5tacjjdpxq.fsf@lysator.liu.se> -From: =?iso-8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se> +From: =?ISO8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se> Newsgroups: gmane.comp.version-control.git Subject: [PATCH] Fixed two bugs in git-cvsimport-script. Date: Mon, 15 Aug 2005 20:18:25 +0200 @@ -220,7 +226,7 @@ Lines: 83 Approved: news@gmane.org NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 -Content-Type: text/plain; charset=iso-8859-1 +Content-Type: text/plain; charset=ISO8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE X-Trace: sea.gmane.org 1124130247 31839 80.91.229.2 (15 Aug 2005 18:24:07 GMT) X-Complaints-To: usenet@sea.gmane.org @@ -386,3 +392,294 @@ index 9123cdc..918dcf8 100644 -- 1.4.0.g6f2b +From nobody Mon Sep 17 00:00:00 2001 +From: A U Thor <a.u.thor@example.com> +Date: Fri, 9 Jun 2006 00:44:16 -0700 +Subject: [PATCH] another patch + +Here is an empty patch from A U Thor. + +From nobody Mon Sep 17 00:00:00 2001 +From: Junio C Hamano <junio@kernel.org> +Date: Fri, 9 Jun 2006 00:44:16 -0700 +Subject: re: [PATCH] another patch + +From: A U Thor <a.u.thor@example.com> +Subject: [PATCH] another patch +>Here is an empty patch from A U Thor. + +Hey you forgot the patch! + +From nobody Mon Sep 17 00:00:00 2001 +From: A U Thor <a.u.thor@example.com> +Date: Mon, 17 Sep 2001 00:00:00 +0900 +Mime-Version: 1.0 +Content-Type: Text/Plain; charset=us-ascii +Content-Transfer-Encoding: Quoted-Printable + +=0A=0AFrom: F U Bar <f.u.bar@example.com> +Subject: [PATCH] updates=0A=0AThis is to fix diff-format documentation. + +diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt +index b426a14..97756ec 100644 +--- a/Documentation/diff-format.txt ++++ b/Documentation/diff-format.txt +@@ -81,7 +81,7 @@ The "diff" formatting options can be customized via the + environment variable 'GIT_DIFF_OPTS'. For example, if you + prefer context diff: +=20 +- GIT_DIFF_OPTS=3D-c git-diff-index -p $(cat .git/HEAD) ++ GIT_DIFF_OPTS=3D-c git-diff-index -p HEAD +=20 +=20 + 2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the +From b9704a518e21158433baa2cc2d591fea687967f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lukas=20Sandstr=C3=B6m?= <lukass@etek.chalmers.se> +Date: Thu, 10 Jul 2008 23:41:33 +0200 +Subject: Re: discussion that lead to this patch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[PATCH] git-mailinfo: Fix getting the subject from the body + +"Subject: " isn't in the static array "header", and thus +memcmp("Subject: ", header[i], 7) will never match. + +Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +--- + builtin-mailinfo.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index 962aa34..2d1520f 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over + return 1; + if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) { + for (i = 0; header[i]; i++) { +- if (!memcmp("Subject: ", header[i], 9)) { ++ if (!memcmp("Subject", header[i], 7)) { + if (! handle_header(line, hdr_data[i], 0)) { + return 1; + } +-- +1.5.6.2.455.g1efb2 + +From nobody Fri Aug 8 22:24:03 2008 +Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST) +From: A U Thor <a.u.thor@example.com> +Subject: [PATCH 3/3 v2] Xyzzy +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="=-=-=" + +--=-=-= +Content-Type: text/plain; charset=ISO8859-15 +Content-Transfer-Encoding: quoted-printable + +Here comes a commit log message, and +its second line is here. +--- + builtin-mailinfo.c | 4 ++-- + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index 3e5fe51..aabfe5c 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -758,8 +758,8 @@ static void handle_body(void) + /* process any boundary lines */ + if (*content_top && is_multipart_boundary(&line)) { + /* flush any leftover */ +- if (line.len) +- handle_filter(&line); ++ if (prev.len) ++ handle_filter(&prev); +=20 + if (!handle_boundary()) + goto handle_body_out; +--=20 +1.6.0.rc2 + +--=-=-=-- + +From bda@mnsspb.ru Wed Nov 12 17:54:41 2008 +From: Dmitriy Blinov <bda@mnsspb.ru> +To: navy-patches@dinar.mns.mnsspb.ru +Date: Wed, 12 Nov 2008 17:54:41 +0300 +Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru> +X-Mailer: git-send-email 1.5.6.5 +MIME-Version: 1.0 +Content-Type: text/plain; + charset=utf-8 +Content-Transfer-Encoding: 8bit +Subject: [Navy-patches] [PATCH] + =?utf-8?b?0JjQt9C80LXQvdGR0L0g0YHQv9C40YHQvtC6INC/0LA=?= + =?utf-8?b?0LrQtdGC0L7QsiDQvdC10L7QsdGF0L7QtNC40LzRi9GFINC00LvRjyA=?= + =?utf-8?b?0YHQsdC+0YDQutC4?= + +textlive-* иÑправлены на texlive-* +docutils заменён на python-docutils + +ДейÑтвительно, оказалоÑÑŒ, что rest2web вытÑгивает за Ñобой +python-docutils. Ð’ то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº Ñам rest2web не нужен. + +Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru> +--- + howto/build_navy.txt | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/howto/build_navy.txt b/howto/build_navy.txt +index 3fd3afb..0ee807e 100644 +--- a/howto/build_navy.txt ++++ b/howto/build_navy.txt +@@ -119,8 +119,8 @@ + - libxv-dev + - libusplash-dev + - latex-make +- - textlive-lang-cyrillic +- - textlive-latex-extra ++ - texlive-lang-cyrillic ++ - texlive-latex-extra + - dia + - python-pyrex + - libtool +@@ -128,7 +128,7 @@ + - sox + - cython + - imagemagick +- - docutils ++ - python-docutils + + #. на машине dinar: добавить Ñвой открытый ssh-ключ в authorized_keys2 Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ddev + #. на Ñвоей машине: отредактировать /etc/sudoers (команда ``visudo``) примерно Ñледующим образом:: +-- +1.5.6.5 +From nobody Mon Sep 17 00:00:00 2001 +From: <a.u.thor@example.com> (A U Thor) +Date: Fri, 9 Jun 2006 00:44:16 -0700 +Subject: [PATCH] a patch + +From nobody Mon Sep 17 00:00:00 2001 +From: Junio Hamano <junkio@cox.net> +Date: Thu, 20 Aug 2009 17:18:22 -0700 +Subject: Why doesn't git-am does not like >8 scissors mark? + +Subject: [PATCH] BLAH ONE + +In real life, we will see a discussion that inspired this patch +discussing related and unrelated things around >8 scissors mark +in this part of the message. + +Subject: [PATCH] BLAH TWO + +And then we will see the scissors. + + This line is not a scissors mark -- >8 -- but talks about it. + - - >8 - - please remove everything above this line - - >8 - - + +Subject: [PATCH] Teach mailinfo to ignore everything before -- >8 -- mark +From: Junio C Hamano <gitster@pobox.com> + +This teaches mailinfo the scissors -- >8 -- mark; the command ignores +everything before it in the message body. + +Signed-off-by: Junio C Hamano <gitster@pobox.com> +--- + builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++- + 1 files changed, 36 insertions(+), 1 deletions(-) + +diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c +index b0b5d8f..461c47e 100644 +--- a/builtin-mailinfo.c ++++ b/builtin-mailinfo.c +@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line) + return 0; + } + ++static int scissors(const struct strbuf *line) ++{ ++ size_t i, len = line->len; ++ int scissors_dashes_seen = 0; ++ const char *buf = line->buf; ++ ++ for (i = 0; i < len; i++) { ++ if (isspace(buf[i])) ++ continue; ++ if (buf[i] == '-') { ++ scissors_dashes_seen |= 02; ++ continue; ++ } ++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) { ++ scissors_dashes_seen |= 01; ++ i++; ++ continue; ++ } ++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) { ++ i += 7; ++ continue; ++ } ++ /* everything else --- not scissors */ ++ break; ++ } ++ return scissors_dashes_seen == 03; ++} ++ + static int handle_commit_msg(struct strbuf *line) + { + static int still_looking = 1; +@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line) + strbuf_ltrim(line); + if (!line->len) + return 0; +- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0) ++ still_looking = check_header(line, s_hdr_data, 0); ++ if (still_looking) + return 0; + } + ++ if (scissors(line)) { ++ fseek(cmitmsg, 0L, SEEK_SET); ++ still_looking = 1; ++ return 0; ++ } ++ + /* normalize the log message to UTF-8. */ + if (metainfo_charset) + convert_to_utf8(line, charset.buf); +-- +1.6.4.1 +From nobody Mon Sep 17 00:00:00 2001 +From: A U Thor <a.u.thor@example.com> +Subject: check bogus body header (from) +Date: Fri, 9 Jun 2006 00:44:16 -0700 + +From: bogosity + - a list + - of stuff +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + +From nobody Mon Sep 17 00:00:00 2001 +From: A U Thor <a.u.thor@example.com> +Subject: check bogus body header (date) +Date: Fri, 9 Jun 2006 00:44:16 -0700 + +Date: bogus + +and some content + +--- +diff --git a/foo b/foo +index e69de29..d95f3ad 100644 +--- a/foo ++++ b/foo +@@ -0,0 +1 @@ ++content + 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 f511547455..bbb9c1251d 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git-pack-object +test_description='git pack-object ' . ./test-lib.sh @@ -13,29 +13,30 @@ TRASH=`pwd` test_expect_success \ 'setup' \ 'rm -f .git/index* - for i in a b c - do - dd if=/dev/zero bs=4k count=1 | tr "\\0" $i >$i && - git-update-index --add $i || return 1 - done && - cat c >d && echo foo >>d && git-update-index --add d && - tree=`git-write-tree` && - commit=`git-commit-tree $tree </dev/null` && { + perl -e "print \"a\" x 4096;" > a && + perl -e "print \"b\" x 4096;" > b && + perl -e "print \"c\" x 4096;" > c && + test-genrandom "seed a" 2097152 > a_big && + test-genrandom "seed b" 2097152 > b_big && + git update-index --add a a_big b b_big c && + cat c >d && echo foo >>d && git update-index --add d && + tree=`git write-tree` && + commit=`git commit-tree $tree </dev/null` && { echo $tree && echo $commit && - git-ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" + git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" } >obj-list && { - git-diff-tree --root -p $commit && + git diff-tree --root -p $commit && while read object do - t=`git-cat-file -t $object` && - git-cat-file $t $object || return 1 + t=`git cat-file -t $object` && + git cat-file $t $object || return 1 done <obj-list } >expect' test_expect_success \ 'pack without delta' \ - 'packname_1=$(git-pack-objects --window=0 test-1 <obj-list)' + 'packname_1=$(git pack-objects --window=0 test-1 <obj-list)' rm -fr .git2 mkdir .git2 @@ -44,9 +45,9 @@ test_expect_success \ 'unpack without delta' \ "GIT_OBJECT_DIRECTORY=.git2/objects && export GIT_OBJECT_DIRECTORY && - git-init && - git-unpack-objects -n <test-1-${packname_1}.pack && - git-unpack-objects <test-1-${packname_1}.pack" + git init && + git unpack-objects -n <test-1-${packname_1}.pack && + git unpack-objects <test-1-${packname_1}.pack" unset GIT_OBJECT_DIRECTORY cd "$TRASH/.git2" @@ -64,25 +65,25 @@ test_expect_success \ cd "$TRASH" test_expect_success \ - 'pack with delta' \ + 'pack with REF_DELTA' \ 'pwd && - packname_2=$(git-pack-objects test-2 <obj-list)' + packname_2=$(git pack-objects test-2 <obj-list)' rm -fr .git2 mkdir .git2 test_expect_success \ - 'unpack with delta' \ + 'unpack with REF_DELTA' \ 'GIT_OBJECT_DIRECTORY=.git2/objects && export GIT_OBJECT_DIRECTORY && - git-init && - git-unpack-objects -n <test-2-${packname_2}.pack && - git-unpack-objects <test-2-${packname_2}.pack' + git init && + git unpack-objects -n <test-2-${packname_2}.pack && + git unpack-objects <test-2-${packname_2}.pack' unset GIT_OBJECT_DIRECTORY cd "$TRASH/.git2" test_expect_success \ - 'check unpack with delta' \ + 'check unpack with REF_DELTA' \ '(cd ../.git && find objects -type f -print) | while read path do @@ -93,6 +94,43 @@ test_expect_success \ done' cd "$TRASH" +test_expect_success \ + 'pack with OFS_DELTA' \ + 'pwd && + packname_3=$(git pack-objects --delta-base-offset test-3 <obj-list)' + +rm -fr .git2 +mkdir .git2 + +test_expect_success \ + 'unpack with OFS_DELTA' \ + 'GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + git init && + git unpack-objects -n <test-3-${packname_3}.pack && + git unpack-objects <test-3-${packname_3}.pack' + +unset GIT_OBJECT_DIRECTORY +cd "$TRASH/.git2" +test_expect_success \ + 'check unpack with OFS_DELTA' \ + '(cd ../.git && find objects -type f -print) | + while read path + do + cmp $path ../.git/$path || { + echo $path differs. + return 1 + } + done' +cd "$TRASH" + +test_expect_success 'compare delta flavors' ' + perl -e '\'' + defined($_ = -s $_) or die for @ARGV; + exit 1 if $ARGV[0] <= $ARGV[1]; + '\'' test-2-$packname_2.pack test-3-$packname_3.pack +' + rm -fr .git2 mkdir .git2 @@ -100,100 +138,280 @@ test_expect_success \ 'use packed objects' \ 'GIT_OBJECT_DIRECTORY=.git2/objects && export GIT_OBJECT_DIRECTORY && - git-init && + git init && cp test-1-${packname_1}.pack test-1-${packname_1}.idx .git2/objects/pack && { - git-diff-tree --root -p $commit && + git diff-tree --root -p $commit && while read object do - t=`git-cat-file -t $object` && - git-cat-file $t $object || return 1 + t=`git cat-file -t $object` && + git cat-file $t $object || return 1 done <obj-list } >current && - diff expect current' - + test_cmp expect current' test_expect_success \ - 'use packed deltified objects' \ + 'use packed deltified (REF_DELTA) objects' \ 'GIT_OBJECT_DIRECTORY=.git2/objects && export GIT_OBJECT_DIRECTORY && - rm -f .git2/objects/pack/test-?.idx && + rm -f .git2/objects/pack/test-* && cp test-2-${packname_2}.pack test-2-${packname_2}.idx .git2/objects/pack && { - git-diff-tree --root -p $commit && + git diff-tree --root -p $commit && + while read object + do + t=`git cat-file -t $object` && + git cat-file $t $object || return 1 + done <obj-list + } >current && + test_cmp expect current' + +test_expect_success \ + 'use packed deltified (OFS_DELTA) objects' \ + 'GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + rm -f .git2/objects/pack/test-* && + cp test-3-${packname_3}.pack test-3-${packname_3}.idx .git2/objects/pack && { + git diff-tree --root -p $commit && while read object do - t=`git-cat-file -t $object` && - git-cat-file $t $object || return 1 + t=`git cat-file -t $object` && + git cat-file $t $object || return 1 done <obj-list } >current && - diff expect current' + test_cmp expect current' unset GIT_OBJECT_DIRECTORY +test_expect_success 'survive missing objects/pack directory' ' + ( + rm -fr missing-pack && + mkdir missing-pack && + cd missing-pack && + git init && + GOP=.git/objects/pack + rm -fr $GOP && + git index-pack --stdin --keep=test <../test-3-${packname_3}.pack && + test -f $GOP/pack-${packname_3}.pack && + test_cmp $GOP/pack-${packname_3}.pack ../test-3-${packname_3}.pack && + test -f $GOP/pack-${packname_3}.idx && + test_cmp $GOP/pack-${packname_3}.idx ../test-3-${packname_3}.idx && + test -f $GOP/pack-${packname_3}.keep + ) +' + test_expect_success \ 'verify pack' \ - 'git-verify-pack test-1-${packname_1}.idx test-2-${packname_2}.idx' + 'git verify-pack test-1-${packname_1}.idx \ + test-2-${packname_2}.idx \ + test-3-${packname_3}.idx' test_expect_success \ - 'corrupt a pack and see if verify catches' \ - 'cp test-1-${packname_1}.idx test-3.idx && - cp test-2-${packname_2}.pack test-3.pack && - if git-verify-pack test-3.idx + 'verify pack -v' \ + 'git verify-pack -v test-1-${packname_1}.idx \ + test-2-${packname_2}.idx \ + test-3-${packname_3}.idx' + +test_expect_success \ + 'verify-pack catches mismatched .idx and .pack files' \ + 'cat test-1-${packname_1}.idx >test-3.idx && + cat test-2-${packname_2}.pack >test-3.pack && + if git verify-pack test-3.idx then false else :; - fi && + fi' - : PACK_SIGNATURE && - cp test-1-${packname_1}.pack test-3.pack && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && - if git-verify-pack test-3.idx +test_expect_success \ + 'verify-pack catches a corrupted pack signature' \ + 'cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && + if git verify-pack test-3.idx then false else :; - fi && + fi' - : PACK_VERSION && - cp test-1-${packname_1}.pack test-3.pack && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && - if git-verify-pack test-3.idx +test_expect_success \ + 'verify-pack catches a corrupted pack version' \ + 'cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && + if git verify-pack test-3.idx then false else :; - fi && + fi' - : TYPE/SIZE byte of the first packed object data && - cp test-1-${packname_1}.pack test-3.pack && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && - if git-verify-pack test-3.idx +test_expect_success \ + 'verify-pack catches a corrupted type/size of the 1st packed object data' \ + 'cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && + if git verify-pack test-3.idx then false else :; - fi && + fi' - : sum of the index file itself && - l=`wc -c <test-3.idx` && +test_expect_success \ + 'verify-pack catches a corrupted sum of the index file itself' \ + 'l=`wc -c <test-3.idx` && l=`expr $l - 20` && - cp test-1-${packname_1}.pack test-3.pack && - dd if=/dev/zero of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && - if git-verify-pack test-3.pack + cat test-1-${packname_1}.pack >test-3.pack && + printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && + if git verify-pack test-3.pack then false else :; - fi && - - :' + fi' test_expect_success \ 'build pack index for an existing pack' \ - 'cp test-1-${packname_1}.pack test-3.pack && - git-index-pack -o tmp.idx test-3.pack && + 'cat test-1-${packname_1}.pack >test-3.pack && + git index-pack -o tmp.idx test-3.pack && cmp tmp.idx test-1-${packname_1}.idx && - git-index-pack test-3.pack && + git index-pack test-3.pack && cmp test-3.idx test-1-${packname_1}.idx && - cp test-2-${packname_2}.pack test-3.pack && - git-index-pack -o tmp.idx test-2-${packname_2}.pack && + cat test-2-${packname_2}.pack >test-3.pack && + git index-pack -o tmp.idx test-2-${packname_2}.pack && cmp tmp.idx test-2-${packname_2}.idx && - git-index-pack test-3.pack && + git index-pack test-3.pack && cmp test-3.idx test-2-${packname_2}.idx && + cat test-3-${packname_3}.pack >test-3.pack && + git index-pack -o tmp.idx test-3-${packname_3}.pack && + cmp tmp.idx test-3-${packname_3}.idx && + + git index-pack test-3.pack && + cmp test-3.idx test-3-${packname_3}.idx && + :' +test_expect_success 'unpacking with --strict' ' + + for j in a b c d e f g + do + for i in 0 1 2 3 4 5 6 7 8 9 + do + o=$(echo $j$i | git hash-object -w --stdin) && + echo "100644 $o 0 $j$i" + done + done >LIST && + rm -f .git/index && + git update-index --index-info <LIST && + LIST=$(git write-tree) && + rm -f .git/index && + head -n 10 LIST | git update-index --index-info && + LI=$(git write-tree) && + rm -f .git/index && + tail -n 10 LIST | git update-index --index-info && + ST=$(git write-tree) && + PACK5=$( git rev-list --objects "$LIST" "$LI" "$ST" | \ + git pack-objects test-5 ) && + PACK6=$( ( + echo "$LIST" + echo "$LI" + echo "$ST" + ) | git pack-objects test-6 ) && + test_create_repo test-5 && + ( + cd test-5 && + git unpack-objects --strict <../test-5-$PACK5.pack && + git ls-tree -r $LIST && + git ls-tree -r $LI && + git ls-tree -r $ST + ) && + test_create_repo test-6 && + ( + # tree-only into empty repo -- many unreachables + cd test-6 && + test_must_fail git unpack-objects --strict <../test-6-$PACK6.pack + ) && + ( + # already populated -- no unreachables + cd test-5 && + git unpack-objects --strict <../test-6-$PACK6.pack + ) +' + +test_expect_success 'index-pack with --strict' ' + + for j in a b c d e f g + do + for i in 0 1 2 3 4 5 6 7 8 9 + do + o=$(echo $j$i | git hash-object -w --stdin) && + echo "100644 $o 0 $j$i" + done + done >LIST && + rm -f .git/index && + git update-index --index-info <LIST && + LIST=$(git write-tree) && + rm -f .git/index && + head -n 10 LIST | git update-index --index-info && + LI=$(git write-tree) && + rm -f .git/index && + tail -n 10 LIST | git update-index --index-info && + ST=$(git write-tree) && + PACK5=$( git rev-list --objects "$LIST" "$LI" "$ST" | \ + git pack-objects test-5 ) && + PACK6=$( ( + echo "$LIST" + echo "$LI" + echo "$ST" + ) | git pack-objects test-6 ) && + test_create_repo test-7 && + ( + cd test-7 && + git index-pack --strict --stdin <../test-5-$PACK5.pack && + git ls-tree -r $LIST && + git ls-tree -r $LI && + git ls-tree -r $ST + ) && + test_create_repo test-8 && + ( + # tree-only into empty repo -- many unreachables + cd test-8 && + test_must_fail git index-pack --strict --stdin <../test-6-$PACK6.pack + ) && + ( + # already populated -- no unreachables + cd test-7 && + git index-pack --strict --stdin <../test-6-$PACK6.pack + ) +' + +test_expect_success 'honor pack.packSizeLimit' ' + git config pack.packSizeLimit 3m && + packname_10=$(git pack-objects test-10 <obj-list) && + test 2 = $(ls test-10-*.pack | wc -l) +' + +test_expect_success 'verify resulting packs' ' + git verify-pack test-10-*.pack +' + +test_expect_success 'tolerate packsizelimit smaller than biggest object' ' + git config pack.packSizeLimit 1 && + packname_11=$(git pack-objects test-11 <obj-list) && + test 5 = $(ls test-11-*.pack | wc -l) +' + +test_expect_success 'verify resulting packs' ' + git verify-pack test-11-*.pack +' + +# +# WARNING! +# +# The following test is destructive. Please keep the next +# two tests at the end of this file. +# + +test_expect_success \ + 'fake a SHA1 hash collision' \ + 'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 && + cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \ + .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67' + +test_expect_success \ + 'make sure index-pack detects the SHA1 collision' \ + 'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg && + grep "SHA1 COLLISION FOUND" msg' + test_done diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh index a6dbb04a86..0a24e61ff9 100755 --- a/t/t5301-sliding-window.sh +++ b/t/t5301-sliding-window.sh @@ -12,49 +12,49 @@ test_expect_success \ for i in a b c do echo $i >$i && - dd if=/dev/urandom bs=32k count=1 >>$i && - git-update-index --add $i || return 1 + test-genrandom "$i" 32768 >>$i && + git update-index --add $i || return 1 done && - echo d >d && cat c >>d && git-update-index --add d && - tree=`git-write-tree` && - commit1=`git-commit-tree $tree </dev/null` && - git-update-ref HEAD $commit1 && - git-repack -a -d && - test "`git-count-objects`" = "0 objects, 0 kilobytes" && + echo d >d && cat c >>d && git update-index --add d && + tree=`git write-tree` && + commit1=`git commit-tree $tree </dev/null` && + git update-ref HEAD $commit1 && + git repack -a -d && + test "`git count-objects`" = "0 objects, 0 kilobytes" && pack1=`ls .git/objects/pack/*.pack` && test -f "$pack1"' test_expect_success \ 'verify-pack -v, defaults' \ - 'git-verify-pack -v "$pack1"' + 'git verify-pack -v "$pack1"' test_expect_success \ 'verify-pack -v, packedGitWindowSize == 1 page' \ - 'git-config core.packedGitWindowSize 512 && - git-verify-pack -v "$pack1"' + 'git config core.packedGitWindowSize 512 && + git verify-pack -v "$pack1"' test_expect_success \ 'verify-pack -v, packedGit{WindowSize,Limit} == 1 page' \ - 'git-config core.packedGitWindowSize 512 && - git-config core.packedGitLimit 512 && - git-verify-pack -v "$pack1"' + 'git config core.packedGitWindowSize 512 && + git config core.packedGitLimit 512 && + git verify-pack -v "$pack1"' test_expect_success \ 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' \ - 'git-config core.packedGitWindowSize 512 && - git-config core.packedGitLimit 512 && - commit2=`git-commit-tree $tree -p $commit1 </dev/null` && - git-update-ref HEAD $commit2 && - git-repack -a -d && - test "`git-count-objects`" = "0 objects, 0 kilobytes" && + 'git config core.packedGitWindowSize 512 && + git config core.packedGitLimit 512 && + commit2=`git commit-tree $tree -p $commit1 </dev/null` && + git update-ref HEAD $commit2 && + git repack -a -d && + test "`git count-objects`" = "0 objects, 0 kilobytes" && pack2=`ls .git/objects/pack/*.pack` && test -f "$pack2" test "$pack1" \!= "$pack2"' test_expect_success \ 'verify-pack -v, defaults' \ - 'git-config --unset core.packedGitWindowSize && - git-config --unset core.packedGitLimit && - git-verify-pack -v "$pack2"' + 'git config --unset core.packedGitWindowSize && + git config --unset core.packedGitLimit && + git verify-pack -v "$pack2"' test_done diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh new file mode 100755 index 0000000000..fb3a270822 --- /dev/null +++ b/t/t5302-pack-index.sh @@ -0,0 +1,225 @@ +#!/bin/sh +# +# Copyright (c) 2007 Nicolas Pitre +# + +test_description='pack index with 64-bit offsets and object CRC' +. ./test-lib.sh + +test_expect_success \ + 'setup' \ + 'rm -rf .git + git init && + git config pack.threads 1 && + i=1 && + while test $i -le 100 + do + iii=`printf '%03i' $i` + test-genrandom "bar" 200 > wide_delta_$iii && + test-genrandom "baz $iii" 50 >> wide_delta_$iii && + test-genrandom "foo"$i 100 > deep_delta_$iii && + test-genrandom "foo"`expr $i + 1` 100 >> deep_delta_$iii && + test-genrandom "foo"`expr $i + 2` 100 >> deep_delta_$iii && + echo $iii >file_$iii && + test-genrandom "$iii" 8192 >>file_$iii && + git update-index --add file_$iii deep_delta_$iii wide_delta_$iii && + i=`expr $i + 1` || return 1 + done && + { echo 101 && test-genrandom 100 8192; } >file_101 && + git update-index --add file_101 && + tree=`git write-tree` && + commit=`git commit-tree $tree </dev/null` && { + echo $tree && + git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" + } >obj-list && + git update-ref HEAD $commit' + +test_expect_success \ + 'pack-objects with index version 1' \ + 'pack1=$(git pack-objects --index-version=1 test-1 <obj-list) && + git verify-pack -v "test-1-${pack1}.pack"' + +test_expect_success \ + 'pack-objects with index version 2' \ + 'pack2=$(git pack-objects --index-version=2 test-2 <obj-list) && + git verify-pack -v "test-2-${pack2}.pack"' + +test_expect_success \ + 'both packs should be identical' \ + 'cmp "test-1-${pack1}.pack" "test-2-${pack2}.pack"' + +test_expect_success \ + 'index v1 and index v2 should be different' \ + '! cmp "test-1-${pack1}.idx" "test-2-${pack2}.idx"' + +test_expect_success \ + 'index-pack with index version 1' \ + 'git index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"' + +test_expect_success \ + 'index-pack with index version 2' \ + 'git index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"' + +test_expect_success \ + 'index-pack results should match pack-objects ones' \ + 'cmp "test-1-${pack1}.idx" "1.idx" && + cmp "test-2-${pack2}.idx" "2.idx"' + +test_expect_success \ + 'index v2: force some 64-bit offsets with pack-objects' \ + 'pack3=$(git pack-objects --index-version=2,0x40000 test-3 <obj-list)' + +if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) || + ! (echo "$msg" | grep "pack too large .* off_t") +then + test_set_prereq OFF64_T +else + say "# skipping tests concerning 64-bit offsets" +fi + +test_expect_success OFF64_T \ + 'index v2: verify a pack with some 64-bit offsets' \ + 'git verify-pack -v "test-3-${pack3}.pack"' + +test_expect_success OFF64_T \ + '64-bit offsets: should be different from previous index v2 results' \ + '! cmp "test-2-${pack2}.idx" "test-3-${pack3}.idx"' + +test_expect_success OFF64_T \ + 'index v2: force some 64-bit offsets with index-pack' \ + 'git index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"' + +test_expect_success OFF64_T \ + '64-bit offsets: index-pack result should match pack-objects one' \ + 'cmp "test-3-${pack3}.idx" "3.idx"' + +# returns the object number for given object in given pack index +index_obj_nr() +{ + idx_file=$1 + object_sha1=$2 + nr=0 + git show-index < $idx_file | + while read offs sha1 extra + do + nr=$(($nr + 1)) + test "$sha1" = "$object_sha1" || continue + echo "$(($nr - 1))" + break + done +} + +# returns the pack offset for given object as found in given pack index +index_obj_offset() +{ + idx_file=$1 + object_sha1=$2 + git show-index < $idx_file | grep $object_sha1 | + ( read offs extra && echo "$offs" ) +} + +test_expect_success \ + '[index v1] 1) stream pack to repository' \ + 'git index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" && + git prune-packed && + git count-objects | ( read nr rest && test "$nr" -eq 1 ) && + cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" && + cmp "test-1-${pack1}.idx" ".git/objects/pack/pack-${pack1}.idx"' + +test_expect_success \ + '[index v1] 2) create a stealth corruption in a delta base reference' \ + '# This test assumes file_101 is a delta smaller than 16 bytes. + # It should be against file_100 but we substitute its base for file_099 + sha1_101=`git hash-object file_101` && + sha1_099=`git hash-object file_099` && + offs_101=`index_obj_offset 1.idx $sha1_101` && + nr_099=`index_obj_nr 1.idx $sha1_099` && + chmod +w ".git/objects/pack/pack-${pack1}.pack" && + dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ + if=".git/objects/pack/pack-${pack1}.idx" \ + skip=$((4 + 256 * 4 + $nr_099 * 24)) \ + bs=1 count=20 conv=notrunc && + git cat-file blob $sha1_101 > file_101_foo1' + +test_expect_success \ + '[index v1] 3) corrupted delta happily returned wrong data' \ + 'test -f file_101_foo1 && ! cmp file_101 file_101_foo1' + +test_expect_success \ + '[index v1] 4) confirm that the pack is actually corrupted' \ + 'test_must_fail git fsck --full $commit' + +test_expect_success \ + '[index v1] 5) pack-objects happily reuses corrupted data' \ + 'pack4=$(git pack-objects test-4 <obj-list) && + test -f "test-4-${pack1}.pack"' + +test_expect_success \ + '[index v1] 6) newly created pack is BAD !' \ + 'test_must_fail git verify-pack -v "test-4-${pack1}.pack"' + +test_expect_success \ + '[index v2] 1) stream pack to repository' \ + 'rm -f .git/objects/pack/* && + git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" && + git prune-packed && + git count-objects | ( read nr rest && test "$nr" -eq 1 ) && + cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" && + cmp "test-2-${pack1}.idx" ".git/objects/pack/pack-${pack1}.idx"' + +test_expect_success \ + '[index v2] 2) create a stealth corruption in a delta base reference' \ + '# This test assumes file_101 is a delta smaller than 16 bytes. + # It should be against file_100 but we substitute its base for file_099 + sha1_101=`git hash-object file_101` && + sha1_099=`git hash-object file_099` && + offs_101=`index_obj_offset 1.idx $sha1_101` && + nr_099=`index_obj_nr 1.idx $sha1_099` && + chmod +w ".git/objects/pack/pack-${pack1}.pack" && + dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ + if=".git/objects/pack/pack-${pack1}.idx" \ + skip=$((8 + 256 * 4 + $nr_099 * 20)) \ + bs=1 count=20 conv=notrunc && + git cat-file blob $sha1_101 > file_101_foo2' + +test_expect_success \ + '[index v2] 3) corrupted delta happily returned wrong data' \ + 'test -f file_101_foo2 && ! cmp file_101 file_101_foo2' + +test_expect_success \ + '[index v2] 4) confirm that the pack is actually corrupted' \ + 'test_must_fail git fsck --full $commit' + +test_expect_success \ + '[index v2] 5) pack-objects refuses to reuse corrupted data' \ + 'test_must_fail git pack-objects test-5 <obj-list && + test_must_fail git pack-objects --no-reuse-object test-6 <obj-list' + +test_expect_success \ + '[index v2] 6) verify-pack detects CRC mismatch' \ + 'rm -f .git/objects/pack/* && + git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" && + git verify-pack ".git/objects/pack/pack-${pack1}.pack" && + obj=`git hash-object file_001` && + nr=`index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj` && + chmod +w ".git/objects/pack/pack-${pack1}.idx" && + printf xxxx | dd of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \ + bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + $nr * 4)) && + ( while read obj + do git cat-file -p $obj >/dev/null || exit 1 + done <obj-list ) && + err=$(test_must_fail git verify-pack \ + ".git/objects/pack/pack-${pack1}.pack" 2>&1) && + echo "$err" | grep "CRC mismatch"' + +test_expect_success 'running index-pack in the object store' ' + rm -f .git/objects/pack/* && + cp test-1-${pack1}.pack .git/objects/pack/pack-${pack1}.pack && + ( + cd .git/objects/pack + git index-pack pack-${pack1}.pack + ) && + test -f .git/objects/pack/pack-${pack1}.idx +' + +test_done diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh new file mode 100755 index 0000000000..5f6cd4f333 --- /dev/null +++ b/t/t5303-pack-corruption-resilience.sh @@ -0,0 +1,287 @@ +#!/bin/sh +# +# Copyright (c) 2008 Nicolas Pitre +# + +test_description='resilience to pack corruptions with redundant objects' +. ./test-lib.sh + +# Note: the test objects are created with knowledge of their pack encoding +# to ensure good code path coverage, and to facilitate direct alteration +# later on. The assumed characteristics are: +# +# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2 +# for base, such that blob_3 delta depth is 2; +# +# 2) the bulk of object data is uncompressible so the text part remains +# visible; +# +# 3) object header is always 2 bytes. + +create_test_files() { + test-genrandom "foo" 2000 > file_1 && + test-genrandom "foo" 1800 > file_2 && + test-genrandom "foo" 1800 > file_3 && + echo " base " >> file_1 && + echo " delta1 " >> file_2 && + echo " delta delta2 " >> file_3 && + test-genrandom "bar" 150 >> file_2 && + test-genrandom "baz" 100 >> file_3 +} + +create_new_pack() { + rm -rf .git && + git init && + blob_1=`git hash-object -t blob -w file_1` && + blob_2=`git hash-object -t blob -w file_2` && + blob_3=`git hash-object -t blob -w file_3` && + pack=`printf "$blob_1\n$blob_2\n$blob_3\n" | + git pack-objects $@ .git/objects/pack/pack` && + pack=".git/objects/pack/pack-${pack}" && + git verify-pack -v ${pack}.pack +} + +do_repack() { + pack=`printf "$blob_1\n$blob_2\n$blob_3\n" | + git pack-objects $@ .git/objects/pack/pack` && + pack=".git/objects/pack/pack-${pack}" +} + +do_corrupt_object() { + ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` && + ofs=$(($ofs + $2)) && + chmod +w ${pack}.pack && + dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs && + test_must_fail git verify-pack ${pack}.pack +} + +printf '\0' > zero + +test_expect_success \ + 'initial setup validation' \ + 'create_test_files && + create_new_pack && + git prune-packed && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in header of first object' \ + 'do_corrupt_object $blob_1 0 < zero && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and loose copy of first delta allows for partial recovery' \ + 'git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in data of first object' \ + 'create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and loose copy of second object allows for partial recovery' \ + 'git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in header of first delta' \ + 'create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 0 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and then a repack "clears" the corruption' \ + 'do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'create corruption in data of first delta' \ + 'create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and then a repack "clears" the corruption' \ + 'do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \ + 'create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and then a repack "clears" the corruption' \ + 'do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \ + 'create_new_pack --delta-base-offset && + git prune-packed && + do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and then a repack "clears" the corruption' \ + 'do_repack --delta-base-offset && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \ + 'create_new_pack --delta-base-offset && + git prune-packed && + printf "\001" | do_corrupt_object $blob_2 2 && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... but having a loose copy allows for full recovery' \ + 'mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and then a repack "clears" the corruption' \ + 'do_repack --delta-base-offset && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + '... and a redundant pack allows for full recovery too' \ + 'do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + git hash-object -t blob -w file_2 && + printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack && + git prune-packed && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null' + +test_expect_success \ + 'corrupting header to have too small output buffer fails unpack' \ + 'create_new_pack && + git prune-packed && + printf "\262\001" | do_corrupt_object $blob_1 0 && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null' + +test_done diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh new file mode 100755 index 0000000000..e2ed13dba2 --- /dev/null +++ b/t/t5304-prune.sh @@ -0,0 +1,197 @@ +#!/bin/sh +# +# Copyright (c) 2008 Johannes E. Schindelin +# + +test_description='prune' +. ./test-lib.sh + +day=$((60*60*24)) +week=$(($day*7)) + +add_blob() { + before=$(git count-objects | sed "s/ .*//") && + BLOB=$(echo aleph_0 | git hash-object -w --stdin) && + BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE +} + +test_expect_success setup ' + + : > file && + git add file && + test_tick && + git commit -m initial && + git gc + +' + +test_expect_success 'prune stale packs' ' + + orig_pack=$(echo .git/objects/pack/*.pack) && + : > .git/objects/tmp_1.pack && + : > .git/objects/tmp_2.pack && + test-chmtime =-86501 .git/objects/tmp_1.pack && + git prune --expire 1.day && + test -f $orig_pack && + test -f .git/objects/tmp_2.pack && + ! test -f .git/objects/tmp_1.pack + +' + +test_expect_success 'prune --expire' ' + + add_blob && + git prune --expire=1.hour.ago && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE && + test-chmtime =-86500 $BLOB_FILE && + git prune --expire 1.day && + test $before = $(git count-objects | sed "s/ .*//") && + ! test -f $BLOB_FILE + +' + +test_expect_success 'gc: implicit prune --expire' ' + + add_blob && + test-chmtime =-$((2*$week-30)) $BLOB_FILE && + git gc && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE && + test-chmtime =-$((2*$week+1)) $BLOB_FILE && + git gc && + test $before = $(git count-objects | sed "s/ .*//") && + ! test -f $BLOB_FILE + +' + +test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' ' + + git config gc.pruneExpire invalid && + test_must_fail git gc + +' + +test_expect_success 'gc: start with ok gc.pruneExpire' ' + + git config gc.pruneExpire 2.days.ago && + git gc + +' + +test_expect_success 'prune: prune nonsense parameters' ' + + test_must_fail git prune garbage && + test_must_fail git prune --- && + test_must_fail git prune --no-such-option + +' + +test_expect_success 'prune: prune unreachable heads' ' + + git config core.logAllRefUpdates false && + mv .git/logs .git/logs.old && + : > file2 && + git add file2 && + git commit -m temporary && + tmp_head=$(git rev-list -1 HEAD) && + git reset HEAD^ && + git prune && + test_must_fail git reset $tmp_head -- + +' + +test_expect_success 'prune: do not prune heads listed as an argument' ' + + : > file2 && + git add file2 && + git commit -m temporary && + tmp_head=$(git rev-list -1 HEAD) && + git reset HEAD^ && + git prune -- $tmp_head && + git reset $tmp_head -- + +' + +test_expect_success 'gc --no-prune' ' + + add_blob && + test-chmtime =-$((5001*$day)) $BLOB_FILE && + git config gc.pruneExpire 2.days.ago && + git gc --no-prune && + test 1 = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE + +' + +test_expect_success 'gc respects gc.pruneExpire' ' + + git config gc.pruneExpire 5002.days.ago && + git gc && + test -f $BLOB_FILE && + git config gc.pruneExpire 5000.days.ago && + git gc && + test ! -f $BLOB_FILE + +' + +test_expect_success 'gc --prune=<date>' ' + + add_blob && + test-chmtime =-$((5001*$day)) $BLOB_FILE && + git gc --prune=5002.days.ago && + test -f $BLOB_FILE && + git gc --prune=5000.days.ago && + test ! -f $BLOB_FILE + +' + +test_expect_success 'gc --prune=never' ' + + add_blob && + git gc --prune=never && + test -f $BLOB_FILE && + git gc --prune=now && + test ! -f $BLOB_FILE + +' + +test_expect_success 'gc respects gc.pruneExpire=never' ' + + git config gc.pruneExpire never && + add_blob && + git gc && + test -f $BLOB_FILE && + git config gc.pruneExpire now && + git gc && + test ! -f $BLOB_FILE + +' + +test_expect_success 'prune --expire=never' ' + + add_blob && + git prune --expire=never && + test -f $BLOB_FILE && + git prune && + test ! -f $BLOB_FILE + +' + +test_expect_success 'gc: prune old objects after local clone' ' + add_blob && + test-chmtime =-$((2*$week+1)) $BLOB_FILE && + git clone --no-hardlinks . aclone && + ( + cd aclone && + test 1 = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE && + git gc --prune && + test 0 = $(git count-objects | sed "s/ .*//") && + ! test -f $BLOB_FILE + ) +' + +test_done diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh new file mode 100755 index 0000000000..b061864a87 --- /dev/null +++ b/t/t5305-include-tag.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +test_description='git pack-object --include-tag' +. ./test-lib.sh + +TRASH=`pwd` + +test_expect_success setup ' + echo c >d && + git update-index --add d && + tree=`git write-tree` && + commit=`git commit-tree $tree </dev/null` && + echo "object $commit" >sig && + echo "type commit" >>sig && + echo "tag mytag" >>sig && + echo "tagger $(git var GIT_COMMITTER_IDENT)" >>sig && + echo >>sig && + echo "our test tag" >>sig && + tag=`git mktag <sig` && + rm d sig && + git update-ref refs/tags/mytag $tag && { + echo $tree && + echo $commit && + git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" + } >obj-list +' + +rm -rf clone.git +test_expect_success 'pack without --include-tag' ' + packname_1=$(git pack-objects \ + --window=0 \ + test-1 <obj-list) +' + +test_expect_success 'unpack objects' ' + ( + GIT_DIR=clone.git && + export GIT_DIR && + git init && + git unpack-objects -n <test-1-${packname_1}.pack && + git unpack-objects <test-1-${packname_1}.pack + ) +' + +test_expect_success 'check unpacked result (have commit, no tag)' ' + git rev-list --objects $commit >list.expect && + ( + GIT_DIR=clone.git && + export GIT_DIR && + test_must_fail git cat-file -e $tag && + git rev-list --objects $commit + ) >list.actual && + test_cmp list.expect list.actual +' + +rm -rf clone.git +test_expect_success 'pack with --include-tag' ' + packname_1=$(git pack-objects \ + --window=0 \ + --include-tag \ + test-2 <obj-list) +' + +test_expect_success 'unpack objects' ' + ( + GIT_DIR=clone.git && + export GIT_DIR && + git init && + git unpack-objects -n <test-2-${packname_1}.pack && + git unpack-objects <test-2-${packname_1}.pack + ) +' + +test_expect_success 'check unpacked result (have commit, have tag)' ' + git rev-list --objects mytag >list.expect && + ( + GIT_DIR=clone.git && + export GIT_DIR && + git rev-list --objects $tag + ) >list.actual && + test_cmp list.expect list.actual +' + +test_done diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh new file mode 100755 index 0000000000..f4931c0c2a --- /dev/null +++ b/t/t5306-pack-nobase.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Copyright (c) 2008 Google Inc. +# + +test_description='git-pack-object with missing base + +' +. ./test-lib.sh + +# Create A-B chain +# +test_expect_success \ + 'setup base' \ + 'for a in a b c d e f g h i; do echo $a >>text; done && + echo side >side && + git update-index --add text side && + A=$(echo A | git commit-tree $(git write-tree)) && + + echo m >>text && + git update-index text && + B=$(echo B | git commit-tree $(git write-tree) -p $A) && + git update-ref HEAD $B + ' + +# Create repository with C whose parent is B. +# Repository contains C, C^{tree}, C:text, B, B^{tree}. +# Repository is missing B:text (best delta base for C:text). +# Repository is missing A (parent of B). +# Repository is missing A:side. +# +test_expect_success \ + 'setup patch_clone' \ + 'base_objects=$(pwd)/.git/objects && + (mkdir patch_clone && + cd patch_clone && + git init && + echo "$base_objects" >.git/objects/info/alternates && + echo q >>text && + git read-tree $B && + git update-index text && + git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) && + rm .git/objects/info/alternates && + + git --git-dir=../.git cat-file commit $B | + git hash-object -t commit -w --stdin && + + git --git-dir=../.git cat-file tree "$B^{tree}" | + git hash-object -t tree -w --stdin + ) && + C=$(git --git-dir=patch_clone/.git rev-parse HEAD) + ' + +# Clone patch_clone indirectly by cloning base and fetching. +# +test_expect_success \ + 'indirectly clone patch_clone' \ + '(mkdir user_clone && + cd user_clone && + git init && + git pull ../.git && + test $(git rev-parse HEAD) = $B && + + git pull ../patch_clone/.git && + test $(git rev-parse HEAD) = $C + ) + ' + +# Cloning the patch_clone directly should fail. +# +test_expect_success \ + 'clone of patch_clone is incomplete' \ + '(mkdir user_direct && + cd user_direct && + git init && + test_must_fail git fetch ../patch_clone/.git + ) + ' + +test_done diff --git a/t/t5307-pack-missing-commit.sh b/t/t5307-pack-missing-commit.sh new file mode 100755 index 0000000000..ae52a1882d --- /dev/null +++ b/t/t5307-pack-missing-commit.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +test_description='pack should notice missing commit objects' + +. ./test-lib.sh + +test_expect_success setup ' + for i in 1 2 3 4 5 + do + echo "$i" >"file$i" && + git add "file$i" && + test_tick && + git commit -m "$i" && + git tag "tag$i" + done && + obj=$(git rev-parse --verify tag3) && + fanout=$(expr "$obj" : "\(..\)") && + remainder=$(expr "$obj" : "..\(.*\)") && + rm -f ".git/objects/$fanout/$remainder" +' + +test_expect_success 'check corruption' ' + test_must_fail git fsck +' + +test_expect_success 'rev-list notices corruption (1)' ' + test_must_fail git rev-list HEAD +' + +test_expect_success 'rev-list notices corruption (2)' ' + test_must_fail git rev-list --objects HEAD +' + +test_expect_success 'pack-objects notices corruption' ' + echo HEAD | + test_must_fail git pack-objects --revs pack +' + +test_done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 7d93d0d7c9..c718253673 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -13,9 +13,9 @@ test_expect_success setup ' test_tick && mkdir mozart mozart/is && echo "Commit #0" >mozart/is/pink && - git-update-index --add mozart/is/pink && - tree=$(git-write-tree) && - commit=$(echo "Commit #0" | git-commit-tree $tree) && + git update-index --add mozart/is/pink && + tree=$(git write-tree) && + commit=$(echo "Commit #0" | git commit-tree $tree) && zero=$commit && parent=$zero && i=0 && @@ -24,18 +24,16 @@ test_expect_success setup ' i=$(($i+1)) && test_tick && echo "Commit #$i" >mozart/is/pink && - git-update-index --add mozart/is/pink && - tree=$(git-write-tree) && - commit=$(echo "Commit #$i" | git-commit-tree $tree -p $parent) && - git-update-ref refs/tags/commit$i $commit && + git update-index --add mozart/is/pink && + tree=$(git write-tree) && + commit=$(echo "Commit #$i" | git commit-tree $tree -p $parent) && + git update-ref refs/tags/commit$i $commit && parent=$commit || return 1 done && - git-update-ref HEAD "$commit" && - git-clone ./. victim && - cd victim && - git-log && - cd .. && - git-update-ref HEAD "$zero" && + git update-ref HEAD "$commit" && + git clone ./. victim && + ( cd victim && git config receive.denyCurrentBranch warn && git log ) && + git update-ref HEAD "$zero" && parent=$zero && i=0 && while test $i -le $cnt @@ -43,15 +41,15 @@ test_expect_success setup ' i=$(($i+1)) && test_tick && echo "Rebase #$i" >mozart/is/pink && - git-update-index --add mozart/is/pink && - tree=$(git-write-tree) && - commit=$(echo "Rebase #$i" | git-commit-tree $tree -p $parent) && - git-update-ref refs/tags/rebase$i $commit && + git update-index --add mozart/is/pink && + tree=$(git write-tree) && + commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) && + git update-ref refs/tags/rebase$i $commit && parent=$commit || return 1 done && - git-update-ref HEAD "$commit" && + git update-ref HEAD "$commit" && echo Rebase && - git-log' + git log' test_expect_success 'pack the source repository' ' git repack -a -d && @@ -59,58 +57,146 @@ test_expect_success 'pack the source repository' ' ' test_expect_success 'pack the destination repository' ' + ( cd victim && git repack -a -d && - git prune && - cd .. + git prune + ) +' + +test_expect_success 'refuse pushing rewound head without --force' ' + pushed_head=$(git rev-parse --verify master) && + victim_orig=$(cd victim && git rev-parse --verify master) && + test_must_fail git send-pack ./victim master && + victim_head=$(cd victim && git rev-parse --verify master) && + test "$victim_head" = "$victim_orig" && + # this should update + git send-pack --force ./victim master && + victim_head=$(cd victim && git rev-parse --verify master) && + test "$victim_head" = "$pushed_head" ' test_expect_success \ - 'pushing rewound head should not barf but require --force' ' - # should not fail but refuse to update. - if git-send-pack ./victim/.git/ master - then - # now it should fail with Pasky patch - echo >&2 Gaah, it should have failed. - false - else - echo >&2 Thanks, it correctly failed. - true - fi && - if cmp victim/.git/refs/heads/master .git/refs/heads/master + 'push can be used to delete a ref' ' + ( cd victim && git branch extra master ) && + git send-pack ./victim :extra master && + ( cd victim && + test_must_fail git rev-parse --verify extra ) +' + +test_expect_success 'refuse deleting push with denyDeletes' ' + ( + cd victim && + ( git branch -D extra || : ) && + git config receive.denyDeletes true && + git branch extra master + ) && + test_must_fail git send-pack ./victim :extra master +' + +test_expect_success 'denyNonFastforwards trumps --force' ' + ( + cd victim && + ( git branch -D extra || : ) && + git config receive.denyNonFastforwards true + ) && + victim_orig=$(cd victim && git rev-parse --verify master) && + test_must_fail git send-pack --force ./victim master^:master && + victim_head=$(cd victim && git rev-parse --verify master) && + test "$victim_orig" = "$victim_head" +' + +test_expect_success 'push --all excludes remote tracking hierarchy' ' + mkdir parent && + ( + cd parent && + git init && : >file && git add file && git commit -m add + ) && + git clone parent child && + ( + cd child && git push --all + ) && + ( + cd parent && + test -z "$(git for-each-ref refs/remotes/origin)" + ) +' + +rewound_push_setup() { + rm -rf parent child && + mkdir parent && + ( + cd parent && + git init && + echo one >file && git add file && git commit -m one && + git config receive.denyCurrentBranch warn && + echo two >file && git commit -a -m two + ) && + git clone parent child && + ( + cd child && git reset --hard HEAD^ + ) +} + +rewound_push_succeeded() { + cmp ../parent/.git/refs/heads/master .git/refs/heads/master +} + +rewound_push_failed() { + if rewound_push_succeeded then - # should have been left as it was! false else true - fi && - # this should update - git-send-pack --force ./victim/.git/ master && - cmp victim/.git/refs/heads/master .git/refs/heads/master -' + fi +} -test_expect_success \ - 'push can be used to delete a ref' ' - cd victim && - git branch extra master && - cd .. && - test -f victim/.git/refs/heads/extra && - git-send-pack ./victim/.git/ :extra master && - ! test -f victim/.git/refs/heads/extra +test_expect_success 'pushing explicit refspecs respects forcing' ' + rewound_push_setup && + parent_orig=$(cd parent && git rev-parse --verify master) && + ( + cd child && + test_must_fail git send-pack ../parent \ + refs/heads/master:refs/heads/master + ) && + parent_head=$(cd parent && git rev-parse --verify master) && + test "$parent_orig" = "$parent_head" && + ( + cd child && + git send-pack ../parent \ + +refs/heads/master:refs/heads/master + ) && + parent_head=$(cd parent && git rev-parse --verify master) && + child_head=$(cd parent && git rev-parse --verify master) && + test "$parent_head" = "$child_head" ' -unset GIT_CONFIG GIT_CONFIG_LOCAL -HOME=`pwd`/no-such-directory -export HOME ;# this way we force the victim/.git/config to be used. +test_expect_success 'pushing wildcard refspecs respects forcing' ' + rewound_push_setup && + parent_orig=$(cd parent && git rev-parse --verify master) && + ( + cd child && + test_must_fail git send-pack ../parent \ + "refs/heads/*:refs/heads/*" + ) && + parent_head=$(cd parent && git rev-parse --verify master) && + test "$parent_orig" = "$parent_head" && + ( + cd child && + git send-pack ../parent \ + "+refs/heads/*:refs/heads/*" + ) && + parent_head=$(cd parent && git rev-parse --verify master) && + child_head=$(cd parent && git rev-parse --verify master) && + test "$parent_head" = "$child_head" +' -test_expect_success \ - 'pushing with --force should be denied with denyNonFastforwards' ' - cd victim && - git-config receive.denyNonFastforwards true && - cd .. && - git-update-ref refs/heads/master master^ && - git-send-pack --force ./victim/.git/ master && - ! diff -u .git/refs/heads/master victim/.git/refs/heads/master +test_expect_success 'deny pushing to delete current branch' ' + rewound_push_setup && + ( + cd child && + test_must_fail git send-pack ../parent :refs/heads/master 2>errs + ) ' test_done diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 0514056ca6..17bcb0b040 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -8,74 +8,131 @@ test_description='Test the update hook infrastructure.' test_expect_success setup ' echo This is a test. >a && - git-update-index --add a && - tree0=$(git-write-tree) && - commit0=$(echo setup | git-commit-tree $tree0) && - git-update-ref HEAD $commit0 && - git-clone ./. victim && + git update-index --add a && + tree0=$(git write-tree) && + commit0=$(echo setup | git commit-tree $tree0) && echo We hope it works. >a && - git-update-index a && - tree1=$(git-write-tree) && - commit1=$(echo modify | git-commit-tree $tree1 -p $commit0) && - git-update-ref HEAD $commit1 + git update-index a && + tree1=$(git write-tree) && + commit1=$(echo modify | git commit-tree $tree1 -p $commit0) && + git update-ref refs/heads/master $commit0 && + git update-ref refs/heads/tofail $commit1 && + git clone --bare ./. victim.git && + GIT_DIR=victim.git git update-ref refs/heads/tofail $commit1 && + git update-ref refs/heads/master $commit1 && + git update-ref refs/heads/tofail $commit0 ' -cat >victim/.git/hooks/update <<'EOF' +cat >victim.git/hooks/pre-receive <<'EOF' #!/bin/sh -echo "$@" >$GIT_DIR/update.args -read x; printf "$x" >$GIT_DIR/update.stdin -echo STDOUT update -echo STDERR update >&2 +printf %s "$@" >>$GIT_DIR/pre-receive.args +cat - >$GIT_DIR/pre-receive.stdin +echo STDOUT pre-receive +echo STDERR pre-receive >&2 EOF -chmod u+x victim/.git/hooks/update +chmod u+x victim.git/hooks/pre-receive -cat >victim/.git/hooks/post-update <<'EOF' +cat >victim.git/hooks/update <<'EOF' #!/bin/sh -echo "$@" >$GIT_DIR/post-update.args -read x; printf "$x" >$GIT_DIR/post-update.stdin +echo "$@" >>$GIT_DIR/update.args +read x; printf %s "$x" >$GIT_DIR/update.stdin +echo STDOUT update $1 +echo STDERR update $1 >&2 +test "$1" = refs/heads/master || exit +EOF +chmod u+x victim.git/hooks/update + +cat >victim.git/hooks/post-receive <<'EOF' +#!/bin/sh +printf %s "$@" >>$GIT_DIR/post-receive.args +cat - >$GIT_DIR/post-receive.stdin +echo STDOUT post-receive +echo STDERR post-receive >&2 +EOF +chmod u+x victim.git/hooks/post-receive + +cat >victim.git/hooks/post-update <<'EOF' +#!/bin/sh +echo "$@" >>$GIT_DIR/post-update.args +read x; printf %s "$x" >$GIT_DIR/post-update.stdin echo STDOUT post-update echo STDERR post-update >&2 EOF -chmod u+x victim/.git/hooks/post-update +chmod u+x victim.git/hooks/post-update test_expect_success push ' - git-send-pack ./victim/.git/ master >send.out 2>send.err + test_must_fail git send-pack --force ./victim.git \ + master tofail >send.out 2>send.err +' + +test_expect_success 'updated as expected' ' + test $(GIT_DIR=victim.git git rev-parse master) = $commit1 && + test $(GIT_DIR=victim.git git rev-parse tofail) = $commit1 ' test_expect_success 'hooks ran' ' - test -f victim/.git/update.args && - test -f victim/.git/update.stdin && - test -f victim/.git/post-update.args && - test -f victim/.git/post-update.stdin + test -f victim.git/pre-receive.args && + test -f victim.git/pre-receive.stdin && + test -f victim.git/update.args && + test -f victim.git/update.stdin && + test -f victim.git/post-receive.args && + test -f victim.git/post-receive.stdin && + test -f victim.git/post-update.args && + test -f victim.git/post-update.stdin +' + +test_expect_success 'pre-receive hook input' ' + (echo $commit0 $commit1 refs/heads/master; + echo $commit1 $commit0 refs/heads/tofail + ) | test_cmp - victim.git/pre-receive.stdin ' test_expect_success 'update hook arguments' ' - echo refs/heads/master $commit0 $commit1 | - diff -u - victim/.git/update.args + (echo refs/heads/master $commit0 $commit1; + echo refs/heads/tofail $commit1 $commit0 + ) | test_cmp - victim.git/update.args +' + +test_expect_success 'post-receive hook input' ' + echo $commit0 $commit1 refs/heads/master | + test_cmp - victim.git/post-receive.stdin ' test_expect_success 'post-update hook arguments' ' echo refs/heads/master | - diff -u - victim/.git/post-update.args + test_cmp - victim.git/post-update.args ' -test_expect_failure 'update hook stdin is /dev/null' ' - test -s victim/.git/update.stdin +test_expect_success 'all hook stdin is /dev/null' ' + ! test -s victim.git/update.stdin && + ! test -s victim.git/post-update.stdin ' -test_expect_failure 'post-update hook stdin is /dev/null' ' - test -s victim/.git/post-update.stdin +test_expect_success 'all *-receive hook args are empty' ' + ! test -s victim.git/pre-receive.args && + ! test -s victim.git/post-receive.args ' -test_expect_failure 'send-pack produced no output' ' - test -s send.out +test_expect_success 'send-pack produced no output' ' + ! test -s send.out ' +cat <<EOF >expect +remote: STDOUT pre-receive +remote: STDERR pre-receive +remote: STDOUT update refs/heads/master +remote: STDERR update refs/heads/master +remote: STDOUT update refs/heads/tofail +remote: STDERR update refs/heads/tofail +remote: error: hook declined to update refs/heads/tofail +remote: STDOUT post-receive +remote: STDERR post-receive +remote: STDOUT post-update +remote: STDERR post-update +EOF test_expect_success 'send-pack stderr contains hook messages' ' - grep "STDOUT update" send.err && - grep "STDERR update" send.err && - grep "STDOUT post-update" send.err && - grep "STDERR post-update" send.err + grep ^remote: send.err | sed "s/ *\$//" >actual && + test_cmp expect actual ' test_done diff --git a/t/t5402-post-merge-hook.sh b/t/t5402-post-merge-hook.sh new file mode 100755 index 0000000000..6eb2ffd6ec --- /dev/null +++ b/t/t5402-post-merge-hook.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# +# Copyright (c) 2006 Josh England +# + +test_description='Test the post-merge hook.' +. ./test-lib.sh + +test_expect_success setup ' + echo Data for commit0. >a && + git update-index --add a && + tree0=$(git write-tree) && + commit0=$(echo setup | git commit-tree $tree0) && + echo Changed data for commit1. >a && + git update-index a && + tree1=$(git write-tree) && + commit1=$(echo modify | git commit-tree $tree1 -p $commit0) && + git update-ref refs/heads/master $commit0 && + git clone ./. clone1 && + GIT_DIR=clone1/.git git update-index --add a && + git clone ./. clone2 && + GIT_DIR=clone2/.git git update-index --add a +' + +for clone in 1 2; do + cat >clone${clone}/.git/hooks/post-merge <<'EOF' +#!/bin/sh +echo $@ >> $GIT_DIR/post-merge.args +EOF + chmod u+x clone${clone}/.git/hooks/post-merge +done + +test_expect_success 'post-merge does not run for up-to-date ' ' + GIT_DIR=clone1/.git git merge $commit0 && + ! test -f clone1/.git/post-merge.args +' + +test_expect_success 'post-merge runs as expected ' ' + GIT_DIR=clone1/.git git merge $commit1 && + test -e clone1/.git/post-merge.args +' + +test_expect_success 'post-merge from normal merge receives the right argument ' ' + grep 0 clone1/.git/post-merge.args +' + +test_expect_success 'post-merge from squash merge runs as expected ' ' + GIT_DIR=clone2/.git git merge --squash $commit1 && + test -e clone2/.git/post-merge.args +' + +test_expect_success 'post-merge from squash merge receives the right argument ' ' + grep 1 clone2/.git/post-merge.args +' + +test_done diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh new file mode 100755 index 0000000000..d05a9138b4 --- /dev/null +++ b/t/t5403-post-checkout-hook.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Copyright (c) 2006 Josh England +# + +test_description='Test the post-checkout hook.' +. ./test-lib.sh + +test_expect_success setup ' + echo Data for commit0. >a && + echo Data for commit0. >b && + git update-index --add a && + git update-index --add b && + tree0=$(git write-tree) && + commit0=$(echo setup | git commit-tree $tree0) && + git update-ref refs/heads/master $commit0 && + git clone ./. clone1 && + git clone ./. clone2 && + GIT_DIR=clone2/.git git branch new2 && + echo Data for commit1. >clone2/b && + GIT_DIR=clone2/.git git add clone2/b && + GIT_DIR=clone2/.git git commit -m new2 +' + +for clone in 1 2; do + cat >clone${clone}/.git/hooks/post-checkout <<'EOF' +#!/bin/sh +echo $@ > $GIT_DIR/post-checkout.args +EOF + chmod u+x clone${clone}/.git/hooks/post-checkout +done + +test_expect_success 'post-checkout runs as expected ' ' + GIT_DIR=clone1/.git git checkout master && + test -e clone1/.git/post-checkout.args +' + +test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' ' + old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && + test $old = $new -a $flag = 1 +' + +test_expect_success 'post-checkout runs as expected ' ' + GIT_DIR=clone1/.git git checkout master && + test -e clone1/.git/post-checkout.args +' + +test_expect_success 'post-checkout args are correct with git checkout -b ' ' + GIT_DIR=clone1/.git git checkout -b new1 && + old=$(awk "{print \$1}" clone1/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone1/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) && + test $old = $new -a $flag = 1 +' + +test_expect_success 'post-checkout receives the right args with HEAD changed ' ' + GIT_DIR=clone2/.git git checkout new2 && + old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && + test $old != $new -a $flag = 1 +' + +test_expect_success 'post-checkout receives the right args when not switching branches ' ' + GIT_DIR=clone2/.git git checkout master b && + old=$(awk "{print \$1}" clone2/.git/post-checkout.args) && + new=$(awk "{print \$2}" clone2/.git/post-checkout.args) && + flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) && + test $old = $new -a $flag = 0 +' + +if test "$(git config --bool core.filemode)" = true; then +mkdir -p templates/hooks +cat >templates/hooks/post-checkout <<'EOF' +#!/bin/sh +echo $@ > $GIT_DIR/post-checkout.args +EOF +chmod +x templates/hooks/post-checkout + +test_expect_success 'post-checkout hook is triggered by clone' ' + git clone --template=templates . clone3 && + test -f clone3/.git/post-checkout.args +' +fi + +test_done diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh new file mode 100755 index 0000000000..c24003565d --- /dev/null +++ b/t/t5404-tracking-branches.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +test_description='tracking branch update checks for git push' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo 1 >file && + git add file && + git commit -m 1 && + git branch b1 && + git branch b2 && + git branch b3 && + git clone . aa && + git checkout b1 && + echo b1 >>file && + git commit -a -m b1 && + git checkout b2 && + echo b2 >>file && + git commit -a -m b2 +' + +test_expect_success 'prepare pushable branches' ' + cd aa && + b1=$(git rev-parse origin/b1) && + b2=$(git rev-parse origin/b2) && + git checkout -b b1 origin/b1 && + echo aa-b1 >>file && + git commit -a -m aa-b1 && + git checkout -b b2 origin/b2 && + echo aa-b2 >>file && + git commit -a -m aa-b2 && + git checkout master && + echo aa-master >>file && + git commit -a -m aa-master +' + +test_expect_success 'mixed-success push returns error' ' + test_must_fail git push +' + +test_expect_success 'check tracking branches updated correctly after push' ' + test "$(git rev-parse origin/master)" = "$(git rev-parse master)" +' + +test_expect_success 'check tracking branches not updated for failed refs' ' + test "$(git rev-parse origin/b1)" = "$b1" && + test "$(git rev-parse origin/b2)" = "$b2" +' + +test_expect_success 'deleted branches have their tracking branches removed' ' + git push origin :b1 && + test "$(git rev-parse origin/b1)" = "origin/b1" +' + +test_expect_success 'already deleted tracking branches ignored' ' + git branch -d -r origin/b3 && + git push origin :b3 >output 2>&1 && + ! grep error output +' + +test_done diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh new file mode 100755 index 0000000000..4bda18a662 --- /dev/null +++ b/t/t5405-send-pack-rewind.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='forced push to replace commit we do not have' + +. ./test-lib.sh + +test_expect_success setup ' + + >file1 && git add file1 && test_tick && + git commit -m Initial && + git config receive.denyCurrentBranch warn && + + mkdir another && ( + cd another && + git init && + git fetch --update-head-ok .. master:master + ) && + + >file2 && git add file2 && test_tick && + git commit -m Second + +' + +test_expect_success 'non forced push should die not segfault' ' + + ( + cd another && + git push .. master:master + test $? = 1 + ) + +' + +test_expect_success 'forced push should succeed' ' + + ( + cd another && + git push .. +master:master + ) + +' + +test_done diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh new file mode 100755 index 0000000000..59e80a5ea2 --- /dev/null +++ b/t/t5406-remote-rejects.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +test_description='remote push rejects are reported by client' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir .git/hooks && + (echo "#!/bin/sh" ; echo "exit 1") >.git/hooks/update && + chmod +x .git/hooks/update && + echo 1 >file && + git add file && + git commit -m 1 && + git clone . child && + cd child && + echo 2 >file && + git commit -a -m 2 +' + +test_expect_success 'push reports error' 'test_must_fail git push 2>stderr' + +test_expect_success 'individual ref reports error' 'grep rejected stderr' + +test_done diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh new file mode 100755 index 0000000000..552da65a61 --- /dev/null +++ b/t/t5407-post-rewrite-hook.sh @@ -0,0 +1,199 @@ +#!/bin/sh +# +# Copyright (c) 2010 Thomas Rast +# + +test_description='Test the post-rewrite hook.' +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit A foo A && + test_commit B foo B && + test_commit C foo C && + test_commit D foo D +' + +mkdir .git/hooks + +cat >.git/hooks/post-rewrite <<EOF +#!/bin/sh +echo \$@ > "$TRASH_DIRECTORY"/post-rewrite.args +cat > "$TRASH_DIRECTORY"/post-rewrite.data +EOF +chmod u+x .git/hooks/post-rewrite + +clear_hook_input () { + rm -f post-rewrite.args post-rewrite.data +} + +verify_hook_input () { + test_cmp "$TRASH_DIRECTORY"/post-rewrite.args expected.args && + test_cmp "$TRASH_DIRECTORY"/post-rewrite.data expected.data +} + +test_expect_success 'git commit --amend' ' + clear_hook_input && + echo "D new message" > newmsg && + oldsha=$(git rev-parse HEAD^0) && + git commit -Fnewmsg --amend && + echo amend > expected.args && + echo $oldsha $(git rev-parse HEAD^0) > expected.data && + verify_hook_input +' + +test_expect_success 'git commit --amend --no-post-rewrite' ' + clear_hook_input && + echo "D new message again" > newmsg && + git commit --no-post-rewrite -Fnewmsg --amend && + test ! -f post-rewrite.args && + test ! -f post-rewrite.data +' + +test_expect_success 'git rebase' ' + git reset --hard D && + clear_hook_input && + test_must_fail git rebase --onto A B && + echo C > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD^) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase --skip' ' + git reset --hard D && + clear_hook_input && + test_must_fail git rebase --onto A B && + test_must_fail git rebase --skip && + echo D > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -m' ' + git reset --hard D && + clear_hook_input && + test_must_fail git rebase -m --onto A B && + echo C > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD^) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -m --skip' ' + git reset --hard D && + clear_hook_input && + test_must_fail git rebase --onto A B && + test_must_fail git rebase --skip && + echo D > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +# Helper to work around the lack of one-shot exporting for +# test_must_fail (as it is a shell function) +test_fail_interactive_rebase () { + ( + FAKE_LINES="$1" && + shift && + export FAKE_LINES && + test_must_fail git rebase -i "$@" + ) +} + +test_expect_success 'git rebase -i (unchanged)' ' + git reset --hard D && + clear_hook_input && + test_fail_interactive_rebase "1 2" --onto A B && + echo C > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD^) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -i (skip)' ' + git reset --hard D && + clear_hook_input && + test_fail_interactive_rebase "2" --onto A B && + echo D > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -i (squash)' ' + git reset --hard D && + clear_hook_input && + test_fail_interactive_rebase "1 squash 2" --onto A B && + echo C > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -i (fixup without conflict)' ' + git reset --hard D && + clear_hook_input && + FAKE_LINES="1 fixup 2" git rebase -i B && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_expect_success 'git rebase -i (double edit)' ' + git reset --hard D && + clear_hook_input && + FAKE_LINES="edit 1 edit 2" git rebase -i B && + git rebase --continue && + echo something > foo && + git add foo && + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<EOF && +$(git rev-parse C) $(git rev-parse HEAD^) +$(git rev-parse D) $(git rev-parse HEAD) +EOF + verify_hook_input +' + +test_done diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 48e3d1705f..18376d6608 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -3,9 +3,8 @@ # Copyright (c) 2005 Johannes Schindelin # -test_description='Testing multi_ack pack fetching +test_description='Testing multi_ack pack fetching' -' . ./test-lib.sh # Test fetch-pack/upload-pack pair. @@ -13,77 +12,60 @@ test_description='Testing multi_ack pack fetching # Some convenience functions add () { - name=$1 - text="$@" - branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` - parents="" + name=$1 && + text="$@" && + branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` && + parents="" && - shift + shift && while test $1; do - parents="$parents -p $1" + parents="$parents -p $1" && shift - done + done && - echo "$text" > test.txt - git-update-index --add test.txt - tree=$(git-write-tree) + echo "$text" > test.txt && + git update-index --add test.txt && + tree=$(git write-tree) && # make sure timestamps are in correct order - sec=$(($sec+1)) - commit=$(echo "$text" | GIT_AUTHOR_DATE=$sec \ - git-commit-tree $tree $parents 2>>log2.txt) - export $name=$commit - echo $commit > .git/refs/heads/$branch + test_tick && + commit=$(echo "$text" | git commit-tree $tree $parents) && + eval "$name=$commit; export $name" && + echo $commit > .git/refs/heads/$branch && eval ${branch}TIP=$commit } -count_objects () { - ls .git/objects/??/* 2>>log2.txt | wc -l | tr -d " " -} - -test_expect_object_count () { - message=$1 - count=$2 - - output="$(count_objects)" - test_expect_success \ - "new object count $message" \ - "test $count = $output" -} - pull_to_client () { - number=$1 - heads=$2 - count=$3 - no_strict_count_check=$4 - - cd client - test_expect_success "$number pull" \ - "git-fetch-pack -k -v .. $heads" - case "$heads" in *A*) echo $ATIP > .git/refs/heads/A;; esac - case "$heads" in *B*) echo $BTIP > .git/refs/heads/B;; esac - git-symbolic-ref HEAD refs/heads/`echo $heads | sed -e 's/^\(.\).*$/\1/'` - - test_expect_success "fsck" 'git-fsck --full > fsck.txt 2>&1' - - test_expect_success 'check downloaded results' \ - 'mv .git/objects/pack/pack-* . && - p=`ls -1 pack-*.pack` && - git-unpack-objects <$p && - git-fsck --full' - - test_expect_success "new object count after $number pull" \ - 'idx=`echo pack-*.idx` && - pack_count=`git-show-index <$idx | wc -l` && - test $pack_count = $count' - test -z "$pack_count" && pack_count=0 - if [ -z "$no_strict_count_check" ]; then - test_expect_success "minimal count" "test $count = $pack_count" - else - test $count != $pack_count && \ - echo "WARNING: $pack_count objects transmitted, only $count of which were needed" - fi - rm -f pack-* - cd .. + number=$1 && + heads=$2 && + count=$3 && + test_expect_success "$number pull" ' + ( + cd client && + git fetch-pack -k -v .. $heads && + + case "$heads" in + *A*) + echo $ATIP > .git/refs/heads/A;; + esac && + case "$heads" in *B*) + echo $BTIP > .git/refs/heads/B;; + esac && + git symbolic-ref HEAD refs/heads/`echo $heads \ + | sed -e "s/^\(.\).*$/\1/"` && + + git fsck --full && + + mv .git/objects/pack/pack-* . && + p=`ls -1 pack-*.pack` && + git unpack-objects <$p && + git fsck --full && + + idx=`echo pack-*.idx` && + pack_count=`git show-index <$idx | wc -l` && + test $pack_count = $count && + rm -f pack-* + ) + ' } # Here begins the actual testing @@ -94,89 +76,176 @@ pull_to_client () { # client pulls A20, B1. Then tracks only B. Then pulls A. -( +test_expect_success 'setup' ' mkdir client && - cd client && - git-init 2>> log2.txt && - git config transfer.unpacklimit 0 -) - -add A1 - -prev=1; cur=2; while [ $cur -le 10 ]; do - add A$cur $(eval echo \$A$prev) - prev=$cur - cur=$(($cur+1)) -done + ( + cd client && + git init && + git config transfer.unpacklimit 0 + ) && + add A1 && + prev=1 && + cur=2 && + while [ $cur -le 10 ]; do + add A$cur $(eval echo \$A$prev) && + prev=$cur && + cur=$(($cur+1)) + done && + add B1 $A1 + echo $ATIP > .git/refs/heads/A && + echo $BTIP > .git/refs/heads/B && + git symbolic-ref HEAD refs/heads/B +' -add B1 $A1 +pull_to_client 1st "B A" $((11*3)) -echo $ATIP > .git/refs/heads/A -echo $BTIP > .git/refs/heads/B -git-symbolic-ref HEAD refs/heads/B +test_expect_success 'post 1st pull setup' ' + add A11 $A10 && + prev=1 && + cur=2 && + while [ $cur -le 65 ]; do + add B$cur $(eval echo \$B$prev) && + prev=$cur && + cur=$(($cur+1)) + done +' -pull_to_client 1st "B A" $((11*3)) +pull_to_client 2nd "B" $((64*3)) -add A11 $A10 +pull_to_client 3rd "A" $((1*3)) -prev=1; cur=2; while [ $cur -le 65 ]; do - add B$cur $(eval echo \$B$prev) - prev=$cur - cur=$(($cur+1)) -done +test_expect_success 'clone shallow' ' + git clone --depth 2 "file://$(pwd)/." shallow +' -pull_to_client 2nd "B" $((64*3)) +test_expect_success 'clone shallow object count' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow && + grep "^in-pack: 18" count.shallow +' -pull_to_client 3rd "A" $((1*3)) # old fails +test_expect_success 'clone shallow object count (part 2)' ' + sed -e "/^in-pack:/d" -e "/^packs:/d" -e "/^size-pack:/d" \ + -e "/: 0$/d" count.shallow > count_output && + ! test -s count_output +' -test_expect_success "clone shallow" "git-clone --depth 2 . shallow" +test_expect_success 'fsck in shallow repo' ' + ( + cd shallow && + git fsck --full + ) +' -(cd shallow; git-count-objects -v) > count.shallow +test_expect_success 'simple fetch in shallow repo' ' + ( + cd shallow && + git fetch + ) +' -test_expect_success "clone shallow object count" \ - "test \"in-pack: 18\" = \"$(grep in-pack count.shallow)\"" +test_expect_success 'no changes expected' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow.2 && + cmp count.shallow count.shallow.2 +' -count_output () { - sed -e '/^in-pack:/d' -e '/^packs:/d' -e '/: 0$/d' "$1" -} +test_expect_success 'fetch same depth in shallow repo' ' + ( + cd shallow && + git fetch --depth=2 + ) +' -test_expect_success "clone shallow object count (part 2)" ' - test -z "$(count_output count.shallow)" +test_expect_success 'no changes expected' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow.3 && + cmp count.shallow count.shallow.3 ' -test_expect_success "fsck in shallow repo" \ - "(cd shallow; git-fsck --full)" +test_expect_success 'add two more' ' + add B66 $B65 && + add B67 $B66 +' -#test_done; exit +test_expect_success 'pull in shallow repo' ' + ( + cd shallow && + git pull .. B + ) +' -add B66 $B65 -add B67 $B66 +test_expect_success 'clone shallow object count' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow && + grep "^count: 6" count.shallow +' -test_expect_success "pull in shallow repo" \ - "(cd shallow; git pull .. B)" +test_expect_success 'add two more (part 2)' ' + add B68 $B67 && + add B69 $B68 +' -(cd shallow; git-count-objects -v) > count.shallow -test_expect_success "clone shallow object count" \ - "test \"count: 6\" = \"$(grep count count.shallow)\"" +test_expect_success 'deepening pull in shallow repo' ' + ( + cd shallow && + git pull --depth 4 .. B + ) +' -add B68 $B67 -add B69 $B68 +test_expect_success 'clone shallow object count' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow && + grep "^count: 12" count.shallow +' -test_expect_success "deepening pull in shallow repo" \ - "(cd shallow; git pull --depth 4 .. B)" +test_expect_success 'deepening fetch in shallow repo' ' + ( + cd shallow && + git fetch --depth 4 .. A:A + ) +' -(cd shallow; git-count-objects -v) > count.shallow -test_expect_success "clone shallow object count" \ - "test \"count: 12\" = \"$(grep count count.shallow)\"" +test_expect_success 'clone shallow object count' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow && + grep "^count: 18" count.shallow +' -test_expect_success "deepening fetch in shallow repo" \ - "(cd shallow; git fetch --depth 4 .. A:A)" +test_expect_success 'pull in shallow repo with missing merge base' ' + ( + cd shallow && + test_must_fail git pull --depth 4 .. A + ) +' -(cd shallow; git-count-objects -v) > count.shallow -test_expect_success "clone shallow object count" \ - "test \"count: 18\" = \"$(grep count count.shallow)\"" +test_expect_success 'additional simple shallow deepenings' ' + ( + cd shallow && + git fetch --depth=8 && + git fetch --depth=10 && + git fetch --depth=11 + ) +' -test_expect_failure "pull in shallow repo with missing merge base" \ - "(cd shallow; git pull --depth 4 .. A)" +test_expect_success 'clone shallow object count' ' + ( + cd shallow && + git count-objects -v + ) > count.shallow && + grep "^count: 52" count.shallow +' test_done diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh new file mode 100755 index 0000000000..1037a723fe --- /dev/null +++ b/t/t5502-quickfetch.sh @@ -0,0 +1,142 @@ +#!/bin/sh + +test_description='test quickfetch from local' + +. ./test-lib.sh + +test_expect_success setup ' + + test_tick && + echo ichi >file && + git add file && + git commit -m initial && + + cnt=$( ( + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 3 +' + +test_expect_success 'clone without alternate' ' + + ( + mkdir cloned && + cd cloned && + git init-db && + git remote add -f origin .. + ) && + cnt=$( ( + cd cloned && + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 3 +' + +test_expect_success 'further commits in the original' ' + + test_tick && + echo ni >file && + git commit -a -m second && + + cnt=$( ( + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 6 +' + +test_expect_success 'copy commit and tree but not blob by hand' ' + + git rev-list --objects HEAD | + git pack-objects --stdout | + ( + cd cloned && + git unpack-objects + ) && + + cnt=$( ( + cd cloned && + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 6 + + blob=$(git rev-parse HEAD:file | sed -e "s|..|&/|") && + test -f "cloned/.git/objects/$blob" && + rm -f "cloned/.git/objects/$blob" && + + cnt=$( ( + cd cloned && + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 5 + +' + +test_expect_success 'quickfetch should not leave a corrupted repository' ' + + ( + cd cloned && + git fetch + ) && + + cnt=$( ( + cd cloned && + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + test $cnt -eq 6 + +' + +test_expect_success 'quickfetch should not copy from alternate' ' + + ( + mkdir quickclone && + cd quickclone && + git init-db && + (cd ../.git/objects && pwd) >.git/objects/info/alternates && + git remote add origin .. && + git fetch -k -k + ) && + obj_cnt=$( ( + cd quickclone && + git count-objects | sed -e "s/ *objects,.*//" + ) ) && + pck_cnt=$( ( + cd quickclone && + git count-objects -v | sed -n -e "/packs:/{ + s/packs:// + p + q + }" + ) ) && + origin_master=$( ( + cd quickclone && + git rev-parse origin/master + ) ) && + echo "loose objects: $obj_cnt, packfiles: $pck_cnt" && + test $obj_cnt -eq 0 && + test $pck_cnt -eq 0 && + test z$origin_master = z$(git rev-parse master) + +' + +test_expect_success 'quickfetch should handle ~1000 refs (on Windows)' ' + + git gc && + head=$(git rev-parse HEAD) && + branchprefix="$head refs/heads/branch" && + for i in 0 1 2 3 4 5 6 7 8 9; do + for j in 0 1 2 3 4 5 6 7 8 9; do + for k in 0 1 2 3 4 5 6 7 8 9; do + echo "$branchprefix$i$j$k" >> .git/packed-refs + done + done + done && + ( + cd cloned && + git fetch && + git fetch + ) + +' + +test_done diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh new file mode 100755 index 0000000000..bab1a536f5 --- /dev/null +++ b/t/t5503-tagfollow.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +test_description='test automatic tag following' + +. ./test-lib.sh + +case $(uname -s) in +*MINGW*) + skip_all="GIT_DEBUG_SEND_PACK not supported - skipping tests" + test_done +esac + +# End state of the repository: +# +# T - tag1 S - tag2 +# / / +# L - A ------ O ------ B +# \ \ \ +# \ C - origin/cat \ +# origin/master master + +test_expect_success setup ' + test_tick && + echo ichi >file && + git add file && + git commit -m L && + L=$(git rev-parse --verify HEAD) && + + ( + mkdir cloned && + cd cloned && + git init-db && + git remote add -f origin .. + ) && + + test_tick && + echo A >file && + git add file && + git commit -m A && + A=$(git rev-parse --verify HEAD) +' + +U=UPLOAD_LOG + +cat - <<EOF >expect +#S +want $A +#E +EOF +test_expect_success 'fetch A (new commit : 1 connection)' ' + rm -f $U + ( + cd cloned && + GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U && + test $A = $(git rev-parse --verify origin/master) + ) && + test -s $U && + cut -d" " -f1,2 $U >actual && + test_cmp expect actual +' + +test_expect_success "create tag T on A, create C on branch cat" ' + git tag -a -m tag1 tag1 $A && + T=$(git rev-parse --verify tag1) && + + git checkout -b cat && + echo C >file && + git add file && + git commit -m C && + C=$(git rev-parse --verify HEAD) && + git checkout master +' + +cat - <<EOF >expect +#S +want $C +want $T +#E +EOF +test_expect_success 'fetch C, T (new branch, tag : 1 connection)' ' + rm -f $U + ( + cd cloned && + GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U && + test $C = $(git rev-parse --verify origin/cat) && + test $T = $(git rev-parse --verify tag1) && + test $A = $(git rev-parse --verify tag1^0) + ) && + test -s $U && + cut -d" " -f1,2 $U >actual && + test_cmp expect actual +' + +test_expect_success "create commits O, B, tag S on B" ' + test_tick && + echo O >file && + git add file && + git commit -m O && + + test_tick && + echo B >file && + git add file && + git commit -m B && + B=$(git rev-parse --verify HEAD) && + + git tag -a -m tag2 tag2 $B && + S=$(git rev-parse --verify tag2) +' + +cat - <<EOF >expect +#S +want $B +want $S +#E +EOF +test_expect_success 'fetch B, S (commit and tag : 1 connection)' ' + rm -f $U + ( + cd cloned && + GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U && + test $B = $(git rev-parse --verify origin/master) && + test $B = $(git rev-parse --verify tag2^0) && + test $S = $(git rev-parse --verify tag2) + ) && + test -s $U && + cut -d" " -f1,2 $U >actual && + test_cmp expect actual +' + +cat - <<EOF >expect +#S +want $B +want $S +#E +EOF +test_expect_success 'new clone fetch master and tags' ' + git branch -D cat + rm -f $U + ( + mkdir clone2 && + cd clone2 && + git init && + git remote add origin .. && + GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U && + test $B = $(git rev-parse --verify origin/master) && + test $S = $(git rev-parse --verify tag2) && + test $B = $(git rev-parse --verify tag2^0) && + test $T = $(git rev-parse --verify tag1) && + test $A = $(git rev-parse --verify tag1^0) + ) && + test -s $U && + cut -d" " -f1,2 $U >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh new file mode 100755 index 0000000000..4c498b1902 --- /dev/null +++ b/t/t5505-remote.sh @@ -0,0 +1,867 @@ +#!/bin/sh + +test_description='git remote porcelain-ish' + +. ./test-lib.sh + +setup_repository () { + mkdir "$1" && ( + cd "$1" && + git init && + >file && + git add file && + test_tick && + git commit -m "Initial" && + git checkout -b side && + >elif && + git add elif && + test_tick && + git commit -m "Second" && + git checkout master + ) +} + +tokens_match () { + echo "$1" | tr ' ' '\012' | sort | sed -e '/^$/d' >expect && + echo "$2" | tr ' ' '\012' | sort | sed -e '/^$/d' >actual && + test_cmp expect actual +} + +check_remote_track () { + actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p') + shift && + tokens_match "$*" "$actual" +} + +check_tracking_branch () { + f="" && + r=$(git for-each-ref "--format=%(refname)" | + sed -ne "s|^refs/remotes/$1/||p") && + shift && + tokens_match "$*" "$r" +} + +test_expect_success setup ' + + setup_repository one && + setup_repository two && + ( + cd two && git branch another + ) && + git clone one test + +' + +test_expect_success 'remote information for the origin' ' +( + cd test && + tokens_match origin "$(git remote)" && + check_remote_track origin master side && + check_tracking_branch origin HEAD master side +) +' + +test_expect_success 'add another remote' ' +( + cd test && + git remote add -f second ../two && + tokens_match "origin second" "$(git remote)" && + check_remote_track origin master side && + check_remote_track second master side another && + check_tracking_branch second master side another && + git for-each-ref "--format=%(refname)" refs/remotes | + sed -e "/^refs\/remotes\/origin\//d" \ + -e "/^refs\/remotes\/second\//d" >actual && + >expect && + test_cmp expect actual +) +' + +test_expect_success 'remote forces tracking branches' ' +( + cd test && + case `git config remote.second.fetch` in + +*) true ;; + *) false ;; + esac +) +' + +test_expect_success 'remove remote' ' +( + cd test && + git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master && + git remote rm second +) +' + +test_expect_success 'remove remote' ' +( + cd test && + tokens_match origin "$(git remote)" && + check_remote_track origin master side && + git for-each-ref "--format=%(refname)" refs/remotes | + sed -e "/^refs\/remotes\/origin\//d" >actual && + >expect && + test_cmp expect actual +) +' + +test_expect_success 'remove remote protects non-remote branches' ' +( + cd test && + { cat >expect1 <<EOF +Note: A non-remote branch was not removed; to delete it, use: + git branch -d master +EOF + } && + { cat >expect2 <<EOF +Note: Non-remote branches were not removed; to delete them, use: + git branch -d foobranch + git branch -d master +EOF + } && + git tag footag && + git config --add remote.oops.fetch "+refs/*:refs/*" && + git remote rm oops 2>actual1 && + git branch foobranch && + git config --add remote.oops.fetch "+refs/*:refs/*" && + git remote rm oops 2>actual2 && + git branch -d foobranch && + git tag -d footag && + test_cmp expect1 actual1 && + test_cmp expect2 actual2 +) +' + +cat > test/expect << EOF +* remote origin + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one + HEAD branch: master + Remote branches: + master new (next fetch will store in remotes/origin) + side tracked + Local branches configured for 'git pull': + ahead merges with remote master + master merges with remote master + octopus merges with remote topic-a + and with remote topic-b + and with remote topic-c + rebase rebases onto remote master + Local refs configured for 'git push': + master pushes to master (local out of date) + master pushes to upstream (create) +* remote two + Fetch URL: ../two + Push URL: ../three + HEAD branch (remote HEAD is ambiguous, may be one of the following): + another + master + Local refs configured for 'git push': + ahead forces to master (fast-forwardable) + master pushes to another (up to date) +EOF + +test_expect_success 'show' ' + (cd test && + git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream && + git fetch && + git checkout -b ahead origin/master && + echo 1 >> file && + test_tick && + git commit -m update file && + git checkout master && + git branch --track octopus origin/master && + git branch --track rebase origin/master && + git branch -d -r origin/master && + git config --add remote.two.url ../two && + git config --add remote.two.pushurl ../three && + git config branch.rebase.rebase true && + git config branch.octopus.merge "topic-a topic-b topic-c" && + (cd ../one && + echo 1 > file && + test_tick && + git commit -m update file) && + git config --add remote.origin.push : && + git config --add remote.origin.push refs/heads/master:refs/heads/upstream && + git config --add remote.origin.push +refs/tags/lastbackup && + git config --add remote.two.push +refs/heads/ahead:refs/heads/master && + git config --add remote.two.push refs/heads/master:refs/heads/another && + git remote show origin two > output && + git branch -d rebase octopus && + test_cmp expect output) +' + +cat > test/expect << EOF +* remote origin + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one + HEAD branch: (not queried) + Remote branches: (status not queried) + master + side + Local branches configured for 'git pull': + ahead merges with remote master + master merges with remote master + Local refs configured for 'git push' (status not queried): + (matching) pushes to (matching) + refs/heads/master pushes to refs/heads/upstream + refs/tags/lastbackup forces to refs/tags/lastbackup +EOF + +test_expect_success 'show -n' ' + (mv one one.unreachable && + cd test && + git remote show -n origin > output && + mv ../one.unreachable ../one && + test_cmp expect output) +' + +test_expect_success 'prune' ' + (cd one && + git branch -m side side2) && + (cd test && + git fetch origin && + git remote prune origin && + git rev-parse refs/remotes/origin/side2 && + test_must_fail git rev-parse refs/remotes/origin/side) +' + +test_expect_success 'set-head --delete' ' + (cd test && + git symbolic-ref refs/remotes/origin/HEAD && + git remote set-head --delete origin && + test_must_fail git symbolic-ref refs/remotes/origin/HEAD) +' + +test_expect_success 'set-head --auto' ' + (cd test && + git remote set-head --auto origin && + echo refs/remotes/origin/master >expect && + git symbolic-ref refs/remotes/origin/HEAD >output && + test_cmp expect output + ) +' + +cat >test/expect <<EOF +error: Multiple remote HEAD branches. Please choose one explicitly with: + git remote set-head two another + git remote set-head two master +EOF + +test_expect_success 'set-head --auto fails w/multiple HEADs' ' + (cd test && + test_must_fail git remote set-head --auto two >output 2>&1 && + test_cmp expect output) +' + +cat >test/expect <<EOF +refs/remotes/origin/side2 +EOF + +test_expect_success 'set-head explicit' ' + (cd test && + git remote set-head origin side2 && + git symbolic-ref refs/remotes/origin/HEAD >output && + git remote set-head origin master && + test_cmp expect output) +' + +cat > test/expect << EOF +Pruning origin +URL: $(pwd)/one + * [would prune] origin/side2 +EOF + +test_expect_success 'prune --dry-run' ' + (cd one && + git branch -m side2 side) && + (cd test && + git remote prune --dry-run origin > output && + git rev-parse refs/remotes/origin/side2 && + test_must_fail git rev-parse refs/remotes/origin/side && + (cd ../one && + git branch -m side side2) && + test_cmp expect output) +' + +test_expect_success 'add --mirror && prune' ' + (mkdir mirror && + cd mirror && + git init --bare && + git remote add --mirror -f origin ../one) && + (cd one && + git branch -m side2 side) && + (cd mirror && + git rev-parse --verify refs/heads/side2 && + test_must_fail git rev-parse --verify refs/heads/side && + git fetch origin && + git remote prune origin && + test_must_fail git rev-parse --verify refs/heads/side2 && + git rev-parse --verify refs/heads/side) +' + +test_expect_success 'add alt && prune' ' + (mkdir alttst && + cd alttst && + git init && + git remote add -f origin ../one && + git config remote.alt.url ../one && + git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") && + (cd one && + git branch -m side side2) && + (cd alttst && + git rev-parse --verify refs/remotes/origin/side && + test_must_fail git rev-parse --verify refs/remotes/origin/side2 && + git fetch alt && + git remote prune alt && + test_must_fail git rev-parse --verify refs/remotes/origin/side && + 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 + drosophila/another + drosophila/master + drosophila/side +EOF + +test_expect_success 'update' ' + + (cd one && + git remote add drosophila ../two && + git remote add apis ../mirror && + git remote update && + git branch -r > output && + test_cmp expect output) + +' + +cat > one/expect << EOF + drosophila/another + drosophila/master + drosophila/side + manduca/master + manduca/side + megaloprepus/master + megaloprepus/side +EOF + +test_expect_success 'update with arguments' ' + + (cd one && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git remote add manduca ../mirror && + git remote add megaloprepus ../mirror && + git config remotes.phobaeticus "drosophila megaloprepus" && + git config remotes.titanus manduca && + git remote update phobaeticus titanus && + git branch -r > output && + test_cmp expect output) + +' + +test_expect_success 'update --prune' ' + + (cd one && + git branch -m side2 side3) && + (cd test && + git remote update --prune && + (cd ../one && git branch -m side3 side2) + git rev-parse refs/remotes/origin/side3 && + test_must_fail git rev-parse refs/remotes/origin/side2) +' + +cat > one/expect << EOF + apis/master + apis/side + manduca/master + manduca/side + megaloprepus/master + megaloprepus/side +EOF + +test_expect_success 'update default' ' + + (cd one && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git config remote.drosophila.skipDefaultUpdate true && + git remote update default && + git branch -r > output && + test_cmp expect output) + +' + +cat > one/expect << EOF + drosophila/another + drosophila/master + drosophila/side +EOF + +test_expect_success 'update default (overridden, with funny whitespace)' ' + + (cd one && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git config remotes.default "$(printf "\t drosophila \n")" && + git remote update default && + git branch -r > output && + test_cmp expect output) + +' + +test_expect_success 'update (with remotes.default defined)' ' + + (cd one && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git config remotes.default "drosophila" && + git remote update && + git branch -r > output && + test_cmp expect output) + +' + +test_expect_success '"remote show" does not show symbolic refs' ' + + git clone one three && + (cd three && + git remote show origin > output && + ! grep "^ *HEAD$" < output && + ! grep -i stale < output) + +' + +test_expect_success 'reject adding remote with an invalid name' ' + + test_must_fail git remote add some:url desired-name + +' + +# The first three test if the tracking branches are properly renamed, +# the last two ones check if the config is updated. + +test_expect_success 'rename a remote' ' + + git clone one four && + (cd four && + git remote rename origin upstream && + rmdir .git/refs/remotes/origin && + test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" && + test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" && + test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" && + test "$(git config branch.master.remote)" = "upstream") + +' + +cat > remotes_origin << EOF +URL: $(pwd)/one +Push: refs/heads/master:refs/heads/upstream +Pull: refs/heads/master:refs/heads/origin +EOF + +test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' ' + git clone one five && + origin_url=$(pwd)/one && + (cd five && + git remote rm origin && + mkdir -p .git/remotes && + cat ../remotes_origin > .git/remotes/origin && + git remote rename origin origin && + ! test -f .git/remotes/origin && + test "$(git config remote.origin.url)" = "$origin_url" && + test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" && + test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin") +' + +test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' + git clone one six && + origin_url=$(pwd)/one && + (cd six && + git remote rm origin && + echo "$origin_url" > .git/branches/origin && + git remote rename origin origin && + ! test -f .git/branches/origin && + test "$(git config remote.origin.url)" = "$origin_url" && + test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin") +' + +test_expect_success 'remote prune to cause a dangling symref' ' + git clone one seven && + ( + cd one && + git checkout side2 && + git branch -D master + ) && + ( + cd seven && + git remote prune origin + ) >err 2>&1 && + grep "has become dangling" err && + + : And the dangling symref will not cause other annoying errors && + ( + cd seven && + git branch -a + ) 2>err && + ! grep "points nowhere" err && + ( + cd seven && + test_must_fail git branch nomore origin + ) 2>err && + grep "dangling symref" err +' + +test_expect_success 'show empty remote' ' + + test_create_repo empty && + git clone empty empty-clone && + ( + cd empty-clone && + git remote show origin + ) +' + +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 && + git config --get-all remote.someremote.url >actual && + cmp expect actual +' + +test_expect_success 'remote set-url bar' ' + git remote set-url someremote bar && + echo bar >expect && + git config --get-all remote.someremote.url >actual && + cmp expect actual +' + +test_expect_success 'remote set-url baz bar' ' + git remote set-url someremote baz bar && + echo baz >expect && + git config --get-all remote.someremote.url >actual && + cmp expect actual +' + +test_expect_success 'remote set-url zot bar' ' + test_must_fail git remote set-url someremote zot bar && + echo baz >expect && + git config --get-all remote.someremote.url >actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push zot baz' ' + test_must_fail git remote set-url --push someremote zot baz && + echo "YYY" >expect && + echo baz >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push zot' ' + git remote set-url --push someremote zot && + echo zot >expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push qux zot' ' + git remote set-url --push someremote qux zot && + echo qux >expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push foo qu+x' ' + git remote set-url --push someremote foo qu+x && + echo foo >expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push --add aaa' ' + git remote set-url --push --add someremote aaa && + echo foo >expect && + echo aaa >>expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push bar aaa' ' + git remote set-url --push someremote bar aaa && + echo foo >expect && + echo bar >>expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push --delete bar' ' + git remote set-url --push --delete someremote bar && + echo foo >expect && + echo "YYY" >>expect && + echo baz >>expect && + git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --push --delete foo' ' + git remote set-url --push --delete someremote foo && + echo "YYY" >expect && + echo baz >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --add bbb' ' + git remote set-url --add someremote bbb && + echo "YYY" >expect && + echo baz >>expect && + echo bbb >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --delete .*' ' + test_must_fail git remote set-url --delete someremote .\* && + echo "YYY" >expect && + echo baz >>expect && + echo bbb >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --delete bbb' ' + git remote set-url --delete someremote bbb && + echo "YYY" >expect && + echo baz >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --delete baz' ' + test_must_fail git remote set-url --delete someremote baz && + echo "YYY" >expect && + echo baz >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --add ccc' ' + git remote set-url --add someremote ccc && + echo "YYY" >expect && + echo baz >>expect && + echo ccc >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_expect_success 'remote set-url --delete baz' ' + git remote set-url --delete someremote baz && + echo "YYY" >expect && + echo ccc >>expect && + test_must_fail git config --get-all remote.someremote.pushurl >actual && + echo "YYY" >>actual && + git config --get-all remote.someremote.url >>actual && + cmp expect actual +' + +test_done diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh new file mode 100755 index 0000000000..b7b7ddaa40 --- /dev/null +++ b/t/t5506-remote-groups.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='git remote group handling' +. ./test-lib.sh + +mark() { + echo "$1" >mark +} + +update_repo() { + (cd $1 && + echo content >>file && + git add file && + git commit -F ../mark) +} + +update_repos() { + update_repo one $1 && + update_repo two $1 +} + +repo_fetched() { + if test "`git log -1 --pretty=format:%s $1 --`" = "`cat mark`"; then + echo >&2 "repo was fetched: $1" + return 0 + fi + echo >&2 "repo was not fetched: $1" + return 1 +} + +test_expect_success 'setup' ' + mkdir one && (cd one && git init) && + mkdir two && (cd two && git init) && + git remote add -m master one one && + git remote add -m master two two +' + +test_expect_success 'no group updates all' ' + mark update-all && + update_repos && + git remote update && + repo_fetched one && + repo_fetched two +' + +test_expect_success 'nonexistant group produces error' ' + mark nonexistant && + update_repos && + test_must_fail git remote update nonexistant && + ! repo_fetched one && + ! repo_fetched two +' + +test_expect_success 'updating group updates all members (remote update)' ' + mark group-all && + update_repos && + git config --add remotes.all one && + git config --add remotes.all two && + git remote update all && + repo_fetched one && + repo_fetched two +' + +test_expect_success 'updating group updates all members (fetch)' ' + mark fetch-group-all && + update_repos && + git fetch all && + repo_fetched one && + repo_fetched two +' + +test_expect_success 'updating group does not update non-members (remote update)' ' + mark group-some && + update_repos && + git config --add remotes.some one && + git remote update some && + repo_fetched one && + ! repo_fetched two +' + +test_expect_success 'updating group does not update non-members (fetch)' ' + mark fetch-group-some && + update_repos && + git config --add remotes.some one && + git remote update some && + repo_fetched one && + ! repo_fetched two +' + +test_expect_success 'updating remote name updates that remote' ' + mark remote-name && + update_repos && + git remote update one && + repo_fetched one && + ! repo_fetched two +' + +test_done diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index fa76662dce..4eb10f602f 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -9,6 +9,11 @@ test_description='Per branch config variables affects "git fetch". D=`pwd` +test_bundle_object_count () { + git verify-pack -v "$1" >verify.out && + test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l) +} + test_expect_success setup ' echo >file original && git add file && @@ -37,7 +42,8 @@ test_expect_success "clone and setup child repos" ' echo "Pull: refs/heads/one:refs/heads/one" } >.git/remotes/two && cd .. && - git clone . bundle + git clone . bundle && + git clone . seven ' test_expect_success "fetch test" ' @@ -65,7 +71,19 @@ 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' ' + + cd "$D" && + + mkdir notags && + cd notags && + git init && + + git fetch -t .. + +' test_expect_success 'fetch following tags' ' @@ -83,6 +101,31 @@ test_expect_success 'fetch following tags' ' ' +test_expect_success 'fetch must not resolve short tag name' ' + + cd "$D" && + + mkdir five && + cd five && + git init && + + test_must_fail git fetch .. anno:five + +' + +test_expect_success 'fetch must not resolve short remote name' ' + + cd "$D" && + git update-ref refs/remotes/six/HEAD HEAD + + mkdir six && + cd six && + git init && + + test_must_fail git fetch .. six:six + +' + test_expect_success 'create bundle 1' ' cd "$D" && echo >file updated again by origin && @@ -90,15 +133,36 @@ test_expect_success 'create bundle 1' ' git bundle create bundle1 master^..master ' +test_expect_success 'header of bundle looks right' ' + head -n 1 "$D"/bundle1 | grep "^#" && + head -n 2 "$D"/bundle1 | grep "^-[0-9a-f]\{40\} " && + head -n 3 "$D"/bundle1 | grep "^[0-9a-f]\{40\} " && + head -n 4 "$D"/bundle1 | grep "^$" +' + test_expect_success 'create bundle 2' ' cd "$D" && git bundle create bundle2 master~2..master ' -test_expect_failure 'unbundle 1' ' +test_expect_success 'unbundle 1' ' cd "$D/bundle" && git checkout -b some-branch && - git fetch "$D/bundle1" master:master + test_must_fail git fetch "$D/bundle1" master:master +' + + +test_expect_success 'bundle 1 has only 3 files ' ' + cd "$D" && + ( + while read x && test -n "$x" + do + :; + done + cat + ) <bundle1 >bundle.pack && + git index-pack bundle.pack && + test_bundle_object_count bundle.pack 3 ' test_expect_success 'unbundle 2' ' @@ -107,4 +171,192 @@ test_expect_success 'unbundle 2' ' test "tip" = "$(git log -1 --pretty=oneline master | cut -b42-)" ' +test_expect_success 'bundle does not prerequisite objects' ' + cd "$D" && + touch file2 && + git add file2 && + git commit -m add.file2 file2 && + git bundle create bundle3 -1 HEAD && + ( + while read x && test -n "$x" + do + :; + done + cat + ) <bundle3 >bundle.pack && + git index-pack bundle.pack && + test_bundle_object_count bundle.pack 3 +' + +test_expect_success 'bundle should be able to create a full history' ' + + cd "$D" && + git tag -a -m '1.0' v1.0 master && + git bundle create bundle4 v1.0 + +' + +! rsync --help > /dev/null 2> /dev/null && +say 'Skipping rsync tests because rsync was not found' || { +test_expect_success 'fetch via rsync' ' + git pack-refs && + mkdir rsynced && + (cd rsynced && + git init --bare && + git fetch "rsync:$(pwd)/../.git" master:refs/heads/master && + git gc --prune && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full) +' + +test_expect_success 'push via rsync' ' + mkdir rsynced2 && + (cd rsynced2 && + git init) && + (cd rsynced && + git push "rsync:$(pwd)/../rsynced2/.git" master) && + (cd rsynced2 && + git gc --prune && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full) +' + +test_expect_success 'push via rsync' ' + mkdir rsynced3 && + (cd rsynced3 && + git init) && + git push --all "rsync:$(pwd)/rsynced3/.git" && + (cd rsynced3 && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full) +' +} + +test_expect_success 'fetch with a non-applying branch.<name>.merge' ' + git config branch.master.remote yeti && + git config branch.master.merge refs/heads/bigfoot && + git config remote.blub.url one && + git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" && + git fetch blub +' + +# 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 && + cat result && + grep "fatal: '\''a\\\\!'\''b'\''" result +' + +test_expect_success 'bundle should record HEAD correctly' ' + + cd "$D" && + git bundle create bundle5 HEAD master && + git bundle list-heads bundle5 >actual && + for h in HEAD refs/heads/master + do + echo "$(git rev-parse --verify $h) $h" + done >expect && + test_cmp expect actual + +' + +test_expect_success 'explicit fetch should not update tracking' ' + + cd "$D" && + git branch -f side && + ( + cd three && + o=$(git rev-parse --verify refs/remotes/origin/master) && + git fetch origin master && + n=$(git rev-parse --verify refs/remotes/origin/master) && + test "$o" = "$n" && + test_must_fail git rev-parse --verify refs/remotes/origin/side + ) +' + +test_expect_success 'explicit pull should not update tracking' ' + + cd "$D" && + git branch -f side && + ( + cd three && + o=$(git rev-parse --verify refs/remotes/origin/master) && + git pull origin master && + n=$(git rev-parse --verify refs/remotes/origin/master) && + test "$o" = "$n" && + test_must_fail git rev-parse --verify refs/remotes/origin/side + ) +' + +test_expect_success 'configured fetch updates tracking' ' + + cd "$D" && + git branch -f side && + ( + cd three && + o=$(git rev-parse --verify refs/remotes/origin/master) && + git fetch origin && + n=$(git rev-parse --verify refs/remotes/origin/master) && + test "$o" != "$n" && + git rev-parse --verify refs/remotes/origin/side + ) +' + +test_expect_success 'pushing nonexistent branch by mistake should not segv' ' + + cd "$D" && + test_must_fail git push seven no:no + +' + +test_expect_success 'auto tag following fetches minimum' ' + + cd "$D" && + git clone .git follow && + git checkout HEAD^0 && + ( + for i in 1 2 3 4 5 6 7 + do + echo $i >>file && + git commit -m $i -a && + git tag -a -m $i excess-$i || exit 1 + done + ) && + git checkout master && + ( + cd follow && + git fetch + ) +' + +test_expect_success 'refuse to fetch into the current branch' ' + + test_must_fail git fetch . side:master + +' + +test_expect_success 'fetch into the current branch with --update-head-ok' ' + + git fetch --update-head-ok . side:master + +' + +test_expect_success 'fetch --dry-run' ' + + rm -f .git/FETCH_HEAD && + git fetch --dry-run . && + ! test -f .git/FETCH_HEAD +' + +test_expect_success "should be able to fetch with duplicate refspecs" ' + mkdir dups && + cd dups && + git init && + git config branch.master.remote three && + git config remote.three.url ../three/.git && + git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && + git fetch three +' + test_done diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh new file mode 100755 index 0000000000..c28932216b --- /dev/null +++ b/t/t5511-refspec.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='refspec parsing' + +. ./test-lib.sh + +test_refspec () { + + kind=$1 refspec=$2 expect=$3 + git config remote.frotz.url "." && + git config --remove-section remote.frotz && + git config remote.frotz.url "." && + git config "remote.frotz.$kind" "$refspec" && + if test "$expect" != invalid + then + title="$kind $refspec" + test='git ls-remote frotz' + else + title="$kind $refspec (invalid)" + test='test_must_fail git ls-remote frotz' + fi + test_expect_success "$title" "$test" +} + +test_refspec push '' invalid +test_refspec push ':' +test_refspec push '::' invalid +test_refspec push '+:' + +test_refspec fetch '' +test_refspec fetch ':' +test_refspec fetch '::' invalid + +test_refspec push 'refs/heads/*:refs/remotes/frotz/*' +test_refspec push 'refs/heads/*:refs/remotes/frotz' invalid +test_refspec push 'refs/heads:refs/remotes/frotz/*' invalid +test_refspec push 'refs/heads/master:refs/remotes/frotz/xyzzy' + + +# These have invalid LHS, but we do not have a formal "valid sha-1 +# expression syntax checker" so they are not checked with the current +# code. They will be caught downstream anyway, but we may want to +# have tighter check later... + +: test_refspec push 'refs/heads/master::refs/remotes/frotz/xyzzy' invalid +: test_refspec push 'refs/heads/maste :refs/remotes/frotz/xyzzy' invalid + +test_refspec fetch 'refs/heads/*:refs/remotes/frotz/*' +test_refspec fetch 'refs/heads/*:refs/remotes/frotz' invalid +test_refspec fetch 'refs/heads:refs/remotes/frotz/*' invalid +test_refspec fetch 'refs/heads/master:refs/remotes/frotz/xyzzy' +test_refspec fetch 'refs/heads/master::refs/remotes/frotz/xyzzy' invalid +test_refspec fetch 'refs/heads/maste :refs/remotes/frotz/xyzzy' invalid + +test_refspec push 'master~1:refs/remotes/frotz/backup' +test_refspec fetch 'master~1:refs/remotes/frotz/backup' invalid +test_refspec push 'HEAD~4:refs/remotes/frotz/new' +test_refspec fetch 'HEAD~4:refs/remotes/frotz/new' invalid + +test_refspec push 'HEAD' +test_refspec fetch 'HEAD' +test_refspec push 'refs/heads/ nitfol' invalid +test_refspec fetch 'refs/heads/ nitfol' invalid + +test_refspec push 'HEAD:' invalid +test_refspec fetch 'HEAD:' +test_refspec push 'refs/heads/ nitfol:' invalid +test_refspec fetch 'refs/heads/ nitfol:' invalid + +test_refspec push ':refs/remotes/frotz/deleteme' +test_refspec fetch ':refs/remotes/frotz/HEAD-to-me' +test_refspec push ':refs/remotes/frotz/delete me' invalid +test_refspec fetch ':refs/remotes/frotz/HEAD to me' invalid + +test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid +test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid + +test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*' invalid +test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*' invalid + +test_refspec fetch 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid +test_refspec push 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid + +test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*' +test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*' + +test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh new file mode 100755 index 0000000000..d1912351db --- /dev/null +++ b/t/t5512-ls-remote.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +test_description='git ls-remote' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + test_tick && + git commit -m initial && + git tag mark && + git show-ref --tags -d | sed -e "s/ / /" >expected.tag && + ( + echo "$(git rev-parse HEAD) HEAD" + git show-ref -d | sed -e "s/ / /" + ) >expected.all && + + git remote add self "$(pwd)/.git" + +' + +test_expect_success 'ls-remote --tags .git' ' + + git ls-remote --tags .git >actual && + test_cmp expected.tag actual + +' + +test_expect_success 'ls-remote .git' ' + + git ls-remote .git >actual && + test_cmp expected.all actual + +' + +test_expect_success 'ls-remote --tags self' ' + + git ls-remote --tags self >actual && + test_cmp expected.tag actual + +' + +test_expect_success 'ls-remote self' ' + + git ls-remote self >actual && + test_cmp expected.all actual + +' + +test_expect_success 'dies when no remote specified and no default remotes found' ' + + test_must_fail git ls-remote + +' + +test_expect_success 'use "origin" when no remote specified' ' + + URL="$(pwd)/.git" && + echo "From $URL" >exp_err && + + 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/t5513-fetch-track.sh b/t/t5513-fetch-track.sh new file mode 100755 index 0000000000..9e7486274b --- /dev/null +++ b/t/t5513-fetch-track.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='fetch follows remote tracking branches correctly' + +. ./test-lib.sh + +test_expect_success setup ' + >file && + git add . && + test_tick && + git commit -m Initial && + git branch b-0 && + git branch b1 && + git branch b/one && + test_create_repo other && + ( + cd other && + git config remote.origin.url .. && + git config remote.origin.fetch "+refs/heads/b/*:refs/remotes/b/*" + ) +' + +test_expect_success fetch ' + ( + cd other && git fetch origin && + test "$(git for-each-ref --format="%(refname)")" = refs/remotes/b/one + ) +' + +test_done diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh new file mode 100755 index 0000000000..b73733219d --- /dev/null +++ b/t/t5514-fetch-multiple.sh @@ -0,0 +1,154 @@ +#!/bin/sh + +test_description='fetch --all works correctly' + +. ./test-lib.sh + +setup_repository () { + mkdir "$1" && ( + cd "$1" && + git init && + >file && + git add file && + test_tick && + git commit -m "Initial" && + git checkout -b side && + >elif && + git add elif && + test_tick && + git commit -m "Second" && + git checkout master + ) +} + +test_expect_success setup ' + setup_repository one && + setup_repository two && + ( + cd two && git branch another + ) && + git clone --mirror two three + git clone one test +' + +cat > test/expect << EOF + one/master + one/side + origin/HEAD -> origin/master + origin/master + origin/side + three/another + three/master + three/side + two/another + two/master + two/side +EOF + +test_expect_success 'git fetch --all' ' + (cd test && + git remote add one ../one && + git remote add two ../two && + git remote add three ../three && + git fetch --all && + git branch -r > output && + test_cmp expect output) +' + +test_expect_success 'git fetch --all should continue if a remote has errors' ' + (git clone one test2 && + cd test2 && + git remote add bad ../non-existing && + git remote add one ../one && + git remote add two ../two && + git remote add three ../three && + test_must_fail git fetch --all && + git branch -r > output && + test_cmp ../test/expect output) +' + +test_expect_success 'git fetch --all does not allow non-option arguments' ' + (cd test && + test_must_fail git fetch --all origin && + test_must_fail git fetch --all origin master) +' + +cat > expect << EOF + origin/HEAD -> origin/master + origin/master + origin/side + three/another + three/master + three/side +EOF + +test_expect_success 'git fetch --multiple (but only one remote)' ' + (git clone one test3 && + cd test3 && + git remote add three ../three && + git fetch --multiple three && + git branch -r > output && + test_cmp ../expect output) +' + +cat > expect << EOF + one/master + one/side + two/another + two/master + two/side +EOF + +test_expect_success 'git fetch --multiple (two remotes)' ' + (git clone one test4 && + cd test4 && + git remote rm origin && + git remote add one ../one && + git remote add two ../two && + git fetch --multiple one two && + git branch -r > output && + test_cmp ../expect output) +' + +test_expect_success 'git fetch --multiple (bad remote names)' ' + (cd test4 && + test_must_fail git fetch --multiple four) +' + + +test_expect_success 'git fetch --all (skipFetchAll)' ' + (cd test4 && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git remote add three ../three && + git config remote.three.skipFetchAll true && + git fetch --all && + git branch -r > output && + test_cmp ../expect output) +' + +cat > expect << EOF + one/master + one/side + three/another + three/master + three/side + two/another + two/master + two/side +EOF + +test_expect_success 'git fetch --multiple (ignoring skipFetchAll)' ' + (cd test4 && + for b in $(git branch -r) + do + git branch -r -d $b || break + done && + git fetch --multiple one two three && + git branch -r > output && + test_cmp ../expect output) +' + +test_done diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 0b600bb429..dbb927dec8 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -84,8 +84,7 @@ test_expect_success setup ' git config branch.br-$remote-merge.merge refs/heads/three && git config branch.br-$remote-octopus.remote $remote && git config branch.br-$remote-octopus.merge refs/heads/one && - git config --add branch.br-$remote-octopus.merge two && - git config --add branch.br-$remote-octopus.merge remotes/rem/three + git config --add branch.br-$remote-octopus.merge two done ' @@ -130,10 +129,11 @@ do '' | '#'*) continue ;; esac test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'` - cnt=`expr $test_count + 1` - pfx=`printf "%04d" $cnt` - expect="../../t5515/fetch.$test" - actual="$pfx-fetch.$test" + pfx=`printf "%04d" $test_count` + expect_f="$TEST_DIRECTORY/t5515/fetch.$test" + actual_f="$pfx-fetch.$test" + expect_r="$TEST_DIRECTORY/t5515/refs.$test" + actual_r="$pfx-refs.$test" test_expect_success "$cmd" ' { @@ -141,19 +141,32 @@ do set x $cmd; shift git symbolic-ref HEAD refs/heads/$1 ; shift rm -f .git/FETCH_HEAD - rm -f .git/refs/heads/* - rm -f .git/refs/remotes/rem/* - rm -f .git/refs/tags/* + git for-each-ref \ + refs/heads refs/remotes/rem refs/tags | + while read val type refname + do + git update-ref -d "$refname" "$val" + done git fetch "$@" >/dev/null cat .git/FETCH_HEAD - } >"$actual" && - if test -f "$expect" + } >"$actual_f" && + git show-ref >"$actual_r" && + if test -f "$expect_f" then - diff -u "$expect" "$actual" && - rm -f "$actual" + test_cmp "$expect_f" "$actual_f" && + rm -f "$actual_f" else # this is to help developing new tests. - cp "$actual" "$expect" + cp "$actual_f" "$expect_f" + false + fi && + if test -f "$expect_r" + then + test_cmp "$expect_r" "$actual_r" && + rm -f "$actual_r" + else + # this is to help developing new tests. + cp "$actual_r" "$expect_r" false fi ' diff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge index ea65f31bde..ca2cc1d1b4 100644 --- a/t/t5515/fetch.br-branches-default-merge +++ b/t/t5515/fetch.br-branches-default-merge @@ -1,5 +1,6 @@ # br-branches-default-merge -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default index 7b5fa949e6..7d947cd80f 100644 --- a/t/t5515/fetch.br-branches-default-merge_branches-default +++ b/t/t5515/fetch.br-branches-default-merge_branches-default @@ -1,5 +1,6 @@ # br-branches-default-merge branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus index 128397d737..ec39c54b7e 100644 --- a/t/t5515/fetch.br-branches-default-octopus +++ b/t/t5515/fetch.br-branches-default-octopus @@ -1,5 +1,7 @@ # br-branches-default-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default index 4b37cd481a..6bf42e24b6 100644 --- a/t/t5515/fetch.br-branches-default-octopus_branches-default +++ b/t/t5515/fetch.br-branches-default-octopus_branches-default @@ -1,5 +1,7 @@ # br-branches-default-octopus branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge index 3a4e77ead5..b4b3b35ce0 100644 --- a/t/t5515/fetch.br-branches-one-merge +++ b/t/t5515/fetch.br-branches-one-merge @@ -1,5 +1,6 @@ # br-branches-one-merge -8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one index 00e04b435e..2ecef384eb 100644 --- a/t/t5515/fetch.br-branches-one-merge_branches-one +++ b/t/t5515/fetch.br-branches-one-merge_branches-one @@ -1,5 +1,6 @@ # br-branches-one-merge branches-one -8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus b/t/t5515/fetch.br-branches-one-octopus index 53fe808a3b..96e3029416 100644 --- a/t/t5515/fetch.br-branches-one-octopus +++ b/t/t5515/fetch.br-branches-one-octopus @@ -1,5 +1,6 @@ # br-branches-one-octopus 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus_branches-one b/t/t5515/fetch.br-branches-one-octopus_branches-one index 41b18ff78a..55e0bad621 100644 --- a/t/t5515/fetch.br-branches-one-octopus_branches-one +++ b/t/t5515/fetch.br-branches-one-octopus_branches-one @@ -1,5 +1,6 @@ # br-branches-one-octopus branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus b/t/t5515/fetch.br-config-glob-octopus index 9ee213ea45..938e532db2 100644 --- a/t/t5515/fetch.br-config-glob-octopus +++ b/t/t5515/fetch.br-config-glob-octopus @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus_config-glob b/t/t5515/fetch.br-config-glob-octopus_config-glob index 44bd0ec59f..c9225bf6ff 100644 --- a/t/t5515/fetch.br-config-glob-octopus_config-glob +++ b/t/t5515/fetch.br-config-glob-octopus_config-glob @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus b/t/t5515/fetch.br-remote-glob-octopus index c1554f8f2d..b08e046195 100644 --- a/t/t5515/fetch.br-remote-glob-octopus +++ b/t/t5515/fetch.br-remote-glob-octopus @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus_remote-glob b/t/t5515/fetch.br-remote-glob-octopus_remote-glob index e6134345b8..d4d547c847 100644 --- a/t/t5515/fetch.br-remote-glob-octopus_remote-glob +++ b/t/t5515/fetch.br-remote-glob-octopus_remote-glob @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/refs.br-branches-default b/t/t5515/refs.br-branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-default-merge b/t/t5515/refs.br-branches-default-merge new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default-merge @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-default-merge_branches-default b/t/t5515/refs.br-branches-default-merge_branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default-merge_branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-default-octopus b/t/t5515/refs.br-branches-default-octopus new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default-octopus @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-default-octopus_branches-default b/t/t5515/refs.br-branches-default-octopus_branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default-octopus_branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-default_branches-default b/t/t5515/refs.br-branches-default_branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-branches-default_branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one b/t/t5515/refs.br-branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one-merge b/t/t5515/refs.br-branches-one-merge new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one-merge @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one-merge_branches-one b/t/t5515/refs.br-branches-one-merge_branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one-merge_branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one-octopus b/t/t5515/refs.br-branches-one-octopus new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one-octopus @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one-octopus_branches-one b/t/t5515/refs.br-branches-one-octopus_branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one-octopus_branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-branches-one_branches-one b/t/t5515/refs.br-branches-one_branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-branches-one_branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit b/t/t5515/refs.br-config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit-merge b/t/t5515/refs.br-config-explicit-merge new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit-merge @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit-merge_config-explicit b/t/t5515/refs.br-config-explicit-merge_config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit-merge_config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit-octopus b/t/t5515/refs.br-config-explicit-octopus new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit-octopus @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit-octopus_config-explicit b/t/t5515/refs.br-config-explicit-octopus_config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit-octopus_config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-explicit_config-explicit b/t/t5515/refs.br-config-explicit_config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-explicit_config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob b/t/t5515/refs.br-config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob-merge b/t/t5515/refs.br-config-glob-merge new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob-merge @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob-merge_config-glob b/t/t5515/refs.br-config-glob-merge_config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob-merge_config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob-octopus b/t/t5515/refs.br-config-glob-octopus new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob-octopus @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob-octopus_config-glob b/t/t5515/refs.br-config-glob-octopus_config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob-octopus_config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-config-glob_config-glob b/t/t5515/refs.br-config-glob_config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-config-glob_config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit b/t/t5515/refs.br-remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit-merge b/t/t5515/refs.br-remote-explicit-merge new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit-merge @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit-merge_remote-explicit b/t/t5515/refs.br-remote-explicit-merge_remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit-merge_remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit-octopus b/t/t5515/refs.br-remote-explicit-octopus new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit-octopus @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit-octopus_remote-explicit b/t/t5515/refs.br-remote-explicit-octopus_remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit-octopus_remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-explicit_remote-explicit b/t/t5515/refs.br-remote-explicit_remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-explicit_remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob b/t/t5515/refs.br-remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob-merge b/t/t5515/refs.br-remote-glob-merge new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob-merge @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob-merge_remote-glob b/t/t5515/refs.br-remote-glob-merge_remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob-merge_remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob-octopus b/t/t5515/refs.br-remote-glob-octopus new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob-octopus @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob-octopus_remote-glob b/t/t5515/refs.br-remote-glob-octopus_remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob-octopus_remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-remote-glob_remote-glob b/t/t5515/refs.br-remote-glob_remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-remote-glob_remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig b/t/t5515/refs.br-unconfig new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.br-unconfig @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_--tags_.._.git b/t/t5515/refs.br-unconfig_--tags_.._.git new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.br-unconfig_--tags_.._.git @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_.._.git b/t/t5515/refs.br-unconfig_.._.git new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.br-unconfig_.._.git_one b/t/t5515/refs.br-unconfig_.._.git_one new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git_one @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_.._.git_one_two b/t/t5515/refs.br-unconfig_.._.git_one_two new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git_one_two @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_branches-default b/t/t5515/refs.br-unconfig_branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.br-unconfig_branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_branches-one b/t/t5515/refs.br-unconfig_branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.br-unconfig_branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_config-explicit b/t/t5515/refs.br-unconfig_config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-unconfig_config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_config-glob b/t/t5515/refs.br-unconfig_config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-unconfig_config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_remote-explicit b/t/t5515/refs.br-unconfig_remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-unconfig_remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.br-unconfig_remote-glob b/t/t5515/refs.br-unconfig_remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.br-unconfig_remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master b/t/t5515/refs.master new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.master @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_--tags_.._.git b/t/t5515/refs.master_--tags_.._.git new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.master_--tags_.._.git @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_.._.git b/t/t5515/refs.master_.._.git new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.master_.._.git @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.master_.._.git_one b/t/t5515/refs.master_.._.git_one new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.master_.._.git_one @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_.._.git_one_two b/t/t5515/refs.master_.._.git_one_two new file mode 100644 index 0000000000..70962eaac1 --- /dev/null +++ b/t/t5515/refs.master_.._.git_one_two @@ -0,0 +1,5 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two diff --git a/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three b/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three new file mode 100644 index 0000000000..13e4ad2e46 --- /dev/null +++ b/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three @@ -0,0 +1,11 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_branches-default b/t/t5515/refs.master_branches-default new file mode 100644 index 0000000000..21917c1e5d --- /dev/null +++ b/t/t5515/refs.master_branches-default @@ -0,0 +1,12 @@ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_branches-one b/t/t5515/refs.master_branches-one new file mode 100644 index 0000000000..8a705a5df2 --- /dev/null +++ b/t/t5515/refs.master_branches-one @@ -0,0 +1,12 @@ +8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_config-explicit b/t/t5515/refs.master_config-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.master_config-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_config-glob b/t/t5515/refs.master_config-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.master_config-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_remote-explicit b/t/t5515/refs.master_remote-explicit new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.master_remote-explicit @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5515/refs.master_remote-glob b/t/t5515/refs.master_remote-glob new file mode 100644 index 0000000000..9bbbfd9fc5 --- /dev/null +++ b/t/t5515/refs.master_remote-glob @@ -0,0 +1,15 @@ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two +754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one +0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two +6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master +8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one +22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree +c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three +0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file +525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh new file mode 100755 index 0000000000..b11da79c9c --- /dev/null +++ b/t/t5516-fetch-push.sh @@ -0,0 +1,785 @@ +#!/bin/sh + +test_description='fetching and pushing, with or without wildcard' + +. ./test-lib.sh + +D=`pwd` + +mk_empty () { + rm -fr testrepo && + mkdir testrepo && + ( + cd testrepo && + git init && + git config receive.denyCurrentBranch warn && + mv .git/hooks .git/hooks-disabled + ) +} + +mk_test () { + mk_empty && + ( + for ref in "$@" + do + git push testrepo $the_first_commit:refs/$ref || { + echo "Oops, push refs/$ref failure" + exit 1 + } + done && + cd testrepo && + for ref in "$@" + do + r=$(git show-ref -s --verify refs/$ref) && + test "z$r" = "z$the_first_commit" || { + echo "Oops, refs/$ref is wrong" + exit 1 + } + done && + git fsck --full + ) +} + +mk_child() { + rm -rf "$1" && + git clone testrepo "$1" +} + +check_push_result () { + ( + cd testrepo && + it="$1" && + shift + for ref in "$@" + do + r=$(git show-ref -s --verify refs/$ref) && + test "z$r" = "z$it" || { + echo "Oops, refs/$ref is wrong" + exit 1 + } + done && + git fsck --full + ) +} + +test_expect_success setup ' + + >path1 && + git add path1 && + test_tick && + git commit -a -m repo && + the_first_commit=$(git show-ref -s --verify refs/heads/master) && + + >path2 && + git add path2 && + test_tick && + git commit -a -m second && + the_commit=$(git show-ref -s --verify refs/heads/master) + +' + +test_expect_success 'fetch without wildcard' ' + mk_empty && + ( + cd testrepo && + git fetch .. refs/heads/master:refs/remotes/origin/master && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'fetch with wildcard' ' + mk_empty && + ( + cd testrepo && + git config remote.up.url .. && + git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" && + git fetch up && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'fetch with insteadOf' ' + mk_empty && + ( + TRASH=$(pwd)/ && + cd testrepo && + git config "url.$TRASH.insteadOf" trash/ && + git config remote.up.url trash/. && + git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" && + git fetch up && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'fetch with pushInsteadOf (should not rewrite)' ' + mk_empty && + ( + TRASH=$(pwd)/ && + cd testrepo && + git config "url.trash/.pushInsteadOf" "$TRASH" && + git config remote.up.url "$TRASH." && + git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" && + git fetch up && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push without wildcard' ' + mk_empty && + + git push testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with wildcard' ' + mk_empty && + + git push testrepo "refs/heads/*:refs/remotes/origin/*" && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with insteadOf' ' + mk_empty && + TRASH="$(pwd)/" && + git config "url.$TRASH.insteadOf" trash/ && + git push trash/testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with pushInsteadOf' ' + mk_empty && + TRASH="$(pwd)/" && + git config "url.$TRASH.pushInsteadOf" trash/ && + git push trash/testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' ' + mk_empty && + TRASH="$(pwd)/" && + git config "url.trash2/.pushInsteadOf" trash/ && + git config remote.r.url trash/wrong && + git config remote.r.pushurl "$TRASH/testrepo" && + git push r refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with matching heads' ' + + mk_test heads/master && + git push testrepo && + check_push_result $the_commit heads/master + +' + +test_expect_success 'push with matching heads on the command line' ' + + mk_test heads/master && + git push testrepo : && + check_push_result $the_commit heads/master + +' + +test_expect_success 'failed (non-fast-forward) push with matching heads' ' + + mk_test heads/master && + git push testrepo : && + git commit --amend -massaged && + test_must_fail git push testrepo && + check_push_result $the_commit heads/master && + git reset --hard $the_commit + +' + +test_expect_success 'push --force with matching heads' ' + + mk_test heads/master && + git push testrepo : && + git commit --amend -massaged && + git push --force testrepo && + ! check_push_result $the_commit heads/master && + git reset --hard $the_commit + +' + +test_expect_success 'push with matching heads and forced update' ' + + mk_test heads/master && + git push testrepo : && + git commit --amend -massaged && + git push testrepo +: && + ! check_push_result $the_commit heads/master && + git reset --hard $the_commit + +' + +test_expect_success 'push with no ambiguity (1)' ' + + mk_test heads/master && + git push testrepo master:master && + check_push_result $the_commit heads/master + +' + +test_expect_success 'push with no ambiguity (2)' ' + + mk_test remotes/origin/master && + git push testrepo master:origin/master && + check_push_result $the_commit remotes/origin/master + +' + +test_expect_success 'push with colon-less refspec, no ambiguity' ' + + mk_test heads/master heads/t/master && + git branch -f t/master master && + git push testrepo master && + check_push_result $the_commit heads/master && + check_push_result $the_first_commit heads/t/master + +' + +test_expect_success 'push with weak ambiguity (1)' ' + + mk_test heads/master remotes/origin/master && + git push testrepo master:master && + check_push_result $the_commit heads/master && + check_push_result $the_first_commit remotes/origin/master + +' + +test_expect_success 'push with weak ambiguity (2)' ' + + mk_test heads/master remotes/origin/master remotes/another/master && + git push testrepo master:master && + check_push_result $the_commit heads/master && + check_push_result $the_first_commit remotes/origin/master remotes/another/master + +' + +test_expect_success 'push with ambiguity' ' + + mk_test heads/frotz tags/frotz && + if git push testrepo master:frotz + then + echo "Oops, should have failed" + false + else + check_push_result $the_first_commit heads/frotz tags/frotz + fi + +' + +test_expect_success 'push with colon-less refspec (1)' ' + + mk_test heads/frotz tags/frotz && + git branch -f frotz master && + git push testrepo frotz && + check_push_result $the_commit heads/frotz && + check_push_result $the_first_commit tags/frotz + +' + +test_expect_success 'push with colon-less refspec (2)' ' + + mk_test heads/frotz tags/frotz && + if git show-ref --verify -q refs/heads/frotz + then + git branch -D frotz + fi && + git tag -f frotz && + git push testrepo frotz && + check_push_result $the_commit tags/frotz && + check_push_result $the_first_commit heads/frotz + +' + +test_expect_success 'push with colon-less refspec (3)' ' + + mk_test && + if git show-ref --verify -q refs/tags/frotz + then + git tag -d frotz + fi && + git branch -f frotz master && + git push testrepo frotz && + check_push_result $the_commit heads/frotz && + test 1 = $( cd testrepo && git show-ref | wc -l ) +' + +test_expect_success 'push with colon-less refspec (4)' ' + + mk_test && + if git show-ref --verify -q refs/heads/frotz + then + git branch -D frotz + fi && + git tag -f frotz && + git push testrepo frotz && + check_push_result $the_commit tags/frotz && + test 1 = $( cd testrepo && git show-ref | wc -l ) + +' + +test_expect_success 'push head with non-existant, incomplete dest' ' + + mk_test && + git push testrepo master:branch && + check_push_result $the_commit heads/branch + +' + +test_expect_success 'push tag with non-existant, incomplete dest' ' + + mk_test && + git tag -f v1.0 && + git push testrepo v1.0:tag && + check_push_result $the_commit tags/tag + +' + +test_expect_success 'push sha1 with non-existant, incomplete dest' ' + + mk_test && + test_must_fail git push testrepo `git rev-parse master`:foo + +' + +test_expect_success 'push ref expression with non-existant, incomplete dest' ' + + mk_test && + test_must_fail git push testrepo master^:branch + +' + +test_expect_success 'push with HEAD' ' + + mk_test heads/master && + git checkout master && + git push testrepo HEAD && + check_push_result $the_commit heads/master + +' + +test_expect_success 'push with HEAD nonexisting at remote' ' + + mk_test heads/master && + git checkout -b local master && + git push testrepo HEAD && + check_push_result $the_commit heads/local +' + +test_expect_success 'push with +HEAD' ' + + mk_test heads/master && + git checkout master && + git branch -D local && + git checkout -b local && + git push testrepo master local && + check_push_result $the_commit heads/master && + check_push_result $the_commit heads/local && + + # Without force rewinding should fail + git reset --hard HEAD^ && + test_must_fail git push testrepo HEAD && + check_push_result $the_commit heads/local && + + # With force rewinding should succeed + git push testrepo +HEAD && + check_push_result $the_first_commit heads/local + +' + +test_expect_success 'push HEAD with non-existant, incomplete dest' ' + + mk_test && + git checkout master && + git push testrepo HEAD:branch && + check_push_result $the_commit heads/branch + +' + +test_expect_success 'push with config remote.*.push = HEAD' ' + + mk_test heads/local && + git checkout master && + git branch -f local $the_commit && + ( + cd testrepo && + git checkout local && + git reset --hard $the_first_commit + ) && + git config remote.there.url testrepo && + git config remote.there.push HEAD && + git config branch.master.remote there && + git push && + check_push_result $the_commit heads/master && + check_push_result $the_first_commit heads/local +' + +# clean up the cruft left with the previous one +git config --remove-section remote.there +git config --remove-section branch.master + +test_expect_success 'push with config remote.*.pushurl' ' + + mk_test heads/master && + git checkout master && + git config remote.there.url test2repo && + git config remote.there.pushurl testrepo && + git push there && + check_push_result $the_commit heads/master +' + +# clean up the cruft left with the previous one +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) + ) && + git push --dry-run testrepo && + check_push_result $old_commit heads/master +' + +test_expect_success 'push updates local refs' ' + + mk_test heads/master && + mk_child child && + ( + cd child && + git pull .. master && + git push && + test $(git rev-parse master) = \ + $(git rev-parse remotes/origin/master) + ) + +' + +test_expect_success 'push updates up-to-date local refs' ' + + mk_test heads/master && + mk_child child1 && + mk_child child2 && + (cd child1 && git pull .. master && git push) && + ( + cd child2 && + git pull ../child1 master && + git push && + test $(git rev-parse master) = \ + $(git rev-parse remotes/origin/master) + ) + +' + +test_expect_success 'push preserves up-to-date packed refs' ' + + mk_test heads/master && + mk_child child && + ( + cd child && + git push && + ! test -f .git/refs/remotes/origin/master + ) + +' + +test_expect_success 'push does not update local refs on failure' ' + + mk_test heads/master && + mk_child child && + mkdir testrepo/.git/hooks && + echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive && + chmod +x testrepo/.git/hooks/pre-receive && + ( + cd child && + git pull .. master + test_must_fail git push && + test $(git rev-parse master) != \ + $(git rev-parse remotes/origin/master) + ) + +' + +test_expect_success 'allow deleting an invalid remote ref' ' + + mk_test heads/master && + rm -f testrepo/.git/objects/??/* && + git push testrepo :refs/heads/master && + (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master) + +' + +test_expect_success 'allow deleting a ref using --delete' ' + mk_test heads/master && + (cd testrepo && git config receive.denyDeleteCurrent warn) && + git push testrepo --delete master && + (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master) +' + +test_expect_success 'allow deleting a tag using --delete' ' + mk_test heads/master && + git tag -a -m dummy_message deltag heads/master && + git push testrepo --tags && + (cd testrepo && git rev-parse --verify -q refs/tags/deltag) && + git push testrepo --delete tag deltag && + (cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag) +' + +test_expect_success 'push --delete without args aborts' ' + mk_test heads/master && + test_must_fail git push testrepo --delete +' + +test_expect_success 'push --delete refuses src:dest refspecs' ' + mk_test heads/master && + test_must_fail git push testrepo --delete master:foo +' + +test_expect_success 'warn on push to HEAD of non-bare repository' ' + mk_test heads/master + ( + cd testrepo && + git checkout master && + 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 && + git checkout master && + 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 && + git checkout master && + git config receive.denyCurrentBranch 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 && + git checkout master && + git config receive.denyCurrentBranch false + ) && + git push testrepo master 2>stderr && + ! grep "warning: updating the current branch" stderr +' + +test_expect_success 'fetch with branches' ' + mk_empty && + git branch second $the_first_commit && + git checkout second && + echo ".." > testrepo/.git/branches/branch1 && + ( + cd testrepo && + git fetch branch1 && + r=$(git show-ref -s --verify refs/heads/branch1) && + test "z$r" = "z$the_commit" && + test 1 = $(git for-each-ref refs/heads | wc -l) + ) && + git checkout master +' + +test_expect_success 'fetch with branches containing #' ' + mk_empty && + echo "..#second" > testrepo/.git/branches/branch2 && + ( + cd testrepo && + git fetch branch2 && + r=$(git show-ref -s --verify refs/heads/branch2) && + test "z$r" = "z$the_first_commit" && + test 1 = $(git for-each-ref refs/heads | wc -l) + ) && + git checkout master +' + +test_expect_success 'push with branches' ' + mk_empty && + git checkout second && + echo "testrepo" > .git/branches/branch1 && + git push branch1 && + ( + 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) + ) +' + +test_expect_success 'push with branches containing #' ' + mk_empty && + echo "testrepo#branch3" > .git/branches/branch2 && + git push branch2 && + ( + 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) + ) && + 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" && + echo >>.git/foo "* refs/heads/master:refs/remotes/origin/master [new branch]" && + echo >>.git/foo "Done" && + git push >.git/bar --porcelain testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) && + test_cmp .git/foo .git/bar +' + +test_expect_success 'push --porcelain bad url' ' + mk_empty && + test_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/master:refs/remotes/origin/master && + test_must_fail grep -q Done .git/bar +' + +test_expect_success 'push --porcelain rejected' ' + mk_empty && + git push testrepo refs/heads/master:refs/remotes/origin/master && + (cd testrepo && + git reset --hard origin/master^ + git config receive.denyCurrentBranch true) && + + echo >.git/foo "To testrepo" && + echo >>.git/foo "! refs/heads/master:refs/heads/master [remote rejected] (branch is currently checked out)" && + + test_must_fail git push >.git/bar --porcelain testrepo refs/heads/master:refs/heads/master && + test_cmp .git/foo .git/bar +' + +test_expect_success 'push --porcelain --dry-run rejected' ' + mk_empty && + git push testrepo refs/heads/master:refs/remotes/origin/master && + (cd testrepo && + git reset --hard origin/master + git config receive.denyCurrentBranch true) && + + echo >.git/foo "To testrepo" && + echo >>.git/foo "! refs/heads/master^:refs/heads/master [rejected] (non-fast-forward)" && + echo >>.git/foo "Done" && + + test_must_fail git push >.git/bar --porcelain --dry-run testrepo refs/heads/master^:refs/heads/master && + test_cmp .git/foo .git/bar +' + +test_done diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh new file mode 100755 index 0000000000..e2ad260508 --- /dev/null +++ b/t/t5517-push-mirror.sh @@ -0,0 +1,268 @@ +#!/bin/sh + +test_description='pushing to a mirror repository' + +. ./test-lib.sh + +D=`pwd` + +invert () { + if "$@"; then + return 1 + else + return 0 + fi +} + +mk_repo_pair () { + rm -rf master mirror && + mkdir mirror && + ( + cd mirror && + git init && + git config receive.denyCurrentBranch warn + ) && + mkdir master && + ( + cd master && + git init && + git remote add $1 up ../mirror + ) +} + + +# BRANCH tests +test_expect_success 'push mirror creates new branches' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/heads/master) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror updates existing branches' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up && + echo two >foo && git add foo && git commit -m two && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/heads/master) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror force updates existing branches' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git push --mirror up && + echo two >foo && git add foo && git commit -m two && + git push --mirror up && + git reset --hard HEAD^ + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/heads/master) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror removes branches' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git branch remove master && + git push --mirror up && + git branch -D remove + git push --mirror up + ) && + ( + cd mirror && + invert git show-ref -s --verify refs/heads/remove + ) + +' + +test_expect_success 'push mirror adds, updates and removes branches together' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git branch remove master && + git push --mirror up && + git branch -D remove && + git branch add master && + echo two >foo && git add foo && git commit -m two && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/heads/master) && + master_add=$(cd master && git show-ref -s --verify refs/heads/add) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) && + mirror_add=$(cd mirror && git show-ref -s --verify refs/heads/add) && + test "$master_master" = "$mirror_master" && + test "$master_add" = "$mirror_add" && + ( + cd mirror && + invert git show-ref -s --verify refs/heads/remove + ) + +' + + +# TAG tests +test_expect_success 'push mirror creates new tags' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git tag -f tmaster master && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror updates existing tags' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git tag -f tmaster master && + git push --mirror up && + echo two >foo && git add foo && git commit -m two && + git tag -f tmaster master && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror force updates existing tags' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git tag -f tmaster master && + git push --mirror up && + echo two >foo && git add foo && git commit -m two && + git tag -f tmaster master && + git push --mirror up && + git reset --hard HEAD^ + git tag -f tmaster master && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) && + test "$master_master" = "$mirror_master" + +' + +test_expect_success 'push mirror removes tags' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git tag -f tremove master && + git push --mirror up && + git tag -d tremove + git push --mirror up + ) && + ( + cd mirror && + invert git show-ref -s --verify refs/tags/tremove + ) + +' + +test_expect_success 'push mirror adds, updates and removes tags together' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git tag -f tmaster master && + git tag -f tremove master && + git push --mirror up && + git tag -d tremove && + git tag tadd master && + echo two >foo && git add foo && git commit -m two && + git tag -f tmaster master && + git push --mirror up + ) && + master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) && + master_add=$(cd master && git show-ref -s --verify refs/tags/tadd) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) && + mirror_add=$(cd mirror && git show-ref -s --verify refs/tags/tadd) && + test "$master_master" = "$mirror_master" && + test "$master_add" = "$mirror_add" && + ( + cd mirror && + invert git show-ref -s --verify refs/tags/tremove + ) + +' + +test_expect_success 'remote.foo.mirror adds and removes branches' ' + + mk_repo_pair --mirror && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git branch keep master && + git branch remove master && + git push up && + git branch -D remove + git push up + ) && + ( + cd mirror && + git show-ref -s --verify refs/heads/keep && + invert git show-ref -s --verify refs/heads/remove + ) + +' + +test_expect_success 'remote.foo.mirror=no has no effect' ' + + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git config --add remote.up.mirror no && + git branch keep master && + git push --mirror up && + git branch -D keep && + git push up + ) && + ( + cd mirror && + git show-ref -s --verify refs/heads/keep + ) + +' + +test_done diff --git a/t/t5518-fetch-exit-status.sh b/t/t5518-fetch-exit-status.sh new file mode 100755 index 0000000000..c2060bb870 --- /dev/null +++ b/t/t5518-fetch-exit-status.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Copyright (c) 2008 Dmitry V. Levin +# + +test_description='fetch exit status test' + +. ./test-lib.sh + +test_expect_success setup ' + + >file && + git add file && + git commit -m initial && + + git checkout -b side && + echo side >file && + git commit -a -m side && + + git checkout master && + echo next >file && + git commit -a -m next +' + +test_expect_success 'non-fast-forward fetch' ' + + test_must_fail git fetch . master:side + +' + +test_expect_success 'forced update' ' + + git fetch . +master:side + +' + +test_done diff --git a/t/t5519-push-alternates.sh b/t/t5519-push-alternates.sh new file mode 100755 index 0000000000..96be5236a2 --- /dev/null +++ b/t/t5519-push-alternates.sh @@ -0,0 +1,143 @@ +#!/bin/sh + +test_description='push to a repository that borrows from elsewhere' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir alice-pub && + ( + cd alice-pub && + GIT_DIR=. git init + ) && + mkdir alice-work && + ( + cd alice-work && + git init && + >file && + git add . && + git commit -m initial && + git push ../alice-pub master + ) && + + # Project Bob is a fork of project Alice + mkdir bob-pub && + ( + cd bob-pub && + GIT_DIR=. git init && + mkdir -p objects/info && + echo ../../alice-pub/objects >objects/info/alternates + ) && + git clone alice-pub bob-work && + ( + cd bob-work && + git push ../bob-pub master + ) +' + +test_expect_success 'alice works and pushes' ' + ( + cd alice-work && + echo more >file && + git commit -a -m second && + git push ../alice-pub + ) +' + +test_expect_success 'bob fetches from alice, works and pushes' ' + ( + # Bob acquires what Alice did in his work tree first. + # Even though these objects are not directly in + # the public repository of Bob, this push does not + # need to send the commit Bob received from Alice + # to his public repository, as all the object Alice + # has at her public repository are available to it + # via its alternates. + cd bob-work && + git pull ../alice-pub master && + echo more bob >file && + git commit -a -m third && + git push ../bob-pub + ) && + + # Check that the second commit by Alice is not sent + # to ../bob-pub + ( + cd bob-pub && + second=$(git rev-parse HEAD^) && + rm -f objects/info/alternates && + test_must_fail git cat-file -t $second && + echo ../../alice-pub/objects >objects/info/alternates + ) +' + +test_expect_success 'clean-up in case the previous failed' ' + ( + cd bob-pub && + echo ../../alice-pub/objects >objects/info/alternates + ) +' + +test_expect_success 'alice works and pushes again' ' + ( + # Alice does not care what Bob does. She does not + # even have to be aware of his existence. She just + # keeps working and pushing + cd alice-work && + echo more alice >file && + git commit -a -m fourth && + git push ../alice-pub + ) +' + +test_expect_success 'bob works and pushes' ' + ( + # This time Bob does not pull from Alice, and + # the master branch at her public repository points + # at a commit Bob does not know about. This should + # not prevent the push by Bob from succeeding. + cd bob-work && + echo yet more bob >file && + git commit -a -m fifth && + git push ../bob-pub + ) +' + +test_expect_success 'alice works and pushes yet again' ' + ( + # Alice does not care what Bob does. She does not + # even have to be aware of his existence. She just + # keeps working and pushing + cd alice-work && + echo more and more alice >file && + git commit -a -m sixth.1 && + echo more and more alice >>file && + git commit -a -m sixth.2 && + echo more and more alice >>file && + git commit -a -m sixth.3 && + git push ../alice-pub + ) +' + +test_expect_success 'bob works and pushes again' ' + ( + cd alice-pub && + git cat-file commit master >../bob-work/commit + ) + ( + # This time Bob does not pull from Alice, and + # the master branch at her public repository points + # at a commit Bob does not fully know about, but + # he happens to have the commit object (but not the + # necessary tree) in his repository from Alice. + # This should not prevent the push by Bob from + # succeeding. + cd bob-work && + git hash-object -t commit -w commit && + echo even more bob >file && + git commit -a -m seventh && + git push ../bob-pub + ) +' + +test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 7eb37838bb..319e389ed0 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -26,8 +26,138 @@ 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_done +test_expect_success 'pulling into void using master:master' ' + mkdir cloned-uho && + ( + cd cloned-uho && + git init && + git pull .. master:master + ) && + test -f file && + test -f cloned-uho/file && + test_cmp file cloned-uho/file +' + +test_expect_success 'test . as a remote' ' + + git branch copy master && + git config branch.copy.remote . && + git config branch.copy.merge refs/heads/master && + echo updated >file && + git commit -a -m updated && + git checkout copy && + test `cat file` = file && + git pull && + test `cat file` = updated +' + +test_expect_success 'the default remote . should not break explicit pull' ' + git checkout -b second master^ && + echo modified >file && + git commit -a -m modified && + git checkout copy && + git reset --hard HEAD^ && + test `cat file` = file && + git pull . second && + test `cat file` = modified +' + +test_expect_success '--rebase' ' + git branch to-rebase && + echo modified again > file && + git commit -m file file && + git checkout to-rebase && + echo new > file2 && + git add file2 && + git commit -m "new file" && + git tag before-rebase && + git pull --rebase . copy && + test $(git rev-parse HEAD^) = $(git rev-parse copy) && + test new = $(git show HEAD:file2) +' + +test_expect_success 'branch.to-rebase.rebase' ' + git reset --hard before-rebase && + git config branch.to-rebase.rebase 1 && + git pull . copy && + git config branch.to-rebase.rebase 0 && + test $(git rev-parse HEAD^) = $(git rev-parse copy) && + test new = $(git show HEAD:file2) +' + +test_expect_success '--rebase with rebased upstream' ' + + git remote add -f me . && + git checkout copy && + git tag copy-orig && + git reset --hard HEAD^ && + echo conflicting modification > file && + git commit -m conflict file && + git checkout to-rebase && + echo file > file2 && + git commit -m to-rebase file2 && + git tag to-rebase-orig && + git pull --rebase me copy && + test "conflicting modification" = "$(cat file)" && + test file = $(cat file2) + +' +test_expect_success '--rebase with rebased default upstream' ' + + git update-ref refs/remotes/me/copy copy-orig && + git checkout --track -b to-rebase2 me/copy && + git reset --hard to-rebase-orig && + git pull --rebase && + test "conflicting modification" = "$(cat file)" && + test file = $(cat file2) + +' + +test_expect_success 'rebased upstream + fetch + pull --rebase' ' + + git update-ref refs/remotes/me/copy copy-orig && + git reset --hard to-rebase-orig && + git checkout --track -b to-rebase3 me/copy && + git reset --hard to-rebase-orig && + git fetch && + git pull --rebase && + test "conflicting modification" = "$(cat file)" && + test file = "$(cat file2)" + +' + +test_expect_success 'pull --rebase dies early with dirty working directory' ' + + git checkout to-rebase && + git update-ref refs/remotes/me/copy copy^ && + COPY=$(git rev-parse --verify me/copy) && + git rebase --onto $COPY copy && + git config branch.to-rebase.remote me && + git config branch.to-rebase.merge refs/heads/copy && + git config branch.to-rebase.rebase true && + echo dirty >> file && + git add file && + test_must_fail git pull && + test $COPY = $(git rev-parse --verify me/copy) && + git checkout HEAD -- file && + git pull && + test $COPY != $(git rev-parse --verify me/copy) + +' + +test_expect_success 'pull --rebase works on branch yet to be born' ' + git rev-parse master >expect && + mkdir empty_repo && + (cd empty_repo && + git init && + git pull --rebase .. master && + git rev-parse HEAD >../actual + ) && + test_cmp expect actual +' + +test_done diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh new file mode 100755 index 0000000000..1b06691bb4 --- /dev/null +++ b/t/t5521-pull-options.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +test_description='pull options' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir parent && + (cd parent && git init && + echo one >file && git add file && + git commit -m one) +' + +test_expect_success 'git pull -q' ' + mkdir clonedq && + (cd clonedq && git init && + git pull -q "../parent" >out 2>err && + test ! -s err && + test ! -s out) +' + +test_expect_success 'git pull' ' + mkdir cloned && + (cd cloned && git init && + git pull "../parent" >out 2>err && + test -s err && + test ! -s out) +' + +test_expect_success 'git pull -v' ' + mkdir clonedv && + (cd clonedv && git init && + git pull -v "../parent" >out 2>err && + test -s err && + test ! -s out) +' + +test_expect_success 'git pull -v -q' ' + mkdir clonedvq && + (cd clonedvq && git init && + git pull -v -q "../parent" >out 2>err && + test ! -s out && + test ! -s err) +' + +test_expect_success 'git pull -q -v' ' + mkdir clonedqv && + (cd clonedqv && git init && + git pull -q -v "../parent" >out 2>err && + test ! -s out && + test -s err) +' + +test_expect_success 'git pull --force' ' + mkdir clonedoldstyle && + (cd clonedoldstyle && git init && + cat >>.git/config <<-\EOF && + [remote "one"] + url = ../parent + fetch = refs/heads/master:refs/heads/mirror + [remote "two"] + url = ../parent + fetch = refs/heads/master:refs/heads/origin + [branch "master"] + remote = two + merge = refs/heads/master + EOF + git pull two && + test_commit A && + git branch -f origin && + git pull --all --force + ) +' + +test_expect_success 'git pull --all' ' + mkdir clonedmulti && + (cd clonedmulti && git init && + cat >>.git/config <<-\EOF && + [remote "one"] + url = ../parent + fetch = refs/heads/*:refs/remotes/one/* + [remote "two"] + url = ../parent + fetch = refs/heads/*:refs/remotes/two/* + [branch "master"] + remote = one + merge = refs/heads/master + EOF + git pull --all + ) +' + +test_done diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh new file mode 100755 index 0000000000..298200fa4c --- /dev/null +++ b/t/t5522-pull-symlink.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + +# The scenario we are building: +# +# trash\ directory/ +# clone-repo/ +# subdir/ +# bar +# subdir-link -> clone-repo/subdir/ +# +# The working directory is subdir-link. + +test_expect_success setup ' + mkdir subdir && + echo file >subdir/file && + git add subdir/file && + git commit -q -m file && + git clone -q . clone-repo && + ln -s clone-repo/subdir/ subdir-link && + ( + cd clone-repo && + git config receive.denyCurrentBranch warn + ) && + git config receive.denyCurrentBranch warn +' + +# Demonstrate that things work if we just avoid the symlink +# +test_expect_success 'pulling from real subdir' ' + ( + echo real >subdir/file && + git commit -m real subdir/file && + cd clone-repo/subdir/ && + git pull && + test real = $(cat file) + ) +' + +# From subdir-link, pulling should work as it does from +# clone-repo/subdir/. +# +# Instead, the error pull gave was: +# +# fatal: 'origin': unable to chdir or not a git archive +# fatal: The remote end hung up unexpectedly +# +# because git would find the .git/config for the "trash directory" +# repo, not for the clone-repo repo. The "trash directory" repo +# had no entry for origin. Git found the wrong .git because +# git rev-parse --show-cdup printed a path relative to +# clone-repo/subdir/, not subdir-link/. Git rev-parse --show-cdup +# used the correct .git, but when the git pull shell script did +# "cd `git rev-parse --show-cdup`", it ended up in the wrong +# 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' ' + ( + echo link >subdir/file && + git commit -m link subdir/file && + cd subdir-link/ && + git pull && + test link = $(cat file) + ) +' + +# 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' ' + ( + cd subdir-link/ && + echo push >file && + git commit -m push ./file && + git push + ) && + test push = $(git show HEAD:subdir/file) +' + +test_done diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh new file mode 100755 index 0000000000..00da70763b --- /dev/null +++ b/t/t5523-push-upstream.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='push with --set-upstream' +. ./test-lib.sh + +test_expect_success 'setup bare parent' ' + git init --bare parent && + git remote add upstream parent +' + +test_expect_success 'setup local commit' ' + echo content >file && + git add file && + git commit -m one +' + +check_config() { + (echo $2; echo $3) >expect.$1 + (git config branch.$1.remote + git config branch.$1.merge) >actual.$1 + test_cmp expect.$1 actual.$1 +} + +test_expect_success 'push -u master:master' ' + git push -u upstream master:master && + check_config master upstream refs/heads/master +' + +test_expect_success 'push -u master:other' ' + git push -u upstream master:other && + check_config master upstream refs/heads/other +' + +test_expect_success 'push -u --dry-run master:otherX' ' + git push -u --dry-run upstream master:otherX && + check_config master upstream refs/heads/other +' + +test_expect_success 'push -u master2:master2' ' + git branch master2 && + git push -u upstream master2:master2 && + check_config master2 upstream refs/heads/master2 +' + +test_expect_success 'push -u master2:other2' ' + git push -u upstream master2:other2 && + check_config master2 upstream refs/heads/other2 +' + +test_expect_success 'push -u :master2' ' + git push -u upstream :master2 && + check_config master2 upstream refs/heads/other2 +' + +test_expect_success 'push -u --all' ' + git branch all1 && + git branch all2 && + git push -u --all && + check_config all1 upstream refs/heads/all1 && + check_config all2 upstream refs/heads/all2 +' + +test_expect_success 'push -u HEAD' ' + git checkout -b headbranch && + git push -u upstream HEAD && + check_config headbranch upstream refs/heads/headbranch +' + +test_done diff --git a/t/t5524-pull-msg.sh b/t/t5524-pull-msg.sh new file mode 100755 index 0000000000..8cccecc2fc --- /dev/null +++ b/t/t5524-pull-msg.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +test_description='git pull message generation' + +. ./test-lib.sh + +dollar='$Dollar' + +test_expect_success setup ' + test_commit initial afile original && + git clone . cloned && + ( + cd cloned && + echo added >bfile && + git add bfile && + test_tick && + git commit -m "add bfile" + ) && + test_tick && test_tick && + echo "original $dollar" >afile && + git add afile && + git commit -m "do not clobber $dollar signs" +' + +test_expect_success pull ' +( + cd cloned && + git pull --log && + git log -2 && + git cat-file commit HEAD >result && + grep Dollar result +) +' + +test_done diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh new file mode 100755 index 0000000000..044603c26e --- /dev/null +++ b/t/t5530-upload-pack-error.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +test_description='errors in upload-pack' + +. ./test-lib.sh + +D=`pwd` + +corrupt_repo () { + object_sha1=$(git rev-parse "$1") && + ob=$(expr "$object_sha1" : "\(..\)") && + ject=$(expr "$object_sha1" : "..\(..*\)") && + rm -f ".git/objects/$ob/$ject" +} + +test_expect_success 'setup and corrupt repository' ' + + echo file >file && + git add file && + git rev-parse :file && + git commit -a -m original && + test_tick && + echo changed >file && + git commit -a -m changed && + corrupt_repo HEAD:file + +' + +test_expect_success 'fsck fails' ' + test_must_fail git fsck +' + +test_expect_success 'upload-pack fails due to error in pack-objects packing' ' + + 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 +' + +test_expect_success 'corrupt repo differently' ' + + git hash-object -w file && + corrupt_repo HEAD^^{tree} + +' + +test_expect_success 'fsck fails' ' + test_must_fail git fsck +' +test_expect_success 'upload-pack fails due to error in rev-list' ' + + 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 fails due to error in pack-objects enumeration' ' + + 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 +' + +test_expect_success 'create empty repository' ' + + mkdir foo && + cd foo && + git init + +' + +test_expect_success 'fetch fails' ' + + test_must_fail git fetch .. master + +' + +test_done diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh new file mode 100755 index 0000000000..65d8d474bc --- /dev/null +++ b/t/t5531-deep-submodule-push.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +test_description='unpack-objects' + +. ./test-lib.sh + +test_expect_success setup ' + mkdir pub.git && + GIT_DIR=pub.git git init --bare + GIT_DIR=pub.git git config receive.fsckobjects true && + mkdir work && + ( + cd work && + git init && + mkdir -p gar/bage && + ( + cd gar/bage && + git init && + >junk && + git add junk && + git commit -m "Initial junk" + ) && + git add gar/bage && + git commit -m "Initial superproject" + ) +' + +test_expect_success push ' + ( + cd work && + git push ../pub.git master + ) +' + +test_done diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh new file mode 100755 index 0000000000..a266ca5636 --- /dev/null +++ b/t/t5540-http-push.sh @@ -0,0 +1,145 @@ +#!/bin/sh +# +# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at> +# + +test_description='test WebDAV http-push + +This test runs various sanity checks on http-push.' + +. ./test-lib.sh + +if git http-push > /dev/null 2>&1 || [ $? -eq 128 ] +then + skip_all="skipping test, USE_CURL_MULTI is not defined" + test_done +fi + +LIB_HTTPD_DAV=t +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5540'} +. "$TEST_DIRECTORY"/lib-httpd.sh +ROOT_PATH="$PWD" +start_httpd + +test_expect_success 'setup remote repository' ' + cd "$ROOT_PATH" && + mkdir test_repo && + cd test_repo && + git init && + : >path1 && + git add path1 && + test_tick && + git commit -m initial && + cd - && + git clone --bare test_repo test_repo.git && + cd test_repo.git && + git --bare update-server-info && + mv hooks/post-update.sample hooks/post-update && + ORIG_HEAD=$(git rev-parse --verify HEAD) && + cd - && + mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" +' + +test_expect_success 'clone remote repository' ' + cd "$ROOT_PATH" && + git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone +' + +test_expect_success 'push to remote repository with packed refs' ' + cd "$ROOT_PATH"/test_repo_clone && + : >path2 && + git add path2 && + test_tick && + git commit -m path2 && + HEAD=$(git rev-parse --verify HEAD) && + git push && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD = $(git rev-parse --verify HEAD)) +' + +test_expect_success 'push already up-to-date' ' + git push +' + +test_expect_success 'push to remote repository with unpacked refs' ' + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + rm packed-refs && + git update-ref refs/heads/master $ORIG_HEAD && + git --bare update-server-info) && + git push && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD = $(git rev-parse --verify HEAD)) +' + +test_expect_success 'http-push fetches unpacked objects' ' + cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ + "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_unpacked.git && + + git clone $HTTPD_URL/dumb/test_repo_unpacked.git \ + "$ROOT_PATH"/fetch_unpacked && + + # By reset, we force git to retrieve the object + (cd "$ROOT_PATH"/fetch_unpacked && + git reset --hard HEAD^ && + git remote rm origin && + git reflog expire --expire=0 --all && + git prune && + git push -f -v $HTTPD_URL/dumb/test_repo_unpacked.git master) +' + +test_expect_success 'http-push fetches packed objects' ' + cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ + "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git && + + git clone $HTTPD_URL/dumb/test_repo_packed.git \ + "$ROOT_PATH"/test_repo_clone_packed && + + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git && + git --bare repack && + git --bare prune-packed) && + + # By reset, we force git to retrieve the packed object + (cd "$ROOT_PATH"/test_repo_clone_packed && + git reset --hard HEAD^ && + git remote rm origin && + git reflog expire --expire=0 --all && + git prune && + git push -f -v $HTTPD_URL/dumb/test_repo_packed.git master) +' + +test_expect_success 'create and delete remote branch' ' + cd "$ROOT_PATH"/test_repo_clone && + git checkout -b dev && + : >path3 && + git add path3 && + test_tick && + git commit -m dev && + git push origin dev && + git push origin :dev && + test_must_fail git show-ref --verify refs/remotes/origin/dev +' + +test_expect_success 'MKCOL sends directory names with trailing slashes' ' + + ! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log + +' + +x1="[0-9a-f]" +x2="$x1$x1" +x5="$x1$x1$x1$x1$x1" +x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1" +x40="$x38$x2" + +test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' ' + sed -e "s/PUT /OP /" -e "s/MOVE /OP /" "$HTTPD_ROOT_PATH"/access.log | + grep -e "\"OP .*/objects/$x2/${x38}_$x40 HTTP/[.0-9]*\" 20[0-9] " + +' + +test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ + "$ROOT_PATH"/test_repo_clone master + +stop_httpd + +test_done diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh new file mode 100755 index 0000000000..b0c2a2c3ae --- /dev/null +++ b/t/t5541-http-push.sh @@ -0,0 +1,141 @@ +#!/bin/sh +# +# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at> +# + +test_description='test smart pushing over http via http-backend' +. ./test-lib.sh + +if test -n "$NO_CURL"; then + skip_all='skipping test, git built without http support' + test_done +fi + +ROOT_PATH="$PWD" +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'} +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'setup remote repository' ' + cd "$ROOT_PATH" && + mkdir test_repo && + cd test_repo && + git init && + : >path1 && + git add path1 && + test_tick && + git commit -m initial && + cd - && + git clone --bare test_repo test_repo.git && + cd test_repo.git && + git config http.receivepack true && + ORIG_HEAD=$(git rev-parse --verify HEAD) && + cd - && + mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH" +' + +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 +' + +test_expect_success 'push to remote repository' ' + cd "$ROOT_PATH"/test_repo_clone && + : >path2 && + git add path2 && + test_tick && + git commit -m path2 && + HEAD=$(git rev-parse --verify HEAD) && + git push && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD = $(git rev-parse --verify HEAD)) +' + +test_expect_success 'push already up-to-date' ' + git push +' + +test_expect_success 'create and delete remote branch' ' + cd "$ROOT_PATH"/test_repo_clone && + git checkout -b dev && + : >path3 && + git add path3 && + test_tick && + git commit -m dev && + git push origin dev && + git push origin :dev && + test_must_fail git show-ref --verify refs/remotes/origin/dev +' + +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 +POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 +GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 +GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 +POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 +GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 +POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 +EOF +test_expect_success 'used receive-pack service' ' + sed -e " + s/^.* \"// + s/\"// + s/ [1-9][0-9]*\$// + s/^GET /GET / + " >act <"$HTTPD_ROOT_PATH"/access.log && + test_cmp exp act +' + +test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ + "$ROOT_PATH"/test_repo_clone master + +test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' ' + # create a dissimilarly-named remote ref so that git is unable to match the + # two refs (viz. local, remote) unless an explicit refspec is provided. + git push origin master:retsam + + echo "change changed" > path2 && + git commit -a -m path2 --amend && + + # push master too; this ensures there is at least one '"'push'"' command to + # the remote helper and triggers interaction with the helper. + test_must_fail git push -v origin +master master:retsam >output 2>&1 && + + grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output && + grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output && + + grep "To prevent you from losing history, non-fast-forward updates were rejected" \ + output +' + +stop_httpd +test_done diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh new file mode 100755 index 0000000000..2fb48d09ed --- /dev/null +++ b/t/t5550-http-fetch.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='test dumb fetching over http via static file' +. ./test-lib.sh + +if test -n "$NO_CURL"; then + skip_all='skipping test, git built without http support' + test_done +fi + +. "$TEST_DIRECTORY"/lib-httpd.sh +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'} +start_httpd + +test_expect_success 'setup repository' ' + echo content >file && + git add file && + git commit -m one +' + +test_expect_success 'create http-accessible bare repository' ' + mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git --bare init && + echo "exec git update-server-info" >hooks/post-update && + chmod +x hooks/post-update + ) && + git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git push public master:master +' + +test_expect_success 'clone http repository' ' + git clone $HTTPD_URL/dumb/repo.git clone && + test_cmp file clone/file +' + +test_expect_success 'fetch changes via http' ' + echo content >>file && + git commit -a -m two && + git push public + (cd clone && git pull) && + test_cmp file clone/file +' + +test_expect_success 'http remote detects correct HEAD' ' + git push public master:other && + (cd clone && + git remote set-head origin -d && + git remote set-head origin -a && + git symbolic-ref refs/remotes/origin/HEAD > output && + echo refs/remotes/origin/master > expect && + test_cmp expect output + ) +' + +test_expect_success 'fetch packed objects' ' + cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git && + git --bare repack && + git --bare prune-packed + ) && + git 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 + test_cmp exp act +' + +stop_httpd +test_done diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh new file mode 100755 index 0000000000..fd19121372 --- /dev/null +++ b/t/t5551-http-fetch.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +test_description='test smart fetching over http via http-backend' +. ./test-lib.sh + +if test -n "$NO_CURL"; then + skip_all='skipping test, git built without http support' + test_done +fi + +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5551'} +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'setup repository' ' + echo content >file && + git add file && + git commit -m one +' + +test_expect_success 'create http-accessible bare repository' ' + mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git --bare init + ) && + git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git push public master:master +' + +cat >exp <<EOF +> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 +> Accept: */* +> Pragma: no-cache +< HTTP/1.1 200 OK +< Pragma: no-cache +< Cache-Control: no-cache, max-age=0, must-revalidate +< Content-Type: application/x-git-upload-pack-advertisement +> POST /smart/repo.git/git-upload-pack HTTP/1.1 +> Accept-Encoding: deflate, gzip +> Content-Type: application/x-git-upload-pack-request +> Accept: application/x-git-upload-pack-result +> Content-Length: xxx +< HTTP/1.1 200 OK +< Pragma: no-cache +< Cache-Control: no-cache, max-age=0, must-revalidate +< Content-Type: application/x-git-upload-pack-result +EOF +test_expect_success 'clone http repository' ' + GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && + test_cmp file clone/file && + tr '\''\015'\'' Q <err | + sed -e " + s/Q\$// + /^[*] /d + /^$/d + /^< $/d + + /^[^><]/{ + s/^/> / + } + + /^> User-Agent: /d + /^> Host: /d + /^> POST /,$ { + /^> Accept: [*]\\/[*]/d + } + s/^> Content-Length: .*/> Content-Length: xxx/ + /^> 00..want /d + /^> 00.*done/d + + /^< Server: /d + /^< Expires: /d + /^< Date: /d + /^< Content-Length: /d + /^< Transfer-Encoding: /d + " >act && + test_cmp exp act +' + +test_expect_success 'fetch changes via http' ' + echo content >>file && + git commit -a -m two && + git push public + (cd clone && git pull) && + test_cmp file clone/file +' + +cat >exp <<EOF +GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 +POST /smart/repo.git/git-upload-pack HTTP/1.1 200 +GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 +POST /smart/repo.git/git-upload-pack HTTP/1.1 200 +EOF +test_expect_success 'used upload-pack service' ' + sed -e " + s/^.* \"// + s/\"// + s/ [1-9][0-9]*\$// + s/^GET /GET / + " >act <"$HTTPD_ROOT_PATH"/access.log && + test_cmp exp act +' + +stop_httpd +test_done diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh new file mode 100755 index 0000000000..44885b850c --- /dev/null +++ b/t/t5560-http-backend-noserver.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='test git-http-backend-noserver' +. ./test-lib.sh + +HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY" + +run_backend() { + echo "$2" | + QUERY_STRING="${1#*\?}" \ + GIT_PROJECT_ROOT="$HTTPD_DOCUMENT_ROOT_PATH" \ + PATH_INFO="${1%%\?*}" \ + git http-backend >act.out 2>act.err +} + +GET() { + export REQUEST_METHOD="GET" && + run_backend "/repo.git/$1" && + unset REQUEST_METHOD && + if ! grep "Status" act.out >act + then + printf "Status: 200 OK\r\n" >act + fi + printf "Status: $2\r\n" >exp && + test_cmp exp act +} + +POST() { + export REQUEST_METHOD="POST" && + export CONTENT_TYPE="application/x-$1-request" && + run_backend "/repo.git/$1" "$2" && + unset REQUEST_METHOD && + unset CONTENT_TYPE && + if ! grep "Status" act.out >act + then + printf "Status: 200 OK\r\n" >act + fi + printf "Status: $3\r\n" >exp && + test_cmp exp act +} + +log_div() { + return 0 +} + +. "$TEST_DIRECTORY"/t556x_common + +expect_aliased() { + export REQUEST_METHOD="GET" && + if test $1 = 0; then + run_backend "$2" + else + run_backend "$2" && + echo "fatal: '$2': aliased" >exp.err && + test_cmp exp.err act.err + fi + unset REQUEST_METHOD +} + +test_expect_success 'http-backend blocks bad PATH_INFO' ' + config http.getanyfile true && + + expect_aliased 0 /repo.git/HEAD && + + expect_aliased 1 /repo.git/../HEAD && + expect_aliased 1 /../etc/passwd && + expect_aliased 1 ../etc/passwd && + expect_aliased 1 /etc//passwd && + expect_aliased 1 /etc/./passwd && + expect_aliased 1 //domain/data.txt +' + +test_done diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh new file mode 100755 index 0000000000..b5d7fbc381 --- /dev/null +++ b/t/t5561-http-backend.sh @@ -0,0 +1,149 @@ +#!/bin/sh + +test_description='test git-http-backend' +. ./test-lib.sh + +if test -n "$NO_CURL"; then + skip_all='skipping test, git built without http support' + test_done +fi + +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5561'} +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +GET() { + curl --include "$HTTPD_URL/$SMART/repo.git/$1" >out 2>/dev/null && + tr '\015' Q <out | + sed ' + s/Q$// + 1q + ' >act && + echo "HTTP/1.1 $2" >exp && + test_cmp exp act +} + +POST() { + curl --include --data "$2" \ + --header "Content-Type: application/x-$1-request" \ + "$HTTPD_URL/smart/repo.git/$1" >out 2>/dev/null && + tr '\015' Q <out | + sed ' + s/Q$// + 1q + ' >act && + echo "HTTP/1.1 $3" >exp && + test_cmp exp act +} + +log_div() { + echo >>"$HTTPD_ROOT_PATH"/access.log + echo "### $1" >>"$HTTPD_ROOT_PATH"/access.log + echo "###" >>"$HTTPD_ROOT_PATH"/access.log +} + +. "$TEST_DIRECTORY"/t556x_common + +cat >exp <<EOF + +### refs/heads/master +### +GET /smart/repo.git/refs/heads/master HTTP/1.1 404 - + +### getanyfile default +### +GET /smart/repo.git/HEAD HTTP/1.1 200 +GET /smart/repo.git/info/refs HTTP/1.1 200 +GET /smart/repo.git/objects/info/packs HTTP/1.1 200 +GET /smart/repo.git/objects/info/alternates HTTP/1.1 200 - +GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 200 - +GET /smart/repo.git/$LOOSE_URL HTTP/1.1 200 +GET /smart/repo.git/$PACK_URL HTTP/1.1 200 +GET /smart/repo.git/$IDX_URL HTTP/1.1 200 + +### no git-daemon-export-ok +### +GET /smart_noexport/repo.git/HEAD HTTP/1.1 404 - +GET /smart_noexport/repo.git/info/refs HTTP/1.1 404 - +GET /smart_noexport/repo.git/objects/info/packs HTTP/1.1 404 - +GET /smart_noexport/repo.git/objects/info/alternates HTTP/1.1 404 - +GET /smart_noexport/repo.git/objects/info/http-alternates HTTP/1.1 404 - +GET /smart_noexport/repo.git/$LOOSE_URL HTTP/1.1 404 - +GET /smart_noexport/repo.git/$PACK_URL HTTP/1.1 404 - +GET /smart_noexport/repo.git/$IDX_URL HTTP/1.1 404 - + +### git-daemon-export-ok +### +GET /smart_noexport/repo.git/HEAD HTTP/1.1 200 +GET /smart_noexport/repo.git/info/refs HTTP/1.1 200 +GET /smart_noexport/repo.git/objects/info/packs HTTP/1.1 200 +GET /smart_noexport/repo.git/objects/info/alternates HTTP/1.1 200 - +GET /smart_noexport/repo.git/objects/info/http-alternates HTTP/1.1 200 - +GET /smart_noexport/repo.git/$LOOSE_URL HTTP/1.1 200 +GET /smart_noexport/repo.git/$PACK_URL HTTP/1.1 200 +GET /smart_noexport/repo.git/$IDX_URL HTTP/1.1 200 + +### getanyfile true +### +GET /smart/repo.git/HEAD HTTP/1.1 200 +GET /smart/repo.git/info/refs HTTP/1.1 200 +GET /smart/repo.git/objects/info/packs HTTP/1.1 200 +GET /smart/repo.git/objects/info/alternates HTTP/1.1 200 - +GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 200 - +GET /smart/repo.git/$LOOSE_URL HTTP/1.1 200 +GET /smart/repo.git/$PACK_URL HTTP/1.1 200 +GET /smart/repo.git/$IDX_URL HTTP/1.1 200 + +### getanyfile false +### +GET /smart/repo.git/HEAD HTTP/1.1 403 - +GET /smart/repo.git/info/refs HTTP/1.1 403 - +GET /smart/repo.git/objects/info/packs HTTP/1.1 403 - +GET /smart/repo.git/objects/info/alternates HTTP/1.1 403 - +GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 403 - +GET /smart/repo.git/$LOOSE_URL HTTP/1.1 403 - +GET /smart/repo.git/$PACK_URL HTTP/1.1 403 - +GET /smart/repo.git/$IDX_URL HTTP/1.1 403 - + +### uploadpack default +### +GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 +POST /smart/repo.git/git-upload-pack HTTP/1.1 200 - + +### uploadpack true +### +GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 +POST /smart/repo.git/git-upload-pack HTTP/1.1 200 - + +### uploadpack false +### +GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 403 - +POST /smart/repo.git/git-upload-pack HTTP/1.1 403 - + +### receivepack default +### +GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 403 - +POST /smart/repo.git/git-receive-pack HTTP/1.1 403 - + +### receivepack true +### +GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 +POST /smart/repo.git/git-receive-pack HTTP/1.1 200 - + +### receivepack false +### +GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 403 - +POST /smart/repo.git/git-receive-pack HTTP/1.1 403 - +EOF +test_expect_success 'server request log matches test results' ' + sed -e " + s/^.* \"// + s/\"// + s/ [1-9][0-9]*\$// + s/^GET /GET / + " >act <"$HTTPD_ROOT_PATH"/access.log && + test_cmp exp act +' + +stop_httpd +test_done diff --git a/t/t556x_common b/t/t556x_common new file mode 100755 index 0000000000..be024e551c --- /dev/null +++ b/t/t556x_common @@ -0,0 +1,122 @@ +#!/bin/sh + +find_file() { + cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + find $1 -type f | + sed -e 1q +} + +config() { + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" config $1 $2 +} + +test_expect_success 'setup repository' ' + echo content >file && + git add file && + git commit -m one && + + mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git --bare init && + : >objects/info/alternates && + : >objects/info/http-alternates + ) && + git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git push public master:master && + + (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git repack -a -d + ) && + + echo other >file && + git add file && + git commit -m two && + git push public master:master && + + LOOSE_URL=$(find_file objects/??) && + PACK_URL=$(find_file objects/pack/*.pack) && + IDX_URL=$(find_file objects/pack/*.idx) +' + +get_static_files() { + GET HEAD "$1" && + GET info/refs "$1" && + GET objects/info/packs "$1" && + GET objects/info/alternates "$1" && + GET objects/info/http-alternates "$1" && + GET $LOOSE_URL "$1" && + GET $PACK_URL "$1" && + GET $IDX_URL "$1" +} + +SMART=smart +export GIT_HTTP_EXPORT_ALL=1 +test_expect_success 'direct refs/heads/master not found' ' + log_div "refs/heads/master" + GET refs/heads/master "404 Not Found" +' +test_expect_success 'static file is ok' ' + log_div "getanyfile default" + get_static_files "200 OK" +' +SMART=smart_noexport +unset GIT_HTTP_EXPORT_ALL +test_expect_success 'no export by default' ' + log_div "no git-daemon-export-ok" + get_static_files "404 Not Found" +' +test_expect_success 'export if git-daemon-export-ok' ' + log_div "git-daemon-export-ok" + (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + touch git-daemon-export-ok + ) && + get_static_files "200 OK" +' +SMART=smart +export GIT_HTTP_EXPORT_ALL=1 +test_expect_success 'static file if http.getanyfile true is ok' ' + log_div "getanyfile true" + config http.getanyfile true && + get_static_files "200 OK" +' +test_expect_success 'static file if http.getanyfile false fails' ' + log_div "getanyfile false" + config http.getanyfile false && + get_static_files "403 Forbidden" +' + +test_expect_success 'http.uploadpack default enabled' ' + log_div "uploadpack default" + GET info/refs?service=git-upload-pack "200 OK" && + POST git-upload-pack 0000 "200 OK" +' +test_expect_success 'http.uploadpack true' ' + log_div "uploadpack true" + config http.uploadpack true && + GET info/refs?service=git-upload-pack "200 OK" && + POST git-upload-pack 0000 "200 OK" +' +test_expect_success 'http.uploadpack false' ' + log_div "uploadpack false" + config http.uploadpack false && + GET info/refs?service=git-upload-pack "403 Forbidden" && + POST git-upload-pack 0000 "403 Forbidden" +' + +test_expect_success 'http.receivepack default disabled' ' + log_div "receivepack default" + GET info/refs?service=git-receive-pack "403 Forbidden" && + POST git-receive-pack 0000 "403 Forbidden" +' +test_expect_success 'http.receivepack true' ' + log_div "receivepack true" + config http.receivepack true && + GET info/refs?service=git-receive-pack "200 OK" && + POST git-receive-pack 0000 "200 OK" +' +test_expect_success 'http.receivepack false' ' + log_div "receivepack false" + config http.receivepack false && + GET info/refs?service=git-receive-pack "403 Forbidden" && + POST git-receive-pack 0000 "403 Forbidden" +' diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh index 1776b377f3..ee06d28649 100755 --- a/t/t5600-clone-fail-cleanup.sh +++ b/t/t5600-clone-fail-cleanup.sh @@ -3,21 +3,21 @@ # Copyright (C) 2006 Carl D. Worth <cworth@cworth.org> # -test_description='test git-clone to cleanup after failure +test_description='test git clone to cleanup after failure -This test covers the fact that if git-clone fails, it should remove +This test covers the fact that if git clone fails, it should remove the directory it created, to avoid the user having to manually remove the directory before attempting a clone again.' . ./test-lib.sh -test_expect_failure \ +test_expect_success \ 'clone of non-existent source should fail' \ - 'git-clone foo bar' + 'test_must_fail git clone foo bar' -test_expect_failure \ +test_expect_success \ 'failed clone should not leave a directory' \ - 'cd bar' + '! test -d bar' # Need a repo to clone test_create_repo foo @@ -25,15 +25,15 @@ test_create_repo foo # clone doesn't like it if there is no HEAD. Is that a bug? (cd foo && touch file && git add file && git commit -m 'add file' >/dev/null 2>&1) -# source repository given to git-clone should be relative to the +# source repository given to git clone should be relative to the # current path not to the target dir -test_expect_failure \ +test_expect_success \ 'clone of non-existent (relative to $PWD) source should fail' \ - 'git-clone ../foo baz' + 'test_must_fail git clone ../foo baz' test_expect_success \ 'clone should work now that source exists' \ - 'git-clone foo bar' + 'git clone foo bar' test_expect_success \ 'successful clone must leave the directory' \ diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh new file mode 100755 index 0000000000..8abb71afcd --- /dev/null +++ b/t/t5601-clone.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +test_description=clone + +. ./test-lib.sh + +test_expect_success setup ' + + rm -fr .git && + test_create_repo src && + ( + cd src + >file + git add file + git commit -m initial + ) + +' + +test_expect_success 'clone with excess parameters (1)' ' + + rm -fr dst && + test_must_fail git clone -n src dst junk + +' + +test_expect_success 'clone with excess parameters (2)' ' + + rm -fr dst && + test_must_fail git clone -n "file://$(pwd)/src" dst junk + +' + +test_expect_success 'output from clone' ' + rm -fr dst && + git clone -n "file://$(pwd)/src" dst >output && + test $(grep Clon output | wc -l) = 1 +' + +test_expect_success 'clone does not keep pack' ' + + rm -fr dst && + git clone -n "file://$(pwd)/src" dst && + ! test -f dst/file && + ! (echo dst/.git/objects/pack/pack-* | grep "\.keep") + +' + +test_expect_success 'clone checks out files' ' + + rm -fr dst && + git clone src dst && + test -f dst/file + +' + +test_expect_success 'clone respects GIT_WORK_TREE' ' + + GIT_WORK_TREE=worktree git clone src bare && + test -f bare/config && + test -f worktree/file + +' + +test_expect_success 'clone creates intermediate directories' ' + + git clone src long/path/to/dst && + test -f long/path/to/dst/file + +' + +test_expect_success 'clone creates intermediate directories for bare repo' ' + + git clone --bare src long/path/to/bare/dst && + test -f long/path/to/bare/dst/config + +' + +test_expect_success 'clone --mirror' ' + + git clone --mirror src mirror && + test -f mirror/HEAD && + test ! -f mirror/file && + FETCH="$(cd mirror && git config remote.origin.fetch)" && + test "+refs/*:refs/*" = "$FETCH" && + MIRROR="$(cd mirror && git config --bool remote.origin.mirror)" && + test "$MIRROR" = true + +' + +test_expect_success 'clone --bare names the local repository <name>.git' ' + + git clone --bare src && + test -d src.git + +' + +test_expect_success 'clone --mirror does not repeat tags' ' + + (cd src && + git tag some-tag HEAD) && + git clone --mirror src mirror2 && + (cd mirror2 && + git show-ref 2> clone.err > clone.out) && + test_must_fail grep Duplicate mirror2/clone.err && + grep some-tag mirror2/clone.out + +' + +test_expect_success 'clone to destination with trailing /' ' + + git clone src target-1/ && + T=$( cd target-1 && git rev-parse HEAD ) && + S=$( cd src && git rev-parse HEAD ) && + test "$T" = "$S" + +' + +test_expect_success 'clone to destination with extra trailing /' ' + + git clone src target-2/// && + T=$( cd target-2 && git rev-parse HEAD ) && + S=$( cd src && git rev-parse HEAD ) && + test "$T" = "$S" + +' + +test_expect_success 'clone to an existing empty directory' ' + mkdir target-3 && + git clone src target-3 && + T=$( cd target-3 && git rev-parse HEAD ) && + S=$( cd src && git rev-parse HEAD ) && + test "$T" = "$S" +' + +test_expect_success 'clone to an existing non-empty directory' ' + mkdir target-4 && + >target-4/Fakefile && + test_must_fail git clone src target-4 +' + +test_expect_success 'clone to an existing path' ' + >target-5 && + test_must_fail git clone src target-5 +' + +test_expect_success 'clone a void' ' + mkdir src-0 && + ( + cd src-0 && git init + ) && + git clone "file://$(pwd)/src-0" target-6 2>err-6 && + ! grep "fatal:" err-6 && + ( + cd src-0 && test_commit A + ) && + git clone "file://$(pwd)/src-0" target-7 2>err-7 && + ! grep "fatal:" err-7 && + # There is no reason to insist they are bit-for-bit + # identical, but this test should suffice for now. + test_cmp target-6/.git/config target-7/.git/config +' + +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 && + rm -fr dst && + git clone src dst && + cd dst && + actual="z$(git config branch.master.rebase)" && + test ztrue = $actual + ) +' + +test_expect_success 'respect url-encoding of file://' ' + git init x+y && + test_must_fail git clone "file://$PWD/x+y" xy-url && + git clone "file://$PWD/x%2By" xy-url +' + +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/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh new file mode 100755 index 0000000000..deffdaee49 --- /dev/null +++ b/t/t5602-clone-remote-exec.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description=clone + +. ./test-lib.sh + +test_expect_success setup ' + echo "#!/bin/sh" > not_ssh + echo "echo \"\$*\" > not_ssh_output" >> not_ssh + echo "exit 1" >> not_ssh + chmod +x not_ssh +' + +test_expect_success 'clone calls git upload-pack unqualified with no -u option' ' + GIT_SSH=./not_ssh git clone localhost:/path/to/repo junk + echo "localhost git-upload-pack '\''/path/to/repo'\''" >expected + test_cmp expected not_ssh_output +' + +test_expect_success 'clone calls specified git upload-pack with -u option' ' + GIT_SSH=./not_ssh git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk + echo "localhost ./something/bin/git-upload-pack '\''/path/to/repo'\''" >expected + test_cmp expected not_ssh_output +' + +test_done diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index 6d43252593..895f5595ae 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -8,6 +8,8 @@ test_description='test clone --reference' base_dir=`pwd` +U=$base_dir/UPLOAD_LOG + test_expect_success 'preparing first repository' \ 'test_create_repo A && cd A && echo first > file1 && @@ -38,7 +40,7 @@ cd "$base_dir" test_expect_success 'pulling from reference' \ 'cd C && -git pull ../B' +git pull ../B master' cd "$base_dir" @@ -46,12 +48,17 @@ 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" +rm -f "$U" + test_expect_success 'cloning with reference (no -l -s)' \ -'git clone --reference B A D' +'GIT_DEBUG_SEND_PACK=3 git clone --reference B "file://$(pwd)/A" D 3>"$U"' + +test_expect_success 'fetched no objects' \ +'! grep "^want" "$U"' cd "$base_dir" @@ -61,14 +68,14 @@ test_expect_success 'existence of info/alternates' \ cd "$base_dir" test_expect_success 'pulling from reference' \ -'cd D && git pull ../B' +'cd D && git pull ../B master' 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" @@ -93,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" @@ -109,7 +116,33 @@ 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" + +test_expect_success 'preparing alternate repository #1' \ +'test_create_repo F && cd F && +echo first > file1 && +git add file1 && +git commit -m initial' + +cd "$base_dir" + +test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' \ +'git clone F G && cd F && +echo second > file2 && +git add file2 && +git commit -m addition' + +cd "$base_dir" + +test_expect_success 'cloning alternate repo #1, using #2 as reference' \ +'git clone --reference G F H' + +cd "$base_dir" + +test_expect_success 'cloning with reference being subset of source (-l -s)' \ +'git clone -l -s --reference A B E' cd "$base_dir" diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh new file mode 100755 index 0000000000..8b4c356cd2 --- /dev/null +++ b/t/t5701-clone-local.sh @@ -0,0 +1,147 @@ +#!/bin/sh + +test_description='test local clone' +. ./test-lib.sh + +D=`pwd` + +test_expect_success 'preparing origin repository' ' + : >file && git add . && git commit -m1 && + git clone --bare . a.git && + git clone --bare . x && + test "$(GIT_CONFIG=a.git/config git config --bool core.bare)" = true && + test "$(GIT_CONFIG=x/config git config --bool core.bare)" = true + git bundle create b1.bundle --all && + git bundle create b2.bundle master && + mkdir dir && + cp b1.bundle dir/b3 + cp b1.bundle b4 +' + +test_expect_success 'local clone without .git suffix' ' + cd "$D" && + git clone -l -s a b && + cd b && + test "$(GIT_CONFIG=.git/config git config --bool core.bare)" = false && + git fetch +' + +test_expect_success 'local clone with .git suffix' ' + cd "$D" && + git clone -l -s a.git c && + cd c && + git fetch +' + +test_expect_success 'local clone from x' ' + cd "$D" && + git clone -l -s x y && + cd y && + git fetch +' + +test_expect_success 'local clone from x.git that does not exist' ' + cd "$D" && + if git clone -l -s x.git z + then + echo "Oops, should have failed" + false + else + echo happy + fi +' + +test_expect_success 'With -no-hardlinks, local will make a copy' ' + cd "$D" && + git clone --bare --no-hardlinks x w && + cd w && + linked=$(find objects -type f ! -links 1 | wc -l) && + test 0 = $linked +' + +test_expect_success 'Even without -l, local will make a hardlink' ' + cd "$D" && + rm -fr w && + git clone -l --bare x w && + cd w && + copied=$(find objects -type f -links 1 | wc -l) && + test 0 = $copied +' + +test_expect_success 'local clone of repo with nonexistent ref in HEAD' ' + cd "$D" && + echo "ref: refs/heads/nonexistent" > a.git/HEAD && + git clone a d && + cd d && + git fetch && + test ! -e .git/refs/remotes/origin/HEAD' + +test_expect_success 'bundle clone without .bundle suffix' ' + cd "$D" && + git clone dir/b3 && + cd b3 && + git fetch +' + +test_expect_success 'bundle clone with .bundle suffix' ' + cd "$D" && + git clone b1.bundle && + cd b1 && + git fetch +' + +test_expect_success 'bundle clone from b4' ' + cd "$D" && + git clone b4 bdl && + cd bdl && + git fetch +' + +test_expect_success 'bundle clone from b4.bundle that does not exist' ' + cd "$D" && + if git clone b4.bundle bb + then + echo "Oops, should have failed" + false + else + echo happy + fi +' + +test_expect_success 'bundle clone with nonexistent HEAD' ' + cd "$D" && + git clone b2.bundle b2 && + cd b2 && + git fetch + test ! -e .git/refs/heads/master +' + +test_expect_success 'clone empty repository' ' + cd "$D" && + mkdir empty && + (cd empty && + git init && + git config receive.denyCurrentBranch warn) && + git clone empty empty-clone && + test_tick && + (cd empty-clone + echo "content" >> foo && + git add foo && + git commit -m "Initial commit" && + git push origin master && + expected=$(git rev-parse master) && + actual=$(git --git-dir=../empty/.git rev-parse master) && + test $actual = $expected) +' + +test_expect_success 'clone empty repository, and then push should not segfault.' ' + cd "$D" && + rm -fr empty/ empty-clone/ && + mkdir empty && + (cd empty && git init) && + git clone empty empty-clone && + (cd empty-clone && + test_must_fail git push) +' + +test_done diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh new file mode 100755 index 0000000000..02cb024723 --- /dev/null +++ b/t/t5702-clone-options.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +test_description='basic clone options' +. ./test-lib.sh + +test_expect_success 'setup' ' + + mkdir parent && + (cd parent && git init && + echo one >file && git add file && + git commit -m one) + +' + +test_expect_success 'clone -o' ' + + git clone -o foo parent clone-o && + (cd clone-o && git rev-parse --verify refs/remotes/foo/master) + +' + +test_expect_success 'redirected clone' ' + + git clone "file://$(pwd)/parent" clone-redirected >out 2>err && + test ! -s err + +' +test_expect_success 'redirected clone -v' ' + + git clone --progress "file://$(pwd)/parent" clone-redirected-progress \ + >out 2>err && + test -s err + +' + +test_done diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh new file mode 100755 index 0000000000..ddc3dc52f4 --- /dev/null +++ b/t/t5704-bundle.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='some bundle related tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + + : > file && + git add file && + test_tick && + git commit -m initial && + test_tick && + git tag -m tag tag && + : > file2 && + git add file2 && + : > file3 && + test_tick && + git commit -m second && + git add file3 && + test_tick && + git commit -m third + +' + +test_expect_success 'tags can be excluded by rev-list options' ' + + git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 && + git ls-remote bundle > output && + ! grep tag output + +' + +test_expect_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 new file mode 100755 index 0000000000..e4d1b6a0fa --- /dev/null +++ b/t/t5705-clone-2gb.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +test_description='Test cloning a repository larger than 2 gigabyte' +. ./test-lib.sh + +test -z "$GIT_TEST_CLONE_2GB" && +skip_all="Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" && +test_done && +exit + +test_expect_success 'setup' ' + + git config pack.compression 0 && + git config pack.depth 0 && + blobsize=$((100*1024*1024)) && + blobcount=$((2*1024*1024*1024/$blobsize+1)) && + i=1 && + (while test $i -le $blobcount + do + printf "Generating blob $i/$blobcount\r" >&2 && + printf "blob\nmark :$i\ndata $blobsize\n" && + #test-genrandom $i $blobsize && + printf "%-${blobsize}s" $i && + echo "M 100644 :$i $i" >> commit + i=$(($i+1)) || + echo $? > exit-status + done && + echo "commit refs/heads/master" && + echo "author A U Thor <author@email.com> 123456789 +0000" && + echo "committer C O Mitter <committer@email.com> 123456789 +0000" && + echo "data 5" && + echo ">2gb" && + cat commit) | + git fast-import --big-file-threshold=2 && + test ! -f exit-status + +' + +test_expect_success 'clone - bare' ' + + git clone --bare --no-hardlinks . clone-bare + +' + +test_expect_success 'clone - with worktree, file:// protocol' ' + + git clone file://. clone-wt + +' + +test_done diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh new file mode 100755 index 0000000000..f3f9a76056 --- /dev/null +++ b/t/t5706-clone-branch.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +test_description='clone --branch option' +. ./test-lib.sh + +check_HEAD() { + echo refs/heads/"$1" >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual +} + +check_file() { + echo "$1" >expect && + test_cmp expect file +} + +test_expect_success 'setup' ' + mkdir parent && + (cd parent && git init && + echo one >file && git add file && git commit -m one && + git checkout -b two && + echo two >file && git add file && git commit -m two && + git checkout master) +' + +test_expect_success 'vanilla clone chooses HEAD' ' + git clone parent clone && + (cd clone && + check_HEAD master && + check_file one + ) +' + +test_expect_success 'clone -b chooses specified branch' ' + git clone -b two parent clone-two && + (cd clone-two && + check_HEAD two && + check_file two + ) +' + +test_expect_success 'clone -b sets up tracking' ' + (cd clone-two && + echo origin >expect && + git config branch.two.remote >actual && + echo refs/heads/two >>expect && + git config branch.two.merge >>actual && + test_cmp expect actual + ) +' + +test_expect_success 'clone -b does not munge remotes/origin/HEAD' ' + (cd clone-two && + echo refs/remotes/origin/master >expect && + git symbolic-ref refs/remotes/origin/HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'clone -b with bogus branch chooses HEAD' ' + git clone -b bogus parent clone-bogus && + (cd clone-bogus && + check_HEAD master && + check_file one + ) +' + +test_done diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh index 2f8e97cb7e..ef7127c1b3 100755 --- a/t/t5710-info-alternate.sh +++ b/t/t5710-info-alternate.sh @@ -53,14 +53,18 @@ git prune' cd "$base_dir" -test_expect_failure 'creating too deep nesting' \ +test_expect_success 'creating too deep nesting' \ 'git clone -l -s C D && git clone -l -s D E && git clone -l -s E F && git clone -l -s F G && -git clone -l -s G H && -cd H && -test_valid_repo' +git clone -l -s G H' + +test_expect_success 'invalidity of deepest repository' \ +'cd H && { + test_valid_repo + test $? -ne 0 +}' cd "$base_dir" @@ -77,16 +81,16 @@ test_valid_repo' cd "$base_dir" test_expect_success 'breaking of loops' \ -"echo '$base_dir/B/.git/objects' >> '$base_dir'/A/.git/objects/info/alternates&& +'echo "$base_dir"/B/.git/objects >> "$base_dir"/A/.git/objects/info/alternates&& cd C && -test_valid_repo" +test_valid_repo' cd "$base_dir" -test_expect_failure 'that info/alternates is necessary' \ +test_expect_success 'that info/alternates is necessary' \ 'cd C && -rm .git/objects/info/alternates && -test_valid_repo' +rm -f .git/objects/info/alternates && +! (test_valid_repo)' cd "$base_dir" @@ -97,11 +101,12 @@ test_valid_repo' cd "$base_dir" -test_expect_failure 'that relative alternate is only possible for current dir' \ -'cd D && -test_valid_repo' +test_expect_success \ + 'that relative alternate is only possible for current dir' ' + cd D && + ! (test_valid_repo) +' cd "$base_dir" test_done - diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh new file mode 100755 index 0000000000..637d8e97ac --- /dev/null +++ b/t/t5800-remote-helpers.sh @@ -0,0 +1,82 @@ +#!/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 + : +else + skip_all='skipping git remote-testgit tests: requires Python 2.4 or newer' + test_done +fi + +test_expect_success '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 'cloning from local repo' ' + git clone "testgit::${PWD}/server" localclone && + test_cmp public/file localclone/file +' + +test_expect_success 'cloning from remote repo' ' + git clone "testgit::file://${PWD}/server" clone && + test_cmp public/file clone/file +' + +test_expect_success 'create new commit on remote' ' + (cd public && + echo content >>file && + git commit -a -m two && + git push) +' + +test_expect_success 'pulling from local repo' ' + (cd localclone && git pull) && + test_cmp public/file localclone/file +' + +test_expect_success 'pulling from remote remote' ' + (cd clone && git pull) && + test_cmp public/file clone/file +' + +test_expect_success 'pushing to local repo' ' + (cd localclone && + echo content >>file && + git commit -a -m three && + git push) && + HEAD=$(git --git-dir=localclone/.git rev-parse --verify HEAD) && + test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) +' + +test_expect_success 'synch with changes from localclone' ' + (cd clone && + git pull) +' + +test_expect_success 'pushing remote local repo' ' + (cd clone && + echo content >>file && + git commit -a -m four && + git push) && + HEAD=$(git --git-dir=clone/.git rev-parse --verify HEAD) && + test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD) +' + +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 7831e3461c..fb07536a0f 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -2,10 +2,10 @@ # # Copyright (c) 2005 Jon Seymour # -test_description='Tests git-rev-list --bisect functionality' +test_description='Tests git rev-list --bisect functionality' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions # usage: test_bisection max-diff bisect-option head ^prune... # @@ -16,17 +16,17 @@ test_bisection_diff() _max_diff=$1 _bisect_option=$2 shift 2 - _bisection=$(git-rev-list $_bisect_option "$@") - _list_size=$(git-rev-list "$@" | wc -l) + _bisection=$(git rev-list $_bisect_option "$@") + _list_size=$(git rev-list "$@" | wc -l) _head=$1 shift 1 - _bisection_size=$(git-rev-list $_bisection "$@" | wc -l) + _bisection_size=$(git rev-list $_bisection "$@" | wc -l) [ -n "$_list_size" -a -n "$_bisection_size" ] || error "test_bisection_diff failed" # Test if bisection size is close to half of list size within # tolerance. - # + # _bisect_err=`expr $_list_size - $_bisection_size \* 2` test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err` _bisect_err=`expr $_bisect_err / 2` ; # floor @@ -37,8 +37,8 @@ test_bisection_diff() } date >path0 -git-update-index --add path0 -save_tag tree git-write-tree +git update-index --add path0 +save_tag tree git write-tree on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0 @@ -58,7 +58,7 @@ on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4 on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3 on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4 -git-update-ref HEAD $(tag l5) +git update-ref HEAD $(tag l5) # E @@ -116,8 +116,8 @@ on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p test_sequence() { - _bisect_option=$1 - + _bisect_option=$1 + test_bisection_diff 0 $_bisect_option l0 ^root test_bisection_diff 0 $_bisect_option l1 ^root test_bisection_diff 0 $_bisect_option l2 ^root @@ -152,7 +152,7 @@ test_sequence() test_bisection_diff 0 $_bisect_option u3 ^U test_bisection_diff 0 $_bisect_option u4 ^U test_bisection_diff 0 $_bisect_option u5 ^U - + # # the following illustrates Linus' binary bug blatt idea. # @@ -163,23 +163,23 @@ test_sequence() # the bisection point is the head - this is the bad point. # -test_output_expect_success "--bisect l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF +test_output_expect_success "$_bisect_option l5 ^root" 'git rev-list $_bisect_option l5 ^root' <<EOF c3 EOF -test_output_expect_success "$_bisect_option l5 ^root ^c3" 'git-rev-list $_bisect_option l5 ^root ^c3' <<EOF +test_output_expect_success "$_bisect_option l5 ^root ^c3" 'git rev-list $_bisect_option l5 ^root ^c3' <<EOF b4 EOF -test_output_expect_success "$_bisect_option l5 ^root ^c3 ^b4" 'git-rev-list $_bisect_option l5 ^c3 ^b4' <<EOF +test_output_expect_success "$_bisect_option l5 ^root ^c3 ^b4" 'git rev-list $_bisect_option l5 ^c3 ^b4' <<EOF l3 EOF -test_output_expect_success "$_bisect_option l3 ^root ^c3 ^b4" 'git-rev-list $_bisect_option l3 ^root ^c3 ^b4' <<EOF +test_output_expect_success "$_bisect_option l3 ^root ^c3 ^b4" 'git rev-list $_bisect_option l3 ^root ^c3 ^b4' <<EOF a4 EOF -test_output_expect_success "$_bisect_option l5 ^b3 ^a3 ^b4 ^a4" 'git-rev-list $_bisect_option l3 ^b3 ^a3 ^a4' <<EOF +test_output_expect_success "$_bisect_option l5 ^b3 ^a3 ^b4 ^a4" 'git rev-list $_bisect_option l3 ^b3 ^a3 ^a4' <<EOF l3 EOF @@ -187,11 +187,11 @@ EOF # if l3 is bad, then l4 is bad too - so advance the bad pointer by making b4 the known bad head # -test_output_expect_success "$_bisect_option l4 ^a2 ^a3 ^b ^a4" 'git-rev-list $_bisect_option l4 ^a2 ^a3 ^a4' <<EOF +test_output_expect_success "$_bisect_option l4 ^a2 ^a3 ^b ^a4" 'git rev-list $_bisect_option l4 ^a2 ^a3 ^a4' <<EOF l3 EOF -test_output_expect_success "$_bisect_option l3 ^a2 ^a3 ^b ^a4" 'git-rev-list $_bisect_option l3 ^a2 ^a3 ^a4' <<EOF +test_output_expect_success "$_bisect_option l3 ^a2 ^a3 ^b ^a4" 'git rev-list $_bisect_option l3 ^a2 ^a3 ^a4' <<EOF l3 EOF @@ -201,15 +201,15 @@ EOF # as another example, let's consider a4 to be the bad head, in which case # -test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF c2 EOF -test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2' <<EOF +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2" 'git rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2' <<EOF c3 EOF -test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3' <<EOF +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3" 'git rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3' <<EOF a4 EOF @@ -219,11 +219,11 @@ EOF # or consider c3 to be the bad head # -test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF c2 EOF -test_output_expect_success "$_bisect_option c3 ^a2 ^a3 ^b4 ^c2" 'git-rev-list $_bisect_option c3 ^a2 ^a3 ^b4 ^c2' <<EOF +test_output_expect_success "$_bisect_option c3 ^a2 ^a3 ^b4 ^c2" 'git rev-list $_bisect_option c3 ^a2 ^a3 ^b4 ^c2' <<EOF c3 EOF diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh index d99a9ad39e..e4c52b0214 100755 --- a/t/t6003-rev-list-topo-order.sh +++ b/t/t6003-rev-list-topo-order.sh @@ -3,10 +3,10 @@ # Copyright (c) 2005 Jon Seymour # -test_description='Tests git-rev-list --topo-order functionality' +test_description='Tests git rev-list --topo-order functionality' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions list_duplicates() { @@ -14,8 +14,8 @@ list_duplicates() } date >path0 -git-update-index --add path0 -save_tag tree git-write-tree +git update-index --add path0 +save_tag tree git write-tree on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0 @@ -77,13 +77,13 @@ save_tag h2 unique_commit g4 tree -p g2 save_tag g3 unique_commit g5 tree -p g2 save_tag g4 unique_commit g6 tree -p g3 -p h2 -git-update-ref HEAD $(tag l5) +git update-ref HEAD $(tag l5) -test_output_expect_success 'rev-list has correct number of entries' 'git-rev-list HEAD | wc -l | tr -d \" \"' <<EOF +test_output_expect_success 'rev-list has correct number of entries' 'git rev-list HEAD | wc -l | tr -d \" \"' <<EOF 19 EOF -test_output_expect_success 'simple topo order' 'git-rev-list --topo-order HEAD' <<EOF +test_output_expect_success 'simple topo order' 'git rev-list --topo-order HEAD' <<EOF l5 l4 l3 @@ -105,7 +105,7 @@ l0 root EOF -test_output_expect_success 'two diamonds topo order (g6)' 'git-rev-list --topo-order g4' <<EOF +test_output_expect_success 'two diamonds topo order (g6)' 'git rev-list --topo-order g4' <<EOF g4 h2 g3 @@ -115,7 +115,7 @@ g1 g0 EOF -test_output_expect_success 'multiple heads' 'git-rev-list --topo-order a3 b3 c3' <<EOF +test_output_expect_success 'multiple heads' 'git rev-list --topo-order a3 b3 c3' <<EOF a3 a2 a1 @@ -132,7 +132,7 @@ l0 root EOF -test_output_expect_success 'multiple heads, prune at a1' 'git-rev-list --topo-order a3 b3 c3 ^a1' <<EOF +test_output_expect_success 'multiple heads, prune at a1' 'git rev-list --topo-order a3 b3 c3 ^a1' <<EOF a3 a2 c3 @@ -143,7 +143,7 @@ b2 b1 EOF -test_output_expect_success 'multiple heads, prune at l1' 'git-rev-list --topo-order a3 b3 c3 ^l1' <<EOF +test_output_expect_success 'multiple heads, prune at l1' 'git rev-list --topo-order a3 b3 c3 ^l1' <<EOF a3 a2 a1 @@ -157,7 +157,7 @@ a0 l2 EOF -test_output_expect_success 'cross-epoch, head at l5, prune at l1' 'git-rev-list --topo-order l5 ^l1' <<EOF +test_output_expect_success 'cross-epoch, head at l5, prune at l1' 'git rev-list --topo-order l5 ^l1' <<EOF l5 l4 l3 @@ -176,7 +176,7 @@ a0 l2 EOF -test_output_expect_success 'duplicated head arguments' 'git-rev-list --topo-order l5 l5 ^l1' <<EOF +test_output_expect_success 'duplicated head arguments' 'git rev-list --topo-order l5 l5 ^l1' <<EOF l5 l4 l3 @@ -195,7 +195,7 @@ a0 l2 EOF -test_output_expect_success 'prune near topo' 'git-rev-list --topo-order a4 ^c3' <<EOF +test_output_expect_success 'prune near topo' 'git rev-list --topo-order a4 ^c3' <<EOF a4 b4 a3 @@ -204,52 +204,52 @@ a1 b3 EOF -test_output_expect_success "head has no parent" 'git-rev-list --topo-order root' <<EOF +test_output_expect_success "head has no parent" 'git rev-list --topo-order root' <<EOF root EOF -test_output_expect_success "two nodes - one head, one base" 'git-rev-list --topo-order l0' <<EOF +test_output_expect_success "two nodes - one head, one base" 'git rev-list --topo-order l0' <<EOF l0 root EOF -test_output_expect_success "three nodes one head, one internal, one base" 'git-rev-list --topo-order l1' <<EOF +test_output_expect_success "three nodes one head, one internal, one base" 'git rev-list --topo-order l1' <<EOF l1 l0 root EOF -test_output_expect_success "linear prune l2 ^root" 'git-rev-list --topo-order l2 ^root' <<EOF +test_output_expect_success "linear prune l2 ^root" 'git rev-list --topo-order l2 ^root' <<EOF l2 l1 l0 EOF -test_output_expect_success "linear prune l2 ^l0" 'git-rev-list --topo-order l2 ^l0' <<EOF +test_output_expect_success "linear prune l2 ^l0" 'git rev-list --topo-order l2 ^l0' <<EOF l2 l1 EOF -test_output_expect_success "linear prune l2 ^l1" 'git-rev-list --topo-order l2 ^l1' <<EOF +test_output_expect_success "linear prune l2 ^l1" 'git rev-list --topo-order l2 ^l1' <<EOF l2 EOF -test_output_expect_success "linear prune l5 ^a4" 'git-rev-list --topo-order l5 ^a4' <<EOF +test_output_expect_success "linear prune l5 ^a4" 'git rev-list --topo-order l5 ^a4' <<EOF l5 l4 l3 EOF -test_output_expect_success "linear prune l5 ^l3" 'git-rev-list --topo-order l5 ^l3' <<EOF +test_output_expect_success "linear prune l5 ^l3" 'git rev-list --topo-order l5 ^l3' <<EOF l5 l4 EOF -test_output_expect_success "linear prune l5 ^l4" 'git-rev-list --topo-order l5 ^l4' <<EOF +test_output_expect_success "linear prune l5 ^l4" 'git rev-list --topo-order l5 ^l4' <<EOF l5 EOF -test_output_expect_success "max-count 10 - topo order" 'git-rev-list --topo-order --max-count=10 l5' <<EOF +test_output_expect_success "max-count 10 - topo order" 'git rev-list --topo-order --max-count=10 l5' <<EOF l5 l4 l3 @@ -262,7 +262,7 @@ a3 a2 EOF -test_output_expect_success "max-count 10 - non topo order" 'git-rev-list --max-count=10 l5' <<EOF +test_output_expect_success "max-count 10 - non topo order" 'git rev-list --max-count=10 l5' <<EOF l5 l4 l3 @@ -275,7 +275,7 @@ c2 b3 EOF -test_output_expect_success '--max-age=c3, no --topo-order' "git-rev-list --max-age=$(commit_date c3) l5" <<EOF +test_output_expect_success '--max-age=c3, no --topo-order' "git rev-list --max-age=$(commit_date c3) l5" <<EOF l5 l4 l3 @@ -289,7 +289,7 @@ EOF # # this test fails on --topo-order - a fix is required # -#test_output_expect_success '--max-age=c3, --topo-order' "git-rev-list --topo-order --max-age=$(commit_date c3) l5" <<EOF +#test_output_expect_success '--max-age=c3, --topo-order' "git rev-list --topo-order --max-age=$(commit_date c3) l5" <<EOF #l5 #l4 #l3 @@ -300,31 +300,31 @@ EOF #a2 #EOF -test_output_expect_success 'one specified head reachable from another a4, c3, --topo-order' "list_duplicates git-rev-list --topo-order a4 c3" <<EOF +test_output_expect_success 'one specified head reachable from another a4, c3, --topo-order' "list_duplicates git rev-list --topo-order a4 c3" <<EOF EOF -test_output_expect_success 'one specified head reachable from another c3, a4, --topo-order' "list_duplicates git-rev-list --topo-order c3 a4" <<EOF +test_output_expect_success 'one specified head reachable from another c3, a4, --topo-order' "list_duplicates git rev-list --topo-order c3 a4" <<EOF EOF -test_output_expect_success 'one specified head reachable from another a4, c3, no --topo-order' "list_duplicates git-rev-list a4 c3" <<EOF +test_output_expect_success 'one specified head reachable from another a4, c3, no --topo-order' "list_duplicates git rev-list a4 c3" <<EOF EOF -test_output_expect_success 'one specified head reachable from another c3, a4, no --topo-order' "list_duplicates git-rev-list c3 a4" <<EOF +test_output_expect_success 'one specified head reachable from another c3, a4, no --topo-order' "list_duplicates git rev-list c3 a4" <<EOF EOF -test_output_expect_success 'graph with c3 and a4 parents of head' "list_duplicates git-rev-list m1" <<EOF +test_output_expect_success 'graph with c3 and a4 parents of head' "list_duplicates git rev-list m1" <<EOF EOF -test_output_expect_success 'graph with a4 and c3 parents of head' "list_duplicates git-rev-list m2" <<EOF +test_output_expect_success 'graph with a4 and c3 parents of head' "list_duplicates git rev-list m2" <<EOF EOF -test_expect_success "head ^head --topo-order" 'git-rev-list --topo-order a3 ^a3' <<EOF +test_expect_success "head ^head --topo-order" 'git rev-list --topo-order a3 ^a3' <<EOF EOF -test_expect_success "head ^head no --topo-order" 'git-rev-list a3 ^a3' <<EOF +test_expect_success "head ^head no --topo-order" 'git rev-list a3 ^a3' <<EOF EOF -test_output_expect_success 'simple topo order (l5r1)' 'git-rev-list --topo-order l5r1' <<EOF +test_output_expect_success 'simple topo order (l5r1)' 'git rev-list --topo-order l5r1' <<EOF l5r1 r1 r0 @@ -350,7 +350,7 @@ l0 root EOF -test_output_expect_success 'simple topo order (r1l5)' 'git-rev-list --topo-order r1l5' <<EOF +test_output_expect_success 'simple topo order (r1l5)' 'git rev-list --topo-order r1l5' <<EOF r1l5 l5 l4 @@ -376,13 +376,13 @@ r0 alt_root EOF -test_output_expect_success "don't print things unreachable from one branch" "git-rev-list a3 ^b3 --topo-order" <<EOF +test_output_expect_success "don't print things unreachable from one branch" "git rev-list a3 ^b3 --topo-order" <<EOF a3 a2 a1 EOF -test_output_expect_success "--topo-order a4 l3" "git-rev-list --topo-order a4 l3" <<EOF +test_output_expect_success "--topo-order a4 l3" "git rev-list --topo-order a4 l3" <<EOF l3 a4 c3 diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh index 5182dbb158..5dabf1c5e3 100755 --- a/t/t6004-rev-list-path-optim.sh +++ b/t/t6004-rev-list-path-optim.sh @@ -1,19 +1,51 @@ #!/bin/sh -test_description='git-rev-list trivial path optimization test' +test_description='git rev-list trivial path optimization test' . ./test-lib.sh test_expect_success setup ' echo Hello > a && git add a && -git commit -m "Initial commit" a +git commit -m "Initial commit" a && +initial=$(git rev-parse --verify HEAD) ' test_expect_success path-optimization ' - commit=$(echo "Unchanged tree" | git-commit-tree "HEAD^{tree}" -p HEAD) && - test $(git-rev-list $commit | wc -l) = 2 && - test $(git-rev-list $commit -- . | wc -l) = 1 + commit=$(echo "Unchanged tree" | git commit-tree "HEAD^{tree}" -p HEAD) && + test $(git rev-list $commit | wc -l) = 2 && + test $(git rev-list $commit -- . | wc -l) = 1 +' + +test_expect_success 'further setup' ' + git checkout -b side && + echo Irrelevant >c && + git add c && + git commit -m "Side makes an irrelevant commit" && + echo "More Irrelevancy" >c && + git add c && + git commit -m "Side makes another irrelevant commit" && + echo Bye >a && + git add a && + git commit -m "Side touches a" && + side=$(git rev-parse --verify HEAD) && + echo "Yet more Irrelevancy" >c && + git add c && + git commit -m "Side makes yet another irrelevant commit" && + git checkout master && + echo Another >b && + git add b && + git commit -m "Master touches b" && + git merge side && + echo Touched >b && + git add b && + git commit -m "Master touches b again" +' + +test_expect_success 'path optimization 2' ' + ( echo "$side"; echo "$initial" ) >expected && + git rev-list HEAD -- a >actual && + test_cmp expected actual ' test_done diff --git a/t/t6005-rev-list-count.sh b/t/t6005-rev-list-count.sh index 334fccf58c..0b64822bf6 100755 --- a/t/t6005-rev-list-count.sh +++ b/t/t6005-rev-list-count.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-rev-list --max-count and --skip test' +test_description='git rev-list --max-count and --skip test' . ./test-lib.sh @@ -13,39 +13,39 @@ test_expect_success 'setup' ' ' test_expect_success 'no options' ' - test $(git-rev-list HEAD | wc -l) = 5 + test $(git rev-list HEAD | wc -l) = 5 ' test_expect_success '--max-count' ' - test $(git-rev-list HEAD --max-count=0 | wc -l) = 0 && - test $(git-rev-list HEAD --max-count=3 | wc -l) = 3 && - test $(git-rev-list HEAD --max-count=5 | wc -l) = 5 && - test $(git-rev-list HEAD --max-count=10 | wc -l) = 5 + test $(git rev-list HEAD --max-count=0 | wc -l) = 0 && + test $(git rev-list HEAD --max-count=3 | wc -l) = 3 && + test $(git rev-list HEAD --max-count=5 | wc -l) = 5 && + test $(git rev-list HEAD --max-count=10 | wc -l) = 5 ' test_expect_success '--max-count all forms' ' - test $(git-rev-list HEAD --max-count=1 | wc -l) = 1 && - test $(git-rev-list HEAD -1 | wc -l) = 1 && - test $(git-rev-list HEAD -n1 | wc -l) = 1 && - test $(git-rev-list HEAD -n 1 | wc -l) = 1 + test $(git rev-list HEAD --max-count=1 | wc -l) = 1 && + test $(git rev-list HEAD -1 | wc -l) = 1 && + test $(git rev-list HEAD -n1 | wc -l) = 1 && + test $(git rev-list HEAD -n 1 | wc -l) = 1 ' test_expect_success '--skip' ' - test $(git-rev-list HEAD --skip=0 | wc -l) = 5 && - test $(git-rev-list HEAD --skip=3 | wc -l) = 2 && - test $(git-rev-list HEAD --skip=5 | wc -l) = 0 && - test $(git-rev-list HEAD --skip=10 | wc -l) = 0 + test $(git rev-list HEAD --skip=0 | wc -l) = 5 && + test $(git rev-list HEAD --skip=3 | wc -l) = 2 && + test $(git rev-list HEAD --skip=5 | wc -l) = 0 && + test $(git rev-list HEAD --skip=10 | wc -l) = 0 ' test_expect_success '--skip --max-count' ' - test $(git-rev-list HEAD --skip=0 --max-count=0 | wc -l) = 0 && - test $(git-rev-list HEAD --skip=0 --max-count=10 | wc -l) = 5 && - test $(git-rev-list HEAD --skip=3 --max-count=0 | wc -l) = 0 && - test $(git-rev-list HEAD --skip=3 --max-count=1 | wc -l) = 1 && - test $(git-rev-list HEAD --skip=3 --max-count=2 | wc -l) = 2 && - test $(git-rev-list HEAD --skip=3 --max-count=10 | wc -l) = 2 && - test $(git-rev-list HEAD --skip=5 --max-count=10 | wc -l) = 0 && - test $(git-rev-list HEAD --skip=10 --max-count=10 | wc -l) = 0 + test $(git rev-list HEAD --skip=0 --max-count=0 | wc -l) = 0 && + test $(git rev-list HEAD --skip=0 --max-count=10 | wc -l) = 5 && + test $(git rev-list HEAD --skip=3 --max-count=0 | wc -l) = 0 && + test $(git rev-list HEAD --skip=3 --max-count=1 | wc -l) = 1 && + test $(git rev-list HEAD --skip=3 --max-count=2 | wc -l) = 2 && + test $(git rev-list HEAD --skip=3 --max-count=10 | wc -l) = 2 && + test $(git rev-list HEAD --skip=5 --max-count=10 | wc -l) = 0 && + test $(git rev-list HEAD --skip=10 --max-count=10 | wc -l) = 0 ' test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh new file mode 100755 index 0000000000..cccacd4add --- /dev/null +++ b/t/t6006-rev-list-format.sh @@ -0,0 +1,271 @@ +#!/bin/sh + +test_description='git rev-list --pretty=format test' + +. ./test-lib.sh + +test_tick +test_expect_success 'setup' ' +touch foo && git add foo && git commit -m "added foo" && + echo changed >foo && git commit -a -m "changed foo" +' + +# usage: test_format name format_string <expected_output +test_format() { + cat >expect.$1 + test_expect_success "format $1" " +git rev-list --pretty=format:'$2' master >output.$1 && +test_cmp expect.$1 output.$1 +" +} + +test_format percent %%h <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +%h +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +%h +EOF + +test_format hash %H%n%h <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +131a310eb913d107dd3c09a65d1651175898735d +131a310 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +EOF + +test_format tree %T%n%t <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +fe722612f26da5064c32ca3843aa154bdb0b08a0 +fe72261 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +4d5fcadc293a348e88f777dc0920f11e7d71441c +4d5fcad +EOF + +test_format parents %P%n%p <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + + +EOF + +# we don't test relative here +test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format encoding %e <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +EOF + +test_format subject %s <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format body %b <<'EOF' +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 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +[31mfoo[32mbar[34mbaz[mxyzzy +EOF + +test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +[1;31;43mfoo[m +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +[1;31;43mfoo[m +EOF + +cat >commit-msg <<'EOF' +Test printing of complex bodies + +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! +EOF +test_expect_success 'setup complex body' ' +git config i18n.commitencoding iso8859-1 && + echo change2 >foo && git commit -a -F commit-msg +' + +test_format complex-encoding %e <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +iso8859-1 +commit 131a310eb913d107dd3c09a65d1651175898735d +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +EOF + +test_format complex-subject %s <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +Test printing of complex bodies +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format complex-body %b <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! + +commit 131a310eb913d107dd3c09a65d1651175898735d +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +EOF + +test_expect_success '%ad respects --date=' ' + echo 2005-04-07 >expect.ad-short && + git log -1 --date=short --pretty=tformat:%ad >output.ad-short master && + test_cmp expect.ad-short output.ad-short +' + +test_expect_success 'empty email' ' + test_tick && + C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) && + A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) && + test "$A" = "A U Thor,,Thu Apr 7 15:14:13 2005 -0700" || { + echo "Eh? $A" >failure + false + } +' + +test_expect_success 'del LF before empty (1)' ' + git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual && + test $(wc -l <actual) = 2 +' + +test_expect_success 'del LF before empty (2)' ' + git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD >actual && + test $(wc -l <actual) = 6 && + grep "^$" actual +' + +test_expect_success 'add LF before non-empty (1)' ' + git show -s --pretty=format:"%s%+b%nThanks%n" HEAD^^ >actual && + test $(wc -l <actual) = 2 +' + +test_expect_success 'add LF before non-empty (2)' ' + git show -s --pretty=format:"%s%+b%nThanks%n" HEAD >actual && + test $(wc -l <actual) = 6 && + 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 && + test_cmp expect actual +' + +test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' ' + git reflog --date=raw >expect && + git log -g --format="%h %gD: %gs" --date=raw >actual && + 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 && + test_cmp expect.gd-short actual.gd-short +' + +test_expect_success 'oneline with empty message' ' + git commit -m "dummy" --allow-empty && + git commit -m "dummy" --allow-empty && + git filter-branch --msg-filter "sed -e s/dummy//" HEAD^^.. && + git rev-list --oneline HEAD >test.txt && + test $(git rev-list --oneline HEAD | wc -l) -eq 5 && + test $(git rev-list --oneline --graph HEAD | wc -l) -eq 5 +' + +test_done diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh new file mode 100755 index 0000000000..b565638e92 --- /dev/null +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +test_description='test git rev-list --cherry-pick -- file' + +. ./test-lib.sh + +# A---B +# \ +# \ +# C +# +# B changes a file foo.c, adding a line of text. C changes foo.c as +# well as bar.c, but the change in foo.c was identical to change B. + +test_expect_success setup ' + echo Hallo > foo && + git add foo && + test_tick && + git commit -m "A" && + git tag A && + git checkout -b branch && + echo Bello > foo && + echo Cello > bar && + git add foo bar && + test_tick && + git commit -m "C" && + git tag C && + git checkout master && + git checkout branch foo && + test_tick && + git commit -m "B" && + 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)" +' + +test_expect_success '--cherry-pick bar does not come up empty' ' + ! test -z "$(git rev-list --left-right --cherry-pick B...C -- bar)" +' + +test_expect_success '--cherry-pick with independent, but identical branches' ' + git symbolic-ref HEAD refs/heads/independent && + rm .git/index && + echo Hallo > foo && + git add foo && + test_tick && + git commit -m "independent" && + echo Bello > foo && + test_tick && + git commit -m "independent, too" foo && + test -z "$(git rev-list --left-right --cherry-pick \ + 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/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh new file mode 100755 index 0000000000..c4af9ca0a7 --- /dev/null +++ b/t/t6008-rev-list-submodule.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='git rev-list involving submodules that this repo has' + +. ./test-lib.sh + +test_expect_success 'setup' ' + : > file && + git add file && + test_tick && + git commit -m initial && + echo 1 > file && + test_tick && + git commit -m second file && + echo 2 > file && + test_tick && + git commit -m third file && + + rm .git/index && + + : > super-file && + git add super-file && + git submodule add "$(pwd)" sub && + git symbolic-ref HEAD refs/heads/super && + test_tick && + git commit -m super-initial && + echo 1 > super-file && + test_tick && + git commit -m super-first super-file && + echo 2 > super-file && + test_tick && + git commit -m super-second super-file +' + +test_expect_success "Ilari's test" ' + git rev-list --objects super master ^super^ +' + +test_done diff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh new file mode 100755 index 0000000000..c8a96a9a99 --- /dev/null +++ b/t/t6009-rev-list-parent.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='properly cull all ancestors' + +. ./test-lib.sh + +commit () { + test_tick && + echo $1 >file && + git commit -a -m $1 && + git tag $1 +} + +test_expect_success setup ' + + touch file && + git add file && + + commit one && + + test_tick=$(($test_tick - 2400)) + + commit two && + commit three && + commit four && + + git log --pretty=oneline --abbrev-commit +' + +test_expect_success 'one is ancestor of others and should not be shown' ' + + git rev-list one --not four >result && + >expect && + test_cmp expect result + +' + +test_done diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh index b15920b852..0144d9e858 100755 --- a/t/t6010-merge-base.sh +++ b/t/t6010-merge-base.sh @@ -8,15 +8,16 @@ test_description='Merge base computation. . ./test-lib.sh -T=$(git-write-tree) +T=$(git write-tree) M=1130000000 Z=+0000 -export GIT_COMMITTER_EMAIL=git@comm.iter.xz -export GIT_COMMITTER_NAME='C O Mmiter' -export GIT_AUTHOR_NAME='A U Thor' -export GIT_AUTHOR_EMAIL=git@au.thor.xz +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 @@ -29,11 +30,17 @@ doit() { GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE export GIT_COMMITTER_DATE GIT_AUTHOR_DATE - commit=$(echo $NAME | git-commit-tree $T $PARENTS) + commit=$(echo $NAME | git commit-tree $T $PARENTS) echo $commit >.git/refs/tags/$NAME echo $commit } +# E---D---C---B---A +# \'-_ \ \ +# \ `---------G \ +# \ \ +# F----------------H + # Setup... E=$(doit 5 E) D=$(doit 4 D $E) @@ -44,6 +51,18 @@ 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. @@ -82,23 +101,77 @@ PL=$(doit 4 PL $L2 $C2) PR=$(doit 4 PR $C2 $R2) test_expect_success 'compute merge-base (single)' \ - 'MB=$(git-merge-base G H) && - expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"' + 'MB=$(git merge-base PL PR) && + expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"' test_expect_success 'compute merge-base (all)' \ - 'MB=$(git-merge-base --all G H) && - expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"' + 'MB=$(git merge-base --all PL PR) && + expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"' -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"' +# 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 '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 && + 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 && + 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_expect_success 'compute merge-base (single)' \ - 'MB=$(git-merge-base PL PR) && - expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"' +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" +' -test_expect_success 'compute merge-base (all)' \ - 'MB=$(git-merge-base --all PL PR) && - expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"' +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" +' + +test_expect_success 'criss-cross merge-base for octopus-step (setup)' ' + git reset --hard MMR && + test_tick && git commit --allow-empty -m 1 && git tag 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 && + git reset --hard CC1 && + test_tick && git merge -s ours CC2 && + test_tick && git commit --allow-empty -m A && git tag CCA +' + +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" +' test_done diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh new file mode 100755 index 0000000000..e51eb41f4b --- /dev/null +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='git rev-list should notice bad commits' + +. ./test-lib.sh + +# Note: +# - compression level is set to zero to make "corruptions" easier to perform +# - reflog is disabled to avoid extra references which would twart the test + +test_expect_success 'setup' \ + ' + git init && + git config core.compression 0 && + git config core.logallrefupdates false && + echo "foo" > foo && + git add foo && + git commit -m "first commit" && + echo "bar" > bar && + git add bar && + git commit -m "second commit" && + echo "baz" > baz && + git add baz && + git commit -m "third commit" && + echo "foo again" >> foo && + git add foo && + git commit -m "fourth commit" && + git repack -a -f -d + ' + +test_expect_success 'verify number of revisions' \ + ' + revs=$(git rev-list --all | wc -l) && + test $revs -eq 4 && + first_commit=$(git rev-parse HEAD~3) + ' + +test_expect_success 'corrupt second commit object' \ + ' + perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack && + test_must_fail git fsck --full + ' + +test_expect_success 'rev-list should fail' \ + ' + test_must_fail git rev-list --all > /dev/null + ' + +test_expect_success 'git repack _MUST_ fail' \ + ' + test_must_fail git repack -a -f -d + ' + +test_expect_success 'first commit is still available' \ + ' + git log $first_commit + ' + +test_done + diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh new file mode 100755 index 0000000000..af34a1e817 --- /dev/null +++ b/t/t6012-rev-list-simplify.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='merge simplification' + +. ./test-lib.sh + +note () { + git tag "$1" +} + +unnote () { + git name-rev --tags --stdin | sed -e "s|$_x40 (tags/\([^)]*\)) |\1 |g" +} + +test_expect_success setup ' + echo "Hi there" >file && + git add file && + test_tick && git commit -m "Initial file" && + note A && + + git branch other-branch && + + echo "Hello" >file && + git add file && + test_tick && git commit -m "Modified file" && + note B && + + git checkout other-branch && + + echo "Hello" >file && + git add file && + test_tick && git commit -m "Modified the file identically" && + note C && + + echo "This is a stupid example" >another-file && + git add another-file && + test_tick && git commit -m "Add another file" && + note D && + + test_tick && git merge -m "merge" master && + note E && + + echo "Yet another" >elif && + git add elif && + test_tick && git commit -m "Irrelevant change" && + note F && + + git checkout master && + echo "Yet another" >elif && + git add elif && + test_tick && git commit -m "Another irrelevant change" && + note G && + + test_tick && git merge -m "merge" other-branch && + note H && + + echo "Final change" >file && + test_tick && git commit -a -m "Final change" && + note I +' + +FMT='tformat:%P %H | %s' + +check_result () { + for c in $1 + do + echo "$c" + done >expect && + shift && + param="$*" && + test_expect_success "log $param" ' + git log --pretty="$FMT" --parents $param | + unnote >actual && + sed -e "s/^.* \([^ ]*\) .*/\1/" >check <actual && + test_cmp expect check || { + cat actual + false + } + ' +} + +check_result 'I H G F E D C B A' --full-history +check_result 'I H E C B A' --full-history -- file +check_result 'I H E C B A' --full-history --topo-order -- file +check_result 'I H E C B A' --full-history --date-order -- file +check_result 'I E C B A' --simplify-merges -- file +check_result 'I B A' -- file +check_result 'I B A' --topo-order -- file + +test_done diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh new file mode 100755 index 0000000000..59fc2f06e0 --- /dev/null +++ b/t/t6013-rev-list-reverse-parents.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='--reverse combines with --parents' + +. ./test-lib.sh + + +commit () { + test_tick && + echo $1 > foo && + git add foo && + git commit -m "$1" +} + +test_expect_success 'set up --reverse example' ' + commit one && + git tag root && + commit two && + git checkout -b side HEAD^ && + commit three && + git checkout master && + git merge -s ours side && + commit five + ' + +test_expect_success '--reverse --parents --full-history combines correctly' ' + git rev-list --parents --full-history master -- foo | + perl -e "print reverse <>" > expected && + git rev-list --reverse --parents --full-history master -- foo \ + > actual && + test_cmp actual expected + ' + +test_expect_success '--boundary does too' ' + git rev-list --boundary --parents --full-history master ^root -- foo | + perl -e "print reverse <>" > expected && + git rev-list --boundary --reverse --parents --full-history \ + master ^root -- foo > actual && + test_cmp actual expected + ' + +test_done diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh new file mode 100755 index 0000000000..991ab4a65b --- /dev/null +++ b/t/t6014-rev-list-all.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='--all includes detached HEADs' + +. ./test-lib.sh + + +commit () { + test_tick && + echo $1 > foo && + git add foo && + git commit -m "$1" +} + +test_expect_success 'setup' ' + + commit one && + commit two && + git checkout HEAD^ && + commit detached + +' + +test_expect_success 'rev-list --all lists detached HEAD' ' + + test 3 = $(git rev-list --all | wc -l) + +' + +test_expect_success 'repack does not lose detached HEAD' ' + + git gc && + git prune --expire=now && + git show HEAD + +' + +test_done diff --git a/t/t6015-rev-list-show-all-parents.sh b/t/t6015-rev-list-show-all-parents.sh new file mode 100755 index 0000000000..8b146fb432 --- /dev/null +++ b/t/t6015-rev-list-show-all-parents.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='--show-all --parents does not rewrite TREESAME commits' + +. ./test-lib.sh + +test_expect_success 'set up --show-all --parents test' ' + test_commit one foo.txt && + commit1=`git rev-list -1 HEAD` && + test_commit two bar.txt && + commit2=`git rev-list -1 HEAD` && + test_commit three foo.txt && + commit3=`git rev-list -1 HEAD` + ' + +test_expect_success '--parents rewrites TREESAME parents correctly' ' + echo $commit3 $commit1 > expected && + echo $commit1 >> expected && + git rev-list --parents HEAD -- foo.txt > actual && + test_cmp expected actual + ' + +test_expect_success '--parents --show-all does not rewrites TREESAME parents' ' + echo $commit3 $commit2 > expected && + echo $commit2 $commit1 >> expected && + echo $commit1 >> expected && + git rev-list --parents --show-all HEAD -- foo.txt > actual && + test_cmp expected actual + ' + +test_done diff --git a/t/t6016-rev-list-graph-simplify-history.sh b/t/t6016-rev-list-graph-simplify-history.sh new file mode 100755 index 0000000000..27fd52b7be --- /dev/null +++ b/t/t6016-rev-list-graph-simplify-history.sh @@ -0,0 +1,276 @@ +#!/bin/sh + +# There's more than one "correct" way to represent the history graphically. +# These tests depend on the current behavior of the graphing code. If the +# graphing code is ever changed to draw the output differently, these tests +# cases will need to be updated to know about the new layout. + +test_description='--graph and simplified history' + +. ./test-lib.sh + +test_expect_success 'set up rev-list --graph test' ' + # 3 commits on branch A + test_commit A1 foo.txt && + test_commit A2 bar.txt && + test_commit A3 bar.txt && + git branch -m master A && + + # 2 commits on branch B, started from A1 + git checkout -b B A1 && + test_commit B1 foo.txt && + test_commit B2 abc.txt && + + # 2 commits on branch C, started from A2 + git checkout -b C A2 && + test_commit C1 xyz.txt && + test_commit C2 xyz.txt && + + # Octopus merge B and C into branch A + git checkout A && + git merge B C && + git tag A4 + + test_commit A5 bar.txt && + + # More commits on C, then merge C into A + git checkout C && + test_commit C3 foo.txt && + test_commit C4 bar.txt && + git checkout A && + git merge -s ours C && + git tag A6 + + test_commit A7 bar.txt && + + # Store commit names in variables for later use + A1=$(git rev-parse --verify A1) && + A2=$(git rev-parse --verify A2) && + A3=$(git rev-parse --verify A3) && + A4=$(git rev-parse --verify A4) && + A5=$(git rev-parse --verify A5) && + A6=$(git rev-parse --verify A6) && + A7=$(git rev-parse --verify A7) && + B1=$(git rev-parse --verify B1) && + B2=$(git rev-parse --verify B2) && + C1=$(git rev-parse --verify C1) && + C2=$(git rev-parse --verify C2) && + C3=$(git rev-parse --verify C3) && + C4=$(git rev-parse --verify C4) + ' + +test_expect_success '--graph --all' ' + rm -f expected && + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "| * $C3" >> expected && + echo "* | $A5" >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. \\ $A4" >> expected && + echo "|\\ \\ \\ " >> expected && + echo "| | |/ " >> expected && + echo "| | * $C2" >> expected && + echo "| | * $C1" >> expected && + echo "| * | $B2" >> expected && + echo "| * | $B1" >> expected && + echo "* | | $A3" >> expected && + echo "| |/ " >> expected && + echo "|/| " >> expected && + echo "* | $A2" >> expected && + echo "|/ " >> expected && + echo "* $A1" >> expected && + git rev-list --graph --all > actual && + test_cmp expected actual + ' + +# Make sure the graph_is_interesting() code still realizes +# that undecorated merges are interesting, even with --simplify-by-decoration +test_expect_success '--graph --simplify-by-decoration' ' + rm -f expected && + git tag -d A4 + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "| * $C3" >> expected && + echo "* | $A5" >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. \\ $A4" >> expected && + echo "|\\ \\ \\ " >> expected && + echo "| | |/ " >> expected && + echo "| | * $C2" >> expected && + echo "| | * $C1" >> expected && + echo "| * | $B2" >> expected && + echo "| * | $B1" >> expected && + echo "* | | $A3" >> expected && + echo "| |/ " >> expected && + echo "|/| " >> expected && + echo "* | $A2" >> expected && + echo "|/ " >> expected && + echo "* $A1" >> expected && + git rev-list --graph --all --simplify-by-decoration > actual && + test_cmp expected actual + ' + +# Get rid of all decorations on branch B, and graph with it simplified away +test_expect_success '--graph --simplify-by-decoration prune branch B' ' + rm -f expected && + git tag -d B2 + git tag -d B1 + git branch -d B + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "| * $C3" >> expected && + echo "* | $A5" >> expected && + echo "* | $A4" >> expected && + echo "|\\ \\ " >> expected && + echo "| |/ " >> expected && + echo "| * $C2" >> expected && + echo "| * $C1" >> expected && + echo "* | $A3" >> expected && + echo "|/ " >> expected && + echo "* $A2" >> expected && + echo "* $A1" >> expected && + git rev-list --graph --simplify-by-decoration --all > actual && + test_cmp expected actual + ' + +test_expect_success '--graph --full-history -- bar.txt' ' + rm -f expected && + git tag -d B2 + git tag -d B1 + git branch -d B + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "* | $A5" >> expected && + echo "* | $A4" >> expected && + echo "|\\ \\ " >> expected && + echo "| |/ " >> expected && + echo "* | $A3" >> expected && + echo "|/ " >> expected && + echo "* $A2" >> expected && + git rev-list --graph --full-history --all -- bar.txt > actual && + test_cmp expected actual + ' + +test_expect_success '--graph --full-history --simplify-merges -- bar.txt' ' + rm -f expected && + git tag -d B2 + git tag -d B1 + git branch -d B + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "* | $A5" >> expected && + echo "* | $A3" >> expected && + echo "|/ " >> expected && + echo "* $A2" >> expected && + git rev-list --graph --full-history --simplify-merges --all \ + -- bar.txt > actual && + test_cmp expected actual + ' + +test_expect_success '--graph -- bar.txt' ' + rm -f expected && + git tag -d B2 + git tag -d B1 + git branch -d B + echo "* $A7" >> expected && + echo "* $A5" >> expected && + echo "* $A3" >> expected && + echo "| * $C4" >> expected && + echo "|/ " >> expected && + echo "* $A2" >> expected && + git rev-list --graph --all -- bar.txt > actual && + test_cmp expected actual + ' + +test_expect_success '--graph --sparse -- bar.txt' ' + rm -f expected && + git tag -d B2 + git tag -d B1 + git branch -d B + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "* $A5" >> expected && + echo "* $A4" >> expected && + echo "* $A3" >> expected && + echo "| * $C4" >> expected && + echo "| * $C3" >> expected && + echo "| * $C2" >> expected && + echo "| * $C1" >> expected && + echo "|/ " >> expected && + echo "* $A2" >> expected && + echo "* $A1" >> expected && + git rev-list --graph --sparse --all -- bar.txt > actual && + test_cmp expected actual + ' + +test_expect_success '--graph ^C4' ' + rm -f expected && + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "* $A5" >> expected && + echo "* $A4" >> expected && + echo "|\\ " >> expected && + echo "| * $B2" >> expected && + echo "| * $B1" >> expected && + echo "* $A3" >> expected && + git rev-list --graph --all ^C4 > actual && + test_cmp expected actual + ' + +test_expect_success '--graph ^C3' ' + rm -f expected && + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "* $A5" >> expected && + echo "* $A4" >> expected && + echo "|\\ " >> expected && + echo "| * $B2" >> expected && + echo "| * $B1" >> expected && + echo "* $A3" >> expected && + git rev-list --graph --all ^C3 > actual && + test_cmp expected actual + ' + +# I don't think the ordering of the boundary commits is really +# that important, but this test depends on it. If the ordering ever changes +# in the code, we'll need to update this test. +test_expect_success '--graph --boundary ^C3' ' + rm -f expected && + echo "* $A7" >> expected && + echo "* $A6" >> expected && + echo "|\\ " >> expected && + echo "| * $C4" >> expected && + echo "* | $A5" >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. \\ $A4" >> expected && + echo "|\\ \\ \\ " >> expected && + echo "| * | | $B2" >> expected && + echo "| * | | $B1" >> expected && + echo "* | | | $A3" >> expected && + echo "o | | | $A2" >> expected && + echo "|/ / / " >> expected && + echo "o | | $A1" >> expected && + echo " / / " >> expected && + echo "| o $C3" >> expected && + echo "|/ " >> expected && + echo "o $C2" >> expected && + git rev-list --graph --boundary --all ^C3 > actual && + test_cmp expected actual + ' + +test_done diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh new file mode 100755 index 0000000000..f1c32dba42 --- /dev/null +++ b/t/t6017-rev-list-stdin.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# Copyright (c) 2009, Junio C Hamano +# + +test_description='log family learns --stdin' + +. ./test-lib.sh + +check () { + for cmd in rev-list "log --stat" + do + for i in "$@" + do + printf "%s\n" $i + done >input && + test_expect_success "check $cmd $*" ' + git $cmd $(cat input) >expect && + git $cmd --stdin <input >actual && + sed -e "s/^/input /" input && + sed -e "s/^/output /" expect && + test_cmp expect actual + ' + done +} + +them='1 2 3 4 5 6 7' + +test_expect_success setup ' + ( + for i in 0 $them + do + for j in $them + do + echo $i.$j >file-$j && + git add file-$j || exit + done && + test_tick && + git commit -m $i || exit + done && + for i in $them + do + git checkout -b side-$i master~$i && + echo updated $i >file-$i && + git add file-$i && + test_tick && + git commit -m side-$i || exit + done + ) +' + +check master +check side-1 ^side-4 +check side-1 ^side-7 -- +check side-1 ^side-7 -- file-1 +check side-1 ^side-7 -- file-2 +check side-3 ^side-4 -- file-3 +check side-3 ^side-2 +check side-3 ^side-2 -- file-1 + +test_done diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh new file mode 100755 index 0000000000..58428d9f5c --- /dev/null +++ b/t/t6018-rev-list-glob.sh @@ -0,0 +1,210 @@ +#!/bin/sh + +test_description='rev-list/rev-parse --glob' + +. ./test-lib.sh + +commit () { + test_tick && + echo $1 > foo && + git add foo && + git commit -m "$1" +} + +compare () { + # Split arguments on whitespace. + git $1 $2 >expected && + git $1 $3 >actual && + test_cmp expected actual +} + +test_expect_success 'setup' ' + + commit master && + git checkout -b subspace/one master && + commit one && + git checkout -b subspace/two master && + commit two && + git checkout -b subspace-x master && + commit subspace-x && + git checkout -b other/three master && + commit three && + git checkout -b someref master && + commit some && + git checkout master && + commit master2 && + git tag foo/bar master && + commit master3 && + git update-ref refs/remotes/foo/baz master && + commit master4 +' + +test_expect_success 'rev-parse --glob=refs/heads/subspace/*' ' + + compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/*" + +' + +test_expect_success 'rev-parse --glob=heads/subspace/*' ' + + compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/*" + +' + +test_expect_success 'rev-parse --glob=refs/heads/subspace/' ' + + compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/" + +' + +test_expect_success 'rev-parse --glob=heads/subspace/' ' + + compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/" + +' + +test_expect_success 'rev-parse --glob=heads/subspace' ' + + compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace" + +' + +test_expect_success 'rev-parse --branches=subspace/*' ' + + compare rev-parse "subspace/one subspace/two" "--branches=subspace/*" + +' + +test_expect_success 'rev-parse --branches=subspace/' ' + + compare rev-parse "subspace/one subspace/two" "--branches=subspace/" + +' + +test_expect_success 'rev-parse --branches=subspace' ' + + compare rev-parse "subspace/one subspace/two" "--branches=subspace" + +' + +test_expect_success 'rev-parse --glob=heads/subspace/* --glob=heads/other/*' ' + + compare rev-parse "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*" + +' + +test_expect_success 'rev-parse --glob=heads/someref/* master' ' + + compare rev-parse "master" "--glob=heads/someref/* master" + +' + +test_expect_success 'rev-parse --glob=heads/*' ' + + compare rev-parse "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*" + +' + +test_expect_success 'rev-parse --tags=foo' ' + + compare rev-parse "foo/bar" "--tags=foo" + +' + +test_expect_success 'rev-parse --remotes=foo' ' + + compare rev-parse "foo/baz" "--remotes=foo" + +' + +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/*" + +' + +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/" + +' + +test_expect_success 'rev-list --glob=heads/subspace' ' + + compare rev-list "subspace/one subspace/two" "--glob=heads/subspace" + +' + +test_expect_success 'rev-list --branches=subspace/*' ' + + compare rev-list "subspace/one subspace/two" "--branches=subspace/*" + +' + +test_expect_success 'rev-list --branches=subspace/' ' + + compare rev-list "subspace/one subspace/two" "--branches=subspace/" + +' + +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" + +' + +test_expect_success 'rev-list --glob=heads/subspace/* --glob=heads/other/*' ' + + compare rev-list "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*" + +' + +test_expect_success 'rev-list --glob=heads/*' ' + + compare rev-list "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*" + +' + +test_expect_success 'rev-list --tags=foo' ' + + compare rev-list "foo/bar" "--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" + +' + +test_done 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 a19d49de28..e71c687f2b 100755 --- a/t/t6020-merge-df.sh +++ b/t/t6020-merge-df.sh @@ -22,4 +22,27 @@ 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' ' + git reset --hard && + git checkout master && + rm .git/index && + + mkdir before && + echo FILE >before/one && + echo FILE >after && + git add . && + git commit -m first && + + rm -f after && + git mv before after && + git commit -m move && + + git checkout -b para HEAD^ && + echo COMPLETELY ANOTHER FILE >another && + git add . && + git commit -m para && + + git merge master +' + test_done diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh index 499cafb882..331b9b07d4 100755 --- a/t/t6021-merge-criss-cross.sh +++ b/t/t6021-merge-criss-cross.sh @@ -20,7 +20,7 @@ test_expect_success 'prepare repository' \ 7 8 9" > file && -git add file && +git add file && git commit -m "Initial commit" file && git branch A && git branch B && @@ -89,4 +89,8 @@ EOF test_expect_success 'Criss-cross merge result' 'cmp file file-expect' +test_expect_success 'Criss-cross merge fails (-s resolve)' \ +'git reset --hard A^ && +test_must_fail git merge -s resolve -m "final merge" B' + test_done diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index b608e202c1..b66544b76d 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -47,6 +47,8 @@ git branch white && git branch red && git branch blue && git branch yellow && +git branch change && +git branch change+rename && sed -e "/^g /s/.*/g : master changes a line/" <A >A+ && mv A+ A && @@ -77,6 +79,17 @@ rm -f A M && git update-index --add --remove A C M N && git commit -m "blue renames A->C, M->N" && +git checkout change && +sed -e "/^g /s/.*/g : changed line/" <A >A+ && +mv A+ A && +git commit -q -a -m "changed" && + +git checkout change+rename && +sed -e "/^g /s/.*/g : changed line/" <A >B && +rm A && +git update-index --add B && +git commit -q -a -m "changed and renamed" && + git checkout master' test_expect_success 'pull renaming branch into unrenaming one' \ @@ -267,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 } @@ -288,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 } @@ -318,4 +331,14 @@ test_expect_success 'interference with untracked working tree file' ' git reset --hard anchor ' +test_expect_success 'merge of identical changes in a renamed file' ' + rm -f A M N + git reset --hard && + git checkout change+rename && + GIT_MERGE_VERBOSITY=3 git merge change | grep "^Skipped B" && + git reset --hard HEAD^ && + git checkout change && + GIT_MERGE_VERBOSITY=3 git merge change+rename | grep "^Skipped B" +' + test_done diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index f3cd3dba4d..d486d73994 100644..100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -54,20 +54,30 @@ deduxit me super semitas jusitiae, EOF printf "propter nomen suum." >> new4.txt +test_expect_success 'merge with no changes' ' + cp orig.txt test.txt && + git merge-file test.txt orig.txt orig.txt && + test_cmp test.txt orig.txt +' + cp new1.txt test.txt test_expect_success "merge without conflict" \ - "git-merge-file test.txt orig.txt new2.txt" + "git merge-file test.txt orig.txt new2.txt" + +cp new1.txt test.txt +test_expect_success "merge without conflict (--quiet)" \ + "git merge-file --quiet test.txt orig.txt new2.txt" cp new1.txt test2.txt test_expect_success "merge without conflict (missing LF at EOF)" \ - "git-merge-file test2.txt orig.txt new2.txt" + "git merge-file test2.txt orig.txt new2.txt" test_expect_success "merge result added missing LF" \ - "diff -u test.txt test2.txt" + "test_cmp test.txt test2.txt" cp test.txt backup.txt -test_expect_failure "merge with conflicts" \ - "git-merge-file test.txt orig.txt new3.txt" +test_expect_success "merge with conflicts" \ + "test_must_fail git merge-file test.txt orig.txt new3.txt" cat > expect.txt << EOF <<<<<<< test.txt @@ -86,11 +96,11 @@ non timebo mala, quoniam tu mecum es: virga tua et baculus tuus ipsa me consolata sunt. EOF -test_expect_success "expected conflict markers" "diff -u test.txt expect.txt" +test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt" cp backup.txt test.txt -test_expect_failure "merge with conflicts, using -L" \ - "git-merge-file -L 1 -L 2 test.txt orig.txt new3.txt" +test_expect_success "merge with conflicts, using -L" \ + "test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt" cat > expect.txt << EOF <<<<<<< 1 @@ -110,11 +120,11 @@ virga tua et baculus tuus ipsa me consolata sunt. EOF test_expect_success "expected conflict markers, with -L" \ - "diff -u test.txt expect.txt" + "test_cmp test.txt expect.txt" sed "s/ tu / TU /" < new1.txt > new5.txt -test_expect_failure "conflict in removed tail" \ - "git-merge-file -p orig.txt new1.txt new5.txt > out" +test_expect_success "conflict in removed tail" \ + "test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out" cat > expect << EOF Dominus regit me, @@ -132,7 +142,114 @@ virga tua et baculus tuus ipsa me consolata sunt. >>>>>>> new5.txt EOF -test_expect_success "expected conflict markers" "diff -u expect out" +test_expect_success "expected conflict markers" "test_cmp expect out" + +test_expect_success 'binary files cannot be merged' ' + test_must_fail git merge-file -p \ + orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err && + grep "Cannot merge binary files" merge.err +' + +sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" < new5.txt > new6.txt +sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" < new5.txt > new7.txt + +test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' ' + + test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output && + test 1 = $(grep ======= < output | wc -l) + +' + +sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit;/"< new6.txt | tr '%' '\012' > new8.txt +sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit --/" < new7.txt | tr '%' '\012' > new9.txt + +test_expect_success 'ZEALOUS_ALNUM' ' + + test_must_fail git merge-file -p \ + new8.txt new5.txt new9.txt > merge.out && + test 1 = $(grep ======= < merge.out | wc -l) + +' + +cat >expect <<\EOF +Dominus regit me, +<<<<<<< new8.txt +et nihil mihi deerit; -test_done + + +In loco pascuae ibi me collocavit; +super aquam refectionis educavit me. +||||||| new5.txt +et nihil mihi deerit. +In loco pascuae ibi me collocavit, +super aquam refectionis educavit me; +======= +et nihil mihi deerit, + + + + +In loco pascuae ibi me collocavit -- +super aquam refectionis educavit me, +>>>>>>> new9.txt +animam meam convertit, +deduxit me super semitas jusitiae, +propter nomen suum. +Nam et si ambulavero in medio umbrae mortis, +non timebo mala, quoniam TU mecum es: +virga tua et baculus tuus ipsa me consolata sunt. +EOF + +test_expect_success '"diff3 -m" style output (1)' ' + test_must_fail git merge-file -p --diff3 \ + new8.txt new5.txt new9.txt >actual && + test_cmp expect actual +' + +test_expect_success '"diff3 -m" style output (2)' ' + git config merge.conflictstyle diff3 && + test_must_fail git merge-file -p \ + new8.txt new5.txt new9.txt >actual && + test_cmp expect actual +' + +cat >expect <<\EOF +Dominus regit me, +<<<<<<<<<< new8.txt +et nihil mihi deerit; + + + + +In loco pascuae ibi me collocavit; +super aquam refectionis educavit me. +|||||||||| new5.txt +et nihil mihi deerit. +In loco pascuae ibi me collocavit, +super aquam refectionis educavit me; +========== +et nihil mihi deerit, + + + + +In loco pascuae ibi me collocavit -- +super aquam refectionis educavit me, +>>>>>>>>>> new9.txt +animam meam convertit, +deduxit me super semitas jusitiae, +propter nomen suum. +Nam et si ambulavero in medio umbrae mortis, +non timebo mala, quoniam TU mecum es: +virga tua et baculus tuus ipsa me consolata sunt. +EOF + +test_expect_success 'marker size' ' + test_must_fail git merge-file -p --marker-size=10 \ + new8.txt new5.txt new9.txt >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index 31b96257b4..b3fbf659c0 100644..100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -28,7 +28,7 @@ echo B > a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:02" git commit -m B a1 && git checkout -b D A && -git-rev-parse B > .git/MERGE_HEAD && +git rev-parse B > .git/MERGE_HEAD && echo D > a1 && git update-index a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:03" git commit -m D && @@ -42,43 +42,81 @@ echo C > a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:05" git commit -m C a1 && git checkout -b E C && -git-rev-parse B > .git/MERGE_HEAD && +git rev-parse B > .git/MERGE_HEAD && echo E > a1 && git update-index a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:06" git commit -m E && git checkout -b G E && -git-rev-parse A > .git/MERGE_HEAD && +git rev-parse A > .git/MERGE_HEAD && echo G > a1 && git update-index a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:07" git commit -m G && git checkout -b F D && -git-rev-parse C > .git/MERGE_HEAD && +git rev-parse C > .git/MERGE_HEAD && echo F > a1 && git update-index a1 && GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F ' -test_expect_failure "combined merge conflicts" "git merge -m final G" +test_expect_success "combined merge conflicts" " + test_must_fail git merge -m final G +" cat > expect << EOF -<<<<<<< HEAD:a1 +<<<<<<< HEAD F ======= G ->>>>>>> G:a1 +>>>>>>> G EOF -test_expect_success "result contains a conflict" "diff -u expect a1" +test_expect_success "result contains a conflict" "test_cmp expect a1" git ls-files --stage > out cat > expect << EOF -100644 da056ce14a2241509897fa68bb2b3b6e6194ef9e 1 a1 +100644 439cc46de773d8a83c77799b7cc9191c128bfcff 1 a1 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1 100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1 EOF -test_expect_success "virtual trees were processed" "diff -u expect out" +test_expect_success "virtual trees were processed" "test_cmp expect out" + +test_expect_success 'refuse to merge binary files' ' + git reset --hard && + printf "\0" > binary-file && + git add binary-file && + git commit -m binary && + git checkout G && + printf "\0\0" > binary-file && + git add binary-file && + git commit -m binary2 && + test_must_fail git merge F > merge.out 2> merge.err && + grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err +' + +test_expect_success 'mark rename/delete as unmerged' ' + + git reset --hard && + git checkout -b delete && + git rm a1 && + test_tick && + git commit -m delete && + git checkout -b rename HEAD^ && + git mv a1 a2 + test_tick && + git commit -m rename && + test_must_fail git merge delete && + test 1 = $(git ls-files --unmerged | wc -l) && + git rev-parse --verify :2:a2 && + test_must_fail git rev-parse --verify :3:a2 && + git checkout -f delete && + test_must_fail git merge rename && + test 1 = $(git ls-files --unmerged | wc -l) && + test_must_fail git rev-parse --verify :2:a2 && + git rev-parse --verify :3:a2 + +' test_done diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh index 3c1a6972bd..433c4de08f 100644..100755 --- a/t/t6025-merge-symlinks.sh +++ b/t/t6025-merge-symlinks.sh @@ -5,55 +5,54 @@ test_description='merging symlinks on filesystem w/o symlink support. -This tests that git-merge-recursive writes merge results as plain files +This tests that git merge-recursive writes merge results as plain files if core.symlinks is false.' . ./test-lib.sh test_expect_success \ 'setup' ' -git-config core.symlinks false && +git config core.symlinks false && > file && -git-add file && -git-commit -m initial && -git-branch b-symlink && -git-branch b-file && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git-update-index --index-info && -git-commit -m master && -git-checkout b-symlink && -l=$(echo -n file-different | git-hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git-update-index --index-info && -git-commit -m b-symlink && -git-checkout b-file && +git add file && +git commit -m initial && +git branch b-symlink && +git branch b-file && +l=$(printf file | git hash-object -t blob -w --stdin) && +echo "120000 $l symlink" | git update-index --index-info && +git commit -m master && +git checkout b-symlink && +l=$(printf file-different | git hash-object -t blob -w --stdin) && +echo "120000 $l symlink" | git update-index --index-info && +git commit -m b-symlink && +git checkout b-file && echo plain-file > symlink && -git-add symlink && -git-commit -m b-file' +git add symlink && +git commit -m b-file' -test_expect_failure \ +test_expect_success \ 'merge master into b-symlink, which has a different symbolic link' ' -! git-checkout b-symlink || -git-merge master' +git checkout b-symlink && +test_must_fail git merge master' test_expect_success \ 'the merge result must be a file' ' test -f symlink' -test_expect_failure \ +test_expect_success \ 'merge master into b-file, which has a file instead of a symbolic link' ' -! (git-reset --hard && -git-checkout b-file) || -git-merge master' +git reset --hard && git checkout b-file && +test_must_fail git merge master' test_expect_success \ 'the merge result must be a file' ' test -f symlink' -test_expect_failure \ +test_expect_success \ 'merge b-file, which has a file instead of a symbolic link, into master' ' -! (git-reset --hard && -git-checkout master) || -git-merge b-file' +git reset --hard && +git checkout master && +test_must_fail git merge b-file' test_expect_success \ 'the merge result must be a file' ' diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh new file mode 100755 index 0000000000..5e439972be --- /dev/null +++ b/t/t6026-merge-attr.sh @@ -0,0 +1,179 @@ +#!/bin/sh +# +# Copyright (c) 2007 Junio C Hamano +# + +test_description='per path merge controlled by merge attribute' + +. ./test-lib.sh + +test_expect_success setup ' + + for f in text binary union + do + echo Initial >$f && git add $f || break + done && + test_tick && + git commit -m Initial && + + git branch side && + for f in text binary union + do + echo Master >>$f && git add $f || break + done && + test_tick && + git commit -m Master && + + git checkout side && + for f in text binary union + do + echo Side >>$f && git add $f || break + done && + test_tick && + git commit -m Side && + + git tag anchor +' + +test_expect_success merge ' + + { + echo "binary -merge" + echo "union merge=union" + } >.gitattributes && + + if git merge master + then + echo Gaah, should have conflicted + false + else + echo Ok, conflicted. + fi +' + +test_expect_success 'check merge result in index' ' + + git ls-files -u | grep binary && + git ls-files -u | grep text && + ! (git ls-files -u | grep union) + +' + +test_expect_success 'check merge result in working tree' ' + + git cat-file -p HEAD:binary >binary-orig && + grep "<<<<<<<" text && + cmp binary-orig binary && + ! grep "<<<<<<<" union && + grep Master union && + grep Side union + +' + +test_expect_success 'retry the merge with longer context' ' + echo text conflict-marker-size=32 >>.gitattributes && + git checkout -m text && + sed -ne "/^\([<=>]\)\1\1\1*/{ + s/ .*$// + p + }" >actual text && + grep ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" actual && + grep "================================" actual && + grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual +' + +cat >./custom-merge <<\EOF +#!/bin/sh + +orig="$1" ours="$2" theirs="$3" exit="$4" +( + echo "orig is $orig" + echo "ours is $ours" + echo "theirs is $theirs" + echo "=== orig ===" + cat "$orig" + echo "=== ours ===" + cat "$ours" + echo "=== theirs ===" + cat "$theirs" +) >"$ours+" +cat "$ours+" >"$ours" +rm -f "$ours+" +exit "$exit" +EOF +chmod +x ./custom-merge + +test_expect_success 'custom merge backend' ' + + echo "* merge=union" >.gitattributes && + echo "text merge=custom" >>.gitattributes && + + git reset --hard anchor && + git config --replace-all \ + merge.custom.driver "./custom-merge %O %A %B 0" && + git config --replace-all \ + merge.custom.name "custom merge driver for testing" && + + git merge master && + + cmp binary union && + sed -e 1,3d text >check-1 && + o=$(git unpack-file master^:text) && + a=$(git unpack-file side^:text) && + b=$(git unpack-file master:text) && + sh -c "./custom-merge $o $a $b 0" && + sed -e 1,3d $a >check-2 && + cmp check-1 check-2 && + rm -f $o $a $b +' + +test_expect_success 'custom merge backend' ' + + git reset --hard anchor && + git config --replace-all \ + merge.custom.driver "./custom-merge %O %A %B 1" && + git config --replace-all \ + merge.custom.name "custom merge driver for testing" && + + if git merge master + then + echo "Eh? should have conflicted" + false + else + echo "Ok, conflicted" + fi && + + cmp binary union && + sed -e 1,3d text >check-1 && + o=$(git unpack-file master^:text) && + a=$(git unpack-file anchor:text) && + b=$(git unpack-file master:text) && + sh -c "./custom-merge $o $a $b 0" && + sed -e 1,3d $a >check-2 && + cmp check-1 check-2 && + rm -f $o $a $b +' + +test_expect_success 'up-to-date merge without common ancestor' ' + test_create_repo repo1 && + test_create_repo repo2 && + test_tick && + ( + cd repo1 && + >a && + git add a && + git commit -m initial + ) && + test_tick && + ( + cd repo2 && + git commit --allow-empty -m initial + ) && + test_tick && + ( + cd repo1 && + git pull ../repo2 master + ) +' + +test_done diff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh new file mode 100755 index 0000000000..b519626ca0 --- /dev/null +++ b/t/t6027-merge-binary.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='ask merge-recursive to merge binary files' + +. ./test-lib.sh + +test_expect_success setup ' + + cat "$TEST_DIRECTORY"/test4012.png >m && + git add m && + git ls-files -s | sed -e "s/ 0 / 1 /" >E1 && + test_tick && + git commit -m "initial" && + + git branch side && + echo frotz >a && + git add a && + echo nitfol >>m && + git add a m && + git ls-files -s a >E0 && + git ls-files -s m | sed -e "s/ 0 / 3 /" >E3 && + test_tick && + git commit -m "master adds some" && + + git checkout side && + echo rezrov >>m && + git add m && + git ls-files -s m | sed -e "s/ 0 / 2 /" >E2 && + test_tick && + git commit -m "side modifies" && + + git tag anchor && + + cat E0 E1 E2 E3 >expect +' + +test_expect_success resolve ' + + rm -f a* m* && + git reset --hard anchor && + + if git merge -s resolve master + then + echo Oops, should not have succeeded + false + else + git ls-files -s >current + test_cmp current expect + fi +' + +test_expect_success recursive ' + + rm -f a* m* && + git reset --hard anchor && + + if git merge -s recursive master + then + echo Oops, should not have succeeded + false + else + git ls-files -s >current + test_cmp current expect + fi +' + +test_done diff --git a/t/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh new file mode 100755 index 0000000000..a91644e3b2 --- /dev/null +++ b/t/t6028-merge-up-to-date.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +test_description='merge fast-forward and up to date' + +. ./test-lib.sh + +test_expect_success setup ' + >file && + git add file && + test_tick && + git commit -m initial && + git tag c0 && + + echo second >file && + git add file && + test_tick && + git commit -m second && + git tag c1 && + git branch test +' + +test_expect_success 'merge -s recursive up-to-date' ' + + git reset --hard c1 && + test_tick && + git merge -s recursive c0 && + expect=$(git rev-parse c1) && + current=$(git rev-parse HEAD) && + test "$expect" = "$current" + +' + +test_expect_success 'merge -s recursive fast-forward' ' + + git reset --hard c0 && + test_tick && + git merge -s recursive c1 && + expect=$(git rev-parse c1) && + current=$(git rev-parse HEAD) && + test "$expect" = "$current" + +' + +test_expect_success 'merge -s ours up-to-date' ' + + git reset --hard c1 && + test_tick && + git merge -s ours c0 && + expect=$(git rev-parse c1) && + current=$(git rev-parse HEAD) && + test "$expect" = "$current" + +' + +test_expect_success 'merge -s ours fast-forward' ' + + git reset --hard c0 && + test_tick && + git merge -s ours c1 && + expect=$(git rev-parse c0^{tree}) && + current=$(git rev-parse HEAD^{tree}) && + test "$expect" = "$current" + +' + +test_expect_success 'merge -s subtree up-to-date' ' + + git reset --hard c1 && + test_tick && + git merge -s subtree c0 && + expect=$(git rev-parse c1) && + current=$(git rev-parse HEAD) && + test "$expect" = "$current" + +' + +test_done diff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh new file mode 100755 index 0000000000..3900d9f61f --- /dev/null +++ b/t/t6029-merge-subtree.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +test_description='subtree merge strategy' + +. ./test-lib.sh + +test_expect_success setup ' + + s="1 2 3 4 5 6 7 8" + for i in $s; do echo $i; done >hello && + git add hello && + git commit -m initial && + git checkout -b side && + echo >>hello world && + git add hello && + git commit -m second && + git checkout master && + for i in mundo $s; do echo $i; done >hello && + git add hello && + git commit -m master + +' + +test_expect_success 'subtree available and works like recursive' ' + + git merge -s subtree side && + for i in mundo $s world; do echo $i; done >expect && + test_cmp expect hello + +' + +test_expect_success 'setup' ' + mkdir git-gui && + cd git-gui && + git init && + echo git-gui > git-gui.sh && + o1=$(git hash-object git-gui.sh) && + git add git-gui.sh && + git commit -m "initial git-gui" && + cd .. && + mkdir git && + cd git && + git init && + echo git >git.c && + o2=$(git hash-object git.c) && + git add git.c && + git commit -m "initial git" +' + +test_expect_success 'initial merge' ' + git remote add -f gui ../git-gui && + git merge -s ours --no-commit gui/master && + git read-tree --prefix=git-gui/ -u gui/master && + git commit -m "Merge git-gui as our subdirectory" && + git checkout -b work && + git ls-files -s >actual && + ( + echo "100644 $o1 0 git-gui/git-gui.sh" + echo "100644 $o2 0 git.c" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'merge update' ' + cd ../git-gui && + echo git-gui2 > git-gui.sh && + o3=$(git hash-object git-gui.sh) && + git add git-gui.sh && + git checkout -b master2 && + git commit -m "update git-gui" && + cd ../git && + git pull -s subtree gui master2 && + git ls-files -s >actual && + ( + echo "100644 $o3 0 git-gui/git-gui.sh" + echo "100644 $o2 0 git.c" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'initial ambiguous subtree' ' + cd ../git && + git reset --hard master && + git checkout -b master2 && + git merge -s ours --no-commit gui/master && + git read-tree --prefix=git-gui2/ -u gui/master && + git commit -m "Merge git-gui2 as our subdirectory" && + git checkout -b work2 && + git ls-files -s >actual && + ( + echo "100644 $o1 0 git-gui/git-gui.sh" + echo "100644 $o1 0 git-gui2/git-gui.sh" + echo "100644 $o2 0 git.c" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'merge using explicit' ' + cd ../git && + git reset --hard master2 && + git pull -Xsubtree=git-gui gui master2 && + git ls-files -s >actual && + ( + echo "100644 $o3 0 git-gui/git-gui.sh" + echo "100644 $o1 0 git-gui2/git-gui.sh" + echo "100644 $o2 0 git.c" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'merge2 using explicit' ' + cd ../git && + git reset --hard master2 && + git pull -Xsubtree=git-gui2 gui master2 && + git ls-files -s >actual && + ( + echo "100644 $o1 0 git-gui/git-gui.sh" + echo "100644 $o3 0 git-gui2/git-gui.sh" + echo "100644 $o2 0 git.c" + ) >expected && + test_cmp expected actual +' + +test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh new file mode 100755 index 0000000000..3b042aacd6 --- /dev/null +++ b/t/t6030-bisect-porcelain.sh @@ -0,0 +1,577 @@ +#!/bin/sh +# +# Copyright (c) 2007 Christian Couder +# +test_description='Tests git bisect functionality' + +exec </dev/null + +. ./test-lib.sh + +add_line_into_file() +{ + _line=$1 + _file=$2 + + if [ -f "$_file" ]; then + echo "$_line" >> $_file || return $? + MSG="Add <$_line> into <$_file>." + else + echo "$_line" > $_file || return $? + git add $_file || return $? + MSG="Create file <$_file> with <$_line> inside." + fi + + test_tick + git commit --quiet -m "$MSG" $_file +} + +HASH1= +HASH2= +HASH3= +HASH4= + +test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' ' + add_line_into_file "1: Hello World" hello && + HASH1=$(git rev-parse --verify HEAD) && + add_line_into_file "2: A new day for git" hello && + HASH2=$(git rev-parse --verify HEAD) && + add_line_into_file "3: Another new day for git" hello && + HASH3=$(git rev-parse --verify HEAD) && + add_line_into_file "4: Ciao for now" hello && + HASH4=$(git rev-parse --verify HEAD) +' + +test_expect_success 'bisect starts with only one bad' ' + git bisect reset && + git bisect start && + git bisect bad $HASH4 && + git bisect next +' + +test_expect_success 'bisect does not start with only one good' ' + git bisect reset && + git bisect start && + git bisect good $HASH1 || return 1 + + if git bisect next + then + echo Oops, should have failed. + false + else + : + fi +' + +test_expect_success 'bisect start with one bad and good' ' + git bisect reset && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect next +' + +test_expect_success 'bisect fails if given any junk instead of revs' ' + git bisect reset && + test_must_fail git bisect start foo $HASH1 -- && + test_must_fail git bisect start $HASH4 $HASH1 bar -- && + test -z "$(git for-each-ref "refs/bisect/*")" && + test -z "$(ls .git/BISECT_* 2>/dev/null)" && + git bisect start && + test_must_fail git bisect good foo $HASH1 && + test_must_fail git bisect good $HASH1 bar && + test_must_fail git bisect bad frotz && + test_must_fail git bisect bad $HASH3 $HASH4 && + test_must_fail git bisect skip bar $HASH3 && + test_must_fail git bisect skip $HASH1 foo && + test -z "$(git for-each-ref "refs/bisect/*")" && + git bisect good $HASH1 && + git bisect bad $HASH4 +' + +test_expect_success 'bisect reset: back in the master branch' ' + git bisect reset && + echo "* master" > branch.expect && + git branch > branch.output && + cmp branch.expect branch.output +' + +test_expect_success 'bisect reset: back in another branch' ' + git checkout -b other && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH3 && + git bisect reset && + echo " master" > branch.expect && + echo "* other" >> branch.expect && + git branch > branch.output && + cmp branch.expect branch.output +' + +test_expect_success 'bisect reset when not bisecting' ' + git bisect reset && + git branch > branch.output && + cmp branch.expect branch.output +' + +test_expect_success 'bisect reset removes packed refs' ' + git bisect reset && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH3 && + git pack-refs --all --prune && + git bisect next && + git bisect reset && + test -z "$(git for-each-ref "refs/bisect/*")" && + test -z "$(git for-each-ref "refs/heads/bisect")" +' + +test_expect_success 'bisect start: back in good branch' ' + git branch > branch.output && + grep "* other" branch.output > /dev/null && + git bisect start $HASH4 $HASH1 -- && + git bisect good && + git bisect start $HASH4 $HASH1 -- && + git bisect bad && + git bisect reset && + git branch > branch.output && + grep "* other" branch.output > /dev/null +' + +test_expect_success 'bisect start: no ".git/BISECT_START" if junk rev' ' + git bisect start $HASH4 $HASH1 -- && + git bisect good && + test_must_fail git bisect start $HASH4 foo -- && + git branch > branch.output && + grep "* other" branch.output > /dev/null && + test_must_fail test -e .git/BISECT_START +' + +test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' + git bisect start $HASH4 $HASH1 -- && + git bisect good && + test_must_fail git bisect start $HASH1 $HASH4 -- && + git branch > branch.output && + grep "* other" branch.output > /dev/null && + test_must_fail test -e .git/BISECT_START +' + +test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' ' + echo "temp stuff" > hello && + test_must_fail git bisect start $HASH4 $HASH1 -- && + git branch && + git branch > branch.output && + grep "* other" branch.output > /dev/null && + test_must_fail test -e .git/BISECT_START && + test -z "$(git for-each-ref "refs/bisect/*")" && + git checkout HEAD hello +' + +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 +# but $HASH2 is bad, +# so we should find $HASH2 as the first bad commit +test_expect_success 'bisect skip: successfull result' ' + git bisect reset && + git bisect start $HASH4 $HASH1 && + git bisect skip && + git bisect bad > my_bisect_log.txt && + grep "$HASH2 is the first bad commit" my_bisect_log.txt && + git bisect reset +' + +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2 +# so we should not be able to tell the first bad commit +# among $HASH2, $HASH3 and $HASH4 +test_expect_success 'bisect skip: cannot tell between 3 commits' ' + git bisect start $HASH4 $HASH1 && + git bisect skip || return 1 + + if git bisect skip > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH1 my_bisect_log.txt && + grep $HASH2 my_bisect_log.txt && + grep $HASH3 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect reset + fi +' + +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 +# but $HASH2 is good, +# so we should not be able to tell the first bad commit +# among $HASH3 and $HASH4 +test_expect_success 'bisect skip: cannot tell between 2 commits' ' + git bisect start $HASH4 $HASH1 && + git bisect skip || return 1 + + if git bisect good > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH1 my_bisect_log.txt && + ! grep $HASH2 my_bisect_log.txt && + grep $HASH3 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect reset + fi +' + +# $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3 +# and $HASH2 is good, +# so we should not be able to tell the first bad commit +# among $HASH3 and $HASH4 +test_expect_success 'bisect skip: with commit both bad and skipped' ' + git bisect start && + git bisect skip && + git bisect bad && + git bisect good $HASH1 && + git bisect skip && + if git bisect good > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH1 my_bisect_log.txt && + ! grep $HASH2 my_bisect_log.txt && + grep $HASH3 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect reset + fi +' + +# We want to automatically find the commit that +# introduced "Another" into hello. +test_expect_success \ + '"git bisect run" simple case' \ + 'echo "#"\!"/bin/sh" > test_script.sh && + echo "grep Another hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH3 is the first bad commit" my_bisect_log.txt && + git bisect reset' + +# We want to automatically find the commit that +# introduced "Ciao" into hello. +test_expect_success \ + '"git bisect run" with more complex "git bisect start"' \ + 'echo "#"\!"/bin/sh" > test_script.sh && + echo "grep Ciao hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start $HASH4 $HASH1 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH4 is the first bad commit" my_bisect_log.txt && + git bisect reset' + +# $HASH1 is good, $HASH5 is bad, we skip $HASH3 +# but $HASH4 is good, +# so we should find $HASH5 as the first bad commit +HASH5= +test_expect_success 'bisect skip: add line and then a new test' ' + add_line_into_file "5: Another new line." hello && + HASH5=$(git rev-parse --verify HEAD) && + git bisect start $HASH5 $HASH1 && + git bisect skip && + git bisect good > my_bisect_log.txt && + grep "$HASH5 is the first bad commit" my_bisect_log.txt && + git bisect log > log_to_replay.txt && + git bisect reset +' + +test_expect_success 'bisect skip and bisect replay' ' + git bisect replay log_to_replay.txt > my_bisect_log.txt && + grep "$HASH5 is the first bad commit" my_bisect_log.txt && + git bisect reset +' + +HASH6= +test_expect_success 'bisect run & skip: cannot tell between 2' ' + add_line_into_file "6: Yet a line." hello && + HASH6=$(git rev-parse --verify HEAD) && + echo "#"\!"/bin/sh" > test_script.sh && + echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh && + echo "grep line hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start $HASH6 $HASH1 && + if git bisect run ./test_script.sh > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH3 my_bisect_log.txt && + ! grep $HASH6 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + grep $HASH5 my_bisect_log.txt + fi +' + +HASH7= +test_expect_success 'bisect run & skip: find first bad' ' + git bisect reset && + add_line_into_file "7: Should be the last line." hello && + HASH7=$(git rev-parse --verify HEAD) && + echo "#"\!"/bin/sh" > test_script.sh && + echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh && + echo "sed -ne \\\$p hello | grep day > /dev/null && exit 125" >> test_script.sh && + echo "grep Yet hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start $HASH7 $HASH1 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH6 is the first bad commit" my_bisect_log.txt +' + +test_expect_success 'bisect skip only one range' ' + git bisect reset && + git bisect start $HASH7 $HASH1 && + git bisect skip $HASH1..$HASH5 && + test "$HASH6" = "$(git rev-parse --verify HEAD)" && + test_must_fail git bisect bad > my_bisect_log.txt && + grep "first bad commit could be any of" my_bisect_log.txt +' + +test_expect_success 'bisect skip many ranges' ' + git bisect start $HASH7 $HASH1 && + test "$HASH4" = "$(git rev-parse --verify HEAD)" && + git bisect skip $HASH2 $HASH2.. ..$HASH5 && + test "$HASH6" = "$(git rev-parse --verify HEAD)" && + test_must_fail git bisect bad > my_bisect_log.txt && + grep "first bad commit could be any of" my_bisect_log.txt +' + +test_expect_success 'bisect starting with a detached HEAD' ' + git bisect reset && + git checkout master^ && + HEAD=$(git rev-parse --verify HEAD) && + git bisect start && + test $HEAD = $(cat .git/BISECT_START) && + git bisect reset && + test $HEAD = $(git rev-parse --verify HEAD) +' + +test_expect_success 'bisect errors out if bad and good are mistaken' ' + git bisect reset && + test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error && + grep "mistake good and bad" rev_list_error && + git bisect reset +' + +test_expect_success 'bisect does not create a "bisect" branch' ' + git bisect reset && + git bisect start $HASH7 $HASH1 && + git branch bisect && + rev_hash4=$(git rev-parse --verify HEAD) && + test "$rev_hash4" = "$HASH4" && + git branch -D bisect && + git bisect good && + git branch bisect && + rev_hash6=$(git rev-parse --verify HEAD) && + test "$rev_hash6" = "$HASH6" && + git bisect good > my_bisect_log.txt && + grep "$HASH7 is the first bad commit" my_bisect_log.txt && + git bisect reset && + rev_hash6=$(git rev-parse --verify bisect) && + test "$rev_hash6" = "$HASH6" && + git branch -D bisect +' + +# This creates a "side" branch to test "siblings" cases. +# +# H1-H2-H3-H4-H5-H6-H7 <--other +# \ +# S5-S6-S7 <--side +# +test_expect_success 'side branch creation' ' + git bisect reset && + git checkout -b side $HASH4 && + add_line_into_file "5(side): first line on a side branch" hello2 && + SIDE_HASH5=$(git rev-parse --verify HEAD) && + add_line_into_file "6(side): second line on a side branch" hello2 && + SIDE_HASH6=$(git rev-parse --verify HEAD) && + add_line_into_file "7(side): third line on a side branch" hello2 && + SIDE_HASH7=$(git rev-parse --verify HEAD) +' + +test_expect_success 'good merge base when good and bad are siblings' ' + git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect good > my_bisect_log.txt && + test_must_fail grep "merge base must be tested" my_bisect_log.txt && + grep $HASH6 my_bisect_log.txt && + git bisect reset +' +test_expect_success 'skipped merge base when good and bad are siblings' ' + git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect skip > my_bisect_log.txt 2>&1 && + grep "warning" my_bisect_log.txt && + grep $SIDE_HASH6 my_bisect_log.txt && + git bisect reset +' + +test_expect_success 'bad merge base when good and bad are siblings' ' + git bisect start "$HASH7" HEAD > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + test_must_fail git bisect bad > my_bisect_log.txt 2>&1 && + grep "merge base $HASH4 is bad" my_bisect_log.txt && + grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && + git bisect reset +' + +# This creates a few more commits (A and B) to test "siblings" cases +# when a good and a bad rev have many merge bases. +# +# We should have the following: +# +# H1-H2-H3-H4-H5-H6-H7 +# \ \ \ +# S5-A \ +# \ \ +# S6-S7----B +# +# And there A and B have 2 merge bases (S5 and H5) that should be +# reported by "git merge-base --all A B". +# +test_expect_success 'many merge bases creation' ' + git checkout "$SIDE_HASH5" && + git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" && + A_HASH=$(git rev-parse --verify HEAD) && + git checkout side && + git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" && + B_HASH=$(git rev-parse --verify HEAD) && + git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt && + test $(wc -l < merge_bases.txt) = "2" && + grep "$HASH5" merge_bases.txt && + grep "$SIDE_HASH5" merge_bases.txt +' + +test_expect_success 'good merge bases when good and bad are siblings' ' + git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + git bisect good > my_bisect_log2.txt && + grep "merge base must be tested" my_bisect_log2.txt && + { + { + grep "$SIDE_HASH5" my_bisect_log.txt && + grep "$HASH5" my_bisect_log2.txt + } || { + grep "$SIDE_HASH5" my_bisect_log2.txt && + grep "$HASH5" my_bisect_log.txt + } + } && + git bisect reset +' + +test_expect_success 'optimized merge base checks' ' + git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && + grep "merge base must be tested" my_bisect_log.txt && + grep "$HASH4" my_bisect_log.txt && + git bisect good > my_bisect_log2.txt && + test -f ".git/BISECT_ANCESTORS_OK" && + test "$HASH6" = $(git rev-parse --verify HEAD) && + git bisect bad > my_bisect_log3.txt && + git bisect good "$A_HASH" > my_bisect_log4.txt && + grep "merge base must be tested" my_bisect_log4.txt && + test_must_fail test -f ".git/BISECT_ANCESTORS_OK" +' + +# This creates another side branch called "parallel" with some files +# in some directories, to test bisecting with paths. +# +# We should have the following: +# +# P1-P2-P3-P4-P5-P6-P7 +# / / / +# H1-H2-H3-H4-H5-H6-H7 +# \ \ \ +# S5-A \ +# \ \ +# S6-S7----B +# +test_expect_success '"parallel" side branch creation' ' + git bisect reset && + git checkout -b parallel $HASH1 && + mkdir dir1 dir2 && + add_line_into_file "1(para): line 1 on parallel branch" dir1/file1 && + PARA_HASH1=$(git rev-parse --verify HEAD) && + add_line_into_file "2(para): line 2 on parallel branch" dir2/file2 && + PARA_HASH2=$(git rev-parse --verify HEAD) && + add_line_into_file "3(para): line 3 on parallel branch" dir2/file3 && + PARA_HASH3=$(git rev-parse --verify HEAD) + git merge -m "merge HASH4 and PARA_HASH3" "$HASH4" && + PARA_HASH4=$(git rev-parse --verify HEAD) + add_line_into_file "5(para): add line on parallel branch" dir1/file1 && + PARA_HASH5=$(git rev-parse --verify HEAD) + add_line_into_file "6(para): add line on parallel branch" dir2/file2 && + PARA_HASH6=$(git rev-parse --verify HEAD) + git merge -m "merge HASH7 and PARA_HASH6" "$HASH7" && + PARA_HASH7=$(git rev-parse --verify HEAD) +' + +test_expect_success 'restricting bisection on one dir' ' + git bisect reset && + git bisect start HEAD $HASH1 -- dir1 && + para1=$(git rev-parse --verify HEAD) && + test "$para1" = "$PARA_HASH1" && + git bisect bad > my_bisect_log.txt && + grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt +' + +test_expect_success 'restricting bisection on one dir and a file' ' + git bisect reset && + git bisect start HEAD $HASH1 -- dir1 hello && + para4=$(git rev-parse --verify HEAD) && + test "$para4" = "$PARA_HASH4" && + git bisect bad && + hash3=$(git rev-parse --verify HEAD) && + test "$hash3" = "$HASH3" && + git bisect good && + hash4=$(git rev-parse --verify HEAD) && + test "$hash4" = "$HASH4" && + git bisect good && + para1=$(git rev-parse --verify HEAD) && + test "$para1" = "$PARA_HASH1" && + git bisect good > my_bisect_log.txt && + grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt +' + +test_expect_success 'skipping away from skipped commit' ' + git bisect start $PARA_HASH7 $HASH1 && + para4=$(git rev-parse --verify HEAD) && + test "$para4" = "$PARA_HASH4" && + git bisect skip && + hash7=$(git rev-parse --verify HEAD) && + test "$hash7" = "$HASH7" && + git bisect skip && + para3=$(git rev-parse --verify HEAD) && + test "$para3" = "$PARA_HASH3" +' + +test_expect_success 'erroring out when using bad path parameters' ' + test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt && + grep "bad path parameters" error.txt +' + +# +# +test_done diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh new file mode 100755 index 0000000000..8a3304fb0b --- /dev/null +++ b/t/t6031-merge-recursive.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +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_expect_success 'mode change in one branch: keep changed version' ' + : >file1 && + git add file1 && + git commit -m initial && + git checkout -b a1 master && + : >dummy && + git add dummy && + git commit -m a && + git checkout -b b1 master && + test_chmod +x file1 && + git commit -m b1 && + git checkout a1 && + git merge-recursive master -- a1 b1 && + git ls-files -s file1 | grep ^100755 +' + +test_expect_success FILEMODE 'verify executable bit on file' ' + test -x file1 +' + +test_expect_success 'mode change in both branches: expect conflict' ' + git reset --hard HEAD && + git checkout -b a2 master && + : >file2 && + H=$(git hash-object file2) && + test_chmod +x file2 && + git commit -m a2 && + git checkout -b b2 master && + : >file2 && + git add file2 && + git commit -m b2 && + git checkout a2 && + ( + git merge-recursive master -- a2 b2 + test $? = 1 + ) && + git ls-files -u >actual && + ( + echo "100755 $H 2 file2" + echo "100644 $H 3 file2" + ) >expect && + test_cmp actual expect && + git ls-files -s file2 | grep ^100755 +' + +test_expect_success FILEMODE 'verify executable bit on file' ' + test -x file2 +' + +test_done diff --git a/t/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh new file mode 100755 index 0000000000..eac5ebac24 --- /dev/null +++ b/t/t6032-merge-large-rename.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='merging with large rename matrix' +. ./test-lib.sh + +count() { + i=1 + while test $i -le $1; do + echo $i + i=$(($i + 1)) + done +} + +test_expect_success 'setup (initial)' ' + touch file && + git add . && + git commit -m initial && + git tag initial +' + +make_text() { + echo $1: $2 + for i in `count 20`; do + echo $1: $i + done + echo $1: $3 +} + +test_rename() { + test_expect_success "rename ($1, $2)" ' + n='$1' + expect='$2' + git checkout -f master && + git branch -D test$n || true && + git reset --hard initial && + for i in $(count $n); do + make_text $i initial initial >$i + done && + git add . && + git commit -m add=$n && + for i in $(count $n); do + make_text $i changed initial >$i + done && + git commit -a -m change=$n && + git checkout -b test$n HEAD^ && + for i in $(count $n); do + git rm $i + make_text $i initial changed >$i.moved + done && + git add . && + git commit -m change+rename=$n && + case "$expect" in + ok) git merge master ;; + *) test_must_fail git merge master ;; + esac + ' +} + +test_rename 5 ok + +test_expect_success 'set diff.renamelimit to 4' ' + git config diff.renamelimit 4 +' +test_rename 4 ok +test_rename 5 fail + +test_expect_success 'set merge.renamelimit to 5' ' + git config merge.renamelimit 5 +' +test_rename 5 ok +test_rename 6 fail + +test_done diff --git a/t/t6033-merge-crlf.sh b/t/t6033-merge-crlf.sh new file mode 100755 index 0000000000..e8d65eefb5 --- /dev/null +++ b/t/t6033-merge-crlf.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='merge conflict in crlf repo + + b---M + / / + initial---a + +' + +. ./test-lib.sh + +test_expect_success setup ' + git config core.autocrlf true && + echo foo | append_cr >file && + git add file && + git commit -m "Initial" && + git tag initial && + git branch side && + echo line from a | append_cr >file && + git commit -m "add line from a" file && + git tag a && + git checkout side && + echo line from b | append_cr >file && + git commit -m "add line from b" file && + git tag b && + git checkout master +' + +test_expect_success 'Check "ours" is CRLF' ' + git reset --hard initial && + git merge side -s ours && + cat file | remove_cr | append_cr >file.temp && + test_cmp file file.temp +' + +test_expect_success 'Check that conflict file is CRLF' ' + git reset --hard a && + test_must_fail git merge side && + cat file | remove_cr | append_cr >file.temp && + test_cmp file file.temp +' + +test_done diff --git a/t/t6023-merge-rename-nocruft.sh b/t/t6034-merge-rename-nocruft.sh index 65be95fbaa..65be95fbaa 100755 --- a/t/t6023-merge-rename-nocruft.sh +++ b/t/t6034-merge-rename-nocruft.sh diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh new file mode 100755 index 0000000000..cd3190c4a6 --- /dev/null +++ b/t/t6035-merge-dir-to-symlink.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +test_description='merging when a directory was replaced with a symlink' +. ./test-lib.sh + +if ! test_have_prereq SYMLINKS +then + skip_all='Symbolic links not supported, skipping tests.' + test_done +fi + +test_expect_success '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 && + > a/x && + git add -A && + git commit -m base && + git tag start && + rm -rf a/b && + ln -s b-2 a/b && + git add -A && + git commit -m "dir to symlink" +' + +test_expect_success 'keep a/b-2/c/d across checkout' ' + git checkout HEAD^0 && + git reset --hard master && + git rm --cached a/b && + git commit -m "untracked symlink remains" && + git checkout start^0 && + test -f a/b-2/c/d +' + +test_expect_success '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' ' + git reset --hard && + test -f a/b-2/c/d && + echo x > a/x && + git add a/x && + git commit -m x && + git tag baseline +' + +test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' ' + git reset --hard && + git checkout baseline^0 && + git merge -s resolve master && + test -h a/b && + test -f a/b-2/c/d +' + +test_expect_failure 'do not lose a/b-2/c/d in merge (recursive)' ' + git reset --hard && + git checkout baseline^0 && + git merge -s recursive master && + test -h a/b && + test -f a/b-2/c/d +' + +test_expect_success 'setup a merge where dir a/b-2 changed to symlink' ' + git reset --hard && + git checkout start^0 && + rm -rf a/b-2 && + ln -s b a/b-2 && + git add -A && + git commit -m "dir a/b-2 to symlink" && + git tag test2 +' + +test_expect_success 'merge should not have conflicts (resolve)' ' + git reset --hard && + git checkout baseline^0 && + git merge -s resolve test2 && + test -h a/b-2 && + test -f a/b/c/d +' + +test_expect_failure 'merge should not have conflicts (recursive)' ' + git reset --hard && + git checkout baseline^0 && + git merge -s recursive test2 && + test -h a/b-2 && + test -f a/b/c/d +' + +test_done diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh new file mode 100755 index 0000000000..b874141658 --- /dev/null +++ b/t/t6036-recursive-corner-cases.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='recursive merge corner cases' + +. ./test-lib.sh + +# +# L1 L2 +# o---o +# / \ / \ +# o X ? +# \ / \ / +# o---o +# R1 R2 +# + +test_expect_success setup ' + ten="0 1 2 3 4 5 6 7 8 9" + for i in $ten + do + echo line $i in a sample file + done >one && + for i in $ten + do + echo line $i in another sample file + done >two && + git add one two && + test_tick && git commit -m initial && + + git branch L1 && + git checkout -b R1 && + git mv one three && + test_tick && git commit -m R1 && + + git checkout L1 && + git mv two three && + test_tick && git commit -m L1 && + + git checkout L1^0 && + test_tick && git merge -s ours R1 && + git tag L2 && + + git checkout R1^0 && + test_tick && git merge -s ours L1 && + git tag R2 +' + +test_expect_success merge ' + git reset --hard && + git checkout L2^0 && + + test_must_fail git merge -s recursive R2^0 +' + +test_done diff --git a/t/t6037-merge-ours-theirs.sh b/t/t6037-merge-ours-theirs.sh new file mode 100755 index 0000000000..8ab3d61f44 --- /dev/null +++ b/t/t6037-merge-ours-theirs.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +test_description='Merge-recursive ours and theirs variants' +. ./test-lib.sh + +test_expect_success setup ' + for i in 1 2 3 4 5 6 7 8 9 + do + echo "$i" + done >file && + git add file && + cp file elif && + git commit -m initial && + + sed -e "s/1/one/" -e "s/9/nine/" >file <elif && + git commit -a -m ours && + + git checkout -b side HEAD^ && + + sed -e "s/9/nueve/" >file <elif && + git commit -a -m theirs && + + git checkout master^0 +' + +test_expect_success 'plain recursive - should conflict' ' + git reset --hard master && + test_must_fail git merge -s recursive side && + grep nine file && + grep nueve file && + ! grep 9 file && + grep one file && + ! grep 1 file +' + +test_expect_success 'recursive favouring theirs' ' + git reset --hard master && + git merge -s recursive -Xtheirs side && + ! grep nine file && + grep nueve file && + ! grep 9 file && + grep one file && + ! grep 1 file +' + +test_expect_success 'recursive favouring ours' ' + git reset --hard master && + git merge -s recursive -X ours side && + grep nine file && + ! grep nueve file && + ! grep 9 file && + grep one file && + ! grep 1 file +' + +test_expect_success 'pull with -X' ' + git reset --hard master && git pull -s recursive -Xours . side && + 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 +' + +test_done diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh new file mode 100755 index 0000000000..1785e178a4 --- /dev/null +++ b/t/t6040-tracking-info.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +test_description='remote tracking stats' + +. ./test-lib.sh + +advance () { + echo "$1" >"$1" && + git add "$1" && + test_tick && + git commit -m "$1" +} + +test_expect_success setup ' + for i in a b c; + do + advance $i || break + done && + git clone . test && + ( + cd test && + git checkout -b b1 origin && + git reset --hard HEAD^ && + advance d && + git checkout -b b2 origin && + git reset --hard b1 && + git checkout -b b3 origin && + git reset --hard HEAD^ && + git checkout -b b4 origin && + advance e && + advance f + ) && + git checkout -b follower --track master && + advance g +' + +script='s/^..\(b.\)[ 0-9a-f]*\[\([^]]*\)\].*/\1 \2/p' +cat >expect <<\EOF +b1 ahead 1, behind 1 +b2 ahead 1, behind 1 +b3 behind 1 +b4 ahead 2 +EOF + +test_expect_success 'branch -v' ' + ( + cd test && + git branch -v + ) | + sed -n -e "$script" >actual && + test_cmp expect actual +' + +test_expect_success 'checkout' ' + ( + cd test && git checkout b1 + ) >actual && + grep "have 1 and 1 different" actual +' + +test_expect_success 'checkout with local tracked branch' ' + git checkout master && + git checkout follower >actual + grep "is ahead of" actual +' + +test_expect_success 'status' ' + ( + cd test && + git checkout b1 >/dev/null && + # reports nothing to commit + test_must_fail git commit --dry-run + ) >actual && + grep "have 1 and 1 different" actual +' + +test_expect_success 'status when tracking lightweight tags' ' + git checkout master && + git tag light && + git branch --track lighttrack light >actual && + grep "set up to track" actual && + git checkout lighttrack +' + +test_expect_success 'status when tracking annotated tags' ' + git checkout master && + git tag -m heavy heavy && + git branch --track heavytrack heavy >actual && + grep "set up to track" actual && + git checkout heavytrack +' + +test_expect_success 'setup tracking with branch --set-upstream on existing branch' ' + git branch from-master master && + test_must_fail git config branch.from-master.merge > actual && + git branch --set-upstream from-master master && + git config branch.from-master.merge > actual && + grep -q "^refs/heads/master$" actual +' + +test_expect_success '--set-upstream does not change branch' ' + git branch from-master2 master && + test_must_fail git config branch.from-master2.merge > actual && + git rev-list from-master2 && + git update-ref refs/heads/from-master2 from-master2^ && + git rev-parse from-master2 >expect2 && + git branch --set-upstream from-master2 master && + git config branch.from-master.merge > actual && + git rev-parse from-master2 >actual2 && + grep -q "^refs/heads/master$" actual && + cmp expect2 actual2 +' +test_done diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh new file mode 100755 index 0000000000..4185b7ca1d --- /dev/null +++ b/t/t6050-replace.sh @@ -0,0 +1,230 @@ +#!/bin/sh +# +# Copyright (c) 2008 Christian Couder +# +test_description='Tests replace refs functionality' + +exec </dev/null + +. ./test-lib.sh + +add_and_commit_file() +{ + _file="$1" + _msg="$2" + + git add $_file || return $? + test_tick || return $? + git commit --quiet -m "$_file: $_msg" +} + +HASH1= +HASH2= +HASH3= +HASH4= +HASH5= +HASH6= +HASH7= + +test_expect_success 'set up buggy branch' ' + echo "line 1" >> hello && + echo "line 2" >> hello && + echo "line 3" >> hello && + echo "line 4" >> hello && + add_and_commit_file hello "4 lines" && + HASH1=$(git rev-parse --verify HEAD) && + echo "line BUG" >> hello && + echo "line 6" >> hello && + echo "line 7" >> hello && + echo "line 8" >> hello && + add_and_commit_file hello "4 more lines with a BUG" && + HASH2=$(git rev-parse --verify HEAD) && + echo "line 9" >> hello && + echo "line 10" >> hello && + add_and_commit_file hello "2 more lines" && + HASH3=$(git rev-parse --verify HEAD) && + echo "line 11" >> hello && + add_and_commit_file hello "1 more line" && + HASH4=$(git rev-parse --verify HEAD) && + sed -e "s/BUG/5/" hello > hello.new && + mv hello.new hello && + add_and_commit_file hello "BUG fixed" && + HASH5=$(git rev-parse --verify HEAD) && + echo "line 12" >> hello && + echo "line 13" >> hello && + add_and_commit_file hello "2 more lines" && + HASH6=$(git rev-parse --verify HEAD) + echo "line 14" >> hello && + echo "line 15" >> hello && + echo "line 16" >> hello && + add_and_commit_file hello "again 3 more lines" && + HASH7=$(git rev-parse --verify HEAD) +' + +test_expect_success 'replace the author' ' + git cat-file commit $HASH2 | grep "author A U Thor" && + R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && + git cat-file commit $R | grep "author O Thor" && + git update-ref refs/replace/$HASH2 $R && + git show HEAD~5 | grep "O Thor" && + git show $HASH2 | grep "O Thor" +' + +test_expect_success 'test --no-replace-objects option' ' + git cat-file commit $HASH2 | grep "author O Thor" && + git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" && + git show $HASH2 | grep "O Thor" && + git --no-replace-objects show $HASH2 | grep "A U Thor" +' + +test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' ' + GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" && + GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor" +' + +cat >tag.sig <<EOF +object $HASH2 +type commit +tag mytag +tagger T A Gger <> 0 +0000 + +EOF + +test_expect_success 'tag replaced commit' ' + git mktag <tag.sig >.git/refs/tags/mytag 2>message +' + +test_expect_success '"git fsck" works' ' + git fsck master > fsck_master.out && + grep "dangling commit $R" fsck_master.out && + grep "dangling tag $(cat .git/refs/tags/mytag)" fsck_master.out && + test -z "$(git fsck)" +' + +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 .. +' + +test_expect_success '"git replace" listing and deleting' ' + test "$HASH2" = "$(git replace -l)" && + test "$HASH2" = "$(git replace)" && + aa=${HASH2%??????????????????????????????????????} && + test "$HASH2" = "$(git replace -l "$aa*")" && + test_must_fail git replace -d $R && + test_must_fail git replace -d && + test_must_fail git replace -l -d $HASH2 && + git replace -d $HASH2 && + git show $HASH2 | grep "A U Thor" && + test -z "$(git replace -l)" +' + +test_expect_success '"git replace" replacing' ' + git replace $HASH2 $R && + git show $HASH2 | grep "O Thor" && + test_must_fail git replace $HASH2 $R && + git replace -f $HASH2 $R && + test_must_fail git replace -f && + test "$HASH2" = "$(git replace)" +' + +# This creates a side branch where the bug in H2 +# does not appear because P2 is created by applying +# H2 and squashing H5 into it. +# P3, P4 and P6 are created by cherry-picking H3, H4 +# and H6 respectively. +# +# At this point, we should have the following: +# +# P2--P3--P4--P6 +# / +# H1-H2-H3-H4-H5-H6-H7 +# +# Then we replace H6 with P6. +# +test_expect_success 'create parallel branch without the bug' ' + git replace -d $HASH2 && + git show $HASH2 | grep "A U Thor" && + git checkout $HASH1 && + git cherry-pick $HASH2 && + git show $HASH5 | git apply && + git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello && + PARA2=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH3 && + PARA3=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH4 && + PARA4=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH6 && + PARA6=$(git rev-parse --verify HEAD) && + git replace $HASH6 $PARA6 && + git checkout master && + cur=$(git rev-parse --verify HEAD) && + test "$cur" = "$HASH7" && + git log --pretty=oneline | grep $PARA2 && + git remote add cloned ./clone_dir +' + +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 .. +' + +test_expect_success 'push branch with replacement' ' + git cat-file commit $PARA3 | grep "author A U Thor" && + S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && + git cat-file commit $S | grep "author O Thor" && + git replace $PARA3 $S && + 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 .. +' + +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 .. +' + +test_expect_success 'bisect and replacements' ' + git bisect start $HASH7 $HASH1 && + test "$S" = "$(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)" && + git bisect reset && + git --no-replace-objects bisect start $HASH7 $HASH1 && + test "$HASH4" = "$(git rev-parse --verify HEAD)" && + 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 7d354a1fae..e673c25e94 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -3,31 +3,42 @@ # Copyright (c) 2005 Johannes Schindelin # -test_description='Test git-rev-parse with different parent options' +test_description='Test git rev-parse with different parent options' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions date >path0 -git-update-index --add path0 -save_tag tree git-write-tree +git update-index --add path0 +save_tag tree git write-tree hide_error save_tag start unique_commit "start" tree save_tag second unique_commit "second" tree -p start hide_error save_tag start2 unique_commit "start2" tree save_tag two_parents unique_commit "next" tree -p second -p start2 save_tag final unique_commit "final" tree -p two_parents -test_expect_success 'start is valid' 'git-rev-parse start | grep "^[0-9a-f]\{40\}$"' -test_expect_success 'start^0' "test $(cat .git/refs/tags/start) = $(git-rev-parse start^0)" -test_expect_success 'start^1 not valid' "if git-rev-parse --verify start^1; then false; else :; fi" -test_expect_success 'second^1 = second^' "test $(git-rev-parse second^1) = $(git-rev-parse second^)" -test_expect_success 'final^1^1^1' "test $(git-rev-parse start) = $(git-rev-parse final^1^1^1)" -test_expect_success 'final^1^1^1 = final^^^' "test $(git-rev-parse final^1^1^1) = $(git-rev-parse final^^^)" -test_expect_success 'final^1^2' "test $(git-rev-parse start2) = $(git-rev-parse final^1^2)" -test_expect_success 'final^1^2 != final^1^1' "test $(git-rev-parse final^1^2) != $(git-rev-parse final^1^1)" -test_expect_success 'final^1^3 not valid' "if git-rev-parse --verify final^1^3; then false; else :; fi" -test_expect_failure '--verify start2^1' 'git-rev-parse --verify start2^1' -test_expect_success '--verify start2^0' 'git-rev-parse --verify start2^0' +test_expect_success 'start is valid' 'git rev-parse start | grep "^[0-9a-f]\{40\}$"' +test_expect_success 'start^0' "test $(cat .git/refs/tags/start) = $(git rev-parse start^0)" +test_expect_success 'start^1 not valid' "if git rev-parse --verify start^1; then false; else :; fi" +test_expect_success 'second^1 = second^' "test $(git rev-parse second^1) = $(git rev-parse second^)" +test_expect_success 'final^1^1^1' "test $(git rev-parse start) = $(git rev-parse final^1^1^1)" +test_expect_success 'final^1^1^1 = final^^^' "test $(git rev-parse final^1^1^1) = $(git rev-parse final^^^)" +test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)" +test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)" +test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi" +test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1' +test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0' +test_expect_success 'final^1^@ = final^1^1 final^1^2' "test \"$(git rev-parse final^1^@)\" = \"$(git rev-parse final^1^1 final^1^2)\"" +test_expect_success 'final^1^! = final^1 ^final^1^1 ^final^1^2' "test \"$(git rev-parse final^1^\!)\" = \"$(git rev-parse final^1 ^final^1^1 ^final^1^2)\"" -test_done +test_expect_success 'repack for next test' 'git repack -a -d' +test_expect_success 'short SHA-1 works' ' + start=`git rev-parse --verify start` && + echo $start && + abbrv=`echo $start | sed s/.\$//` && + echo $abbrv && + abbrv=`git rev-parse --verify $abbrv` && + echo $abbrv && + test $start = $abbrv' +test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 3e9edda1ca..876d1ab743 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -8,15 +8,18 @@ test_description='test describe o----o----o----o----o----. / \ A c / .------------o---o---o - D e + D,R e ' . ./test-lib.sh check_describe () { expect="$1" shift - R=$(git describe "$@") && + R=$(git describe "$@" 2>err.actual) + S=$? + cat err.actual >&3 test_expect_success "describe $*" ' + test $S = 0 && case "$R" in $expect) echo happy ;; *) echo "Oops - $R is not $expect"; @@ -28,70 +31,144 @@ check_describe () { test_expect_success setup ' test_tick && - echo one >file && git-add file && git-commit -m initial && - one=$(git-rev-parse HEAD) && + echo one >file && git add file && git commit -m initial && + one=$(git rev-parse HEAD) && + + git describe --always HEAD && test_tick && - echo two >file && git-add file && git-commit -m second && - two=$(git-rev-parse HEAD) && + echo two >file && git add file && git commit -m second && + two=$(git rev-parse HEAD) && test_tick && - echo three >file && git-add file && git-commit -m third && + echo three >file && git add file && git commit -m third && test_tick && - echo A >file && git-add file && git-commit -m A && + echo A >file && git add file && git commit -m A && test_tick && - git-tag -a -m A A && + git tag -a -m A A && test_tick && - echo c >file && git-add file && git-commit -m c && + echo c >file && git add file && git commit -m c && test_tick && - git-tag c && + git tag c && git reset --hard $two && test_tick && - echo B >side && git-add side && git-commit -m B && + echo B >side && git add side && git commit -m B && test_tick && - git-tag -a -m B B && + git tag -a -m B B && test_tick && - git-merge -m Merged c && - merged=$(git-rev-parse HEAD) && + git merge -m Merged c && + merged=$(git rev-parse HEAD) && git reset --hard $two && test_tick && - echo D >another && git-add another && git-commit -m D && + echo D >another && git add another && git commit -m D && + test_tick && + git tag -a -m D D && test_tick && - git-tag -a -m D D && + git tag -a -m R R && test_tick && echo DD >another && git commit -a -m another && test_tick && - git-tag e && + git tag e && test_tick && echo DDD >another && git commit -a -m "yet another" && test_tick && - git-merge -m Merged $merged && + git merge -m Merged $merged && test_tick && - echo X >file && echo X >side && git-add file side && - git-commit -m x + echo X >file && echo X >side && git add file side && + git commit -m x ' 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 R-* HEAD^^^ -check_describe A-* --tags HEAD -check_describe A-* --tags HEAD^ -check_describe D-* --tags HEAD^^ -check_describe A-* --tags HEAD^^2 +check_describe c-* --tags HEAD +check_describe c-* --tags HEAD^ +check_describe e-* --tags HEAD^^ +check_describe c-* --tags HEAD^^2 check_describe B --tags HEAD^^2^ +check_describe e --tags HEAD^^^ + +check_describe heads/master --all HEAD +check_describe tags/c-* --all HEAD^ +check_describe tags/e --all HEAD^^^ + +check_describe B-0-* --long HEAD^^2^ +check_describe A-3-* --long HEAD^^2 + +: >err.expect +check_describe A --all A^0 +test_expect_success 'no warning was displayed for A' ' + test_cmp err.expect err.actual +' + +test_expect_success 'rename tag A to Q locally' ' + mv .git/refs/tags/A .git/refs/tags/Q +' +cat - >err.expect <<EOF +warning: tag 'A' is really 'Q' here +EOF +check_describe A-* HEAD +test_expect_success 'warning was displayed for Q' ' + test_cmp err.expect err.actual +' +test_expect_success 'rename tag Q back to A' ' + mv .git/refs/tags/Q .git/refs/tags/A +' + +test_expect_success 'pack tag refs' 'git pack-refs' +check_describe A-* HEAD + +check_describe "A-*[0-9a-f]" --dirty + +test_expect_success 'set-up dirty work tree' ' + echo >>file +' + +check_describe "A-*[0-9a-f]-dirty" --dirty + +check_describe "A-*[0-9a-f].mod" --dirty=.mod + +test_expect_success 'describe --dirty HEAD' ' + test_must_fail git describe --dirty HEAD +' + +test_expect_success 'set-up matching pattern tests' ' + git tag -a -m test-annotated test-annotated && + echo >>file && + test_tick && + git commit -a -m "one more" && + git tag test1-lightweight && + echo >>file && + test_tick && + git commit -a -m "yet another" && + git tag test2-lightweight && + echo >>file && + test_tick && + git commit -a -m "even more" + +' + +check_describe "test-annotated-*" --match="test-*" + +check_describe "test1-lightweight-*" --tags --match="test1-*" + +check_describe "test2-lightweight-*" --tags --match="test2-*" + +check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^ test_done diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index ea14023616..42f8ece097 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -7,65 +7,69 @@ test_description='fmt-merge-msg test' . ./test-lib.sh -datestamp=1151939923 -setdate () { - GIT_COMMITTER_DATE="$datestamp +0200" - GIT_AUTHOR_DATE="$datestamp +0200" - datestamp=`expr "$datestamp" + 1` - export GIT_COMMITTER_DATE GIT_AUTHOR_DATE -} - test_expect_success setup ' echo one >one && git add one && - setdate && + test_tick && git commit -m "Initial" && + git clone . remote && + echo uno >one && echo dos >two && git add two && - setdate && + test_tick && git commit -a -m "Second" && git checkout -b left && - echo $datestamp >one && - setdate && + echo "c1" >one && + test_tick && git commit -a -m "Common #1" && - echo $datestamp >one && - setdate && + echo "c2" >one && + test_tick && git commit -a -m "Common #2" && git branch right && - echo $datestamp >two && - setdate && + echo "l3" >two && + test_tick && git commit -a -m "Left #3" && - echo $datestamp >two && - setdate && + echo "l4" >two && + test_tick && git commit -a -m "Left #4" && - echo $datestamp >two && - setdate && + echo "l5" >two && + test_tick && git commit -a -m "Left #5" && + git tag tag-l5 && git checkout right && - echo $datestamp >three && + echo "r3" >three && git add three && - setdate && + test_tick && git commit -a -m "Right #3" && + git tag tag-r3 && - echo $datestamp >three && - setdate && + echo "r4" >three && + test_tick && git commit -a -m "Right #4" && - echo $datestamp >three && - setdate && + echo "r5" >three && + test_tick && git commit -a -m "Right #5" && + git checkout -b long && + i=0 && + while test $i -lt 30 + do + test_commit $i one && + i=$(($i+1)) + done && + git show-branch ' @@ -79,20 +83,20 @@ test_expect_success 'merge-msg test #1' ' git fetch . left && git fmt-merge-msg <.git/FETCH_HEAD >actual && - diff -u actual expected + test_cmp expected actual ' -cat >expected <<\EOF -Merge branch 'left' of ../trash +cat >expected <<EOF +Merge branch 'left' of $(pwd) EOF test_expect_success 'merge-msg test #2' ' git checkout master && - git fetch ../trash left && + git fetch "$(pwd)" left && git fmt-merge-msg <.git/FETCH_HEAD >actual && - diff -u actual expected + test_cmp expected actual ' cat >expected <<\EOF @@ -106,16 +110,32 @@ Merge branch 'left' Common #1 EOF -test_expect_success 'merge-msg test #3' ' +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 && + + 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 config --unset-all merge.log + git config --unset-all merge.summary git config merge.summary true && git checkout master && - setdate && + test_tick && git fetch . left && git fmt-merge-msg <.git/FETCH_HEAD >actual && - diff -u actual expected + test_cmp expected actual ' cat >expected <<\EOF @@ -136,28 +156,216 @@ Merge branches 'left' and 'right' Common #1 EOF -test_expect_success 'merge-msg test #4' ' +test_expect_success 'merge-msg test #4-1' ' + + git config --unset-all merge.log + git config --unset-all merge.summary + git config merge.log true && + + git checkout master && + test_tick && + git fetch . left right && + + git fmt-merge-msg <.git/FETCH_HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'merge-msg test #4-2' ' + git config --unset-all merge.log + git config --unset-all merge.summary git config merge.summary true && git checkout master && - setdate && + test_tick && git fetch . left right && git fmt-merge-msg <.git/FETCH_HEAD >actual && - diff -u actual expected + test_cmp expected actual ' -test_expect_success 'merge-msg test #5' ' +test_expect_success 'merge-msg test #5-1' ' + + git config --unset-all merge.log + git config --unset-all merge.summary + git config merge.log yes && + git checkout master && + test_tick && + git fetch . left right && + + git fmt-merge-msg <.git/FETCH_HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'merge-msg test #5-2' ' + + git config --unset-all merge.log + git config --unset-all merge.summary git config merge.summary yes && git checkout master && - setdate && + test_tick && git fetch . left right && git fmt-merge-msg <.git/FETCH_HEAD >actual && - diff -u actual expected + test_cmp expected actual +' + +test_expect_success 'merge-msg -F' ' + + git config --unset-all merge.log + git config --unset-all merge.summary + 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 + git config merge.summary yes && + + git checkout master && + test_tick && + git fetch . left right && + mkdir sub && + cp .git/FETCH_HEAD sub/FETCH_HEAD && + ( + cd sub && + git fmt-merge-msg -F FETCH_HEAD >../actual + ) && + test_cmp expected actual +' + +test_expect_success 'merge-msg with nothing to merge' ' + + git config --unset-all merge.log + git config --unset-all merge.summary + git config merge.summary yes && + + ( + cd remote && + git checkout -b unrelated && + test_tick && + git fetch origin && + git fmt-merge-msg <.git/FETCH_HEAD >../actual + ) && + + test_cmp /dev/null actual +' + +cat >expected <<\EOF +Merge tag 'tag-r3' + +* tag 'tag-r3': + Right #3 + Common #2 + Common #1 +EOF + +test_expect_success 'merge-msg tag' ' + + git config --unset-all merge.log + git config --unset-all merge.summary + git config merge.summary yes && + + git checkout master && + test_tick && + git fetch . tag tag-r3 && + + git fmt-merge-msg <.git/FETCH_HEAD >actual && + 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 + git config merge.summary yes && + + git checkout master && + test_tick && + git fetch . tag tag-r3 tag tag-l5 && + + git fmt-merge-msg <.git/FETCH_HEAD >actual && + 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 + git config merge.summary yes && + + git checkout master && + test_tick && + git fetch . tag tag-r3 left && + + git fmt-merge-msg <.git/FETCH_HEAD >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +Merge branch 'long' + +* long: (35 commits) +EOF + +test_expect_success 'merge-msg lots of commits' ' + + 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 ' test_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh new file mode 100755 index 0000000000..7dc8a510c7 --- /dev/null +++ b/t/t6300-for-each-ref.sh @@ -0,0 +1,362 @@ +#!/bin/sh +# +# Copyright (c) 2007 Andy Parkins +# + +test_description='for-each-ref test' + +. ./test-lib.sh + +# Mon Jul 3 15:18:43 2006 +0000 +datestamp=1151939923 +setdate_and_increment () { + GIT_COMMITTER_DATE="$datestamp +0200" + datestamp=$(expr "$datestamp" + 1) + GIT_AUTHOR_DATE="$datestamp +0200" + datestamp=$(expr "$datestamp" + 1) + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE +} + +test_expect_success 'Create sample commit with known timestamp' ' + setdate_and_increment && + echo "Using $datestamp" > one && + git add one && + git commit -m "Initial" && + setdate_and_increment && + git tag -a -m "Tagging at $datestamp" testtag +' + +test_expect_success 'Create upstream config' ' + git update-ref refs/remotes/origin/master master && + git remote add origin nowhere && + git config branch.master.remote origin && + git config branch.master.merge refs/heads/master +' + +test_atom() { + case "$1" in + head) ref=refs/heads/master ;; + tag) ref=refs/tags/testtag ;; + esac + printf '%s\n' "$3" >expected + test_expect_${4:-success} "basic atom: $1 $2" " + git for-each-ref --format='%($2)' $ref >actual && + test_cmp expected actual + " +} + +test_atom head refname refs/heads/master +test_atom head upstream refs/remotes/origin/master +test_atom head objecttype commit +test_atom head objectsize 171 +test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581 +test_atom head tree 0e51c00fcb93dffc755546f27593d511e1bdb46f +test_atom head parent '' +test_atom head numparent 0 +test_atom head object '' +test_atom head type '' +test_atom head author 'A U Thor <author@example.com> 1151939924 +0200' +test_atom head authorname 'A U Thor' +test_atom head authoremail '<author@example.com>' +test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200' +test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200' +test_atom head committername 'C O Mitter' +test_atom head committeremail '<committer@example.com>' +test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200' +test_atom head tag '' +test_atom head tagger '' +test_atom head taggername '' +test_atom head taggeremail '' +test_atom head taggerdate '' +test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200' +test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200' +test_atom head subject 'Initial' +test_atom head body '' +test_atom head contents 'Initial +' + +test_atom tag refname refs/tags/testtag +test_atom tag upstream '' +test_atom tag objecttype tag +test_atom tag objectsize 154 +test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322 +test_atom tag tree '' +test_atom tag parent '' +test_atom tag numparent '' +test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581' +test_atom tag type 'commit' +test_atom tag author '' +test_atom tag authorname '' +test_atom tag authoremail '' +test_atom tag authordate '' +test_atom tag committer '' +test_atom tag committername '' +test_atom tag committeremail '' +test_atom tag committerdate '' +test_atom tag tag 'testtag' +test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200' +test_atom tag taggername 'C O Mitter' +test_atom tag taggeremail '<committer@example.com>' +test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200' +test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200' +test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200' +test_atom tag subject 'Tagging at 1151939927' +test_atom tag body '' +test_atom tag contents 'Tagging at 1151939927 +' + +test_expect_success 'Check invalid atoms names are errors' ' + test_must_fail git for-each-ref --format="%(INVALID)" refs/heads +' + +test_expect_success 'Check format specifiers are ignored in naming date atoms' ' + git for-each-ref --format="%(authordate)" refs/heads && + git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads && + git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads && + git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads +' + +test_expect_success 'Check valid format specifiers for date fields' ' + git for-each-ref --format="%(authordate:default)" refs/heads && + git for-each-ref --format="%(authordate:relative)" refs/heads && + git for-each-ref --format="%(authordate:short)" refs/heads && + git for-each-ref --format="%(authordate:local)" refs/heads && + git for-each-ref --format="%(authordate:iso8601)" refs/heads && + git for-each-ref --format="%(authordate:rfc2822)" refs/heads +' + +test_expect_success 'Check invalid format specifiers are errors' ' + test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads +' + +cat >expected <<\EOF +'refs/heads/master' 'Mon Jul 3 17:18:43 2006 +0200' 'Mon Jul 3 17:18:44 2006 +0200' +'refs/tags/testtag' 'Mon Jul 3 17:18:45 2006 +0200' +EOF + +test_expect_success 'Check unformatted date fields output' ' + (git for-each-ref --shell --format="%(refname) %(committerdate) %(authordate)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate)" refs/tags) >actual && + test_cmp expected actual +' + +test_expect_success 'Check format "default" formatted date fields output' ' + f=default && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual && + test_cmp expected actual +' + +# Don't know how to do relative check because I can't know when this script +# is going to be run and can't fake the current time to git, and hence can't +# provide expected output. Instead, I'll just make sure that "relative" +# doesn't exit in error +# +#cat >expected <<\EOF +# +#EOF +# +test_expect_success 'Check format "relative" date fields output' ' + f=relative && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual +' + +cat >expected <<\EOF +'refs/heads/master' '2006-07-03' '2006-07-03' +'refs/tags/testtag' '2006-07-03' +EOF + +test_expect_success 'Check format "short" date fields output' ' + f=short && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +'refs/heads/master' 'Mon Jul 3 15:18:43 2006' 'Mon Jul 3 15:18:44 2006' +'refs/tags/testtag' 'Mon Jul 3 15:18:45 2006' +EOF + +test_expect_success 'Check format "local" date fields output' ' + f=local && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +'refs/heads/master' '2006-07-03 17:18:43 +0200' '2006-07-03 17:18:44 +0200' +'refs/tags/testtag' '2006-07-03 17:18:45 +0200' +EOF + +test_expect_success 'Check format "iso8601" date fields output' ' + f=iso8601 && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +'refs/heads/master' 'Mon, 3 Jul 2006 17:18:43 +0200' 'Mon, 3 Jul 2006 17:18:44 +0200' +'refs/tags/testtag' 'Mon, 3 Jul 2006 17:18:45 +0200' +EOF + +test_expect_success 'Check format "rfc2822" date fields output' ' + f=rfc2822 && + (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads && + git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +refs/heads/master +refs/remotes/origin/master +refs/tags/testtag +EOF + +test_expect_success 'Verify ascending sort' ' + git for-each-ref --format="%(refname)" --sort=refname >actual && + test_cmp expected actual +' + + +cat >expected <<\EOF +refs/tags/testtag +refs/remotes/origin/master +refs/heads/master +EOF + +test_expect_success 'Verify descending sort' ' + git for-each-ref --format="%(refname)" --sort=-refname >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +'refs/heads/master' +'refs/remotes/origin/master' +'refs/tags/testtag' +EOF + +test_expect_success 'Quoting style: shell' ' + git for-each-ref --shell --format="%(refname)" >actual && + test_cmp expected actual +' + +test_expect_success 'Quoting style: perl' ' + git for-each-ref --perl --format="%(refname)" >actual && + test_cmp expected actual +' + +test_expect_success 'Quoting style: python' ' + git for-each-ref --python --format="%(refname)" >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +"refs/heads/master" +"refs/remotes/origin/master" +"refs/tags/testtag" +EOF + +test_expect_success 'Quoting style: tcl' ' + git for-each-ref --tcl --format="%(refname)" >actual && + test_cmp expected actual +' + +for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do + test_expect_success "more than one quoting style: $i" " + git for-each-ref $i 2>&1 | (read line && + case \$line in + \"error: more than one quoting style\"*) : happy;; + *) false + esac) + " +done + +cat >expected <<\EOF +master +testtag +EOF + +test_expect_success 'Check short refname format' ' + (git for-each-ref --format="%(refname:short)" refs/heads && + git for-each-ref --format="%(refname:short)" refs/tags) >actual && + test_cmp expected actual +' + +cat >expected <<EOF +origin/master +EOF + +test_expect_success 'Check short upstream format' ' + git for-each-ref --format="%(upstream:short)" refs/heads >actual && + 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)" +' + +cat >expected <<\EOF +heads/master +tags/master +EOF + +test_expect_success 'Check ambiguous head and tag refs (strict)' ' + git config --bool core.warnambiguousrefs true && + git checkout -b newtag && + echo "Using $datestamp" > one && + git add one && + git commit -m "Branch" && + setdate_and_increment && + git tag -m "Tagging at $datestamp" master && + git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +heads/master +master +EOF + +test_expect_success 'Check ambiguous head and tag refs (loose)' ' + git config --bool core.warnambiguousrefs false && + git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +heads/ambiguous +ambiguous +EOF + +test_expect_success 'Check ambiguous head and tag refs II (loose)' ' + git checkout master && + git tag ambiguous testtag^0 && + git branch ambiguous testtag^0 && + git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual && + test_cmp expected actual +' + +test_expect_success 'an unusual tag with an incomplete line' ' + + git tag -m "bogo" bogo && + bogo=$(git cat-file tag bogo) && + bogo=$(printf "%s" "$bogo" | git mktag) && + git tag -f bogo "$bogo" && + git for-each-ref --format "%(body)" refs/tags/bogo + +' + +test_done diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 344033249c..65a35d94a0 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -1,90 +1,123 @@ #!/bin/sh -test_description='git-mv in subdirs' +test_description='git mv in subdirs' . ./test-lib.sh test_expect_success \ 'prepare reference tree' \ 'mkdir path0 path1 && - cp ../../COPYING path0/COPYING && - git-add path0/COPYING && - git-commit -m add -a' + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && + git add path0/COPYING && + git commit -m add -a' test_expect_success \ 'moving the file out of subdirectory' \ - 'cd path0 && git-mv COPYING ../path1/COPYING' + 'cd path0 && git mv COPYING ../path1/COPYING' # in path0 currently test_expect_success \ 'commiting the change' \ - 'cd .. && git-commit -m move-out -a' + 'cd .. && git commit -m move-out -a' test_expect_success \ 'checking the commit' \ - 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path0/COPYING.+path1/COPYING"' + 'git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path0/COPYING..*path1/COPYING"' test_expect_success \ 'moving the file back into subdirectory' \ - 'cd path0 && git-mv ../path1/COPYING COPYING' + 'cd path0 && git mv ../path1/COPYING COPYING' # in path0 currently test_expect_success \ 'commiting the change' \ - 'cd .. && git-commit -m move-in -a' + 'cd .. && git commit -m move-in -a' test_expect_success \ 'checking the commit' \ - 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path1/COPYING.+path0/COPYING"' + 'git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path1/COPYING..*path0/COPYING"' + +test_expect_success \ + 'checking -k on non-existing file' \ + 'git mv -k idontexist path0' + +test_expect_success \ + 'checking -k on untracked file' \ + 'touch untracked1 && + git mv -k untracked1 path0 && + test -f untracked1 && + test ! -f path0/untracked1' + +test_expect_success \ + 'checking -k on multiple untracked files' \ + 'touch untracked2 && + git mv -k untracked1 untracked2 path0 && + test -f untracked1 && + test -f untracked2 && + test ! -f path0/untracked1 && + test ! -f path0/untracked2' + +test_expect_success \ + 'checking -f on untracked file with existing target' \ + 'touch path0/untracked1 && + git mv -f untracked1 path0 + test ! -f .git/index.lock && + test -f untracked1 && + test -f path0/untracked1' + +# clean up the mess in case bad things happen +rm -f idontexist untracked1 untracked2 \ + path0/idontexist path0/untracked1 path0/untracked2 \ + .git/index.lock test_expect_success \ 'adding another file' \ - 'cp ../../README path0/README && - git-add path0/README && - git-commit -m add2 -a' + 'cp "$TEST_DIRECTORY"/../README path0/README && + git add path0/README && + git commit -m add2 -a' test_expect_success \ 'moving whole subdirectory' \ - 'git-mv path0 path2' + 'git mv path0 path2' test_expect_success \ 'commiting the change' \ - 'git-commit -m dir-move -a' + 'git commit -m dir-move -a' test_expect_success \ 'checking the commit' \ - 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path0/COPYING.+path2/COPYING" && - git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path0/README.+path2/README"' + 'git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path0/COPYING..*path2/COPYING" && + git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path0/README..*path2/README"' test_expect_success \ 'succeed when source is a prefix of destination' \ - 'git-mv path2/COPYING path2/COPYING-renamed' + 'git mv path2/COPYING path2/COPYING-renamed' test_expect_success \ 'moving whole subdirectory into subdirectory' \ - 'git-mv path2 path1' + 'git mv path2 path1' test_expect_success \ 'commiting the change' \ - 'git-commit -m dir-move -a' + 'git commit -m dir-move -a' test_expect_success \ 'checking the commit' \ - 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path2/COPYING.+path1/path2/COPYING" && - git-diff-tree -r -M --name-status HEAD^ HEAD | \ - grep -E "^R100.+path2/README.+path1/path2/README"' + 'git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path2/COPYING..*path1/path2/COPYING" && + git diff-tree -r -M --name-status HEAD^ HEAD | \ + grep "^R100..*path2/README..*path1/path2/README"' -test_expect_failure \ +test_expect_success \ 'do not move directory over existing directory' \ - 'mkdir path0 && mkdir path0/path2 && git-mv path2 path0' + 'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0' test_expect_success \ 'move into "."' \ - 'git-mv path1/path2/ .' + 'git mv path1/path2/ .' test_expect_success "Michael Cassar's test case" ' rm -fr .git papers partA && @@ -118,4 +151,108 @@ test_expect_success "Sergey Vlasov's test case" ' git mv ab a ' +test_expect_success 'absolute pathname' '( + + rm -fr mine && + mkdir mine && + cd mine && + test_create_repo one && + cd one && + mkdir sub && + >sub/file && + git add sub/file && + + git mv sub "$(pwd)/in" && + ! test -d sub && + test -d in && + git ls-files --error-unmatch in/file + + +)' + +test_expect_success 'absolute pathname outside should fail' '( + + rm -fr mine && + mkdir mine && + cd mine && + out=$(pwd) && + test_create_repo one && + cd one && + mkdir sub && + >sub/file && + git add sub/file && + + test_must_fail git mv sub "$out/out" && + test -d sub && + ! test -d ../in && + git ls-files --error-unmatch sub/file + +)' + +test_expect_success 'git mv to move multiple sources into a directory' ' + rm -fr .git && git init && + mkdir dir other && + >dir/a.txt && + >dir/b.txt && + git add dir/?.txt && + git mv dir/a.txt dir/b.txt other && + git ls-files >actual && + { echo other/a.txt; echo other/b.txt; } >expect && + test_cmp expect actual +' + +test_expect_success 'git mv should not change sha1 of moved cache entry' ' + + rm -fr .git && + git init && + echo 1 >dirty && + git add dirty && + entry="$(git ls-files --stage dirty | cut -f 1)" + git mv dirty dirty2 && + [ "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" ] && + echo 2 >dirty2 && + git mv dirty2 dirty && + [ "$entry" = "$(git ls-files --stage dirty | cut -f 1)" ] + +' + +rm -f dirty dirty2 + +test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' ' + + rm -fr .git && + git init && + echo 1 >moved && + ln -s moved symlink && + git add moved symlink && + test_must_fail git mv moved symlink && + git mv -f moved symlink && + ! test -e moved && + test -f symlink && + test "$(cat symlink)" = 1 && + git update-index --refresh && + git diff-files --quiet + +' + +rm -f moved symlink + +test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' ' + + rm -fr .git && + git init && + echo 1 >moved && + ln -s moved symlink && + git add moved symlink && + test_must_fail git mv symlink moved && + git mv -f symlink moved && + ! test -e symlink && + test -h moved && + git update-index --refresh && + git diff-files --quiet + +' + +rm -f moved symlink + test_done diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh deleted file mode 100755 index 6bfb899ed1..0000000000 --- a/t/t7002-grep.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006 Junio C Hamano -# - -test_description='git grep various. -' - -. ./test-lib.sh - -test_expect_success setup ' - { - echo foo mmap bar - echo foo_mmap bar - echo foo_mmap bar mmap - echo foo mmap bar_mmap - echo foo_mmap bar mmap baz - } >file && - echo x x xx x >x && - echo y yy >y && - echo zzz > z && - mkdir t && - echo test >t/t && - git add file x y z t/t && - git commit -m initial -' - -for H in HEAD '' -do - case "$H" in - HEAD) HC='HEAD:' L='HEAD' ;; - '') HC= L='in working tree' ;; - esac - - test_expect_success "grep -w $L" ' - { - echo ${HC}file:1:foo mmap bar - echo ${HC}file:3:foo_mmap bar mmap - echo ${HC}file:4:foo mmap bar_mmap - echo ${HC}file:5:foo_mmap bar mmap baz - } >expected && - git grep -n -w -e mmap $H >actual && - diff expected actual - ' - - test_expect_success "grep -w $L (x)" ' - { - echo ${HC}x:1:x x xx x - } >expected && - git grep -n -w -e "x xx* x" $H >actual && - diff expected actual - ' - - test_expect_success "grep -w $L (y-1)" ' - { - echo ${HC}y:1:y yy - } >expected && - git grep -n -w -e "^y" $H >actual && - diff expected actual - ' - - test_expect_success "grep -w $L (y-2)" ' - : >expected && - if git grep -n -w -e "^y y" $H >actual - then - echo should not have matched - cat actual - false - else - diff expected actual - fi - ' - - test_expect_success "grep -w $L (z)" ' - : >expected && - if git grep -n -w -e "^z" $H >actual - then - echo should not have matched - cat actual - false - else - diff 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_expect_success "grep $L (t-2)" ' - echo "${HC}t:1:test" >expected && - ( - cd t && - git grep -n -e test $H - ) >actual && - diff expected actual - ' - - test_expect_success "grep $L (t-3)" ' - echo "${HC}t/t:1:test" >expected && - ( - cd t && - git grep --full-name -n -e test $H - ) >actual && - diff expected actual - ' - -done - -test_done diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh new file mode 100755 index 0000000000..2c55801ee8 --- /dev/null +++ b/t/t7003-filter-branch.sh @@ -0,0 +1,349 @@ +#!/bin/sh + +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 +' + +H=$(git rev-parse H) + +test_expect_success 'rewrite identically' ' + git filter-branch branch +' +test_expect_success 'result is really identical' ' + test $H = $(git rev-parse HEAD) +' + +test_expect_success 'rewrite bare repository identically' ' + (git config core.bare true && cd .git && + git filter-branch branch > filter-output 2>&1 && + ! fgrep fatal filter-output) +' +git config core.bare false +test_expect_success 'result is really identical' ' + test $H = $(git rev-parse HEAD) +' + +TRASHDIR=$(pwd) +test_expect_success 'correct GIT_DIR while using -d' ' + mkdir drepo && + ( cd drepo && + git init && + test_commit drepo && + git filter-branch -d "$TRASHDIR/dfoo" \ + --index-filter "cp \"$TRASHDIR\"/dfoo/backup-refs \"$TRASHDIR\"" \ + ) && + grep drepo "$TRASHDIR/backup-refs" +' + +test_expect_success 'Fail if commit filter fails' ' + test_must_fail git filter-branch -f --commit-filter "exit 1" HEAD +' + +test_expect_success 'rewrite, renaming a specific file' ' + git filter-branch -f --tree-filter "mv d doh || :" HEAD +' + +test_expect_success 'test that the file was renamed' ' + test d = "$(git show HEAD:doh --)" && + ! test -f d && + test -f doh && + test d = "$(cat doh)" +' + +test_expect_success 'rewrite, renaming a specific directory' ' + git filter-branch -f --tree-filter "mv dir diroh || :" HEAD +' + +test_expect_success 'test that the directory was renamed' ' + test dir/d = "$(git show HEAD:diroh/d --)" && + ! test -d dir && + test -d diroh && + ! test -d diroh/dir && + test -f diroh/d && + test dir/d = "$(cat diroh/d)" +' + +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 +' + +test_expect_success 'common ancestor is still common (unchanged)' ' + test "$(git merge-base modD D)" = "$(git rev-parse B)" +' + +test_expect_success 'filter subdirectory only' ' + mkdir subdir && + touch subdir/new && + git add subdir/new && + test_tick && + git commit -m "subdir" && + echo H > a && + test_tick && + git commit -m "not subdir" a && + echo A > subdir/new && + test_tick && + git commit -m "again subdir" subdir/new && + git rm a && + test_tick && + git commit -m "again not subdir" && + git branch sub && + git branch sub-earlier HEAD~2 && + git filter-branch -f --subdirectory-filter subdir \ + refs/heads/sub refs/heads/sub-earlier +' + +test_expect_success 'subdirectory filter result looks okay' ' + test 2 = $(git rev-list sub | wc -l) && + git show sub:new && + test_must_fail git show sub:subdir && + git show sub-earlier:new && + test_must_fail git show sub-earlier:subdir +' + +test_expect_success 'more setup' ' + git checkout master && + mkdir subdir && + echo A > subdir/new && + git add subdir/new && + test_tick && + git commit -m "subdir on master" subdir/new && + git rm a && + test_tick && + git commit -m "again subdir on master" && + git merge branch +' + +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- -&newsubdir/-\" | + GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \ + git update-index --index-info && + mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved && + git diff --exit-code HEAD directorymoved:newsubdir +' + +test_expect_success 'stops when msg filter fails' ' + old=$(git rev-parse HEAD) && + test_must_fail git filter-branch -f --msg-filter false HEAD && + test $old = $(git rev-parse HEAD) && + rm -rf .git-rewrite +' + +test_expect_success 'author information is preserved' ' + : > i && + git add i && + test_tick && + GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips && + git branch preserved-author && + git filter-branch -f --msg-filter "cat; \ + test \$GIT_COMMIT != $(git rev-parse master) || \ + echo Hallo" \ + preserved-author && + test 1 = $(git rev-list --author="B V Uips" preserved-author | wc -l) +' + +test_expect_success "remove a certain author's commits" ' + echo i > i && + test_tick && + git commit -m i i && + git branch removed-author && + git filter-branch -f --commit-filter "\ + if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\ + then\ + skip_commit \"\$@\"; + else\ + git commit-tree \"\$@\";\ + fi" removed-author && + cnt1=$(git rev-list master | wc -l) && + cnt2=$(git rev-list removed-author | wc -l) && + test $cnt1 -eq $(($cnt2 + 1)) && + test 0 = $(git rev-list --author="B V Uips" removed-author | wc -l) +' + +test_expect_success 'barf on invalid name' ' + test_must_fail git filter-branch -f master xy-problem && + test_must_fail git filter-branch -f HEAD^ +' + +test_expect_success '"map" works in commit filter' ' + git filter-branch -f --commit-filter "\ + parent=\$(git rev-parse \$GIT_COMMIT^) && + mapped=\$(map \$parent) && + actual=\$(echo \"\$@\" | sed \"s/^.*-p //\") && + test \$mapped = \$actual && + git commit-tree \"\$@\";" master~2..master && + git rev-parse --verify master +' + +test_expect_success 'Name needing quotes' ' + + git checkout -b rerere A && + mkdir foo && + name="れれれ" && + >foo/$name && + git add foo && + git commit -m "Adding a file" && + git filter-branch --tree-filter "rm -fr foo" && + test_must_fail git ls-files --error-unmatch "foo/$name" && + test $(git rev-parse --verify rerere) != $(git rev-parse --verify A) + +' + +test_expect_success 'Subdirectory filter with disappearing trees' ' + git reset --hard && + git checkout master && + + mkdir foo && + touch foo/bar && + git add foo && + test_tick && + git commit -m "Adding foo" && + + git rm -r foo && + test_tick && + git commit -m "Removing foo" && + + mkdir foo && + touch foo/bar && + git add foo && + test_tick && + git commit -m "Re-adding foo" && + + git filter-branch -f --subdirectory-filter foo && + test $(git rev-list master | wc -l) = 3 +' + +test_expect_success 'Tag name filtering retains tag message' ' + git tag -m atag T && + git cat-file tag T > expect && + git filter-branch -f --tag-name-filter cat && + git cat-file tag T > actual && + test_cmp expect actual +' + +faux_gpg_tag='object XXXXXX +type commit +tag S +tagger T A Gger <tagger@example.com> 1206026339 -0500 + +This is a faux gpg signed tag. +-----BEGIN PGP SIGNATURE----- +Version: FauxGPG v0.0.0 (FAUX/Linux) + +gdsfoewhxu/6l06f1kxyxhKdZkrcbaiOMtkJUA9ITAc1mlamh0ooasxkH1XwMbYQ +acmwXaWET20H0GeAGP+7vow= +=agpO +-----END PGP SIGNATURE----- +' +test_expect_success 'Tag name filtering strips gpg signature' ' + sha1=$(git rev-parse HEAD) && + sha1t=$(echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | git mktag) && + git update-ref "refs/tags/S" "$sha1t" && + echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect && + git filter-branch -f --tag-name-filter cat && + git cat-file tag S > actual && + test_cmp expect actual +' + +test_expect_success 'Tag name filtering allows slashes in tag names' ' + git tag -m tag-with-slash X/1 && + git cat-file tag X/1 | sed -e s,X/1,X/2, > expect && + git filter-branch -f --tag-name-filter "echo X/2" && + git cat-file tag X/2 > actual && + test_cmp expect actual +' + +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 && + git rev-list HEAD > actual && + test_cmp expect actual +' + +test_expect_success '--remap-to-ancestor with filename filters' ' + git checkout master && + git reset --hard A && + test_commit add-foo foo 1 && + git branch moved-foo && + test_commit add-bar bar a && + git branch invariant && + orig_invariant=$(git rev-parse invariant) && + git branch moved-bar && + test_commit change-foo foo 2 && + git filter-branch -f --remap-to-ancestor \ + moved-foo moved-bar A..master \ + -- -- foo && + test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) && + test $(git rev-parse moved-foo) = $(git rev-parse master^) && + test $orig_invariant = $(git rev-parse invariant) +' + +test_expect_success 'setup submodule' ' + rm -fr ?* .git && + git init && + test_commit file && + mkdir submod && + submodurl="$PWD/submod" && + ( cd submod && + git init && + test_commit file-in-submod ) && + git submodule add "$submodurl" && + git commit -m "added submodule" && + test_commit add-file && + ( cd submod && test_commit add-in-submodule ) && + git add submod && + git commit -m "changed submodule" && + git branch original HEAD +' + +orig_head=`git show-ref --hash --head HEAD` + +test_expect_success 'rewrite submodule with another content' ' + git filter-branch --tree-filter "test -d submod && { + rm -rf submod && + git rm -rf --quiet submod && + mkdir submod && + : > submod/file + } || :" HEAD && + test $orig_head != `git show-ref --hash --head HEAD` +' + +test_expect_success 'replace submodule revision' ' + git reset --hard original && + git filter-branch -f --tree-filter \ + "if git ls-files --error-unmatch -- submod > /dev/null 2>&1 + then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod + fi" HEAD && + test $orig_head != `git show-ref --hash --head HEAD` +' + +test_done diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh new file mode 100755 index 0000000000..ac943f5eee --- /dev/null +++ b/t/t7004-tag.sh @@ -0,0 +1,1219 @@ +#!/bin/sh +# +# Copyright (c) 2007 Carlos Rica +# + +test_description='git tag + +Tests for operations with tags.' + +. ./test-lib.sh + +# creating and listing lightweight tags: + +tag_exists () { + git show-ref --quiet --verify refs/tags/"$1" +} + +# todo: git tag -l now returns always zero, when fixed, change this test +test_expect_success 'listing all tags in an empty tree should succeed' ' + git tag -l && + git tag +' + +test_expect_success 'listing all tags in an empty tree should output nothing' ' + test `git tag -l | wc -l` -eq 0 && + test `git tag | wc -l` -eq 0 +' + +test_expect_success 'looking for a tag in an empty tree should fail' \ + '! (tag_exists mytag)' + +test_expect_success 'creating a tag in an empty tree should fail' ' + test_must_fail git tag mynotag && + ! tag_exists mynotag +' + +test_expect_success 'creating a tag for HEAD in an empty tree should fail' ' + test_must_fail git tag mytaghead HEAD && + ! tag_exists mytaghead +' + +test_expect_success 'creating a tag for an unknown revision should fail' ' + test_must_fail git tag mytagnorev aaaaaaaaaaa && + ! tag_exists mytagnorev +' + +# commit used in the tests, test_tick is also called here to freeze the date: +test_expect_success 'creating a tag using default HEAD should succeed' ' + test_tick && + echo foo >foo && + git add foo && + git commit -m Foo && + git tag mytag +' + +test_expect_success 'listing all tags if one exists should succeed' ' + git tag -l && + git tag +' + +test_expect_success 'listing all tags if one exists should output that tag' ' + test `git tag -l` = mytag && + test `git tag` = mytag +' + +# pattern matching: + +test_expect_success 'listing a tag using a matching pattern should succeed' \ + 'git tag -l mytag' + +test_expect_success \ + 'listing a tag using a matching pattern should output that tag' \ + 'test `git tag -l mytag` = mytag' + +# todo: git tag -l now returns always zero, when fixed, change this test +test_expect_success \ + 'listing tags using a non-matching pattern should suceed' \ + 'git tag -l xxx' + +test_expect_success \ + 'listing tags using a non-matching pattern should output nothing' \ + 'test `git tag -l xxx | wc -l` -eq 0' + +# special cases for creating tags: + +test_expect_success \ + 'trying to create a tag with the name of one existing should fail' \ + 'test_must_fail git tag mytag' + +test_expect_success \ + 'trying to create a tag with a non-valid name should fail' ' + test `git tag -l | wc -l` -eq 1 && + test_must_fail git tag "" && + test_must_fail git tag .othertag && + test_must_fail git tag "other tag" && + test_must_fail git tag "othertag^" && + test_must_fail git tag "other~tag" && + test `git tag -l | wc -l` -eq 1 +' + +test_expect_success 'creating a tag using HEAD directly should succeed' ' + git tag myhead HEAD && + tag_exists myhead +' + +# deleting tags: + +test_expect_success 'trying to delete an unknown tag should fail' ' + ! tag_exists unknown-tag && + test_must_fail git tag -d unknown-tag +' + +cat >expect <<EOF +myhead +mytag +EOF +test_expect_success \ + 'trying to delete tags without params should succeed and do nothing' ' + git tag -l > actual && test_cmp expect actual && + git tag -d && + git tag -l > actual && test_cmp expect actual +' + +test_expect_success \ + 'deleting two existing tags in one command should succeed' ' + tag_exists mytag && + tag_exists myhead && + git tag -d mytag myhead && + ! tag_exists mytag && + ! tag_exists myhead +' + +test_expect_success \ + 'creating a tag with the name of another deleted one should succeed' ' + ! tag_exists mytag && + git tag mytag && + tag_exists mytag +' + +test_expect_success \ + 'trying to delete two tags, existing and not, should fail in the 2nd' ' + tag_exists mytag && + ! tag_exists myhead && + test_must_fail git tag -d mytag anothertag && + ! tag_exists mytag && + ! tag_exists myhead +' + +test_expect_success 'trying to delete an already deleted tag should fail' \ + 'test_must_fail git tag -d mytag' + +# listing various tags with pattern matching: + +cat >expect <<EOF +a1 +aa1 +cba +t210 +t211 +v0.2.1 +v1.0 +v1.0.1 +v1.1.3 +EOF +test_expect_success 'listing all tags should print them ordered' ' + git tag v1.0.1 && + git tag t211 && + git tag aa1 && + git tag v0.2.1 && + git tag v1.1.3 && + git tag cba && + git tag a1 && + git tag v1.0 && + git tag t210 && + git tag -l > actual && + test_cmp expect actual && + git tag > actual && + test_cmp expect actual +' + +cat >expect <<EOF +a1 +aa1 +cba +EOF +test_expect_success \ + 'listing tags with substring as pattern must print those matching' ' + rm *a* && + git tag -l "*a*" > current && + test_cmp expect current +' + +cat >expect <<EOF +v0.2.1 +v1.0.1 +EOF +test_expect_success \ + 'listing tags with a suffix as pattern must print those matching' ' + git tag -l "*.1" > actual && + test_cmp expect actual +' + +cat >expect <<EOF +t210 +t211 +EOF +test_expect_success \ + 'listing tags with a prefix as pattern must print those matching' ' + git tag -l "t21*" > actual && + test_cmp expect actual +' + +cat >expect <<EOF +a1 +EOF +test_expect_success \ + 'listing tags using a name as pattern must print that one matching' ' + git tag -l a1 > actual && + test_cmp expect actual +' + +cat >expect <<EOF +v1.0 +EOF +test_expect_success \ + 'listing tags using a name as pattern must print that one matching' ' + git tag -l v1.0 > actual && + test_cmp expect actual +' + +cat >expect <<EOF +v1.0.1 +v1.1.3 +EOF +test_expect_success \ + 'listing tags with ? in the pattern should print those matching' ' + git tag -l "v1.?.?" > actual && + test_cmp expect actual +' + +>expect +test_expect_success \ + 'listing tags using v.* should print nothing because none have v.' ' + git tag -l "v.*" > actual && + test_cmp expect actual +' + +cat >expect <<EOF +v0.2.1 +v1.0 +v1.0.1 +v1.1.3 +EOF +test_expect_success \ + 'listing tags using v* should print only those having v' ' + git tag -l "v*" > actual && + test_cmp expect actual +' + +# creating and verifying lightweight tags: + +test_expect_success \ + 'a non-annotated tag created without parameters should point to HEAD' ' + git tag non-annotated-tag && + test $(git cat-file -t non-annotated-tag) = commit && + test $(git rev-parse non-annotated-tag) = $(git rev-parse HEAD) +' + +test_expect_success 'trying to verify an unknown tag should fail' \ + 'test_must_fail git tag -v unknown-tag' + +test_expect_success \ + 'trying to verify a non-annotated and non-signed tag should fail' \ + 'test_must_fail git tag -v non-annotated-tag' + +test_expect_success \ + 'trying to verify many non-annotated or unknown tags, should fail' \ + 'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2' + +# creating annotated tags: + +get_tag_msg () { + git cat-file tag "$1" | sed -e "/BEGIN PGP/q" +} + +# run test_tick before committing always gives the time in that timezone +get_tag_header () { +cat <<EOF +object $2 +type $3 +tag $1 +tagger C O Mitter <committer@example.com> $4 -0700 + +EOF +} + +commit=$(git rev-parse HEAD) +time=$test_tick + +get_tag_header annotated-tag $commit commit $time >expect +echo "A message" >>expect +test_expect_success \ + 'creating an annotated tag with -m message should succeed' ' + git tag -m "A message" annotated-tag && + get_tag_msg annotated-tag >actual && + test_cmp expect actual +' + +cat >msgfile <<EOF +Another message +in a file. +EOF +get_tag_header file-annotated-tag $commit commit $time >expect +cat msgfile >>expect +test_expect_success \ + 'creating an annotated tag with -F messagefile should succeed' ' + git tag -F msgfile file-annotated-tag && + get_tag_msg file-annotated-tag >actual && + test_cmp expect actual +' + +cat >inputmsg <<EOF +A message from the +standard input +EOF +get_tag_header stdin-annotated-tag $commit commit $time >expect +cat inputmsg >>expect +test_expect_success 'creating an annotated tag with -F - should succeed' ' + git tag -F - stdin-annotated-tag <inputmsg && + get_tag_msg stdin-annotated-tag >actual && + test_cmp expect actual +' + +test_expect_success \ + 'trying to create a tag with a non-existing -F file should fail' ' + ! test -f nonexistingfile && + ! tag_exists notag && + test_must_fail git tag -F nonexistingfile notag && + ! tag_exists notag +' + +test_expect_success \ + 'trying to create tags giving both -m or -F options should fail' ' + echo "message file 1" >msgfile1 && + echo "message file 2" >msgfile2 && + ! tag_exists msgtag && + test_must_fail git tag -m "message 1" -F msgfile1 msgtag && + ! tag_exists msgtag && + test_must_fail git tag -F msgfile1 -m "message 1" msgtag && + ! tag_exists msgtag && + test_must_fail git tag -m "message 1" -F msgfile1 \ + -m "message 2" msgtag && + ! tag_exists msgtag +' + +# blank and empty messages: + +get_tag_header empty-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with an empty -m message should succeed' ' + git tag -m "" empty-annotated-tag && + get_tag_msg empty-annotated-tag >actual && + test_cmp expect actual +' + +>emptyfile +get_tag_header emptyfile-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with an empty -F messagefile should succeed' ' + git tag -F emptyfile emptyfile-annotated-tag && + get_tag_msg emptyfile-annotated-tag >actual && + test_cmp expect actual +' + +printf '\n\n \n\t\nLeading blank lines\n' >blanksfile +printf '\n\t \t \nRepeated blank lines\n' >>blanksfile +printf '\n\n\nTrailing spaces \t \n' >>blanksfile +printf '\nTrailing blank lines\n\n\t \n\n' >>blanksfile +get_tag_header blanks-annotated-tag $commit commit $time >expect +cat >>expect <<EOF +Leading blank lines + +Repeated blank lines + +Trailing spaces + +Trailing blank lines +EOF +test_expect_success \ + 'extra blanks in the message for an annotated tag should be removed' ' + git tag -F blanksfile blanks-annotated-tag && + get_tag_msg blanks-annotated-tag >actual && + test_cmp expect actual +' + +get_tag_header blank-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with blank -m message with spaces should succeed' ' + git tag -m " " blank-annotated-tag && + get_tag_msg blank-annotated-tag >actual && + test_cmp expect actual +' + +echo ' ' >blankfile +echo '' >>blankfile +echo ' ' >>blankfile +get_tag_header blankfile-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with blank -F messagefile with spaces should succeed' ' + git tag -F blankfile blankfile-annotated-tag && + get_tag_msg blankfile-annotated-tag >actual && + test_cmp expect actual +' + +printf ' ' >blanknonlfile +get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with -F file of spaces and no newline should succeed' ' + git tag -F blanknonlfile blanknonlfile-annotated-tag && + get_tag_msg blanknonlfile-annotated-tag >actual && + test_cmp expect actual +' + +# messages with commented lines: + +cat >commentsfile <<EOF +# A comment + +############ +The message. +############ +One line. + + +# commented lines +# commented lines + +Another line. +# comments + +Last line. +EOF +get_tag_header comments-annotated-tag $commit commit $time >expect +cat >>expect <<EOF +The message. +One line. + +Another line. + +Last line. +EOF +test_expect_success \ + 'creating a tag using a -F messagefile with #comments should succeed' ' + git tag -F commentsfile comments-annotated-tag && + get_tag_msg comments-annotated-tag >actual && + test_cmp expect actual +' + +get_tag_header comment-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with a #comment in the -m message should succeed' ' + git tag -m "#comment" comment-annotated-tag && + get_tag_msg comment-annotated-tag >actual && + test_cmp expect actual +' + +echo '#comment' >commentfile +echo '' >>commentfile +echo '####' >>commentfile +get_tag_header commentfile-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with #comments in the -F messagefile should succeed' ' + git tag -F commentfile commentfile-annotated-tag && + get_tag_msg commentfile-annotated-tag >actual && + test_cmp expect actual +' + +printf '#comment' >commentnonlfile +get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect +test_expect_success \ + 'creating a tag with a file of #comment and no newline should succeed' ' + git tag -F commentnonlfile commentnonlfile-annotated-tag && + get_tag_msg commentnonlfile-annotated-tag >actual && + test_cmp expect actual +' + +# listing messages for annotated non-signed tags: + +test_expect_success \ + 'listing the one-line message of a non-signed tag should succeed' ' + git tag -m "A msg" tag-one-line && + + echo "tag-one-line" >expect && + git tag -l | grep "^tag-one-line" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^tag-one-line" >actual && + test_cmp expect actual && + git tag -n0 -l tag-one-line >actual && + test_cmp expect actual && + + echo "tag-one-line A msg" >expect && + git tag -n1 -l | grep "^tag-one-line" >actual && + test_cmp expect actual && + git tag -n -l | grep "^tag-one-line" >actual && + test_cmp expect actual && + git tag -n1 -l tag-one-line >actual && + test_cmp expect actual && + git tag -n2 -l tag-one-line >actual && + test_cmp expect actual && + git tag -n999 -l tag-one-line >actual && + test_cmp expect actual +' + +test_expect_success \ + 'listing the zero-lines message of a non-signed tag should succeed' ' + git tag -m "" tag-zero-lines && + + echo "tag-zero-lines" >expect && + git tag -l | grep "^tag-zero-lines" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^tag-zero-lines" >actual && + test_cmp expect actual && + git tag -n0 -l tag-zero-lines >actual && + test_cmp expect actual && + + echo "tag-zero-lines " >expect && + git tag -n1 -l | grep "^tag-zero-lines" >actual && + test_cmp expect actual && + git tag -n -l | grep "^tag-zero-lines" >actual && + test_cmp expect actual && + git tag -n1 -l tag-zero-lines >actual && + test_cmp expect actual && + git tag -n2 -l tag-zero-lines >actual && + test_cmp expect actual && + git tag -n999 -l tag-zero-lines >actual && + test_cmp expect actual +' + +echo 'tag line one' >annotagmsg +echo 'tag line two' >>annotagmsg +echo 'tag line three' >>annotagmsg +test_expect_success \ + 'listing many message lines of a non-signed tag should succeed' ' + git tag -F annotagmsg tag-lines && + + echo "tag-lines" >expect && + git tag -l | grep "^tag-lines" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^tag-lines" >actual && + test_cmp expect actual && + git tag -n0 -l tag-lines >actual && + test_cmp expect actual && + + echo "tag-lines tag line one" >expect && + git tag -n1 -l | grep "^tag-lines" >actual && + test_cmp expect actual && + git tag -n -l | grep "^tag-lines" >actual && + test_cmp expect actual && + git tag -n1 -l tag-lines >actual && + test_cmp expect actual && + + echo " tag line two" >>expect && + git tag -n2 -l | grep "^ *tag.line" >actual && + test_cmp expect actual && + git tag -n2 -l tag-lines >actual && + test_cmp expect actual && + + echo " tag line three" >>expect && + git tag -n3 -l | grep "^ *tag.line" >actual && + test_cmp expect actual && + git tag -n3 -l tag-lines >actual && + test_cmp expect actual && + git tag -n4 -l | grep "^ *tag.line" >actual && + test_cmp expect actual && + git tag -n4 -l tag-lines >actual && + test_cmp expect actual && + git tag -n99 -l | grep "^ *tag.line" >actual && + test_cmp expect actual && + git tag -n99 -l tag-lines >actual && + test_cmp expect actual +' + +# subsequent tests require gpg; check if it is available +gpg --version >/dev/null 2>/dev/null +if [ $? -eq 127 ]; then + say "# gpg not found - skipping tag signing and verification tests" +else + # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 + # the gpg version 1.0.6 didn't parse trust packets correctly, so for + # that version, creation of signed tags using the generated key fails. + case "$(gpg --version)" in + 'gpg (GnuPG) 1.0.6'*) + say "Skipping signed tag tests, because a bug in 1.0.6 version" + ;; + *) + test_set_prereq GPG + ;; + esac +fi + +# trying to verify annotated non-signed tags: + +test_expect_success GPG \ + 'trying to verify an annotated non-signed tag should fail' ' + tag_exists annotated-tag && + test_must_fail git tag -v annotated-tag +' + +test_expect_success GPG \ + 'trying to verify a file-annotated non-signed tag should fail' ' + tag_exists file-annotated-tag && + test_must_fail git tag -v file-annotated-tag +' + +test_expect_success GPG \ + 'trying to verify two annotated non-signed tags should fail' ' + tag_exists annotated-tag file-annotated-tag && + test_must_fail git tag -v annotated-tag file-annotated-tag +' + +# creating and verifying signed tags: + +# key generation info: gpg --homedir t/t7004 --gen-key +# Type DSA and Elgamal, size 2048 bits, no expiration date. +# Name and email: C O Mitter <committer@example.com> +# No password given, to enable non-interactive operation. + +cp -R "$TEST_DIRECTORY"/t7004 ./gpghome +chmod 0700 gpghome +GNUPGHOME="$(pwd)/gpghome" +export GNUPGHOME + +get_tag_header signed-tag $commit commit $time >expect +echo 'A signed tag message' >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG 'creating a signed tag with -m message should succeed' ' + git tag -s -m "A signed tag message" signed-tag && + get_tag_msg signed-tag >actual && + test_cmp expect actual +' + +get_tag_header u-signed-tag $commit commit $time >expect +echo 'Another message' >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG 'sign with a given key id' ' + + git tag -u committer@example.com -m "Another message" u-signed-tag && + get_tag_msg u-signed-tag >actual && + test_cmp expect actual + +' + +test_expect_success GPG 'sign with an unknown id (1)' ' + + test_must_fail git tag -u author@example.com \ + -m "Another message" o-signed-tag + +' + +test_expect_success GPG 'sign with an unknown id (2)' ' + + test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag + +' + +cat >fakeeditor <<'EOF' +#!/bin/sh +test -n "$1" && exec >"$1" +echo A signed tag message +echo from a fake editor. +EOF +chmod +x fakeeditor + +get_tag_header implied-sign $commit commit $time >expect +./fakeeditor >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG '-u implies signed tag' ' + GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign && + get_tag_msg implied-sign >actual && + test_cmp expect actual +' + +cat >sigmsgfile <<EOF +Another signed tag +message in a file. +EOF +get_tag_header file-signed-tag $commit commit $time >expect +cat sigmsgfile >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with -F messagefile should succeed' ' + git tag -s -F sigmsgfile file-signed-tag && + get_tag_msg file-signed-tag >actual && + test_cmp expect actual +' + +cat >siginputmsg <<EOF +A signed tag message from +the standard input +EOF +get_tag_header stdin-signed-tag $commit commit $time >expect +cat siginputmsg >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG 'creating a signed tag with -F - should succeed' ' + git tag -s -F - stdin-signed-tag <siginputmsg && + get_tag_msg stdin-signed-tag >actual && + test_cmp expect actual +' + +get_tag_header implied-annotate $commit commit $time >expect +./fakeeditor >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG '-s implies annotated tag' ' + GIT_EDITOR=./fakeeditor git tag -s implied-annotate && + get_tag_msg implied-annotate >actual && + test_cmp expect actual +' + +test_expect_success GPG \ + 'trying to create a signed tag with non-existing -F file should fail' ' + ! test -f nonexistingfile && + ! tag_exists nosigtag && + test_must_fail git tag -s -F nonexistingfile nosigtag && + ! tag_exists nosigtag +' + +test_expect_success GPG 'verifying a signed tag should succeed' \ + 'git tag -v signed-tag' + +test_expect_success GPG 'verifying two signed tags in one command should succeed' \ + 'git tag -v signed-tag file-signed-tag' + +test_expect_success GPG \ + 'verifying many signed and non-signed tags should fail' ' + test_must_fail git tag -v signed-tag annotated-tag && + test_must_fail git tag -v file-annotated-tag file-signed-tag && + test_must_fail git tag -v annotated-tag \ + file-signed-tag file-annotated-tag && + test_must_fail git tag -v signed-tag annotated-tag file-signed-tag +' + +test_expect_success GPG 'verifying a forged tag should fail' ' + forged=$(git cat-file tag signed-tag | + sed -e "s/signed-tag/forged-tag/" | + git mktag) && + git tag forged-tag $forged && + test_must_fail git tag -v forged-tag +' + +# blank and empty messages for signed tags: + +get_tag_header empty-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with an empty -m message should succeed' ' + git tag -s -m "" empty-signed-tag && + get_tag_msg empty-signed-tag >actual && + test_cmp expect actual && + git tag -v empty-signed-tag +' + +>sigemptyfile +get_tag_header emptyfile-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with an empty -F messagefile should succeed' ' + git tag -s -F sigemptyfile emptyfile-signed-tag && + get_tag_msg emptyfile-signed-tag >actual && + test_cmp expect actual && + git tag -v emptyfile-signed-tag +' + +printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile +printf '\n\t \t \nRepeated blank lines\n' >>sigblanksfile +printf '\n\n\nTrailing spaces \t \n' >>sigblanksfile +printf '\nTrailing blank lines\n\n\t \n\n' >>sigblanksfile +get_tag_header blanks-signed-tag $commit commit $time >expect +cat >>expect <<EOF +Leading blank lines + +Repeated blank lines + +Trailing spaces + +Trailing blank lines +EOF +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'extra blanks in the message for a signed tag should be removed' ' + git tag -s -F sigblanksfile blanks-signed-tag && + get_tag_msg blanks-signed-tag >actual && + test_cmp expect actual && + git tag -v blanks-signed-tag +' + +get_tag_header blank-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with a blank -m message should succeed' ' + git tag -s -m " " blank-signed-tag && + get_tag_msg blank-signed-tag >actual && + test_cmp expect actual && + git tag -v blank-signed-tag +' + +echo ' ' >sigblankfile +echo '' >>sigblankfile +echo ' ' >>sigblankfile +get_tag_header blankfile-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with blank -F file with spaces should succeed' ' + git tag -s -F sigblankfile blankfile-signed-tag && + get_tag_msg blankfile-signed-tag >actual && + test_cmp expect actual && + git tag -v blankfile-signed-tag +' + +printf ' ' >sigblanknonlfile +get_tag_header blanknonlfile-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with spaces and no newline should succeed' ' + git tag -s -F sigblanknonlfile blanknonlfile-signed-tag && + get_tag_msg blanknonlfile-signed-tag >actual && + test_cmp expect actual && + git tag -v signed-tag +' + +# messages with commented lines for signed tags: + +cat >sigcommentsfile <<EOF +# A comment + +############ +The message. +############ +One line. + + +# commented lines +# commented lines + +Another line. +# comments + +Last line. +EOF +get_tag_header comments-signed-tag $commit commit $time >expect +cat >>expect <<EOF +The message. +One line. + +Another line. + +Last line. +EOF +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with a -F file with #comments should succeed' ' + git tag -s -F sigcommentsfile comments-signed-tag && + get_tag_msg comments-signed-tag >actual && + test_cmp expect actual && + git tag -v comments-signed-tag +' + +get_tag_header comment-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with #commented -m message should succeed' ' + git tag -s -m "#comment" comment-signed-tag && + get_tag_msg comment-signed-tag >actual && + test_cmp expect actual && + git tag -v comment-signed-tag +' + +echo '#comment' >sigcommentfile +echo '' >>sigcommentfile +echo '####' >>sigcommentfile +get_tag_header commentfile-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with #commented -F messagefile should succeed' ' + git tag -s -F sigcommentfile commentfile-signed-tag && + get_tag_msg commentfile-signed-tag >actual && + test_cmp expect actual && + git tag -v commentfile-signed-tag +' + +printf '#comment' >sigcommentnonlfile +get_tag_header commentnonlfile-signed-tag $commit commit $time >expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag with a #comment and no newline should succeed' ' + git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag && + get_tag_msg commentnonlfile-signed-tag >actual && + test_cmp expect actual && + git tag -v commentnonlfile-signed-tag +' + +# listing messages for signed tags: + +test_expect_success GPG \ + 'listing the one-line message of a signed tag should succeed' ' + git tag -s -m "A message line signed" stag-one-line && + + echo "stag-one-line" >expect && + git tag -l | grep "^stag-one-line" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^stag-one-line" >actual && + test_cmp expect actual && + git tag -n0 -l stag-one-line >actual && + test_cmp expect actual && + + echo "stag-one-line A message line signed" >expect && + git tag -n1 -l | grep "^stag-one-line" >actual && + test_cmp expect actual && + git tag -n -l | grep "^stag-one-line" >actual && + test_cmp expect actual && + git tag -n1 -l stag-one-line >actual && + test_cmp expect actual && + git tag -n2 -l stag-one-line >actual && + test_cmp expect actual && + git tag -n999 -l stag-one-line >actual && + test_cmp expect actual +' + +test_expect_success GPG \ + 'listing the zero-lines message of a signed tag should succeed' ' + git tag -s -m "" stag-zero-lines && + + echo "stag-zero-lines" >expect && + git tag -l | grep "^stag-zero-lines" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^stag-zero-lines" >actual && + test_cmp expect actual && + git tag -n0 -l stag-zero-lines >actual && + test_cmp expect actual && + + echo "stag-zero-lines " >expect && + git tag -n1 -l | grep "^stag-zero-lines" >actual && + test_cmp expect actual && + git tag -n -l | grep "^stag-zero-lines" >actual && + test_cmp expect actual && + git tag -n1 -l stag-zero-lines >actual && + test_cmp expect actual && + git tag -n2 -l stag-zero-lines >actual && + test_cmp expect actual && + git tag -n999 -l stag-zero-lines >actual && + test_cmp expect actual +' + +echo 'stag line one' >sigtagmsg +echo 'stag line two' >>sigtagmsg +echo 'stag line three' >>sigtagmsg +test_expect_success GPG \ + 'listing many message lines of a signed tag should succeed' ' + git tag -s -F sigtagmsg stag-lines && + + echo "stag-lines" >expect && + git tag -l | grep "^stag-lines" >actual && + test_cmp expect actual && + git tag -n0 -l | grep "^stag-lines" >actual && + test_cmp expect actual && + git tag -n0 -l stag-lines >actual && + test_cmp expect actual && + + echo "stag-lines stag line one" >expect && + git tag -n1 -l | grep "^stag-lines" >actual && + test_cmp expect actual && + git tag -n -l | grep "^stag-lines" >actual && + test_cmp expect actual && + git tag -n1 -l stag-lines >actual && + test_cmp expect actual && + + echo " stag line two" >>expect && + git tag -n2 -l | grep "^ *stag.line" >actual && + test_cmp expect actual && + git tag -n2 -l stag-lines >actual && + test_cmp expect actual && + + echo " stag line three" >>expect && + git tag -n3 -l | grep "^ *stag.line" >actual && + test_cmp expect actual && + git tag -n3 -l stag-lines >actual && + test_cmp expect actual && + git tag -n4 -l | grep "^ *stag.line" >actual && + test_cmp expect actual && + git tag -n4 -l stag-lines >actual && + test_cmp expect actual && + git tag -n99 -l | grep "^ *stag.line" >actual && + test_cmp expect actual && + git tag -n99 -l stag-lines >actual && + test_cmp expect actual +' + +# tags pointing to objects different from commits: + +tree=$(git rev-parse HEAD^{tree}) +blob=$(git rev-parse HEAD:foo) +tag=$(git rev-parse signed-tag 2>/dev/null) + +get_tag_header tree-signed-tag $tree tree $time >expect +echo "A message for a tree" >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag pointing to a tree should succeed' ' + git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} && + get_tag_msg tree-signed-tag >actual && + test_cmp expect actual +' + +get_tag_header blob-signed-tag $blob blob $time >expect +echo "A message for a blob" >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag pointing to a blob should succeed' ' + git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo && + get_tag_msg blob-signed-tag >actual && + test_cmp expect actual +' + +get_tag_header tag-signed-tag $tag tag $time >expect +echo "A message for another tag" >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'creating a signed tag pointing to another tag should succeed' ' + git tag -s -m "A message for another tag" tag-signed-tag signed-tag && + get_tag_msg tag-signed-tag >actual && + test_cmp expect actual +' + +# try to sign with bad user.signingkey +git config user.signingkey BobTheMouse +test_expect_success GPG \ + 'git tag -s fails if gpg is misconfigured' \ + 'test_must_fail git tag -s -m tail tag-gpg-failure' +git config --unset user.signingkey + +# try to verify without gpg: + +rm -rf gpghome +test_expect_success GPG \ + 'verify signed tag fails when public key is not present' \ + 'test_must_fail git tag -v signed-tag' + +test_expect_success \ + 'git tag -a fails if tag annotation is empty' ' + ! (GIT_EDITOR=cat git tag -a initial-comment) +' + +test_expect_success \ + 'message in editor has initial comment' ' + GIT_EDITOR=cat git tag -a initial-comment > actual + # check the first line --- should be empty + first=$(sed -e 1q <actual) && + test -z "$first" && + # remove commented lines from the remainder -- should be empty + rest=$(sed -e 1d -e '/^#/d' <actual) && + test -z "$rest" +' + +get_tag_header reuse $commit commit $time >expect +echo "An annotation to be reused" >> expect +test_expect_success \ + 'overwriting an annoted tag should use its previous body' ' + git tag -a -m "An annotation to be reused" reuse && + GIT_EDITOR=true git tag -f -a reuse && + get_tag_msg reuse >actual && + test_cmp expect actual +' + +test_expect_success 'filename for the message is relative to cwd' ' + mkdir subdir && + echo "Tag message in top directory" >msgfile-5 && + echo "Tag message in sub directory" >subdir/msgfile-5 && + ( + cd subdir && + git tag -a -F msgfile-5 tag-from-subdir + ) && + git cat-file tag tag-from-subdir | grep "in sub directory" +' + +test_expect_success 'filename for the message is relative to cwd' ' + echo "Tag message in sub directory" >subdir/msgfile-6 && + ( + cd subdir && + git tag -a -F msgfile-6 tag-from-subdir-2 + ) && + git cat-file tag tag-from-subdir-2 | grep "in sub directory" +' + +# create a few more commits to test --contains + +hash1=$(git rev-parse HEAD) + +test_expect_success 'creating second commit and tag' ' + echo foo-2.0 >foo && + git add foo && + git commit -m second + git tag v2.0 +' + +hash2=$(git rev-parse HEAD) + +test_expect_success 'creating third commit without tag' ' + echo foo-dev >foo && + git add foo && + git commit -m third +' + +hash3=$(git rev-parse HEAD) + +# simple linear checks of --continue + +cat > expected <<EOF +v0.2.1 +v1.0 +v1.0.1 +v1.1.3 +v2.0 +EOF + +test_expect_success 'checking that first commit is in all tags (hash)' " + git tag -l --contains $hash1 v* >actual + test_cmp expected actual +" + +# other ways of specifying the commit +test_expect_success 'checking that first commit is in all tags (tag)' " + git tag -l --contains v1.0 v* >actual + test_cmp expected actual +" + +test_expect_success 'checking that first commit is in all tags (relative)' " + git tag -l --contains HEAD~2 v* >actual + test_cmp expected actual +" + +cat > expected <<EOF +v2.0 +EOF + +test_expect_success 'checking that second commit only has one tag' " + git tag -l --contains $hash2 v* >actual + test_cmp expected actual +" + + +cat > expected <<EOF +EOF + +test_expect_success 'checking that third commit has no tags' " + git tag -l --contains $hash3 v* >actual + test_cmp expected actual +" + +# how about a simple merge? + +test_expect_success 'creating simple branch' ' + git branch stable v2.0 && + git checkout stable && + echo foo-3.0 > foo && + git commit foo -m fourth + git tag v3.0 +' + +hash4=$(git rev-parse HEAD) + +cat > expected <<EOF +v3.0 +EOF + +test_expect_success 'checking that branch head only has one tag' " + git tag -l --contains $hash4 v* >actual + test_cmp expected actual +" + +test_expect_success 'merging original branch into this branch' ' + git merge --strategy=ours master && + git tag v4.0 +' + +cat > expected <<EOF +v4.0 +EOF + +test_expect_success 'checking that original branch head has one tag now' " + git tag -l --contains $hash3 v* >actual + test_cmp expected actual +" + +cat > expected <<EOF +v0.2.1 +v1.0 +v1.0.1 +v1.1.3 +v2.0 +v3.0 +v4.0 +EOF + +test_expect_success 'checking that initial commit is in all tags' " + git tag -l --contains $hash1 v* >actual + test_cmp expected actual +" + +# mixing modes and options: + +test_expect_success 'mixing incompatibles modes and options is forbidden' ' + test_must_fail git tag -a + test_must_fail git tag -l -v + test_must_fail git tag -n 100 + test_must_fail git tag -l -m msg + test_must_fail git tag -l -F some file + test_must_fail git tag -v -s +' + +test_done diff --git a/t/t7004/pubring.gpg b/t/t7004/pubring.gpg Binary files differnew file mode 100644 index 0000000000..83855fa4e1 --- /dev/null +++ b/t/t7004/pubring.gpg diff --git a/t/t7004/random_seed b/t/t7004/random_seed Binary files differnew file mode 100644 index 0000000000..8fed1339ed --- /dev/null +++ b/t/t7004/random_seed diff --git a/t/t7004/secring.gpg b/t/t7004/secring.gpg Binary files differnew file mode 100644 index 0000000000..d831cd9eb3 --- /dev/null +++ b/t/t7004/secring.gpg diff --git a/t/t7004/trustdb.gpg b/t/t7004/trustdb.gpg Binary files differnew file mode 100644 index 0000000000..abace962b8 --- /dev/null +++ b/t/t7004/trustdb.gpg diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh new file mode 100755 index 0000000000..26ddf9d496 --- /dev/null +++ b/t/t7005-editor.sh @@ -0,0 +1,137 @@ +#!/bin/sh + +test_description='GIT_EDITOR, core.editor, and stuff' + +. ./test-lib.sh + +unset EDITOR VISUAL GIT_EDITOR + +test_expect_success 'determine default editor' ' + + vi=$(TERM=vt100 git var GIT_EDITOR) && + test -n "$vi" + +' + +if ! expr "$vi" : '[a-z]*$' >/dev/null +then + vi= +fi + +for i in GIT_EDITOR core_editor EDITOR VISUAL $vi +do + cat >e-$i.sh <<-EOF + #!$SHELL_PATH + echo "Edited by $i" >"\$1" + EOF + chmod +x e-$i.sh +done + +if ! test -z "$vi" +then + mv e-$vi.sh $vi +fi + +test_expect_success setup ' + + msg="Hand-edited" && + test_commit "$msg" && + echo "$msg" >expect && + git show -s --format=%s > actual && + test_cmp actual expect + +' + +TERM=dumb +export TERM +test_expect_success 'dumb should error out when falling back on vi' ' + + if git commit --amend + then + echo "Oops?" + false + else + : happy + fi +' + +test_expect_success 'dumb should prefer EDITOR to VISUAL' ' + + EDITOR=./e-EDITOR.sh && + VISUAL=./e-VISUAL.sh && + export EDITOR VISUAL && + git commit --amend && + test "$(git show -s --format=%s)" = "Edited by EDITOR" + +' + +TERM=vt100 +export TERM +for i in $vi EDITOR VISUAL core_editor GIT_EDITOR +do + echo "Edited by $i" >expect + unset EDITOR VISUAL GIT_EDITOR + git config --unset-all core.editor + case "$i" in + core_editor) + git config core.editor ./e-core_editor.sh + ;; + [A-Z]*) + eval "$i=./e-$i.sh" + export $i + ;; + esac + test_expect_success "Using $i" ' + git --exec-path=. commit --amend && + git show -s --pretty=oneline | + sed -e "s/^[0-9a-f]* //" >actual && + test_cmp actual expect + ' +done + +unset EDITOR VISUAL GIT_EDITOR +git config --unset-all core.editor +for i in $vi EDITOR VISUAL core_editor GIT_EDITOR +do + echo "Edited by $i" >expect + case "$i" in + core_editor) + git config core.editor ./e-core_editor.sh + ;; + [A-Z]*) + eval "$i=./e-$i.sh" + export $i + ;; + esac + test_expect_success "Using $i (override)" ' + git --exec-path=. commit --amend && + git show -s --pretty=oneline | + sed -e "s/^[0-9a-f]* //" >actual && + test_cmp actual expect + ' +done + +if ! echo 'echo space > "$1"' > "e space.sh" +then + skip_all="Skipping; FS does not support spaces in filenames" + test_done +fi + +test_expect_success 'editor with a space' ' + + chmod a+x "e space.sh" && + GIT_EDITOR="./e\ space.sh" git commit --amend && + test space = "$(git show -s --pretty=format:%s)" + +' + +unset GIT_EDITOR +test_expect_success 'core.editor with a space' ' + + git config core.editor \"./e\ space.sh\" && + git commit --amend && + test space = "$(git show -s --pretty=format:%s)" + +' + +test_done diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh new file mode 100755 index 0000000000..71d3ceff8f --- /dev/null +++ b/t/t7006-pager.sh @@ -0,0 +1,372 @@ +#!/bin/sh + +test_description='Test automatic use of a pager.' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-pager.sh + +cleanup_fail() { + echo >&2 cleanup failed + (exit 1) +} + +test_expect_success 'set up terminal for tests' ' + rm -f stdout_is_tty || + cleanup_fail && + + if test -t 1 + then + >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 + fi +' + +if test -e stdout_is_tty +then + test_terminal() { "$@"; } + test_set_prereq TTY +elif test -e test_terminal_works +then + test_terminal() { + "$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl "$@" + } + test_set_prereq TTY +else + say "# no usable terminal, so skipping some tests" +fi + +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 +' + +test_expect_success TTY 'some commands use a pager' ' + rm -f paginated.out || + cleanup_fail && + + test_terminal git log && + test -e paginated.out +' + +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 +' + +test_expect_success 'no pager when stdout is a pipe' ' + rm -f paginated.out || + cleanup_fail && + + git log | cat && + ! test -e paginated.out +' + +test_expect_success 'no pager when stdout is a regular file' ' + rm -f paginated.out || + cleanup_fail && + + git log >file && + ! test -e 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 +' + +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 +' + +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 +' + +# 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 +} + +test_expect_success 'tests can detect color' ' + 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 +' + +test_expect_success 'no color when stdout is a regular file' ' + rm -f colorless.log && + git config color.ui auto || + cleanup_fail && + + git log >colorless.log && + ! colorful colorless.log +' + +test_expect_success TTY 'color when writing to a pager' ' + rm -f paginated.out && + git config color.ui auto || + cleanup_fail && + + ( + TERM=vt100 && + export TERM && + test_terminal git log + ) && + colorful paginated.out +' + +test_expect_success 'color when writing to a file intended for a pager' ' + rm -f colorful.log && + git config color.ui auto || + cleanup_fail && + + ( + TERM=vt100 && + GIT_PAGER_IN_USE=true && + export TERM GIT_PAGER_IN_USE && + git log >colorful.log + ) && + colorful colorful.log +' + +if test_have_prereq SIMPLEPAGER && test_have_prereq TTY +then + test_set_prereq SIMPLEPAGERTTY +fi + +# 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" +} + +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" +' + +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_done diff --git a/t/t7006/test-terminal.perl b/t/t7006/test-terminal.perl new file mode 100755 index 0000000000..73ff809371 --- /dev/null +++ b/t/t7006/test-terminal.perl @@ -0,0 +1,58 @@ +#!/usr/bin/perl +use strict; +use warnings; +use IO::Pty; +use File::Copy; + +# Run @$argv in the background with stdout redirected to $out. +sub start_child { + my ($argv, $out) = @_; + my $pid = fork; + if (not defined $pid) { + die "fork failed: $!" + } elsif ($pid == 0) { + open STDOUT, ">&", $out; + close $out; + exec(@$argv) or die "cannot exec '$argv->[0]': $!" + } + return $pid; +} + +# Wait for $pid to finish. +sub finish_child { + # Simplified from wait_or_whine() in run-command.c. + my ($pid) = @_; + + my $waiting = waitpid($pid, 0); + if ($waiting < 0) { + die "waitpid failed: $!"; + } elsif ($? & 127) { + my $code = $? & 127; + warn "died of signal $code"; + return $code - 128; + } else { + return $? >> 8; + } +} + +sub xsendfile { + my ($out, $in) = @_; + + # Note: the real sendfile() cannot read from a terminal. + + # It is unspecified by POSIX whether reads + # from a disconnected terminal will return + # EIO (as in AIX 4.x, IRIX, and Linux) or + # end-of-file. Either is fine. + copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!"; +} + +if ($#ARGV < 1) { + die "usage: test-terminal program args"; +} +my $master = new IO::Pty; +my $slave = $master->slave; +my $pid = start_child(\@ARGV, $slave); +close $slave; +xsendfile(\*STDOUT, $master); +exit(finish_child($pid)); diff --git a/t/t7007-show.sh b/t/t7007-show.sh new file mode 100755 index 0000000000..cce222f052 --- /dev/null +++ b/t/t7007-show.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='git show' + +. ./test-lib.sh + +test_expect_success setup ' + echo hello world >foo && + H=$(git hash-object -w foo) && + git tag -a foo-tag -m "Tags $H" $H && + HH=$(expr "$H" : "\(..\)") && + H38=$(expr "$H" : "..\(.*\)") && + rm -f .git/objects/$HH/$H38 +' + +test_expect_success 'showing a tag that point at a missing object' ' + test_must_fail git --no-pager show foo-tag +' + +test_done diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh new file mode 100755 index 0000000000..eb8ca88cce --- /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' " + printf 'binary\000file\n' >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_failure '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 'y\000f' >f && + git grep -f f -F a +" + +test_expect_success 'git grep -F y<NUL>x a' " + printf 'y\000x' >f && + test_must_fail git grep -f f -F a +" + +test_expect_success 'git grep -Fi Y<NUL>f a' " + printf 'Y\000f' >f && + git grep -f f -Fi a +" + +test_expect_failure 'git grep -Fi Y<NUL>x a' " + printf 'Y\000x' >f && + test_must_fail git grep -f f -Fi a +" + +test_expect_success 'git grep y<NUL>f a' " + printf 'y\000f' >f && + git grep -f f a +" + +test_expect_failure 'git grep y<NUL>x a' " + printf 'y\000x' >f && + test_must_fail git grep -f f a +" + +test_done diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh new file mode 100755 index 0000000000..0335a9a158 --- /dev/null +++ b/t/t7010-setup.sh @@ -0,0 +1,161 @@ +#!/bin/sh + +test_description='setup taking and sanitizing funny paths' + +. ./test-lib.sh + +test_expect_success setup ' + + mkdir -p a/b/c a/e && + D=$(pwd) && + >a/b/c/d && + >a/e/f + +' + +test_expect_success 'git add (absolute)' ' + + git add "$D/a/b/c/d" && + git ls-files >current && + echo a/b/c/d >expect && + test_cmp expect current + +' + + +test_expect_success 'git add (funny relative)' ' + + rm -f .git/index && + ( + cd a/b && + git add "../e/./f" + ) && + git ls-files >current && + echo a/e/f >expect && + test_cmp expect current + +' + +test_expect_success 'git rm (absolute)' ' + + rm -f .git/index && + git add a && + git rm -f --cached "$D/a/b/c/d" && + git ls-files >current && + echo a/e/f >expect && + test_cmp expect current + +' + +test_expect_success 'git rm (funny relative)' ' + + rm -f .git/index && + git add a && + ( + cd a/b && + git rm -f --cached "../e/./f" + ) && + git ls-files >current && + echo a/b/c/d >expect && + test_cmp expect current + +' + +test_expect_success 'git ls-files (absolute)' ' + + rm -f .git/index && + git add a && + git ls-files "$D/a/e/../b" >current && + echo a/b/c/d >expect && + test_cmp expect current + +' + +test_expect_success 'git ls-files (relative #1)' ' + + rm -f .git/index && + git add a && + ( + cd a/b && + git ls-files "../b/c" + ) >current && + echo c/d >expect && + test_cmp expect current + +' + +test_expect_success 'git ls-files (relative #2)' ' + + rm -f .git/index && + git add a && + ( + cd a/b && + git ls-files --full-name "../e/f" + ) >current && + echo a/e/f >expect && + test_cmp expect current + +' + +test_expect_success 'git ls-files (relative #3)' ' + + rm -f .git/index && + git add a && + ( + cd a/b && + git ls-files "../e/f" + ) >current && + echo ../e/f >expect && + test_cmp expect current + +' + +test_expect_success 'commit using absolute path names' ' + git commit -m "foo" && + echo aa >>a/b/c/d && + git commit -m "aa" "$(pwd)/a/b/c/d" +' + +test_expect_success 'log using absolute path names' ' + echo bb >>a/b/c/d && + git commit -m "bb" "$(pwd)/a/b/c/d" && + + git log a/b/c/d >f1.txt && + git log "$(pwd)/a/b/c/d" >f2.txt && + test_cmp f1.txt f2.txt +' + +test_expect_success 'blame using absolute path names' ' + git blame a/b/c/d >f1.txt && + git blame "$(pwd)/a/b/c/d" >f2.txt && + test_cmp f1.txt f2.txt +' + +test_expect_success 'setup deeper work tree' ' + test_create_repo tester +' + +test_expect_success 'add a directory outside the work tree' '( + cd tester && + d1="$(cd .. ; pwd)" && + test_must_fail git add "$d1" +)' + + +test_expect_success 'add a file outside the work tree, nasty case 1' '( + cd tester && + f="$(pwd)x" && + echo "$f" && + touch "$f" && + test_must_fail git add "$f" +)' + +test_expect_success 'add a file outside the work tree, nasty case 2' '( + cd tester && + f="$(pwd | sed "s/.$//")x" && + echo "$f" && + touch "$f" && + test_must_fail git add "$f" +)' + +test_done diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh new file mode 100755 index 0000000000..bb4066f767 --- /dev/null +++ b/t/t7011-skip-worktree-reading.sh @@ -0,0 +1,163 @@ +#!/bin/sh +# +# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy +# + +test_description='skip-worktree bit test' + +. ./test-lib.sh + +cat >expect.full <<EOF +H 1 +H 2 +H init.t +H sub/1 +H sub/2 +EOF + +cat >expect.skip <<EOF +S 1 +H 2 +H init.t +S sub/1 +H sub/2 +EOF + +NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +ZERO_SHA0=0000000000000000000000000000000000000000 +setup_absent() { + test -f 1 && rm 1 + git update-index --remove 1 && + git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --skip-worktree 1 +} + +test_absent() { + echo "100644 $NULL_SHA1 0 1" > expected && + git ls-files --stage 1 > result && + test_cmp expected result && + test ! -f 1 +} + +setup_dirty() { + git update-index --force-remove 1 && + echo dirty > 1 && + git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --skip-worktree 1 +} + +test_dirty() { + echo "100644 $NULL_SHA1 0 1" > expected && + git ls-files --stage 1 > result && + test_cmp expected result && + echo dirty > expected + test_cmp expected 1 +} + +test_expect_success 'setup' ' + test_commit init && + mkdir sub && + touch ./1 ./2 sub/1 sub/2 && + git add 1 2 sub/1 sub/2 && + git update-index --skip-worktree 1 sub/1 && + git ls-files -t > result && + test_cmp expect.skip result +' + +test_expect_success 'update-index' ' + setup_absent && + git update-index 1 && + test_absent +' + +test_expect_success 'update-index' ' + setup_dirty && + git update-index 1 && + test_dirty +' + +test_expect_success 'update-index --remove' ' + setup_absent && + git update-index --remove 1 && + test -z "$(git ls-files 1)" && + test ! -f 1 +' + +test_expect_success 'update-index --remove' ' + setup_dirty && + git update-index --remove 1 && + test -z "$(git ls-files 1)" && + echo dirty > expected && + test_cmp expected 1 +' + +test_expect_success 'ls-files --delete' ' + setup_absent && + test -z "$(git ls-files -d)" +' + +test_expect_success 'ls-files --delete' ' + setup_dirty && + test -z "$(git ls-files -d)" +' + +test_expect_success 'ls-files --modified' ' + setup_absent && + test -z "$(git ls-files -m)" +' + +test_expect_success 'ls-files --modified' ' + setup_dirty && + test -z "$(git ls-files -m)" +' + +test_expect_success 'grep with skip-worktree file' ' + git update-index --no-skip-worktree 1 && + echo test > 1 && + git update-index 1 && + git update-index --skip-worktree 1 && + rm 1 && + test "$(git grep --no-ext-grep test)" = "1:test" +' + +echo ":000000 100644 $ZERO_SHA0 $NULL_SHA1 A 1" > expected +test_expect_success 'diff-index does not examine skip-worktree absent entries' ' + setup_absent && + git diff-index HEAD -- 1 > result && + test_cmp expected result +' + +test_expect_success 'diff-index does not examine skip-worktree dirty entries' ' + setup_dirty && + git diff-index HEAD -- 1 > result && + test_cmp expected result +' + +test_expect_success 'diff-files does not examine skip-worktree absent entries' ' + setup_absent && + test -z "$(git diff-files -- one)" +' + +test_expect_success 'diff-files does not examine skip-worktree dirty entries' ' + setup_dirty && + test -z "$(git diff-files -- one)" +' + +test_expect_success 'git-rm succeeds on skip-worktree absent entries' ' + setup_absent && + git rm 1 +' + +test_expect_success 'commit on skip-worktree absent entries' ' + git reset && + setup_absent && + test_must_fail git commit -m null 1 +' + +test_expect_success 'commit on skip-worktree dirty entries' ' + git reset && + setup_dirty && + test_must_fail git commit -m null 1 +' + +test_done diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh new file mode 100755 index 0000000000..582d0b54f1 --- /dev/null +++ b/t/t7012-skip-worktree-writing.sh @@ -0,0 +1,146 @@ +#!/bin/sh +# +# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy +# + +test_description='test worktree writing operations when skip-worktree is used' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit init && + echo modified >> init.t && + touch added && + git add init.t added && + git commit -m "modified and added" && + git tag top +' + +test_expect_success 'read-tree updates worktree, absent case' ' + git checkout -f top && + git update-index --skip-worktree init.t && + rm init.t && + git read-tree -m -u HEAD^ && + echo init > expected && + test_cmp expected init.t +' + +test_expect_success 'read-tree updates worktree, dirty case' ' + git checkout -f top && + git update-index --skip-worktree init.t && + echo dirty >> init.t && + test_must_fail git read-tree -m -u HEAD^ && + grep -q dirty init.t && + test "$(git ls-files -t init.t)" = "S init.t" && + git update-index --no-skip-worktree init.t +' + +test_expect_success 'read-tree removes worktree, absent case' ' + git checkout -f top && + git update-index --skip-worktree added && + rm added && + git read-tree -m -u HEAD^ && + test ! -f added +' + +test_expect_success 'read-tree removes worktree, dirty case' ' + git checkout -f top && + git update-index --skip-worktree added && + echo dirty >> added && + test_must_fail git read-tree -m -u HEAD^ && + grep -q dirty added && + test "$(git ls-files -t added)" = "S added" && + git update-index --no-skip-worktree added +' + +NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +ZERO_SHA0=0000000000000000000000000000000000000000 +setup_absent() { + test -f 1 && rm 1 + git update-index --remove 1 && + git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --skip-worktree 1 +} + +test_absent() { + echo "100644 $NULL_SHA1 0 1" > expected && + git ls-files --stage 1 > result && + test_cmp expected result && + test ! -f 1 +} + +setup_dirty() { + git update-index --force-remove 1 && + echo dirty > 1 && + git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --skip-worktree 1 +} + +test_dirty() { + echo "100644 $NULL_SHA1 0 1" > expected && + git ls-files --stage 1 > result && + test_cmp expected result && + echo dirty > expected + test_cmp expected 1 +} + +cat >expected <<EOF +S 1 +H 2 +H init.t +S sub/1 +H sub/2 +EOF + +test_expect_success 'index setup' ' + git checkout -f init && + mkdir sub && + touch ./1 ./2 sub/1 sub/2 && + git add 1 2 sub/1 sub/2 && + git update-index --skip-worktree 1 sub/1 && + git ls-files -t > result && + test_cmp expected result +' + +test_expect_success 'git-add ignores worktree content' ' + setup_absent && + git add 1 && + test_absent +' + +test_expect_success 'git-add ignores worktree content' ' + setup_dirty && + git add 1 && + test_dirty +' + +test_expect_success 'git-rm fails if worktree is dirty' ' + setup_dirty && + test_must_fail git rm 1 && + test_dirty +' + +cat >expected <<EOF +Would remove expected +Would remove result +EOF +test_expect_success 'git-clean, absent case' ' + setup_absent && + git clean -n > result && + test_cmp expected result +' + +test_expect_success 'git-clean, dirty case' ' + setup_dirty && + git clean -n > result && + test_cmp expected result +' + +#TODO test_expect_failure 'git-apply adds file' false +#TODO test_expect_failure 'git-apply updates file' false +#TODO test_expect_failure 'git-apply removes file' false +#TODO test_expect_failure 'git-mv to skip-worktree' false +#TODO test_expect_failure 'git-mv from skip-worktree' false +#TODO test_expect_failure 'git-checkout' false + +test_done diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh new file mode 100755 index 0000000000..fcac472598 --- /dev/null +++ b/t/t7060-wtstatus.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +test_description='basic work tree status reporting' + +. ./test-lib.sh + +test_expect_success setup ' + test_commit A && + test_commit B oneside added && + git checkout A^0 && + test_commit C oneside created +' + +test_expect_success 'A/A conflict' ' + git checkout B^0 && + test_must_fail git merge C +' + +test_expect_success 'Report path with conflict' ' + git diff --cached --name-status >actual && + echo "U oneside" >expect && + test_cmp expect actual +' + +test_expect_success 'Report new path with conflict' ' + git diff --cached --name-status HEAD^ >actual && + echo "U oneside" >expect && + test_cmp expect actual +' + +cat >expect <<EOF +# On branch side +# Unmerged paths: +# (use "git add/rm <file>..." as appropriate to mark resolution) +# +# deleted by us: foo +# +no changes added to commit (use "git add" and/or "git commit -a") +EOF + +test_expect_success 'M/D conflict does not segfault' ' + mkdir mdconflict && + ( + cd mdconflict && + git init && + test_commit initial foo "" && + test_commit modify foo foo && + git checkout -b side HEAD^ && + git rm foo && + git commit -m delete && + test_must_fail git merge master && + test_must_fail git commit --dry-run >../actual && + test_cmp ../expect ../actual && + git status >../actual && + test_cmp ../expect ../actual + ) +' + +test_done diff --git a/t/t7101-reset.sh b/t/t7101-reset.sh index a9191407f2..96e163f084 100755 --- a/t/t7101-reset.sh +++ b/t/t7101-reset.sh @@ -3,61 +3,61 @@ # Copyright (c) 2006 Shawn Pearce # -test_description='git-reset should cull empty subdirs' +test_description='git reset should cull empty subdirs' . ./test-lib.sh test_expect_success \ 'creating initial files' \ 'mkdir path0 && - cp ../../COPYING path0/COPYING && - git-add path0/COPYING && - git-commit -m add -a' + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && + git add path0/COPYING && + git commit -m add -a' test_expect_success \ 'creating second files' \ 'mkdir path1 && mkdir path1/path2 && - cp ../../COPYING path1/path2/COPYING && - cp ../../COPYING path1/COPYING && - cp ../../COPYING COPYING && - cp ../../COPYING path0/COPYING-TOO && - git-add path1/path2/COPYING && - git-add path1/COPYING && - git-add COPYING && - git-add path0/COPYING-TOO && - git-commit -m change -a' + cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING && + cp "$TEST_DIRECTORY"/../COPYING path1/COPYING && + cp "$TEST_DIRECTORY"/../COPYING COPYING && + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO && + git add path1/path2/COPYING && + git add path1/COPYING && + git add COPYING && + git add path0/COPYING-TOO && + git commit -m change -a' test_expect_success \ 'resetting tree HEAD^' \ - 'git-reset --hard HEAD^' + 'git reset --hard HEAD^' test_expect_success \ 'checking initial files exist after rewind' \ 'test -d path0 && test -f path0/COPYING' -test_expect_failure \ +test_expect_success \ 'checking lack of path1/path2/COPYING' \ - 'test -f path1/path2/COPYING' + '! test -f path1/path2/COPYING' -test_expect_failure \ +test_expect_success \ 'checking lack of path1/COPYING' \ - 'test -f path1/COPYING' + '! test -f path1/COPYING' -test_expect_failure \ +test_expect_success \ 'checking lack of COPYING' \ - 'test -f COPYING' + '! test -f COPYING' -test_expect_failure \ +test_expect_success \ 'checking checking lack of path1/COPYING-TOO' \ - 'test -f path0/COPYING-TOO' + '! test -f path0/COPYING-TOO' -test_expect_failure \ +test_expect_success \ 'checking lack of path1/path2' \ - 'test -d path1/path2' + '! test -d path1/path2' -test_expect_failure \ +test_expect_success \ 'checking lack of path1' \ - 'test -d path1' + '! test -d path1' test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh new file mode 100755 index 0000000000..b8cf2603a1 --- /dev/null +++ b/t/t7102-reset.sh @@ -0,0 +1,479 @@ +#!/bin/sh +# +# Copyright (c) 2007 Carlos Rica +# + +test_description='git reset + +Documented tests for git reset' + +. ./test-lib.sh + +test_expect_success 'creating initial files and commits' ' + test_tick && + echo "1st file" >first && + git add first && + git commit -m "create 1st file" && + + echo "2nd file" >second && + git add second && + git commit -m "create 2nd file" && + + echo "2nd line 1st file" >>first && + git commit -a -m "modify 1st file" && + + git rm first && + git mv second secondfile && + git commit -a -m "remove 1st and rename 2nd" && + + echo "1st line 2nd file" >secondfile && + echo "2nd line 2nd file" >>secondfile && + git commit -a -m "modify 2nd file" +' +# git log --pretty=oneline # to see those SHA1 involved + +check_changes () { + test "$(git rev-parse HEAD)" = "$1" && + git diff | test_cmp .diff_expect - && + git diff --cached | test_cmp .cached_expect - && + for FILE in * + do + echo $FILE':' + cat $FILE || return + done | test_cmp .cat_expect - +} + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF + +test_expect_success 'giving a non existing revision should fail' ' + test_must_fail git reset aaaaaa && + test_must_fail git reset --mixed aaaaaa && + test_must_fail git reset --soft aaaaaa && + test_must_fail git reset --hard aaaaaa && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +test_expect_success 'reset --soft with unmerged index should fail' ' + touch .git/MERGE_HEAD && + echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" | + git update-index --index-info && + test_must_fail git reset --soft HEAD && + rm .git/MERGE_HEAD && + git rm --cached -- un +' + +test_expect_success \ + 'giving paths with options different than --mixed should fail' ' + test_must_fail git reset --soft -- first && + test_must_fail git reset --hard -- first && + test_must_fail git reset --soft HEAD^ -- first && + test_must_fail git reset --hard HEAD^ -- first && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +test_expect_success 'giving unrecognized options should fail' ' + test_must_fail git reset --other && + test_must_fail git reset -o && + test_must_fail git reset --mixed --other && + test_must_fail git reset --mixed -o && + test_must_fail git reset --soft --other && + test_must_fail git reset --soft -o && + test_must_fail git reset --hard --other && + test_must_fail git reset --hard -o && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +test_expect_success \ + 'trying to do reset --soft with pending merge should fail' ' + git branch branch1 && + git branch branch2 && + + git checkout branch1 && + echo "3rd line in branch1" >>secondfile && + git commit -a -m "change in branch1" && + + git checkout branch2 && + echo "3rd line in branch2" >>secondfile && + git commit -a -m "change in branch2" && + + test_must_fail git merge branch1 && + test_must_fail git reset --soft && + + printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile && + git commit -a -m "the change in branch2" && + + git checkout master && + git branch -D branch1 branch2 && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +test_expect_success \ + 'trying to do reset --soft with pending checkout merge should fail' ' + git branch branch3 && + git branch branch4 && + + git checkout branch3 && + echo "3rd line in branch3" >>secondfile && + git commit -a -m "line in branch3" && + + git checkout branch4 && + echo "3rd line in branch4" >>secondfile && + + git checkout -m branch3 && + test_must_fail git reset --soft && + + printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile && + git commit -a -m "the line in branch3" && + + git checkout master && + git branch -D branch3 branch4 && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +test_expect_success \ + 'resetting to HEAD with no changes should succeed and do nothing' ' + git reset --hard && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset --hard HEAD && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset --soft && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset --soft HEAD && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset --mixed && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset --mixed HEAD && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + git reset HEAD && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +>.diff_expect +cat >.cached_expect <<EOF +diff --git a/secondfile b/secondfile +index 1bbba79..44c5b58 100644 +--- a/secondfile ++++ b/secondfile +@@ -1 +1,2 @@ +-2nd file ++1st line 2nd file ++2nd line 2nd file +EOF +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF +test_expect_success '--soft reset only should show changes in diff --cached' ' + git reset --soft HEAD^ && + check_changes d1a4bc3abce4829628ae2dcb0d60ef3d1a78b1c4 && + test "$(git rev-parse ORIG_HEAD)" = \ + 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +3rd line 2nd file +EOF +test_expect_success \ + 'changing files and redo the last commit should succeed' ' + echo "3rd line 2nd file" >>secondfile && + git commit -a -C ORIG_HEAD && + check_changes 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d && + test "$(git rev-parse ORIG_HEAD)" = \ + 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +first: +1st file +2nd line 1st file +second: +2nd file +EOF +test_expect_success \ + '--hard reset should change the files and undo commits permanently' ' + git reset --hard HEAD~2 && + check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e && + test "$(git rev-parse ORIG_HEAD)" = \ + 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d +' + +>.diff_expect +cat >.cached_expect <<EOF +diff --git a/first b/first +deleted file mode 100644 +index 8206c22..0000000 +--- a/first ++++ /dev/null +@@ -1,2 +0,0 @@ +-1st file +-2nd line 1st file +diff --git a/second b/second +deleted file mode 100644 +index 1bbba79..0000000 +--- a/second ++++ /dev/null +@@ -1 +0,0 @@ +-2nd file +diff --git a/secondfile b/secondfile +new file mode 100644 +index 0000000..44c5b58 +--- /dev/null ++++ b/secondfile +@@ -0,0 +1,2 @@ ++1st line 2nd file ++2nd line 2nd file +EOF +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF +test_expect_success \ + 'redoing changes adding them without commit them should succeed' ' + git rm first && + git mv second secondfile && + + echo "1st line 2nd file" >secondfile && + echo "2nd line 2nd file" >>secondfile && + git add secondfile && + check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e +' + +cat >.diff_expect <<EOF +diff --git a/first b/first +deleted file mode 100644 +index 8206c22..0000000 +--- a/first ++++ /dev/null +@@ -1,2 +0,0 @@ +-1st file +-2nd line 1st file +diff --git a/second b/second +deleted file mode 100644 +index 1bbba79..0000000 +--- a/second ++++ /dev/null +@@ -1 +0,0 @@ +-2nd file +EOF +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF +test_expect_success '--mixed reset to HEAD should unadd the files' ' + git reset && + check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e && + test "$(git rev-parse ORIG_HEAD)" = \ + ddaefe00f1da16864591c61fdc7adb5d7cd6b74e +' + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF +test_expect_success 'redoing the last two commits should succeed' ' + git add secondfile && + git reset --hard ddaefe00f1da16864591c61fdc7adb5d7cd6b74e && + + git rm first && + git mv second secondfile && + git commit -a -m "remove 1st and rename 2nd" && + + echo "1st line 2nd file" >secondfile && + echo "2nd line 2nd file" >>secondfile && + git commit -a -m "modify 2nd file" && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +3rd line in branch2 +EOF +test_expect_success '--hard reset to HEAD should clear a failed merge' ' + git branch branch1 && + git branch branch2 && + + git checkout branch1 && + echo "3rd line in branch1" >>secondfile && + git commit -a -m "change in branch1" && + + git checkout branch2 && + echo "3rd line in branch2" >>secondfile && + git commit -a -m "change in branch2" && + + test_must_fail git pull . branch1 && + git reset --hard && + check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb +' + +>.diff_expect +>.cached_expect +cat >.cat_expect <<EOF +secondfile: +1st line 2nd file +2nd line 2nd file +EOF +test_expect_success \ + '--hard reset to ORIG_HEAD should clear a fast-forward merge' ' + git reset --hard HEAD^ && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + + git pull . branch1 && + git reset --hard ORIG_HEAD && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && + + git checkout master && + git branch -D branch1 branch2 && + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc +' + +cat > expect << EOF +diff --git a/file1 b/file1 +index d00491f..7ed6ff8 100644 +--- a/file1 ++++ b/file1 +@@ -1 +1 @@ +-1 ++5 +diff --git a/file2 b/file2 +deleted file mode 100644 +index 0cfbf08..0000000 +--- a/file2 ++++ /dev/null +@@ -1 +0,0 @@ +-2 +EOF +cat > cached_expect << EOF +diff --git a/file4 b/file4 +new file mode 100644 +index 0000000..b8626c4 +--- /dev/null ++++ b/file4 +@@ -0,0 +1 @@ ++4 +EOF +test_expect_success 'test --mixed <paths>' ' + echo 1 > file1 && + echo 2 > file2 && + git add file1 file2 && + test_tick && + git commit -m files && + git rm file2 && + echo 3 > file3 && + echo 4 > file4 && + echo 5 > file1 && + git add file1 file3 file4 && + test_must_fail git reset HEAD -- file1 file2 file3 && + git diff > output && + test_cmp output expect && + git diff --cached > output && + test_cmp output cached_expect +' + +test_expect_success 'test resetting the index at give paths' ' + + mkdir sub && + >sub/file1 && + >sub/file2 && + git update-index --add sub/file1 sub/file2 && + T=$(git write-tree) && + test_must_fail git reset HEAD sub/file2 && + U=$(git write-tree) && + echo "$T" && + echo "$U" && + test_must_fail git diff-index --cached --exit-code "$T" && + test "$T" != "$U" + +' + +test_expect_success 'resetting an unmodified path is a no-op' ' + git reset --hard && + git reset -- file1 && + git diff-files --exit-code && + git diff-index --cached --exit-code HEAD +' + +cat > expect << EOF +Unstaged changes after reset: +M file2 +EOF + +test_expect_success '--mixed refreshes the index' ' + echo 123 >> file2 && + git reset --mixed HEAD > output && + test_cmp expect output +' + +test_expect_success 'disambiguation (1)' ' + + git reset --hard && + >secondfile && + git add secondfile && + test_must_fail git reset secondfile && + test -z "$(git diff --cached --name-only)" && + test -f secondfile && + test ! -s secondfile + +' + +test_expect_success 'disambiguation (2)' ' + + git reset --hard && + >secondfile && + git add secondfile && + rm -f secondfile && + test_must_fail git reset secondfile && + test -n "$(git diff --cached --name-only -- secondfile)" && + test ! -f secondfile + +' + +test_expect_success 'disambiguation (3)' ' + + git reset --hard && + >secondfile && + git add secondfile && + rm -f secondfile && + test_must_fail git reset HEAD secondfile && + test -z "$(git diff --cached --name-only)" && + test ! -f secondfile + +' + +test_expect_success 'disambiguation (4)' ' + + git reset --hard && + >secondfile && + git add secondfile && + rm -f secondfile && + test_must_fail git reset -- secondfile && + test -z "$(git diff --cached --name-only)" && + test ! -f secondfile +' + +test_done diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh new file mode 100755 index 0000000000..1eef93c2b2 --- /dev/null +++ b/t/t7103-reset-bare.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='git reset in a bare repository' +. ./test-lib.sh + +test_expect_success 'setup non-bare' ' + echo one >file && + git add file && + git commit -m one && + echo two >file && + git commit -a -m two +' + +test_expect_success '"hard" reset requires a worktree' ' + (cd .git && + test_must_fail git reset --hard) +' + +test_expect_success '"merge" reset requires a worktree' ' + (cd .git && + test_must_fail git reset --merge) +' + +test_expect_success '"keep" reset requires a worktree' ' + (cd .git && + test_must_fail git reset --keep) +' + +test_expect_success '"mixed" reset is ok' ' + (cd .git && git reset) +' + +test_expect_success '"soft" reset is ok' ' + (cd .git && git reset --soft) +' + +test_expect_success 'hard reset works with GIT_WORK_TREE' ' + mkdir worktree && + GIT_WORK_TREE=$PWD/worktree GIT_DIR=$PWD/.git git reset --hard && + test_cmp file worktree/file +' + +test_expect_success 'setup bare' ' + git clone --bare . bare.git && + cd bare.git +' + +test_expect_success '"hard" reset is not allowed in bare' ' + test_must_fail git reset --hard HEAD^ +' + +test_expect_success '"merge" reset is not allowed in bare' ' + test_must_fail git reset --merge HEAD^ +' + +test_expect_success '"keep" reset is not allowed in bare' ' + test_must_fail git reset --keep HEAD^ +' + +test_expect_success '"mixed" reset is not allowed in bare' ' + test_must_fail git reset --mixed HEAD^ +' + +test_expect_success '"soft" reset is allowed in bare' ' + git reset --soft HEAD^ && + test "`git show --pretty=format:%s | head -n 1`" = "one" +' + +test_done diff --git a/t/t7104-reset.sh b/t/t7104-reset.sh new file mode 100755 index 0000000000..f136ee7bb5 --- /dev/null +++ b/t/t7104-reset.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +test_description='reset --hard unmerged' + +. ./test-lib.sh + +test_expect_success setup ' + + mkdir before later && + >before/1 && + >before/2 && + >hello && + >later/3 && + git add before hello later && + git commit -m world && + + H=$(git rev-parse :hello) && + git rm --cached hello && + echo "100644 $H 2 hello" | git update-index --index-info && + + rm -f hello && + mkdir -p hello && + >hello/world && + test "$(git ls-files -o)" = hello/world + +' + +test_expect_success 'reset --hard should restore unmerged ones' ' + + git reset --hard && + git ls-files --error-unmatch before/1 before/2 hello later/3 && + test -f hello + +' + +test_expect_success 'reset --hard did not corrupt index nor cached-tree' ' + + T=$(git write-tree) && + rm -f .git/index && + git add before hello later && + U=$(git write-tree) && + test "$T" = "$U" + +' + +test_done diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh new file mode 100755 index 0000000000..c1f4fc3c65 --- /dev/null +++ b/t/t7105-reset-patch.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='git reset --patch' +. ./lib-patch-mode.sh + +test_expect_success 'setup' ' + mkdir dir && + echo parent > dir/foo && + echo dummy > bar && + git add dir && + git commit -m initial && + test_tick && + test_commit second dir/foo head && + set_and_save_state bar bar_work bar_index && + save_head +' + +# note: bar sorts before foo, so the first 'n' is always to skip 'bar' + +test_expect_success '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' ' + (echo n; echo y) | git reset -p && + verify_state dir/foo work head && + verify_saved_state bar +' + +test_expect_success 'git reset -p HEAD^' ' + (echo n; echo y) | git reset -p HEAD^ && + verify_state dir/foo work parent && + verify_saved_state bar +' + +# The idea in the rest is that bar sorts first, so we always say 'y' +# first and if the path limiter fails it'll apply to bar instead of +# 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' ' + 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)' ' + 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' ' + (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' ' + verify_saved_head +' + + +test_done diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh new file mode 100755 index 0000000000..70cdd8e618 --- /dev/null +++ b/t/t7110-reset-merge.sh @@ -0,0 +1,295 @@ +#!/bin/sh +# +# Copyright (c) 2009 Christian Couder +# + +test_description='Tests for "git reset" with "--merge" and "--keep" options' + +. ./test-lib.sh + +test_expect_success setup ' + for i in 1 2 3; do echo line $i; done >file1 && + cat file1 >file2 && + git add file1 file2 && + test_tick && + git commit -m "Initial commit" && + git tag initial && + echo line 4 >>file1 && + cat file1 >file2 && + test_tick && + git commit -m "add line 4 to file1" file1 && + git tag second +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: C C C D --merge D D D +# file2: C D D D --merge C D D +test_expect_success 'reset --merge is ok with changes in file it does not touch' ' + git reset --merge HEAD^ && + ! grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" +' + +test_expect_success 'reset --merge is ok when switching back' ' + git reset --merge second && + grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: C C C D --keep D D D +# file2: C D D D --keep C D D +test_expect_success 'reset --keep is ok with changes in file it does not touch' ' + git reset --hard second && + cat file1 >file2 && + git reset --keep HEAD^ && + ! grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" +' + +test_expect_success 'reset --keep is ok when switching back' ' + git reset --keep second && + grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: B B C D --merge D D D +# file2: C D D D --merge C D D +test_expect_success 'reset --merge discards changes added to index (1)' ' + git reset --hard second && + cat file1 >file2 && + echo "line 5" >> file1 && + git add file1 && + git reset --merge HEAD^ && + ! grep 4 file1 && + ! grep 5 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" +' + +test_expect_success 'reset --merge is ok again when switching back (1)' ' + git reset --hard initial && + echo "line 5" >> file2 && + git add file2 && + git reset --merge second && + ! grep 4 file2 && + ! grep 5 file1 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: B B C D --keep (disallowed) +test_expect_success 'reset --keep fails with changes in index in files it touches' ' + git reset --hard second && + echo "line 5" >> file1 && + git add file1 && + test_must_fail git reset --keep HEAD^ +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: C C C D --merge D D D +# file2: C C D D --merge D D D +test_expect_success 'reset --merge discards changes added to index (2)' ' + git reset --hard second && + echo "line 4" >> file2 && + git add file2 && + git reset --merge HEAD^ && + ! grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff)" && + test -z "$(git diff --cached)" +' + +test_expect_success 'reset --merge is ok again when switching back (2)' ' + git reset --hard initial && + git reset --merge second && + ! grep 4 file2 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: C C C D --keep D D D +# file2: C C D D --keep C D D +test_expect_success 'reset --keep keeps changes it does not touch' ' + git reset --hard second && + echo "line 4" >> file2 && + git add file2 && + git reset --keep HEAD^ && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" +' + +test_expect_success 'reset --keep keeps changes when switching back' ' + git reset --keep second && + grep 4 file2 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: A B B C --merge (disallowed) +test_expect_success 'reset --merge fails with changes in file it touches' ' + git reset --hard second && + echo "line 5" >> file1 && + test_tick && + git commit -m "add line 5" file1 && + sed -e "s/line 1/changed line 1/" <file1 >file3 && + mv file3 file1 && + test_must_fail git reset --merge HEAD^ 2>err.log && + grep file1 err.log | grep "not uptodate" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: A B B C --keep (disallowed) +test_expect_success 'reset --keep fails with changes in file it touches' ' + git reset --hard second && + echo "line 5" >> file1 && + test_tick && + git commit -m "add line 5" file1 && + sed -e "s/line 1/changed line 1/" <file1 >file3 && + mv file3 file1 && + test_must_fail git reset --keep HEAD^ 2>err.log && + grep file1 err.log | grep "not uptodate" +' + +test_expect_success 'setup 3 different branches' ' + git reset --hard second && + git branch branch1 && + git branch branch2 && + git branch branch3 && + git checkout branch1 && + echo "line 5 in branch1" >> file1 && + test_tick && + git commit -a -m "change in branch1" && + git checkout branch2 && + echo "line 5 in branch2" >> file1 && + test_tick && + git commit -a -m "change in branch2" && + git tag third && + git checkout branch3 && + echo a new file >file3 && + rm -f file1 && + git add file3 && + test_tick && + git commit -a -m "change in branch3" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: X U B C --merge C C C +test_expect_success '"reset --merge HEAD^" is ok with pending merge' ' + git checkout third && + test_must_fail git merge branch1 && + git reset --merge HEAD^ && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" && + test -z "$(git diff)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: X U B C --keep (disallowed) +test_expect_success '"reset --keep HEAD^" fails with pending merge' ' + git reset --hard third && + test_must_fail git merge branch1 && + test_must_fail git reset --keep HEAD^ 2>err.log && + grep "middle of a merge" err.log +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: X U B B --merge B B B +test_expect_success '"reset --merge HEAD" is ok with pending merge' ' + git reset --hard third && + test_must_fail git merge branch1 && + git reset --merge HEAD && + test "$(git rev-parse HEAD)" = "$(git rev-parse third)" && + test -z "$(git diff --cached)" && + test -z "$(git diff)" +' + +# The next test will test the following: +# +# working index HEAD target working index HEAD +# ---------------------------------------------------- +# file1: X U B B --keep (disallowed) +test_expect_success '"reset --keep HEAD" fails with pending merge' ' + git reset --hard third && + test_must_fail git merge branch1 && + test_must_fail git reset --keep HEAD 2>err.log && + grep "middle of a merge" err.log +' + +test_expect_success '--merge is ok with added/deleted merge' ' + git reset --hard third && + rm -f file2 && + test_must_fail git merge branch3 && + ! test -f file2 && + test -f file3 && + git diff --exit-code file3 && + git diff --exit-code branch3 file3 && + git reset --merge HEAD && + ! test -f file3 && + ! test -f file2 && + git diff --exit-code --cached +' + +test_expect_success '--keep fails with added/deleted merge' ' + git reset --hard third && + rm -f file2 && + test_must_fail git merge branch3 && + ! test -f file2 && + test -f file3 && + git diff --exit-code file3 && + git diff --exit-code branch3 file3 && + test_must_fail git reset --keep HEAD 2>err.log && + grep "middle of a merge" err.log +' + +test_done diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh new file mode 100755 index 0000000000..ce421ad5ac --- /dev/null +++ b/t/t7111-reset-table.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# +# Copyright (c) 2010 Christian Couder +# + +test_description='Tests to check that "reset" options follow a known table' + +. ./test-lib.sh + + +test_expect_success 'creating initial commits' ' + test_commit E file1 && + test_commit D file1 && + test_commit C file1 +' + +while read W1 I1 H1 T opt W2 I2 H2 +do + test_expect_success "check: $W1 $I1 $H1 $T --$opt $W2 $I2 $H2" ' + git reset --hard C && + if test "$I1" != "$H1" + then + echo "$I1" >file1 && + git add file1 + fi && + if test "$W1" != "$I1" + then + echo "$W1" >file1 + fi && + if test "$W2" != "XXXXX" + then + git reset --$opt $T && + test "$(cat file1)" = "$W2" && + git checkout-index -f -- file1 && + test "$(cat file1)" = "$I2" && + git checkout -f HEAD -- file1 && + test "$(cat file1)" = "$H2" + else + test_must_fail git reset --$opt $T + fi + ' +done <<\EOF +A B C D soft A B D +A B C D mixed A D D +A B C D hard D D D +A B C D merge XXXXX +A B C D keep XXXXX +A B C C soft A B C +A B C C mixed A C C +A B C C hard C C C +A B C C merge XXXXX +A B C C keep A C C +B B C D soft B B D +B B C D mixed B D D +B B C D hard D D D +B B C D merge D D D +B B C D keep XXXXX +B B C C soft B B C +B B C C mixed B C C +B B C C hard C C C +B B C C merge C C C +B B C C keep B C C +B C C D soft B C D +B C C D mixed B D D +B C C D hard D D D +B C C D merge XXXXX +B C C D keep XXXXX +B C C C soft B C C +B C C C mixed B C C +B C C C hard C C C +B C C C merge B C C +B C C C keep B C C +EOF + +test_expect_success 'setting up branches to test with unmerged entries' ' + git reset --hard C && + git branch branch1 && + git branch branch2 && + git checkout branch1 && + test_commit B1 file1 && + git checkout branch2 && + test_commit B file1 +' + +while read W1 I1 H1 T opt W2 I2 H2 +do + test_expect_success "check: $W1 $I1 $H1 $T --$opt $W2 $I2 $H2" ' + git reset --hard B && + test_must_fail git merge branch1 && + cat file1 >X_file1 && + if test "$W2" != "XXXXX" + then + git reset --$opt $T && + if test "$W2" = "X" + then + test_cmp file1 X_file1 + else + test "$(cat file1)" = "$W2" + fi && + git checkout-index -f -- file1 && + test "$(cat file1)" = "$I2" && + git checkout -f HEAD -- file1 && + test "$(cat file1)" = "$H2" + else + test_must_fail git reset --$opt $T + fi + ' +done <<\EOF +X U B C soft XXXXX +X U B C mixed X C C +X U B C hard C C C +X U B C merge C C C +X U B C keep XXXXX +X U B B soft XXXXX +X U B B mixed X B B +X U B B hard B B B +X U B B merge B B B +X U B B keep XXXXX +EOF + +test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 867bbd26cb..1337fa5a22 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -3,10 +3,27 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='git-checkout tests.' +test_description='git checkout tests. + +Creates master, forks renamer and side branches from it. +Test switching across them. + + ! [master] Initial A one, A two + * [renamer] Renamer R one->uno, M two + ! [side] Side M one, D two, A three + ! [simple] Simple D one, M two + ---- + + [simple] Simple D one, M two + + [side] Side M one, D two, A three + * [renamer] Renamer R one->uno, M two + +*++ [master] Initial A one, A two + +' . ./test-lib.sh +test_tick + fill () { for i do @@ -17,9 +34,10 @@ fill () { test_expect_success setup ' + fill x y z > same && fill 1 2 3 4 5 6 7 8 >one && fill a b c d e >two && - git add one two && + git add same one two && git commit -m "Initial A one, A two" && git checkout -b renamer && @@ -36,6 +54,11 @@ test_expect_success setup ' git update-index --add --remove one two three && git commit -m "Side M one, D two, A three" && + git checkout -b simple master && + rm -f one && + fill a c e > two && + git commit -a -m "Simple D one, M two" && + git checkout master ' @@ -61,32 +84,53 @@ test_expect_success "checkout with dirty tree without -m" ' ' +test_expect_success "checkout with unrelated dirty tree without -m" ' + + git checkout -f master && + fill 0 1 2 3 4 5 6 7 8 >same && + cp same kept + git checkout side >messages && + test_cmp same kept + (cat > messages.expect <<EOF +M same +EOF +) && + touch messages.expect && + test_cmp messages.expect messages +' + test_expect_success "checkout -m with dirty tree" ' git checkout -f master && - git clean && + git clean -f && fill 0 1 2 3 4 5 6 7 8 >one && - git checkout -m side && + git checkout -m side > messages && test "$(git symbolic-ref HEAD)" = "refs/heads/side" && + (cat >expect.messages <<EOF +M one +EOF +) && + test_cmp expect.messages messages && + fill "M one" "A three" "D two" >expect.master && git diff --name-status master >current.master && - diff expect.master current.master && + test_cmp expect.master current.master && fill "M one" >expect.side && git diff --name-status side >current.side && - diff expect.side current.side && + test_cmp expect.side current.side && : >expect.index && git diff --cached >current.index && - diff expect.index current.index + test_cmp expect.index current.index ' test_expect_success "checkout -m with dirty tree, renamed" ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && fill 1 2 3 4 5 7 8 >one && if git checkout renamer @@ -99,7 +143,7 @@ test_expect_success "checkout -m with dirty tree, renamed" ' git checkout -m renamer && fill 1 3 4 5 7 8 >expect && - diff expect uno && + test_cmp expect uno && ! test -f one && git diff --cached >current && ! test -s current @@ -108,7 +152,7 @@ test_expect_success "checkout -m with dirty tree, renamed" ' test_expect_success 'checkout -m with merge conflict' ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && fill 1 T 3 4 5 6 S 8 >one && if git checkout renamer @@ -124,9 +168,504 @@ test_expect_success 'checkout -m with merge conflict' ' git diff master:one :3:uno | sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current && fill d2 aT d7 aS >expect && - diff current expect && + test_cmp current expect && git diff --cached two >current && ! test -s current ' +test_expect_success 'format of merge conflict from checkout -m' ' + + git checkout -f master && git clean -f && + + fill b d > two && + git checkout -m simple && + + git ls-files >current && + fill same two two two >expect && + test_cmp current expect && + + cat <<-EOF >expect && + <<<<<<< simple + a + c + e + ======= + b + d + >>>>>>> local + EOF + test_cmp two expect +' + +test_expect_success 'checkout --merge --conflict=diff3 <branch>' ' + + git checkout -f master && git reset --hard && git clean -f && + + fill b d > two && + git checkout --merge --conflict=diff3 simple && + + cat <<-EOF >expect && + <<<<<<< simple + a + c + e + ||||||| master + a + b + c + d + e + ======= + b + d + >>>>>>> local + EOF + test_cmp two expect +' + +test_expect_success 'checkout to detach HEAD (with advice declined)' ' + + git config advice.detachedHead false && + git checkout -f renamer && git clean -f && + git checkout renamer^ 2>messages && + grep "HEAD is now at 7329388" messages && + test 1 -eq $(wc -l <messages) && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD' ' + git config advice.detachedHead true && + git checkout -f renamer && git clean -f && + git checkout renamer^ 2>messages && + grep "HEAD is now at 7329388" messages && + test 1 -lt $(wc -l <messages) && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD with branchname^' ' + + git checkout -f master && git clean -f && + git checkout renamer^ && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD with :/message' ' + + git checkout -f master && git clean -f && + git checkout ":/Initial" && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout to detach HEAD with HEAD^0' ' + + git checkout -f master && git clean -f && + git checkout HEAD^0 && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + if git symbolic-ref HEAD >/dev/null 2>&1 + then + echo "OOPS, HEAD is still symbolic???" + false + else + : happy + fi +' + +test_expect_success 'checkout with ambiguous tag/branch names' ' + + git tag both side && + git branch both master && + git reset --hard && + git checkout master && + + git checkout both && + H=$(git rev-parse --verify HEAD) && + M=$(git show-ref -s --verify refs/heads/master) && + test "z$H" = "z$M" && + name=$(git symbolic-ref HEAD 2>/dev/null) && + test "z$name" = zrefs/heads/both + +' + +test_expect_success 'checkout with ambiguous tag/branch names' ' + + git reset --hard && + git checkout master && + + git tag frotz side && + git branch frotz master && + git reset --hard && + git checkout master && + + git checkout tags/frotz && + H=$(git rev-parse --verify HEAD) && + S=$(git show-ref -s --verify refs/heads/side) && + test "z$H" = "z$S" && + if name=$(git symbolic-ref HEAD 2>/dev/null) + then + echo "Bad -- should have detached" + false + else + : happy + fi + +' + +test_expect_success 'switch branches while in subdirectory' ' + + git reset --hard && + git checkout master && + + mkdir subs && + ( + cd subs && + git checkout side + ) && + ! test -f subs/one && + rm -fr subs + +' + +test_expect_success 'checkout specific path while in subdirectory' ' + + git reset --hard && + git checkout side && + mkdir subs && + >subs/bero && + git add subs/bero && + git commit -m "add subs/bero" && + + git checkout master && + mkdir -p subs && + ( + cd subs && + git checkout side -- bero + ) && + test -f subs/bero + +' + +test_expect_success \ + 'checkout w/--track sets up tracking' ' + git config branch.autosetupmerge false && + git checkout master && + git checkout --track -b track1 && + test "$(git config branch.track1.remote)" && + test "$(git config branch.track1.merge)"' + +test_expect_success \ + 'checkout w/autosetupmerge=always sets up tracking' ' + git config branch.autosetupmerge always && + git checkout master && + git checkout -b track2 && + test "$(git config branch.track2.remote)" && + test "$(git config branch.track2.merge)" + git config branch.autosetupmerge false' + +test_expect_success 'checkout w/--track from non-branch HEAD fails' ' + git checkout master^0 && + test_must_fail git symbolic-ref HEAD && + test_must_fail git checkout --track -b track && + test_must_fail git rev-parse --verify track && + test_must_fail git symbolic-ref HEAD && + test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)" +' + +test_expect_success 'detach a symbolic link HEAD' ' + git checkout master && + git config --bool core.prefersymlinkrefs yes && + git checkout side && + git checkout master && + it=$(git symbolic-ref HEAD) && + test "z$it" = zrefs/heads/master && + here=$(git rev-parse --verify refs/heads/master) && + git checkout side^ && + test "z$(git rev-parse --verify refs/heads/master)" = "z$here" +' + +test_expect_success \ + 'checkout with --track fakes a sensible -b <name>' ' + git update-ref refs/remotes/origin/koala/bear renamer && + git update-ref refs/new/koala/bear renamer && + + git checkout --track origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/new/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" +' + +test_expect_success \ + 'checkout with --track, but without -b, fails with too short tracked name' ' + test_must_fail git checkout --track renamer' + +setup_conflicting_index () { + rm -f .git/index && + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + ( + echo "100644 $A 0 fild" && + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" && + echo "100644 $A 0 filf" + ) | git update-index --index-info +} + +test_expect_success 'checkout an unmerged path should fail' ' + setup_conflicting_index && + echo "none of the above" >sample && + cat sample >fild && + cat sample >file && + cat sample >filf && + test_must_fail git checkout fild file filf && + test_cmp sample fild && + test_cmp sample filf && + test_cmp sample file +' + +test_expect_success 'checkout with an unmerged path can be ignored' ' + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout -f fild file filf && + test_cmp expect fild && + test_cmp expect filf && + test_cmp sample file +' + +test_expect_success 'checkout unmerged stage' ' + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout --ours . && + test_cmp expect fild && + test_cmp expect filf && + test_cmp expect file && + git checkout --theirs file && + test ztheirside = "z$(cat file)" +' + +test_expect_success 'checkout with --merge' ' + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout -m -- fild file filf && + ( + echo "<<<<<<< ours" + echo ourside + echo "=======" + echo theirside + echo ">>>>>>> theirs" + ) >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + +test_expect_success 'checkout with --merge, in diff3 -m style' ' + git config merge.conflictstyle diff3 && + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout -m -- fild file filf && + ( + echo "<<<<<<< ours" + echo ourside + echo "||||||| base" + echo original + echo "=======" + echo theirside + echo ">>>>>>> theirs" + ) >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + +test_expect_success 'checkout --conflict=merge, overriding config' ' + git config merge.conflictstyle diff3 && + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout --conflict=merge -- fild file filf && + ( + echo "<<<<<<< ours" + echo ourside + echo "=======" + echo theirside + echo ">>>>>>> theirs" + ) >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + +test_expect_success 'checkout --conflict=diff3' ' + git config --unset merge.conflictstyle + setup_conflicting_index && + echo "none of the above" >sample && + echo ourside >expect && + cat sample >fild && + cat sample >file && + cat sample >filf && + git checkout --conflict=diff3 -- fild file filf && + ( + echo "<<<<<<< ours" + echo ourside + echo "||||||| base" + echo original + echo "=======" + echo theirside + echo ">>>>>>> theirs" + ) >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + +test_expect_success 'failing checkout -b should not break working tree' ' + git reset --hard master && + git symbolic-ref HEAD refs/heads/master && + test_must_fail git checkout -b renamer side^ && + test $(git symbolic-ref HEAD) = refs/heads/master && + git diff --exit-code && + git diff --cached --exit-code + +' + +test_expect_success 'switch out of non-branch' ' + git reset --hard master && + git checkout master^0 && + echo modified >one && + test_must_fail git checkout renamer 2>error.log && + ! grep "^Previous HEAD" error.log +' + +( + echo "#!$SHELL_PATH" + cat <<\EOF +O=$1 A=$2 B=$3 +cat "$A" >.tmp +exec >"$A" +echo '<<<<<<< filfre-theirs' +cat "$B" +echo '||||||| filfre-common' +cat "$O" +echo '=======' +cat ".tmp" +echo '>>>>>>> filfre-ours' +rm -f .tmp +exit 1 +EOF +) >filfre.sh +chmod +x filfre.sh + +test_expect_success 'custom merge driver with checkout -m' ' + git reset --hard && + + git config merge.filfre.driver "./filfre.sh %O %A %B" && + git config merge.filfre.name "Feel-free merge driver" && + git config merge.filfre.recursive binary && + echo "arm merge=filfre" >.gitattributes && + + git checkout -b left && + echo neutral >arm && + git add arm .gitattributes && + test_tick && + git commit -m neutral && + git branch right && + + echo left >arm && + test_tick && + git commit -a -m left && + git checkout right && + + echo right >arm && + test_tick && + git commit -a -m right && + + test_must_fail git merge left && + ( + for t in filfre-common left right + do + grep $t arm || exit 1 + done + exit 0 + ) && + + mv arm expect && + git checkout -m arm && + test_cmp expect arm +' + test_done diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh new file mode 100755 index 0000000000..7d8ed68bef --- /dev/null +++ b/t/t7300-clean.sh @@ -0,0 +1,441 @@ +#!/bin/sh +# +# Copyright (c) 2007 Michael Spang +# + +test_description='git clean basic tests' + +. ./test-lib.sh + +git config clean.requireForce no + +test_expect_success 'setup' ' + + mkdir -p src && + touch src/part1.c Makefile && + echo build >.gitignore && + echo \*.o >>.gitignore && + git add . && + git commit -m setup && + touch src/part2.c README && + git add . + +' + +test_expect_success 'git clean with skip-worktree .gitignore' ' + git update-index --skip-worktree .gitignore && + rm .gitignore && + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so && + git update-index --no-skip-worktree .gitignore && + git checkout .gitignore +' + +test_expect_success 'git clean' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean src/' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean src/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean src/ src/' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean src/ src/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean with prefix' ' + + mkdir -p build docs src/test && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c && + (cd src/ && git clean) && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f src/test/1.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean with relative prefix' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + would_clean=$( + cd docs && + git clean -n ../src | + sed -n -e "s|^Would remove ||p" + ) && + test "$would_clean" = ../src/part3.c || { + echo "OOps <$would_clean>" + false + } +' + +test_expect_success 'git clean with absolute path' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + would_clean=$( + cd docs && + git clean -n "$(pwd)/../src" | + sed -n -e "s|^Would remove ||p" + ) && + test "$would_clean" = ../src/part3.c || { + echo "OOps <$would_clean>" + false + } +' + +test_expect_success 'git clean with out of work tree relative path' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + ( + cd docs && + test_must_fail git clean -n ../.. + ) +' + +test_expect_success 'git clean with out of work tree absolute path' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + dd=$(cd .. && pwd) && + ( + cd docs && + test_must_fail git clean -n $dd + ) +' + +test_expect_success 'git clean -d with prefix and path' ' + + mkdir -p build docs src/feature && + touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so && + (cd src/ && git clean -d feature/) && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test ! -f src/feature/file.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean symbolic link' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + ln -s docs/manual.txt src/part4.c + git clean && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test ! -f src/part4.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean with wildcard' ' + + touch a.clean b.clean other.c && + git clean "*.clean" && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.clean && + test ! -f b.clean && + test -f other.c + +' + +test_expect_success 'git clean -n' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -n && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean -d' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -d && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test ! -d docs && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean -d src/ examples/' ' + + mkdir -p build docs examples && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c && + git clean -d src/ examples/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test ! -f examples/1.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean -x' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -x && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test ! -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean -d -x' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -d -x && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test ! -d docs && + test ! -f obj.o && + test ! -d build + +' + +test_expect_success 'git clean -X' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -X && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test -f docs/manual.txt && + test ! -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git clean -d -X' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -d -X && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test -f docs/manual.txt && + test ! -f obj.o && + test ! -d build + +' + +test_expect_success 'clean.requireForce defaults to true' ' + + git config --unset clean.requireForce && + test_must_fail git clean + +' + +test_expect_success 'clean.requireForce' ' + + git config clean.requireForce true && + test_must_fail git clean + +' + +test_expect_success 'clean.requireForce and -n' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git clean -n && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'clean.requireForce and -f' ' + + git clean -f && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'core.excludesfile' ' + + echo excludes >excludes && + echo included >included && + git config core.excludesfile excludes && + output=$(git clean -n excludes included 2>&1) && + expr "$output" : ".*included" >/dev/null && + ! expr "$output" : ".*excludes" >/dev/null + +' + +test_expect_success 'removal failure' ' + + mkdir foo && + touch foo/bar && + (exec <foo/bar && + chmod 0 foo && + test_must_fail git clean -f -d) + +' +chmod 755 foo + +test_expect_success 'nested git work tree' ' + rm -fr foo bar && + mkdir foo bar && + ( + cd foo && + git init && + >hello.world + git add . && + git commit -a -m nested + ) && + ( + cd bar && + >goodbye.people + ) && + git clean -f -d && + test -f foo/.git/index && + test -f foo/hello.world && + ! test -d bar +' + +test_expect_success 'force removal of nested git work tree' ' + rm -fr foo bar && + mkdir foo bar && + ( + cd foo && + git init && + >hello.world + git add . && + git commit -a -m nested + ) && + ( + cd bar && + >goodbye.people + ) && + git clean -f -f -d && + ! test -d foo && + ! test -d bar +' + +test_done diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh new file mode 100755 index 0000000000..9bda970584 --- /dev/null +++ b/t/t7400-submodule-basic.sh @@ -0,0 +1,430 @@ +#!/bin/sh +# +# Copyright (c) 2007 Lars Hjemli +# + +test_description='Basic porcelain support for submodules + +This test tries to verify basic sanity of the init, update and status +subcommands of git submodule. +' + +. ./test-lib.sh + +test_expect_success 'setup - initial commit' ' + >t && + git add t && + git commit -m "initial commit" && + 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 + ) +' + +test_expect_success 'setup - commit with gitlink' ' + echo a >a && + echo z >z && + git add a init z && + git commit -m "super commit 1" +' + +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:-..}" && + + ( + 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 + ) && + + 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' ' + 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' ' + 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 >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 && + 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 && + 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 && + + test_must_fail git submodule update && + + test_cmp expect init/a +' + +test_expect_success 'update should work when path is an empty dir' ' + rm -fr init && + rm -f head-sha1 && + echo "$rev1" >expect && + + mkdir init && + git submodule update && + + inspect init && + test_cmp expect head-sha1 +' + +test_expect_success 'status should be "up-to-date" after update' ' + 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=$(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 >list && + grep "^+$rev1" list +' + +test_expect_success 'git diff should report the SHA1 of the new submodule commit' ' + 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 && + inspect init && + + test_cmp expect head-sha1 +' + +test_expect_success 'status should be "up-to-date" after update' ' + git submodule status >list && + grep "^ $rev1" list +' + +test_expect_success 'checkout superproject with subproject already present' ' + git checkout initial && + git checkout master +' + +test_expect_success 'apply submodule diff' ' + >empty && + + git branch second && + ( + cd init && + echo s >s && + git add s && + git commit -m "change subproject" + ) && + git update-index --add init && + git commit -m "change init" && + git format-patch -1 --stdout >P.diff && + git checkout second && + git apply --index P.diff && + + 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 && + 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 && + + git submodule update --init init && + test -d init/.git +' + +test_expect_success 'do not add files from a submodule' ' + + git reset --hard && + test_must_fail git add init/a + +' + +test_expect_success 'gracefully add submodule with a trailing slash' ' + + git reset --hard && + git commit -m "commit subproject" init && + (cd init && + echo b > a) && + git add init/ && + git diff --exit-code --cached init && + commit=$(cd init && + git commit -m update a >/dev/null && + git rev-parse HEAD) && + git add init/ && + test_must_fail git diff --exit-code --cached init && + test $commit = $(git ls-files --stage | + sed -n "s/^160000 \([^ ]*\).*/\1/p") + +' + +test_expect_success 'ls-files gracefully handles trailing slash' ' + + test "init" = "$(git ls-files init/)" + +' + +test_expect_success 'moving to a commit without submodule does not leave empty dir' ' + rm -rf init && + mkdir init && + git reset --hard && + git checkout initial && + test ! -d init && + git checkout second +' + +test_expect_success 'submodule <invalid-path> warns' ' + + git submodule no-such-submodule 2> output.err && + grep "^error: .*no-such-submodule" output.err + +' + +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 .. && + git clone --bare repo/ bare.git && + cd addtest && + git submodule add "$submodurl/repo" && + git config -f .gitmodules submodule.repo.path repo && + git submodule add "$submodurl/bare.git" && + git config -f .gitmodules submodule.bare.path bare +' + +test_done diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh new file mode 100755 index 0000000000..cee319da0a --- /dev/null +++ b/t/t7401-submodule-summary.sh @@ -0,0 +1,237 @@ +#!/bin/sh +# +# Copyright (c) 2008 Ping Yin +# + +test_description='Summary support for submodules + +This test tries to verify the sanity of summary subcommand of git submodule. +' + +. ./test-lib.sh + +add_file () { + sm=$1 + shift + owd=$(pwd) + cd "$sm" + for name; do + echo "$name" > "$name" && + git add "$name" && + test_tick && + git commit -m "Add $name" + done >/dev/null + git rev-parse --verify HEAD | cut -c1-7 + cd "$owd" +} +commit_file () { + test_tick && + git commit "$@" -m "Commit $*" >/dev/null +} + +test_create_repo sm1 && +add_file . foo >/dev/null + +head1=$(add_file sm1 foo1 foo2) + +test_expect_success 'added submodule' " + git add sm1 && + git submodule summary >actual && + diff actual - <<-EOF +* sm1 0000000...$head1 (2): + > Add foo2 + +EOF +" + +commit_file sm1 && +head2=$(add_file sm1 foo3) + +test_expect_success 'modified submodule(forward)' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head1...$head2 (1): + > Add foo3 + +EOF +" + +test_expect_success 'modified submodule(forward), --files' " + git submodule summary --files >actual && + diff actual - <<-EOF +* sm1 $head1...$head2 (1): + > Add foo3 + +EOF +" + +commit_file sm1 && +cd sm1 && +git reset --hard HEAD~2 >/dev/null && +head3=$(git rev-parse --verify HEAD | cut -c1-7) && +cd .. + +test_expect_success 'modified submodule(backward)' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head2...$head3 (2): + < Add foo3 + < Add foo2 + +EOF +" + +head4=$(add_file sm1 foo4 foo5) && +head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD) +test_expect_success 'modified submodule(backward and forward)' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head2...$head4 (4): + > Add foo5 + > Add foo4 + < Add foo3 + < Add foo2 + +EOF +" + +test_expect_success '--summary-limit' " + git submodule summary -n 3 >actual && + diff actual - <<-EOF +* sm1 $head2...$head4 (4): + > Add foo5 + > Add foo4 + < Add foo3 + +EOF +" + +commit_file sm1 && +mv sm1 sm1-bak && +echo sm1 >sm1 && +head5=$(git hash-object sm1 | cut -c1-7) && +git add sm1 && +rm -f sm1 && +mv sm1-bak sm1 + +test_expect_success 'typechanged submodule(submodule->blob), --cached' " + git submodule summary --cached >actual && + diff actual - <<-EOF +* sm1 $head4(submodule)->$head5(blob) (3): + < Add foo5 + +EOF +" + +test_expect_success 'typechanged submodule(submodule->blob), --files' " + git submodule summary --files >actual && + diff actual - <<-EOF +* sm1 $head5(blob)->$head4(submodule) (3): + > Add foo5 + +EOF +" + +rm -rf sm1 && +git checkout-index sm1 +test_expect_success 'typechanged submodule(submodule->blob)' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head4(submodule)->$head5(blob): + +EOF +" + +rm -f sm1 && +test_create_repo sm1 && +head6=$(add_file sm1 foo6 foo7) +test_expect_success 'nonexistent commit' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head4...$head6: + Warn: sm1 doesn't contain commit $head4_full + +EOF +" + +commit_file +test_expect_success 'typechanged submodule(blob->submodule)' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head5(blob)->$head6(submodule) (2): + > Add foo7 + +EOF +" + +commit_file sm1 && +rm -rf sm1 +test_expect_success 'deleted submodule' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head6...0000000: + +EOF +" + +test_create_repo sm2 && +head7=$(add_file sm2 foo8 foo9) && +git add sm2 + +test_expect_success 'multiple submodules' " + git submodule summary >actual && + diff actual - <<-EOF +* sm1 $head6...0000000: + +* sm2 0000000...$head7 (2): + > Add foo9 + +EOF +" + +test_expect_success 'path filter' " + git submodule summary sm2 >actual && + diff actual - <<-EOF +* sm2 0000000...$head7 (2): + > Add foo9 + +EOF +" + +commit_file sm2 +test_expect_success 'given commit' " + git submodule summary HEAD^ >actual && + diff actual - <<-EOF +* sm1 $head6...0000000: + +* sm2 0000000...$head7 (2): + > Add foo9 + +EOF +" + +test_expect_success '--for-status' " + git submodule summary --for-status HEAD^ >actual && + test_cmp actual - <<EOF +# Submodule changes to be committed: +# +# * sm1 $head6...0000000: +# +# * sm2 0000000...$head7 (2): +# > Add foo9 +# +EOF +" + +test_expect_success 'fail when using --files together with --cached' " + test_must_fail git submodule summary --files --cached +" + +test_expect_success 'should not fail in an empty repo' " + git init xyzzy && + cd xyzzy && + git submodule summary >output 2>&1 && + test_cmp output /dev/null +" + +test_done diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh new file mode 100755 index 0000000000..f919c8d34d --- /dev/null +++ b/t/t7402-submodule-rebase.sh @@ -0,0 +1,92 @@ +#!/bin/sh +# +# Copyright (c) 2008 Johannes Schindelin +# + +test_description='Test rebasing and stashing with dirty submodules' + +. ./test-lib.sh + +test_expect_success setup ' + + echo file > file && + git add file && + test_tick && + git commit -m initial && + git clone . submodule && + git add submodule && + test_tick && + git commit -m submodule && + echo second line >> file && + (cd submodule && git pull) && + test_tick && + git commit -m file-and-submodule -a + +' + +test_expect_success 'rebase with a dirty submodule' ' + + (cd submodule && + echo 3rd line >> file && + test_tick && + git commit -m fork -a) && + echo unrelated >> file2 && + git add file2 && + test_tick && + git commit -m unrelated file2 && + echo other line >> file && + test_tick && + git commit -m update file && + CURRENT=$(cd submodule && git rev-parse HEAD) && + EXPECTED=$(git rev-parse HEAD~2:submodule) && + GIT_TRACE=1 git rebase --onto HEAD~2 HEAD^ && + STORED=$(git rev-parse HEAD:submodule) && + test $EXPECTED = $STORED && + test $CURRENT = $(cd submodule && git rev-parse HEAD) + +' + +cat > fake-editor.sh << \EOF +#!/bin/sh +echo $EDITOR_TEXT +EOF +chmod a+x fake-editor.sh + +test_expect_success 'interactive rebase with a dirty submodule' ' + + test submodule = $(git diff --name-only) && + HEAD=$(git rev-parse HEAD) && + GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \ + git rebase -i HEAD^ && + test submodule = $(git diff --name-only) + +' + +test_expect_success 'rebase with dirty file and submodule fails' ' + + echo yet another line >> file && + test_tick && + git commit -m next file && + echo rewrite > file && + test_tick && + git commit -m rewrite file && + echo dirty > file && + test_must_fail git rebase --onto HEAD~2 HEAD^ + +' + +test_expect_success 'stash with a dirty submodule' ' + + echo new > file && + CURRENT=$(cd submodule && git rev-parse HEAD) && + git stash && + test new != $(cat file) && + test submodule = $(git diff --name-only) && + test $CURRENT = $(cd submodule && git rev-parse HEAD) && + git stash apply && + test new = $(cat file) && + test $CURRENT = $(cd submodule && git rev-parse HEAD) + +' + +test_done diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh new file mode 100755 index 0000000000..7538756487 --- /dev/null +++ b/t/t7403-submodule-sync.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Copyright (c) 2008 David Aguilar +# + +test_description='git submodule sync + +These tests exercise the "git submodule sync" subcommand. +' + +. ./test-lib.sh + +test_expect_success setup ' + echo file > file && + git add file && + test_tick && + git commit -m upstream + git clone . super && + git clone super submodule && + (cd super && + git submodule add ../submodule submodule && + test_tick && + git commit -m "submodule" + ) && + git clone super super-clone && + (cd super-clone && git submodule update --init) +' + +test_expect_success 'change submodule' ' + (cd submodule && + echo second line >> file && + test_tick && + git commit -a -m "change submodule" + ) +' + +test_expect_success 'change submodule url' ' + (cd super && + cd submodule && + git checkout master && + git pull + ) && + mv submodule moved-submodule && + (cd super && + git config -f .gitmodules submodule.submodule.url ../moved-submodule + test_tick && + git commit -a -m moved-submodule + ) +' + +test_expect_success '"git submodule sync" should update submodule URLs' ' + (cd super-clone && + git pull && + git submodule sync + ) && + test -d "$(git config -f super-clone/submodule/.git/config \ + remote.origin.url)" && + (cd super-clone/submodule && + git checkout master && + git pull + ) +' + +test_done diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh new file mode 100755 index 0000000000..4a7b8933f4 --- /dev/null +++ b/t/t7405-submodule-merge.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +test_description='merging with submodules' + +. ./test-lib.sh + +# +# history +# +# a --- c +# / \ / +# root X +# \ / \ +# b --- d +# + +test_expect_success setup ' + + mkdir sub && + (cd sub && + git init && + echo original > file && + git add file && + test_tick && + git commit -m sub-root) && + git add sub && + test_tick && + git commit -m root && + + git checkout -b a master && + (cd sub && + echo A > file && + git add file && + test_tick && + git commit -m sub-a) && + git add sub && + test_tick && + git commit -m a && + + git checkout -b b master && + (cd sub && + echo B > file && + git add file && + test_tick && + git commit -m sub-b) && + git add sub && + test_tick && + git commit -m b && + + git checkout -b c a && + git merge -s ours b && + + git checkout -b d b && + git merge -s ours a +' + +test_expect_success 'merging with modify/modify conflict' ' + + git checkout -b test1 a && + test_must_fail git merge b && + test -f .git/MERGE_MSG && + git diff && + test -n "$(git ls-files -u)" +' + +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 new file mode 100755 index 0000000000..1382a8e58a --- /dev/null +++ b/t/t7406-submodule-update.sh @@ -0,0 +1,206 @@ +#!/bin/sh +# +# Copyright (c) 2009 Red Hat, Inc. +# + +test_description='Test updating submodules + +This test verifies that "git submodule update" detaches the HEAD of the +submodule and "git submodule update --rebase/--merge" does not detach the HEAD. +' + +. ./test-lib.sh + + +compare_head() +{ + sha_master=`git rev-list --max-count=1 master` + sha_head=`git rev-list --max-count=1 HEAD` + + test "$sha_master" = "$sha_head" +} + + +test_expect_success 'setup a submodule tree' ' + echo file > file && + git add file && + test_tick && + git commit -m upstream + git clone . super && + git clone super submodule && + git clone super rebasing && + git clone super merging && + (cd super && + git submodule add ../submodule submodule && + test_tick && + git commit -m "submodule" && + git submodule init submodule + ) && + (cd submodule && + echo "line2" > file && + git add file && + git commit -m "Commit 2" + ) && + (cd super && + (cd submodule && + git pull --rebase origin + ) && + git add submodule && + git commit -m "submodule update" + ) && + (cd super && + git submodule add ../rebasing rebasing && + test_tick && + git commit -m "rebasing" + ) && + (cd super && + git submodule add ../merging merging && + test_tick && + git commit -m "rebasing" + ) +' + +test_expect_success 'submodule update detaching the HEAD ' ' + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + ! compare_head + ) +' + +test_expect_success 'submodule update --rebase staying on master' ' + (cd super/submodule && + git checkout master + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --rebase submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update --merge staying on master' ' + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --merge submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - rebase in .git/config' ' + (cd super && + git config submodule.submodule.update rebase + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - checkout in .git/config but --rebase given' ' + (cd super && + git config submodule.submodule.update checkout + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --rebase submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - merge in .git/config' ' + (cd super && + git config submodule.submodule.update merge + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - checkout in .git/config but --merge given' ' + (cd super && + git config submodule.submodule.update checkout + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --merge submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - checkout in .git/config' ' + (cd super && + git config submodule.submodule.update checkout + ) && + (cd super/submodule && + git reset --hard HEAD^ + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + ! compare_head + ) +' + +test_expect_success 'submodule init picks up rebase' ' + (cd super && + git config -f .gitmodules submodule.rebasing.update rebase && + git submodule init rebasing && + test "rebase" = "$(git config submodule.rebasing.update)" + ) +' + +test_expect_success 'submodule init picks up merge' ' + (cd super && + git config -f .gitmodules submodule.merging.update merge && + git submodule init merging && + test "merge" = "$(git config submodule.merging.update)" + ) +' + +test_done diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh new file mode 100755 index 0000000000..db9365b645 --- /dev/null +++ b/t/t7407-submodule-foreach.sh @@ -0,0 +1,241 @@ +#!/bin/sh +# +# Copyright (c) 2009 Johan Herland +# + +test_description='Test "git submodule foreach" + +This test verifies that "git submodule foreach" correctly visits all submodules +that are currently checked out. +' + +. ./test-lib.sh + + +test_expect_success 'setup a submodule tree' ' + echo file > file && + git add file && + test_tick && + git commit -m upstream + git clone . super && + git clone super submodule && + ( + cd super && + git submodule add ../submodule sub1 && + git submodule add ../submodule sub2 && + git submodule add ../submodule sub3 && + git config -f .gitmodules --rename-section \ + submodule.sub1 submodule.foo1 && + git config -f .gitmodules --rename-section \ + submodule.sub2 submodule.foo2 && + git config -f .gitmodules --rename-section \ + submodule.sub3 submodule.foo3 && + git add .gitmodules + test_tick && + git commit -m "submodules" && + git submodule init sub1 && + git submodule init sub2 && + git submodule init sub3 + ) && + ( + cd submodule && + echo different > file && + git add file && + test_tick && + git commit -m "different" + ) && + ( + cd super && + ( + cd sub3 && + git pull + ) && + git add sub3 && + test_tick && + git commit -m "update sub3" + ) +' + +sub1sha1=$(cd super/sub1 && git rev-parse HEAD) +sub3sha1=$(cd super/sub3 && git rev-parse HEAD) + +pwd=$(pwd) + +cat > expect <<EOF +Entering 'sub1' +$pwd/clone-foo1-sub1-$sub1sha1 +Entering 'sub3' +$pwd/clone-foo3-sub3-$sub3sha1 +EOF + +test_expect_success 'test basic "submodule foreach" usage' ' + git clone super clone && + ( + cd clone && + git submodule update --init -- sub1 sub3 && + 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 +' + +test_expect_success 'setup nested submodules' ' + git clone submodule nested1 && + git clone submodule nested2 && + git clone submodule nested3 && + ( + cd nested3 && + git submodule add ../submodule submodule && + test_tick && + git commit -m "submodule" && + git submodule init submodule + ) && + ( + cd nested2 && + git submodule add ../nested3 nested3 && + test_tick && + git commit -m "nested3" && + git submodule init nested3 + ) && + ( + cd nested1 && + git submodule add ../nested2 nested2 && + test_tick && + git commit -m "nested2" && + git submodule init nested2 + ) && + ( + cd super && + git submodule add ../nested1 nested1 && + test_tick && + git commit -m "nested1" && + git submodule init nested1 + ) +' + +test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' ' + git clone super clone2 && + ( + cd clone2 && + test ! -d sub1/.git && + test ! -d sub2/.git && + test ! -d sub3/.git && + test ! -d nested1/.git && + git submodule update --init && + test -d sub1/.git && + test -d sub2/.git && + test -d sub3/.git && + test -d nested1/.git && + test ! -d nested1/nested2/.git && + git submodule foreach "git submodule update --init" && + test -d nested1/nested2/.git && + test ! -d nested1/nested2/nested3/.git + ) +' + +test_expect_success 'use "foreach --recursive" to checkout all submodules' ' + ( + cd clone2 && + git submodule foreach --recursive "git submodule update --init" && + test -d nested1/nested2/nested3/.git && + test -d nested1/nested2/nested3/submodule/.git + ) +' + +cat > expect <<EOF +Entering 'nested1' +Entering 'nested1/nested2' +Entering 'nested1/nested2/nested3' +Entering 'nested1/nested2/nested3/submodule' +Entering 'sub1' +Entering 'sub2' +Entering 'sub3' +EOF + +test_expect_success 'test messages from "foreach --recursive"' ' + ( + cd clone2 && + git submodule foreach --recursive "true" > ../actual + ) && + test_cmp expect actual +' + +cat > expect <<EOF +nested1-nested1 +nested2-nested2 +nested3-nested3 +submodule-submodule +foo1-sub1 +foo2-sub2 +foo3-sub3 +EOF + +test_expect_success 'test "foreach --quiet --recursive"' ' + ( + cd clone2 && + git submodule foreach -q --recursive "echo \$name-\$path" > ../actual + ) && + test_cmp expect actual +' + +test_expect_success 'use "update --recursive" to checkout all submodules' ' + git clone super clone3 && + ( + cd clone3 && + test ! -d sub1/.git && + test ! -d sub2/.git && + test ! -d sub3/.git && + test ! -d nested1/.git && + git submodule update --init --recursive && + test -d sub1/.git && + test -d sub2/.git && + test -d sub3/.git && + test -d nested1/.git && + test -d nested1/nested2/.git && + test -d nested1/nested2/nested3/.git && + test -d nested1/nested2/nested3/submodule/.git + ) +' + +nested1sha1=$(cd clone3/nested1 && git rev-parse HEAD) +nested2sha1=$(cd clone3/nested1/nested2 && git rev-parse HEAD) +nested3sha1=$(cd clone3/nested1/nested2/nested3 && git rev-parse HEAD) +submodulesha1=$(cd clone3/nested1/nested2/nested3/submodule && git rev-parse HEAD) +sub1sha1=$(cd clone3/sub1 && git rev-parse HEAD) +sub2sha1=$(cd clone3/sub2 && git rev-parse HEAD) +sub3sha1=$(cd clone3/sub3 && git rev-parse HEAD) +sub1sha1_short=$(cd clone3/sub1 && git rev-parse --short HEAD) +sub2sha1_short=$(cd clone3/sub2 && git rev-parse --short HEAD) + +cat > expect <<EOF + $nested1sha1 nested1 (heads/master) + $nested2sha1 nested1/nested2 (heads/master) + $nested3sha1 nested1/nested2/nested3 (heads/master) + $submodulesha1 nested1/nested2/nested3/submodule (heads/master) + $sub1sha1 sub1 ($sub1sha1_short) + $sub2sha1 sub2 ($sub2sha1_short) + $sub3sha1 sub3 (heads/master) +EOF + +test_expect_success 'test "status --recursive"' ' + ( + cd clone3 && + git submodule status --recursive > ../actual + ) && + test_cmp expect actual +' + +test_expect_success 'use "git clone --recursive" to checkout all submodules' ' + git clone --recursive super clone4 && + test -d clone4/.git && + test -d clone4/sub1/.git && + test -d clone4/sub2/.git && + test -d clone4/sub3/.git && + test -d clone4/nested1/.git && + test -d clone4/nested1/nested2/.git && + test -d clone4/nested1/nested2/nested3/.git && + test -d clone4/nested1/nested2/nested3/submodule/.git +' + +test_done diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh new file mode 100755 index 0000000000..cc16d3f05d --- /dev/null +++ b/t/t7408-submodule-reference.sh @@ -0,0 +1,81 @@ +#!/bin/sh +# +# Copyright (c) 2009, Red Hat Inc, Author: Michael S. Tsirkin (mst@redhat.com) +# + +test_description='test clone --reference' +. ./test-lib.sh + +base_dir=`pwd` + +U=$base_dir/UPLOAD_LOG + +test_expect_success 'preparing first repository' \ +'test_create_repo A && cd A && +echo first > file1 && +git add file1 && +git commit -m A-initial' + +cd "$base_dir" + +test_expect_success 'preparing second repository' \ +'git clone A B && cd B && +echo second > file2 && +git add file2 && +git commit -m B-addition && +git repack -a -d && +git prune' + +cd "$base_dir" + +test_expect_success 'preparing supermodule' \ +'test_create_repo super && cd super && +echo file > file && +git add file && +git commit -m B-super-initial' + +cd "$base_dir" + +test_expect_success 'submodule add --reference' \ +'cd super && git submodule add --reference ../B "file://$base_dir/A" sub && +git commit -m B-super-added' + +cd "$base_dir" + +test_expect_success 'after add: existence of info/alternates' \ +'test `wc -l <super/sub/.git/objects/info/alternates` = 1' + +cd "$base_dir" + +test_expect_success 'that reference gets used with add' \ +'cd super/sub && +echo "0 objects, 0 kilobytes" > expected && +git count-objects > current && +diff expected current' + +cd "$base_dir" + +test_expect_success 'cloning supermodule' \ +'git clone super super-clone' + +cd "$base_dir" + +test_expect_success 'update with reference' \ +'cd super-clone && git submodule update --init --reference ../B' + +cd "$base_dir" + +test_expect_success 'after update: existence of info/alternates' \ +'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1' + +cd "$base_dir" + +test_expect_success 'that reference gets used with update' \ +'cd super-clone/sub && +echo "0 objects, 0 kilobytes" > expected && +git count-objects > current && +diff expected current' + +cd "$base_dir" + +test_done diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh new file mode 100755 index 0000000000..aa9c577e9e --- /dev/null +++ b/t/t7500-commit.sh @@ -0,0 +1,218 @@ +#!/bin/sh +# +# Copyright (c) 2007 Steven Grimm +# + +test_description='git commit + +Tests for selected commit options.' + +. ./test-lib.sh + +commit_msg_is () { + test "`git log --pretty=format:%s%b -1`" = "$1" +} + +# A sanity check to see if commit is working at all. +test_expect_success 'a basic commit in an empty tree should succeed' ' + echo content > foo && + git add foo && + git commit -m "initial commit" +' + +test_expect_success 'nonexistent template file should return error' ' + echo changes >> foo && + git add foo && + test_must_fail git commit --template "$PWD"/notexist +' + +test_expect_success 'nonexistent template file in config should return error' ' + git config commit.template "$PWD"/notexist && + test_must_fail git commit && + git config --unset commit.template +' + +# From now on we'll use a template file that exists. +TEMPLATE="$PWD"/template + +test_expect_success 'unedited template should not commit' ' + echo "template line" > "$TEMPLATE" && + test_must_fail git commit --template "$TEMPLATE" +' + +test_expect_success 'unedited template with comments should not commit' ' + echo "# comment in template" >> "$TEMPLATE" && + test_must_fail git commit --template "$TEMPLATE" +' + +test_expect_success 'a Signed-off-by line by itself should not commit' ' + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-signed-off && + test_must_fail git commit --template "$TEMPLATE" + ) +' + +test_expect_success 'adding comments to a template should not commit' ' + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-comments && + test_must_fail git commit --template "$TEMPLATE" + ) +' + +test_expect_success 'adding real content to a template should commit' ' + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit --template "$TEMPLATE" + ) && + commit_msg_is "template linecommit message" +' + +test_expect_success '-t option should be short for --template' ' + echo "short template" > "$TEMPLATE" && + echo "new content" >> foo && + git add foo && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit -t "$TEMPLATE" + ) && + commit_msg_is "short templatecommit message" +' + +test_expect_success 'config-specified template should commit' ' + echo "new template" > "$TEMPLATE" && + git config commit.template "$TEMPLATE" && + echo "more content" >> foo && + git add foo && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit + ) && + git config --unset commit.template && + commit_msg_is "new templatecommit message" +' + +test_expect_success 'explicit commit message should override template' ' + echo "still more content" >> foo && + git add foo && + GIT_EDITOR="$TEST_DIRECTORY"/t7500/add-content git commit --template "$TEMPLATE" \ + -m "command line msg" && + commit_msg_is "command line msg" +' + +test_expect_success 'commit message from file should override template' ' + echo "content galore" >> foo && + git add foo && + echo "standard input msg" | + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit --template "$TEMPLATE" --file - + ) && + commit_msg_is "standard input msg" +' + +test_expect_success 'using alternate GIT_INDEX_FILE (1)' ' + + cp .git/index saved-index && + ( + echo some new content >file && + GIT_INDEX_FILE=.git/another_index && + export GIT_INDEX_FILE && + git add file && + git commit -m "commit using another index" && + git diff-index --exit-code HEAD && + git diff-files --exit-code + ) && + cmp .git/index saved-index >/dev/null + +' + +test_expect_success 'using alternate GIT_INDEX_FILE (2)' ' + + cp .git/index saved-index && + ( + rm -f .git/no-such-index && + GIT_INDEX_FILE=.git/no-such-index && + export GIT_INDEX_FILE && + git commit -m "commit using nonexistent index" && + test -z "$(git ls-files)" && + test -z "$(git ls-tree HEAD)" + + ) && + cmp .git/index saved-index >/dev/null +' + +cat > expect << EOF +zort + +Signed-off-by: C O Mitter <committer@example.com> +EOF + +test_expect_success '--signoff' ' + echo "yet another content *narf*" >> foo && + echo "zort" | git commit -s -F - foo && + git cat-file commit HEAD | sed "1,/^\$/d" > output && + test_cmp expect output +' + +test_expect_success 'commit message from file (1)' ' + mkdir subdir && + echo "Log in top directory" >log && + echo "Log in sub directory" >subdir/log && + ( + cd subdir && + git commit --allow-empty -F log + ) && + commit_msg_is "Log in sub directory" +' + +test_expect_success 'commit message from file (2)' ' + rm -f log && + echo "Log in sub directory" >subdir/log && + ( + cd subdir && + git commit --allow-empty -F log + ) && + commit_msg_is "Log in sub directory" +' + +test_expect_success 'commit message from stdin' ' + ( + cd subdir && + echo "Log with foo word" | git commit --allow-empty -F - + ) && + commit_msg_is "Log with foo word" +' + +test_expect_success 'commit -F overrides -t' ' + ( + cd subdir && + echo "-F log" > f.log && + echo "-t template" > t.template && + git commit --allow-empty -F f.log -t t.template + ) && + 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/t7500/add-comments b/t/t7500/add-comments new file mode 100755 index 0000000000..a72e65c891 --- /dev/null +++ b/t/t7500/add-comments @@ -0,0 +1,4 @@ +#!/bin/sh +echo "# this is a new comment" >> "$1" +echo "# and so is this" >> "$1" +exit 0 diff --git a/t/t7500/add-content b/t/t7500/add-content new file mode 100755 index 0000000000..2fa3d86a10 --- /dev/null +++ b/t/t7500/add-content @@ -0,0 +1,3 @@ +#!/bin/sh +echo "commit message" >> "$1" +exit 0 diff --git a/t/t7500/add-signed-off b/t/t7500/add-signed-off new file mode 100755 index 0000000000..e1d856af6d --- /dev/null +++ b/t/t7500/add-signed-off @@ -0,0 +1,3 @@ +#!/bin/sh +echo "Signed-off-by: foo <bar@frotz>" >> "$1" +exit 0 diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh new file mode 100755 index 0000000000..8297cb4f1e --- /dev/null +++ b/t/t7501-commit.sh @@ -0,0 +1,440 @@ +#!/bin/sh +# +# Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com> +# + +# FIXME: Test the various index usages, -i and -o, test reflog, +# signoff + +test_description='git commit' +. ./test-lib.sh + +test_tick + +test_expect_success \ + "initial status" \ + "echo 'bongo bongo' >file && + git add file && \ + git status | grep 'Initial commit'" + +test_expect_success \ + "fail initial amend" \ + "test_must_fail git commit --amend" + +test_expect_success \ + "initial commit" \ + "git commit -m initial" + +test_expect_success \ + "invalid options 1" \ + "test_must_fail git commit -m foo -m bar -F file" + +test_expect_success \ + "invalid options 2" \ + "test_must_fail git commit -C HEAD -m illegal" + +test_expect_success \ + "using paths with -a" \ + "echo King of the bongo >file && + test_must_fail git commit -m foo -a file" + +test_expect_success PERL \ + "using paths with --interactive" \ + "echo bong-o-bong >file && + ! (echo 7 | git commit -m foo --interactive file)" + +test_expect_success \ + "using invalid commit with -C" \ + "test_must_fail git commit -C bogus" + +test_expect_success \ + "testing nothing to commit" \ + "test_must_fail git commit -m initial" + +test_expect_success \ + "next commit" \ + "echo 'bongo bongo bongo' >file \ + git commit -m next -a" + +test_expect_success \ + "commit message from non-existing file" \ + "echo 'more bongo: bongo bongo bongo bongo' >file && \ + test_must_fail git commit -F gah -a" + +# Empty except stray tabs and spaces on a few lines. +sed -e 's/@$//' >msg <<EOF + @ + + @ +Signed-off-by: hula +EOF +test_expect_success \ + "empty commit message" \ + "test_must_fail git commit -F msg -a" + +test_expect_success \ + "commit message from file" \ + "echo 'this is the commit message, coming from a file' >msg && \ + git commit -F msg -a" + +cat >editor <<\EOF +#!/bin/sh +sed -e "s/a file/an amend commit/g" < "$1" > "$1-" +mv "$1-" "$1" +EOF +chmod 755 editor + +test_expect_success \ + "amend commit" \ + "EDITOR=./editor git commit --amend" + +test_expect_success \ + "passing -m and -F" \ + "echo 'enough with the bongos' >file && \ + test_must_fail git commit -F msg -m amending ." + +test_expect_success \ + "using message from other commit" \ + "git commit -C HEAD^ ." + +cat >editor <<\EOF +#!/bin/sh +sed -e "s/amend/older/g" < "$1" > "$1-" +mv "$1-" "$1" +EOF +chmod 755 editor + +test_expect_success \ + "editing message from other commit" \ + "echo 'hula hula' >file && \ + EDITOR=./editor git commit -c HEAD^ -a" + +test_expect_success \ + "message from stdin" \ + "echo 'silly new contents' >file && \ + echo commit message from stdin | git commit -F - -a" + +test_expect_success \ + "overriding author from command line" \ + "echo 'gak' >file && \ + git commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a >output 2>&1" + +test_expect_success \ + "commit --author output mentions author" \ + "grep Rubber.Duck output" + +test_expect_success PERL \ + "interactive add" \ + "echo 7 | git commit --interactive | grep 'What now'" + +test_expect_success \ + "showing committed revisions" \ + "git rev-list HEAD >current" + +cat >editor <<\EOF +#!/bin/sh +sed -e "s/good/bad/g" < "$1" > "$1-" +mv "$1-" "$1" +EOF +chmod 755 editor + +cat >msg <<EOF +A good commit message. +EOF + +test_expect_success \ + 'editor not invoked if -F is given' ' + echo "moo" >file && + EDITOR=./editor git commit -a -F msg && + git show -s --pretty=format:"%s" | grep -q good && + echo "quack" >file && + echo "Another good message." | EDITOR=./editor git commit -a -F - && + git show -s --pretty=format:"%s" | grep -q good + ' +# We could just check the head sha1, but checking each commit makes it +# easier to isolate bugs. + +cat >expected <<\EOF +72c0dc9855b0c9dadcbfd5a31cab072e0cb774ca +9b88fc14ce6b32e3d9ee021531a54f18a5cf38a2 +3536bbb352c3a1ef9a420f5b4242d48578b92aa7 +d381ac431806e53f3dd7ac2f1ae0534f36d738b9 +4fd44095ad6334f3ef72e4c5ec8ddf108174b54a +402702b49136e7587daa9280e91e4bb7cb2179f7 +EOF + +test_expect_success \ + 'validate git rev-list output.' \ + 'test_cmp expected current' + +test_expect_success 'partial commit that involves removal (1)' ' + + git rm --cached file && + mv file elif && + git add elif && + git commit -m "Partial: add elif" elif && + git diff-tree --name-status HEAD^ HEAD >current && + echo "A elif" >expected && + test_cmp expected current + +' + +test_expect_success 'partial commit that involves removal (2)' ' + + git commit -m "Partial: remove file" file && + git diff-tree --name-status HEAD^ HEAD >current && + echo "D file" >expected && + test_cmp expected current + +' + +test_expect_success 'partial commit that involves removal (3)' ' + + git rm --cached elif && + echo elif >elif && + git commit -m "Partial: modify elif" elif && + git diff-tree --name-status HEAD^ HEAD >current && + echo "M elif" >expected && + test_cmp expected current + +' + +author="The Real Author <someguy@his.email.org>" +test_expect_success 'amend commit to fix author' ' + + oldtick=$GIT_AUTHOR_DATE && + test_tick && + git reset --hard && + git cat-file -p HEAD | + sed -e "s/author.*/author $author $oldtick/" \ + -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ + expected && + git commit --amend --author="$author" && + git cat-file -p HEAD > current && + test_cmp expected current + +' + +test_expect_success 'amend commit to fix date' ' + + test_tick && + newtick=$GIT_AUTHOR_DATE && + git reset --hard && + git cat-file -p HEAD | + sed -e "s/author.*/author $author $newtick/" \ + -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ + expected && + git commit --amend --date="$newtick" && + git cat-file -p HEAD > current && + test_cmp expected current + +' + +test_expect_success 'sign off (1)' ' + + echo 1 >positive && + git add positive && + git commit -s -m "thank you" && + git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && + ( + echo thank you + echo + git var GIT_COMMITTER_IDENT | + sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'sign off (2)' ' + + echo 2 >positive && + git add positive && + existing="Signed-off-by: Watch This <watchthis@example.com>" && + git commit -s -m "thank you + +$existing" && + git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && + ( + echo thank you + echo + echo $existing + git var GIT_COMMITTER_IDENT | + sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" + ) >expected && + test_cmp expected actual + +' + +test_expect_success 'signoff gap' ' + + echo 3 >positive && + git add positive && + alt="Alt-RFC-822-Header: Value" && + git commit -s -m "welcome + +$alt" && + git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && + ( + echo welcome + echo + echo $alt + git var GIT_COMMITTER_IDENT | + sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'signoff gap 2' ' + + echo 4 >positive && + git add positive && + alt="fixed: 34" && + git commit -s -m "welcome + +We have now +$alt" && + git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && + ( + echo welcome + echo + echo We have now + echo $alt + echo + git var GIT_COMMITTER_IDENT | + sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /" + ) >expected && + test_cmp expected actual +' + +test_expect_success 'multiple -m' ' + + >negative && + git add negative && + git commit -m "one" -m "two" -m "three" && + git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && + ( + echo one + echo + echo two + echo + echo three + ) >expected && + test_cmp expected actual + +' + +author="The Real Author <someguy@his.email.org>" +test_expect_success 'amend commit to fix author' ' + + oldtick=$GIT_AUTHOR_DATE && + test_tick && + git reset --hard && + git cat-file -p HEAD | + sed -e "s/author.*/author $author $oldtick/" \ + -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \ + expected && + git commit --amend --author="$author" && + git cat-file -p HEAD > current && + test_cmp expected current + +' + +test_expect_success 'git commit <file> with dirty index' ' + echo tacocat > elif && + echo tehlulz > chz && + git add chz && + git commit elif -m "tacocat is a palindrome" && + git show --stat | grep elif && + git diff --cached | grep chz +' + +test_expect_success 'same tree (single parent)' ' + + git reset --hard + + if git commit -m empty + then + echo oops -- should have complained + false + else + : happy + fi + +' + +test_expect_success 'same tree (single parent) --allow-empty' ' + + git commit --allow-empty -m "forced empty" && + git cat-file commit HEAD | grep forced + +' + +test_expect_success 'same tree (merge and amend merge)' ' + + git checkout -b side HEAD^ && + echo zero >zero && + git add zero && + git commit -m "add zero" && + git checkout master && + + git merge -s ours side -m "empty ok" && + git diff HEAD^ HEAD >actual && + : >expected && + test_cmp expected actual && + + git commit --amend -m "empty really ok" && + git diff HEAD^ HEAD >actual && + : >expected && + test_cmp expected actual + +' + +test_expect_success 'amend using the message from another commit' ' + + git reset --hard && + test_tick && + git commit --allow-empty -m "old commit" && + old=$(git rev-parse --verify HEAD) && + test_tick && + git commit --allow-empty -m "new commit" && + new=$(git rev-parse --verify HEAD) && + test_tick && + git commit --allow-empty --amend -C "$old" && + git show --pretty="format:%ad %s" "$old" >expected && + git show --pretty="format:%ad %s" HEAD >actual && + test_cmp expected actual + +' + +test_expect_success 'amend using the message from a commit named with tag' ' + + git reset --hard && + test_tick && + git commit --allow-empty -m "old commit" && + old=$(git rev-parse --verify HEAD) && + git tag -a -m "tag on old" tagged-old HEAD && + test_tick && + git commit --allow-empty -m "new commit" && + new=$(git rev-parse --verify HEAD) && + test_tick && + git commit --allow-empty --amend -C tagged-old && + git show --pretty="format:%ad %s" "$old" >expected && + git show --pretty="format:%ad %s" HEAD >actual && + test_cmp expected actual + +' + +test_expect_success 'amend can copy notes' ' + + git config notes.rewrite.amend true && + git config notes.rewriteRef "refs/notes/*" && + test_commit foo && + git notes add -m"a note" && + test_tick && + git commit --amend -m"new foo" && + test "$(git notes show)" = "a note" + +' + +test_done diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh new file mode 100755 index 0000000000..ac2e187a57 --- /dev/null +++ b/t/t7502-commit.sh @@ -0,0 +1,447 @@ +#!/bin/sh + +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 && + git add "commit is" not && + echo update added "commit is" file >"commit is" && + echo also update another >not/forbid && + test_tick && + git commit -a -m "initial with -a" && + + git cat-file blob HEAD:"commit is" >current.1 && + git cat-file blob HEAD:not/forbid >current.2 && + + cmp current.1 "commit is" && + cmp current.2 not/forbid + +' + +test_expect_success 'partial' ' + + echo another >"commit is" && + echo another >not/forbid && + test_tick && + git commit -m "partial commit to handle a file" "commit is" && + + changed=$(git diff-tree --name-only HEAD^ HEAD) && + test "$changed" = "commit is" + +' + +test_expect_success 'partial modification in a subdirectory' ' + + test_tick && + git commit -m "partial commit to subdirectory" not && + + changed=$(git diff-tree -r --name-only HEAD^ HEAD) && + test "$changed" = "not/forbid" + +' + +test_expect_success 'partial removal' ' + + git rm not/forbid && + git commit -m "partial commit to remove not/forbid" not && + + changed=$(git diff-tree -r --name-only HEAD^ HEAD) && + test "$changed" = "not/forbid" && + remain=$(git ls-tree -r --name-only HEAD) && + test "$remain" = "commit is" + +' + +test_expect_success 'sign off' ' + + >positive && + git add positive && + git commit -s -m "thank you" && + actual=$(git cat-file commit HEAD | sed -ne "s/Signed-off-by: //p") && + expected=$(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/") && + test "z$actual" = "z$expected" + +' + +test_expect_success 'multiple -m' ' + + >negative && + git add negative && + git commit -m "one" -m "two" -m "three" && + actual=$(git cat-file commit HEAD | sed -e "1,/^\$/d") && + expected=$(echo one; echo; echo two; echo; echo three) && + test "z$actual" = "z$expected" + +' + +test_expect_success 'verbose' ' + + echo minus >negative && + git add negative && + git status -v | sed -ne "/^diff --git /p" >actual && + echo "diff --git a/negative b/negative" >expect && + test_cmp expect actual + +' + +test_expect_success 'verbose respects diff config' ' + + git config color.diff always && + git status -v >actual && + grep "\[1mdiff --git" actual && + git config --unset color.diff +' + +test_expect_success 'cleanup commit messages (verbatim,-t)' ' + + echo >>negative && + { echo;echo "# text";echo; } >expect && + git commit --cleanup=verbatim -t expect -a && + git cat-file -p HEAD |sed -e "1,/^\$/d" |head -n 3 >actual && + test_cmp expect actual + +' + +test_expect_success 'cleanup commit messages (verbatim,-F)' ' + + echo >>negative && + git commit --cleanup=verbatim -F expect -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + test_cmp expect actual + +' + +test_expect_success 'cleanup commit messages (verbatim,-m)' ' + + echo >>negative && + git commit --cleanup=verbatim -m "$(cat expect)" -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + test_cmp expect actual + +' + +test_expect_success 'cleanup commit messages (whitespace,-F)' ' + + echo >>negative && + { echo;echo "# text";echo; } >text && + echo "# text" >expect && + git commit --cleanup=whitespace -F text -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + test_cmp expect actual + +' + +test_expect_success 'cleanup commit messages (strip,-F)' ' + + echo >>negative && + { echo;echo "# text";echo sample;echo; } >text && + echo sample >expect && + git commit --cleanup=strip -F text -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + test_cmp expect actual + +' + +echo "sample + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit." >expect + +test_expect_success 'cleanup commit messages (strip,-F,-e)' ' + + echo >>negative && + { echo;echo sample;echo; } >text && + git commit -e -F text -a && + head -n 4 .git/COMMIT_EDITMSG >actual && + test_cmp expect actual + +' + +echo "# +# Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> +#" >> expect + +test_expect_success 'author different from committer' ' + + echo >>negative && + git commit -e -m "sample" + head -n 7 .git/COMMIT_EDITMSG >actual && + test_cmp expect actual +' + +mv expect expect.tmp +sed '$d' < expect.tmp > expect +rm -f expect.tmp +echo "# Committer: +#" >> expect + +test_expect_success 'committer is automatic' ' + + echo >>negative && + ( + unset GIT_COMMITTER_EMAIL + unset GIT_COMMITTER_NAME + # must fail because there is no change + test_must_fail git commit -e -m "sample" + ) && + head -n 8 .git/COMMIT_EDITMSG | \ + sed "s/^# Committer: .*/# Committer:/" >actual && + test_cmp expect actual +' + +pwd=`pwd` +cat >> .git/FAKE_EDITOR << EOF +#! /bin/sh +echo editor started > "$pwd/.git/result" +exit 0 +EOF +chmod +x .git/FAKE_EDITOR + +test_expect_success 'do not fire editor in the presence of conflicts' ' + + git clean -f && + echo f >g && + git add g && + git commit -m "add g" && + git branch second && + echo master >g && + echo g >h && + git add g h && + git commit -m "modify g and add h" && + git checkout second && + echo second >g && + git add g && + git commit -m second && + # Must fail due to conflict + test_must_fail git cherry-pick -n master && + echo "editor not started" >.git/result && + ( + GIT_EDITOR="$(pwd)/.git/FAKE_EDITOR" && + export GIT_EDITOR && + test_must_fail git commit + ) && + test "$(cat .git/result)" = "editor not started" +' + +pwd=`pwd` +cat >.git/FAKE_EDITOR <<EOF +#! $SHELL_PATH +# kill -TERM command added below. +EOF + +test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' ' + echo >>negative && + ! "$SHELL_PATH" -c '\'' + echo kill -TERM $$ >> .git/FAKE_EDITOR + GIT_EDITOR=.git/FAKE_EDITOR + export GIT_EDITOR + exec git commit -a'\'' && + test ! -f .git/index.lock +' + +rm -f .git/MERGE_MSG .git/COMMIT_EDITMSG +git reset -q --hard + +test_expect_success 'Hand committing of a redundant merge removes dups' ' + + git rev-parse second master >expect && + test_must_fail git merge second master && + git checkout master g && + EDITOR=: git commit -a && + git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual && + test_cmp expect actual + +' + +test_expect_success 'A single-liner subject with a token plus colon is not a footer' ' + + git reset --hard && + git commit -s -m "hello: kitty" --allow-empty && + git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + test $(wc -l <actual) = 3 + +' + +cat >.git/FAKE_EDITOR <<EOF +#!$SHELL_PATH +mv "\$1" "\$1.orig" +( + echo message + cat "\$1.orig" +) >"\$1" +EOF + +echo '## Custom template' >template + +clear_config () { + ( + git config --unset-all "$1" + case $? in + 0|5) exit 0 ;; + *) exit 1 ;; + esac + ) +} + +try_commit () { + git reset --hard && + echo >>negative && + GIT_EDITOR=.git/FAKE_EDITOR git commit -a $* $use_template && + case "$use_template" in + '') + ! grep "^## Custom template" .git/COMMIT_EDITMSG ;; + *) + grep "^## Custom template" .git/COMMIT_EDITMSG ;; + esac +} + +try_commit_status_combo () { + + test_expect_success 'commit' ' + clear_config commit.status && + try_commit "" && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit' ' + clear_config commit.status && + try_commit "" && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --status' ' + clear_config commit.status && + try_commit --status && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --no-status' ' + clear_config commit.status && + try_commit --no-status + ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit with commit.status = yes' ' + clear_config commit.status && + git config commit.status yes && + try_commit "" && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit with commit.status = no' ' + clear_config commit.status && + git config commit.status no && + try_commit "" && + ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --status with commit.status = yes' ' + clear_config commit.status && + git config commit.status yes && + try_commit --status && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --no-status with commit.status = yes' ' + clear_config commit.status && + git config commit.status yes && + try_commit --no-status && + ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --status with commit.status = no' ' + clear_config commit.status && + git config commit.status no && + try_commit --status && + grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + + test_expect_success 'commit --no-status with commit.status = no' ' + clear_config commit.status && + git config commit.status no && + try_commit --no-status && + ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG + ' + +} + +try_commit_status_combo + +use_template="-t template" + +try_commit_status_combo + +test_done diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh new file mode 100755 index 0000000000..8528f64c8d --- /dev/null +++ b/t/t7503-pre-commit-hook.sh @@ -0,0 +1,88 @@ +#!/bin/sh + +test_description='pre-commit hook' + +. ./test-lib.sh + +test_expect_success 'with no hook' ' + + echo "foo" > file && + git add file && + git commit -m "first" + +' + +test_expect_success '--no-verify with no hook' ' + + echo "bar" > file && + git add file && + git commit --no-verify -m "bar" + +' + +# now install hook that always succeeds +HOOKDIR="$(git rev-parse --git-dir)/hooks" +HOOK="$HOOKDIR/pre-commit" +mkdir -p "$HOOKDIR" +cat > "$HOOK" <<EOF +#!/bin/sh +exit 0 +EOF +chmod +x "$HOOK" + +test_expect_success 'with succeeding hook' ' + + echo "more" >> file && + git add file && + git commit -m "more" + +' + +test_expect_success '--no-verify with succeeding hook' ' + + echo "even more" >> file && + git add file && + git commit --no-verify -m "even more" + +' + +# now a hook that fails +cat > "$HOOK" <<EOF +#!/bin/sh +exit 1 +EOF + +test_expect_success 'with failing hook' ' + + echo "another" >> file && + git add file && + test_must_fail git commit -m "another" + +' + +test_expect_success '--no-verify with failing hook' ' + + echo "stuff" >> file && + git add file && + git commit --no-verify -m "stuff" + +' + +chmod -x "$HOOK" +test_expect_success POSIXPERM 'with non-executable hook' ' + + echo "content" >> file && + git add file && + git commit -m "content" + +' + +test_expect_success POSIXPERM '--no-verify with non-executable hook' ' + + echo "more content" >> file && + git add file && + git commit --no-verify -m "more content" + +' + +test_done diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh new file mode 100755 index 0000000000..1f53ea8090 --- /dev/null +++ b/t/t7504-commit-msg-hook.sh @@ -0,0 +1,223 @@ +#!/bin/sh + +test_description='commit-msg hook' + +. ./test-lib.sh + +test_expect_success 'with no hook' ' + + echo "foo" > file && + git add file && + git commit -m "first" + +' + +# set up fake editor for interactive editing +cat > fake-editor <<'EOF' +#!/bin/sh +cp FAKE_MSG "$1" +exit 0 +EOF +chmod +x fake-editor + +## Not using test_set_editor here so we can easily ensure the editor variable +## is only set for the editor tests +FAKE_EDITOR="$(pwd)/fake-editor" +export FAKE_EDITOR + +test_expect_success 'with no hook (editor)' ' + + echo "more foo" >> file && + git add file && + echo "more foo" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit + +' + +test_expect_success '--no-verify with no hook' ' + + echo "bar" > file && + git add file && + git commit --no-verify -m "bar" + +' + +test_expect_success '--no-verify with no hook (editor)' ' + + echo "more bar" > file && + git add file && + echo "more bar" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify + +' + +# now install hook that always succeeds +HOOKDIR="$(git rev-parse --git-dir)/hooks" +HOOK="$HOOKDIR/commit-msg" +mkdir -p "$HOOKDIR" +cat > "$HOOK" <<EOF +#!/bin/sh +exit 0 +EOF +chmod +x "$HOOK" + +test_expect_success 'with succeeding hook' ' + + echo "more" >> file && + git add file && + git commit -m "more" + +' + +test_expect_success 'with succeeding hook (editor)' ' + + echo "more more" >> file && + git add file && + echo "more more" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit + +' + +test_expect_success '--no-verify with succeeding hook' ' + + echo "even more" >> file && + git add file && + git commit --no-verify -m "even more" + +' + +test_expect_success '--no-verify with succeeding hook (editor)' ' + + echo "even more more" >> file && + git add file && + echo "even more more" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify + +' + +# now a hook that fails +cat > "$HOOK" <<EOF +#!/bin/sh +exit 1 +EOF + +test_expect_success 'with failing hook' ' + + echo "another" >> file && + git add file && + test_must_fail git commit -m "another" + +' + +test_expect_success 'with failing hook (editor)' ' + + echo "more another" >> file && + git add file && + echo "more another" > FAKE_MSG && + ! (GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit) + +' + +test_expect_success '--no-verify with failing hook' ' + + echo "stuff" >> file && + git add file && + git commit --no-verify -m "stuff" + +' + +test_expect_success '--no-verify with failing hook (editor)' ' + + echo "more stuff" >> file && + git add file && + echo "more stuff" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify + +' + +chmod -x "$HOOK" +test_expect_success POSIXPERM 'with non-executable hook' ' + + echo "content" >> file && + git add file && + git commit -m "content" + +' + +test_expect_success POSIXPERM 'with non-executable hook (editor)' ' + + echo "content again" >> file && + git add file && + echo "content again" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -m "content again" + +' + +test_expect_success POSIXPERM '--no-verify with non-executable hook' ' + + echo "more content" >> file && + git add file && + git commit --no-verify -m "more content" + +' + +test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' ' + + echo "even more content" >> file && + git add file && + echo "even more content" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify + +' + +# now a hook that edits the commit message +cat > "$HOOK" <<'EOF' +#!/bin/sh +echo "new message" > "$1" +exit 0 +EOF +chmod +x "$HOOK" + +commit_msg_is () { + test "`git log --pretty=format:%s%b -1`" = "$1" +} + +test_expect_success 'hook edits commit message' ' + + echo "additional" >> file && + git add file && + git commit -m "additional" && + commit_msg_is "new message" + +' + +test_expect_success 'hook edits commit message (editor)' ' + + echo "additional content" >> file && + git add file && + echo "additional content" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit && + commit_msg_is "new message" + +' + +test_expect_success "hook doesn't edit commit message" ' + + echo "plus" >> file && + git add file && + git commit --no-verify -m "plus" && + commit_msg_is "plus" + +' + +test_expect_success "hook doesn't edit commit message (editor)" ' + + echo "more plus" >> file && + git add file && + echo "more plus" > FAKE_MSG && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify && + commit_msg_is "more plus" + +' + +test_done diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh new file mode 100755 index 0000000000..ff189624d4 --- /dev/null +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -0,0 +1,159 @@ +#!/bin/sh + +test_description='prepare-commit-msg hook' + +. ./test-lib.sh + +test_expect_success 'with no hook' ' + + echo "foo" > file && + git add file && + git commit -m "first" + +' + +# set up fake editor for interactive editing +cat > fake-editor <<'EOF' +#!/bin/sh +exit 0 +EOF +chmod +x fake-editor + +## Not using test_set_editor here so we can easily ensure the editor variable +## is only set for the editor tests +FAKE_EDITOR="$(pwd)/fake-editor" +export FAKE_EDITOR + +# now install hook that always succeeds and adds a message +HOOKDIR="$(git rev-parse --git-dir)/hooks" +HOOK="$HOOKDIR/prepare-commit-msg" +mkdir -p "$HOOKDIR" +echo "#!$SHELL_PATH" > "$HOOK" +cat >> "$HOOK" <<'EOF' + +if test "$2" = commit; then + source=$(git rev-parse "$3") +else + source=${2-default} +fi +if test "$GIT_EDITOR" = :; then + sed -e "1s/.*/$source (no editor)/" "$1" > msg.tmp +else + sed -e "1s/.*/$source/" "$1" > msg.tmp +fi +mv msg.tmp "$1" +exit 0 +EOF +chmod +x "$HOOK" + +echo dummy template > "$(git rev-parse --git-dir)/template" + +test_expect_success 'with hook (-m)' ' + + echo "more" >> file && + git add file && + git commit -m "more" && + test "`git log -1 --pretty=format:%s`" = "message (no editor)" + +' + +test_expect_success 'with hook (-m editor)' ' + + echo "more" >> file && + git add file && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -m "more more" && + test "`git log -1 --pretty=format:%s`" = message + +' + +test_expect_success 'with hook (-t)' ' + + echo "more" >> file && + git add file && + git commit -t "$(git rev-parse --git-dir)/template" && + test "`git log -1 --pretty=format:%s`" = template + +' + +test_expect_success 'with hook (-F)' ' + + echo "more" >> file && + git add file && + (echo more | git commit -F -) && + test "`git log -1 --pretty=format:%s`" = "message (no editor)" + +' + +test_expect_success 'with hook (-F editor)' ' + + echo "more" >> file && + git add file && + (echo more more | GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -F -) && + test "`git log -1 --pretty=format:%s`" = message + +' + +test_expect_success 'with hook (-C)' ' + + head=`git rev-parse HEAD` && + echo "more" >> file && + git add file && + git commit -C $head && + test "`git log -1 --pretty=format:%s`" = "$head (no editor)" + +' + +test_expect_success 'with hook (editor)' ' + + echo "more more" >> file && + git add file && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit && + test "`git log -1 --pretty=format:%s`" = default + +' + +test_expect_success 'with hook (--amend)' ' + + head=`git rev-parse HEAD` && + echo "more" >> file && + git add file && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --amend && + test "`git log -1 --pretty=format:%s`" = "$head" + +' + +test_expect_success 'with hook (-c)' ' + + head=`git rev-parse HEAD` && + echo "more" >> file && + git add file && + GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head && + test "`git log -1 --pretty=format:%s`" = "$head" + +' + +cat > "$HOOK" <<'EOF' +#!/bin/sh +exit 1 +EOF + +test_expect_success 'with failing hook' ' + + head=`git rev-parse HEAD` && + echo "more" >> file && + git add file && + ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head + +' + +test_expect_success 'with failing hook (--no-verify)' ' + + head=`git rev-parse HEAD` && + echo "more" >> file && + git add file && + ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head + +' + + +test_done diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh new file mode 100755 index 0000000000..3d4f85d74f --- /dev/null +++ b/t/t7506-status-submodule.sh @@ -0,0 +1,190 @@ +#!/bin/sh + +test_description='git status for submodule' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_create_repo sub && + ( + cd sub && + : >bar && + git add bar && + git commit -m " Add bar" && + : >foo && + git add foo && + git commit -m " Add foo" + ) && + echo output > .gitignore && + git add sub .gitignore && + git commit -m "Add submodule sub" +' + +test_expect_success 'status clean' ' + git status >output && + grep "nothing to commit" output +' + +test_expect_success 'commit --dry-run -a clean' ' + test_must_fail git commit --dry-run -a >output && + grep "nothing to commit" output +' + +test_expect_success 'status with modified file in submodule' ' + (cd sub && git reset --hard) && + echo "changed" >sub/foo && + git status >output && + grep "modified: sub (modified content)" output +' + +test_expect_success 'status with modified file in submodule (porcelain)' ' + (cd sub && git reset --hard) && + echo "changed" >sub/foo && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with added file in submodule' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + git status >output && + grep "modified: sub (modified content)" output +' + +test_expect_success 'status with added file in submodule (porcelain)' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with untracked file in submodule' ' + (cd sub && git reset --hard) && + echo "content" >sub/new-file && + git status >output && + grep "modified: sub (untracked content)" output +' + +test_expect_success 'status -uno with untracked file in submodule' ' + git status -uno >output && + grep "^nothing to commit" output +' + +test_expect_success 'status with untracked file in submodule (porcelain)' ' + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with added and untracked file in submodule' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + echo "content" >sub/new-file && + git status >output && + grep "modified: sub (modified content, untracked content)" output +' + +test_expect_success 'status with added and untracked file in submodule (porcelain)' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + echo "content" >sub/new-file && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with modified file in modified submodule' ' + (cd sub && git reset --hard) && + rm sub/new-file && + (cd sub && echo "next change" >foo && git commit -m "next change" foo) && + echo "changed" >sub/foo && + git status >output && + grep "modified: sub (new commits, modified content)" output +' + +test_expect_success 'status with modified file in modified submodule (porcelain)' ' + (cd sub && git reset --hard) && + echo "changed" >sub/foo && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with added file in modified submodule' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + git status >output && + grep "modified: sub (new commits, modified content)" output +' + +test_expect_success 'status with added file in modified submodule (porcelain)' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with untracked file in modified submodule' ' + (cd sub && git reset --hard) && + echo "content" >sub/new-file && + git status >output && + grep "modified: sub (new commits, untracked content)" output +' + +test_expect_success 'status with untracked file in modified submodule (porcelain)' ' + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'status with added and untracked file in modified submodule' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + echo "content" >sub/new-file && + git status >output && + grep "modified: sub (new commits, modified content, untracked content)" output +' + +test_expect_success 'status with added and untracked file in modified submodule (porcelain)' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + echo "content" >sub/new-file && + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF +' + +test_expect_success 'setup .git file for sub' ' + (cd sub && + rm -f new-file + REAL="$(pwd)/../.real" && + mv .git "$REAL" + echo "gitdir: $REAL" >.git) && + echo .real >>.gitignore && + git commit -m "added .real to .gitignore" .gitignore +' + +test_expect_success 'status with added file in modified submodule with .git file' ' + (cd sub && git reset --hard && echo >foo && git add foo) && + git status >output && + grep "modified: sub (new commits, modified content)" output +' + +test_expect_success 'rm submodule contents' ' + rm -rf sub/* sub/.git +' + +test_expect_success 'status clean (empty submodule dir)' ' + git status >output && + grep "nothing to commit" output +' + +test_expect_success 'status -a clean (empty submodule dir)' ' + test_must_fail git commit --dry-run -a >output && + grep "nothing to commit" output +' + +test_done diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh new file mode 100755 index 0000000000..da5bd3b5a5 --- /dev/null +++ b/t/t7507-commit-verbose.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='verbose commit template' +. ./test-lib.sh + +cat >check-for-diff <<EOF +#!$SHELL_PATH +exec grep '^diff --git' "\$1" +EOF +chmod +x check-for-diff +test_set_editor "$PWD/check-for-diff" + +cat >message <<'EOF' +subject + +body +EOF + +test_expect_success 'setup' ' + echo content >file && + git add file && + git commit -F message +' + +test_expect_success 'initial commit shows verbose diff' ' + git commit --amend -v +' + +test_expect_success 'second commit' ' + echo content modified >file && + git add file && + git commit -F message +' + +check_message() { + git log -1 --pretty=format:%s%n%n%b >actual && + test_cmp "$1" actual +} + +test_expect_success 'verbose diff is stripped out' ' + git commit --amend -v && + check_message message +' + +test_expect_success 'verbose diff is stripped out (mnemonicprefix)' ' + git config diff.mnemonicprefix true && + git commit --amend -v && + check_message message +' + +cat >diff <<'EOF' +This is an example commit message that contains a diff. + +diff --git c/file i/file +new file mode 100644 +index 0000000..f95c11d +--- /dev/null ++++ i/file +@@ -0,0 +1 @@ ++this is some content +EOF + +test_expect_success 'diff in message is retained without -v' ' + git commit --amend -F diff && + check_message diff +' + +test_expect_failure 'diff in message is retained with -v' ' + git commit --amend -F diff -v && + check_message diff +' + +test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh new file mode 100755 index 0000000000..a72fe3ae64 --- /dev/null +++ b/t/t7508-status.sh @@ -0,0 +1,938 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='git status' + +. ./test-lib.sh + +test_expect_success 'setup' ' + : >tracked && + : >modified && + mkdir dir1 && + : >dir1/tracked && + : >dir1/modified && + mkdir dir2 && + : >dir1/tracked && + : >dir1/modified && + git add . && + + git status >output && + + test_tick && + git commit -m initial && + : >untracked && + : >dir1/untracked && + : >dir2/untracked && + echo 1 >dir1/modified && + echo 2 >dir2/modified && + echo 3 >dir2/added && + git add dir2/added +' + +test_expect_success 'status (1)' ' + + grep "use \"git rm --cached <file>\.\.\.\" to unstage" output + +' + +cat >expect <<\EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + +test_expect_success 'status (2)' ' + + git status >output && + 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: +# 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 +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +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: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files not listed (use -u option to show untracked files) +EOF +test_expect_success 'status -uno' ' + mkdir dir3 && + : >dir3/untracked1 && + : >dir3/untracked2 && + git status -uno >output && + test_cmp expect output +' + +test_expect_success 'status (status.showUntrackedFiles no)' ' + git config status.showuntrackedfiles no + git status >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# 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 +EOF +test_expect_success 'status -s -uno' ' + git config --unset status.showuntrackedfiles + git status -s -uno >output && + test_cmp expect output +' + +test_expect_success 'status -s (status.showUntrackedFiles no)' ' + git config status.showuntrackedfiles no + git status -s >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# dir3/ +# expect +# output +# untracked +EOF +test_expect_success 'status -unormal' ' + git status -unormal >output && + test_cmp expect output +' + +test_expect_success 'status (status.showUntrackedFiles normal)' ' + git config status.showuntrackedfiles normal + git status >output && + test_cmp expect output +' + +cat >expect <<EOF + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? dir3/ +?? expect +?? output +?? untracked +EOF +test_expect_success 'status -s -unormal' ' + git config --unset status.showuntrackedfiles + git status -s -unormal >output && + test_cmp expect output +' + +test_expect_success 'status -s (status.showUntrackedFiles normal)' ' + git config status.showuntrackedfiles normal + git status -s >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# dir3/untracked1 +# dir3/untracked2 +# expect +# output +# untracked +EOF +test_expect_success 'status -uall' ' + git status -uall >output && + test_cmp expect output +' +test_expect_success 'status (status.showUntrackedFiles all)' ' + git config status.showuntrackedfiles all + git status >output && + rm -rf dir3 && + git config --unset status.showuntrackedfiles && + test_cmp expect output +' + +cat >expect <<EOF + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF +test_expect_success 'status -s -uall' ' + git config --unset status.showuntrackedfiles + git status -s -uall >output && + test_cmp expect output +' +test_expect_success 'status -s (status.showUntrackedFiles all)' ' + git config status.showuntrackedfiles all + git status -s >output && + rm -rf dir3 && + git config --unset status.showuntrackedfiles && + test_cmp expect output +' + +cat >expect <<\EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: ../dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# untracked +# ../dir2/modified +# ../dir2/untracked +# ../expect +# ../output +# ../untracked +EOF + +test_expect_success 'status with relative paths' ' + + (cd dir1 && git status) >output && + test_cmp expect output + +' + +cat >expect <<\EOF + M modified +A ../dir2/added +?? untracked +?? ../dir2/modified +?? ../dir2/untracked +?? ../expect +?? ../output +?? ../untracked +EOF +test_expect_success 'status -s with relative paths' ' + + (cd dir1 && git status -s) >output && + test_cmp expect output + +' + +cat >expect <<\EOF + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +test_expect_success 'status --porcelain ignores relative paths setting' ' + + (cd dir1 && git status --porcelain) >output && + test_cmp expect output + +' + +test_expect_success 'setup unique colors' ' + + git config status.color.untracked blue + +' + +cat >expect <<\EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# <GREEN>new file: dir2/added<RESET> +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# <RED>modified: dir1/modified<RESET> +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# <BLUE>dir1/untracked<RESET> +# <BLUE>dir2/modified<RESET> +# <BLUE>dir2/untracked<RESET> +# <BLUE>expect<RESET> +# <BLUE>output<RESET> +# <BLUE>untracked<RESET> +EOF + +test_expect_success 'status with color.ui' ' + + git config color.ui always && + git status | test_decode_color >output && + test_cmp expect output + +' + +test_expect_success 'status with color.status' ' + + git config --unset color.ui && + git config color.status always && + git status | test_decode_color >output && + test_cmp expect output + +' + +cat >expect <<\EOF + <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 with color.ui' ' + + git config --unset color.status && + git config color.ui always && + git status -s | test_decode_color >output && + test_cmp expect output + +' + +test_expect_success 'status -s with color.status' ' + + git config --unset color.ui && + git config color.status always && + git status -s | test_decode_color >output && + test_cmp expect output + +' + +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 +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +test_expect_success 'status --porcelain ignores color.ui' ' + + git config --unset color.status && + git config color.ui always && + git status --porcelain | test_decode_color >output && + test_cmp expect output + +' + +test_expect_success 'status --porcelain ignores color.status' ' + + git config --unset color.ui && + git config color.status always && + git status --porcelain | test_decode_color >output && + test_cmp expect output + +' + +# recover unconditionally from color tests +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: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# +# Changed but not updated: +# (use "git add <file>..." to update what will be committed) +# (use "git checkout -- <file>..." to discard changes in working directory) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF + + +test_expect_success 'status without relative paths' ' + + git config status.relativePaths false + (cd dir1 && git status) >output && + test_cmp expect output + +' + +cat >expect <<\EOF + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +test_expect_success 'status -s without relative paths' ' + + (cd dir1 && git status -s) >output && + test_cmp expect output + +' + +cat <<EOF >expect +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# modified: dir1/modified +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/ +# expect +# output +# untracked +EOF +test_expect_success 'dry-run of partial commit excluding new file in index' ' + git commit --dry-run dir1/modified >output && + test_cmp expect output +' + +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 && + >foo && + git add foo && + git commit -m "Add foo" + ) && + git add sm +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# new file: 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 +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF +test_expect_success 'status submodule summary is disabled by default' ' + git status >output && + test_cmp expect output +' + +# we expect the same as the previous test +test_expect_success 'status --untracked-files=all does not show submodule' ' + git status --untracked-files=all >output && + test_cmp expect output +' + +cat >expect <<EOF + M dir1/modified +A dir2/added +A sm +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF +test_expect_success 'status -s submodule summary is disabled by default' ' + git status -s >output && + test_cmp expect output +' + +# we expect the same as the previous test +test_expect_success 'status -s --untracked-files=all does not show submodule' ' + git status -s --untracked-files=all >output && + test_cmp expect output +' + +head=$(cd sm && git rev-parse --short=7 --verify HEAD) + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD <file>..." to unstage) +# +# new file: dir2/added +# new file: 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 0000000...$head (1): +# > Add foo +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF +test_expect_success 'status submodule summary' ' + git config status.submodulesummary 10 && + git status >output && + test_cmp expect output +' + +cat >expect <<EOF + M dir1/modified +A dir2/added +A sm +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF +test_expect_success 'status -s submodule summary' ' + git status -s >output && + test_cmp expect output +' + +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) +# +# 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 'status submodule summary (clean submodule)' ' + git commit -m "commit submodule" && + git config status.submodulesummary 10 && + test_must_fail git commit --dry-run >output && + test_cmp expect output && + git status >output && + test_cmp expect output +' + +cat >expect <<EOF + M dir1/modified +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF +test_expect_success 'status -s submodule summary (clean submodule)' ' + git status -s >output && + test_cmp expect output +' + +cat >expect <<EOF +# On branch master +# Changes to be committed: +# (use "git reset HEAD^1 <file>..." to unstage) +# +# new file: dir2/added +# new file: 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 0000000...$head (1): +# > Add foo +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# dir1/untracked +# dir2/modified +# dir2/untracked +# expect +# output +# untracked +EOF +test_expect_success 'commit --dry-run submodule summary (--amend)' ' + git config status.submodulesummary 10 && + git commit --dry-run --amend >output && + test_cmp expect output +' + +test_expect_success POSIXPERM '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) +' + +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) +# +# 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=untracked suppresses submodules with untracked content' ' + echo modified > sm/untracked && + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' ' + git status --ignore-submodules=dirty > output && + test_cmp expect output +' + +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 +' + +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) +# (commit or discard the untracked or modified content in submodules) +# +# modified: dir1/modified +# modified: sm (modified content) +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# 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=untracked doesn't suppress submodules with modified content" ' + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD) + +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 +# modified: sm (new commits) +# +# Submodules changed but not updated: +# +# * sm $head...$head2 (1): +# > 2nd commit +# +# Untracked files: +# (use "git add <file>..." to include in what will be committed) +# +# 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=untracked doesn't suppress submodule summary" ' + git status --ignore-submodules=untracked > output && + test_cmp expect output +' + +test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" ' + git status --ignore-submodules=dirty > output && + test_cmp expect output +' + +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) +# +# 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_done diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh new file mode 100755 index 0000000000..3ea33db6c7 --- /dev/null +++ b/t/t7509-commit.sh @@ -0,0 +1,160 @@ +#!/bin/sh +# +# Copyright (c) 2009 Erick Mattos +# + +test_description='git commit --reset-author' + +. ./test-lib.sh + +author_header () { + git cat-file commit "$1" | + sed -n -e '/^$/q' -e '/^author /p' +} + +message_body () { + git cat-file commit "$1" | + sed -e '1,/^$/d' +} + +test_expect_success '-C option copies authorship and message' ' + echo "Initial" >foo && + git add foo && + test_tick && + git commit -m "Initial Commit" --author Frigate\ \<flying@over.world\> && + git tag Initial && + echo "Test 1" >>foo && + test_tick && + git commit -a -C Initial && + author_header Initial >expect && + author_header HEAD >actual && + test_cmp expect actual && + + message_body Initial >expect && + message_body HEAD >actual && + test_cmp expect actual +' + +test_expect_success '-C option copies only the message with --reset-author' ' + echo "Test 2" >>foo && + test_tick && + git commit -a -C Initial --reset-author && + echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect && + author_header HEAD >actual + test_cmp expect actual && + + message_body Initial >expect && + message_body HEAD >actual && + test_cmp expect actual +' + +test_expect_success '-c option copies authorship and message' ' + echo "Test 3" >>foo && + test_tick && + EDITOR=: VISUAL=: git commit -a -c Initial && + author_header Initial >expect && + author_header HEAD >actual && + test_cmp expect actual +' + +test_expect_success '-c option copies only the message with --reset-author' ' + echo "Test 4" >>foo && + test_tick && + EDITOR=: VISUAL=: git commit -a -c Initial --reset-author && + echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect && + author_header HEAD >actual && + test_cmp expect actual && + + message_body Initial >expect && + message_body HEAD >actual && + test_cmp expect actual +' + +test_expect_success '--amend option copies authorship' ' + git checkout Initial && + echo "Test 5" >>foo && + test_tick && + git commit -a --amend -m "amend test" && + author_header Initial >expect && + author_header HEAD >actual && + + echo "amend test" >expect && + message_body HEAD >actual && + 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 && + ! 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 && + ! 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 && + test_tick && + git commit -a --reset-author -m "Changed again" --amend && + echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect && + author_header HEAD >actual && + test_cmp expect actual && + + echo "Changed again" >expect && + message_body HEAD >actual && + test_cmp expect actual +' + +test_expect_success '--reset-author and --author are mutually exclusive' ' + git checkout Initial && + echo "Test 7" >>foo && + test_tick && + test_must_fail git commit -a --reset-author --author="Xyzzy <frotz@nitfol.xz>" +' + +test_expect_success '--reset-author should be rejected without -c/-C/--amend' ' + git checkout Initial && + echo "Test 7" >>foo && + test_tick && + test_must_fail git commit -a --reset-author -m done +' + +test_done diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh new file mode 100755 index 0000000000..cde8390c1b --- /dev/null +++ b/t/t7600-merge.sh @@ -0,0 +1,603 @@ +#!/bin/sh +# +# Copyright (c) 2007 Lars Hjemli +# + +test_description='git merge + +Testing basic merge operations/option parsing.' + +. ./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)" + then + echo "[OOPS] HEAD^$i != $1" + return 1 + 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" + return 1 + fi + i=$(expr $i + 1) + shift + done +} + +verify_no_mergehead() { + if test -f .git/MERGE_HEAD + then + echo "[OOPS] MERGE_HEAD exists" + false + fi +} + + +test_expect_success 'setup' ' + git add file && + test_tick && + git commit -m "commit 0" && + git tag c0 && + c0=$(git rev-parse HEAD) && + cp file.1 file && + git add file && + test_tick && + git commit -m "commit 1" && + git tag c1 && + c1=$(git rev-parse HEAD) && + git reset --hard "$c0" && + cp file.5 file && + git add file && + test_tick && + git commit -m "commit 2" && + git tag c2 && + c2=$(git rev-parse HEAD) && + git reset --hard "$c0" && + cp file.9 file && + git add file && + test_tick && + git commit -m "commit 3" && + git tag c3 && + c3=$(git rev-parse HEAD) + git reset --hard "$c0" && + create_merge_msgs +' + +test_debug 'gitk --all' + +test_expect_success 'test option parsing' ' + test_must_fail git merge -$ c1 && + test_must_fail git merge --no-such c1 && + test_must_fail git merge -s foobar c1 && + test_must_fail git merge -s=foobar c1 && + test_must_fail git merge -m && + test_must_fail git merge +' + +test_expect_success 'reject non-strategy with a git-merge-foo name' ' + test_must_fail git merge -s index c1 +' + +test_expect_success 'merge c0 with c1' ' + git reset --hard c0 && + git merge c1 && + verify_merge file result.1 && + verify_head "$c1" +' + +test_debug 'gitk --all' + +test_expect_success 'merge c0 with c1 with --ff-only' ' + git reset --hard c0 && + git merge --ff-only c1 && + git merge --ff-only HEAD c0 c1 && + verify_merge file result.1 && + verify_head "$c1" +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2' ' + git reset --hard c1 && + test_tick && + git merge c2 && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 and c3' ' + git reset --hard c1 && + test_tick && + git merge c2 c3 && + verify_merge file result.1-5-9 msg.1-5-9 && + verify_parents $c1 $c2 $c3 +' + +test_debug 'gitk --all' + +test_expect_success 'failing merges with --ff-only' ' + git reset --hard c1 && + test_tick && + test_must_fail git merge --ff-only c2 && + test_must_fail git merge --ff-only c3 && + test_must_fail git merge --ff-only c2 c3 +' + +test_expect_success 'merge c0 with c1 (no-commit)' ' + git reset --hard c0 && + git merge --no-commit c1 && + verify_merge file result.1 && + verify_head $c1 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (no-commit)' ' + git reset --hard c1 && + git merge --no-commit c2 && + verify_merge file result.1-5 && + verify_head $c1 && + verify_mergeheads $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 and c3 (no-commit)' ' + git reset --hard c1 && + git merge --no-commit c2 c3 && + verify_merge file result.1-5-9 && + verify_head $c1 && + verify_mergeheads $c2 $c3 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c0 with c1 (squash)' ' + git reset --hard c0 && + git merge --squash c1 && + verify_merge file result.1 && + verify_head $c0 && + verify_no_mergehead && + verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message" +' + +test_debug 'gitk --all' + +test_expect_success 'merge c0 with c1 (squash, ff-only)' ' + git reset --hard c0 && + git merge --squash --ff-only c1 && + verify_merge file result.1 && + verify_head $c0 && + verify_no_mergehead && + verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message" +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (squash)' ' + git reset --hard c1 && + git merge --squash c2 && + 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_debug 'gitk --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_expect_success 'merge c1 with c2 and c3 (squash)' ' + git reset --hard c1 && + git merge --squash c2 c3 && + 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_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (no-commit in config)' ' + git reset --hard c1 && + git config branch.master.mergeoptions "--no-commit" && + git merge c2 && + verify_merge file result.1-5 && + verify_head $c1 && + verify_mergeheads $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (squash in config)' ' + git reset --hard c1 && + git config branch.master.mergeoptions "--squash" && + git merge c2 && + 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_debug 'gitk --all' + +test_expect_success 'override config option -n with --summary' ' + git reset --hard c1 && + git config branch.master.mergeoptions "-n" && + test_tick && + git merge --summary c2 >diffstat.txt && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 && + if ! grep "^ file | *2 +-$" diffstat.txt + then + echo "[OOPS] diffstat was not generated with --summary" + false + fi +' + +test_expect_success 'override config option -n with --stat' ' + git reset --hard c1 && + git config branch.master.mergeoptions "-n" && + test_tick && + git merge --stat c2 >diffstat.txt && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 && + if ! grep "^ file | *2 +-$" diffstat.txt + then + echo "[OOPS] diffstat was not generated with --stat" + false + fi +' + +test_debug 'gitk --all' + +test_expect_success 'override config option --stat' ' + git reset --hard c1 && + git config branch.master.mergeoptions "--stat" && + test_tick && + git merge -n c2 >diffstat.txt && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 && + if grep "^ file | *2 +-$" diffstat.txt + then + echo "[OOPS] diffstat was generated" + false + fi +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (override --no-commit)' ' + git reset --hard c1 && + git config branch.master.mergeoptions "--no-commit" && + test_tick && + git merge --commit c2 && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c2 (override --squash)' ' + git reset --hard c1 && + git config branch.master.mergeoptions "--squash" && + test_tick && + git merge --no-squash c2 && + verify_merge file result.1-5 msg.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c0 with c1 (no-ff)' ' + git reset --hard c0 && + git config branch.master.mergeoptions "" && + test_tick && + git merge --no-ff c1 && + verify_merge file result.1 && + verify_parents $c0 $c1 +' + +test_debug 'gitk --all' + +test_expect_success 'combining --squash and --no-ff is refused' ' + test_must_fail git merge --squash --no-ff c1 && + test_must_fail git merge --no-ff --squash c1 +' + +test_expect_success 'combining --ff-only and --no-ff is refused' ' + test_must_fail git merge --ff-only --no-ff c1 && + test_must_fail git merge --no-ff --ff-only c1 +' + +test_expect_success 'merge c0 with c1 (ff overrides no-ff)' ' + git reset --hard c0 && + git config branch.master.mergeoptions "--no-ff" && + git merge --ff c1 && + verify_merge file result.1 && + verify_head $c1 +' + +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" && + + git merge --log c3 && + git show -s --pretty=format:%b HEAD >msg.act && + verify_diff msg.log msg.act "[OOPS] bad merge log message" && + + 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_debug 'gitk --all' + +test_expect_success 'merge c1 with c0, c2, c0, and c1' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + git merge c0 c2 c0 c1 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c0, c2, c0, and c1' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + git merge c0 c2 c0 c1 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge c1 with c1 and c2' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + git merge c1 c2 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 +' + +test_debug 'gitk --all' + +test_expect_success 'merge fast-forward in a dirty tree' ' + git reset --hard c0 && + mv file file1 && + cat file1 >file && + rm -f file1 && + git merge c2 +' + +test_debug 'gitk --all' + +test_expect_success 'in-index merge' ' + git reset --hard c0 && + git merge --no-ff -s resolve c1 > out && + grep "Wonderful." out && + verify_parents $c0 $c1 +' + +test_debug 'gitk --all' + +test_expect_success 'refresh the index before merging' ' + git reset --hard c1 && + cp file file.n && mv -f file.n file && + git merge c3 +' + +cat >expected <<EOF +Merge branch 'c5' (early part) +EOF + +test_expect_success 'merge early part of c2' ' + git reset --hard c3 && + echo c4 > c4.c && + git add c4.c && + git commit -m c4 && + git tag c4 && + echo c5 > c5.c && + git add c5.c && + git commit -m c5 && + git tag c5 && + git reset --hard c3 && + echo c6 > c6.c && + git add c6.c && + git commit -m c6 && + git tag c6 && + git merge c5~1 && + git show -s --pretty=format:%s HEAD > actual && + test_cmp actual expected +' + +test_debug 'gitk --all' + +test_expect_success 'merge --no-ff --no-commit && commit' ' + git reset --hard c0 && + git merge --no-ff --no-commit c1 && + EDITOR=: git commit && + verify_parents $c0 $c1 +' + +test_debug 'gitk --all' + +test_expect_success 'amending no-ff merge commit' ' + EDITOR=: git commit --amend && + verify_parents $c0 $c1 +' + +test_debug 'gitk --all' + +test_done diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh new file mode 100755 index 0000000000..7ba94ea99b --- /dev/null +++ b/t/t7601-merge-pull-config.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +test_description='git merge + +Testing pull.* configuration parsing.' + +. ./test-lib.sh + +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 && + echo c2 >c2.c && + git add c2.c && + git commit -m c2 && + git tag c2 && + git reset --hard c0 && + echo c3 >c3.c && + git add c3.c && + git commit -m c3 && + git tag c3 +' + +test_expect_success 'merge c1 with c2' ' + git reset --hard c1 && + test -f c0.c && + test -f c1.c && + test ! -f c2.c && + test ! -f c3.c && + git merge c2 && + test -f c1.c && + test -f c2.c +' + +test_expect_success 'merge c1 with c2 (ours in pull.twohead)' ' + git reset --hard c1 && + git config pull.twohead ours && + git merge c2 && + test -f c1.c && + ! test -f c2.c +' + +test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' ' + git reset --hard c1 && + git config pull.octopus "recursive" && + test_must_fail git merge c2 c3 && + test "$(git rev-parse c1)" = "$(git rev-parse HEAD)" +' + +test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octopus)' ' + git reset --hard c1 && + git config pull.octopus "recursive octopus" && + git merge c2 c3 && + test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && + test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" && + test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" && + test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && + git diff --exit-code && + test -f c0.c && + test -f c1.c && + test -f c2.c && + test -f c3.c +' + +conflict_count() +{ + { + git diff-files --name-only + git ls-files --unmerged + } | wc -l +} + +# c4 - c5 +# \ c6 +# +# There are two conflicts here: +# +# 1) Because foo.c is renamed to bar.c, recursive will handle this, +# resolve won't. +# +# 2) One in conflict.c and that will always fail. + +test_expect_success 'setup conflicted merge' ' + git reset --hard c0 && + echo A >conflict.c && + git add conflict.c && + echo contents >foo.c && + git add foo.c && + git commit -m c4 && + git tag c4 && + echo B >conflict.c && + git add conflict.c && + git mv foo.c bar.c && + git commit -m c5 && + git tag c5 && + git reset --hard c4 && + echo C >conflict.c && + git add conflict.c && + echo secondline >> foo.c && + git add foo.c && + git commit -m c6 && + git tag c6 +' + +# First do the merge with resolve and recursive then verify that +# recusive is choosen. + +test_expect_success 'merge picks up the best result' ' + git config --unset-all pull.twohead && + git reset --hard c5 && + git merge -s resolve c6 + resolve_count=$(conflict_count) && + git reset --hard c5 && + git merge -s recursive c6 + recursive_count=$(conflict_count) && + git reset --hard c5 && + git merge -s recursive -s resolve c6 + auto_count=$(conflict_count) && + test $auto_count = $recursive_count && + test $auto_count != $resolve_count +' + +test_expect_success 'merge picks up the best result (from config)' ' + git config pull.twohead "recursive resolve" && + git reset --hard c5 && + git merge -s resolve c6 + resolve_count=$(conflict_count) && + git reset --hard c5 && + git merge -s recursive c6 + recursive_count=$(conflict_count) && + git reset --hard c5 && + git merge c6 + auto_count=$(conflict_count) && + test $auto_count = $recursive_count && + test $auto_count != $resolve_count +' + +test_expect_success 'merge errors out on invalid strategy' ' + git config pull.twohead "foobar" && + git reset --hard c5 && + test_must_fail git merge c6 +' + +test_expect_success 'merge errors out on invalid strategy' ' + git config --unset-all pull.twohead && + git reset --hard c5 && + test_must_fail git merge -s "resolve recursive" c6 +' + +test_done diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh new file mode 100755 index 0000000000..2746169514 --- /dev/null +++ b/t/t7602-merge-octopus-many.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='git merge + +Testing octopus merge with more than 25 refs.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo c0 > c0.c && + git add c0.c && + git commit -m c0 && + git tag c0 && + i=1 && + while test $i -le 30 + do + git reset --hard c0 && + echo c$i > c$i.c && + git add c$i.c && + git commit -m c$i && + git tag c$i && + i=`expr $i + 1` || return 1 + done +' + +test_expect_success 'merge c1 with c2, c3, c4, ... c29' ' + git reset --hard c1 && + i=2 && + refs="" && + while test $i -le 30 + do + refs="$refs c$i" + i=`expr $i + 1` + done + git merge $refs && + test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && + i=1 && + while test $i -le 30 + do + test "$(git rev-parse c$i)" = "$(git rev-parse HEAD^$i)" && + i=`expr $i + 1` || return 1 + done && + git diff --exit-code && + i=1 && + while test $i -le 30 + do + test -f c$i.c && + i=`expr $i + 1` || return 1 + done +' + +cat >expected <<\EOF +Trying simple merge with c2 +Trying simple merge with c3 +Trying simple merge with c4 +Merge made by octopus. + c2.c | 1 + + c3.c | 1 + + c4.c | 1 + + 3 files changed, 3 insertions(+), 0 deletions(-) + create mode 100644 c2.c + create mode 100644 c3.c + create mode 100644 c4.c +EOF + +test_expect_success 'merge output uses pretty names' ' + git reset --hard c1 && + git merge c2 c3 c4 >actual && + test_cmp actual expected +' + +cat >expected <<\EOF +Already up-to-date with c4 +Trying simple merge with c5 +Merge made by octopus. + c5.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + create mode 100644 c5.c +EOF + +test_expect_success 'merge up-to-date output uses pretty names' ' + git merge c4 c5 >actual && + test_cmp actual expected +' + +cat >expected <<\EOF +Fast-forwarding to: c1 +Trying simple merge with c2 +Merge made by octopus. + c1.c | 1 + + c2.c | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + create mode 100644 c1.c + create mode 100644 c2.c +EOF + +test_expect_success 'merge fast-forward output uses pretty names' ' + git reset --hard c0 && + git merge c1 c2 >actual && + test_cmp actual expected +' + +test_done diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh new file mode 100755 index 0000000000..7e17eb490d --- /dev/null +++ b/t/t7603-merge-reduce-heads.sh @@ -0,0 +1,116 @@ +#!/bin/sh + +test_description='git merge + +Testing octopus merge when reducing parents to independent branches.' + +. ./test-lib.sh + +# 0 - 1 +# \ 2 +# \ 3 +# \ 4 - 5 +# +# So 1, 2, 3 and 5 should be kept, 4 should be avoided. + +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 && + echo c2 > c2.c && + git add c2.c && + git commit -m c2 && + git tag c2 && + git reset --hard c0 && + echo c3 > c3.c && + git add c3.c && + git commit -m c3 && + git tag c3 && + git reset --hard c0 && + echo c4 > c4.c && + git add c4.c && + git commit -m c4 && + git tag c4 && + echo c5 > c5.c && + git add c5.c && + git commit -m c5 && + git tag c5 +' + +test_expect_success 'merge c1 with c2, c3, c4, c5' ' + git reset --hard c1 && + git merge c2 c3 c4 c5 && + test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" && + test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" && + test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" && + test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && + test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" && + git diff --exit-code && + test -f c0.c && + test -f c1.c && + test -f c2.c && + test -f c3.c && + test -f c4.c && + test -f c5.c +' + +test_expect_success 'setup' ' + for i in A B C D E + do + echo $i > $i.c && + git add $i.c && + git commit -m $i && + git tag $i + done && + git reset --hard A && + for i in F G H I + do + echo $i > $i.c && + git add $i.c && + git commit -m $i && + git tag $i + done +' + +test_expect_success 'merge E and I' ' + git reset --hard A && + git merge E I +' + +test_expect_success 'verify merge result' ' + test $(git rev-parse HEAD^1) = $(git rev-parse E) && + test $(git rev-parse HEAD^2) = $(git rev-parse I) +' + +test_expect_success 'add conflicts' ' + git reset --hard E && + echo foo > file.c && + git add file.c && + git commit -m E2 && + git tag E2 && + git reset --hard I && + echo bar >file.c && + git add file.c && + git commit -m I2 && + git tag I2 +' + +test_expect_success 'merge E2 and I2, causing a conflict and resolve it' ' + git reset --hard A && + test_must_fail git merge E2 I2 && + echo baz > file.c && + git add file.c && + git commit -m "resolve conflict" +' + +test_expect_success 'verify merge result' ' + test $(git rev-parse HEAD^1) = $(git rev-parse E2) && + test $(git rev-parse HEAD^2) = $(git rev-parse I2) +' +test_done diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh new file mode 100755 index 0000000000..9114785ef7 --- /dev/null +++ b/t/t7604-merge-custom-message.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='git merge + +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 && + 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 && + echo c2 > c2.c && + git add c2.c && + git commit -m c2 && + git tag c2 && + create_merge_msgs +' + + +test_expect_success 'merge c2 with a custom message' ' + git reset --hard c1 && + 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 exp.log actual +' + +test_done diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh new file mode 100755 index 0000000000..0cb9d11f21 --- /dev/null +++ b/t/t7605-merge-resolve.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +test_description='git merge + +Testing the resolve strategy.' + +. ./test-lib.sh + +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 && + echo c2 > c2.c && + git add c2.c && + git commit -m c2 && + git tag c2 && + git reset --hard c0 && + echo c3 > c2.c && + git add c2.c && + git commit -m c3 && + git tag c3 +' + +test_expect_success 'merge c1 to c2' ' + git reset --hard c1 && + git merge -s resolve 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)" && + git diff --exit-code && + test -f c0.c && + test -f c1.c && + test -f c2.c && + test 3 = $(git ls-tree -r HEAD | wc -l) && + test 3 = $(git ls-files | wc -l) +' + +test_expect_success 'merge c2 to c3 (fails)' ' + git reset --hard c2 && + test_must_fail git merge -s resolve c3 +' +test_done diff --git a/t/t7606-merge-custom.sh b/t/t7606-merge-custom.sh new file mode 100755 index 0000000000..52a451dd57 --- /dev/null +++ b/t/t7606-merge-custom.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='git merge + +Testing a custom strategy.' + +. ./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 '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 && + echo c1c1 >c1.c && + echo c2 >c2.c && + git add c1.c c2.c && + git commit -m c2 && + git tag c2 +' + +test_expect_success 'merge c2 with a custom strategy' ' + git reset --hard c1 && + 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 diff --exit-code && + git diff --exit-code c2 HEAD && + git diff --exit-code c2 && + test -f c0.c && + grep c1c1 c1.c && + test -f c2.c +' + +test_done diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh new file mode 100755 index 0000000000..49f4e1599a --- /dev/null +++ b/t/t7607-merge-overwrite.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='git-merge + +Do not overwrite changes.' + +. ./test-lib.sh + +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 && + echo c2 > c2.c && + git add c2.c && + git commit -m c2 && + git tag c2 && + git reset --hard c1 && + echo "c1 a" > c1.c && + git add c1.c && + git commit -m "c1 a" && + git tag c1a && + echo "VERY IMPORTANT CHANGES" > important +' + +test_expect_success 'will not overwrite untracked file' ' + git reset --hard c1 && + cat important > c2.c && + ! git merge c2 && + test_cmp important c2.c +' + +test_expect_success 'will not overwrite new file' ' + git reset --hard c1 && + cat important > c2.c && + git add c2.c && + ! git merge c2 && + test_cmp important c2.c +' + +test_expect_success 'will not overwrite staged changes' ' + git reset --hard c1 && + cat important > c2.c && + git add c2.c && + rm c2.c && + ! git merge c2 && + git checkout c2.c && + test_cmp important c2.c +' + +test_expect_success 'will not overwrite removed file' ' + git reset --hard c1 && + git rm c1.c && + git commit -m "rm c1.c" && + cat important > c1.c && + ! git merge c1a && + test_cmp important c1.c +' + +test_expect_success 'will not overwrite re-added file' ' + git reset --hard c1 && + git rm c1.c && + git commit -m "rm c1.c" && + cat important > c1.c && + git add c1.c && + ! git merge c1a && + test_cmp important c1.c +' + +test_expect_success 'will not overwrite removed file with staged changes' ' + git reset --hard c1 && + git rm c1.c && + git commit -m "rm c1.c" && + cat important > c1.c && + git add c1.c && + rm c1.c && + ! git merge c1a && + git checkout c1.c && + test_cmp important c1.c +' + +test_done diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh new file mode 100755 index 0000000000..28d56797b1 --- /dev/null +++ b/t/t7608-merge-messages.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='test auto-generated merge messages' +. ./test-lib.sh + +check_oneline() { + echo "$1" | sed "s/Q/'/g" >expect && + git log -1 --pretty=tformat:%s >actual && + test_cmp expect actual +} + +test_expect_success 'merge local branch' ' + test_commit master-1 && + git checkout -b local-branch && + test_commit branch-1 && + git checkout master && + test_commit master-2 && + git merge local-branch && + check_oneline "Merge branch Qlocal-branchQ" +' + +test_expect_success 'merge octopus branches' ' + git checkout -b octopus-a master && + test_commit octopus-1 && + git checkout -b octopus-b master && + test_commit octopus-2 && + git checkout master && + git merge octopus-a octopus-b && + check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ" +' + +test_expect_success 'merge tag' ' + git checkout -b tag-branch master && + test_commit tag-1 && + git checkout master && + test_commit master-3 && + git merge tag-1 && + check_oneline "Merge commit Qtag-1Q" +' + +test_expect_success 'ambiguous tag' ' + git checkout -b ambiguous master && + test_commit ambiguous && + git checkout master && + test_commit master-4 && + git merge ambiguous && + check_oneline "Merge commit QambiguousQ" +' + +test_expect_success 'remote branch' ' + git checkout -b remote master && + test_commit remote-1 && + git update-ref refs/remotes/origin/master remote && + git checkout master && + test_commit master-5 && + git merge origin/master && + check_oneline "Merge remote branch Qorigin/masterQ" +' + +test_done diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh new file mode 100755 index 0000000000..e768c3eb2d --- /dev/null +++ b/t/t7610-mergetool.sh @@ -0,0 +1,89 @@ +#!/bin/sh +# +# Copyright (c) 2008 Charles Bailey +# + +test_description='git mergetool + +Testing basic merge tool invocation' + +. ./test-lib.sh + +# All the mergetool test work by checking out a temporary branch based +# off 'branch1' and then merging in master and checking the results of +# running mergetool + +test_expect_success 'setup' ' + echo master >file1 && + mkdir subdir && + echo master sub >subdir/file3 && + git add file1 subdir/file3 && + git commit -m "added file1" && + + git checkout -b branch1 master && + echo branch1 change >file1 && + echo branch1 newfile >file2 && + echo branch1 sub >subdir/file3 && + git add file1 file2 subdir/file3 && + git commit -m "branch1 changes" && + + git checkout master && + echo master updated >file1 && + echo master new >file2 && + echo master new sub >subdir/file3 && + git add file1 file2 subdir/file3 && + git commit -m "master updates" && + + git config merge.tool mytool && + git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" && + git config mergetool.mytool.trustExitCode true +' + +test_expect_success 'custom mergetool' ' + git checkout -b test1 branch1 && + test_must_fail git merge master >/dev/null 2>&1 && + ( yes "" | git mergetool file1 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file2 >/dev/null 2>&1 ) && + ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && + test "$(cat file1)" = "master updated" && + test "$(cat file2)" = "master new" && + test "$(cat subdir/file3)" = "master new sub" && + git commit -m "branch1 resolved with mergetool" +' + +test_expect_success 'mergetool crlf' ' + git config core.autocrlf true && + git checkout -b test2 branch1 + test_must_fail git merge master >/dev/null 2>&1 && + ( yes "" | git mergetool file1 >/dev/null 2>&1 ) && + ( yes "" | git mergetool file2 >/dev/null 2>&1 ) && + ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && + test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" && + test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" && + test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" && + git commit -m "branch1 resolved with mergetool - autocrlf" && + git config core.autocrlf false && + git reset --hard +' + +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" ) +' + +# 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_done diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh new file mode 100755 index 0000000000..c2f66ff170 --- /dev/null +++ b/t/t7700-repack.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +test_description='git repack works correctly' + +. ./test-lib.sh + +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 + git rev-list --objects --all | grep -v file2 | + git pack-objects pack > /dev/null && + # The second pack will contain the excluded object + packsha1=$(git rev-list --objects --all | grep file2 | + git pack-objects pack) && + touch -r pack-$packsha1.pack pack-$packsha1.keep && + objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 | + sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") && + mv pack-* .git/objects/pack/ && + git repack -A -d -l && + git prune-packed && + for p in .git/objects/pack/*.idx; do + idx=$(basename $p) + test "pack-$packsha1.idx" = "$idx" && continue + if git verify-pack -v $p | egrep "^$objsha1"; then + found_duplicate_object=1 + echo "DUPLICATE OBJECT FOUND" + break + fi + done && + test -z "$found_duplicate_object" +' + +test_expect_success 'loose objects in alternate ODB are not repacked' ' + mkdir alt_objects && + echo `pwd`/alt_objects > .git/objects/info/alternates && + 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 && + for p in .git/objects/pack/*.idx; do + if git verify-pack -v $p | egrep "^$objsha1"; then + found_duplicate_object=1 + echo "DUPLICATE OBJECT FOUND" + break + fi + done && + test -z "$found_duplicate_object" +' + +test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' ' + mkdir alt_objects/pack + mv .git/objects/pack/* alt_objects/pack && + git repack -a && + myidx=$(ls -1 .git/objects/pack/*.idx) && + test -f "$myidx" && + for p in alt_objects/pack/*.idx; do + git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p" + done | while read sha1 rest; do + if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then + echo "Missing object in local pack: $sha1" + return 1 + fi + done +' + +test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' ' + 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 && + myidx=$(ls -1 .git/objects/pack/*.idx) && + test -f "$myidx" && + for p in alt_objects/pack/*.idx; do + git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p" + done | while read sha1 rest; do + if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then + echo "Missing object in local pack: $sha1" + return 1 + fi + done +' + +test_expect_success 'packed obs in alternate ODB kept pack are repacked' ' + # swap the .keep so the commit object is in the pack with .keep + for p in alt_objects/pack/*.pack + do + base_name=$(basename $p .pack) + if test -f alt_objects/pack/$base_name.keep + then + rm alt_objects/pack/$base_name.keep + else + touch alt_objects/pack/$base_name.keep + fi + done + git repack -a -d && + myidx=$(ls -1 .git/objects/pack/*.idx) && + test -f "$myidx" && + for p in alt_objects/pack/*.idx; do + git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p" + done | while read sha1 rest; do + if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then + echo "Missing object in local pack: $sha1" + return 1 + fi + done +' + +test_expect_success 'packed unreachable obs in alternate ODB are not loosened' ' + rm -f alt_objects/pack/*.keep && + mv .git/objects/pack/* alt_objects/pack/ && + csha1=$(git rev-parse HEAD^{commit}) && + git reset --hard HEAD^ && + 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 \ + --unpack-unreachable </dev/null pack && + rm -f .git/objects/pack/* && + mv pack-* .git/objects/pack/ && + test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx | + egrep "^$csha1 " | sort | uniq | wc -l) && + echo > .git/objects/info/alternates && + test_must_fail git show $csha1 +' + +test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' ' + echo `pwd`/alt_objects > .git/objects/info/alternates && + echo "$csha1" | git pack-objects --non-empty --all --reflog pack && + rm -f .git/objects/pack/* && + mv pack-* .git/objects/pack/ && + # 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 \ + --unpack-unreachable </dev/null pack && + rm -f .git/objects/pack/* && + mv pack-* .git/objects/pack/ && + test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx | + egrep "^$csha1 " | sort | uniq | wc -l) && + echo > .git/objects/info/alternates && + test_must_fail git show $csha1 +' + +test_expect_success 'objects made unreachable by grafts only are kept' ' + test_tick && + git commit --allow-empty -m "commit 4" && + H0=$(git rev-parse HEAD) && + H1=$(git rev-parse HEAD^) && + H2=$(git rev-parse HEAD^^) && + echo "$H0 $H2" > .git/info/grafts && + git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all && + git repack -a -d && + git cat-file -t $H1 + ' + +test_done + diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh new file mode 100755 index 0000000000..200ab61278 --- /dev/null +++ b/t/t7701-repack-unpack-unreachable.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='git repack works correctly' + +. ./test-lib.sh + +fsha1= +csha1= +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 && + # pack the repo + git repack -A -d -l && + # verify objects are packed in repository + test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx | + egrep "^($fsha1|$csha1|$tsha1) " | + sort | uniq | wc -l) && + git show $fsha1 && + git show $csha1 && + git show $tsha1 && + # 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 + test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx | + egrep "^($fsha1|$csha1|$tsha1) " | + sort | uniq | wc -l) && + git show $fsha1 && + git show $csha1 && + git show $tsha1 +' + +compare_mtimes () +{ + read tref rest && + while read t rest; do + test "$tref" = "$t" || break + done +} + +test_expect_success '-A without -d option leaves unreachable objects packed' ' + fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") && + fsha1path=".git/objects/$fsha1path" && + csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") && + csha1path=".git/objects/$csha1path" && + tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") && + tsha1path=".git/objects/$tsha1path" && + git branch transient_branch $csha1 && + git repack -a -d -l && + test ! -f "$fsha1path" && + test ! -f "$csha1path" && + test ! -f "$tsha1path" && + test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) && + packfile=$(ls .git/objects/pack/pack-*.pack) && + git branch -D transient_branch && + test_tick && + git repack -A -l && + test ! -f "$fsha1path" && + test ! -f "$csha1path" && + test ! -f "$tsha1path" && + git show $fsha1 && + git show $csha1 && + git show $tsha1 +' + +test_expect_success 'unpacked objects receive timestamp of pack file' ' + tmppack=".git/objects/pack/tmp_pack" && + ln "$packfile" "$tmppack" && + git repack -A -l -d && + test-chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \ + > mtimes && + compare_mtimes < mtimes +' + +test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh new file mode 100755 index 0000000000..196827e7ea --- /dev/null +++ b/t/t7800-difftool.sh @@ -0,0 +1,276 @@ +#!/bin/sh +# +# Copyright (c) 2009, 2010 David Aguilar +# + +test_description='git-difftool + +Testing basic diff tool invocation +' + +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping difftool tests, perl not available' + test_done +fi + +LF=' +' + +remove_config_vars() +{ + # Unset all config variables used by git-difftool + git config --unset diff.tool + git config --unset diff.guitool + git config --unset difftool.test-tool.cmd + git config --unset difftool.prompt + git config --unset merge.tool + git config --unset mergetool.test-tool.cmd + git config --unset mergetool.prompt + return 0 +} + +restore_test_defaults() +{ + # Restores the test defaults used by several tests + remove_config_vars + unset GIT_DIFF_TOOL + unset GIT_DIFFTOOL_PROMPT + unset GIT_DIFFTOOL_NO_PROMPT + git config diff.tool test-tool && + git config difftool.test-tool.cmd 'cat $LOCAL' + git config difftool.bogus-tool.cmd false +} + +prompt_given() +{ + prompt="$1" + test "$prompt" = "Hit return to launch 'test-tool': branch" +} + +# Create a file on master and change it on branch +test_expect_success 'setup' ' + echo master >file && + git add file && + git commit -m "added file" && + + git checkout -b branch master && + echo branch >file && + git commit -a -m "branch changed file" && + git checkout master +' + +# Configure a custom difftool.<tool>.cmd and use it +test_expect_success 'custom commands' ' + restore_test_defaults && + git config difftool.test-tool.cmd "cat \$REMOTE" && + + diff=$(git difftool --no-prompt branch) && + test "$diff" = "master" && + + restore_test_defaults && + diff=$(git difftool --no-prompt branch) && + test "$diff" = "branch" +' + +# Ensures that git-difftool ignores bogus --tool values +test_expect_success 'difftool ignores bad --tool values' ' + diff=$(git difftool --no-prompt --tool=bad-tool branch) + test "$?" = 1 && + test "$diff" = "" +' + +test_expect_success 'difftool honors --gui' ' + git config merge.tool bogus-tool && + git config diff.tool bogus-tool && + git config diff.guitool test-tool && + + diff=$(git difftool --no-prompt --gui branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +test_expect_success 'difftool --gui works without configured diff.guitool' ' + git config diff.tool test-tool && + + diff=$(git difftool --no-prompt --gui branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# Specify the diff tool using $GIT_DIFF_TOOL +test_expect_success 'GIT_DIFF_TOOL variable' ' + git config --unset diff.tool + GIT_DIFF_TOOL=test-tool && + export GIT_DIFF_TOOL && + + diff=$(git difftool --no-prompt branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# Test the $GIT_*_TOOL variables and ensure +# that $GIT_DIFF_TOOL always wins unless --tool is specified +test_expect_success 'GIT_DIFF_TOOL overrides' ' + git config diff.tool bogus-tool && + git config merge.tool bogus-tool && + + GIT_DIFF_TOOL=test-tool && + export GIT_DIFF_TOOL && + + diff=$(git difftool --no-prompt branch) && + test "$diff" = "branch" && + + GIT_DIFF_TOOL=bogus-tool && + export GIT_DIFF_TOOL && + + diff=$(git difftool --no-prompt --tool=test-tool branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# 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' ' + GIT_DIFFTOOL_NO_PROMPT=true && + export GIT_DIFFTOOL_NO_PROMPT && + + diff=$(git difftool branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# git-difftool supports the difftool.prompt variable. +# Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false +test_expect_success 'GIT_DIFFTOOL_PROMPT variable' ' + git config difftool.prompt false && + GIT_DIFFTOOL_PROMPT=true && + export GIT_DIFFTOOL_PROMPT && + + prompt=$(echo | git difftool branch | tail -1) && + prompt_given "$prompt" && + + restore_test_defaults +' + +# Test that we don't have to pass --no-prompt when difftool.prompt is false +test_expect_success 'difftool.prompt config variable is false' ' + git config difftool.prompt false && + + diff=$(git difftool branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# Test that we don't have to pass --no-prompt when mergetool.prompt is false +test_expect_success 'difftool merge.prompt = false' ' + git config --unset difftool.prompt + git config mergetool.prompt false && + + diff=$(git difftool branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# Test that the -y flag can override difftool.prompt = true +test_expect_success 'difftool.prompt can overridden with -y' ' + git config difftool.prompt true && + + diff=$(git difftool -y branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +# Test that the --prompt flag can override difftool.prompt = false +test_expect_success 'difftool.prompt can overridden with --prompt' ' + git config difftool.prompt false && + + prompt=$(echo | git difftool --prompt branch | tail -1) && + prompt_given "$prompt" && + + restore_test_defaults +' + +# Test that the last flag passed on the command-line wins +test_expect_success 'difftool last flag wins' ' + diff=$(git difftool --prompt --no-prompt branch) && + test "$diff" = "branch" && + + restore_test_defaults && + + prompt=$(echo | git difftool --no-prompt --prompt branch | tail -1) && + prompt_given "$prompt" && + + restore_test_defaults +' + +# git-difftool falls back to git-mergetool config variables +# so test that behavior here +test_expect_success 'difftool + mergetool config variables' ' + remove_config_vars + git config merge.tool test-tool && + git config mergetool.test-tool.cmd "cat \$LOCAL" && + + diff=$(git difftool --no-prompt branch) && + test "$diff" = "branch" && + + # set merge.tool to something bogus, diff.tool to test-tool + git config merge.tool bogus-tool && + git config diff.tool test-tool && + + diff=$(git difftool --no-prompt branch) && + test "$diff" = "branch" && + + restore_test_defaults +' + +test_expect_success 'difftool.<tool>.path' ' + git config difftool.tkdiff.path echo && + diff=$(git difftool --tool=tkdiff --no-prompt branch) && + git config --unset difftool.tkdiff.path && + lines=$(echo "$diff" | grep file | wc -l) && + test "$lines" -eq 1 && + + restore_test_defaults +' + +test_expect_success 'difftool --extcmd=cat' ' + diff=$(git difftool --no-prompt --extcmd=cat branch) && + test "$diff" = branch"$LF"master +' + +test_expect_success 'difftool --extcmd cat' ' + diff=$(git difftool --no-prompt --extcmd cat branch) && + test "$diff" = branch"$LF"master +' + +test_expect_success 'difftool -x cat' ' + diff=$(git difftool --no-prompt -x cat branch) && + test "$diff" = branch"$LF"master +' + +test_expect_success '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' ' + diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch) + test "$diff" = master +' + +test_expect_success 'difftool --extcmd cat arg2' ' + diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch) + test "$diff" = branch +' + +test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh new file mode 100755 index 0000000000..8a6322765c --- /dev/null +++ b/t/t7810-grep.sh @@ -0,0 +1,530 @@ +#!/bin/sh +# +# Copyright (c) 2006 Junio C Hamano +# + +test_description='git grep various. +' + +. ./test-lib.sh + +cat >hello.c <<EOF +#include <stdio.h> +int main(int argc, const char **argv) +{ + printf("Hello world.\n"); + return 0; + /* char ?? */ +} +EOF + +test_expect_success setup ' + { + echo foo mmap bar + echo foo_mmap bar + echo foo_mmap bar mmap + echo foo mmap bar_mmap + echo foo_mmap bar mmap baz + } >file && + echo vvv >v && + echo ww w >w && + echo x x xx x >x && + echo y yy >y && + echo zzz > z && + mkdir t && + echo test >t/t && + echo vvv >t/v && + mkdir t/a && + echo vvv >t/a/v && + git add . && + test_tick && + git commit -m initial +' + +test_expect_success 'grep should not segfault with a bad input' ' + test_must_fail git grep "(" +' + +for H in HEAD '' +do + case "$H" in + HEAD) HC='HEAD:' L='HEAD' ;; + '') HC= L='in working tree' ;; + esac + + test_expect_success "grep -w $L" ' + { + echo ${HC}file:1:foo mmap bar + echo ${HC}file:3:foo_mmap bar mmap + echo ${HC}file:4:foo mmap bar_mmap + echo ${HC}file:5:foo_mmap bar mmap baz + } >expected && + git grep -n -w -e mmap $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L (w)" ' + : >expected && + ! git grep -n -w -e "^w" >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L (x)" ' + { + echo ${HC}x:1:x x xx x + } >expected && + git grep -n -w -e "x xx* x" $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L (y-1)" ' + { + echo ${HC}y:1:y yy + } >expected && + git grep -n -w -e "^y" $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep -w $L (y-2)" ' + : >expected && + if git grep -n -w -e "^y y" $H >actual + then + echo should not have matched + cat actual + false + else + test_cmp expected actual + fi + ' + + test_expect_success "grep -w $L (z)" ' + : >expected && + if git grep -n -w -e "^z" $H >actual + then + echo should not have matched + cat actual + false + else + 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 && + test_cmp expected actual + ' + + test_expect_success "grep $L (t-2)" ' + echo "${HC}t:1:test" >expected && + ( + cd t && + git grep -n -e test $H + ) >actual && + test_cmp expected actual + ' + + test_expect_success "grep $L (t-3)" ' + echo "${HC}t/t:1:test" >expected && + ( + cd t && + git grep --full-name -n -e test $H + ) >actual && + test_cmp expected actual + ' + + test_expect_success "grep -c $L (no /dev/null)" ' + ! git grep -c test $H | grep /dev/null + ' + + test_expect_success "grep --max-depth -1 $L" ' + { + echo ${HC}t/a/v:1:vvv + echo ${HC}t/v:1:vvv + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth -1 -n -e vvv $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep --max-depth 0 $L" ' + { + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth 0 -n -e vvv $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep --max-depth 0 -- '*' $L" ' + { + echo ${HC}t/a/v:1:vvv + echo ${HC}t/v:1:vvv + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth 0 -n -e vvv $H -- "*" >actual && + test_cmp expected actual + ' + + test_expect_success "grep --max-depth 1 $L" ' + { + echo ${HC}t/v:1:vvv + echo ${HC}v:1:vvv + } >expected && + git grep --max-depth 1 -n -e vvv $H >actual && + test_cmp expected actual + ' + + test_expect_success "grep --max-depth 0 -- t $L" ' + { + echo ${HC}t/v:1:vvv + } >expected && + git grep --max-depth 0 -n -e vvv $H -- t >actual && + test_cmp expected actual + ' + +done + +cat >expected <<EOF +file:foo mmap bar_mmap +EOF + +test_expect_success 'grep -e A --and -e B' ' + git grep -e "foo mmap" --and -e bar_mmap >actual && + test_cmp expected actual +' + +cat >expected <<EOF +file:foo_mmap bar mmap +file:foo_mmap bar mmap baz +EOF + + +test_expect_success 'grep ( -e A --or -e B ) --and -e B' ' + git grep \( -e foo_ --or -e baz \) \ + --and -e " mmap" >actual && + test_cmp expected actual +' + +cat >expected <<EOF +file:foo mmap bar +EOF + +test_expect_success 'grep -e A --and --not -e B' ' + git grep -e "foo mmap" --and --not -e bar_mmap >actual && + test_cmp expected actual +' + +test_expect_success 'grep should ignore GREP_OPTIONS' ' + GREP_OPTIONS=-v git grep " mmap bar\$" >actual && + test_cmp expected actual +' + +test_expect_success 'grep -f, non-existent file' ' + test_must_fail git grep -f patterns +' + +cat >expected <<EOF +file:foo mmap bar +file:foo_mmap bar +file:foo_mmap bar mmap +file:foo mmap bar_mmap +file:foo_mmap bar mmap baz +EOF + +cat >pattern <<EOF +mmap +EOF + +test_expect_success 'grep -f, one pattern' ' + git grep -f pattern >actual && + test_cmp expected actual +' + +cat >expected <<EOF +file:foo mmap bar +file:foo_mmap bar +file:foo_mmap bar mmap +file:foo mmap bar_mmap +file:foo_mmap bar mmap baz +t/a/v:vvv +t/v:vvv +v:vvv +EOF + +cat >patterns <<EOF +mmap +vvv +EOF + +test_expect_success 'grep -f, multiple patterns' ' + git grep -f patterns >actual && + test_cmp expected actual +' + +cat >expected <<EOF +file:foo mmap bar +file:foo_mmap bar +file:foo_mmap bar mmap +file:foo mmap bar_mmap +file:foo_mmap bar mmap baz +t/a/v:vvv +t/v:vvv +v:vvv +EOF + +cat >patterns <<EOF + +mmap + +vvv + +EOF + +test_expect_success 'grep -f, ignore empty lines' ' + git grep -f patterns >actual && + test_cmp expected actual +' + +cat >expected <<EOF +y:y yy +-- +z:zzz +EOF + +test_expect_success 'grep -q, silently report matches' ' + >empty && + git grep -q mmap >actual && + test_cmp empty actual && + test_must_fail git grep -q qfwfq >actual && + test_cmp empty actual +' + +# Create 1024 file names that sort between "y" and "z" to make sure +# the two files are handled by different calls to an external grep. +# This depends on MAXARGS in builtin-grep.c being 1024 or less. +c32="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v" +test_expect_success 'grep -C1, hunk mark between files' ' + for a in $c32; do for b in $c32; do : >y-$a$b; done; done && + git add y-?? && + git grep -C1 "^[yz]" >actual && + test_cmp expected actual +' + +test_expect_success 'grep -C1 hunk mark between files' ' + git grep -C1 "^[yz]" >actual && + test_cmp expected actual +' + +test_expect_success 'log grep setup' ' + echo a >>file && + test_tick && + GIT_AUTHOR_NAME="With * Asterisk" \ + GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \ + git commit -a -m "second" && + + echo a >>file && + test_tick && + git commit -a -m "third" + +' + +test_expect_success 'log grep (1)' ' + git log --author=author --pretty=tformat:%s >actual && + ( echo third ; echo initial ) >expect && + test_cmp expect actual +' + +test_expect_success 'log grep (2)' ' + git log --author=" * " -F --pretty=tformat:%s >actual && + ( echo second ) >expect && + test_cmp expect actual +' + +test_expect_success 'log grep (3)' ' + git log --author="^A U" --pretty=tformat:%s >actual && + ( echo third ; echo initial ) >expect && + test_cmp expect actual +' + +test_expect_success 'log grep (4)' ' + git log --author="frotz\.com>$" --pretty=tformat:%s >actual && + ( echo second ) >expect && + test_cmp expect actual +' + +test_expect_success 'log grep (5)' ' + git log --author=Thor -F --pretty=tformat:%s >actual && + ( echo third ; echo initial ) >expect && + test_cmp expect actual +' + +test_expect_success 'log grep (6)' ' + git log --author=-0700 --pretty=tformat:%s >actual && + >expect && + test_cmp expect actual +' + +test_expect_success 'log --grep --author implicitly uses all-match' ' + # grep matches initial and second but not third + # author matches only initial and third + git log --author="A U Thor" --grep=s --grep=l --format=%s >actual && + echo initial >expect && + test_cmp expect actual +' + +test_expect_success 'grep with CE_VALID file' ' + git update-index --assume-unchanged t/t && + rm t/t && + test "$(git grep test)" = "t/t:test" && + git update-index --no-assume-unchanged t/t && + git checkout t/t +' + +cat >expected <<EOF +hello.c=#include <stdio.h> +hello.c: return 0; +EOF + +test_expect_success 'grep -p with userdiff' ' + git config diff.custom.funcname "^#" && + echo "hello.c diff=custom" >.gitattributes && + git grep -p return >actual && + test_cmp expected actual +' + +cat >expected <<EOF +hello.c=int main(int argc, const char **argv) +hello.c: return 0; +EOF + +test_expect_success 'grep -p' ' + rm -f .gitattributes && + git grep -p return >actual && + test_cmp expected actual +' + +cat >expected <<EOF +hello.c-#include <stdio.h> +hello.c=int main(int argc, const char **argv) +hello.c-{ +hello.c- printf("Hello world.\n"); +hello.c: return 0; +EOF + +test_expect_success 'grep -p -B5' ' + git grep -p -B5 return >actual && + test_cmp expected actual +' + +test_expect_success 'grep from a subdirectory to search wider area (1)' ' + mkdir -p s && + ( + cd s && git grep "x x x" .. + ) +' + +test_expect_success 'grep from a subdirectory to search wider area (2)' ' + mkdir -p s && + ( + cd s || exit 1 + ( git grep xxyyzz .. >out ; echo $? >status ) + ! test -s out && + test 1 = $(cat status) + ) +' + +cat >expected <<EOF +hello.c:int main(int argc, const char **argv) +EOF + +test_expect_success 'grep -Fi' ' + git grep -Fi "CHAR *" >actual && + test_cmp expected actual +' + +test_expect_success 'outside of git repository' ' + rm -fr non && + mkdir -p non/git/sub && + echo hello >non/git/file1 && + echo world >non/git/sub/file2 && + echo ".*o*" >non/git/.gitignore && + { + echo file1:hello && + echo sub/file2:world + } >non/expect.full && + echo file2:world >non/expect.sub + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non/git" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_must_fail git grep o && + git grep --no-index o >../actual.full && + test_cmp ../expect.full ../actual.full + cd sub && + test_must_fail git grep o && + git grep --no-index o >../../actual.sub && + test_cmp ../../expect.sub ../../actual.sub + ) +' + +test_expect_success 'inside git repository but with --no-index' ' + rm -fr is && + mkdir -p is/git/sub && + echo hello >is/git/file1 && + echo world >is/git/sub/file2 && + echo ".*o*" >is/git/.gitignore && + { + echo file1:hello && + echo sub/file2:world + } >is/expect.full && + : >is/expect.empty && + echo file2:world >is/expect.sub + ( + cd is/git && + git init && + test_must_fail git grep o >../actual.full && + test_cmp ../expect.empty ../actual.full && + git grep --no-index o >../actual.full && + test_cmp ../expect.full ../actual.full && + cd sub && + test_must_fail git grep o >../../actual.sub && + test_cmp ../../expect.empty ../../actual.sub && + git grep --no-index o >../../actual.sub && + test_cmp ../../expect.sub ../../actual.sub + ) +' + +test_expect_success 'setup double-dash tests' ' +cat >double-dash <<EOF && +-- +-> +other +EOF +git add double-dash +' + +cat >expected <<EOF +double-dash:-> +EOF +test_expect_success 'grep -- pattern' ' + git grep -- "->" >actual && + test_cmp expected actual +' +test_expect_success 'grep -- pattern -- pathspec' ' + git grep -- "->" -- double-dash >actual && + test_cmp expected actual +' +test_expect_success 'grep -e pattern -- path' ' + git grep -e "->" -- double-dash >actual && + test_cmp expected actual +' + +cat >expected <<EOF +double-dash:-- +EOF +test_expect_success 'grep -e -- -- path' ' + git grep -e -- -- double-dash >actual && + test_cmp expected actual +' + +test_done 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/t8001-annotate.sh b/t/t8001-annotate.sh index 3a6490e8f8..45cb60ea4b 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -1,10 +1,10 @@ #!/bin/sh -test_description='git-annotate' +test_description='git annotate' . ./test-lib.sh PROG='git annotate' -. ../annotate-tests.sh +. "$TEST_DIRECTORY"/annotate-tests.sh test_expect_success \ 'Annotating an old revision works' \ diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index 9777393996..597cf0486f 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -1,9 +1,9 @@ #!/bin/sh -test_description='git-blame' +test_description='git blame' . ./test-lib.sh PROG='git blame -c' -. ../annotate-tests.sh +. "$TEST_DIRECTORY"/annotate-tests.sh test_done diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh new file mode 100755 index 0000000000..230143cf31 --- /dev/null +++ b/t/t8003-blame.sh @@ -0,0 +1,188 @@ +#!/bin/sh + +test_description='git blame corner cases' +. ./test-lib.sh + +pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/' + +test_expect_success setup ' + + echo A A A A A >one && + echo B B B B B >two && + echo C C C C C >tres && + echo ABC >mouse && + for i in 1 2 3 4 5 6 7 8 9 + do + echo $i + done >nine_lines && + for i in 1 2 3 4 5 6 7 8 9 a + do + echo $i + done >ten_lines && + git add one two tres mouse nine_lines ten_lines && + test_tick && + GIT_AUTHOR_NAME=Initial git commit -m Initial && + + cat one >uno && + mv two dos && + cat one >>tres && + echo DEF >>mouse + git add uno dos tres mouse && + test_tick && + GIT_AUTHOR_NAME=Second git commit -a -m Second && + + echo GHIJK >>mouse && + git add mouse && + test_tick && + GIT_AUTHOR_NAME=Third git commit -m Third && + + cat mouse >cow && + git add cow && + test_tick && + GIT_AUTHOR_NAME=Fourth git commit -m Fourth && + + { + echo ABC + echo DEF + echo XXXX + echo GHIJK + } >cow && + git add cow && + test_tick && + GIT_AUTHOR_NAME=Fifth git commit -m Fifth +' + +test_expect_success 'straight copy without -C' ' + + git blame uno | grep Second + +' + +test_expect_success 'straight move without -C' ' + + git blame dos | grep Initial + +' + +test_expect_success 'straight copy with -C' ' + + git blame -C1 uno | grep Second + +' + +test_expect_success 'straight move with -C' ' + + git blame -C1 dos | grep Initial + +' + +test_expect_success 'straight copy with -C -C' ' + + git blame -C -C1 uno | grep Initial + +' + +test_expect_success 'straight move with -C -C' ' + + git blame -C -C1 dos | grep Initial + +' + +test_expect_success 'append without -C' ' + + git blame -L2 tres | grep Second + +' + +test_expect_success 'append with -C' ' + + git blame -L2 -C1 tres | grep Second + +' + +test_expect_success 'append with -C -C' ' + + git blame -L2 -C -C1 tres | grep Second + +' + +test_expect_success 'append with -C -C -C' ' + + git blame -L2 -C -C -C1 tres | grep Initial + +' + +test_expect_success 'blame wholesale copy' ' + + git blame -f -C -C1 HEAD^ -- cow | sed -e "$pick_fc" >current && + { + echo mouse-Initial + echo mouse-Second + echo mouse-Third + } >expected && + test_cmp expected current + +' + +test_expect_success 'blame wholesale copy and more' ' + + git blame -f -C -C1 HEAD -- cow | sed -e "$pick_fc" >current && + { + echo mouse-Initial + echo mouse-Second + echo cow-Fifth + echo mouse-Third + } >expected && + test_cmp expected current + +' + +test_expect_success 'blame path that used to be a directory' ' + mkdir path && + echo A A A A A >path/file && + echo B B B B B >path/elif && + git add path && + test_tick && + git commit -m "path was a directory" && + rm -fr path && + echo A A A A A >path && + git add path && + test_tick && + git commit -m "path is a regular file" && + git blame HEAD^.. -- path +' + +test_expect_success 'blame to a commit with no author name' ' + TREE=`git rev-parse HEAD:` + cat >badcommit <<EOF +tree $TREE +author <noname> 1234567890 +0000 +committer David Reiss <dreiss@facebook.com> 1234567890 +0000 + +some message +EOF + COMMIT=`git hash-object -t commit -w badcommit` + git --no-pager blame $COMMIT -- uno >/dev/null +' + +test_expect_success 'blame -L with invalid start' ' + test_must_fail git blame -L5 tres 2>errors && + grep "has only 2 lines" errors +' + +test_expect_success 'blame -L with invalid end' ' + test_must_fail git blame -L1,5 tres 2>errors && + grep "has only 2 lines" errors +' + +test_expect_success 'indent of line numbers, nine lines' ' + git blame nine_lines >actual && + test $(grep -c " " actual) = 0 +' + +test_expect_success 'indent of line numbers, ten lines' ' + git blame ten_lines >actual && + test $(grep -c " " actual) = 9 +' + +test_done diff --git a/t/t8004-blame.sh b/t/t8004-blame.sh new file mode 100755 index 0000000000..ba19ac127e --- /dev/null +++ b/t/t8004-blame.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Based on a test case submitted by Björn Steinbrink. + +test_description='git blame on conflicted files' +. ./test-lib.sh + +test_expect_success 'setup first case' ' + # Create the old file + echo "Old line" > file1 && + git add file1 && + git commit --author "Old Line <ol@localhost>" -m file1.a && + + # Branch + git checkout -b foo && + + # Do an ugly move and change + git rm file1 && + echo "New line ..." > file2 && + echo "... and more" >> file2 && + git add file2 && + git commit --author "U Gly <ug@localhost>" -m ugly && + + # Back to master and change something + git checkout master && + echo " + +bla" >> file1 && + git commit --author "Old Line <ol@localhost>" -a -m file1.b && + + # Back to foo and merge master + git checkout foo && + if git merge master; then + echo needed conflict here + exit 1 + else + echo merge failed - resolving automatically + fi && + echo "New line ... +... and more + +bla +Even more" > file2 && + git rm file1 && + git commit --author "M Result <mr@localhost>" -a -m merged && + + # Back to master and change file1 again + git checkout master && + sed s/bla/foo/ <file1 >X && + rm file1 && + mv X file1 && + git commit --author "No Bla <nb@localhost>" -a -m replace && + + # Try to merge into foo again + git checkout foo && + if git merge master; then + echo needed conflict here + exit 1 + else + echo merge failed - test is setup + fi +' + +test_expect_success \ + 'blame runs on unconflicted file while other file has conflicts' ' + git blame file2 +' + +test_expect_success 'blame runs on conflicted file in stages 1,3' ' + git blame file1 +' + +test_done diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh new file mode 100755 index 0000000000..cb390559f9 --- /dev/null +++ b/t/t8005-blame-i18n.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='git blame encoding conversion' +. ./test-lib.sh + +. "$TEST_DIRECTORY"/t8005/utf8.txt +. "$TEST_DIRECTORY"/t8005/euc-japan.txt +. "$TEST_DIRECTORY"/t8005/sjis.txt + +test_expect_success 'setup the repository' ' + # Create the file + echo "UTF-8 LINE" > file && + git add file && + git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" && + + echo "EUC-JAPAN LINE" >> file && + git add file && + git config i18n.commitencoding eucJP && + git commit --author "$EUC_JAPAN_NAME <euc-japan@localhost>" -m "$EUC_JAPAN_MSG" && + + echo "SJIS LINE" >> file && + git add file && + git config i18n.commitencoding SJIS && + git commit --author "$SJIS_NAME <sjis@localhost>" -m "$SJIS_MSG" +' + +cat >expected <<EOF +author $SJIS_NAME +summary $SJIS_MSG +author $SJIS_NAME +summary $SJIS_MSG +author $SJIS_NAME +summary $SJIS_MSG +EOF + +test_expect_success \ + 'blame respects i18n.commitencoding' ' + git blame --incremental file | \ + egrep "^(author|summary) " > actual && + test_cmp actual expected +' + +cat >expected <<EOF +author $EUC_JAPAN_NAME +summary $EUC_JAPAN_MSG +author $EUC_JAPAN_NAME +summary $EUC_JAPAN_MSG +author $EUC_JAPAN_NAME +summary $EUC_JAPAN_MSG +EOF + +test_expect_success \ + 'blame respects i18n.logoutputencoding' ' + git config i18n.logoutputencoding eucJP && + git blame --incremental file | \ + egrep "^(author|summary) " > actual && + test_cmp actual expected +' + +cat >expected <<EOF +author $UTF8_NAME +summary $UTF8_MSG +author $UTF8_NAME +summary $UTF8_MSG +author $UTF8_NAME +summary $UTF8_MSG +EOF + +test_expect_success \ + 'blame respects --encoding=UTF-8' ' + git blame --incremental --encoding=UTF-8 file | \ + egrep "^(author|summary) " > actual && + test_cmp actual expected +' + +cat >expected <<EOF +author $SJIS_NAME +summary $SJIS_MSG +author $EUC_JAPAN_NAME +summary $EUC_JAPAN_MSG +author $UTF8_NAME +summary $UTF8_MSG +EOF + +test_expect_success \ + 'blame respects --encoding=none' ' + git blame --incremental --encoding=none file | \ + egrep "^(author|summary) " > actual && + test_cmp actual expected +' + +test_done diff --git a/t/t8005/euc-japan.txt b/t/t8005/euc-japan.txt new file mode 100644 index 0000000000..288f040c99 --- /dev/null +++ b/t/t8005/euc-japan.txt @@ -0,0 +1,2 @@ +EUC_JAPAN_NAME="»³ÅÄ ÂÀϺ" +EUC_JAPAN_MSG="¥Ö¥ì¡¼¥à¤Î¥Æ¥¹¥È¤Ç¤¹¡£" diff --git a/t/t8005/sjis.txt b/t/t8005/sjis.txt new file mode 100644 index 0000000000..bbdefeaced --- /dev/null +++ b/t/t8005/sjis.txt @@ -0,0 +1,2 @@ +SJIS_NAME="ŽR“c ‘¾˜Y" +SJIS_MSG="ƒuƒŒ[ƒ€‚̃eƒXƒg‚Å‚·B" diff --git a/t/t8005/utf8.txt b/t/t8005/utf8.txt new file mode 100644 index 0000000000..4d00dbea76 --- /dev/null +++ b/t/t8005/utf8.txt @@ -0,0 +1,2 @@ +UTF8_NAME="山田 太郎" +UTF8_MSG="ブレームã®ãƒ†ã‚¹ãƒˆã§ã™ã€‚" 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 e9ea33c18d..23597cc407 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1,44 +1,998 @@ #!/bin/sh -test_description='git-send-email' +test_description='git send-email' . ./test-lib.sh +if ! test_have_prereq PERL; then + skip_all='skipping git send-email tests, perl not available' + test_done +fi + PROG='git send-email' test_expect_success \ 'prepare reference tree' \ 'echo "1A quick brown fox jumps over the" >file && echo "lazy dog" >>file && - git add file + git add file && GIT_AUTHOR_NAME="A" git commit -a -m "Initial."' test_expect_success \ 'Setup helper tool' \ - '(echo "#!/bin/sh" + '(echo "#!$SHELL_PATH" echo shift + echo output=1 + echo "while test -f commandline\$output; do output=\$((\$output+1)); done" echo for a echo do echo " echo \"!\$a!\"" - echo "done >commandline" - echo "cat > msgtxt" - ) >fake.sendmail - chmod +x ./fake.sendmail - git add fake.sendmail + echo "done >commandline\$output" + echo "cat > msgtxt\$output" + ) >fake.sendmail && + chmod +x ./fake.sendmail && + git add fake.sendmail && GIT_AUTHOR_NAME="A" git commit -a -m "Second."' +clean_fake_sendmail() { + rm -f commandline* msgtxt* +} + test_expect_success 'Extract patches' ' - patches=`git format-patch -n HEAD^1` + patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1` +' + +# Test no confirm early to ensure remaining tests will not hang +test_no_confirm () { + rm -f no_confirm_okay + echo n | \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $@ \ + $patches > stdout && + test_must_fail grep "Send this email" stdout && + > no_confirm_okay +} + +# Exit immediately to prevent hang if a no-confirm test fails +check_no_confirm () { + test -f no_confirm_okay || { + skip_all='confirm test failed; skipping remaining tests to prevent hanging' + test_done + } +} + +test_expect_success 'No confirm with --suppress-cc' ' + test_no_confirm --suppress-cc=sob ' +check_no_confirm + +test_expect_success 'No confirm with --confirm=never' ' + test_no_confirm --confirm=never +' +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' ' + git config sendemail.confirm never && + test_no_confirm --compose --subject=foo +' +check_no_confirm test_expect_success 'Send patches' ' - git send-email -from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors + git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors +' + +cat >expected <<\EOF +!nobody@example.com! +!author@example.com! +!one@example.com! +!two@example.com! +EOF +test_expect_success \ + 'Verify commandline' \ + 'test_cmp expected commandline1' + +test_expect_success '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 +' + +cat >expected <<\EOF +!patch@example.com! +!-i! +!nobody@example.com! +!author@example.com! +!one@example.com! +!two@example.com! +EOF +test_expect_success \ + 'Verify commandline' \ + 'test_cmp expected commandline1' + +test_expect_success '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 ' cat >expected <<\EOF !nobody@example.com! +!-i! +!nobody@example.com! !author@example.com! +!one@example.com! +!two@example.com! EOF test_expect_success \ 'Verify commandline' \ - 'diff commandline expected' + 'test_cmp expected commandline1' + +cat >expected-show-all-headers <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<cc@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<bcc@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: cc@example.com, + A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING +In-Reply-To: <unique-message-id@example.com> +References: <unique-message-id@example.com> + +Result: OK +EOF + +test_expect_success 'Show all headers' ' + git send-email \ + --dry-run \ + --suppress-cc=sob \ + --from="Example <from@example.com>" \ + --to=to@example.com \ + --cc=cc@example.com \ + --bcc=bcc@example.com \ + --in-reply-to="<unique-message-id@example.com>" \ + --smtp-server relay.example.com \ + $patches | + sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \ + -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \ + -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \ + >actual-show-all-headers && + test_cmp expected-show-all-headers actual-show-all-headers +' + +test_expect_success 'Prompting works' ' + clean_fake_sendmail && + (echo "Example <from@example.com>" + echo "to@example.com" + echo "" + ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches \ + 2>errors && + grep "^From: Example <from@example.com>\$" msgtxt1 && + grep "^To: to@example.com\$" msgtxt1 +' + +test_expect_success 'cccmd works' ' + clean_fake_sendmail && + cp $patches cccmd.patch && + echo cccmd--cccmd@example.com >>cccmd.patch && + { + echo "#!$SHELL_PATH" + echo sed -n -e s/^cccmd--//p \"\$1\" + } > cccmd-sed && + chmod +x cccmd-sed && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --cc-cmd=./cccmd-sed \ + --smtp-server="$(pwd)/fake.sendmail" \ + cccmd.patch \ + && + 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' ' + clean_fake_sendmail && + cp $patches longline.patch && + echo $z512$z512 >>longline.patch && + test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches longline.patch \ + 2>errors && + grep longline.patch errors +' + +test_expect_success 'no patch was sent' ' + ! test -e commandline1 +' + +test_expect_success 'Author From: in message body' ' + clean_fake_sendmail && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + sed "1,/^\$/d" < msgtxt1 > msgbody1 + grep "From: A <author@example.com>" msgbody1 +' + +test_expect_success 'Author From: not in message body' ' + clean_fake_sendmail && + git send-email \ + --from="A <author@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + sed "1,/^\$/d" < msgtxt1 > msgbody1 + ! grep "From: A <author@example.com>" msgbody1 +' + +test_expect_success 'allow long lines with --no-validate' ' + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --novalidate \ + $patches longline.patch \ + 2>errors +' + +test_expect_success '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 + 2>errors + ! grep "^In-Reply-To: < *>" msgtxt1 +' + +test_expect_success 'Valid In-Reply-To when prompting' ' + clean_fake_sendmail && + (echo "From Example <from@example.com>" + echo "To Example <to@example.com>" + echo "" + ) | env GIT_SEND_EMAIL_NOTTY=1 git send-email \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches 2>errors && + ! grep "^In-Reply-To: < *>" msgtxt1 +' + +test_expect_success 'setup fake editor' ' + (echo "#!$SHELL_PATH" && + echo "echo fake edit >>\"\$1\"" + ) >fake-editor && + chmod +x fake-editor +' + +test_set_editor "$(pwd)/fake-editor" + +test_expect_success '--compose works' ' + clean_fake_sendmail && + git send-email \ + --compose --subject foo \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches \ + 2>errors +' + +test_expect_success 'first message is compose text' ' + grep "^fake edit" msgtxt1 +' + +test_expect_success 'second message is patch' ' + grep "Subject:.*Second" msgtxt2 +' + +cat >expected-suppress-sob <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<cc@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: cc@example.com, + A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_suppression () { + git send-email \ + --dry-run \ + --suppress-cc=$1 ${2+"--suppress-cc=$2"} \ + --from="Example <from@example.com>" \ + --to=to@example.com \ + --smtp-server relay.example.com \ + $patches | + sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \ + -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \ + -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \ + >actual-suppress-$1${2+"-$2"} && + test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"} +} + +test_expect_success 'sendemail.cc set' ' + git config sendemail.cc cc@example.com && + test_suppression sob +' + +cat >expected-suppress-sob <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success 'sendemail.cc unset' ' + git config --unset sendemail.cc && + test_suppression sob +' + +cat >expected-suppress-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<committer@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + C O Mitter <committer@example.com> +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success 'sendemail.cccmd' ' + echo echo cc-cmd@example.com > cccmd && + chmod +x cccmd && + git config sendemail.cccmd ./cccmd && + test_suppression cccmd +' + +cat >expected-suppress-all <<\EOF +0001-Second.patch +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +From: Example <from@example.com> +To: to@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=all' ' + test_suppression all +' + +cat >expected-suppress-body <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<cc-cmd@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + cc-cmd@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=body' ' + test_suppression body +' + +cat >expected-suppress-body-cccmd <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=body --suppress-cc=cccmd' ' + test_suppression body cccmd +' + +cat >expected-suppress-sob <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=sob' ' + git config --unset sendemail.cccmd + test_suppression sob +' + +cat >expected-suppress-bodycc <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com' +(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com' +(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<one@example.com> +RCPT TO:<two@example.com> +RCPT TO:<committer@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + One <one@example.com>, + two@example.com, + C O Mitter <committer@example.com> +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=bodycc' ' + test_suppression bodycc +' + +cat >expected-suppress-cc <<\EOF +0001-Second.patch +(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>' +(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>' +Dry-OK. Log says: +Server: relay.example.com +MAIL FROM:<from@example.com> +RCPT TO:<to@example.com> +RCPT TO:<author@example.com> +RCPT TO:<committer@example.com> +From: Example <from@example.com> +To: to@example.com +Cc: A <author@example.com>, + C O Mitter <committer@example.com> +Subject: [PATCH 1/1] Second. +Date: DATE-STRING +Message-Id: MESSAGE-ID-STRING +X-Mailer: X-MAILER-STRING + +Result: OK +EOF + +test_expect_success '--suppress-cc=cc' ' + test_suppression cc +' + +test_confirm () { + echo y | \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $@ $patches > stdout && + grep "Send this email" stdout +} + +test_expect_success '--confirm=always' ' + test_confirm --confirm=always --suppress-cc=all +' + +test_expect_success '--confirm=auto' ' + test_confirm --confirm=auto +' + +test_expect_success '--confirm=cc' ' + test_confirm --confirm=cc +' + +test_expect_success '--confirm=compose' ' + test_confirm --confirm=compose --compose +' + +test_expect_success 'confirm by default (due to cc)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + test_confirm + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm by default (due to --compose)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + test_confirm --suppress-cc=all --compose + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm detects EOF (inform assumes y)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config --unset sendemail.confirm && + rm -fr outdir && + git format-patch -2 -o outdir && + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/*.patch < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm detects EOF (auto causes failure)' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && + test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches < /dev/null + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'confirm doesnt loop forever' ' + CONFIRM=$(git config --get sendemail.confirm) && + git config sendemail.confirm auto && + GIT_SEND_EMAIL_NOTTY=1 && + export GIT_SEND_EMAIL_NOTTY && + yes "bogus" | test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches + ret="$?" + git config sendemail.confirm ${CONFIRM:-never} + test $ret = "0" +' + +test_expect_success 'utf8 Cc is rfc2047 encoded' ' + clean_fake_sendmail && + rm -fr outdir && + git format-patch -1 -o outdir --cc="à éìöú <utf8@example.com>" && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + outdir/*.patch && + grep "^ " msgtxt1 | + 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' ' + clean_fake_sendmail && + (echo "#!$SHELL_PATH" && + echo "echo utf8 body: à éìöú >>\"\$1\"" + ) >fake-editor-utf8 && + chmod +x fake-editor-utf8 && + GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \ + git send-email \ + --compose --subject foo \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^utf8 body" msgtxt1 && + grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 +' + +test_expect_success '--compose respects user mime type' ' + clean_fake_sendmail && + (echo "#!$SHELL_PATH" && + echo "(echo MIME-Version: 1.0" + echo " echo Content-Type: text/plain\\; charset=iso-8859-1" + echo " echo Content-Transfer-Encoding: 8bit" + echo " echo Subject: foo" + echo " echo " + echo " echo utf8 body: à éìöú) >\"\$1\"" + ) >fake-editor-utf8-mime && + chmod +x fake-editor-utf8-mime && + GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \ + git send-email \ + --compose --subject foo \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^utf8 body" msgtxt1 && + grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 && + ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 +' + +test_expect_success '--compose adds MIME for utf8 subject' ' + clean_fake_sendmail && + GIT_EDITOR="\"$(pwd)/fake-editor\"" \ + git send-email \ + --compose --subject utf8-sübjëct \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^fake edit" msgtxt1 && + grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 +' + +test_expect_success 'detects ambiguous reference/file conflict' ' + echo master > master && + git add master && + git commit -m"add master" && + test_must_fail git send-email --dry-run master 2>errors && + grep disambiguate errors +' + +test_expect_success 'feed two files' ' + rm -fr outdir && + git format-patch -2 -o outdir && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + grep "^Subject: " out >subjects && + test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." && + test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master" +' + +test_expect_success 'in-reply-to but no threading' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --in-reply-to="<in-reply-id@example.com>" \ + --nothread \ + $patches | + grep "In-Reply-To: <in-reply-id@example.com>" +' + +test_expect_success 'no in-reply-to and no threading' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --nothread \ + $patches $patches >stdout && + ! grep "In-Reply-To: " stdout +' + +test_expect_success 'threading but no chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --thread \ + --nochain-reply-to \ + $patches $patches >stdout && + grep "In-Reply-To: " stdout +' + +test_expect_success 'warning with an implicit --chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with an explicit --chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --chain-reply-to \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with an explicit --no-chain-reply-to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --nochain-reply-to \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with sendemail.chainreplyto = false' ' + git config sendemail.chainreplyto false && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'no warning with sendemail.chainreplyto = true' ' + git config sendemail.chainreplyto true && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + outdir/000?-*.patch 2>errors >out && + ! grep "no-chain-reply-to" errors +' + +test_expect_success 'sendemail.to works' ' + git config --replace-all sendemail.to "Somebody <somebody@ex.com>" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + $patches $patches >stdout && + grep "To: Somebody <somebody@ex.com>" stdout +' + +test_expect_success '--no-to overrides sendemail.to' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --no-to \ + --to=nobody@example.com \ + $patches $patches >stdout && + grep "To: nobody@example.com" stdout && + ! grep "To: Somebody <somebody@ex.com>" stdout +' + +test_expect_success 'sendemail.cc works' ' + git config --replace-all sendemail.cc "Somebody <somebody@ex.com>" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + $patches $patches >stdout && + grep "Cc: Somebody <somebody@ex.com>" stdout +' + +test_expect_success '--no-cc overrides sendemail.cc' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --no-cc \ + --cc=bodies@example.com \ + --to=nobody@example.com \ + $patches $patches >stdout && + grep "Cc: bodies@example.com" stdout && + ! grep "Cc: Somebody <somebody@ex.com>" stdout +' + +test_expect_success 'sendemail.bcc works' ' + git config --replace-all sendemail.bcc "Other <other@ex.com>" && + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server relay.example.com \ + $patches $patches >stdout && + grep "RCPT TO:<other@ex.com>" stdout +' + +test_expect_success '--no-bcc overrides sendemail.bcc' ' + git send-email \ + --dry-run \ + --from="Example <nobody@example.com>" \ + --no-bcc \ + --bcc=bodies@example.com \ + --to=nobody@example.com \ + --smtp-server relay.example.com \ + $patches $patches >stdout && + grep "RCPT TO:<bodies@example.com>" stdout && + ! grep "RCPT TO:<other@ex.com>" stdout +' + +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 + +cat >content-type-decl <<EOF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +EOF + +test_expect_success '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 '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 '--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 +' + +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 + +cat >expected <<EOF +Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?= +EOF + +test_expect_success '--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 +' test_done diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 7dcfc7e7db..13766ab160 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -3,201 +3,196 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-svn basic tests' -GIT_SVN_LC_ALL=$LC_ALL +test_description='git svn basic tests' +GIT_SVN_LC_ALL=${LC_ALL:-$LANG} -case "$LC_ALL" in +. ./lib-git-svn.sh + +say 'define NO_SVN_TESTS to skip git svn tests' + +case "$GIT_SVN_LC_ALL" in *.UTF-8) - have_utf8=t + test_set_prereq UTF8 ;; *) - have_utf8= + say "# UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)" ;; esac -. ./lib-git-svn.sh - -echo 'define NO_SVN_TESTS to skip git-svn tests' - test_expect_success \ - 'initialize git-svn' " + '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 && + echo "deep dir" > dir/a/b/c/d/e/file && mkdir bar && - echo 'zzz' > bar/zzz && - echo '#!/bin/sh' > exec.sh && + echo "zzz" > bar/zzz && + echo "#!/bin/sh" > exec.sh && chmod +x exec.sh && - svn import -m 'import for git-svn' . $svnrepo >/dev/null && + svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null && cd .. && rm -rf import && - git-svn init $svnrepo" + git svn init "$svnrepo"' test_expect_success \ 'import an SVN revision into git' \ - 'git-svn fetch' + 'git svn fetch' -test_expect_success "checkout from svn" "svn co $svnrepo '$SVN_TREE'" +test_expect_success "checkout from svn" 'svn co "$svnrepo" "$SVN_TREE"' name='try a deep --rmdir with a commit' -test_expect_success "$name" " - git checkout -f -b mybranch remotes/git-svn && +test_expect_success "$name" ' + git checkout -f -b mybranch ${remotes_git_svn} && mv dir/a/b/c/d/e/file dir/file && cp dir/file file && git update-index --add --remove dir/a/b/c/d/e/file dir/file file && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch && - svn up '$SVN_TREE' && - test -d '$SVN_TREE'/dir && test ! -d '$SVN_TREE'/dir/a" + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch && + svn_cmd up "$SVN_TREE" && + test -d "$SVN_TREE"/dir && test ! -d "$SVN_TREE"/dir/a' name='detect node change from file to directory #1' -test_expect_failure "$name" " +test_expect_success "$name" " mkdir dir/new_file && mv dir/file dir/new_file/file && mv dir/new_file dir/file && git update-index --remove dir/file && git update-index --add dir/file/file && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch" || true + git commit -m '$name' && + test_must_fail git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch" || true name='detect node change from directory to file #1' -test_expect_failure "$name" " - rm -rf dir '$GIT_DIR'/index && - git checkout -f -b mybranch2 remotes/git-svn && +test_expect_success "$name" ' + rm -rf dir "$GIT_DIR"/index && + git checkout -f -b mybranch2 ${remotes_git_svn} && mv bar/zzz zzz && rm -rf bar && mv zzz bar && git update-index --remove -- bar/zzz && git update-index --add -- bar && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch2" || true + git commit -m "$name" && + test_must_fail git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch2' || true name='detect node change from file to directory #2' -test_expect_failure "$name" " - rm -f '$GIT_DIR'/index && - git checkout -f -b mybranch3 remotes/git-svn && +test_expect_success "$name" ' + rm -f "$GIT_DIR"/index && + git checkout -f -b mybranch3 ${remotes_git_svn} && rm bar/zzz && - git-update-index --remove bar/zzz && + git update-index --remove bar/zzz && mkdir bar/zzz && echo yyy > bar/zzz/yyy && - git-update-index --add bar/zzz/yyy && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch3" || true + git update-index --add bar/zzz/yyy && + git commit -m "$name" && + test_must_fail git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch3' || true name='detect node change from directory to file #2' -test_expect_failure "$name" " - rm -f '$GIT_DIR'/index && - git checkout -f -b mybranch4 remotes/git-svn && +test_expect_success "$name" ' + rm -f "$GIT_DIR"/index && + git checkout -f -b mybranch4 ${remotes_git_svn} && rm -rf dir && git update-index --remove -- dir/file && touch dir && echo asdf > dir && git update-index --add -- dir && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch4" || true + git commit -m "$name" && + test_must_fail git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch4' || true name='remove executable bit from a file' -test_expect_success "$name" " - rm -f '$GIT_DIR'/index && - git checkout -f -b mybranch5 remotes/git-svn && +test_expect_success "$name" ' + rm -f "$GIT_DIR"/index && + git checkout -f -b mybranch5 ${remotes_git_svn} && chmod -x exec.sh && git update-index exec.sh && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch5 && - svn up '$SVN_TREE' && - test ! -x '$SVN_TREE'/exec.sh" + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && + test ! -x "$SVN_TREE"/exec.sh' name='add executable bit back file' -test_expect_success "$name" " +test_expect_success "$name" ' chmod +x exec.sh && git update-index exec.sh && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch5 && - svn up '$SVN_TREE' && - test -x '$SVN_TREE'/exec.sh" + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && + test -x "$SVN_TREE"/exec.sh' name='executable file becomes a symlink to bar/zzz (file)' -test_expect_success "$name" " +test_expect_success "$name" ' rm exec.sh && ln -s bar/zzz exec.sh && git update-index exec.sh && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch5 && - svn up '$SVN_TREE' && - test -L '$SVN_TREE'/exec.sh" + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && + test -L "$SVN_TREE"/exec.sh' name='new symlink is added to a file that was also just made executable' -test_expect_success "$name" " +test_expect_success "$name" ' chmod +x bar/zzz && ln -s bar/zzz exec-2.sh && git update-index --add bar/zzz exec-2.sh && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch5 && - svn up '$SVN_TREE' && - test -x '$SVN_TREE'/bar/zzz && - test -L '$SVN_TREE'/exec-2.sh" + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && + test -x "$SVN_TREE"/bar/zzz && + test -L "$SVN_TREE"/exec-2.sh' name='modify a symlink to become a file' -test_expect_success "$name" " +test_expect_success "$name" ' echo git help > help || true && rm exec-2.sh && cp help exec-2.sh && git update-index exec-2.sh && - git commit -m '$name' && - git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch5 && - svn up '$SVN_TREE' && - test -f '$SVN_TREE'/exec-2.sh && - test ! -L '$SVN_TREE'/exec-2.sh && - diff -u help $SVN_TREE/exec-2.sh" - -if test "$have_utf8" = t -then - name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL" - LC_ALL="$GIT_SVN_LC_ALL" - export LC_ALL - test_expect_success "$name" " - echo '# hello' >> exec-2.sh && - git update-index exec-2.sh && - git commit -m 'éïâˆ' && - git-svn set-tree HEAD" - unset LC_ALL -else - echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)" -fi + git commit -m "$name" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && + test -f "$SVN_TREE"/exec-2.sh && + test ! -L "$SVN_TREE"/exec-2.sh && + test_cmp help "$SVN_TREE"/exec-2.sh' + +name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL" +LC_ALL="$GIT_SVN_LC_ALL" +export LC_ALL +test_expect_success UTF8 "$name" " + echo '# hello' >> exec-2.sh && + git update-index exec-2.sh && + git commit -m 'éïâˆ' && + git svn set-tree HEAD" +unset LC_ALL name='test fetch functionality (svn => git) with alternate GIT_SVN_ID' GIT_SVN_ID=alt export GIT_SVN_ID test_expect_success "$name" \ - "git-svn init $svnrepo && git-svn fetch && - git-rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a && - git-rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b && - diff -u a b" + 'git svn init "$svnrepo" && git svn fetch && + git rev-list --pretty=raw ${remotes_git_svn} | grep ^tree | uniq > a && + git rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b && + test_cmp a b' name='check imported tree checksums expected tree checksums' rm -f expected -if test "$have_utf8" = t +if test_have_prereq UTF8 then echo tree bf522353586b1b883488f2bc73dab0d9f774b9a9 > expected fi @@ -211,49 +206,68 @@ tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4 EOF -test_expect_success "$name" "diff -u a expected" +test_expect_success "$name" "test_cmp a expected" -test_expect_failure 'exit if remote refs are ambigious' " - git-config --add svn-remote.svn.fetch \ - bar:refs/remotes/git-svn && - git-svn migrate - " +test_expect_success 'exit if remote refs are ambigious' " + git config --add svn-remote.svn.fetch \ + bar:refs/${remotes_git_svn} && + test_must_fail git svn migrate +" -test_expect_failure 'exit if init-ing a would clobber a URL' " - svnadmin create ${PWD}/svnrepo2 && - svn mkdir -m 'mkdir bar' ${svnrepo}2/bar && - git-config --unset svn-remote.svn.fetch \ - '^bar:refs/remotes/git-svn$' && - git-svn init ${svnrepo}2/bar - " +test_expect_success 'exit if init-ing a would clobber a URL' ' + svnadmin create "${PWD}/svnrepo2" && + svn mkdir -m "mkdir bar" "${svnrepo}2/bar" && + git config --unset svn-remote.svn.fetch \ + "^bar:refs/${remotes_git_svn}$" && + test_must_fail git svn init "${svnrepo}2/bar" + ' test_expect_success \ - 'init allows us to connect to another directory in the same repo' " - git-svn init -i bar $svnrepo/bar && + 'init allows us to connect to another directory in the same repo' ' + git svn init --minimize-url -i bar "$svnrepo/bar" && git config --get svn-remote.svn.fetch \ - '^bar:refs/remotes/bar$' && + "^bar:refs/remotes/bar$" && git config --get svn-remote.svn.fetch \ - '^:refs/remotes/git-svn$' - " + "^:refs/${remotes_git_svn}$" + ' + +test_expect_success 'dcommit $rev does not clobber current branch' ' + git svn fetch -i bar && + git checkout -b my-bar refs/remotes/bar && + echo 1 > foo && + git add foo && + git commit -m "change 1" && + echo 2 > foo && + git add foo && + git commit -m "change 2" && + old_head=$(git rev-parse HEAD) && + git svn dcommit -i bar HEAD^ && + test $old_head = $(git rev-parse HEAD) && + test refs/heads/my-bar = $(git symbolic-ref HEAD) && + git log refs/remotes/bar | grep "change 1" && + ! git log refs/remotes/bar | grep "change 2" && + git checkout master && + git branch -D my-bar + ' test_expect_success 'able to dcommit to a subdirectory' " - git-svn fetch -i bar && + git svn fetch -i bar && git checkout -b my-bar refs/remotes/bar && echo abc > d && git update-index --add d && git commit -m '/bar/d should be in the log' && - git-svn dcommit -i bar && + git svn dcommit -i bar && test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && mkdir newdir && echo new > newdir/dir && git update-index --add newdir/dir && git commit -m 'add a new directory' && - git-svn dcommit -i bar && + git svn dcommit -i bar && test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && echo foo >> newdir/dir && git update-index newdir/dir && git commit -m 'modify a file in new directory' && - git-svn dcommit -i bar && + git svn dcommit -i bar && test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" " @@ -261,8 +275,17 @@ test_expect_success 'able to set-tree to a subdirectory' " echo cba > d && git update-index d && git commit -m 'update /bar/d' && - git-svn set-tree -i bar HEAD && + git svn set-tree -i bar HEAD && test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" " +test_expect_success 'git-svn works in a bare repository' ' + mkdir bare-repo && + ( cd bare-repo && + git init --bare && + GIT_DIR=. git svn init "$svnrepo" && + git svn fetch ) && + rm -rf bare-repo + ' + test_done diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index 622ea1c0df..929499e996 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-svn property tests' +test_description='git svn property tests' . ./lib-git-svn.sh mkdir import @@ -26,56 +26,56 @@ cd import EOF printf "Hello\r\nWorld\r\n" > crlf - a_crlf=`git-hash-object -w crlf` + a_crlf=`git hash-object -w crlf` printf "Hello\rWorld\r" > cr - a_cr=`git-hash-object -w cr` + a_cr=`git hash-object -w cr` printf "Hello\nWorld\n" > lf - a_lf=`git-hash-object -w lf` + a_lf=`git hash-object -w lf` printf "Hello\r\nWorld" > ne_crlf - a_ne_crlf=`git-hash-object -w ne_crlf` + a_ne_crlf=`git hash-object -w ne_crlf` printf "Hello\nWorld" > ne_lf - a_ne_lf=`git-hash-object -w ne_lf` + a_ne_lf=`git hash-object -w ne_lf` printf "Hello\rWorld" > ne_cr - a_ne_cr=`git-hash-object -w ne_cr` + a_ne_cr=`git hash-object -w ne_cr` touch empty - a_empty=`git-hash-object -w empty` + a_empty=`git hash-object -w empty` printf "\n" > empty_lf - a_empty_lf=`git-hash-object -w empty_lf` + a_empty_lf=`git hash-object -w empty_lf` printf "\r" > empty_cr - a_empty_cr=`git-hash-object -w empty_cr` + a_empty_cr=`git hash-object -w empty_cr` printf "\r\n" > empty_crlf - a_empty_crlf=`git-hash-object -w empty_crlf` + a_empty_crlf=`git hash-object -w empty_crlf` - svn import -m 'import for git-svn' . "$svnrepo" >/dev/null + svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null cd .. rm -rf import -test_expect_success 'checkout working copy from svn' "svn co $svnrepo test_wc" +test_expect_success 'checkout working copy from svn' 'svn co "$svnrepo" test_wc' test_expect_success 'setup some commits to svn' \ 'cd test_wc && echo Greetings >> kw.c && poke kw.c && - svn commit -m "Not yet an Id" && + svn_cmd commit -m "Not yet an Id" && echo Hello world >> kw.c && poke kw.c && - svn commit -m "Modified file, but still not yet an Id" && - svn propset svn:keywords Id kw.c && + svn_cmd commit -m "Modified file, but still not yet an Id" && + svn_cmd propset svn:keywords Id kw.c && poke kw.c && - svn commit -m "Propset Id" && + svn_cmd commit -m "Propset Id" && cd ..' -test_expect_success 'initialize git-svn' "git-svn init $svnrepo" -test_expect_success 'fetch revisions from svn' 'git-svn fetch' +test_expect_success 'initialize git svn' 'git svn init "$svnrepo"' +test_expect_success 'fetch revisions from svn' 'git svn fetch' name='test svn:keywords ignoring' test_expect_success "$name" \ - 'git checkout -b mybranch remotes/git-svn && + 'git checkout -b mybranch ${remotes_git_svn} && echo Hi again >> kw.c && git commit -a -m "test keywords ignoring" && - git-svn set-tree remotes/git-svn..mybranch && - git pull . remotes/git-svn' + git svn set-tree ${remotes_git_svn}..mybranch && + git pull . ${remotes_git_svn}' expect='/* $Id$ */' got="`sed -ne 2p kw.c`" @@ -83,16 +83,16 @@ test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'" test_expect_success "propset CR on crlf files" \ 'cd test_wc && - svn propset svn:eol-style CR empty && - svn propset svn:eol-style CR crlf && - svn propset svn:eol-style CR ne_crlf && - svn commit -m "propset CR on crlf files" && + 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 ..' test_expect_success 'fetch and pull latest from svn and checkout a new wc' \ - "git-svn fetch && - git pull . remotes/git-svn && - svn co $svnrepo new_wc" + 'git svn fetch && + git pull . ${remotes_git_svn} && + svn_cmd co "$svnrepo" new_wc' for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf do @@ -103,20 +103,20 @@ done cd test_wc printf '$Id$\rHello\rWorld\r' > cr printf '$Id$\rHello\rWorld' > ne_cr - a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git-hash-object --stdin` - a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git-hash-object --stdin` + a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin` + a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin` test_expect_success 'Set CRLF on cr files' \ - 'svn propset svn:eol-style CRLF cr && - svn propset svn:eol-style CRLF ne_cr && - svn propset svn:keywords Id cr && - svn propset svn:keywords Id ne_cr && - svn commit -m "propset CRLF on cr files"' + 'svn_cmd propset svn:eol-style CRLF cr && + svn_cmd propset svn:eol-style CRLF ne_cr && + svn_cmd propset svn:keywords Id cr && + svn_cmd propset svn:keywords Id ne_cr && + svn_cmd commit -m "propset CRLF on cr files"' cd .. test_expect_success 'fetch and pull latest from svn' \ - 'git-svn fetch && git pull . remotes/git-svn' + 'git svn fetch && git pull . ${remotes_git_svn}' -b_cr="`git-hash-object cr`" -b_ne_cr="`git-hash-object ne_cr`" +b_cr="`git hash-object cr`" +b_ne_cr="`git hash-object ne_cr`" test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'" test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'" @@ -126,25 +126,95 @@ cat > show-ignore.expect <<\EOF # / /no-such-file* -# deeply +# /deeply/ /deeply/no-such-file* -# deeply/nested +# /deeply/nested/ /deeply/nested/no-such-file* -# deeply/nested/directory +# /deeply/nested/directory/ /deeply/nested/directory/no-such-file* EOF test_expect_success 'test show-ignore' " cd test_wc && mkdir -p deeply/nested/directory && - svn add deeply && - svn propset -R svn:ignore 'no-such-file*' . - svn commit -m 'propset svn:ignore' + 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 .. && - git-svn show-ignore > show-ignore.got && + git svn show-ignore > show-ignore.got && cmp show-ignore.expect show-ignore.got " +cat >create-ignore.expect <<\EOF +/no-such-file* +EOF + +cat >create-ignore-index.expect <<\EOF +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 .gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/.gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/.gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/directory/.gitignore +EOF + +test_expect_success 'test create-ignore' " + git svn fetch && git pull . ${remotes_git_svn} && + git svn create-ignore && + cmp ./.gitignore create-ignore.expect && + cmp ./deeply/.gitignore create-ignore.expect && + cmp ./deeply/nested/.gitignore create-ignore.expect && + cmp ./deeply/nested/directory/.gitignore create-ignore.expect && + git ls-files -s | grep gitignore | cmp - create-ignore-index.expect + " + +cat >prop.expect <<\EOF + +no-such-file* + +EOF +cat >prop2.expect <<\EOF +8 +EOF + +# This test can be improved: since all the svn:ignore contain the same +# pattern, it can pass even though the propget did not execute on the +# right directory. +test_expect_success 'test propget' " + git svn propget svn:ignore . | cmp - prop.expect && + cd deeply && + git svn propget svn:ignore . | cmp - ../prop.expect && + git svn propget svn:entry:committed-rev nested/directory/.keep \ + | cmp - ../prop2.expect && + git svn propget svn:ignore .. | cmp - ../prop.expect && + git svn propget svn:ignore nested/ | cmp - ../prop.expect && + git svn propget svn:ignore ./nested | cmp - ../prop.expect && + git svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect + " + +cat >prop.expect <<\EOF +Properties on '.': + svn:entry:committed-date + svn:entry:committed-rev + svn:entry:last-author + svn:entry:uuid + svn:ignore +EOF +cat >prop2.expect <<\EOF +Properties on 'nested/directory/.keep': + svn:entry:committed-date + svn:entry:committed-rev + svn:entry:last-author + svn:entry:uuid +EOF + +test_expect_success 'test proplist' " + git svn proplist . | cmp - prop.expect && + git svn proplist nested/directory/.keep | cmp - prop2.expect + " + test_done diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh index 4e0808380f..028fb19e09 100755 --- a/t/t9102-git-svn-deep-rmdir.sh +++ b/t/t9102-git-svn-deep-rmdir.sh @@ -1,30 +1,30 @@ #!/bin/sh -test_description='git-svn rmdir' +test_description='git svn rmdir' . ./lib-git-svn.sh -test_expect_success 'initialize repo' " +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 import -m 'import for git-svn' . $svnrepo && + svn_cmd import -m "import for git svn" . "$svnrepo" && cd .. - " + ' -test_expect_success 'mirror via git-svn' " - git-svn init $svnrepo && - git-svn fetch && - git checkout -f -b test-rmdir remotes/git-svn - " +test_expect_success 'mirror via git svn' ' + git svn init "$svnrepo" && + git svn fetch && + git checkout -f -b test-rmdir ${remotes_git_svn} + ' -test_expect_success 'Try a commit on rmdir' " +test_expect_success 'Try a commit on rmdir' ' git rm -f deeply/nested/directory/number/2/another && - git commit -a -m 'remove another' && - git-svn set-tree --rmdir HEAD && - svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1 - " + git commit -a -m "remove another" && + git svn set-tree --rmdir HEAD && + svn_cmd ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1 + ' test_done diff --git a/t/t9103-git-svn-tracked-directory-removed.sh b/t/t9103-git-svn-tracked-directory-removed.sh new file mode 100755 index 0000000000..3413164cb1 --- /dev/null +++ b/t/t9103-git-svn-tracked-directory-removed.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +test_description='git svn tracking removed top-level path' +. ./lib-git-svn.sh + +test_expect_success 'make history for tracking' ' + mkdir import && + mkdir import/trunk && + echo hello >> import/trunk/README && + svn_cmd import -m initial import "$svnrepo" && + rm -rf import && + svn_cmd co "$svnrepo"/trunk trunk && + echo bye bye >> trunk/README && + svn_cmd rm -m "gone" "$svnrepo"/trunk && + rm -rf trunk && + mkdir trunk && + echo "new" > trunk/FOLLOWME && + svn_cmd import -m "new trunk" trunk "$svnrepo"/trunk +' + +test_expect_success 'clone repo with git' ' + git svn clone -s "$svnrepo" x && + test -f x/FOLLOWME && + test ! -f x/README +' + +test_expect_success 'make sure r2 still has old file' " + cd x && + test -n \"\$(git svn find-rev r1)\" && + git reset --hard \$(git svn find-rev r1) && + test -f README && + test ! -f FOLLOWME && + test x\$(git svn find-rev r2) = x +" + +test_done diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index bd4f366e86..bbfd7f4793 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -3,166 +3,210 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-svn fetching' +test_description='git svn fetching' . ./lib-git-svn.sh -test_expect_success 'initialize repo' " +test_expect_success 'initialize repo' ' mkdir import && cd import && mkdir -p trunk && echo hello > trunk/readme && - svn import -m 'initial' . $svnrepo && + svn_cmd import -m "initial" . "$svnrepo" && cd .. && - svn co $svnrepo wc && + svn_cmd co "$svnrepo" wc && cd wc && echo world >> trunk/readme && poke trunk/readme && - svn commit -m 'another commit' && - svn up && - svn mv -m 'rename to thunk' trunk thunk && - svn up && + svn_cmd commit -m "another commit" && + svn_cmd up && + svn_cmd mv trunk thunk && echo goodbye >> thunk/readme && poke thunk/readme && - svn commit -m 'bye now' && + svn_cmd commit -m "bye now" && cd .. - " + ' -test_expect_success 'init and fetch a moved directory' " - git-svn init -i thunk $svnrepo/thunk && - git-svn fetch -i thunk && - test \"\`git-rev-parse --verify refs/remotes/thunk@2\`\" \ - = \"\`git-rev-parse --verify refs/remotes/thunk~1\`\" && - test \"\`git-cat-file blob refs/remotes/thunk:readme |\ - sed -n -e '3p'\`\" = goodbye && - test -z \"\`git-config --get svn-remote.svn.fetch \ - '^trunk:refs/remotes/thunk@2$'\`\" - " +test_expect_success 'init and fetch a moved directory' ' + git svn init --minimize-url -i thunk "$svnrepo"/thunk && + git svn fetch -i thunk && + test "`git rev-parse --verify refs/remotes/thunk@2`" \ + = "`git rev-parse --verify refs/remotes/thunk~1`" && + test "`git cat-file blob refs/remotes/thunk:readme |\ + sed -n -e "3p"`" = goodbye && + test -z "`git config --get svn-remote.svn.fetch \ + "^trunk:refs/remotes/thunk@2$"`" + ' -test_expect_success 'init and fetch from one svn-remote' " - git-config svn-remote.svn.url $svnrepo && - git-config --add svn-remote.svn.fetch \ +test_expect_success 'init and fetch from one svn-remote' ' + git config svn-remote.svn.url "$svnrepo" && + git config --add svn-remote.svn.fetch \ trunk:refs/remotes/svn/trunk && - git-config --add svn-remote.svn.fetch \ + git config --add svn-remote.svn.fetch \ thunk:refs/remotes/svn/thunk && - git-svn fetch -i svn/thunk && - test \"\`git-rev-parse --verify refs/remotes/svn/trunk\`\" \ - = \"\`git-rev-parse --verify refs/remotes/svn/thunk~1\`\" && - test \"\`git-cat-file blob refs/remotes/svn/thunk:readme |\ - sed -n -e '3p'\`\" = goodbye - " - -test_expect_success 'follow deleted parent' " - svn cp -m 'resurrecting trunk as junk' \ - -r2 $svnrepo/trunk $svnrepo/junk && - git-config --add svn-remote.svn.fetch \ + git svn fetch -i svn/thunk && + test "`git rev-parse --verify refs/remotes/svn/trunk`" \ + = "`git rev-parse --verify refs/remotes/svn/thunk~1`" && + test "`git cat-file blob refs/remotes/svn/thunk:readme |\ + sed -n -e "3p"`" = goodbye + ' + +test_expect_success 'follow deleted parent' ' + (svn_cmd cp -m "resurrecting trunk as junk" \ + "$svnrepo"/trunk@2 "$svnrepo"/junk || + svn cp -m "resurrecting trunk as junk" \ + -r2 "$svnrepo"/trunk "$svnrepo"/junk) && + git config --add svn-remote.svn.fetch \ junk:refs/remotes/svn/junk && - git-svn fetch -i svn/thunk && - git-svn fetch -i svn/junk && - test -z \"\`git diff svn/junk svn/trunk\`\" && - test \"\`git merge-base svn/junk svn/trunk\`\" \ - = \"\`git rev-parse svn/trunk\`\" - " - -test_expect_success 'follow larger parent' " + git svn fetch -i svn/thunk && + git svn fetch -i svn/junk && + test -z "`git diff svn/junk svn/trunk`" && + test "`git merge-base svn/junk svn/trunk`" \ + = "`git rev-parse svn/trunk`" + ' + +test_expect_success 'follow larger parent' ' mkdir -p import/trunk/thunk/bump/thud && echo hi > import/trunk/thunk/bump/thud/file && - svn import -m 'import a larger parent' import $svnrepo/larger-parent && - svn cp -m 'hi' $svnrepo/larger-parent $svnrepo/another-larger && - git-svn init -i larger $svnrepo/another-larger/trunk/thunk/bump/thud && - git-svn fetch -i larger && - git-rev-parse --verify refs/remotes/larger && - git-rev-parse --verify \ + svn import -m "import a larger parent" import "$svnrepo"/larger-parent && + svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger && + git svn init --minimize-url -i larger \ + "$svnrepo"/another-larger/trunk/thunk/bump/thud && + git svn fetch -i larger && + git rev-parse --verify refs/remotes/larger && + git rev-parse --verify \ refs/remotes/larger-parent/trunk/thunk/bump/thud && - test \"\`git-merge-base \ + test "`git merge-base \ refs/remotes/larger-parent/trunk/thunk/bump/thud \ - refs/remotes/larger\`\" = \ - \"\`git-rev-parse refs/remotes/larger\`\" + refs/remotes/larger`" = \ + "`git rev-parse refs/remotes/larger`" true - " + ' -test_expect_success 'follow higher-level parent' " - svn mkdir -m 'follow higher-level parent' $svnrepo/blob && - svn co $svnrepo/blob blob && +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' && + 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 -i blob $svnrepo/glob/blob && - git-svn fetch -i blob - " - -test_expect_success 'follow deleted directory' " - svn mv -m 'bye!' $svnrepo/glob/blob/hi $svnrepo/glob/blob/bye && - svn rm -m 'remove glob' $svnrepo/glob && - git-svn init -i glob $svnrepo/glob && - git-svn fetch -i glob && - test \"\`git cat-file blob refs/remotes/glob:blob/bye\`\" = hi && - test \"\`git ls-tree refs/remotes/glob | wc -l \`\" -eq 1 - " + 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 + ' + +test_expect_success 'follow deleted directory' ' + svn_cmd mv -m "bye!" "$svnrepo"/glob/blob/hi "$svnrepo"/glob/blob/bye && + svn_cmd rm -m "remove glob" "$svnrepo"/glob && + git svn init --minimize-url -i glob "$svnrepo"/glob && + git svn fetch -i glob && + test "`git cat-file blob refs/remotes/glob:blob/bye`" = hi && + test "`git ls-tree refs/remotes/glob | wc -l `" -eq 1 + ' # ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn) # in trunk/subversion/bindings/swig/perl -test_expect_success 'follow-parent avoids deleting relevant info' " +test_expect_success 'follow-parent avoids deleting relevant info' ' mkdir -p import/trunk/subversion/bindings/swig/perl/t && for i in a b c ; do \ - echo \$i > import/trunk/subversion/bindings/swig/perl/\$i.pm && - echo _\$i > import/trunk/subversion/bindings/swig/perl/t/\$i.t; \ + echo $i > import/trunk/subversion/bindings/swig/perl/$i.pm && + echo _$i > import/trunk/subversion/bindings/swig/perl/t/$i.t; \ done && - echo 'bad delete test' > \ + echo "bad delete test" > \ import/trunk/subversion/bindings/swig/perl/t/larger-parent && - echo 'bad delete test 2' > \ + echo "bad delete test 2" > \ import/trunk/subversion/bindings/swig/perl/another-larger && cd import && - svn import -m 'r9270 test' . $svnrepo/r9270 && + svn import -m "r9270 test" . "$svnrepo"/r9270 && cd .. && - svn co $svnrepo/r9270/trunk/subversion/bindings/swig/perl 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 && + 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' && + svn commit -m "reorg test" && cd .. && - git-svn init -i r9270-t \ - $svnrepo/r9270/trunk/subversion/bindings/swig/perl/native/t && - git-svn fetch -i r9270-t && - test \`git rev-list r9270-t | wc -l\` -eq 2 && - test \"\`git ls-tree --name-only r9270-t~1\`\" = \ - \"\`git ls-tree --name-only r9270-t\`\" - " + git svn init --minimize-url -i r9270-t \ + "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl/native/t && + git svn fetch -i r9270-t && + test `git rev-list r9270-t | wc -l` -eq 2 && + test "`git ls-tree --name-only r9270-t~1`" = \ + "`git ls-tree --name-only r9270-t`" + ' -test_expect_success "track initial change if it was only made to parent" " - svn cp -m 'wheee!' $svnrepo/r9270/trunk $svnrepo/r9270/drunk && - git-svn init -i r9270-d \ - $svnrepo/r9270/drunk/subversion/bindings/swig/perl/native/t && - git-svn fetch -i r9270-d && - test \`git rev-list r9270-d | wc -l\` -eq 3 && - test \"\`git ls-tree --name-only r9270-t\`\" = \ - \"\`git ls-tree --name-only r9270-d\`\" && - test \"\`git rev-parse r9270-t\`\" = \ - \"\`git rev-parse r9270-d~1\`\" - " +test_expect_success "track initial change if it was only made to parent" ' + svn_cmd cp -m "wheee!" "$svnrepo"/r9270/trunk "$svnrepo"/r9270/drunk && + git svn init --minimize-url -i r9270-d \ + "$svnrepo"/r9270/drunk/subversion/bindings/swig/perl/native/t && + git svn fetch -i r9270-d && + test `git rev-list r9270-d | wc -l` -eq 3 && + test "`git ls-tree --name-only r9270-t`" = \ + "`git ls-tree --name-only r9270-d`" && + test "`git rev-parse r9270-t`" = \ + "`git rev-parse r9270-d~1`" + ' -test_expect_success "track multi-parent paths" " - svn cp -m 'resurrect /glob' $svnrepo/r9270 $svnrepo/glob && - git-svn multi-fetch && - test \`git cat-file commit refs/remotes/glob | \ - grep '^parent ' | wc -l\` -eq 2 - " +test_expect_success "follow-parent is atomic" ' + ( + cd wc && + svn_cmd up && + svn_cmd mkdir stunk && + echo "trunk stunk" > stunk/readme && + svn_cmd add stunk/readme && + svn_cmd ci -m "trunk stunk" && + echo "stunk like junk" >> stunk/readme && + svn_cmd ci -m "really stunk" && + echo "stink stank stunk" >> stunk/readme && + svn_cmd ci -m "even the grinch agrees" + ) && + svn_cmd copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk && + { svn cp -m "early stunk flunked too" \ + "$svnrepo"/stunk@17 "$svnrepo"/flunked || + svn_cmd cp -m "early stunk flunked too" \ + -r17 "$svnrepo"/stunk "$svnrepo"/flunked; } && + git svn init --minimize-url -i stunk "$svnrepo"/stunk && + git svn fetch -i stunk && + git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 && + git update-ref -d refs/remotes/stunk && + git config --unset svn-remote.svn.fetch stunk && + mkdir -p "$GIT_DIR"/svn/refs/remotes/flunk@18 && + rev_map=$(cd "$GIT_DIR"/svn/refs/remotes/stunk && ls .rev_map*) && + dd if="$GIT_DIR"/svn/refs/remotes/stunk/$rev_map \ + of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=24 count=1 && + rm -rf "$GIT_DIR"/svn/refs/remotes/stunk && + git svn init --minimize-url -i flunk "$svnrepo"/flunk && + git svn fetch -i flunk && + git svn init --minimize-url -i stunk "$svnrepo"/stunk && + git svn fetch -i stunk && + git svn init --minimize-url -i flunked "$svnrepo"/flunked && + git svn fetch -i flunked + test "`git rev-parse --verify refs/remotes/flunk@18`" \ + = "`git rev-parse --verify refs/remotes/stunk`" && + test "`git rev-parse --verify refs/remotes/flunk~1`" \ + = "`git rev-parse --verify refs/remotes/stunk`" && + test "`git rev-parse --verify refs/remotes/flunked~1`" \ + = "`git rev-parse --verify refs/remotes/stunk~1`" + ' + +test_expect_success "track multi-parent paths" ' + svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob && + git svn multi-fetch && + test `git cat-file commit refs/remotes/glob | \ + grep "^parent " | wc -l` -eq 2 + ' test_expect_success "multi-fetch continues to work" " - git-svn multi-fetch + git svn multi-fetch " -test_expect_success "multi-fetch works off a 'clean' repository" " - rm -r $GIT_DIR/svn $GIT_DIR/refs/remotes $GIT_DIR/logs && - mkdir $GIT_DIR/svn && - git-svn multi-fetch - " +test_expect_success "multi-fetch works off a 'clean' repository" ' + rm -r "$GIT_DIR/svn" "$GIT_DIR/refs/remotes" "$GIT_DIR/logs" && + mkdir "$GIT_DIR/svn" && + git svn multi-fetch + ' test_debug 'gitk --all &' diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh index c668dd1270..dd48e9cba8 100755 --- a/t/t9105-git-svn-commit-diff.sh +++ b/t/t9105-git-svn-commit-diff.sh @@ -1,21 +1,21 @@ #!/bin/sh # # Copyright (c) 2006 Eric Wong -test_description='git-svn commit-diff' +test_description='git svn commit-diff' . ./lib-git-svn.sh -test_expect_success 'initialize repo' " +test_expect_success 'initialize repo' ' mkdir import && cd import && echo hello > readme && - svn import -m 'initial' . $svnrepo && + svn_cmd import -m "initial" . "$svnrepo" && cd .. && echo hello > readme && git update-index --add readme && - git commit -a -m 'initial' && + git commit -a -m "initial" && echo world >> readme && - git commit -a -m 'another' - " + git commit -a -m "another" + ' head=`git rev-parse --verify HEAD^0` prev=`git rev-parse --verify HEAD^1` @@ -24,20 +24,20 @@ prev=`git rev-parse --verify HEAD^1` # commit, so only a basic test of functionality is needed since we've # already tested commit extensively elsewhere -test_expect_success 'test the commit-diff command' " - test -n '$prev' && test -n '$head' && - git-svn commit-diff -r1 '$prev' '$head' '$svnrepo' && - svn co $svnrepo wc && +test_expect_success 'test the commit-diff command' ' + test -n "$prev" && test -n "$head" && + git svn commit-diff -r1 "$prev" "$head" "$svnrepo" && + svn_cmd co "$svnrepo" wc && cmp readme wc/readme - " + ' -test_expect_success 'commit-diff to a sub-directory (with git-svn config)' " - svn import -m 'sub-directory' import $svnrepo/subdir && - git-svn init $svnrepo/subdir && - git-svn fetch && - git-svn commit-diff -r3 '$prev' '$head' && - svn cat $svnrepo/subdir/readme > readme.2 && +test_expect_success 'commit-diff to a sub-directory (with git svn config)' ' + svn_cmd import -m "sub-directory" import "$svnrepo"/subdir && + git svn init --minimize-url "$svnrepo"/subdir && + git svn fetch && + git svn commit-diff -r3 "$prev" "$head" && + svn_cmd cat "$svnrepo"/subdir/readme > readme.2 && cmp readme readme.2 - " + ' test_done diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh index 6f132f2419..12f21b700e 100755 --- a/t/t9106-git-svn-commit-diff-clobber.sh +++ b/t/t9106-git-svn-commit-diff-clobber.sh @@ -1,69 +1,101 @@ #!/bin/sh # # Copyright (c) 2006 Eric Wong -test_description='git-svn commit-diff clobber' +test_description='git svn commit-diff clobber' . ./lib-git-svn.sh -test_expect_success 'initialize repo' " +test_expect_success 'initialize repo' ' mkdir import && cd import && echo initial > file && - svn import -m 'initial' . $svnrepo && + svn_cmd import -m "initial" . "$svnrepo" && cd .. && echo initial > file && git update-index --add file && - git commit -a -m 'initial' - " -test_expect_success 'commit change from svn side' " - svn co $svnrepo t.svn && + 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 commit -m 'second line from svn' && + svn_cmd commit -m "second line from svn" && cd .. && rm -rf t.svn - " + ' -test_expect_failure 'commit conflicting change from git' " +test_expect_success 'commit conflicting change from git' ' echo second line from git >> file && - git commit -a -m 'second line from git' && - git-svn commit-diff -r1 HEAD~1 HEAD $svnrepo - " || true + git commit -a -m "second line from git" && + test_must_fail git svn commit-diff -r1 HEAD~1 HEAD "$svnrepo" +' -test_expect_success 'commit complementing change from git' " +test_expect_success 'commit complementing change from git' ' git reset --hard HEAD~1 && echo second line from svn >> file && - git commit -a -m 'second line from svn' && + git commit -a -m "second line from svn" && echo third line from git >> file && - git commit -a -m 'third line from git' && - git-svn commit-diff -r2 HEAD~1 HEAD $svnrepo - " + git commit -a -m "third line from git" && + git svn commit-diff -r2 HEAD~1 HEAD "$svnrepo" + ' -test_expect_failure 'dcommit fails to commit because of conflict' " - git-svn init $svnrepo && - git-svn fetch && - git reset --hard refs/remotes/git-svn && - svn co $svnrepo t.svn && +test_expect_success 'dcommit fails to commit because of conflict' ' + git svn init "$svnrepo" && + 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 commit -m 'fourth line from svn' && + svn_cmd commit -m "fourth line from svn" && cd .. && rm -rf t.svn && - echo 'fourth line from git' >> file && - git commit -a -m 'fourth line from git' && - git-svn dcommit - " || true + echo "fourth line from git" >> file && + git commit -a -m "fourth line from git" && + test_must_fail git svn dcommit + ' test_expect_success 'dcommit does the svn equivalent of an index merge' " - git reset --hard refs/remotes/git-svn && + git reset --hard refs/${remotes_git_svn} && echo 'index merge' > file2 && git update-index --add file2 && git commit -a -m 'index merge' && echo 'more changes' >> file2 && git update-index file2 && git commit -a -m 'more changes' && - git-svn dcommit + git svn dcommit + " + +test_expect_success 'commit another change from svn side' ' + svn_cmd co "$svnrepo" t.svn && + cd t.svn && + echo third line from svn >> file && + poke file && + svn_cmd commit -m "third line from svn" && + cd .. && + rm -rf t.svn + ' + +test_expect_success 'multiple dcommit from git svn will not clobber svn' " + git reset --hard refs/${remotes_git_svn} && + echo new file >> new-file && + git update-index --add new-file && + git commit -a -m 'new file' && + echo clobber > file && + git commit -a -m 'clobber' && + test_must_fail git svn dcommit + " + + +test_expect_success 'check that rebase really failed' ' + test -d .git/rebase-apply +' + +test_expect_success 'resolve, continue the rebase and dcommit' " + echo clobber and I really mean it > file && + git update-index file && + git rebase --continue && + git svn dcommit " test_done diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index dc2afdaa45..901b8e09fb 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -1,67 +1,73 @@ #!/bin/sh # Copyright (c) 2006 Eric Wong -test_description='git-svn metadata migrations from previous versions' +test_description='git svn metadata migrations from previous versions' . ./lib-git-svn.sh -test_expect_success 'setup old-looking metadata' " - cp $GIT_DIR/config $GIT_DIR/config-old-git-svn && +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 + mkdir -p $i && \ + echo hello >> $i/README || exit 1 done && \ - svn import -m test . $svnrepo + svn_cmd import -m test . "$svnrepo" cd .. && - git-svn init $svnrepo && - git-svn fetch && - mv $GIT_DIR/svn/* $GIT_DIR/ && - mv $GIT_DIR/svn/.metadata $GIT_DIR/ && - rmdir $GIT_DIR/svn && - git-update-ref refs/heads/git-svn-HEAD refs/remotes/git-svn && - git-update-ref refs/heads/svn-HEAD refs/remotes/git-svn && - git-update-ref -d refs/remotes/git-svn refs/remotes/git-svn - " + git svn init "$svnrepo" && + git svn fetch && + rm -rf "$GIT_DIR"/svn && + git update-ref refs/heads/git-svn-HEAD refs/${remotes_git_svn} && + git update-ref refs/heads/svn-HEAD refs/${remotes_git_svn} && + git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn} + ' head=`git rev-parse --verify refs/heads/git-svn-HEAD^0` test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'" -test_expect_success 'initialize old-style (v0) git-svn layout' " - mkdir -p $GIT_DIR/git-svn/info $GIT_DIR/svn/info && - echo $svnrepo > $GIT_DIR/git-svn/info/url && - echo $svnrepo > $GIT_DIR/svn/info/url && - git-svn migrate && - ! test -d $GIT_DIR/git-svn && - git-rev-parse --verify refs/remotes/git-svn^0 && - git-rev-parse --verify refs/remotes/svn^0 && - test \`git config --get svn-remote.svn.url\` = '$svnrepo' && - test \`git config --get svn-remote.svn.fetch\` = \ - ':refs/remotes/git-svn' - " +test_expect_success 'initialize old-style (v0) git svn layout' ' + mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info && + echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url && + echo "$svnrepo" > "$GIT_DIR"/svn/info/url && + git svn migrate && + ! test -d "$GIT_DIR"/git svn && + git rev-parse --verify refs/${remotes_git_svn}^0 && + git rev-parse --verify refs/remotes/svn^0 && + test "$(git config --get svn-remote.svn.url)" = "$svnrepo" && + test `git config --get svn-remote.svn.fetch` = \ + ":refs/${remotes_git_svn}" + ' -test_expect_success 'initialize a multi-repository repo' " - git-svn init $svnrepo -T trunk -t tags -b branches && - git-config --get-all svn-remote.svn.fetch > fetch.out && - grep '^trunk:refs/remotes/trunk$' fetch.out && - test -n \"\`git-config --get svn-remote.svn.branches \ - '^branches/\*:refs/remotes/\*$'\`\" && - test -n \"\`git-config --get svn-remote.svn.tags \ - '^tags/\*:refs/remotes/tags/\*$'\`\" && +test_expect_success 'initialize a multi-repository repo' ' + git svn init "$svnrepo" -T trunk -t tags -b branches && + git config --get-all svn-remote.svn.fetch > fetch.out && + grep "^trunk:refs/remotes/trunk$" fetch.out && + test -n "`git config --get svn-remote.svn.branches \ + "^branches/\*:refs/remotes/\*$"`" && + test -n "`git config --get svn-remote.svn.tags \ + "^tags/\*:refs/remotes/tags/\*$"`" && git config --unset svn-remote.svn.branches \ - '^branches/\*:refs/remotes/\*$' && + "^branches/\*:refs/remotes/\*$" && git config --unset svn-remote.svn.tags \ - '^tags/\*:refs/remotes/tags/\*$' && - git-config --add svn-remote.svn.fetch 'branches/a:refs/remotes/a' && - git-config --add svn-remote.svn.fetch 'branches/b:refs/remotes/b' && + "^tags/\*:refs/remotes/tags/\*$" && + git config --add svn-remote.svn.fetch "branches/a:refs/remotes/a" && + git config --add svn-remote.svn.fetch "branches/b:refs/remotes/b" && for i in tags/0.1 tags/0.2 tags/0.3; do - git-config --add svn-remote.svn.fetch \ - \$i:refs/remotes/\$i || exit 1; done - " + git config --add svn-remote.svn.fetch \ + $i:refs/remotes/$i || exit 1; done && + git config --get-all svn-remote.svn.fetch > fetch.out && + grep "^trunk:refs/remotes/trunk$" fetch.out && + grep "^branches/a:refs/remotes/a$" fetch.out && + grep "^branches/b:refs/remotes/b$" fetch.out && + grep "^tags/0\.1:refs/remotes/tags/0\.1$" fetch.out && + grep "^tags/0\.2:refs/remotes/tags/0\.2$" fetch.out && + grep "^tags/0\.3:refs/remotes/tags/0\.3$" fetch.out && + grep "^:refs/${remotes_git_svn}" fetch.out + ' # refs should all be different, but the trees should all be the same: test_expect_success 'multi-fetch works on partial urls + paths' " - git-svn multi-fetch && + git svn multi-fetch && for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do git rev-parse --verify refs/remotes/\$i^0 >> refs.out || exit 1; done && @@ -73,40 +79,43 @@ test_expect_success 'multi-fetch works on partial urls + paths' " refs/remotes/\$j\`\" ||exit 1; done; done " -test_expect_success 'migrate --minimize on old inited layout' " +test_expect_success 'migrate --minimize on old inited layout' ' git config --unset-all svn-remote.svn.fetch && git config --unset-all svn-remote.svn.url && - rm -rf $GIT_DIR/svn && - for i in \`cat fetch.out\`; do - path=\`expr \$i : '\\([^:]*\\):.*$'\` - ref=\`expr \$i : '[^:]*:refs/remotes/\\(.*\\)$'\` - if test -z \"\$ref\"; then continue; fi - if test -n \"\$path\"; then path=\"/\$path\"; fi - ( mkdir -p $GIT_DIR/svn/\$ref/info/ && - echo $svnrepo\$path > $GIT_DIR/svn/\$ref/info/url ) || exit 1; + rm -rf "$GIT_DIR"/svn && + for i in `cat fetch.out`; do + path=`expr $i : "\([^:]*\):.*$"` + ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"` + if test -z "$ref"; then continue; fi + if test -n "$path"; then path="/$path"; fi + ( mkdir -p "$GIT_DIR"/svn/$ref/info/ && + echo "$svnrepo"$path > "$GIT_DIR"/svn/$ref/info/url ) || exit 1; done && - git-svn migrate --minimize && - test -z \"\`git-config -l |grep -v '^svn-remote\.git-svn\.'\`\" && - git-config --get-all svn-remote.svn.fetch > fetch.out && - grep '^trunk:refs/remotes/trunk$' fetch.out && - grep '^branches/a:refs/remotes/a$' fetch.out && - grep '^branches/b:refs/remotes/b$' fetch.out && - grep '^tags/0\.1:refs/remotes/tags/0\.1$' fetch.out && - grep '^tags/0\.2:refs/remotes/tags/0\.2$' fetch.out && - grep '^tags/0\.3:refs/remotes/tags/0\.3$' fetch.out - grep '^:refs/remotes/git-svn' fetch.out - " + git svn migrate --minimize && + test -z "`git config -l | grep "^svn-remote\.git-svn\."`" && + git config --get-all svn-remote.svn.fetch > fetch.out && + grep "^trunk:refs/remotes/trunk$" fetch.out && + grep "^branches/a:refs/remotes/a$" fetch.out && + grep "^branches/b:refs/remotes/b$" fetch.out && + grep "^tags/0\.1:refs/remotes/tags/0\.1$" fetch.out && + grep "^tags/0\.2:refs/remotes/tags/0\.2$" fetch.out && + grep "^tags/0\.3:refs/remotes/tags/0\.3$" fetch.out && + grep "^:refs/${remotes_git_svn}" fetch.out + ' -test_expect_success ".rev_db auto-converted to .rev_db.UUID" " - git-svn fetch -i trunk && - expect=$GIT_DIR/svn/trunk/.rev_db.* && - test -n \"\$expect\" && - mv \$expect $GIT_DIR/svn/trunk/.rev_db && - git-svn fetch -i trunk && - test -L $GIT_DIR/svn/trunk/.rev_db && - test -f \$expect && - cmp \$expect $GIT_DIR/svn/trunk/.rev_db - " +test_expect_success ".rev_db auto-converted to .rev_map.UUID" ' + git svn fetch -i trunk && + test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" && + expect="$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_map.*)" && + test -n "$expect" && + rev_db="$(echo $expect | sed -e "s,_map,_db,")" && + convert_to_rev_db "$expect" "$rev_db" && + rm -f "$expect" && + test -f "$rev_db" && + git svn fetch -i trunk && + test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" && + test ! -e "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db && + test -f "$expect" + ' test_done - diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh index db4344cc84..d732d31302 100755 --- a/t/t9108-git-svn-glob.sh +++ b/t/t9108-git-svn-glob.sh @@ -1,6 +1,6 @@ #!/bin/sh # Copyright (c) 2007 Eric Wong -test_description='git-svn globbing refspecs' +test_description='git svn globbing refspecs' . ./lib-git-svn.sh cat > expect.end <<EOF @@ -10,77 +10,102 @@ start a new branch initial EOF -test_expect_success 'test refspec globbing' " +test_expect_success 'test refspec globbing' ' mkdir -p trunk/src/a trunk/src/b trunk/doc && - echo 'hello world' > trunk/src/a/readme && - echo 'goodbye world' > trunk/src/b/readme && - svn import -m 'initial' trunk $svnrepo/trunk && - svn co $svnrepo tmp && - cd tmp && + echo "hello world" > trunk/src/a/readme && + echo "goodbye world" > trunk/src/b/readme && + svn_cmd import -m "initial" trunk "$svnrepo"/trunk && + svn_cmd co "$svnrepo" tmp && + ( + cd tmp && mkdir branches tags && - svn add branches tags && - svn cp trunk branches/start && - svn commit -m 'start a new branch' && - svn up && - echo 'hi' >> branches/start/src/b/readme && + svn_cmd add branches tags && + svn_cmd cp trunk branches/start && + svn_cmd commit -m "start a new branch" && + svn_cmd up && + echo "hi" >> branches/start/src/b/readme && poke branches/start/src/b/readme && - echo 'hey' >> branches/start/src/a/readme && + echo "hey" >> branches/start/src/a/readme && poke branches/start/src/a/readme && - svn commit -m 'hi' && - svn up && - svn cp branches/start tags/end && - echo 'bye' >> tags/end/src/b/readme && + svn_cmd commit -m "hi" && + svn_cmd up && + svn_cmd cp branches/start tags/end && + echo "bye" >> tags/end/src/b/readme && poke tags/end/src/b/readme && - echo 'aye' >> tags/end/src/a/readme && + echo "aye" >> tags/end/src/a/readme && poke tags/end/src/a/readme && - svn commit -m 'the end' && - echo 'byebye' >> tags/end/src/b/readme && + svn_cmd commit -m "the end" && + echo "byebye" >> tags/end/src/b/readme && poke tags/end/src/b/readme && - svn commit -m 'nothing to see here' - cd .. && - git config --add svn-remote.svn.url $svnrepo && + svn_cmd commit -m "nothing to see here" + ) && + git config --add svn-remote.svn.url "$svnrepo" && git config --add svn-remote.svn.fetch \ - 'trunk/src/a:refs/remotes/trunk' && + "trunk/src/a:refs/remotes/trunk" && git config --add svn-remote.svn.branches \ - 'branches/*/src/a:refs/remotes/branches/*' && + "branches/*/src/a:refs/remotes/branches/*" && git config --add svn-remote.svn.tags\ - 'tags/*/src/a:refs/remotes/tags/*' && - git-svn multi-fetch && + "tags/*/src/a:refs/remotes/tags/*" && + git svn multi-fetch && git log --pretty=oneline refs/remotes/tags/end | \ - sed -e 's/^.\{41\}//' > output.end && - cmp expect.end output.end && - test \"\`git rev-parse refs/remotes/tags/end~1\`\" = \ - \"\`git rev-parse refs/remotes/branches/start\`\" && - test \"\`git rev-parse refs/remotes/branches/start~2\`\" = \ - \"\`git rev-parse refs/remotes/trunk\`\" - " + sed -e "s/^.\{41\}//" > output.end && + test_cmp expect.end output.end && + test "`git rev-parse refs/remotes/tags/end~1`" = \ + "`git rev-parse refs/remotes/branches/start`" && + test "`git rev-parse refs/remotes/branches/start~2`" = \ + "`git rev-parse refs/remotes/trunk`" && + test_must_fail git rev-parse refs/remotes/tags/end@3 + ' echo try to try > expect.two echo nothing to see here >> expect.two cat expect.end >> expect.two -test_expect_success 'test left-hand-side only globbing' " - git config --add svn-remote.two.url $svnrepo && +test_expect_success 'test left-hand-side only globbing' ' + git config --add svn-remote.two.url "$svnrepo" && git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk && git config --add svn-remote.two.branches \ - 'branches/*:refs/remotes/two/branches/*' && + "branches/*:refs/remotes/two/branches/*" && git config --add svn-remote.two.tags \ - 'tags/*:refs/remotes/two/tags/*' && - cd tmp && - echo 'try try' >> tags/end/src/b/readme && + "tags/*:refs/remotes/two/tags/*" && + ( + cd tmp && + echo "try try" >> tags/end/src/b/readme && poke tags/end/src/b/readme && - svn commit -m 'try to try' - cd .. && - git-svn fetch two && - test \`git rev-list refs/remotes/two/tags/end | wc -l\` -eq 6 && - test \`git rev-list refs/remotes/two/branches/start | wc -l\` -eq 3 && - test \`git rev-parse refs/remotes/two/branches/start~2\` = \ - \`git rev-parse refs/remotes/two/trunk\` && - test \`git rev-parse refs/remotes/two/tags/end~3\` = \ - \`git rev-parse refs/remotes/two/branches/start\` && + svn_cmd commit -m "try to try" + ) && + git svn fetch two && + test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 && + test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 && + test `git rev-parse refs/remotes/two/branches/start~2` = \ + `git rev-parse refs/remotes/two/trunk` && + test `git rev-parse refs/remotes/two/tags/end~3` = \ + `git rev-parse refs/remotes/two/branches/start` && git log --pretty=oneline refs/remotes/two/tags/end | \ - sed -e 's/^.\{41\}//' > output.two && - cmp expect.two output.two - " + sed -e "s/^.\{41\}//" > output.two && + test_cmp expect.two output.two + ' + +echo "Only one set of wildcard directories" \ + "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three +echo "" >> expect.three + +test_expect_success 'test disallow multi-globs' ' + git config --add svn-remote.three.url "$svnrepo" && + git config --add svn-remote.three.fetch \ + trunk:refs/remotes/three/trunk && + git config --add svn-remote.three.branches \ + "branches/*/t/*:refs/remotes/three/branches/*" && + git config --add svn-remote.three.tags \ + "tags/*/*:refs/remotes/three/tags/*" && + ( + cd tmp && + echo "try try" >> tags/end/src/b/readme && + poke tags/end/src/b/readme && + svn_cmd commit -m "try to try" + ) && + test_must_fail git svn fetch three 2> stderr.three && + test_cmp expect.three stderr.three + ' test_done diff --git a/t/t9109-git-svn-multi-glob.sh b/t/t9109-git-svn-multi-glob.sh new file mode 100755 index 0000000000..c318f9f946 --- /dev/null +++ b/t/t9109-git-svn-multi-glob.sh @@ -0,0 +1,160 @@ +#!/bin/sh +# Copyright (c) 2007 Eric Wong +test_description='git svn globbing refspecs' +. ./lib-git-svn.sh + +cat > expect.end <<EOF +the end +hi +start a new branch +initial +EOF + +test_expect_success 'test refspec globbing' ' + mkdir -p trunk/src/a trunk/src/b trunk/doc && + echo "hello world" > trunk/src/a/readme && + echo "goodbye world" > trunk/src/b/readme && + svn_cmd import -m "initial" trunk "$svnrepo"/trunk && + svn_cmd co "$svnrepo" tmp && + ( + cd tmp && + mkdir branches branches/v1 tags && + svn_cmd add branches tags && + svn_cmd cp trunk branches/v1/start && + svn_cmd commit -m "start a new branch" && + svn_cmd up && + echo "hi" >> branches/v1/start/src/b/readme && + poke branches/v1/start/src/b/readme && + echo "hey" >> branches/v1/start/src/a/readme && + poke branches/v1/start/src/a/readme && + svn_cmd commit -m "hi" && + svn_cmd up && + svn_cmd cp branches/v1/start tags/end && + echo "bye" >> tags/end/src/b/readme && + poke tags/end/src/b/readme && + echo "aye" >> tags/end/src/a/readme && + poke tags/end/src/a/readme && + svn_cmd commit -m "the end" && + echo "byebye" >> tags/end/src/b/readme && + poke tags/end/src/b/readme && + svn_cmd commit -m "nothing to see here" + ) && + git config --add svn-remote.svn.url "$svnrepo" && + git config --add svn-remote.svn.fetch \ + "trunk/src/a:refs/remotes/trunk" && + git config --add svn-remote.svn.branches \ + "branches/*/*/src/a:refs/remotes/branches/*/*" && + git config --add svn-remote.svn.tags\ + "tags/*/src/a:refs/remotes/tags/*" && + git svn multi-fetch && + git log --pretty=oneline refs/remotes/tags/end | \ + sed -e "s/^.\{41\}//" > output.end && + test_cmp expect.end output.end && + test "`git rev-parse refs/remotes/tags/end~1`" = \ + "`git rev-parse refs/remotes/branches/v1/start`" && + test "`git rev-parse refs/remotes/branches/v1/start~2`" = \ + "`git rev-parse refs/remotes/trunk`" && + test_must_fail git rev-parse refs/remotes/tags/end@3 + ' + +echo try to try > expect.two +echo nothing to see here >> expect.two +cat expect.end >> expect.two + +test_expect_success 'test left-hand-side only globbing' ' + git config --add svn-remote.two.url "$svnrepo" && + git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk && + git config --add svn-remote.two.branches \ + "branches/*/*:refs/remotes/two/branches/*/*" && + git config --add svn-remote.two.tags \ + "tags/*:refs/remotes/two/tags/*" && + ( + cd tmp && + echo "try try" >> tags/end/src/b/readme && + poke tags/end/src/b/readme && + svn_cmd commit -m "try to try" + ) && + git svn fetch two && + test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 && + test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 && + test `git rev-parse refs/remotes/two/branches/v1/start~2` = \ + `git rev-parse refs/remotes/two/trunk` && + test `git rev-parse refs/remotes/two/tags/end~3` = \ + `git rev-parse refs/remotes/two/branches/v1/start` && + git log --pretty=oneline refs/remotes/two/tags/end | \ + sed -e "s/^.\{41\}//" > output.two && + test_cmp expect.two output.two + ' +cat > expect.four <<EOF +adios +adding more +Changed 2 in v2/start +Another versioned branch +initial +EOF + +test_expect_success 'test another branch' ' + ( + cd tmp && + mkdir branches/v2 && + svn_cmd add branches/v2 && + svn_cmd cp trunk branches/v2/start && + svn_cmd commit -m "Another versioned branch" && + svn_cmd up && + echo "hello" >> branches/v2/start/src/b/readme && + poke branches/v2/start/src/b/readme && + echo "howdy" >> branches/v2/start/src/a/readme && + poke branches/v2/start/src/a/readme && + svn_cmd commit -m "Changed 2 in v2/start" && + svn_cmd up && + svn_cmd cp branches/v2/start tags/next && + echo "bye" >> tags/next/src/b/readme && + poke tags/next/src/b/readme && + echo "aye" >> tags/next/src/a/readme && + poke tags/next/src/a/readme && + svn_cmd commit -m "adding more" && + echo "byebye" >> tags/next/src/b/readme && + poke tags/next/src/b/readme && + svn_cmd commit -m "adios" + ) && + git config --add svn-remote.four.url "$svnrepo" && + git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk && + git config --add svn-remote.four.branches \ + "branches/*/*:refs/remotes/four/branches/*/*" && + git config --add svn-remote.four.tags \ + "tags/*:refs/remotes/four/tags/*" && + git svn fetch four && + test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 && + test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 && + test `git rev-parse refs/remotes/four/branches/v2/start~2` = \ + `git rev-parse refs/remotes/four/trunk` && + test `git rev-parse refs/remotes/four/tags/next~2` = \ + `git rev-parse refs/remotes/four/branches/v2/start` && + git log --pretty=oneline refs/remotes/four/tags/next | \ + sed -e "s/^.\{41\}//" > output.four && + test_cmp expect.four output.four + ' + +echo "Only one set of wildcard directories" \ + "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three +echo "" >> expect.three + +test_expect_success 'test disallow multiple globs' ' + git config --add svn-remote.three.url "$svnrepo" && + git config --add svn-remote.three.fetch \ + trunk:refs/remotes/three/trunk && + git config --add svn-remote.three.branches \ + "branches/*/t/*:refs/remotes/three/branches/*/*" && + git config --add svn-remote.three.tags \ + "tags/*:refs/remotes/three/tags/*" && + ( + cd tmp && + echo "try try" >> tags/end/src/b/readme && + poke tags/end/src/b/readme && + svn_cmd commit -m "try to try" + ) && + test_must_fail git svn fetch three 2> stderr.three && + test_cmp expect.three stderr.three + ' + +test_done diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh index 9db0d8fd8d..a06e4c5b8e 100755 --- a/t/t9110-git-svn-use-svm-props.sh +++ b/t/t9110-git-svn-use-svm-props.sh @@ -3,49 +3,59 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn useSvmProps test' +test_description='git svn useSvmProps test' . ./lib-git-svn.sh -test_expect_success 'load svm repo' " - svnadmin load -q $rawsvnrepo < ../t9110/svm.dump && - git-svn init -R arr -i bar $svnrepo/mirror/arr && - git-svn init -R argh -i dir $svnrepo/mirror/argh && - git-svn init -R argh -i e $svnrepo/mirror/argh/a/b/c/d/e && - git-config svn.useSvmProps true && - git-svn fetch --all - " +test_expect_success 'load svm repo' ' + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9110/svm.dump && + git svn init --minimize-url -R arr -i bar "$svnrepo"/mirror/arr && + git svn init --minimize-url -R argh -i dir "$svnrepo"/mirror/argh && + git svn init --minimize-url -R argh -i e \ + "$svnrepo"/mirror/argh/a/b/c/d/e && + git config svn.useSvmProps true && + git svn fetch --all + ' uuid=161ce429-a9dd-4828-af4a-52023f968c89 bar_url=http://mayonaise/svnrepo/bar test_expect_success 'verify metadata for /bar' " - git-cat-file commit refs/remotes/bar | \ - grep '^git-svn-id: $bar_url@12 $uuid$' && - git-cat-file commit refs/remotes/bar~1 | \ - grep '^git-svn-id: $bar_url@11 $uuid$' && - git-cat-file commit refs/remotes/bar~2 | \ - grep '^git-svn-id: $bar_url@10 $uuid$' && - git-cat-file commit refs/remotes/bar~3 | \ - grep '^git-svn-id: $bar_url@9 $uuid$' && - git-cat-file commit refs/remotes/bar~4 | \ - grep '^git-svn-id: $bar_url@6 $uuid$' && - git-cat-file commit refs/remotes/bar~5 | \ - grep '^git-svn-id: $bar_url@1 $uuid$' + git cat-file commit refs/remotes/bar | \ + grep '^${git_svn_id}: $bar_url@12 $uuid$' && + git cat-file commit refs/remotes/bar~1 | \ + grep '^${git_svn_id}: $bar_url@11 $uuid$' && + git cat-file commit refs/remotes/bar~2 | \ + grep '^${git_svn_id}: $bar_url@10 $uuid$' && + git cat-file commit refs/remotes/bar~3 | \ + grep '^${git_svn_id}: $bar_url@9 $uuid$' && + git cat-file commit refs/remotes/bar~4 | \ + grep '^${git_svn_id}: $bar_url@6 $uuid$' && + git cat-file commit refs/remotes/bar~5 | \ + grep '^${git_svn_id}: $bar_url@1 $uuid$' " e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e test_expect_success 'verify metadata for /dir/a/b/c/d/e' " - git-cat-file commit refs/remotes/e | \ - grep '^git-svn-id: $e_url@1 $uuid$' + git cat-file commit refs/remotes/e | \ + grep '^${git_svn_id}: $e_url@1 $uuid$' " dir_url=http://mayonaise/svnrepo/dir test_expect_success 'verify metadata for /dir' " - git-cat-file commit refs/remotes/dir | \ - grep '^git-svn-id: $dir_url@2 $uuid$' && - git-cat-file commit refs/remotes/dir~1 | \ - grep '^git-svn-id: $dir_url@1 $uuid$' + git cat-file commit refs/remotes/dir | \ + grep '^${git_svn_id}: $dir_url@2 $uuid$' && + git cat-file commit refs/remotes/dir~1 | \ + grep '^${git_svn_id}: $dir_url@1 $uuid$' + " + +test_expect_success 'find commit based on SVN revision number' " + git svn find-rev r12 | + grep `git rev-parse HEAD` + " + +test_expect_success 'empty rebase' " + git svn rebase " test_done diff --git a/t/t9111-git-svn-use-svnsync-props.sh b/t/t9111-git-svn-use-svnsync-props.sh index 483d7f8159..bd081c2ec3 100755 --- a/t/t9111-git-svn-use-svnsync-props.sh +++ b/t/t9111-git-svn-use-svnsync-props.sh @@ -3,49 +3,49 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn useSvnsyncProps test' +test_description='git svn useSvnsyncProps test' . ./lib-git-svn.sh -test_expect_success 'load svnsync repo' " - svnadmin load -q $rawsvnrepo < ../t9111/svnsync.dump && - git-svn init -R arr -i bar $svnrepo/bar && - git-svn init -R argh -i dir $svnrepo/dir && - git-svn init -R argh -i e $svnrepo/dir/a/b/c/d/e && - git-config svn.useSvnsyncProps true && - git-svn fetch --all - " +test_expect_success 'load svnsync repo' ' + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9111/svnsync.dump && + git svn init --minimize-url -R arr -i bar "$svnrepo"/bar && + git svn init --minimize-url -R argh -i dir "$svnrepo"/dir && + git svn init --minimize-url -R argh -i e "$svnrepo"/dir/a/b/c/d/e && + git config svn.useSvnsyncProps true && + git svn fetch --all + ' uuid=161ce429-a9dd-4828-af4a-52023f968c89 bar_url=http://mayonaise/svnrepo/bar test_expect_success 'verify metadata for /bar' " - git-cat-file commit refs/remotes/bar | \ - grep '^git-svn-id: $bar_url@12 $uuid$' && - git-cat-file commit refs/remotes/bar~1 | \ - grep '^git-svn-id: $bar_url@11 $uuid$' && - git-cat-file commit refs/remotes/bar~2 | \ - grep '^git-svn-id: $bar_url@10 $uuid$' && - git-cat-file commit refs/remotes/bar~3 | \ - grep '^git-svn-id: $bar_url@9 $uuid$' && - git-cat-file commit refs/remotes/bar~4 | \ - grep '^git-svn-id: $bar_url@6 $uuid$' && - git-cat-file commit refs/remotes/bar~5 | \ - grep '^git-svn-id: $bar_url@1 $uuid$' + git cat-file commit refs/remotes/bar | \ + grep '^${git_svn_id}: $bar_url@12 $uuid$' && + git cat-file commit refs/remotes/bar~1 | \ + grep '^${git_svn_id}: $bar_url@11 $uuid$' && + git cat-file commit refs/remotes/bar~2 | \ + grep '^${git_svn_id}: $bar_url@10 $uuid$' && + git cat-file commit refs/remotes/bar~3 | \ + grep '^${git_svn_id}: $bar_url@9 $uuid$' && + git cat-file commit refs/remotes/bar~4 | \ + grep '^${git_svn_id}: $bar_url@6 $uuid$' && + git cat-file commit refs/remotes/bar~5 | \ + grep '^${git_svn_id}: $bar_url@1 $uuid$' " e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e test_expect_success 'verify metadata for /dir/a/b/c/d/e' " - git-cat-file commit refs/remotes/e | \ - grep '^git-svn-id: $e_url@1 $uuid$' + git cat-file commit refs/remotes/e | \ + grep '^${git_svn_id}: $e_url@1 $uuid$' " dir_url=http://mayonaise/svnrepo/dir test_expect_success 'verify metadata for /dir' " - git-cat-file commit refs/remotes/dir | \ - grep '^git-svn-id: $dir_url@2 $uuid$' && - git-cat-file commit refs/remotes/dir~1 | \ - grep '^git-svn-id: $dir_url@1 $uuid$' + git cat-file commit refs/remotes/dir | \ + grep '^${git_svn_id}: $dir_url@2 $uuid$' && + git cat-file commit refs/remotes/dir~1 | \ + grep '^${git_svn_id}: $dir_url@1 $uuid$' " test_done diff --git a/t/t9111/svnsync.dump b/t/t9111/svnsync.dump index a9a46eeb29..499fa9594f 100644 --- a/t/t9111/svnsync.dump +++ b/t/t9111/svnsync.dump @@ -558,5 +558,3 @@ Text-content-md5: 7abb78de7f2756ca8b511cbc879fd5e7 Content-length: 4 cba - - diff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh new file mode 100755 index 0000000000..a61d6716d2 --- /dev/null +++ b/t/t9112-git-svn-md5less-file.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +test_description='test that git handles an svn repository with missing md5sums' + +. ./lib-git-svn.sh + +# Loading a node from a svn dumpfile without a Text-Content-Length +# field causes svn to neglect to store or report an md5sum. (it will +# calculate one if you had put Text-Content-Length: 0). This showed +# up in a repository creted with cvs2svn. + +cat > dumpfile.svn <<EOF +SVN-fs-dump-format-version: 1 + +Revision-number: 1 +Prop-content-length: 98 +Content-length: 98 + +K 7 +svn:log +V 0 + +K 10 +svn:author +V 4 +test +K 8 +svn:date +V 27 +2007-05-06T12:37:01.153339Z +PROPS-END + +Node-path: md5less-file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + +EOF + +test_expect_success 'load svn dumpfile' 'svnadmin load "$rawsvnrepo" < dumpfile.svn' + +test_expect_success 'initialize git svn' 'git svn init "$svnrepo"' +test_expect_success 'fetch revisions from svn' 'git svn fetch' +test_done diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh new file mode 100755 index 0000000000..e8479cec7a --- /dev/null +++ b/t/t9113-git-svn-dcommit-new-file.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +# Don't run this test by default unless the user really wants it +# I don't like the idea of taking a port and possibly leaving a +# daemon running on a users system if the test fails. +# Not all git users will need to interact with SVN. + +test_description='git svn dcommit new files over svn:// test' + +. ./lib-git-svn.sh + +require_svnserve + +test_expect_success 'start tracking an empty repo' ' + svn_cmd mkdir -m "empty dir" "$svnrepo"/empty-dir && + echo "[general]" > "$rawsvnrepo"/conf/svnserve.conf && + echo anon-access = write >> "$rawsvnrepo"/conf/svnserve.conf && + start_svnserve && + git svn init svn://127.0.0.1:$SVNSERVE_PORT && + git svn fetch + ' + +test_expect_success 'create files in new directory with dcommit' " + mkdir git-new-dir && + echo hello > git-new-dir/world && + git update-index --add git-new-dir/world && + git commit -m hello && + start_svnserve && + git svn dcommit + " + +test_done diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh new file mode 100755 index 0000000000..84f7c9b4bb --- /dev/null +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -0,0 +1,94 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# Based on a script by Joakim Tjernlund <joakim.tjernlund@transmode.se> + +test_description='git svn dcommit handles merges' + +. ./lib-git-svn.sh + +big_text_block () { +cat << EOF +# +# (C) Copyright 2000 - 2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +EOF +} + +test_expect_success 'setup svn repository' ' + svn_cmd co "$svnrepo" mysvnwork && + mkdir -p mysvnwork/trunk && + cd mysvnwork && + big_text_block >> trunk/README && + svn_cmd add trunk && + svn_cmd ci -m "first commit" trunk && + cd .. + ' + +test_expect_success 'setup git mirror and merge' ' + git svn init "$svnrepo" -t tags -T trunk -b branches && + git svn fetch && + git checkout --track -b svn remotes/trunk && + git checkout -b merge && + echo new file > new_file && + git add new_file && + git commit -a -m "New file" && + echo hello >> README && + git commit -a -m "hello" && + echo add some stuff >> new_file && + git commit -a -m "add some stuff" && + git checkout svn && + mv -f README tmp && + echo friend > README && + cat tmp >> README && + git commit -a -m "friend" && + git pull . merge + ' + +test_debug 'gitk --all & sleep 1' + +test_expect_success 'verify pre-merge ancestry' " + test x\`git rev-parse --verify refs/heads/svn^2\` = \ + x\`git rev-parse --verify refs/heads/merge\` && + git cat-file commit refs/heads/svn^ | grep '^friend$' + " + +test_expect_success 'git svn dcommit merges' " + git svn dcommit + " + +test_debug 'gitk --all & sleep 1' + +test_expect_success 'verify post-merge ancestry' " + test x\`git rev-parse --verify refs/heads/svn\` = \ + x\`git rev-parse --verify refs/remotes/trunk \` && + test x\`git rev-parse --verify refs/heads/svn^2\` = \ + x\`git rev-parse --verify refs/heads/merge\` && + git cat-file commit refs/heads/svn^ | grep '^friend$' + " + +test_expect_success 'verify merge commit message' " + git rev-list --pretty=raw -1 refs/heads/svn | \ + grep \" Merge branch 'merge' into svn\" + " + +test_done diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh new file mode 100755 index 0000000000..767799e7a7 --- /dev/null +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong + + +test_description='git svn dcommit can commit renames of files with ugly names' + +. ./lib-git-svn.sh + +test_expect_success 'load repository with strange names' ' + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump && + start_httpd gtk+ + ' + +test_expect_success 'init and fetch repository' ' + git svn init "$svnrepo" && + git svn fetch && + git reset --hard git-svn + ' + +test_expect_success 'create file in existing ugly and empty dir' ' + mkdir -p "#{bad_directory_name}" && + echo hi > "#{bad_directory_name}/ foo" && + git update-index --add "#{bad_directory_name}/ foo" && + git commit -m "new file in ugly parent" && + git svn dcommit + ' + +test_expect_success 'rename ugly file' ' + git mv "#{bad_directory_name}/ foo" "file name with feces" && + git commit -m "rename ugly file" && + git svn dcommit + ' + +test_expect_success 'rename pretty file' ' + echo :x > pretty && + git update-index --add pretty && + git commit -m "pretty :x" && + git svn dcommit && + mkdir -p regular_dir_name && + git mv pretty regular_dir_name/pretty && + git commit -m "moved pretty file" && + git svn dcommit + ' + +test_expect_success 'rename pretty file into ugly one' ' + git mv regular_dir_name/pretty "#{bad_directory_name}/ booboo" && + git commit -m booboo && + git svn dcommit + ' + +test_expect_success 'add a file with plus signs' ' + echo .. > +_+ && + git update-index --add +_+ && + git commit -m plus && + mkdir gtk+ && + git mv +_+ gtk+/_+_ && + git commit -m plus_dir && + git svn dcommit + ' + +test_expect_success 'clone the repository to test rebase' ' + git svn clone "$svnrepo" test-rebase && + cd test-rebase && + echo test-rebase > test-rebase && + git add test-rebase && + git commit -m test-rebase && + cd .. + ' + +test_expect_success 'make a commit to test rebase' ' + echo test-rebase-main > test-rebase-main && + git add test-rebase-main && + git commit -m test-rebase-main && + git svn dcommit + ' + +test_expect_success 'git svn rebase works inside a fresh-cloned repository' ' + cd test-rebase && + git svn rebase && + test -e test-rebase-main && + test -e test-rebase + ' + +stop_httpd + +test_done diff --git a/t/t9115/funky-names.dump b/t/t9115/funky-names.dump new file mode 100644 index 0000000000..42422f791e --- /dev/null +++ b/t/t9115/funky-names.dump @@ -0,0 +1,103 @@ +SVN-fs-dump-format-version: 2 + +UUID: 819c44fe-2bcc-4066-88e4-985e2bc0b418 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2007-07-12T07:54:26.062914Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 152 +Content-length: 152 + +K 7 +svn:log +V 44 +what will those wacky people think of next? + +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2007-07-12T08:00:05.011573Z +PROPS-END + +Node-path: leading space +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: leading space file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 5 +Text-content-md5: e4fa20c67542cdc21271e08d329397ab +Content-length: 15 + +PROPS-END +ugly + + +Node-path: #{bad_directory_name} +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: #{cool_name} +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 18 +Text-content-md5: 87dac40ca337dfa3dcc8911388c3ddda +Content-length: 28 + +PROPS-END +strange name here + + +Node-path: dir name with spaces +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: file name with spaces +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 7 +Text-content-md5: c1f10cfd640618484a2a475c11410fd3 +Content-length: 17 + +PROPS-END +spaces + + +Node-path: regular_dir_name +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh new file mode 100755 index 0000000000..0374a7476b --- /dev/null +++ b/t/t9116-git-svn-log.sh @@ -0,0 +1,128 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +test_description='git svn log tests' +. ./lib-git-svn.sh + +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 && \ + svn_cmd import -m test . "$svnrepo" + cd .. && + git svn init "$svnrepo" -T trunk -b branches -t tags && + git svn fetch && + git reset --hard trunk && + echo bye >> README && + git commit -a -m bye && + git svn dcommit && + git reset --hard a && + echo why >> FEEDME && + git update-index --add FEEDME && + git commit -m feedme && + git svn dcommit && + git reset --hard trunk && + echo aye >> README && + git commit -a -m aye && + git svn dcommit && + git reset --hard b && + echo spy >> README && + git commit -a -m spy && + echo try >> README && + git commit -a -m try && + git svn dcommit + ' + +test_expect_success 'run log' " + git reset --hard a && + git svn log -r2 trunk | grep ^r2 && + git svn log -r4 trunk | grep ^r4 && + git svn log -r3 | grep ^r3 + " + +test_expect_success 'run log against a from trunk' " + git reset --hard trunk && + git svn log -r3 a | grep ^r3 + " + +printf 'r1 \nr2 \nr4 \n' > expected-range-r1-r2-r4 + +test_expect_success 'test ascending revision range' " + git reset --hard trunk && + git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 - + " + +printf 'r4 \nr2 \nr1 \n' > expected-range-r4-r2-r1 + +test_expect_success 'test descending revision range' " + git reset --hard trunk && + git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4-r2-r1 - + " + +printf 'r1 \nr2 \n' > expected-range-r1-r2 + +test_expect_success 'test ascending revision range with unreachable revision' " + git reset --hard trunk && + git svn log -r 1:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2 - + " + +printf 'r2 \nr1 \n' > expected-range-r2-r1 + +test_expect_success 'test descending revision range with unreachable revision' " + git reset --hard trunk && + git svn log -r 3:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2-r1 - + " + +printf 'r2 \n' > expected-range-r2 + +test_expect_success 'test ascending revision range with unreachable upper boundary revision and 1 commit' " + git reset --hard trunk && + git svn log -r 2:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 - + " + +test_expect_success 'test descending revision range with unreachable upper boundary revision and 1 commit' " + git reset --hard trunk && + git svn log -r 3:2 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 - + " + +printf 'r4 \n' > expected-range-r4 + +test_expect_success 'test ascending revision range with unreachable lower boundary revision and 1 commit' " + git reset --hard trunk && + git svn log -r 3:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 - + " + +test_expect_success 'test descending revision range with unreachable lower boundary revision and 1 commit' " + git reset --hard trunk && + git svn log -r 4:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 - + " + +printf -- '------------------------------------------------------------------------\n' > expected-separator + +test_expect_success 'test ascending revision range with unreachable boundary revisions and no commits' " + git reset --hard trunk && + git svn log -r 5:6 | test_cmp expected-separator - + " + +test_expect_success 'test descending revision range with unreachable boundary revisions and no commits' " + git reset --hard trunk && + git svn log -r 6:5 | test_cmp expected-separator - + " + +test_expect_success 'test ascending revision range with unreachable boundary revisions and 1 commit' " + git reset --hard trunk && + git svn log -r 3:5 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 - + " + +test_expect_success 'test descending revision range with unreachable boundary revisions and 1 commit' " + git reset --hard trunk && + git svn log -r 5:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 - + " + +test_done diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh new file mode 100755 index 0000000000..b7ef9e2589 --- /dev/null +++ b/t/t9117-git-svn-init-clone.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +test_description='git svn init/clone tests' + +. ./lib-git-svn.sh + +# setup, run inside tmp so we don't have any conflicts with $svnrepo +set -e +rm -r .git +mkdir tmp +cd tmp + +test_expect_success 'setup svnrepo' ' + mkdir project project/trunk project/branches project/tags && + echo foo > project/trunk/foo && + svn_cmd import -m "$test_description" project "$svnrepo"/project && + rm -rf project + ' + +test_expect_success 'basic clone' ' + test ! -d trunk && + git svn clone "$svnrepo"/project/trunk && + test -d trunk/.git/svn && + test -e trunk/foo && + rm -rf trunk + ' + +test_expect_success 'clone to target directory' ' + test ! -d target && + git svn clone "$svnrepo"/project/trunk target && + test -d target/.git/svn && + test -e target/foo && + rm -rf target + ' + +test_expect_success 'clone with --stdlayout' ' + test ! -d project && + git svn clone -s "$svnrepo"/project && + test -d project/.git/svn && + test -e project/foo && + rm -rf project + ' + +test_expect_success 'clone to target directory with --stdlayout' ' + test ! -d target && + git svn clone -s "$svnrepo"/project target && + test -d target/.git/svn && + test -e target/foo && + rm -rf target + ' + +test_done diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh new file mode 100755 index 0000000000..63fc982c8c --- /dev/null +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -0,0 +1,81 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +test_description='git svn funky branch names' +. ./lib-git-svn.sh + +# Abo-Uebernahme (Bug #994) +scary_uri='Abo-Uebernahme%20%28Bug%20%23994%29' +scary_ref='Abo-Uebernahme%20(Bug%20#994)' + +test_expect_success 'setup svnrepo' ' + mkdir project project/trunk project/branches project/tags && + echo foo > project/trunk/foo && + svn_cmd import -m "$test_description" project "$svnrepo/pr ject" && + rm -rf project && + svn_cmd cp -m "fun" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/fun plugin" && + svn_cmd cp -m "more fun!" "$svnrepo/pr ject/branches/fun plugin" \ + "$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 && + git rev-parse "refs/remotes/fun%20plugin" && + git rev-parse "refs/remotes/more%20fun%20plugin!" && + git rev-parse "refs/remotes/$scary_ref" && + 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 + ) + " + +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 + ) + ' + +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 + +test_done diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh new file mode 100755 index 0000000000..5fb94fb3d6 --- /dev/null +++ b/t/t9119-git-svn-info.sh @@ -0,0 +1,378 @@ +#!/bin/sh +# +# Copyright (c) 2007 David D. Kilzer + +test_description='git svn info' + +. ./lib-git-svn.sh + +# Tested with: svn, version 1.4.4 (r25188) +# Tested with: svn, version 1.6.[12345689] +v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'` +case $v in +1.[456].*) + ;; +*) + skip_all="skipping svn-info test (SVN version: $v not supported)" + test_done + ;; +esac + +ptouch() { + perl -w -e ' + use strict; + use POSIX qw(mktime); + die "ptouch requires exactly 2 arguments" if @ARGV != 2; + my $text_last_updated = shift @ARGV; + my $git_file = shift @ARGV; + die "\"$git_file\" does not exist" if ! -e $git_file; + if ($text_last_updated + =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) { + my $mtime = mktime($6, $5, $4, $3, $2 - 1, $1 - 1900); + my $atime = $mtime; + utime $atime, $mtime, $git_file; + } + ' "`svn_cmd info $2 | grep '^Text Last Updated:'`" "$1" +} + +quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')" + +test_expect_success 'setup repository and import' ' + mkdir info && + 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 co "$svnrepo" svnwc && + cd svnwc && + echo foo > foo && + svn_cmd add foo && + svn_cmd commit -m "change outside directory" && + svn_cmd update && + cd .. && + mkdir gitwc && + cd gitwc && + git svn init "$svnrepo" && + git svn fetch && + cd .. && + ptouch gitwc/file svnwc/file && + ptouch gitwc/directory svnwc/directory && + ptouch gitwc/symlink-file svnwc/symlink-file && + ptouch gitwc/symlink-directory svnwc/symlink-directory + ' + +test_expect_success 'info' " + (cd svnwc; svn info) > expected.info && + (cd gitwc; git svn info) > actual.info && + test_cmp expected.info actual.info + " + +test_expect_success 'info --url' ' + test "$(cd gitwc; git svn info --url)" = "$quoted_svnrepo" + ' + +test_expect_success 'info .' " + (cd svnwc; svn info .) > expected.info-dot && + (cd gitwc; git svn info .) > actual.info-dot && + test_cmp expected.info-dot actual.info-dot + " + +test_expect_success 'info --url .' ' + test "$(cd gitwc; git svn info --url .)" = "$quoted_svnrepo" + ' + +test_expect_success 'info file' " + (cd svnwc; svn info file) > expected.info-file && + (cd gitwc; git svn info file) > actual.info-file && + test_cmp expected.info-file actual.info-file + " + +test_expect_success 'info --url file' ' + test "$(cd gitwc; git svn info --url file)" = "$quoted_svnrepo/file" + ' + +test_expect_success 'info directory' " + (cd svnwc; svn info directory) > expected.info-directory && + (cd gitwc; git svn info directory) > actual.info-directory && + test_cmp expected.info-directory actual.info-directory + " + +test_expect_success 'info inside directory' " + (cd svnwc/directory; svn info) > expected.info-inside-directory && + (cd gitwc/directory; git svn info) > actual.info-inside-directory && + test_cmp expected.info-inside-directory actual.info-inside-directory + " + +test_expect_success 'info --url directory' ' + test "$(cd gitwc; git svn info --url directory)" = "$quoted_svnrepo/directory" + ' + +test_expect_success 'info symlink-file' " + (cd svnwc; svn info symlink-file) > expected.info-symlink-file && + (cd gitwc; git svn info symlink-file) > actual.info-symlink-file && + test_cmp expected.info-symlink-file actual.info-symlink-file + " + +test_expect_success 'info --url symlink-file' ' + test "$(cd gitwc; git svn info --url symlink-file)" \ + = "$quoted_svnrepo/symlink-file" + ' + +test_expect_success 'info symlink-directory' " + (cd svnwc; svn info symlink-directory) \ + > expected.info-symlink-directory && + (cd gitwc; git svn info symlink-directory) \ + > actual.info-symlink-directory && + test_cmp expected.info-symlink-directory actual.info-symlink-directory + " + +test_expect_success 'info --url symlink-directory' ' + test "$(cd gitwc; git svn info --url symlink-directory)" \ + = "$quoted_svnrepo/symlink-directory" + ' + +test_expect_success 'info added-file' " + echo two > gitwc/added-file && + cd gitwc && + git add added-file && + cd .. && + 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 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 + " + +test_expect_success 'info --url added-file' ' + test "$(cd gitwc; git svn info --url added-file)" \ + = "$quoted_svnrepo/added-file" + ' + +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 info added-directory) \ + > expected.info-added-directory && + (cd gitwc; git svn info added-directory) \ + > actual.info-added-directory && + test_cmp expected.info-added-directory actual.info-added-directory + " + +test_expect_success 'info --url added-directory' ' + test "$(cd gitwc; git svn info --url added-directory)" \ + = "$quoted_svnrepo/added-directory" + ' + +test_expect_success 'info added-symlink-file' " + cd gitwc && + ln -s added-file added-symlink-file && + git add added-symlink-file && + cd .. && + cd svnwc && + ln -s added-file added-symlink-file && + svn_cmd add added-symlink-file > /dev/null && + cd .. && + ptouch gitwc/added-symlink-file svnwc/added-symlink-file && + (cd svnwc; svn info added-symlink-file) \ + > expected.info-added-symlink-file && + (cd gitwc; git svn info added-symlink-file) \ + > actual.info-added-symlink-file && + test_cmp expected.info-added-symlink-file \ + actual.info-added-symlink-file + " + +test_expect_success 'info --url added-symlink-file' ' + test "$(cd gitwc; git svn info --url added-symlink-file)" \ + = "$quoted_svnrepo/added-symlink-file" + ' + +test_expect_success 'info added-symlink-directory' " + cd gitwc && + ln -s added-directory added-symlink-directory && + git add added-symlink-directory && + cd .. && + cd svnwc && + ln -s added-directory added-symlink-directory && + svn_cmd add added-symlink-directory > /dev/null && + cd .. && + ptouch gitwc/added-symlink-directory svnwc/added-symlink-directory && + (cd svnwc; svn info added-symlink-directory) \ + > expected.info-added-symlink-directory && + (cd gitwc; git svn info added-symlink-directory) \ + > actual.info-added-symlink-directory && + test_cmp expected.info-added-symlink-directory \ + actual.info-added-symlink-directory + " + +test_expect_success 'info --url added-symlink-directory' ' + test "$(cd gitwc; git svn info --url added-symlink-directory)" \ + = "$quoted_svnrepo/added-symlink-directory" + ' + +# The next few tests replace the "Text Last Updated" value with a +# placeholder since git doesn't have a way to know the date that a +# now-deleted file was last checked out locally. Internally it +# 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 svnwc; svn info file) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > expected.info-deleted-file && + (cd gitwc; git svn info file) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > actual.info-deleted-file && + test_cmp expected.info-deleted-file actual.info-deleted-file + " + +test_expect_success 'info --url file (deleted)' ' + test "$(cd gitwc; git svn info --url file)" \ + = "$quoted_svnrepo/file" + ' + +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 svnwc; svn info directory) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > expected.info-deleted-directory && + (cd gitwc; git svn info directory) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > actual.info-deleted-directory && + test_cmp expected.info-deleted-directory actual.info-deleted-directory + " + +test_expect_success 'info --url directory (deleted)' ' + test "$(cd gitwc; git svn info --url directory)" \ + = "$quoted_svnrepo/directory" + ' + +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 svnwc; svn info symlink-file) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > expected.info-deleted-symlink-file && + (cd gitwc; git svn info symlink-file) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > actual.info-deleted-symlink-file && + test_cmp expected.info-deleted-symlink-file \ + actual.info-deleted-symlink-file + " + +test_expect_success 'info --url symlink-file (deleted)' ' + test "$(cd gitwc; git svn info --url symlink-file)" \ + = "$quoted_svnrepo/symlink-file" + ' + +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 svnwc; svn info symlink-directory) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > expected.info-deleted-symlink-directory && + (cd gitwc; git svn info symlink-directory) | + sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ + > actual.info-deleted-symlink-directory && + test_cmp expected.info-deleted-symlink-directory \ + actual.info-deleted-symlink-directory + " + +test_expect_success 'info --url symlink-directory (deleted)' ' + test "$(cd gitwc; git svn info --url symlink-directory)" \ + = "$quoted_svnrepo/symlink-directory" + ' + +# NOTE: git does not have the concept of replaced objects, +# so we can't test for files in that state. + +test_expect_success 'info unknown-file' " + echo two > gitwc/unknown-file && + (cd gitwc; test_must_fail git svn info unknown-file) \ + 2> actual.info-unknown-file && + grep unknown-file actual.info-unknown-file + " + +test_expect_success 'info --url unknown-file' ' + echo two > gitwc/unknown-file && + (cd gitwc; test_must_fail git svn info --url unknown-file) \ + 2> actual.info-url-unknown-file && + grep unknown-file actual.info-url-unknown-file + ' + +test_expect_success 'info unknown-directory' " + mkdir gitwc/unknown-directory svnwc/unknown-directory && + (cd gitwc; test_must_fail git svn info unknown-directory) \ + 2> actual.info-unknown-directory && + grep unknown-directory actual.info-unknown-directory + " + +test_expect_success 'info --url unknown-directory' ' + (cd gitwc; test_must_fail git svn info --url unknown-directory) \ + 2> actual.info-url-unknown-directory && + grep unknown-directory actual.info-url-unknown-directory + ' + +test_expect_success 'info unknown-symlink-file' " + cd gitwc && + ln -s unknown-file unknown-symlink-file && + cd .. && + (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 + " + +test_expect_success 'info --url unknown-symlink-file' ' + (cd gitwc; test_must_fail git svn info --url unknown-symlink-file) \ + 2> actual.info-url-unknown-symlink-file && + grep unknown-symlink-file actual.info-url-unknown-symlink-file + ' + +test_expect_success 'info unknown-symlink-directory' " + cd gitwc && + ln -s unknown-directory unknown-symlink-directory && + cd .. && + (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 + " + +test_expect_success 'info --url unknown-symlink-directory' ' + (cd gitwc; test_must_fail git svn info --url unknown-symlink-directory) \ + 2> actual.info-url-unknown-symlink-directory && + grep unknown-symlink-directory actual.info-url-unknown-symlink-directory + ' + +test_done diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh new file mode 100755 index 0000000000..9d9ebd533c --- /dev/null +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -0,0 +1,78 @@ +#!/bin/sh +# +# Copyright (c) 2008 Kevin Ballard +# + +test_description='git svn clone with percent escapes' +. ./lib-git-svn.sh + +test_expect_success 'setup svnrepo' ' + mkdir project project/trunk project/branches project/tags && + echo foo > project/trunk/foo && + svn_cmd import -m "$test_description" project "$svnrepo/pr ject" && + svn_cmd cp -m "branch" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/b" && + svn_cmd cp -m "tag" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/tags/v1" && + rm -rf project && + start_httpd +' + +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 .. +' + +# SVN works either way, so should we... + +test_expect_success 'svn checkout with percent escapes' ' + svn_cmd checkout "$svnrepo/pr%20ject" svn.percent && + svn_cmd checkout "$svnrepo/pr%20ject/trunk" svn.percent.trunk +' + +test_expect_success 'svn checkout with space' ' + svn_cmd checkout "$svnrepo/pr ject" svn.space && + svn_cmd checkout "$svnrepo/pr ject/trunk" svn.space.trunk +' + +test_expect_success 'test clone trunk with percent escapes and minimize-url' ' + git svn clone --minimize-url "$svnrepo/pr%20ject/trunk" minimize && + ( + cd minimize && + git rev-parse refs/${remotes_git_svn} + ) +' + +test_expect_success 'test clone trunk with percent escapes' ' + git svn clone "$svnrepo/pr%20ject/trunk" trunk && + ( + cd trunk && + git rev-parse refs/${remotes_git_svn} + ) +' + +test_expect_success 'test clone --stdlayout with percent escapes' ' + git svn clone --stdlayout "$svnrepo/pr%20ject" percent && + ( + cd percent && + git rev-parse refs/remotes/trunk^0 && + git rev-parse refs/remotes/b^0 && + git rev-parse refs/remotes/tags/v1^0 + ) +' + +test_expect_success 'test clone -s with unescaped space' ' + git svn clone -s "$svnrepo/pr ject" space && + ( + cd space && + git rev-parse refs/remotes/trunk^0 && + git rev-parse refs/remotes/b^0 && + git rev-parse refs/remotes/tags/v1^0 + ) +' + +stop_httpd + +test_done diff --git a/t/t9121-git-svn-fetch-renamed-dir.sh b/t/t9121-git-svn-fetch-renamed-dir.sh new file mode 100755 index 0000000000..000cad37c6 --- /dev/null +++ b/t/t9121-git-svn-fetch-renamed-dir.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Copyright (c) 2008 Santhosh Kumar Mani + + +test_description='git svn can fetch renamed directories' + +. ./lib-git-svn.sh + +test_expect_success 'load repository with renamed directory' ' + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9121/renamed-dir.dump + ' + +test_expect_success 'init and fetch repository' ' + git svn init "$svnrepo/newname" && + git svn fetch + ' + +test_done + diff --git a/t/t9121/renamed-dir.dump b/t/t9121/renamed-dir.dump new file mode 100644 index 0000000000..5f9127be92 --- /dev/null +++ b/t/t9121/renamed-dir.dump @@ -0,0 +1,90 @@ +SVN-fs-dump-format-version: 2 + +UUID: 06b9b3ad-f546-4fbe-8328-fcb4e6ef5c3f + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-04-02T09:11:59.778557Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 14 +initial import +K 10 +svn:author +V 8 +santhosh +K 8 +svn:date +V 27 +2008-04-02T09:13:03.170863Z +PROPS-END + +Node-path: name +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: name/a.txt +Node-kind: file +Node-action: add +Prop-content-length: 71 +Text-content-length: 6 +Text-content-md5: b1946ac92492d2347c6235b4d2611184 +Content-length: 77 + +K 13 +svn:mime-type +V 10 +text/plain +K 13 +svn:eol-style +V 2 +LF +PROPS-END +hello + + +Revision-number: 2 +Prop-content-length: 109 +Content-length: 109 + +K 7 +svn:log +V 7 +renamed +K 10 +svn:author +V 8 +santhosh +K 8 +svn:date +V 27 +2008-04-02T09:14:22.952186Z +PROPS-END + +Node-path: newname +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: name + + +Node-path: name +Node-action: delete + + diff --git a/t/t9122-git-svn-author.sh b/t/t9122-git-svn-author.sh new file mode 100755 index 0000000000..30013b7bb9 --- /dev/null +++ b/t/t9122-git-svn-author.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +test_description='git svn authorship' +. ./lib-git-svn.sh + +test_expect_success 'setup svn repository' ' + svn_cmd checkout "$svnrepo" work.svn && + ( + cd work.svn && + echo >file + svn_cmd add file + svn_cmd commit -m "first commit" file + ) +' + +test_expect_success 'interact with it via git svn' ' + mkdir work.git && + ( + cd work.git && + git svn init "$svnrepo" + git svn fetch && + + echo modification >file && + test_tick && + git commit -a -m second && + + test_tick && + git svn dcommit && + + echo "further modification" >file && + test_tick && + git commit -a -m third && + + test_tick && + git svn --add-author-from dcommit && + + echo "yet further modification" >file && + test_tick && + git commit -a -m fourth && + + test_tick && + git svn --add-author-from --use-log-author dcommit && + + git log && + + git show -s HEAD^^ >../actual.2 && + git show -s HEAD^ >../actual.3 && + git show -s HEAD >../actual.4 + + ) && + + # Make sure that --add-author-from without --use-log-author + # did not affect the authorship information + myself=$(grep "^Author: " actual.2) && + unaffected=$(grep "^Author: " actual.3) && + test "z$myself" = "z$unaffected" && + + # Make sure lack of --add-author-from did not add cruft + ! grep "^ From: A U Thor " actual.2 && + + # Make sure --add-author-from added cruft + grep "^ From: A U Thor " actual.3 && + grep "^ From: A U Thor " actual.4 && + + # Make sure --add-author-from with --use-log-author affected + # the authorship information + grep "^Author: A U Thor " actual.4 && + + # Make sure there are no commit messages with excess blank lines + test $(grep "^ " actual.2 | wc -l) = 3 && + test $(grep "^ " actual.3 | wc -l) = 5 && + test $(grep "^ " actual.4 | wc -l) = 5 && + + # Make sure there are no svn commit messages with excess blank lines + ( + cd work.svn && + svn_cmd up && + + test $(svn_cmd log -r2:2 | wc -l) = 5 && + test $(svn_cmd log -r4:4 | wc -l) = 7 + ) +' + +test_done diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh new file mode 100755 index 0000000000..045521615c --- /dev/null +++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright (c) 2008 Jan Krüger +# + +test_description='git svn respects rewriteRoot during rebuild' + +. ./lib-git-svn.sh + +mkdir 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' ' + git svn init --rewrite-root=http://invalid.invalid/ "$svnrepo" && + git svn fetch + git checkout -b mybranch ${remotes_git_svn} + ' + +test_expect_success 'remove rev_map' ' + rm "$GIT_SVN_DIR"/.rev_map.* + ' + +test_expect_success 'rebuild rev_map' ' + git svn rebase >/dev/null + ' + +test_done + diff --git a/t/t9124-git-svn-dcommit-auto-props.sh b/t/t9124-git-svn-dcommit-auto-props.sh new file mode 100755 index 0000000000..d6b076f6b7 --- /dev/null +++ b/t/t9124-git-svn-dcommit-auto-props.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# +# Copyright (c) 2008 Brad King + +test_description='git svn dcommit honors auto-props' + +. ./lib-git-svn.sh + +generate_auto_props() { +cat << EOF +[miscellany] +enable-auto-props=$1 +[auto-props] +*.sh = svn:mime-type=application/x-shellscript; svn:eol-style=LF +*.txt = svn:mime-type=text/plain; svn:eol-style = native +EOF +} + +test_expect_success 'initialize git svn' ' + mkdir import && + ( + cd import && + echo foo >foo && + svn_cmd import -m "import for git svn" . "$svnrepo" + ) && + rm -rf import && + git svn init "$svnrepo" + git svn fetch +' + +test_expect_success 'enable auto-props config' ' + mkdir user && + generate_auto_props yes >user/config +' + +test_expect_success 'add files matching auto-props' ' + echo "#!$SHELL_PATH" >exec1.sh && + chmod +x exec1.sh && + echo "hello" >hello.txt && + echo bar >bar && + git add exec1.sh hello.txt bar && + git commit -m "files for enabled auto-props" && + git svn dcommit --config-dir=user +' + +test_expect_success 'disable auto-props config' ' + generate_auto_props no >user/config +' + +test_expect_success 'add files matching disabled auto-props' ' + echo "#$SHELL_PATH" >exec2.sh && + chmod +x exec2.sh && + echo "world" >world.txt && + echo zot >zot && + git add exec2.sh world.txt zot && + git commit -m "files for disabled auto-props" && + git svn dcommit --config-dir=user +' + +test_expect_success 'check resulting svn repository' ' +( + mkdir work && + cd work && + svn_cmd co "$svnrepo" && + cd svnrepo && + + # Check properties from first commit. + test "x$(svn_cmd propget svn:executable exec1.sh)" = "x*" && + test "x$(svn_cmd propget svn:mime-type exec1.sh)" = \ + "xapplication/x-shellscript" && + test "x$(svn_cmd propget svn:mime-type hello.txt)" = "xtext/plain" && + test "x$(svn_cmd propget svn:eol-style hello.txt)" = "xnative" && + test "x$(svn_cmd propget svn:mime-type bar)" = "x" && + + # Check properties from second commit. + test "x$(svn_cmd propget svn:executable exec2.sh)" = "x*" && + test "x$(svn_cmd propget svn:mime-type exec2.sh)" = "x" && + test "x$(svn_cmd propget svn:mime-type world.txt)" = "x" && + test "x$(svn_cmd propget svn:eol-style world.txt)" = "x" && + test "x$(svn_cmd propget svn:mime-type zot)" = "x" +) +' + +test_expect_success 'check renamed file' ' + test -d user && + generate_auto_props yes > user/config && + git mv foo foo.sh && + git commit -m "foo => foo.sh" && + git svn dcommit --config-dir=user && + ( + cd work/svnrepo && + svn_cmd up && + test ! -e foo && + test -e foo.sh && + test "x$(svn_cmd propget svn:mime-type foo.sh)" = \ + "xapplication/x-shellscript" && + test "x$(svn_cmd propget svn:eol-style foo.sh)" = "xLF" + ) +' + +test_done diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh new file mode 100755 index 0000000000..c19418614f --- /dev/null +++ b/t/t9125-git-svn-multi-glob-branch-names.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Copyright (c) 2008 Marcus Griep + +test_description='git svn multi-glob branch names' +. ./lib-git-svn.sh + +test_expect_success 'setup svnrepo' ' + mkdir project project/trunk project/branches \ + project/branches/v14.1 project/tags && + echo foo > project/trunk/foo && + svn_cmd import -m "$test_description" project "$svnrepo/project" && + rm -rf project && + svn_cmd cp -m "fun" "$svnrepo/project/trunk" \ + "$svnrepo/project/branches/v14.1/beta" && + svn_cmd cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \ + "$svnrepo/project/branches/v14.1/gold" + ' + +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 && + git rev-parse "refs/remotes/v14.1/beta" && + git rev-parse "refs/remotes/v14.1/gold" && + cd .. + ' + +test_expect_success 'test dcommit to multi-globbed branch' " + cd project && + git reset --hard 'refs/remotes/v14.1/gold' && + echo hello >> foo && + git commit -m 'hello' -- foo && + git svn dcommit && + cd .. + " + +test_done diff --git a/t/t9126-git-svn-follow-deleted-readded-directory.sh b/t/t9126-git-svn-follow-deleted-readded-directory.sh new file mode 100755 index 0000000000..edec640e97 --- /dev/null +++ b/t/t9126-git-svn-follow-deleted-readded-directory.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Copyright (c) 2008 Alec Berryman + +test_description='git svn fetch repository with deleted and readded directory' + +. ./lib-git-svn.sh + +# Don't run this by default; it opens up a port. +require_svnserve + +test_expect_success 'load repository' ' + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9126/follow-deleted-readded.dump + ' + +test_expect_success 'fetch repository' ' + start_svnserve && + git svn init svn://127.0.0.1:$SVNSERVE_PORT && + git svn fetch + ' + +test_done diff --git a/t/t9126/follow-deleted-readded.dump b/t/t9126/follow-deleted-readded.dump new file mode 100644 index 0000000000..19da5d1ddc --- /dev/null +++ b/t/t9126/follow-deleted-readded.dump @@ -0,0 +1,201 @@ +SVN-fs-dump-format-version: 2 + +UUID: 1807dc6f-c693-4cda-9710-00e1be8c1f21 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-09-14T19:53:13.006748Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 12 +Create trunk +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:13.239689Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 119 +Content-length: 119 + +K 7 +svn:log +V 20 +Create trunk/project +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:13.548860Z +PROPS-END + +Node-path: trunk/project +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 3 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 12 +add new file +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:15.433630Z +PROPS-END + +Node-path: trunk/project/foo +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 4 +Text-content-md5: d3b07384d113edec49eaa6238ad5ff00 +Content-length: 14 + +PROPS-END +foo + + +Revision-number: 4 +Prop-content-length: 116 +Content-length: 116 + +K 7 +svn:log +V 17 +change foo to bar +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:17.339884Z +PROPS-END + +Node-path: trunk/project/foo +Node-kind: file +Node-action: change +Text-content-length: 4 +Text-content-md5: c157a79031e1c40f85931829bc5fc552 +Content-length: 4 + +bar + + +Revision-number: 5 +Prop-content-length: 114 +Content-length: 114 + +K 7 +svn:log +V 15 +don't like that +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:19.335001Z +PROPS-END + +Node-path: trunk/project +Node-action: delete + + +Revision-number: 6 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 11 +reset trunk +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:19.845897Z +PROPS-END + +Node-path: trunk/project +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 4 +Node-copyfrom-path: trunk/project + + +Revision-number: 7 +Prop-content-length: 113 +Content-length: 113 + +K 7 +svn:log +V 14 +change to quux +K 10 +svn:author +V 4 +alec +K 8 +svn:date +V 27 +2008-09-14T19:53:21.367947Z +PROPS-END + +Node-path: trunk/project/foo +Node-kind: file +Node-action: change +Text-content-length: 5 +Text-content-md5: d3b07a382ec010c01889250fce66fb13 +Content-length: 5 + +quux + + diff --git a/t/t9127-git-svn-partial-rebuild.sh b/t/t9127-git-svn-partial-rebuild.sh new file mode 100755 index 0000000000..4aab8ecc14 --- /dev/null +++ b/t/t9127-git-svn-partial-rebuild.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Copyright (c) 2008 Deskin Miller +# + +test_description='git svn partial-rebuild tests' +. ./lib-git-svn.sh + +test_expect_success 'initialize svnrepo' ' + mkdir import && + ( + cd import && + mkdir trunk branches tags && + cd trunk && + echo foo > foo && + cd .. && + svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null && + svn_cmd copy "$svnrepo"/trunk "$svnrepo"/branches/a \ + -m "created branch a" && + cd .. && + rm -rf import && + svn_cmd co "$svnrepo"/trunk trunk && + cd trunk && + echo bar >> foo && + svn_cmd ci -m "updated trunk" && + cd .. && + svn_cmd co "$svnrepo"/branches/a a && + cd a && + echo baz >> a && + svn_cmd add a && + svn_cmd ci -m "updated a" && + cd .. && + git svn init --stdlayout "$svnrepo" + ) +' + +test_expect_success 'import an early SVN revision into git' ' + git svn fetch -r1:2 +' + +test_expect_success 'make full git mirror of SVN' ' + mkdir mirror && + ( + cd mirror && + git init && + git svn init --stdlayout "$svnrepo" && + git svn fetch && + cd .. + ) +' + +test_expect_success 'fetch from git mirror and partial-rebuild' ' + git config --add remote.origin.url "file://$PWD/mirror/.git" && + git config --add remote.origin.fetch refs/remotes/*:refs/remotes/* && + git fetch origin && + git svn fetch +' + +test_done diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh new file mode 100755 index 0000000000..807e494a3a --- /dev/null +++ b/t/t9128-git-svn-cmd-branch.sh @@ -0,0 +1,78 @@ +#!/bin/sh +# +# Copyright (c) 2008 Deskin Miller +# + +test_description='git svn partial-rebuild tests' +. ./lib-git-svn.sh + +test_expect_success 'initialize svnrepo' ' + mkdir 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 .. && + rm -rf import && + svn_cmd co "$svnrepo"/trunk trunk && + cd trunk && + echo bar >> foo && + svn_cmd ci -m "updated trunk" && + cd .. && + rm -rf trunk + ) +' + +test_expect_success 'import into git' ' + git svn init --stdlayout "$svnrepo" && + git svn fetch && + git checkout remotes/trunk +' + +test_expect_success 'git svn branch tests' ' + git svn branch a && + base=$(git rev-parse HEAD:) && + test $base = $(git rev-parse remotes/a:) && + git svn branch -m "created branch b blah" b && + test $base = $(git rev-parse remotes/b:) && + test_must_fail git branch -m "no branchname" && + git svn branch -n c && + test_must_fail git rev-parse remotes/c && + test_must_fail git svn branch a && + git svn branch -t tag1 && + test $base = $(git rev-parse remotes/tags/tag1:) && + git svn branch --tag tag2 && + test $base = $(git rev-parse remotes/tags/tag2:) && + git svn tag tag3 && + test $base = $(git rev-parse remotes/tags/tag3:) && + git svn tag -m "created tag4 foo" tag4 && + test $base = $(git rev-parse remotes/tags/tag4:) && + test_must_fail git svn tag -m "no tagname" && + git svn tag -n tag5 && + test_must_fail git rev-parse remotes/tags/tag5 && + test_must_fail git svn tag tag1 +' + +test_expect_success 'branch uses correct svn-remote' ' + (svn_cmd co "$svnrepo" svn && + cd svn && + mkdir mirror && + svn_cmd add mirror && + svn_cmd copy trunk mirror/ && + svn_cmd copy tags mirror/ && + svn_cmd copy branches mirror/ && + svn_cmd ci -m "made mirror" ) && + rm -rf svn && + git svn init -s -R mirror --prefix=mirror/ "$svnrepo"/mirror && + git svn fetch -R mirror && + git checkout mirror/trunk && + base=$(git rev-parse HEAD:) && + git svn branch -m "branch in mirror" d && + test $base = $(git rev-parse remotes/mirror/d:) && + test_must_fail git rev-parse remotes/d +' + +test_done diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh new file mode 100755 index 0000000000..8cfdfe790f --- /dev/null +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# +# Copyright (c) 2008 Eric Wong + +test_description='git svn honors i18n.commitEncoding in config' + +. ./lib-git-svn.sh + +compare_git_head_with () { + nr=`wc -l < "$1"` + a=7 + b=$(($a + $nr - 1)) + git cat-file commit HEAD | sed -ne "$a,${b}p" >current && + 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="$a_utf8_locale" svn log `git svn info --url` | perl -w -e ' + use bytes; + $/ = ("-"x72) . "\n"; + my @x = <STDIN>; + @x = split(/\n/, $x[1]); + splice(@x, 0, 2); + $x[-1] = ""; + print join("\n", @x); + ' > current && + test_cmp current "$1" +} + +for H in ISO8859-1 eucJP ISO-2022-JP +do + test_expect_success "$H setup" ' + mkdir $H && + svn_cmd import -m "$H test" $H "$svnrepo"/$H && + git svn clone "$svnrepo"/$H $H + ' +done + +for H in ISO8859-1 eucJP ISO-2022-JP +do + test_expect_success "$H commit on git side" ' + ( + cd $H && + git config i18n.commitencoding $H && + git checkout -b t refs/remotes/git-svn && + echo $H >F && + git add F && + git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt && + E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") && + test "z$E" = "z$H" + compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt + ) + ' +done + +for H in ISO8859-1 eucJP ISO-2022-JP +do + test_expect_success "$H dcommit to svn" ' + ( + cd $H && + git svn dcommit && + git cat-file commit HEAD | grep git-svn-id: && + E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") && + test "z$E" = "z$H" && + compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt + ) + ' +done + +test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' ' + ( + cd ISO8859-1 && + compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt + ) +' + +for H in eucJP ISO-2022-JP +do + test_expect_success UTF8 "$H should match UTF-8 in svn" ' + ( + cd $H && + compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt + ) + ' +done + +test_done diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh new file mode 100755 index 0000000000..134411e0a5 --- /dev/null +++ b/t/t9130-git-svn-authors-file.sh @@ -0,0 +1,117 @@ +#!/bin/sh +# +# Copyright (c) 2008 Eric Wong +# + +test_description='git svn authors file tests' + +. ./lib-git-svn.sh + +cat > svn-authors <<EOF +aa = AAAAAAA AAAAAAA <aa@example.com> +bb = BBBBBBB BBBBBBB <bb@example.com> +EOF + +test_expect_success 'setup svnrepo' ' + for i in aa bb cc dd + do + svn_cmd mkdir -m $i --username $i "$svnrepo"/$i + done + ' + +test_expect_success 'start import with incomplete authors file' ' + ! git svn clone --authors-file=svn-authors "$svnrepo" x + ' + +test_expect_success 'imported 2 revisions successfully' ' + ( + cd x + test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 && + git rev-list -1 --pretty=raw refs/remotes/git-svn | \ + grep "^author BBBBBBB BBBBBBB <bb@example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ + grep "^author AAAAAAA AAAAAAA <aa@example\.com> " + ) + ' + +cat >> svn-authors <<EOF +cc = CCCCCCC CCCCCCC <cc@example.com> +dd = DDDDDDD DDDDDDD <dd@example.com> +EOF + +test_expect_success 'continues to import once authors have been added' ' + ( + cd x + git svn fetch --authors-file=../svn-authors && + test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 && + git rev-list -1 --pretty=raw refs/remotes/git-svn | \ + grep "^author DDDDDDD DDDDDDD <dd@example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ + grep "^author CCCCCCC CCCCCCC <cc@example\.com> " + ) + ' + +test_expect_success 'authors-file against globs' ' + svn_cmd mkdir -m globs --username aa \ + "$svnrepo"/aa/trunk "$svnrepo"/aa/branches "$svnrepo"/aa/tags && + git svn clone --authors-file=svn-authors -s "$svnrepo"/aa aa-work && + for i in bb ee cc + do + branch="aa/branches/$i" + svn_cmd mkdir -m "$branch" --username $i "$svnrepo/$branch" + done + ' + +test_expect_success 'fetch fails on ee' ' + ( cd aa-work && ! git svn fetch --authors-file=../svn-authors ) + ' + +tmp_config_get () { + GIT_CONFIG=.git/svn/.metadata git config --get "$1" +} + +test_expect_success 'failure happened without negative side effects' ' + ( + cd aa-work && + test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && + test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + ) + ' + +cat >> svn-authors <<EOF +ee = EEEEEEE EEEEEEE <ee@example.com> +EOF + +test_expect_success 'fetch continues after authors-file is fixed' ' + ( + cd aa-work && + git svn fetch --authors-file=../svn-authors && + test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && + test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + ) + ' + +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 && + unset GIT_CONFIG && + git config --global \ + svn.authorsfile "$HOME"/svn-authors && + test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" && + git svn clone "$svnrepo" gitconfig.clone && + cd gitconfig.clone && + nr_ex=$(git log | grep "^Author:.*example.com" | wc -l) && + nr_rev=$(git rev-list HEAD | wc -l) && + test $nr_rev -eq $nr_ex + ) +' + +test_debug 'GIT_DIR=gitconfig.clone/.git git log' + +test_done diff --git a/t/t9131-git-svn-empty-symlink.sh b/t/t9131-git-svn-empty-symlink.sh new file mode 100755 index 0000000000..9a24a65b64 --- /dev/null +++ b/t/t9131-git-svn-empty-symlink.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +test_description='test that git handles an svn repository with empty symlinks' + +. ./lib-git-svn.sh +test_expect_success 'load svn dumpfile' ' + svnadmin load "$rawsvnrepo" <<EOF +SVN-fs-dump-format-version: 2 + +UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-11-26T07:17:27.590577Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 4 +test +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2008-11-26T07:18:03.511836Z +PROPS-END + +Node-path: bar +Node-kind: file +Node-action: add +Prop-content-length: 33 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Content-length: 33 + +K 11 +svn:special +V 1 +* +PROPS-END + +Revision-number: 2 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 13 +bar => doink + +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2008-11-27T03:55:31.601672Z +PROPS-END + +Node-path: bar +Node-kind: file +Node-action: change +Text-content-length: 10 +Text-content-md5: 92ca4fe7a9721f877f765c252dcd66c9 +Content-length: 10 + +link doink + +EOF +' + +test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x' +test_expect_success 'enable broken symlink workaround' \ + '(cd x && git config svn.brokenSymlinkWorkaround true)' +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 'clone using git svn' 'git svn clone -r1 "$svnrepo" y' +test_expect_success 'disable broken symlink workaround' \ + '(cd y && git config svn.brokenSymlinkWorkaround false)' +test_expect_success '"bar" is an empty file' 'test -f y/bar && ! test -s y/bar' +test_expect_success 'get "bar" => symlink fix from svn' \ + '(cd y && git svn rebase)' +test_expect_success '"bar" does not become a symlink' '! test -L y/bar' + +# svn.brokenSymlinkWorkaround is unset +test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" z' +test_expect_success '"bar" is an empty file' 'test -f z/bar && ! test -s z/bar' +test_expect_success 'get "bar" => symlink fix from svn' \ + '(cd z && git svn rebase)' +test_expect_success '"bar" does not become a symlink' '! test -L z/bar' + + +test_done diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh new file mode 100755 index 0000000000..6c4c90b036 --- /dev/null +++ b/t/t9132-git-svn-broken-symlink.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='test that git handles an svn repository with empty symlinks' + +. ./lib-git-svn.sh +test_expect_success 'load svn dumpfile' ' + svnadmin load "$rawsvnrepo" <<EOF +SVN-fs-dump-format-version: 2 + +UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-11-26T07:17:27.590577Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 4 +test +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2008-11-26T07:18:03.511836Z +PROPS-END + +Node-path: bar +Node-kind: file +Node-action: add +Prop-content-length: 33 +Text-content-length: 4 +Text-content-md5: 912ec803b2ce49e4a541068d495ab570 +Content-length: 37 + +K 11 +svn:special +V 1 +* +PROPS-END +asdf + +Revision-number: 2 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 13 +bar => doink + +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2008-11-27T03:55:31.601672Z +PROPS-END + +Node-path: bar +Node-kind: file +Node-action: change +Text-content-length: 10 +Text-content-md5: 92ca4fe7a9721f877f765c252dcd66c9 +Content-length: 10 + +link doink + +EOF +' + +test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x' + +test_expect_success SYMLINKS '"bar" is a symlink that points to "asdf"' ' + test -L x/bar && + (cd x && test xasdf = x"`git cat-file blob HEAD:bar`") +' + +test_expect_success 'get "bar" => symlink fix from svn' ' + (cd x && git svn rebase) +' + +test_expect_success SYMLINKS '"bar" remains a proper symlink' ' + test -L x/bar && + (cd x && test xdoink = x"`git cat-file blob HEAD:bar`") +' + +test_done diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh new file mode 100755 index 0000000000..f3c30e63b7 --- /dev/null +++ b/t/t9133-git-svn-nested-git-repo.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong +# + +test_description='git svn property tests' +. ./lib-git-svn.sh + +test_expect_success 'setup repo with a git repo inside it' ' + svn_cmd co "$svnrepo" s && + ( + cd s && + git init && + test -f .git/HEAD && + > .git/a && + echo a > a && + svn_cmd add .git a && + svn_cmd commit -m "create a nested git repo" && + svn_cmd up && + echo hi >> .git/a && + svn_cmd commit -m "modify .git/a" && + svn_cmd up + ) +' + +test_expect_success 'clone an SVN repo containing a git repo' ' + git svn clone "$svnrepo" g && + echo a > expect && + test_cmp expect g/a +' + +test_expect_success 'SVN-side change outside of .git' ' + ( + cd s && + echo b >> a && + svn_cmd commit -m "SVN-side change outside of .git" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change outside of .git" + ) +' + +test_expect_success 'update git svn-cloned repo' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + test_cmp a expect && + rm expect + ) +' + +test_expect_success 'SVN-side change inside of .git' ' + ( + cd s && + git add a && + git commit -m "add a inside an SVN repo" && + git log && + svn_cmd add --force .git && + svn_cmd commit -m "SVN-side change inside of .git" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change inside of .git" + ) +' + +test_expect_success 'update git svn-cloned repo' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + test_cmp a expect && + rm expect + ) +' + +test_expect_success 'SVN-side change in and out of .git' ' + ( + cd s && + echo c >> a && + git add a && + git commit -m "add a inside an SVN repo" && + svn_cmd commit -m "SVN-side change in and out of .git" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change in and out of .git" + ) +' + +test_expect_success 'update git svn-cloned repo again' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + echo c >> expect && + test_cmp a expect && + rm expect + ) +' + +test_done diff --git a/t/t9134-git-svn-ignore-paths.sh b/t/t9134-git-svn-ignore-paths.sh new file mode 100755 index 0000000000..09ff10cd9b --- /dev/null +++ b/t/t9134-git-svn-ignore-paths.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# +# Copyright (c) 2009 Vitaly Shukela +# Copyright (c) 2009 Eric Wong +# + +test_description='git svn property tests' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository' ' + svn_cmd co "$svnrepo" s && + ( + cd s && + mkdir qqq www && + echo test_qqq > qqq/test_qqq.txt && + echo test_www > www/test_www.txt && + svn_cmd add qqq && + svn_cmd add www && + svn_cmd commit -m "create some files" && + svn_cmd up && + echo hi >> www/test_www.txt && + svn_cmd commit -m "modify www/test_www.txt" && + svn_cmd up + ) +' + +test_expect_success 'clone an SVN repository with ignored www directory' ' + git svn clone --ignore-paths="^www" "$svnrepo" g && + echo test_qqq > expect && + for i in g/*/*.txt; do cat $i >> expect2; done && + test_cmp expect expect2 +' + +test_expect_success 'init+fetch an SVN repository with ignored www directory' ' + git svn init "$svnrepo" c && + ( cd c && git svn fetch --ignore-paths="^www" ) && + rm expect2 && + echo test_qqq > expect && + for i in c/*/*.txt; do cat $i >> expect2; done && + test_cmp expect expect2 +' + +test_expect_success 'verify ignore-paths config saved by clone' ' + ( + cd g && + git config --get svn-remote.svn.ignore-paths | fgrep "www" + ) +' + +test_expect_success 'SVN-side change outside of www' ' + ( + cd s && + echo b >> qqq/test_qqq.txt && + svn_cmd commit -m "SVN-side change outside of www" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change outside of www" + ) +' + +test_expect_success 'update git svn-cloned repo (config ignore)' ' + ( + cd g && + git svn rebase && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo (option ignore)' ' + ( + cd c && + git svn rebase --ignore-paths="^www" && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'SVN-side change inside of ignored www' ' + ( + cd s && + echo zaq >> www/test_www.txt + svn_cmd commit -m "SVN-side change inside of www/test_www.txt" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt" + ) +' + +test_expect_success 'update git svn-cloned repo (config ignore)' ' + ( + cd g && + git svn rebase && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo (option ignore)' ' + ( + cd c && + git svn rebase --ignore-paths="^www" && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'SVN-side change in and out of ignored www' ' + ( + cd s && + echo cvf >> www/test_www.txt + echo ygg >> qqq/test_qqq.txt + svn_cmd commit -m "SVN-side change in and out of ignored www" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change in and out of ignored www" + ) +' + +test_expect_success 'update git svn-cloned repo again (config ignore)' ' + ( + cd g && + git svn rebase && + printf "test_qqq\nb\nygg\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo again (option ignore)' ' + ( + cd c && + git svn rebase --ignore-paths="^www" && + printf "test_qqq\nb\nygg\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_done diff --git a/t/t9135-git-svn-moved-branch-empty-file.sh b/t/t9135-git-svn-moved-branch-empty-file.sh new file mode 100755 index 0000000000..5280e5f1e4 --- /dev/null +++ b/t/t9135-git-svn-moved-branch-empty-file.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +test_description='test moved svn branch with missing empty files' + +. ./lib-git-svn.sh +test_expect_success 'load svn dumpfile' ' + svnadmin load "$rawsvnrepo" < "${TEST_DIRECTORY}/t9135/svn.dump" + ' + +test_expect_success 'clone using git svn' 'git svn clone -s "$svnrepo" x' + +test_expect_success 'test that b1 exists and is empty' ' + ( + cd x && + git reset --hard branch-c && + test -f b1 && + ! test -s b1 + ) + ' + +test_done diff --git a/t/t9135/svn.dump b/t/t9135/svn.dump new file mode 100644 index 0000000000..b51c0ccceb --- /dev/null +++ b/t/t9135/svn.dump @@ -0,0 +1,192 @@ +SVN-fs-dump-format-version: 2 + +UUID: 1f80e919-e9e3-4d80-a3ae-d9f21095e27b + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2009-02-10T19:23:16.424027Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 20 +init standard layout +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:17.195072Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 18 +branch-b off trunk +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:19.160095Z +PROPS-END + +Node-path: branches/branch-b +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk +Prop-content-length: 34 +Content-length: 34 + +K 13 +svn:mergeinfo +V 0 + +PROPS-END + + +Revision-number: 3 +Prop-content-length: 120 +Content-length: 120 + +K 7 +svn:log +V 17 +add empty file b1 +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:20.194568Z +PROPS-END + +Node-path: branches/branch-b/b1 +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Content-length: 10 + +PROPS-END + + +Revision-number: 4 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 8 +branch-c +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:21.169100Z +PROPS-END + +Node-path: branches/branch-c +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 3 +Node-copyfrom-path: trunk + + +Revision-number: 5 +Prop-content-length: 126 +Content-length: 126 + +K 7 +svn:log +V 23 +oops, wrong branchpoint +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:21.253557Z +PROPS-END + +Node-path: branches/branch-c +Node-action: delete + + +Revision-number: 6 +Prop-content-length: 127 +Content-length: 127 + +K 7 +svn:log +V 24 +branch-c off of branch-b +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-10T19:23:21.314659Z +PROPS-END + +Node-path: branches/branch-c +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 5 +Node-copyfrom-path: branches/branch-b +Prop-content-length: 34 +Content-length: 34 + +K 13 +svn:mergeinfo +V 0 + +PROPS-END + + diff --git a/t/t9136-git-svn-recreated-branch-empty-file.sh b/t/t9136-git-svn-recreated-branch-empty-file.sh new file mode 100755 index 0000000000..733d16e0b2 --- /dev/null +++ b/t/t9136-git-svn-recreated-branch-empty-file.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +test_description='test recreated svn branch with empty files' + +. ./lib-git-svn.sh +test_expect_success 'load svn dumpfile' ' + svnadmin load "$rawsvnrepo" < "${TEST_DIRECTORY}/t9136/svn.dump" + ' + +test_expect_success 'clone using git svn' 'git svn clone -s "$svnrepo" x' + +test_done diff --git a/t/t9136/svn.dump b/t/t9136/svn.dump new file mode 100644 index 0000000000..6b1ce0b2e8 --- /dev/null +++ b/t/t9136/svn.dump @@ -0,0 +1,192 @@ +SVN-fs-dump-format-version: 2 + +UUID: eecae021-8f16-48da-969d-79beb8ae6ea5 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2009-02-22T00:50:56.292890Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 106 +Content-length: 106 + +K 7 +svn:log +V 4 +init +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:57.192384Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: tags +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk/file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 0 +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 105 +Content-length: 105 + +K 7 +svn:log +V 3 +1.0 +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:58.124724Z +PROPS-END + +Node-path: tags/1.0 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 3 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 9 +1.0.1-bad +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:58.151727Z +PROPS-END + +Node-path: tags/1.0.1 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: tags/1.0 + + +Revision-number: 4 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 9 +Wrong tag +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:58.167427Z +PROPS-END + +Node-path: tags/1.0.1 +Node-action: delete + + +Revision-number: 5 +Prop-content-length: 113 +Content-length: 113 + +K 7 +svn:log +V 10 +1.0-branch +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:58.184498Z +PROPS-END + +Node-path: branches/1.0 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 4 +Node-copyfrom-path: tags/1.0 + + +Revision-number: 6 +Prop-content-length: 113 +Content-length: 113 + +K 7 +svn:log +V 10 +1.0.1-good +K 10 +svn:author +V 8 +john.doe +K 8 +svn:date +V 27 +2009-02-22T00:50:58.200695Z +PROPS-END + +Node-path: tags/1.0.1 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 5 +Node-copyfrom-path: branches/1.0 + + diff --git a/t/t9137-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh new file mode 100755 index 0000000000..636ca0abb9 --- /dev/null +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +test_description='git svn dcommit clobber series' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' ' + mkdir import && + cd import && + awk "BEGIN { for (i = 1; i < 64; i++) { print i } }" > file + svn_cmd import -m "initial" . "$svnrepo" && + cd .. && + git svn init "$svnrepo" && + git svn fetch && + test -e file + ' + +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 && + 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 .. + ' + +test_expect_success 'some unrelated changes to git' " + echo hi > life && + git update-index --add life && + git commit -m hi-life && + echo bye >> life && + git commit -m bye-life life + " + +test_expect_success 'change file but in unrelated area' " + test x\"\`sed -n -e 4p < file\`\" = x4 && + test x\"\`sed -n -e 7p < file\`\" = x7 && + perl -i.bak -p -e 's/^4\$/4444/' file && + perl -i.bak -p -e 's/^7\$/7777/' file && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + git commit -m '4 => 4444, 7 => 7777' file && + git svn dcommit && + svn_cmd up tmp && + cd tmp && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + test x\"\`sed -n -e 58p < file\`\" = x5588 && + test x\"\`sed -n -e 61p < file\`\" = x6611 + " + +test_expect_success 'attempt to dcommit with a dirty index' ' + echo foo >>file && + git add file && + test_must_fail git svn dcommit +' + +test_done diff --git a/t/t9138-git-svn-authors-prog.sh b/t/t9138-git-svn-authors-prog.sh new file mode 100755 index 0000000000..83cc5fc9d1 --- /dev/null +++ b/t/t9138-git-svn-authors-prog.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong, Mark Lodato +# + +test_description='git svn authors prog tests' + +. ./lib-git-svn.sh + +cat > svn-authors-prog <<'EOF' +#!/usr/bin/perl +$_ = shift; +if (s/-sub$//) { + print "$_ <$_\@sub.example.com>\n"; +} +else { + print "$_ <$_\@example.com>\n"; +} +EOF +chmod +x svn-authors-prog + +cat > svn-authors <<'EOF' +ff = FFFFFFF FFFFFFF <fFf@other.example.com> +EOF + +test_expect_success 'setup svnrepo' ' + for i in aa bb cc-sub dd-sub ee-foo ff + do + svn mkdir -m $i --username $i "$svnrepo"/$i + done + ' + +test_expect_success 'import authors with prog and file' ' + git svn clone --authors-prog=./svn-authors-prog \ + --authors-file=svn-authors "$svnrepo" x + ' + +test_expect_success 'imported 6 revisions successfully' ' + ( + cd x + test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 6 + ) + ' + +test_expect_success 'authors-prog ran correctly' ' + ( + cd x + git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ + grep "^author ee-foo <ee-foo@example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~2 | \ + grep "^author dd <dd@sub\.example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~3 | \ + grep "^author cc <cc@sub\.example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~4 | \ + grep "^author bb <bb@example\.com> " && + git rev-list -1 --pretty=raw refs/remotes/git-svn~5 | \ + grep "^author aa <aa@example\.com> " + ) + ' + +test_expect_success 'authors-file overrode authors-prog' ' + ( + cd x + git rev-list -1 --pretty=raw refs/remotes/git-svn | \ + grep "^author FFFFFFF FFFFFFF <fFf@other\.example\.com> " + ) + ' + +git --git-dir=x/.git config --unset svn.authorsfile +git --git-dir=x/.git config --unset svn.authorsprog + +test_expect_success 'authors-prog handled special characters in username' ' + svn mkdir -m bad --username "xyz; touch evil" "$svnrepo"/bad && + ( + cd x && + git svn --authors-prog=../svn-authors-prog fetch && + git rev-list -1 --pretty=raw refs/remotes/git-svn | + grep "^author xyz; touch evil <xyz; touch evil@example\.com> " && + ! test -f evil + ) +' + +test_done diff --git a/t/t9139-git-svn-non-utf8-commitencoding.sh b/t/t9139-git-svn-non-utf8-commitencoding.sh new file mode 100755 index 0000000000..f337959ccc --- /dev/null +++ b/t/t9139-git-svn-non-utf8-commitencoding.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong + +test_description='git svn refuses to dcommit non-UTF8 messages' + +. ./lib-git-svn.sh + +# ISO-2022-JP can pass for valid UTF-8, so skipping that in this test + +for H in ISO8859-1 eucJP +do + test_expect_success "$H setup" ' + mkdir $H && + svn_cmd import -m "$H test" $H "$svnrepo"/$H && + git svn clone "$svnrepo"/$H $H + ' +done + +for H in ISO8859-1 eucJP +do + test_expect_success "$H commit on git side" ' + ( + cd $H && + git config i18n.commitencoding $H && + git checkout -b t refs/remotes/git-svn && + echo $H >F && + git add F && + git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt && + E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") && + test "z$E" = "z$H" + ) + ' +done + +for H in ISO8859-1 eucJP +do + test_expect_success "$H dcommit to svn" ' + ( + cd $H && + git config --unset i18n.commitencoding && + ! git svn dcommit + ) + ' +done + +test_done diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh new file mode 100755 index 0000000000..0735526d4b --- /dev/null +++ b/t/t9140-git-svn-reset.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2009 Ben Jackson +# + +test_description='git svn reset' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository' ' + svn_cmd co "$svnrepo" s && + ( + cd s && + mkdir vis && + echo always visible > vis/vis.txt && + svn_cmd add vis && + svn_cmd commit -m "create visible files" && + mkdir hid && + echo initially hidden > hid/hid.txt && + svn_cmd add hid && + svn_cmd commit -m "create initially hidden files" && + svn_cmd up && + echo mod >> vis/vis.txt && + svn_cmd commit -m "modify vis" && + svn_cmd up + ) +' + +test_expect_success 'clone SVN repository with hidden directory' ' + git svn init "$svnrepo" g && + ( cd g && git svn fetch --ignore-paths="^hid" ) +' + +test_expect_success 'modify hidden file in SVN repo' ' + ( cd s && + echo mod hidden >> hid/hid.txt && + svn_cmd commit -m "modify hid" && + svn_cmd up + ) +' + +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 && + git svn find-rev refs/remotes/git-svn > ../expect2 ) && + fgrep "not found in commit" errors && + test_cmp expect expect2 +' + +test_expect_success 'reset unwinds back to r1' ' + ( cd g && + git svn reset -r1 && + git svn find-rev refs/remotes/git-svn > ../expect2 ) && + echo 1 >expect && + test_cmp expect expect2 +' + +test_expect_success 'refetch succeeds not ignoring any files' ' + ( cd g && + git svn fetch && + git svn rebase && + fgrep "mod hidden" hid/hid.txt + ) +' + +test_done diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh new file mode 100755 index 0000000000..3cd06718eb --- /dev/null +++ b/t/t9141-git-svn-multiple-branches.sh @@ -0,0 +1,122 @@ +#!/bin/sh +# +# Copyright (c) 2009 Marc Branchaud +# + +test_description='git svn multiple branch and tag paths in the svn repo' +. ./lib-git-svn.sh + +test_expect_success 'setup svnrepo' ' + mkdir project \ + project/trunk \ + project/b_one \ + project/b_two \ + project/tags_A \ + project/tags_B && + echo 1 > project/trunk/a.file && + svn_cmd import -m "$test_description" project "$svnrepo/project" && + rm -rf project && + svn_cmd cp -m "Branch 1" "$svnrepo/project/trunk" \ + "$svnrepo/project/b_one/first" && + svn_cmd cp -m "Tag 1" "$svnrepo/project/trunk" \ + "$svnrepo/project/tags_A/1.0" && + svn_cmd co "$svnrepo/project" svn_project && + ( cd svn_project && + echo 2 > trunk/a.file && + svn_cmd ci -m "Change 1" trunk/a.file && + svn_cmd cp -m "Branch 2" "$svnrepo/project/trunk" \ + "$svnrepo/project/b_one/second" && + svn_cmd cp -m "Tag 2" "$svnrepo/project/trunk" \ + "$svnrepo/project/tags_A/2.0" && + echo 3 > trunk/a.file && + svn_cmd ci -m "Change 2" trunk/a.file && + svn_cmd cp -m "Branch 3" "$svnrepo/project/trunk" \ + "$svnrepo/project/b_two/1" && + svn_cmd cp -m "Tag 3" "$svnrepo/project/trunk" \ + "$svnrepo/project/tags_A/3.0" && + echo 4 > trunk/a.file && + svn_cmd ci -m "Change 3" trunk/a.file && + svn_cmd cp -m "Branch 4" "$svnrepo/project/trunk" \ + "$svnrepo/project/b_two/2" && + svn_cmd cp -m "Tag 4" "$svnrepo/project/trunk" \ + "$svnrepo/project/tags_A/4.0" && + svn_cmd up && + echo 5 > b_one/first/a.file && + svn_cmd ci -m "Change 4" b_one/first/a.file && + svn_cmd cp -m "Tag 5" "$svnrepo/project/b_one/first" \ + "$svnrepo/project/tags_B/v5" && + echo 6 > b_one/second/a.file && + svn_cmd ci -m "Change 5" b_one/second/a.file && + svn_cmd cp -m "Tag 6" "$svnrepo/project/b_one/second" \ + "$svnrepo/project/tags_B/v6" && + echo 7 > b_two/1/a.file && + svn_cmd ci -m "Change 6" b_two/1/a.file && + svn_cmd cp -m "Tag 7" "$svnrepo/project/b_two/1" \ + "$svnrepo/project/tags_B/v7" && + echo 8 > b_two/2/a.file && + svn_cmd ci -m "Change 7" b_two/2/a.file && + svn_cmd cp -m "Tag 8" "$svnrepo/project/b_two/2" \ + "$svnrepo/project/tags_B/v8" + ) +' + +test_expect_success 'clone multiple branch and tag paths' ' + git svn clone -T trunk \ + -b b_one/* --branches b_two/* \ + -t tags_A/* --tags tags_B \ + "$svnrepo/project" git_project && + ( cd git_project && + git rev-parse refs/remotes/first && + git rev-parse refs/remotes/second && + git rev-parse refs/remotes/1 && + git rev-parse refs/remotes/2 && + git rev-parse refs/remotes/tags/1.0 && + git rev-parse refs/remotes/tags/2.0 && + git rev-parse refs/remotes/tags/3.0 && + git rev-parse refs/remotes/tags/4.0 && + git rev-parse refs/remotes/tags/v5 && + git rev-parse refs/remotes/tags/v6 && + git rev-parse refs/remotes/tags/v7 && + git rev-parse refs/remotes/tags/v8 + ) +' + +test_expect_success 'Multiple branch or tag paths require -d' ' + ( cd git_project && + test_must_fail git svn branch -m "No new branch" Nope && + test_must_fail git svn tag -m "No new tag" Tagless && + test_must_fail git rev-parse refs/remotes/Nope && + test_must_fail git rev-parse refs/remotes/tags/Tagless + ) && + ( cd svn_project && + svn_cmd up && + test_must_fail test -d b_one/Nope && + test_must_fail test -d b_two/Nope && + test_must_fail test -d tags_A/Tagless && + test_must_fail test -d tags_B/Tagless + ) +' + +test_expect_success 'create new branches and tags' ' + ( cd git_project && + git svn branch -m "New branch 1" -d b_one New1 ) && + ( cd svn_project && + svn_cmd up && test -e b_one/New1/a.file ) && + + ( cd git_project && + git svn branch -m "New branch 2" -d b_two New2 ) && + ( cd svn_project && + svn_cmd up && test -e b_two/New2/a.file ) && + + ( cd git_project && + git svn branch -t -m "New tag 1" -d tags_A Tag1 ) && + ( cd svn_project && + svn_cmd up && test -e tags_A/Tag1/a.file ) && + + ( cd git_project && + git svn tag -m "New tag 2" -d tags_B Tag2 ) && + ( cd svn_project && + svn_cmd up && test -e tags_B/Tag2/a.file ) +' + +test_done diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh new file mode 100755 index 0000000000..1236accd99 --- /dev/null +++ b/t/t9142-git-svn-shallow-clone.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong +# + +test_description='git svn shallow clone' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository' ' + svn_cmd mkdir -m "create standard layout" \ + "$svnrepo"/trunk "$svnrepo"/branches "$svnrepo"/tags && + svn_cmd cp -m "branch off trunk" \ + "$svnrepo"/trunk "$svnrepo"/branches/a && + svn_cmd co "$svnrepo"/branches/a && + ( + cd a && + > foo && + svn_cmd add foo && + svn_cmd commit -m "add foo" + ) +' + +start_httpd + +test_expect_success 'clone trunk with "-r HEAD"' ' + git svn clone -r HEAD "$svnrepo/trunk" g && + ( cd g && git rev-parse --symbolic --verify HEAD ) +' + +stop_httpd + +test_done diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh new file mode 100755 index 0000000000..337ea59711 --- /dev/null +++ b/t/t9143-git-svn-gc.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# +# Copyright (c) 2009 Robert Allan Zeh + +test_description='git svn gc basic tests' + +. ./lib-git-svn.sh + +test_expect_success 'setup directories and test repo' ' + mkdir import && + mkdir tmp && + echo "Sample text for Subversion repository." > import/test.txt && + svn_cmd import -m "import for git svn" import "$svnrepo" > /dev/null + ' + +test_expect_success 'checkout working copy from svn' \ + 'svn_cmd co "$svnrepo" test_wc' + +test_expect_success 'set some properties to create an unhandled.log file' ' + ( + cd test_wc && + svn_cmd propset foo bar test.txt && + svn_cmd commit -m "property set" + )' + +test_expect_success 'Setup repo' 'git svn init "$svnrepo"' + +test_expect_success 'Fetch repo' 'git svn fetch' + +test_expect_success 'make backup copy of unhandled.log' ' + cp .git/svn/refs/remotes/git-svn/unhandled.log tmp + ' + +test_expect_success 'create leftover index' '> .git/svn/refs/remotes/git-svn/index' + +test_expect_success 'git svn gc runs' 'git svn gc' + +test_expect_success 'git svn index removed' '! test -f .git/svn/refs/remotes/git-svn/index' + +if perl -MCompress::Zlib -e 0 2>/dev/null +then + test_expect_success 'git svn gc produces a valid gzip file' ' + gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz + ' +else + say "# Perl Compress::Zlib unavailable, skipping gunzip test" +fi + +test_expect_success 'git svn gc does not change unhandled.log files' ' + test_cmp .git/svn/refs/remotes/git-svn/unhandled.log tmp/unhandled.log + ' + +test_done diff --git a/t/t9144-git-svn-old-rev_map.sh b/t/t9144-git-svn-old-rev_map.sh new file mode 100755 index 0000000000..7600a35cd4 --- /dev/null +++ b/t/t9144-git-svn-old-rev_map.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong + +test_description='git svn old rev_map preservd' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository with old layout' ' + mkdir i && + (cd i && > a) && + svn_cmd import -m- i "$svnrepo" && + git svn init "$svnrepo" && + git svn fetch && + test -d .git/svn/refs/remotes/git-svn/ && + ! test -e .git/svn/git-svn/ && + mv .git/svn/refs/remotes/git-svn .git/svn/ && + rm -r .git/svn/refs +' + +test_expect_success 'old layout continues to work' ' + svn_cmd import -m- i "$svnrepo/b" && + git svn rebase && + echo a >> b/a && + git add b/a && + git commit -m- -a && + git svn dcommit && + ! test -d .git/svn/refs/ && + test -e .git/svn/git-svn/ +' + +test_done diff --git a/t/t9145-git-svn-master-branch.sh b/t/t9145-git-svn-master-branch.sh new file mode 100755 index 0000000000..16852d26ae --- /dev/null +++ b/t/t9145-git-svn-master-branch.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong +# +test_description='git svn initial master branch is "trunk" if possible' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository' ' + mkdir i && + > i/a && + svn_cmd import -m trunk i "$svnrepo/trunk" && + svn_cmd import -m b/a i "$svnrepo/branches/a" && + svn_cmd import -m b/b i "$svnrepo/branches/b" +' + +test_expect_success 'git svn clone --stdlayout sets up trunk as master' ' + git svn clone -s "$svnrepo" g && + ( + cd g && + test x`git rev-parse --verify refs/remotes/trunk^0` = \ + x`git rev-parse --verify refs/heads/master^0` + ) +' + +test_done diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh new file mode 100755 index 0000000000..565365cbd3 --- /dev/null +++ b/t/t9146-git-svn-empty-dirs.sh @@ -0,0 +1,142 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong + +test_description='git svn creates empty directories' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' ' + for i in a b c d d/e d/e/f "weird file name" + do + svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i" + done +' + +test_expect_success 'clone' 'git svn clone "$svnrepo" cloned' + +test_expect_success 'empty directories exist' ' + ( + cd cloned && + for i in a b c d d/e d/e/f "weird file name" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + ) +' + +test_expect_success 'more emptiness' ' + svn_cmd mkdir -m "bang bang" "$svnrepo"/"! !" +' + +test_expect_success 'git svn rebase creates empty directory' ' + ( cd cloned && git svn rebase ) + test -d cloned/"! !" +' + +test_expect_success 'git svn mkdirs recreates empty directories' ' + ( + cd cloned && + rm -r * && + git svn mkdirs && + for i in a b c d d/e d/e/f "weird file name" "! !" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + ) +' + +test_expect_success 'git svn mkdirs -r works' ' + ( + cd cloned && + rm -r * && + git svn mkdirs -r7 && + for i in a b c d d/e d/e/f "weird file name" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + + if test -d "! !" + then + echo >&2 "$i should not exist" + exit 1 + fi + + git svn mkdirs -r8 && + if ! test -d "! !" + then + echo >&2 "$i not exist" + exit 1 + fi + ) +' + +test_expect_success 'initialize trunk' ' + for i in trunk trunk/a trunk/"weird file name" + do + svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i" + done +' + +test_expect_success 'clone trunk' 'git svn clone -s "$svnrepo" trunk' + +test_expect_success 'empty directories in trunk exist' ' + ( + cd trunk && + for i in a "weird file name" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + ) +' + +test_expect_success 'remove a top-level directory from svn' ' + svn_cmd rm -m "remove d" "$svnrepo"/d +' + +test_expect_success 'removed top-level directory does not exist' ' + git svn clone "$svnrepo" removed && + test ! -e removed/d + +' +unhandled=.git/svn/refs/remotes/git-svn/unhandled.log +test_expect_success 'git svn gc-ed files work' ' + ( + cd removed && + git svn gc && + : Compress::Zlib may not be available && + if test -f "$unhandled".gz + then + svn_cmd mkdir -m gz "$svnrepo"/gz && + git reset --hard $(git rev-list HEAD | tail -1) && + git svn rebase && + test -f "$unhandled".gz && + test -f "$unhandled" && + for i in a b c "weird file name" gz "! !" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + fi + ) +' + +test_done diff --git a/t/t9150-svk-mergetickets.sh b/t/t9150-svk-mergetickets.sh new file mode 100755 index 0000000000..24c2421bfc --- /dev/null +++ b/t/t9150-svk-mergetickets.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright (c) 2007 Sam Vilain +# + +test_description='git-svn svk merge tickets' + +. ./lib-git-svn.sh + +test_expect_success 'load svk depot' " + svnadmin load -q '$rawsvnrepo' \ + < '$TEST_DIRECTORY/t9150/svk-merge.dump' && + git svn init --minimize-url -R svkmerge \ + --rewrite-root=http://svn.example.org \ + -T trunk -b branches '$svnrepo' && + git svn fetch --all + " + +uuid=b48289b2-9c08-4d72-af37-0358a40b9c15 + +test_expect_success 'svk merges were represented coming in' " + [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ] + " + +test_done diff --git a/t/t9150/make-svk-dump b/t/t9150/make-svk-dump new file mode 100644 index 0000000000..2242f14ebe --- /dev/null +++ b/t/t9150/make-svk-dump @@ -0,0 +1,57 @@ +#!/bin/sh +# +# this script sets up a Subversion repository for Makefile in the +# first ever git merge, as if it were done with svk. +# + +set -e + +svk depotmap foo ~/.svk/foo +svk co /foo/ foo +cd foo +mkdir trunk +mkdir branches +svk add trunk branches +svk commit -m "Setup trunk and branches" +cd trunk + +git cat-file blob 6683463e:Makefile > Makefile +svk add Makefile + +svk commit -m "ancestor" +cd .. +svk cp trunk branches/left + +svk commit -m "make left branch" +cd branches/left/ + +git cat-file blob 5873b67e:Makefile > Makefile +svk commit -m "left update 1" + +cd ../../trunk +git cat-file blob 75118b13:Makefile > Makefile +svk commit -m "trunk update" + +cd ../branches/left +git cat-file blob b5039db6:Makefile > Makefile +svk commit -m "left update 2" + +cd ../../trunk +svk sm /foo/branches/left +# in theory we could delete the "left" branch here, but it's not +# required so don't do it, in case people start getting ideas ;) +svk commit -m "merge branch 'left' into 'trunk'" + +git cat-file blob b51ad431:Makefile > Makefile + +svk diff Makefile && echo "Hey! No differences, magic" + +cd ../.. + +svnadmin dump ~/.svk/foo > svk-merge.dump + +svk co -d foo +rm -rf foo +svk depotmap -d /foo/ +rm -rf ~/.svk/foo + diff --git a/t/t9150/svk-merge.dump b/t/t9150/svk-merge.dump new file mode 100644 index 0000000000..42f70dbec7 --- /dev/null +++ b/t/t9150/svk-merge.dump @@ -0,0 +1,616 @@ +SVN-fs-dump-format-version: 2 + +UUID: b48289b2-9c08-4d72-af37-0358a40b9c15 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2009-10-19T23:44:03.722969Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 24 +Setup trunk and branches +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:04.927533Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 106 +Content-length: 106 + +K 7 +svn:log +V 8 +ancestor +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:05.835585Z +PROPS-END + +Node-path: trunk/Makefile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2401 +Text-content-md5: bfd8ff778d1492dc6758567373176a89 +Content-length: 2411 + +PROPS-END +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 3 +Prop-content-length: 115 +Content-length: 115 + +K 7 +svn:log +V 16 +make left branch +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:06.719737Z +PROPS-END + +Node-path: branches/left +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: trunk + + +Revision-number: 4 +Prop-content-length: 112 +Content-length: 112 + +K 7 +svn:log +V 13 +left update 1 +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:07.167666Z +PROPS-END + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2465 +Text-content-md5: 16e38d9753b061731650561ce01b1195 +Content-length: 2465 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 5 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 12 +trunk update +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:07.619633Z +PROPS-END + +Node-path: trunk/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2521 +Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0 +Content-length: 2521 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 6 +Prop-content-length: 112 +Content-length: 112 + +K 7 +svn:log +V 13 +left update 2 +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:08.067554Z +PROPS-END + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2593 +Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba +Content-length: 2593 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 7 +Prop-content-length: 131 +Content-length: 131 + +K 7 +svn:log +V 32 +merge branch 'left' into 'trunk' +K 10 +svn:author +V 4 +samv +K 8 +svn:date +V 27 +2009-10-19T23:44:08.971801Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 83 +Content-length: 83 + +K 9 +svk:merge +V 53 +b48289b2-9c08-4d72-af37-0358a40b9c15:/branches/left:6 +PROPS-END + + +Node-path: trunk/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2713 +Text-content-md5: 0afbe34f244cd662b1f97d708c687f90 +Content-length: 2713 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + diff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh new file mode 100755 index 0000000000..250c651eae --- /dev/null +++ b/t/t9151-svn-mergeinfo.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2007, 2009 Sam Vilain +# + +test_description='git-svn svn mergeinfo properties' + +. ./lib-git-svn.sh + +test_expect_success 'load svn dump' " + svnadmin load -q '$rawsvnrepo' \ + < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' && + git svn init --minimize-url -R svnmerge \ + --rewrite-root=http://svn.example.org \ + -T trunk -b branches '$svnrepo' && + git svn fetch --all + " + +test_expect_success 'all svn merges became git merge commits' ' + unmarked=$(git rev-list --parents --all --grep=Merge | + grep -v " .* " | cut -f1 -d" ") + [ -z "$unmarked" ] + ' + +test_expect_success 'cherry picks did not become git merge commits' ' + bad_cherries=$(git rev-list --parents --all --grep=Cherry | + grep " .* " | cut -f1 -d" ") + [ -z "$bad_cherries" ] + ' + +test_expect_success 'svn non-merge merge commits did not become git merge commits' ' + bad_non_merges=$(git rev-list --parents --all --grep=non-merge | + grep " .* " | cut -f1 -d" ") + [ -z "$bad_non_merges" ] + ' + +test_expect_success 'commit made to merged branch is reachable from the merge' ' + before_commit=$(git rev-list --all --grep="trunk commit before merging trunk to b2") + merge_commit=$(git rev-list --all --grep="Merge trunk to b2") + not_reachable=$(git rev-list -1 $before_commit --not $merge_commit) + [ -z "$not_reachable" ] + ' + +test_expect_success 'merging two branches in one commit is detected correctly' ' + f1_commit=$(git rev-list --all --grep="make f1 branch from trunk") + f2_commit=$(git rev-list --all --grep="make f2 branch from trunk") + merge_commit=$(git rev-list --all --grep="Merge f1 and f2 to trunk") + not_reachable=$(git rev-list -1 $f1_commit $f2_commit --not $merge_commit) + [ -z "$not_reachable" ] + ' + +test_expect_failure 'everything got merged in the end' ' + unmerged=$(git rev-list --all --not master) + [ -z "$unmerged" ] + ' + +test_done diff --git a/t/t9151/.gitignore b/t/t9151/.gitignore new file mode 100644 index 0000000000..587c37dba3 --- /dev/null +++ b/t/t9151/.gitignore @@ -0,0 +1,2 @@ +foo +foo.svn diff --git a/t/t9151/make-svnmerge-dump b/t/t9151/make-svnmerge-dump new file mode 100644 index 0000000000..e1e138cb1a --- /dev/null +++ b/t/t9151/make-svnmerge-dump @@ -0,0 +1,305 @@ +#!/bin/sh +# +# this script sets up a Subversion repository for Makefile in the +# first ever git merge, as if it were done with svnmerge (SVN 1.5+) +# + +rm -rf foo.svn foo +set -e + +mkdir foo.svn +svnadmin create foo.svn +svn co file://`pwd`/foo.svn foo + +commit() { + i=$(( $1 + 1 )) + shift; + svn commit -m "(r$i) $*" >/dev/null || exit 1 + echo $i +} + +say() { + echo "[1m * $*[0m" +} + +i=0 +cd foo +mkdir trunk +mkdir branches +mkdir tags +svn add trunk branches tags +i=$(commit $i "Setup trunk, branches, and tags") + +git cat-file blob 6683463e:Makefile > trunk/Makefile +svn add trunk/Makefile + +say "Committing ANCESTOR" +i=$(commit $i "ancestor") +svn cp trunk branches/left + +say "Committing BRANCH POINT" +i=$(commit $i "make left branch") +svn cp trunk branches/right + +say "Committing other BRANCH POINT" +i=$(commit $i "make right branch") + +say "Committing LEFT UPDATE" +git cat-file blob 5873b67e:Makefile > branches/left/Makefile +i=$(commit $i "left update 1") + +git cat-file blob 75118b13:Makefile > branches/right/Makefile +say "Committing RIGHT UPDATE" +pre_right_update_1=$i +i=$(commit $i "right update 1") + +say "Making more commits on LEFT" +git cat-file blob ff5ebe39:Makefile > branches/left/Makefile +i=$(commit $i "left update 2") +git cat-file blob b5039db6:Makefile > branches/left/Makefile +i=$(commit $i "left update 3") + +say "Making a LEFT SUB-BRANCH" +svn cp branches/left branches/left-sub +sub_left_make=$i +i=$(commit $i "make left sub-branch") + +say "Making a commit on LEFT SUB-BRANCH" +echo "crunch" > branches/left-sub/README +svn add branches/left-sub/README +i=$(commit $i "left sub-branch update 1") + +say "Merging LEFT to TRUNK" +svn update +cd trunk +svn merge ../branches/left --accept postpone +git cat-file blob b5039db6:Makefile > Makefile +svn resolved Makefile +i=$(commit $i "Merge left to trunk 1") +cd .. + +say "Making more commits on LEFT and RIGHT" +echo "touche" > branches/left/zlonk +svn add branches/left/zlonk +i=$(commit $i "left update 4") +echo "thwacke" > branches/right/bang +svn add branches/right/bang +i=$(commit $i "right update 2") + +say "Squash merge of RIGHT tip 2 commits onto TRUNK" +svn update +cd trunk +svn merge -r$pre_right_update_1:$i ../branches/right +i=$(commit $i "Cherry-pick right 2 commits to trunk") +cd .. + +say "Merging RIGHT to TRUNK" +svn update +cd trunk +svn merge ../branches/right --accept postpone +git cat-file blob b51ad431:Makefile > Makefile +svn resolved Makefile +i=$(commit $i "Merge right to trunk 1") +cd .. + +say "Making more commits on RIGHT and TRUNK" +echo "whamm" > branches/right/urkkk +svn add branches/right/urkkk +i=$(commit $i "right update 3") +echo "pow" > trunk/vronk +svn add trunk/vronk +i=$(commit $i "trunk update 1") + +say "Merging RIGHT to LEFT SUB-BRANCH" +svn update +cd branches/left-sub +svn merge ../right --accept postpone +git cat-file blob b51ad431:Makefile > Makefile +svn resolved Makefile +i=$(commit $i "Merge right to left sub-branch") +cd ../.. + +say "Making more commits on LEFT SUB-BRANCH and LEFT" +echo "zowie" > branches/left-sub/wham_eth +svn add branches/left-sub/wham_eth +pre_sub_left_update_2=$i +i=$(commit $i "left sub-branch update 2") +sub_left_update_2=$i +echo "eee_yow" > branches/left/glurpp +svn add branches/left/glurpp +i=$(commit $i "left update 5") + +say "Cherry pick LEFT SUB-BRANCH commit to LEFT" +svn update +cd branches/left +svn merge -r$pre_sub_left_update_2:$sub_left_update_2 ../left-sub +i=$(commit $i "Cherry-pick left sub-branch commit to left") +cd ../.. + +say "Merging LEFT SUB-BRANCH back to LEFT" +svn update +cd branches/left +# it's only a merge because the previous merge cherry-picked the top commit +svn merge -r$sub_left_make:$sub_left_update_2 ../left-sub --accept postpone +i=$(commit $i "Merge left sub-branch to left") +cd ../.. + +say "Merging EVERYTHING to TRUNK" +svn update +cd trunk +svn merge ../branches/left --accept postpone +svn resolved bang +i=$(commit $i "Merge left to trunk 2") +# this merge, svn happily updates the mergeinfo, but there is actually +# nothing to merge. git-svn will not make a meaningless merge commit. +svn merge ../branches/right --accept postpone +i=$(commit $i "non-merge right to trunk 2") +cd .. + +say "Branching b1 from trunk" +svn update +svn cp trunk branches/b1 +i=$(commit $i "make b1 branch from trunk") + +say "Branching b2 from trunk" +svn update +svn cp trunk branches/b2 +i=$(commit $i "make b2 branch from trunk") + +say "Make a commit to b2" +svn update +cd branches/b2 +echo "b2" > b2file +svn add b2file +i=$(commit $i "b2 update 1") +cd ../.. + +say "Make a commit to b1" +svn update +cd branches/b1 +echo "b1" > b1file +svn add b1file +i=$(commit $i "b1 update 1") +cd ../.. + +say "Merge b1 to trunk" +svn update +cd trunk +svn merge ../branches/b1/ --accept postpone +i=$(commit $i "Merge b1 to trunk") +cd .. + +say "Make a commit to trunk before merging trunk to b2" +svn update +cd trunk +echo "trunk" > trunkfile +svn add trunkfile +i=$(commit $i "trunk commit before merging trunk to b2") +cd .. + +say "Merge trunk to b2" +svn update +cd branches/b2 +svn merge ../../trunk/ --accept postpone +i=$(commit $i "Merge trunk to b2") +cd ../.. + +say "Merge b2 to trunk" +svn update +cd trunk +svn merge ../branches/b2/ --accept postpone +svn resolved b1file +svn resolved trunkfile +i=$(commit $i "Merge b2 to trunk") +cd .. + +say "Creating f1 from trunk with a new file" +svn update +svn cp trunk branches/f1 +cd branches/f1 +echo "f1" > f1file +svn add f1file +cd ../.. +i=$(commit $i "make f1 branch from trunk with a new file") + +say "Creating f2 from trunk with a new file" +svn update +svn cp trunk branches/f2 +cd branches/f2 +echo "f2" > f2file +svn add f2file +cd ../.. +i=$(commit $i "make f2 branch from trunk with a new file") + +say "Merge f1 and f2 to trunk in one go" +svn update +cd trunk +svn merge ../branches/f1/ --accept postpone +svn merge ../branches/f2/ --accept postpone +i=$(commit $i "Merge f1 and f2 to trunk") +cd .. + +say "Adding subdirectory to LEFT" +svn update +cd branches/left +mkdir subdir +echo "Yeehaw" > subdir/cowboy +svn add subdir +i=$(commit $i "add subdirectory to left branch") +cd ../../ + +say "Merging LEFT to TRUNK" +svn update +cd trunk +svn merge ../branches/left --accept postpone +i=$(commit $i "merge left to trunk") +cd .. + +say "Make PARTIAL branch" +svn update +svn cp trunk/subdir branches/partial +i=$(commit $i "make partial branch") + +say "Make a commit to PARTIAL" +svn update +cd branches/partial +echo "racecar" > palindromes +svn add palindromes +i=$(commit $i "partial update") +cd ../../ + +say "Merge PARTIAL to TRUNK" +svn update +cd trunk/subdir +svn merge ../../branches/partial --accept postpone +i=$(commit $i "merge partial to trunk") +cd ../../ + +say "Tagging trunk" +svn update +svn cp trunk tags/v1.0 +i=$(commit $i "tagging v1.0") + +say "Branching BUGFIX from v1.0" +svn update +svn cp tags/v1.0 branches/bugfix +i=$(commit $i "make bugfix branch from tag") + +say "Make a commit to BUGFIX" +svn update +cd branches/bugfix/ +echo "kayak" >> subdir/palindromes +i=$(commit $i "commit to bugfix") +cd ../../ + +say "Merge BUGFIX to TRUNK" +svn update +cd trunk +svn merge ../branches/bugfix/ --accept postpone +i=$(commit $i "Merge BUGFIX to TRUNK") +cd .. + +cd .. +svnadmin dump foo.svn > svn-mergeinfo.dump + +rm -rf foo foo.svn diff --git a/t/t9151/svn-mergeinfo.dump b/t/t9151/svn-mergeinfo.dump new file mode 100644 index 0000000000..47cafcf528 --- /dev/null +++ b/t/t9151/svn-mergeinfo.dump @@ -0,0 +1,2388 @@ +SVN-fs-dump-format-version: 2 + +UUID: d6191530-2693-4a8e-98e7-b194d4c3edd8 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2010-01-19T04:14:02.832406Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 134 +Content-length: 134 + +K 7 +svn:log +V 36 +(r1) Setup trunk, branches, and tags +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:03.055172Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: tags +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 111 +Content-length: 111 + +K 7 +svn:log +V 13 +(r2) ancestor +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:04.064506Z +PROPS-END + +Node-path: trunk/Makefile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2401 +Text-content-md5: bfd8ff778d1492dc6758567373176a89 +Text-content-sha1: 103205ce331f7d64086dba497574734f78439590 +Content-length: 2411 + +PROPS-END +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 3 +Prop-content-length: 119 +Content-length: 119 + +K 7 +svn:log +V 21 +(r3) make left branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:06.040389Z +PROPS-END + +Node-path: branches/left +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: trunk/Makefile +Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89 +Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590 + + +Revision-number: 4 +Prop-content-length: 120 +Content-length: 120 + +K 7 +svn:log +V 22 +(r4) make right branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:08.040905Z +PROPS-END + +Node-path: branches/right +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Node-path: branches/right/Makefile +Node-kind: file +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: trunk/Makefile +Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89 +Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590 + + +Revision-number: 5 +Prop-content-length: 116 +Content-length: 116 + +K 7 +svn:log +V 18 +(r5) left update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:09.049169Z +PROPS-END + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2465 +Text-content-md5: 16e38d9753b061731650561ce01b1195 +Text-content-sha1: 36da4b84ea9b64218ab48171dfc5c48ae025f38b +Content-length: 2465 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 6 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 19 +(r6) right update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:10.049350Z +PROPS-END + +Node-path: branches/right/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2521 +Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0 +Text-content-sha1: 4f29afd038e52f45acb5ef8c41acfc70062a741a +Content-length: 2521 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 7 +Prop-content-length: 116 +Content-length: 116 + +K 7 +svn:log +V 18 +(r7) left update 2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:11.049209Z +PROPS-END + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2529 +Text-content-md5: f6b197cc3f2e89a83e545d4bb003de73 +Text-content-sha1: 2f656677cfec0bceec85e53036ffb63e25126f8e +Content-length: 2529 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 8 +Prop-content-length: 116 +Content-length: 116 + +K 7 +svn:log +V 18 +(r8) left update 3 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:12.049234Z +PROPS-END + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2593 +Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba +Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10 +Content-length: 2593 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 9 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 25 +(r9) make left sub-branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:14.040894Z +PROPS-END + +Node-path: branches/left-sub +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 3 +Node-copyfrom-path: branches/left + + +Node-path: branches/left-sub/Makefile +Node-kind: file +Node-action: delete + +Node-path: branches/left-sub/Makefile +Node-kind: file +Node-action: add +Node-copyfrom-rev: 8 +Node-copyfrom-path: branches/left/Makefile +Text-copy-source-md5: 5ccff689fb290e00b85fe18ee50c54ba +Text-copy-source-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10 + + + + +Revision-number: 10 +Prop-content-length: 128 +Content-length: 128 + +K 7 +svn:log +V 30 +(r10) left sub-branch update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:15.049935Z +PROPS-END + +Node-path: branches/left-sub/README +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 7 +Text-content-md5: fdbcfb6be9afe1121862143f226b51cf +Text-content-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4 +Content-length: 17 + +PROPS-END +crunch + + +Revision-number: 11 +Prop-content-length: 125 +Content-length: 125 + +K 7 +svn:log +V 27 +(r11) Merge left to trunk 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:18.056594Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 54 +Content-length: 54 + +K 13 +svn:mergeinfo +V 19 +/branches/left:2-10 +PROPS-END + + +Node-path: trunk/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2593 +Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba +Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10 +Content-length: 2593 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Revision-number: 12 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 19 +(r12) left update 4 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:19.049620Z +PROPS-END + +Node-path: branches/left/zlonk +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 7 +Text-content-md5: 8b9d8c7c2aaa6167e7d3407a773bbbba +Text-content-sha1: 9716527ebd70a75c27625cacbeb2d897c6e86178 +Content-length: 17 + +PROPS-END +touche + + +Revision-number: 13 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +(r13) right update 2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:20.049659Z +PROPS-END + +Node-path: branches/right/bang +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 8 +Text-content-md5: 34c28f1d2dc6a9adeccc4265bf7516cb +Text-content-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062 +Content-length: 18 + +PROPS-END +thwacke + + +Revision-number: 14 +Prop-content-length: 140 +Content-length: 140 + +K 7 +svn:log +V 42 +(r14) Cherry-pick right 2 commits to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:23.041991Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 75 +Content-length: 75 + +K 13 +svn:mergeinfo +V 40 +/branches/left:2-10 +/branches/right:6-13 +PROPS-END + + +Node-path: trunk/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2713 +Text-content-md5: 0afbe34f244cd662b1f97d708c687f90 +Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14 +Content-length: 2713 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Node-path: trunk/bang +Node-kind: file +Node-action: add +Node-copyfrom-rev: 13 +Node-copyfrom-path: branches/right/bang +Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb +Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062 + + +Revision-number: 15 +Prop-content-length: 126 +Content-length: 126 + +K 7 +svn:log +V 28 +(r15) Merge right to trunk 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:26.054456Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 75 +Content-length: 75 + +K 13 +svn:mergeinfo +V 40 +/branches/left:2-10 +/branches/right:2-14 +PROPS-END + + +Revision-number: 16 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +(r16) right update 3 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:27.049955Z +PROPS-END + +Node-path: branches/right/urkkk +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 6 +Text-content-md5: 5889c8392e16251b0c80927607a03036 +Text-content-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302 +Content-length: 16 + +PROPS-END +whamm + + +Revision-number: 17 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +(r17) trunk update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:28.049615Z +PROPS-END + +Node-path: trunk/vronk +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 4 +Text-content-md5: b2f80fa02a7f1364b9c29d3da44bf9f9 +Text-content-sha1: e994d980c0f2d7a3f76138bf96d57f36f9633828 +Content-length: 14 + +PROPS-END +pow + + +Revision-number: 18 +Prop-content-length: 134 +Content-length: 134 + +K 7 +svn:log +V 36 +(r18) Merge right to left sub-branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:31.061460Z +PROPS-END + +Node-path: branches/left-sub +Node-kind: dir +Node-action: change +Prop-content-length: 55 +Content-length: 55 + +K 13 +svn:mergeinfo +V 20 +/branches/right:2-17 +PROPS-END + + +Node-path: branches/left-sub/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2713 +Text-content-md5: 0afbe34f244cd662b1f97d708c687f90 +Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14 +Content-length: 2713 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Node-path: branches/left-sub/bang +Node-kind: file +Node-action: add +Node-copyfrom-rev: 17 +Node-copyfrom-path: branches/right/bang +Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb +Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062 + + +Node-path: branches/left-sub/urkkk +Node-kind: file +Node-action: add +Node-copyfrom-rev: 17 +Node-copyfrom-path: branches/right/urkkk +Text-copy-source-md5: 5889c8392e16251b0c80927607a03036 +Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302 + + +Revision-number: 19 +Prop-content-length: 128 +Content-length: 128 + +K 7 +svn:log +V 30 +(r19) left sub-branch update 2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:32.049244Z +PROPS-END + +Node-path: branches/left-sub/wham_eth +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 6 +Text-content-md5: 757bcd5818572ef3f9580052617c1c8b +Text-content-sha1: b165019b005c199237ba822c4404e771e93b654a +Content-length: 16 + +PROPS-END +zowie + + +Revision-number: 20 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 19 +(r20) left update 5 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:33.049332Z +PROPS-END + +Node-path: branches/left/glurpp +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 8 +Text-content-md5: 14a169f628e0bb59df9c2160649d0a30 +Text-content-sha1: ef7d929e52177767ecfcd28941f6b7f04b4131e3 +Content-length: 18 + +PROPS-END +eee_yow + + +Revision-number: 21 +Prop-content-length: 146 +Content-length: 146 + +K 7 +svn:log +V 48 +(r21) Cherry-pick left sub-branch commit to left +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:36.041839Z +PROPS-END + +Node-path: branches/left +Node-kind: dir +Node-action: change +Prop-content-length: 56 +Content-length: 56 + +K 13 +svn:mergeinfo +V 21 +/branches/left-sub:19 +PROPS-END + + +Node-path: branches/left/wham_eth +Node-kind: file +Node-action: add +Node-copyfrom-rev: 19 +Node-copyfrom-path: branches/left-sub/wham_eth +Text-copy-source-md5: 757bcd5818572ef3f9580052617c1c8b +Text-copy-source-sha1: b165019b005c199237ba822c4404e771e93b654a + + +Revision-number: 22 +Prop-content-length: 133 +Content-length: 133 + +K 7 +svn:log +V 35 +(r22) Merge left sub-branch to left +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:39.045014Z +PROPS-END + +Node-path: branches/left +Node-kind: dir +Node-action: change +Prop-content-length: 79 +Content-length: 79 + +K 13 +svn:mergeinfo +V 44 +/branches/left-sub:4-19 +/branches/right:2-17 +PROPS-END + + +Node-path: branches/left/Makefile +Node-kind: file +Node-action: change +Text-content-length: 2713 +Text-content-md5: 0afbe34f244cd662b1f97d708c687f90 +Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14 +Content-length: 2713 + +# -DCOLLISION_CHECK if you believe that SHA1's +# 1461501637330902918203684832716283019655932542976 hashes do not give you +# enough guarantees about no collisions between objects ever hapenning. +# +# -DNSEC if you want git to care about sub-second file mtimes and ctimes. +# Note that you need some new glibc (at least >2.2.4) for this, and it will +# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly +# break unless your underlying filesystem supports those sub-second times +# (my ext3 doesn't). +CFLAGS=-g -O3 -Wall + +CC=gcc + + +PROG= update-cache show-diff init-db write-tree read-tree commit-tree \ + cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \ + check-files ls-tree merge-base merge-cache + +all: $(PROG) + +install: $(PROG) + install $(PROG) $(HOME)/bin/ + +LIBS= -lssl -lz + +init-db: init-db.o + +update-cache: update-cache.o read-cache.o + $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS) + +show-diff: show-diff.o read-cache.o + $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS) + +write-tree: write-tree.o read-cache.o + $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS) + +read-tree: read-tree.o read-cache.o + $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS) + +commit-tree: commit-tree.o read-cache.o + $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS) + +cat-file: cat-file.o read-cache.o + $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS) + +fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +checkout-cache: checkout-cache.o read-cache.o + $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS) + +diff-tree: diff-tree.o read-cache.o + $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS) + +rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +show-files: show-files.o read-cache.o + $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS) + +check-files: check-files.o read-cache.o + $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS) + +ls-tree: ls-tree.o read-cache.o + $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS) + +merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o + $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS) + +merge-cache: merge-cache.o read-cache.o + $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS) + +read-cache.o: cache.h +show-diff.o: cache.h + +clean: + rm -f *.o $(PROG) + +backup: clean + cd .. ; tar czvf dircache.tar.gz dir-cache + + +Node-path: branches/left/README +Node-kind: file +Node-action: add +Node-copyfrom-rev: 18 +Node-copyfrom-path: branches/left-sub/README +Text-copy-source-md5: fdbcfb6be9afe1121862143f226b51cf +Text-copy-source-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4 + + +Node-path: branches/left/bang +Node-kind: file +Node-action: add +Node-copyfrom-rev: 18 +Node-copyfrom-path: branches/left-sub/bang +Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb +Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062 + + +Node-path: branches/left/urkkk +Node-kind: file +Node-action: add +Node-copyfrom-rev: 18 +Node-copyfrom-path: branches/left-sub/urkkk +Text-copy-source-md5: 5889c8392e16251b0c80927607a03036 +Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302 + + +Revision-number: 23 +Prop-content-length: 125 +Content-length: 125 + +K 7 +svn:log +V 27 +(r23) Merge left to trunk 2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:42.052798Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 99 +Content-length: 99 + +K 13 +svn:mergeinfo +V 64 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-17 +PROPS-END + + +Node-path: trunk/README +Node-kind: file +Node-action: add +Node-copyfrom-rev: 22 +Node-copyfrom-path: branches/left/README +Text-copy-source-md5: fdbcfb6be9afe1121862143f226b51cf +Text-copy-source-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4 + + +Node-path: trunk/glurpp +Node-kind: file +Node-action: add +Node-copyfrom-rev: 22 +Node-copyfrom-path: branches/left/glurpp +Text-copy-source-md5: 14a169f628e0bb59df9c2160649d0a30 +Text-copy-source-sha1: ef7d929e52177767ecfcd28941f6b7f04b4131e3 + + +Node-path: trunk/urkkk +Node-kind: file +Node-action: add +Node-copyfrom-rev: 22 +Node-copyfrom-path: branches/left/urkkk +Text-copy-source-md5: 5889c8392e16251b0c80927607a03036 +Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302 + + +Node-path: trunk/wham_eth +Node-kind: file +Node-action: add +Node-copyfrom-rev: 22 +Node-copyfrom-path: branches/left/wham_eth +Text-copy-source-md5: 757bcd5818572ef3f9580052617c1c8b +Text-copy-source-sha1: b165019b005c199237ba822c4404e771e93b654a + + +Node-path: trunk/zlonk +Node-kind: file +Node-action: add +Node-copyfrom-rev: 22 +Node-copyfrom-path: branches/left/zlonk +Text-copy-source-md5: 8b9d8c7c2aaa6167e7d3407a773bbbba +Text-copy-source-sha1: 9716527ebd70a75c27625cacbeb2d897c6e86178 + + +Revision-number: 24 +Prop-content-length: 130 +Content-length: 130 + +K 7 +svn:log +V 32 +(r24) non-merge right to trunk 2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:44.038434Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 99 +Content-length: 99 + +K 13 +svn:mergeinfo +V 64 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Revision-number: 25 +Prop-content-length: 129 +Content-length: 129 + +K 7 +svn:log +V 31 +(r25) make b1 branch from trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:18:56.084589Z +PROPS-END + +Node-path: branches/b1 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 24 +Node-copyfrom-path: trunk + + +Revision-number: 26 +Prop-content-length: 129 +Content-length: 129 + +K 7 +svn:log +V 31 +(r26) make b2 branch from trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:18:59.076940Z +PROPS-END + +Node-path: branches/b2 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 25 +Node-copyfrom-path: trunk + + +Revision-number: 27 +Prop-content-length: 115 +Content-length: 115 + +K 7 +svn:log +V 17 +(r27) b2 update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:01.095762Z +PROPS-END + +Node-path: branches/b2/b2file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 3 +Text-content-md5: 5edbdd57cba621eb3c6e601bf563b4dc +Text-content-sha1: 9d4b38049776bd0a2074d67cad23f8eaed35a3b3 +Content-length: 13 + +PROPS-END +b2 + + +Revision-number: 28 +Prop-content-length: 115 +Content-length: 115 + +K 7 +svn:log +V 17 +(r28) b1 update 1 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:03.097465Z +PROPS-END + +Node-path: branches/b1/b1file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 3 +Text-content-md5: 08778dfd9ac4f603231896aba7aad523 +Text-content-sha1: b551771aa4ad5b14123fc3bd98d89db2bc0edd4f +Content-length: 13 + +PROPS-END +b1 + + +Revision-number: 29 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 23 +(r29) Merge b1 to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:06.073175Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 118 +Content-length: 118 + +K 13 +svn:mergeinfo +V 83 +/branches/b1:25-28 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Node-path: trunk/b1file +Node-kind: file +Node-action: add +Node-copyfrom-rev: 28 +Node-copyfrom-path: branches/b1/b1file +Text-copy-source-md5: 08778dfd9ac4f603231896aba7aad523 +Text-copy-source-sha1: b551771aa4ad5b14123fc3bd98d89db2bc0edd4f + + +Revision-number: 30 +Prop-content-length: 143 +Content-length: 143 + +K 7 +svn:log +V 45 +(r30) trunk commit before merging trunk to b2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:08.096353Z +PROPS-END + +Node-path: trunk/trunkfile +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 6 +Text-content-md5: edf45fe5c98c5367733b39bbb2bb20d9 +Text-content-sha1: 7361d1685e5c86dfc523620cfaf598f196f86239 +Content-length: 16 + +PROPS-END +trunk + + +Revision-number: 31 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 23 +(r31) Merge trunk to b2 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:11.081541Z +PROPS-END + +Node-path: branches/b2 +Node-kind: dir +Node-action: change +Prop-content-length: 131 +Content-length: 131 + +K 13 +svn:mergeinfo +V 96 +/branches/b1:25-28 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-22 +/trunk:26-30 +PROPS-END + + +Node-path: branches/b2/b1file +Node-kind: file +Node-action: add +Node-copyfrom-rev: 30 +Node-copyfrom-path: trunk/b1file +Text-copy-source-md5: 08778dfd9ac4f603231896aba7aad523 +Text-copy-source-sha1: b551771aa4ad5b14123fc3bd98d89db2bc0edd4f + + +Node-path: branches/b2/trunkfile +Node-kind: file +Node-action: add +Node-copyfrom-rev: 30 +Node-copyfrom-path: trunk/trunkfile +Text-copy-source-md5: edf45fe5c98c5367733b39bbb2bb20d9 +Text-copy-source-sha1: 7361d1685e5c86dfc523620cfaf598f196f86239 + + +Revision-number: 32 +Prop-content-length: 121 +Content-length: 121 + +K 7 +svn:log +V 23 +(r32) Merge b2 to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:14.117939Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 138 +Content-length: 138 + +K 13 +svn:mergeinfo +V 102 +/branches/b1:25-28 +/branches/b2:26-31 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Node-path: trunk/b2file +Node-kind: file +Node-action: add +Node-copyfrom-rev: 31 +Node-copyfrom-path: branches/b2/b2file +Text-copy-source-md5: 5edbdd57cba621eb3c6e601bf563b4dc +Text-copy-source-sha1: 9d4b38049776bd0a2074d67cad23f8eaed35a3b3 + + +Revision-number: 33 +Prop-content-length: 145 +Content-length: 145 + +K 7 +svn:log +V 47 +(r33) make f1 branch from trunk with a new file +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:17.105832Z +PROPS-END + +Node-path: branches/f1 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 32 +Node-copyfrom-path: trunk + + +Node-path: branches/f1/f1file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 3 +Text-content-md5: 2b1abc6b6c5c0018851f9f8e6475563b +Text-content-sha1: aece6dfba588900e00d95601d22b4408d49580af +Content-length: 13 + +PROPS-END +f1 + + +Revision-number: 34 +Prop-content-length: 145 +Content-length: 145 + +K 7 +svn:log +V 47 +(r34) make f2 branch from trunk with a new file +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:20.110057Z +PROPS-END + +Node-path: branches/f2 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 33 +Node-copyfrom-path: trunk + + +Node-path: branches/f2/f2file +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 3 +Text-content-md5: 575c5638d60271457e54ab7d07309502 +Text-content-sha1: 1c49a440c352f3473efa9512255033b94dc7def0 +Content-length: 13 + +PROPS-END +f2 + + +Revision-number: 35 +Prop-content-length: 128 +Content-length: 128 + +K 7 +svn:log +V 30 +(r35) Merge f1 and f2 to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:24.081490Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 173 +Content-length: 173 + +K 13 +svn:mergeinfo +V 137 +/branches/b1:25-28 +/branches/b2:26-31 +/branches/f1:33-34 +/branches/f2:34 +/branches/left:2-22 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Node-path: trunk/f1file +Node-kind: file +Node-action: add +Node-copyfrom-rev: 34 +Node-copyfrom-path: branches/f1/f1file +Text-copy-source-md5: 2b1abc6b6c5c0018851f9f8e6475563b +Text-copy-source-sha1: aece6dfba588900e00d95601d22b4408d49580af + + +Node-path: trunk/f2file +Node-kind: file +Node-action: add +Node-copyfrom-rev: 34 +Node-copyfrom-path: branches/f2/f2file +Text-copy-source-md5: 575c5638d60271457e54ab7d07309502 +Text-copy-source-sha1: 1c49a440c352f3473efa9512255033b94dc7def0 + + +Revision-number: 36 +Prop-content-length: 135 +Content-length: 135 + +K 7 +svn:log +V 37 +(r36) add subdirectory to left branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:26.113516Z +PROPS-END + +Node-path: branches/left/subdir +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: branches/left/subdir/cowboy +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 7 +Text-content-md5: f1d6530278ad409e68cc675476ad995f +Text-content-sha1: 732d9e3e5c391ffd767a98b45ddcc848de778cea +Content-length: 17 + +PROPS-END +Yeehaw + + +Revision-number: 37 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 25 +(r37) merge left to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:29.073699Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 173 +Content-length: 173 + +K 13 +svn:mergeinfo +V 137 +/branches/b1:25-28 +/branches/b2:26-31 +/branches/f1:33-34 +/branches/f2:34 +/branches/left:2-36 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Node-path: trunk/subdir +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 36 +Node-copyfrom-path: branches/left/subdir + + +Revision-number: 38 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 25 +(r38) make partial branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:32.072243Z +PROPS-END + +Node-path: branches/partial +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 37 +Node-copyfrom-path: trunk/subdir + + +Revision-number: 39 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +(r39) partial update +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:34.097961Z +PROPS-END + +Node-path: branches/partial/palindromes +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 8 +Text-content-md5: 5d1c2024fb5efc4eef812856df1b080c +Text-content-sha1: 5f8509ddd14c91a52864dd1447344e706f9bbc69 +Content-length: 18 + +PROPS-END +racecar + + +Revision-number: 40 +Prop-content-length: 126 +Content-length: 126 + +K 7 +svn:log +V 28 +(r40) merge partial to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:37.080211Z +PROPS-END + +Node-path: trunk/subdir +Node-kind: dir +Node-action: change +Prop-content-length: 246 +Content-length: 246 + +K 13 +svn:mergeinfo +V 210 +/branches/b1/subdir:25-28 +/branches/b2/subdir:26-31 +/branches/f1/subdir:33-34 +/branches/f2/subdir:34 +/branches/left/subdir:2-36 +/branches/left-sub/subdir:4-19 +/branches/partial:38-39 +/branches/right/subdir:2-22 +PROPS-END + + +Node-path: trunk/subdir/palindromes +Node-kind: file +Node-action: add +Node-copyfrom-rev: 39 +Node-copyfrom-path: branches/partial/palindromes +Text-copy-source-md5: 5d1c2024fb5efc4eef812856df1b080c +Text-copy-source-sha1: 5f8509ddd14c91a52864dd1447344e706f9bbc69 + + +Revision-number: 41 +Prop-content-length: 116 +Content-length: 116 + +K 7 +svn:log +V 18 +(r41) tagging v1.0 +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:40.083460Z +PROPS-END + +Node-path: tags/v1.0 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 40 +Node-copyfrom-path: trunk + + +Revision-number: 42 +Prop-content-length: 131 +Content-length: 131 + +K 7 +svn:log +V 33 +(r42) make bugfix branch from tag +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:43.118075Z +PROPS-END + +Node-path: branches/bugfix +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 41 +Node-copyfrom-path: tags/v1.0 + + +Revision-number: 43 +Prop-content-length: 120 +Content-length: 120 + +K 7 +svn:log +V 22 +(r43) commit to bugfix +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:45.079536Z +PROPS-END + +Node-path: branches/bugfix/subdir/palindromes +Node-kind: file +Node-action: change +Text-content-length: 14 +Text-content-md5: 3b12d98578a3f4320ba97e66da54fe5f +Text-content-sha1: 672931c9e8ac2c408209efab2f015638b6d64042 +Content-length: 14 + +racecar +kayak + + +Revision-number: 44 +Prop-content-length: 125 +Content-length: 125 + +K 7 +svn:log +V 27 +(r44) Merge BUGFIX to TRUNK +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-02-22T06:19:48.078914Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 210 +Content-length: 210 + +K 13 +svn:mergeinfo +V 174 +/branches/b1:25-28 +/branches/b2:26-31 +/branches/bugfix:42-43 +/branches/f1:33-34 +/branches/f2:34 +/branches/left:2-36 +/branches/left-sub:4-19 +/branches/right:2-22 +/tags/v1.0:41 +PROPS-END + + +Node-path: trunk/subdir +Node-kind: dir +Node-action: change +Prop-content-length: 297 +Content-length: 297 + +K 13 +svn:mergeinfo +V 261 +/branches/b1/subdir:25-28 +/branches/b2/subdir:26-31 +/branches/bugfix/subdir:42-43 +/branches/f1/subdir:33-34 +/branches/f2/subdir:34 +/branches/left/subdir:2-36 +/branches/left-sub/subdir:4-19 +/branches/partial:38-39 +/branches/right/subdir:2-22 +/tags/v1.0/subdir:41 +PROPS-END + + +Node-path: trunk/subdir/palindromes +Node-kind: file +Node-action: change +Text-content-length: 14 +Text-content-md5: 3b12d98578a3f4320ba97e66da54fe5f +Text-content-sha1: 672931c9e8ac2c408209efab2f015638b6d64042 +Content-length: 14 + +racecar +kayak + + diff --git a/t/t9152-svn-empty-dirs-after-gc.sh b/t/t9152-svn-empty-dirs-after-gc.sh new file mode 100755 index 0000000000..301e779709 --- /dev/null +++ b/t/t9152-svn-empty-dirs-after-gc.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# +# Copyright (c) 2009 Robert Zeh + +test_description='git svn creates empty directories, calls git gc, makes sure they are still empty' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' ' + for i in a b c d d/e d/e/f "weird file name" + do + svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i" + done +' + +test_expect_success 'clone' 'git svn clone "$svnrepo" cloned' + +test_expect_success 'git svn gc runs' ' + ( + cd cloned && + git svn gc + ) +' + +test_expect_success 'git svn mkdirs recreates empty directories after git svn gc' ' + ( + cd cloned && + rm -r * && + git svn mkdirs && + for i in a b c d d/e d/e/f "weird file name" + do + if ! test -d "$i" + then + echo >&2 "$i does not exist" + exit 1 + fi + done + ) +' + +test_done diff --git a/t/t9153-git-svn-rewrite-uuid.sh b/t/t9153-git-svn-rewrite-uuid.sh new file mode 100755 index 0000000000..88a2cfa233 --- /dev/null +++ b/t/t9153-git-svn-rewrite-uuid.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright (c) 2010 Jay Soffian +# + +test_description='git svn --rewrite-uuid test' + +. ./lib-git-svn.sh + +uuid=6cc8ada4-5932-4b4a-8242-3534ed8a3232 + +test_expect_success 'load svn repo' " + svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9153/svn.dump' && + git svn init --minimize-url --rewrite-uuid='$uuid' '$svnrepo' && + git svn fetch + " + +test_expect_success 'verify uuid' " + git cat-file commit refs/remotes/git-svn~0 | \ + grep '^${git_svn_id}: .*@2 $uuid$' && + git cat-file commit refs/remotes/git-svn~1 | \ + grep '^${git_svn_id}: .*@1 $uuid$' + " + +test_done diff --git a/t/t9153/svn.dump b/t/t9153/svn.dump new file mode 100644 index 0000000000..0ddfe7025d --- /dev/null +++ b/t/t9153/svn.dump @@ -0,0 +1,75 @@ +SVN-fs-dump-format-version: 2 + +UUID: b4885626-c94f-4a6c-b179-00c030fc68e8 + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2010-01-23T06:41:03.908576Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 109 +Content-length: 109 + +K 7 +svn:log +V 11 +initial foo +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T06:41:48.353776Z +PROPS-END + +Node-path: foo +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 4 +Text-content-md5: d3b07384d113edec49eaa6238ad5ff00 +Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 +Content-length: 14 + +PROPS-END +foo + + +Revision-number: 2 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 12 +now with bar +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T06:42:14.214640Z +PROPS-END + +Node-path: foo +Node-kind: file +Node-action: change +Text-content-length: 8 +Text-content-md5: f47c75614087a8dd938ba4acff252494 +Text-content-sha1: 4e48e2c9a3d2ca8a708cb0cc545700544efb5021 +Content-length: 8 + +foo +bar + + diff --git a/t/t9154-git-svn-fancy-glob.sh b/t/t9154-git-svn-fancy-glob.sh new file mode 100755 index 0000000000..a6a56a6cb9 --- /dev/null +++ b/t/t9154-git-svn-fancy-glob.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright (c) 2010 Jay Soffian +# + +test_description='git svn fancy glob test' + +. ./lib-git-svn.sh + +test_expect_success 'load svn repo' " + svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9154/svn.dump' && + git svn init --minimize-url -T trunk '$svnrepo' && + git svn fetch + " + +test_expect_success 'add red branch' " + git config svn-remote.svn.branches 'branches/{red}:refs/remotes/*' && + git svn fetch && + git rev-parse refs/remotes/red && + test_must_fail git rev-parse refs/remotes/green && + test_must_fail git rev-parse refs/remotes/blue + " + +test_expect_success 'add green branch' " + GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev && + git config svn-remote.svn.branches 'branches/{red,green}:refs/remotes/*' && + git svn fetch && + git rev-parse refs/remotes/red && + git rev-parse refs/remotes/green && + test_must_fail git rev-parse refs/remotes/blue + " + +test_expect_success 'add all branches' " + GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev && + git config svn-remote.svn.branches 'branches/*:refs/remotes/*' && + git svn fetch && + git rev-parse refs/remotes/red && + git rev-parse refs/remotes/green && + git rev-parse refs/remotes/blue + " + +test_done diff --git a/t/t9154/svn.dump b/t/t9154/svn.dump new file mode 100644 index 0000000000..3dfabb67db --- /dev/null +++ b/t/t9154/svn.dump @@ -0,0 +1,222 @@ +SVN-fs-dump-format-version: 2 + +UUID: a18093a0-5f0b-44e0-8d88-8911ac7078db + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2010-01-23T07:40:25.660053Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 104 +Content-length: 104 + +K 7 +svn:log +V 7 +initial +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:41:33.636365Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: trunk/foo +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 4 +Text-content-md5: d3b07384d113edec49eaa6238ad5ff00 +Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 +Content-length: 14 + +PROPS-END +foo + + +Revision-number: 2 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 12 +add branches +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:42:37.290694Z +PROPS-END + +Node-path: branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: branches/blue +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Node-path: branches/green +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Node-path: branches/red +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: trunk + + +Revision-number: 3 +Prop-content-length: 108 +Content-length: 108 + +K 7 +svn:log +V 10 +red change +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:43:02.208918Z +PROPS-END + +Node-path: branches/red/foo +Node-kind: file +Node-action: change +Text-content-length: 8 +Text-content-md5: 64c3c8cf7d0233ab7627623a68888bd1 +Text-content-sha1: 95a0492027876adfd3891ec71ee37b79ee44d640 +Content-length: 8 + +foo +red + + +Revision-number: 4 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 12 +green change +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:43:15.746586Z +PROPS-END + +Node-path: branches/green/foo +Node-kind: file +Node-action: change +Text-content-length: 10 +Text-content-md5: 0209b6450891abc033d5eaaa9d3a8023 +Text-content-sha1: 87fc3bef9faeec48c0cd61dfc9851db377fdccf7 +Content-length: 10 + +foo +green + + +Revision-number: 5 +Prop-content-length: 109 +Content-length: 109 + +K 7 +svn:log +V 11 +blue change +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:43:29.364811Z +PROPS-END + +Node-path: branches/blue/foo +Node-kind: file +Node-action: change +Text-content-length: 9 +Text-content-md5: 9fbe4c13d0bae86386ae5209b2e6b275 +Text-content-sha1: cc4575083459a16f9aaef796c4a2456d64691ba0 +Content-length: 9 + +foo +blue + + +Revision-number: 6 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 12 +trunk change +K 10 +svn:author +V 3 +jay +K 8 +svn:date +V 27 +2010-01-23T07:44:01.313130Z +PROPS-END + +Node-path: trunk/foo +Node-kind: file +Node-action: change +Text-content-length: 10 +Text-content-md5: 1c4db977d7a57c3bae582aab87948516 +Text-content-sha1: 469c08df449e702cf2a1fe746244a9ef3f837fad +Content-length: 10 + +foo +trunk + + diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index 4efa0c926c..ee39b36d78 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -2,16 +2,20 @@ # # Copyright (c) Robin Rosenberg # -test_description='CVS export comit. ' +test_description='Test export of commits to CVS' . ./test-lib.sh +if ! test_have_prereq PERL; then + skip_all='skipping git cvsexportcommit tests, perl not available' + test_done +fi + cvs >/dev/null 2>&1 if test $? -ne 1 then - test_expect_success 'skipping git-cvsexportcommit tests, cvs not found' : + skip_all='skipping git cvsexportcommit tests, cvs not found' test_done - exit fi CVSROOT=$(pwd)/cvsroot @@ -28,13 +32,25 @@ git add empty && git commit -q -a -m "Initial" 2>/dev/null || exit 1 +check_entries () { + # $1 == directory, $2 == expected + grep '^/' "$1/CVS/Entries" | sort | cut -d/ -f2,3,5 >actual + if test -z "$2" + then + >expected + else + printf '%s\n' "$2" | tr '|' '\012' >expected + fi + test_cmp expected actual +} + test_expect_success \ 'New file' \ 'mkdir A B C D E F && echo hello1 >A/newfile1.txt && echo hello2 >B/newfile2.txt && - cp ../test9200a.png C/newfile3.png && - cp ../test9200a.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png && + cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png && git add A/newfile1.txt && git add B/newfile2.txt && git add C/newfile3.png && @@ -43,14 +59,14 @@ test_expect_success \ id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && git cvsexportcommit -c $id && - test "$(echo $(sort A/CVS/Entries|cut -d/ -f2,3,5))" = "newfile1.txt/1.1/" && - test "$(echo $(sort B/CVS/Entries|cut -d/ -f2,3,5))" = "newfile2.txt/1.1/" && - test "$(echo $(sort C/CVS/Entries|cut -d/ -f2,3,5))" = "newfile3.png/1.1/-kb" && - test "$(echo $(sort D/CVS/Entries|cut -d/ -f2,3,5))" = "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 + check_entries A "newfile1.txt/1.1/" && + check_entries B "newfile2.txt/1.1/" && + check_entries C "newfile3.png/1.1/-kb" && + check_entries D "newfile4.png/1.1/-kb" && + 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 \ @@ -59,27 +75,27 @@ test_expect_success \ rm -f B/newfile2.txt && rm -f C/newfile3.png && echo Hello5 >E/newfile5.txt && - cp ../test9200b.png D/newfile4.png && - cp ../test9200a.png F/newfile6.png && + cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png && git add E/newfile5.txt && git add F/newfile6.png && git commit -a -m "Test: Remove, add and update" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && git cvsexportcommit -c $id && - test "$(echo $(sort A/CVS/Entries|cut -d/ -f2,3,5))" = "newfile1.txt/1.2/" && - test "$(echo $(sort B/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort C/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort D/CVS/Entries|cut -d/ -f2,3,5))" = "newfile4.png/1.2/-kb" && - test "$(echo $(sort E/CVS/Entries|cut -d/ -f2,3,5))" = "newfile5.txt/1.1/" && - test "$(echo $(sort F/CVS/Entries|cut -d/ -f2,3,5))" = "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 + check_entries A "newfile1.txt/1.2/" && + check_entries B "" && + check_entries C "" && + check_entries D "newfile4.png/1.2/-kb" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + 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) +# Should fail (but only on the git cvsexportcommit stage) test_expect_success \ 'Fail to change binary more than one generation old' \ 'cat F/newfile6.png >>D/newfile4.png && @@ -88,7 +104,7 @@ test_expect_success \ git commit -a -m "generation 2" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - ! git cvsexportcommit -c $id + test_must_fail git cvsexportcommit -c $id )' #test_expect_success \ @@ -100,7 +116,7 @@ test_expect_success \ # git commit -a -m "generation 3" && # id=$(git rev-list --max-count=1 HEAD) && # (cd "$CVSWORK" && -# ! git cvsexportcommit -c $id +# test_must_fail git cvsexportcommit -c $id # )' # We reuse the state from two tests back here @@ -115,15 +131,15 @@ test_expect_success \ id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && git cvsexportcommit -c $id && - test "$(echo $(sort A/CVS/Entries|cut -d/ -f2,3,5))" = "newfile1.txt/1.2/" && - test "$(echo $(sort B/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort C/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort D/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort E/CVS/Entries|cut -d/ -f2,3,5))" = "newfile5.txt/1.1/" && - test "$(echo $(sort F/CVS/Entries|cut -d/ -f2,3,5))" = "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 + check_entries A "newfile1.txt/1.2/" && + check_entries B "" && + check_entries C "" && + check_entries D "" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + 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 \ @@ -133,14 +149,14 @@ test_expect_success \ id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && git cvsexportcommit -c $id && - test "$(echo $(sort A/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort B/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort C/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort D/CVS/Entries|cut -d/ -f2,3,5))" = "" && - test "$(echo $(sort E/CVS/Entries|cut -d/ -f2,3,5))" = "newfile5.txt/1.1/" && - test "$(echo $(sort F/CVS/Entries|cut -d/ -f2,3,5))" = "newfile6.png/1.1/-kb" && - diff E/newfile5.txt ../E/newfile5.txt && - diff F/newfile6.png ../F/newfile6.png + check_entries A "" && + check_entries B "" && + check_entries C "" && + check_entries D "" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png )' test_expect_success \ @@ -148,25 +164,25 @@ test_expect_success \ 'mkdir "G g" && echo ok then >"G g/with spaces.txt" && git add "G g/with spaces.txt" && \ - cp ../test9200a.png "G g/with spaces.png" && \ + cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "With spaces" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - git-cvsexportcommit -c $id && - test "$(echo $(sort "G g/CVS/Entries"|cut -d/ -f2,3,5))" = "with spaces.png/1.1/-kb with spaces.txt/1.1/" + git cvsexportcommit -c $id && + check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/" )' test_expect_success \ 'Update file with spaces in file name' \ 'echo Ok then >>"G g/with spaces.txt" && - cat ../test9200a.png >>"G g/with spaces.png" && \ + cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \ git add "G g/with spaces.png" && git commit -a -m "Update with spaces" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - git-cvsexportcommit -c $id - test "$(echo $(sort "G g/CVS/Entries"|cut -d/ -f2,3,5))" = "with spaces.png/1.2/-kb with spaces.txt/1.2/" + git cvsexportcommit -c $id + check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/" )' # Some filesystems mangle pathnames with UTF-8 characters -- @@ -185,13 +201,15 @@ test_expect_success \ 'mkdir -p Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö && echo Foo >Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.txt && git add Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.txt && - cp ../test9200a.png Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png && + cp "$TEST_DIRECTORY"/test9200a.png Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png && git add Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png && git commit -a -m "GÃ¥r det sÃ¥ gÃ¥r det" && \ id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - git-cvsexportcommit -v -c $id && - test "$(echo $(sort Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/CVS/Entries|cut -d/ -f2,3,5))" = "gÃ¥rdetsÃ¥gÃ¥rdet.png/1.1/-kb gÃ¥rdetsÃ¥gÃ¥rdet.txt/1.1/" + git cvsexportcommit -v -c $id && + check_entries \ + "Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö" \ + "gÃ¥rdetsÃ¥gÃ¥rdet.png/1.1/-kb|gÃ¥rdetsÃ¥gÃ¥rdet.txt/1.1/" )' fi @@ -208,14 +226,15 @@ test_expect_success \ git commit -a -m "Update two" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - ! git-cvsexportcommit -c $id + test_must_fail git cvsexportcommit -c $id )' -case "$(git repo-config --bool core.filemode)" in -false) - ;; -*) -test_expect_success \ +if ! test "$(git config --bool core.filemode)" = false +then + test_set_prereq FILEMODE +fi + +test_expect_success FILEMODE \ 'Retain execute bit' \ 'mkdir G && echo executeon >G/on && @@ -225,11 +244,98 @@ test_expect_success \ git add G/off && git commit -a -m "Execute test" && (cd "$CVSWORK" && - git-cvsexportcommit -c HEAD + git cvsexportcommit -c HEAD test -x G/on && ! test -x G/off )' - ;; -esac + +test_expect_success '-w option should work with relative GIT_DIR' ' + mkdir W && + echo foobar >W/file1.txt && + echo bazzle >W/file2.txt && + git add W/file1.txt && + git add W/file2.txt && + git commit -m "More updates" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$GIT_DIR" && + GIT_DIR=. git cvsexportcommit -w "$CVSWORK" -c $id && + check_entries "$CVSWORK/W" "file1.txt/1.1/|file2.txt/1.1/" && + test_cmp "$CVSWORK/W/file1.txt" ../W/file1.txt && + test_cmp "$CVSWORK/W/file2.txt" ../W/file2.txt + ) +' + +test_expect_success 'check files before directories' ' + + echo Notes > release-notes && + git add release-notes && + git commit -m "Add release notes" release-notes && + id=$(git rev-parse HEAD) && + git cvsexportcommit -w "$CVSWORK" -c $id && + + echo new > DS && + echo new > E/DS && + echo modified > release-notes && + git add DS E/DS release-notes && + git commit -m "Add two files with the same basename" && + id=$(git rev-parse HEAD) && + git cvsexportcommit -w "$CVSWORK" -c $id && + check_entries "$CVSWORK/E" "DS/1.1/|newfile5.txt/1.1/" && + check_entries "$CVSWORK" "DS/1.1/|release-notes/1.2/" && + test_cmp "$CVSWORK/DS" DS && + test_cmp "$CVSWORK/E/DS" E/DS && + test_cmp "$CVSWORK/release-notes" release-notes + +' + +test_expect_success 're-commit a removed filename which remains in CVS attic' ' + + (cd "$CVSWORK" && + echo >attic_gremlin && + cvs -Q add attic_gremlin && + cvs -Q ci -m "added attic_gremlin" && + rm attic_gremlin && + cvs -Q rm attic_gremlin && + cvs -Q ci -m "removed attic_gremlin") && + + echo > attic_gremlin && + git add attic_gremlin && + git commit -m "Added attic_gremlin" && + git cvsexportcommit -w "$CVSWORK" -c HEAD && + (cd "$CVSWORK"; cvs -Q update -d) && + test -f "$CVSWORK/attic_gremlin" +' + +# the state of the CVS sandbox may be indeterminate for ' space' +# after this test on some platforms / with some versions of CVS +# consider adding new tests above this point +test_expect_success 'commit a file with leading spaces in the name' ' + + echo space > " space" && + git add " space" && + git commit -m "Add a file with a leading space" && + id=$(git rev-parse HEAD) && + git cvsexportcommit -w "$CVSWORK" -c $id && + check_entries "$CVSWORK" " space/1.1/|DS/1.1/|attic_gremlin/1.3/|release-notes/1.2/" && + test_cmp "$CVSWORK/ space" " space" + +' + +test_expect_success 'use the same checkout for Git and CVS' ' + + (mkdir shared && + cd shared && + unset GIT_DIR && + cvs co . && + git init && + git add " space" && + git commit -m "fake initial commit" && + echo Hello >> " space" && + git commit -m "Another change" " space" && + git cvsexportcommit -W -p -u -c HEAD && + grep Hello " space" && + git diff-files) + +' test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 970d683650..2aeed7bd06 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3,9 +3,9 @@ # Copyright (c) 2007 Shawn Pearce # -test_description='test git-fast-import utility' +test_description='test git fast-import utility' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash file2_data='file2 second line of EOF' @@ -56,14 +56,20 @@ M 644 :2 file2 M 644 :3 file3 M 755 :4 file4 +tag series-A +from :5 +data <<EOF +An annotated tag without a tagger +EOF + INPUT_END test_expect_success \ 'A: create pack from stdin' \ - 'git-fast-import --export-marks=marks.out <input && - git-whatchanged master' + 'git fast-import --export-marks=marks.out <input && + git whatchanged master' test_expect_success \ 'A: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' cat >expect <<EOF author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -73,8 +79,8 @@ initial EOF test_expect_success \ 'A: verify commit' \ - 'git-cat-file commit master | sed 1d >actual && - diff -u expect actual' + 'git cat-file commit master | sed 1d >actual && + test_cmp expect actual' cat >expect <<EOF 100644 blob file2 @@ -83,33 +89,139 @@ cat >expect <<EOF EOF test_expect_success \ 'A: verify tree' \ - 'git-cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual && - diff -u expect actual' + 'git cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual && + test_cmp expect actual' echo "$file2_data" >expect test_expect_success \ 'A: verify file2' \ - 'git-cat-file blob master:file2 >actual && diff -u expect actual' + 'git cat-file blob master:file2 >actual && test_cmp expect actual' echo "$file3_data" >expect test_expect_success \ 'A: verify file3' \ - 'git-cat-file blob master:file3 >actual && diff -u expect actual' + 'git cat-file blob master:file3 >actual && test_cmp expect actual' printf "$file4_data" >expect test_expect_success \ 'A: verify file4' \ - 'git-cat-file blob master:file4 >actual && diff -u expect actual' + 'git cat-file blob master:file4 >actual && test_cmp expect actual' cat >expect <<EOF -:2 `git-rev-parse --verify master:file2` -:3 `git-rev-parse --verify master:file3` -:4 `git-rev-parse --verify master:file4` -:5 `git-rev-parse --verify master^0` +object $(git rev-parse refs/heads/master) +type commit +tag series-A + +An annotated tag without a tagger +EOF +test_expect_success 'A: verify tag/series-A' ' + git cat-file tag tags/series-A >actual && + test_cmp expect actual +' + +cat >expect <<EOF +:2 `git rev-parse --verify master:file2` +:3 `git rev-parse --verify master:file3` +:4 `git rev-parse --verify master:file4` +:5 `git rev-parse --verify master^0` EOF test_expect_success \ 'A: verify marks output' \ - 'diff -u expect marks.out' + 'test_cmp expect marks.out' + +test_expect_success \ + 'A: verify marks import' \ + 'git fast-import \ + --import-marks=marks.out \ + --export-marks=marks.new \ + </dev/null && + test_cmp expect marks.new' + +test_tick +cat >input <<INPUT_END +commit refs/heads/verify--import-marks +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +recreate from :5 +COMMIT + +from :5 +M 755 :2 copy-of-file2 + +INPUT_END +test_expect_success \ + 'A: verify marks import does not crash' \ + 'git fast-import --import-marks=marks.out <input && + git whatchanged verify--import-marks' +test_expect_success \ + 'A: verify pack' \ + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' +cat >expect <<EOF +:000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A copy-of-file2 +EOF +git diff-tree -M -r master verify--import-marks >actual +test_expect_success \ + 'A: verify diff' \ + 'compare_diff_raw expect actual && + 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 @@ -128,17 +240,64 @@ from refs/heads/master M 755 0000000000000000000000000000000000000001 zero1 INPUT_END -test_expect_failure \ - 'B: fail on invalid blob sha1' \ - 'git-fast-import <input' +test_expect_success 'B: fail on invalid blob sha1' ' + test_must_fail git fast-import <input +' +rm -f .git/objects/pack_* .git/objects/index_* + +cat >input <<INPUT_END +commit .badbranchname +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/master + +INPUT_END +test_expect_success 'B: fail on invalid branch name ".badbranchname"' ' + test_must_fail git fast-import <input +' rm -f .git/objects/pack_* .git/objects/index_* +cat >input <<INPUT_END +commit bad[branch]name +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/master + +INPUT_END +test_expect_success 'B: fail on invalid branch name "bad[branch]name"' ' + test_must_fail git fast-import <input +' +rm -f .git/objects/pack_* .git/objects/index_* + +cat >input <<INPUT_END +commit TEMP_TAG +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +tag base +COMMIT + +from refs/heads/master + +INPUT_END +test_expect_success \ + 'B: accept branch name "TEMP_TAG"' \ + 'git fast-import <input && + test -f .git/TEMP_TAG && + test `git rev-parse master` = `git rev-parse TEMP_TAG^`' +rm -f .git/TEMP_TAG + ### ### series C ### -newf=`echo hi newf | git-hash-object -w --stdin` -oldf=`git-rev-parse --verify master:file2` +newf=`echo hi newf | git hash-object -w --stdin` +oldf=`git rev-parse --verify master:file2` test_tick cat >input <<INPUT_END commit refs/heads/branch @@ -155,18 +314,18 @@ D file3 INPUT_END test_expect_success \ 'C: incremental import create pack from stdin' \ - 'git-fast-import <input && - git-whatchanged branch' + 'git fast-import <input && + git whatchanged branch' test_expect_success \ 'C: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' test_expect_success \ 'C: validate reuse existing blob' \ - 'test $newf = `git-rev-parse --verify branch:file2/newf` - test $oldf = `git-rev-parse --verify branch:file2/oldf`' + 'test $newf = `git rev-parse --verify branch:file2/newf` + test $oldf = `git rev-parse --verify branch:file2/oldf`' cat >expect <<EOF -parent `git-rev-parse --verify master^0` +parent `git rev-parse --verify master^0` author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -174,15 +333,15 @@ second EOF test_expect_success \ 'C: verify commit' \ - 'git-cat-file commit branch | sed 1d >actual && - diff -u expect actual' + 'git cat-file commit branch | sed 1d >actual && + test_cmp expect actual' cat >expect <<EOF :000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A file2/newf :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100 file2 file2/oldf :100644 000000 0d92e9f3374ae2947c23aa477cbc68ce598135f1 0000000000000000000000000000000000000000 D file3 EOF -git-diff-tree -M -r master branch >actual +git diff-tree -M -r master branch >actual test_expect_success \ 'C: validate rename result' \ 'compare_diff_raw expect actual' @@ -213,17 +372,17 @@ EOF INPUT_END test_expect_success \ 'D: inline data in commit' \ - 'git-fast-import <input && - git-whatchanged branch' + 'git fast-import <input && + git whatchanged branch' test_expect_success \ 'D: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' cat >expect <<EOF :000000 100755 0000000000000000000000000000000000000000 35a59026a33beac1569b1c7f66f3090ce9c09afc A newdir/exec.sh :000000 100644 0000000000000000000000000000000000000000 046d0371e9220107917db0d0e030628de8a1de9b A newdir/interesting EOF -git-diff-tree -M -r branch^ branch >actual +git diff-tree -M -r branch^ branch >actual test_expect_success \ 'D: validate new files added' \ 'compare_diff_raw expect actual' @@ -231,14 +390,14 @@ test_expect_success \ echo "$file5_data" >expect test_expect_success \ 'D: verify file5' \ - 'git-cat-file blob branch:newdir/interesting >actual && - diff -u expect actual' + 'git cat-file blob branch:newdir/interesting >actual && + test_cmp expect actual' echo "$file6_data" >expect test_expect_success \ 'D: verify file6' \ - 'git-cat-file blob branch:newdir/exec.sh >actual && - diff -u expect actual' + 'git cat-file blob branch:newdir/exec.sh >actual && + test_cmp expect actual' ### ### series E @@ -255,15 +414,15 @@ COMMIT from refs/heads/branch^0 INPUT_END -test_expect_failure \ - 'E: rfc2822 date, --date-format=raw' \ - 'git-fast-import --date-format=raw <input' +test_expect_success 'E: rfc2822 date, --date-format=raw' ' + test_must_fail git fast-import --date-format=raw <input +' test_expect_success \ 'E: rfc2822 date, --date-format=rfc2822' \ - 'git-fast-import --date-format=rfc2822 <input' + 'git fast-import --date-format=rfc2822 <input' test_expect_success \ 'E: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' cat >expect <<EOF author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500 @@ -273,14 +432,14 @@ RFC 2822 type date EOF test_expect_success \ 'E: verify commit' \ - 'git-cat-file commit branch | sed 1,2d >actual && - diff -u expect actual' + 'git cat-file commit branch | sed 1,2d >actual && + test_cmp expect actual' ### ### series F ### -old_branch=`git-rev-parse --verify branch^0` +old_branch=`git rev-parse --verify branch^0` test_tick cat >input <<INPUT_END commit refs/heads/branch @@ -297,12 +456,12 @@ from refs/heads/branch INPUT_END test_expect_success \ 'F: non-fast-forward update skips' \ - 'if git-fast-import <input + 'if git fast-import <input then echo BAD gfi did not fail return 1 else - if test $old_branch = `git-rev-parse --verify branch^0` + if test $old_branch = `git rev-parse --verify branch^0` then : branch unaffected and failure returned return 0 @@ -314,11 +473,11 @@ test_expect_success \ ' test_expect_success \ 'F: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' cat >expect <<EOF -tree `git-rev-parse branch~1^{tree}` -parent `git-rev-parse branch~1` +tree `git rev-parse branch~1^{tree}` +parent `git rev-parse branch~1` author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE @@ -326,14 +485,14 @@ losing things already? EOF test_expect_success \ 'F: verify other commit' \ - 'git-cat-file commit other >actual && - diff -u expect actual' + 'git cat-file commit other >actual && + test_cmp expect actual' ### ### series G ### -old_branch=`git-rev-parse --verify branch^0` +old_branch=`git rev-parse --verify branch^0` test_tick cat >input <<INPUT_END commit refs/heads/branch @@ -347,14 +506,14 @@ from refs/heads/branch~1 INPUT_END test_expect_success \ 'G: non-fast-forward update forced' \ - 'git-fast-import --force <input' + 'git fast-import --force <input' test_expect_success \ 'G: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' test_expect_success \ 'G: branch changed, but logged' \ - 'test $old_branch != `git-rev-parse --verify branch^0` && - test $old_branch = `git-rev-parse --verify branch@{1}`' + 'test $old_branch != `git rev-parse --verify branch^0` && + test $old_branch = `git rev-parse --verify branch@{1}`' ### ### series H @@ -383,11 +542,11 @@ EOF INPUT_END test_expect_success \ 'H: deletall, add 1' \ - 'git-fast-import <input && - git-whatchanged H' + 'git fast-import <input && + git whatchanged H' test_expect_success \ 'H: verify pack' \ - 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' cat >expect <<EOF :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf @@ -396,7 +555,7 @@ cat >expect <<EOF :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting h/e/l/lo :100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D newdir/exec.sh EOF -git-diff-tree -M -r H^ H >actual +git diff-tree -M -r H^ H >actual test_expect_success \ 'H: validate old files removed, new files added' \ 'compare_diff_raw expect actual' @@ -404,8 +563,8 @@ test_expect_success \ echo "$file5_data" >expect test_expect_success \ 'H: verify file' \ - 'git-cat-file blob H:h/e/l/lo >actual && - diff -u expect actual' + 'git cat-file blob H:h/e/l/lo >actual && + test_cmp expect actual' ### ### series I @@ -423,15 +582,15 @@ from refs/heads/branch INPUT_END test_expect_success \ 'I: export-pack-edges' \ - 'git-fast-import --export-pack-edges=edges.list <input' + 'git fast-import --export-pack-edges=edges.list <input' cat >expect <<EOF -.git/objects/pack/pack-.pack: `git-rev-parse --verify export-boundary` +.git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary` EOF test_expect_success \ 'I: verify edge list' \ 'sed -e s/pack-.*pack/pack-.pack/ edges.list >actual && - diff -u expect actual' + test_cmp expect actual' ### ### series J @@ -457,10 +616,10 @@ COMMIT INPUT_END test_expect_success \ 'J: reset existing branch creates empty commit' \ - 'git-fast-import <input' + 'git fast-import <input' test_expect_success \ 'J: branch has 1 commit, empty tree' \ - 'test 1 = `git-rev-list J | wc -l` && + 'test 1 = `git rev-list J | wc -l` && test 0 = `git ls-tree J | wc -l`' ### @@ -487,10 +646,997 @@ from refs/heads/branch^1 INPUT_END test_expect_success \ 'K: reinit branch with from' \ - 'git-fast-import <input' + 'git fast-import <input' test_expect_success \ 'K: verify K^1 = branch^1' \ - 'test `git-rev-parse --verify branch^1` \ - = `git-rev-parse --verify K^1`' + 'test `git rev-parse --verify branch^1` \ + = `git rev-parse --verify K^1`' + +### +### series L +### + +cat >input <<INPUT_END +blob +mark :1 +data <<EOF +some data +EOF + +blob +mark :2 +data <<EOF +other data +EOF + +commit refs/heads/L +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +create L +COMMIT + +M 644 :1 b. +M 644 :1 b/other +M 644 :1 ba + +commit refs/heads/L +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +update L +COMMIT + +M 644 :2 b. +M 644 :2 b/other +M 644 :2 ba +INPUT_END + +cat >expect <<EXPECT_END +:100644 100644 4268632... 55d3a52... M b. +:040000 040000 0ae5cac... 443c768... M b +:100644 100644 4268632... 55d3a52... M ba +EXPECT_END + +test_expect_success \ + 'L: verify internal tree sorting' \ + 'git fast-import <input && + git diff-tree --abbrev --raw L^ L >output && + test_cmp expect output' + +### +### series M +### + +test_tick +cat >input <<INPUT_END +commit refs/heads/M1 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +file rename +COMMIT + +from refs/heads/branch^0 +R file2/newf file2/n.e.w.f + +INPUT_END + +cat >expect <<EOF +:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf file2/n.e.w.f +EOF +test_expect_success \ + 'M: rename file in same subdirectory' \ + 'git fast-import <input && + git diff-tree -M -r M1^ M1 >actual && + compare_diff_raw expect actual' + +cat >input <<INPUT_END +commit refs/heads/M2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +file rename +COMMIT + +from refs/heads/branch^0 +R file2/newf i/am/new/to/you + +INPUT_END + +cat >expect <<EOF +:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 file2/newf i/am/new/to/you +EOF +test_expect_success \ + 'M: rename file to new subdirectory' \ + 'git fast-import <input && + git diff-tree -M -r M2^ M2 >actual && + compare_diff_raw expect actual' + +cat >input <<INPUT_END +commit refs/heads/M3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +file rename +COMMIT + +from refs/heads/M2^0 +R i other/sub + +INPUT_END + +cat >expect <<EOF +:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100 i/am/new/to/you other/sub/am/new/to/you +EOF +test_expect_success \ + 'M: rename subdirectory to new subdirectory' \ + 'git fast-import <input && + git diff-tree -M -r M3^ M3 >actual && + compare_diff_raw expect actual' + +### +### series N +### + +test_tick +cat >input <<INPUT_END +commit refs/heads/N1 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +file copy +COMMIT + +from refs/heads/branch^0 +C file2/newf file2/n.e.w.f + +INPUT_END + +cat >expect <<EOF +:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf file2/n.e.w.f +EOF +test_expect_success \ + 'N: copy file in same subdirectory' \ + 'git fast-import <input && + git diff-tree -C --find-copies-harder -r N1^ N1 >actual && + compare_diff_raw expect actual' + +cat >input <<INPUT_END +commit refs/heads/N2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +clean directory copy +COMMIT + +from refs/heads/branch^0 +C file2 file3 + +commit refs/heads/N2 +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 + +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 +test_expect_success \ + 'N: copy then modify subdirectory' \ + 'git fast-import <input && + git diff-tree -C --find-copies-harder -r N2^^ N2 >actual && + compare_diff_raw expect actual' + +cat >input <<INPUT_END +commit refs/heads/N3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +dirty directory copy +COMMIT + +from refs/heads/branch^0 +M 644 inline file2/file5 +data <<EOF +$file5_data +EOF + +C file2 file3 +D file2/file5 + +INPUT_END + +test_expect_success \ + 'N: copy dirty subdirectory' \ + 'git fast-import <input && + test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`' + +### +### series O +### + +cat >input <<INPUT_END +#we will +commit refs/heads/O1 +# -- ignore all of this text +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +# $GIT_COMMITTER_NAME has inserted here for his benefit. +data <<COMMIT +dirty directory copy +COMMIT + +# don't forget the import blank line! +# +# yes, we started from our usual base of branch^0. +# i like branch^0. +from refs/heads/branch^0 +# and we need to reuse file2/file5 from N3 above. +M 644 inline file2/file5 +# otherwise the tree will be different +data <<EOF +$file5_data +EOF + +# don't forget to copy file2 to file3 +C file2 file3 +# +# or to delete file5 from file2. +D file2/file5 +# are we done yet? + +INPUT_END + +test_expect_success \ + 'O: comments are all skipped' \ + 'git fast-import <input && + test `git rev-parse N3` = `git rev-parse O1`' + +cat >input <<INPUT_END +commit refs/heads/O2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +dirty directory copy +COMMIT +from refs/heads/branch^0 +M 644 inline file2/file5 +data <<EOF +$file5_data +EOF +C file2 file3 +D file2/file5 + +INPUT_END + +test_expect_success \ + 'O: blank lines not necessary after data commands' \ + 'git fast-import <input && + test `git rev-parse N3` = `git rev-parse O2`' + +test_expect_success \ + 'O: repack before next test' \ + 'git repack -a -d' + +cat >input <<INPUT_END +commit refs/heads/O3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zstring +COMMIT +commit refs/heads/O3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zof +COMMIT +checkpoint +commit refs/heads/O3 +mark :5 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zempty +COMMIT +checkpoint +commit refs/heads/O3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zcommits +COMMIT +reset refs/tags/O3-2nd +from :5 +reset refs/tags/O3-3rd +from :5 +INPUT_END + +cat >expect <<INPUT_END +string +of +empty +commits +INPUT_END +test_expect_success \ + 'O: blank lines not necessary after other commands' \ + 'git fast-import <input && + test 8 = `find .git/objects/pack -type f | wc -l` && + test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` && + git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual && + test_cmp expect actual' + +cat >input <<INPUT_END +commit refs/heads/O4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zstring +COMMIT +commit refs/heads/O4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zof +COMMIT +progress Two commits down, 2 to go! +commit refs/heads/O4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zempty +COMMIT +progress Three commits down, 1 to go! +commit refs/heads/O4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +zcommits +COMMIT +progress I'm done! +INPUT_END +test_expect_success \ + 'O: progress outputs as requested by input' \ + 'git fast-import <input >actual && + grep "progress " <input >expect && + test_cmp expect actual' + +### +### series P (gitlinks) +### + +cat >input <<INPUT_END +blob +mark :1 +data 10 +test file + +reset refs/heads/sub +commit refs/heads/sub +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 12 +sub_initial +M 100644 :1 file + +blob +mark :3 +data <<DATAEND +[submodule "sub"] + path = sub + url = "`pwd`/sub" +DATAEND + +commit refs/heads/subuse1 +mark :4 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :3 .gitmodules +M 160000 :2 sub + +blob +mark :5 +data 20 +test file +more data + +commit refs/heads/sub +mark :6 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 11 +sub_second +from :2 +M 100644 :5 file + +commit refs/heads/subuse1 +mark :7 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :4 +M 160000 :6 sub + +INPUT_END + +test_expect_success \ + 'P: supermodule & submodule mix' \ + 'git fast-import <input && + git checkout subuse1 && + 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 submodule init && + git submodule update' + +SUBLAST=$(git rev-parse --verify sub) +SUBPREV=$(git rev-parse --verify sub^) + +cat >input <<INPUT_END +blob +mark :1 +data <<DATAEND +[submodule "sub"] + path = sub + url = "`pwd`/sub" +DATAEND + +commit refs/heads/subuse2 +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :1 .gitmodules +M 160000 $SUBPREV sub + +commit refs/heads/subuse2 +mark :3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :2 +M 160000 $SUBLAST sub + +INPUT_END + +test_expect_success \ + 'P: verbatim SHA gitlinks' \ + 'git branch -D sub && + git gc && git prune && + git fast-import <input && + test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)' + +test_tick +cat >input <<INPUT_END +commit refs/heads/subuse3 +mark :1 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/subuse2 +M 160000 inline sub +data <<DATA +$SUBPREV +DATA + +INPUT_END + +test_expect_success 'P: fail on inline gitlink' ' + test_must_fail git fast-import <input' + +test_tick +cat >input <<INPUT_END +blob +mark :1 +data <<DATA +$SUBPREV +DATA + +commit refs/heads/subuse3 +mark :2 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +corrupt +COMMIT + +from refs/heads/subuse2 +M 160000 :1 sub + +INPUT_END + +test_expect_success 'P: fail on blob mark in gitlink' ' + test_must_fail git fast-import <input' + +### +### series Q (notes) +### + +note1_data="The first note for the first commit" +note2_data="The first note for the second commit" +note3_data="The first note for the third commit" +note1b_data="The second note for the first commit" +note1c_data="The third note for the first commit" +note2b_data="The second note for the second commit" + +test_tick +cat >input <<INPUT_END +blob +mark :2 +data <<EOF +$file2_data +EOF + +commit refs/heads/notes-test +mark :3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +first (:3) +COMMIT + +M 644 :2 file2 + +blob +mark :4 +data $file4_len +$file4_data +commit refs/heads/notes-test +mark :5 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +second (:5) +COMMIT + +M 644 :4 file4 + +commit refs/heads/notes-test +mark :6 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +third (:6) +COMMIT + +M 644 inline file5 +data <<EOF +$file5_data +EOF + +M 755 inline file6 +data <<EOF +$file6_data +EOF + +blob +mark :7 +data <<EOF +$note1_data +EOF + +blob +mark :8 +data <<EOF +$note2_data +EOF + +commit refs/notes/foobar +mark :9 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes (:9) +COMMIT + +N :7 :3 +N :8 :5 +N inline :6 +data <<EOF +$note3_data +EOF + +commit refs/notes/foobar +mark :10 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes (:10) +COMMIT + +N inline :3 +data <<EOF +$note1b_data +EOF + +commit refs/notes/foobar2 +mark :11 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes (:11) +COMMIT + +N inline :3 +data <<EOF +$note1c_data +EOF + +commit refs/notes/foobar +mark :12 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +notes (:12) +COMMIT + +deleteall +N inline :5 +data <<EOF +$note2b_data +EOF + +INPUT_END + +test_expect_success \ + 'Q: commit notes' \ + 'git fast-import <input && + git whatchanged notes-test' +test_expect_success \ + 'Q: verify pack' \ + 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done' + +commit1=$(git rev-parse notes-test~2) +commit2=$(git rev-parse notes-test^) +commit3=$(git rev-parse notes-test) + +cat >expect <<EOF +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +first (:3) +EOF +test_expect_success \ + 'Q: verify first commit' \ + 'git cat-file commit notes-test~2 | sed 1d >actual && + test_cmp expect actual' + +cat >expect <<EOF +parent $commit1 +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +second (:5) +EOF +test_expect_success \ + 'Q: verify second commit' \ + 'git cat-file commit notes-test^ | sed 1d >actual && + test_cmp expect actual' + +cat >expect <<EOF +parent $commit2 +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +third (:6) +EOF +test_expect_success \ + 'Q: verify third commit' \ + 'git cat-file commit notes-test | sed 1d >actual && + test_cmp expect actual' + +cat >expect <<EOF +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +notes (:9) +EOF +test_expect_success \ + 'Q: verify first notes commit' \ + 'git cat-file commit refs/notes/foobar~2 | sed 1d >actual && + test_cmp expect actual' + +cat >expect.unsorted <<EOF +100644 blob $commit1 +100644 blob $commit2 +100644 blob $commit3 +EOF +cat expect.unsorted | sort >expect +test_expect_success \ + 'Q: verify first notes tree' \ + 'git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual && + test_cmp expect actual' + +echo "$note1_data" >expect +test_expect_success \ + 'Q: verify first note for first commit' \ + 'git cat-file blob refs/notes/foobar~2:$commit1 >actual && test_cmp expect actual' + +echo "$note2_data" >expect +test_expect_success \ + 'Q: verify first note for second commit' \ + 'git cat-file blob refs/notes/foobar~2:$commit2 >actual && test_cmp expect actual' + +echo "$note3_data" >expect +test_expect_success \ + 'Q: verify first note for third commit' \ + 'git cat-file blob refs/notes/foobar~2:$commit3 >actual && test_cmp expect actual' + +cat >expect <<EOF +parent `git rev-parse --verify refs/notes/foobar~2` +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +notes (:10) +EOF +test_expect_success \ + 'Q: verify second notes commit' \ + 'git cat-file commit refs/notes/foobar^ | sed 1d >actual && + test_cmp expect actual' + +cat >expect.unsorted <<EOF +100644 blob $commit1 +100644 blob $commit2 +100644 blob $commit3 +EOF +cat expect.unsorted | sort >expect +test_expect_success \ + 'Q: verify second notes tree' \ + 'git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual && + test_cmp expect actual' + +echo "$note1b_data" >expect +test_expect_success \ + 'Q: verify second note for first commit' \ + 'git cat-file blob refs/notes/foobar^:$commit1 >actual && test_cmp expect actual' + +echo "$note2_data" >expect +test_expect_success \ + 'Q: verify first note for second commit' \ + 'git cat-file blob refs/notes/foobar^:$commit2 >actual && test_cmp expect actual' + +echo "$note3_data" >expect +test_expect_success \ + 'Q: verify first note for third commit' \ + 'git cat-file blob refs/notes/foobar^:$commit3 >actual && test_cmp expect actual' + +cat >expect <<EOF +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +notes (:11) +EOF +test_expect_success \ + 'Q: verify third notes commit' \ + 'git cat-file commit refs/notes/foobar2 | sed 1d >actual && + test_cmp expect actual' + +cat >expect.unsorted <<EOF +100644 blob $commit1 +EOF +cat expect.unsorted | sort >expect +test_expect_success \ + 'Q: verify third notes tree' \ + 'git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual && + test_cmp expect actual' + +echo "$note1c_data" >expect +test_expect_success \ + 'Q: verify third note for first commit' \ + 'git cat-file blob refs/notes/foobar2:$commit1 >actual && test_cmp expect actual' + +cat >expect <<EOF +parent `git rev-parse --verify refs/notes/foobar^` +author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +notes (:12) +EOF +test_expect_success \ + 'Q: verify fourth notes commit' \ + 'git cat-file commit refs/notes/foobar | sed 1d >actual && + test_cmp expect actual' + +cat >expect.unsorted <<EOF +100644 blob $commit2 +EOF +cat expect.unsorted | sort >expect +test_expect_success \ + 'Q: verify fourth notes tree' \ + 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual && + test_cmp expect actual' + +echo "$note2b_data" >expect +test_expect_success \ + 'Q: verify second note for second commit' \ + 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual' + +### +### series R (feature and option) +### + +cat >input <<EOF +feature no-such-feature-exists +EOF + +test_expect_success 'R: abort on unsupported feature' ' + test_must_fail git fast-import <input +' + +cat >input <<EOF +feature date-format=now +EOF + +test_expect_success 'R: supported feature is accepted' ' + git fast-import <input +' + +cat >input << EOF +blob +data 3 +hi +feature date-format=now +EOF + +test_expect_success 'R: abort on receiving feature after data command' ' + test_must_fail git fast-import <input +' + +cat >input << EOF +feature import-marks=git.marks +feature import-marks=git2.marks +EOF + +test_expect_success 'R: only one import-marks feature allowed per stream' ' + test_must_fail git fast-import <input +' + +cat >input << EOF +feature export-marks=git.marks +blob +mark :1 +data 3 +hi + +EOF + +test_expect_success \ + 'R: export-marks feature results in a marks file being created' \ + 'cat input | git fast-import && + grep :1 git.marks' + +test_expect_success \ + 'R: export-marks options can be overriden by commandline options' \ + 'cat input | git fast-import --export-marks=other.marks && + grep :1 other.marks' + +cat >input << EOF +feature import-marks=marks.out +feature export-marks=marks.new +EOF + +test_expect_success \ + 'R: import to output marks works without any content' \ + 'cat input | git fast-import && + test_cmp marks.out marks.new' + +cat >input <<EOF +feature import-marks=nonexistant.marks +feature export-marks=marks.new +EOF + +test_expect_success \ + 'R: import marks prefers commandline marks file over the stream' \ + 'cat input | git fast-import --import-marks=marks.out && + test_cmp marks.out marks.new' + + +cat >input <<EOF +feature import-marks=nonexistant.marks +feature export-marks=combined.marks +EOF + +test_expect_success 'R: multiple --import-marks= should be honoured' ' + head -n2 marks.out > one.marks && + tail -n +3 marks.out > two.marks && + git fast-import --import-marks=one.marks --import-marks=two.marks <input && + test_cmp marks.out combined.marks +' + +cat >input <<EOF +feature relative-marks +feature import-marks=relative.in +feature export-marks=relative.out +EOF + +test_expect_success 'R: feature relative-marks should be honoured' ' + mkdir -p .git/info/fast-import/ && + cp marks.new .git/info/fast-import/relative.in && + git fast-import <input && + test_cmp marks.new .git/info/fast-import/relative.out +' + +cat >input <<EOF +feature relative-marks +feature import-marks=relative.in +feature no-relative-marks +feature export-marks=non-relative.out +EOF + +test_expect_success 'R: feature no-relative-marks should be honoured' ' + git fast-import <input && + test_cmp marks.new non-relative.out +' + +cat >input << EOF +option git quiet +blob +data 3 +hi + +EOF + +touch empty + +test_expect_success 'R: quiet option results in no stats being output' ' + cat input | git fast-import 2> output && + test_cmp empty output +' + +cat >input <<EOF +option git non-existing-option +EOF + +test_expect_success 'R: die on unknown option' ' + test_must_fail git fast-import <input +' + +test_expect_success 'R: unknown commandline options are rejected' '\ + test_must_fail git fast-import --non-existing-option < /dev/null +' + +cat >input <<EOF +option non-existing-vcs non-existing-option +EOF + +test_expect_success 'R: ignore non-git options' ' + git fast-import <input +' + +## +## R: very large blobs +## +blobsize=$((2*1024*1024 + 53)) +test-genrandom bar $blobsize >expect +cat >input <<INPUT_END +commit refs/heads/big-file +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +R - big file +COMMIT + +M 644 inline big1 +data $blobsize +INPUT_END +cat expect >>input +cat >>input <<INPUT_END +M 644 inline big2 +data $blobsize +INPUT_END +cat expect >>input +echo >>input + +test_expect_success \ + 'R: blob bigger than threshold' \ + 'test_create_repo R && + git --git-dir=R/.git fast-import --big-file-threshold=1 <input' +test_expect_success \ + 'R: verify created pack' \ + ': >verify && + for p in R/.git/objects/pack/*.pack; + do + git verify-pack -v $p >>verify || exit; + done' +test_expect_success \ + 'R: verify written objects' \ + 'git --git-dir=R/.git cat-file blob big-file:big1 >actual && + test_cmp expect actual && + a=$(git --git-dir=R/.git rev-parse big-file:big1) && + b=$(git --git-dir=R/.git rev-parse big-file:big2) && + test $a = $b' +test_expect_success \ + 'R: blob appears only once' \ + 'n=$(grep $a verify | wc -l) && + test 1 = $n' test_done diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh new file mode 100755 index 0000000000..a5c99d8507 --- /dev/null +++ b/t/t9301-fast-import-notes.sh @@ -0,0 +1,623 @@ +#!/bin/sh +# +# Copyright (c) 2009 Johan Herland +# + +test_description='test git fast-import of notes objects' +. ./test-lib.sh + + +test_tick +cat >input <<INPUT_END +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +first commit +COMMIT + +M 644 inline foo +data <<EOF +file foo in first commit +EOF + +M 755 inline bar +data <<EOF +file bar in first commit +EOF + +M 644 inline baz/xyzzy +data <<EOF +file baz/xyzzy in first commit +EOF + +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +second commit +COMMIT + +M 644 inline foo +data <<EOF +file foo in second commit +EOF + +M 755 inline baz/xyzzy +data <<EOF +file baz/xyzzy in second commit +EOF + +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +third commit +COMMIT + +M 644 inline foo +data <<EOF +file foo in third commit +EOF + +commit refs/heads/master +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +fourth commit +COMMIT + +M 755 inline bar +data <<EOF +file bar in fourth commit +EOF + +INPUT_END + +test_expect_success 'set up master branch' ' + + git fast-import <input && + git whatchanged master +' + +commit4=$(git rev-parse refs/heads/master) +commit3=$(git rev-parse "$commit4^") +commit2=$(git rev-parse "$commit4~2") +commit1=$(git rev-parse "$commit4~3") + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +first notes commit +COMMIT + +M 644 inline $commit1 +data <<EOF +first note for first commit +EOF + +M 755 inline $commit2 +data <<EOF +first note for second commit +EOF + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + third commit + second commit + first note for second commit + first commit + first note for first commit +EXPECT_END + +test_expect_success 'add notes with simple M command' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +second notes commit +COMMIT + +from refs/notes/test^0 +N inline $commit3 +data <<EOF +first note for third commit +EOF + +N inline $commit4 +data <<EOF +first note for fourth commit +EOF + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + first note for fourth commit + third commit + first note for third commit + second commit + first note for second commit + first commit + first note for first commit +EXPECT_END + +test_expect_success 'add notes with simple N command' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +third notes commit +COMMIT + +from refs/notes/test^0 +N inline $commit1 +data <<EOF +second note for first commit +EOF + +N inline $commit2 +data <<EOF +second note for second commit +EOF + +N inline $commit3 +data <<EOF +second note for third commit +EOF + +N inline $commit4 +data <<EOF +second note for fourth commit +EOF + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + second note for fourth commit + third commit + second note for third commit + second commit + second note for second commit + first commit + second note for first commit +EXPECT_END + +test_expect_success 'update existing notes with N command' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +fourth notes commit +COMMIT + +from refs/notes/test^0 +M 644 inline $(echo "$commit3" | sed "s|^..|&/|") +data <<EOF +prefix of note for third commit +EOF + +M 644 inline $(echo "$commit4" | sed "s|^..|&/|") +data <<EOF +prefix of note for fourth commit +EOF + +M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|") +data <<EOF +pre-prefix of note for fourth commit +EOF + +N inline $commit1 +data <<EOF +third note for first commit +EOF + +N inline $commit2 +data <<EOF +third note for second commit +EOF + +N inline $commit3 +data <<EOF +third note for third commit +EOF + +N inline $commit4 +data <<EOF +third note for fourth commit +EOF + + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + pre-prefix of note for fourth commit + prefix of note for fourth commit + third note for fourth commit + third commit + prefix of note for third commit + third note for third commit + second commit + third note for second commit + first commit + third note for first commit +EXPECT_END + +test_expect_success 'add concatentation notes with M command' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +fifth notes commit +COMMIT + +from refs/notes/test^0 +deleteall + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + third commit + second commit + first commit +EXPECT_END + +test_expect_success 'verify that deleteall also removes notes' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +test_tick +cat >input <<INPUT_END +commit refs/notes/test +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +sixth notes commit +COMMIT + +from refs/notes/test^0 +M 644 inline $commit1 +data <<EOF +third note for first commit +EOF + +M 644 inline $commit3 +data <<EOF +third note for third commit +EOF + +N inline $commit1 +data <<EOF +fourth note for first commit +EOF + +N inline $commit3 +data <<EOF +fourth note for third commit +EOF + +INPUT_END + +cat >expect <<EXPECT_END + fourth commit + third commit + fourth note for third commit + second commit + first commit + fourth note for first commit +EXPECT_END + +test_expect_success 'verify that later N commands override earlier M commands' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && + test_cmp expect actual + +' + +# Write fast-import commands to create the given number of commits +fast_import_commits () { + my_ref=$1 + my_num_commits=$2 + my_append_to_file=$3 + my_i=0 + while test $my_i -lt $my_num_commits + do + my_i=$(($my_i + 1)) + test_tick + cat >>"$my_append_to_file" <<INPUT_END +commit $my_ref +mark :$my_i +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +commit #$my_i +COMMIT + +M 644 inline file +data <<EOF +file contents in commit #$my_i +EOF + +INPUT_END + done +} + +# Write fast-import commands to create the given number of notes annotating +# the commits created by fast_import_commits() +fast_import_notes () { + my_notes_ref=$1 + my_num_commits=$2 + my_append_to_file=$3 + my_note_append=$4 + test_tick + cat >>"$my_append_to_file" <<INPUT_END +commit $my_notes_ref +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +committing $my_num_commits notes +COMMIT + +INPUT_END + + my_i=0 + while test $my_i -lt $my_num_commits + do + my_i=$(($my_i + 1)) + cat >>"$my_append_to_file" <<INPUT_END +N inline :$my_i +data <<EOF +note for commit #$my_i$my_note_append +EOF + +INPUT_END + done +} + + +rm input expect +num_commits=400 +# Create lots of commits +fast_import_commits "refs/heads/many_commits" $num_commits input +# Create one note per above commit +fast_import_notes "refs/notes/many_notes" $num_commits input +# Add a couple of non-notes as well +test_tick +cat >>input <<INPUT_END +commit refs/notes/many_notes +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +committing some non-notes to the notes tree +COMMIT + +M 755 inline foobar/non-note.txt +data <<EOF +This is not a note, but rather a regular file residing in a notes tree +EOF + +M 644 inline deadbeef +data <<EOF +Non-note file +EOF + +M 644 inline de/adbeef +data <<EOF +Another non-note file +EOF + +INPUT_END +# Finally create the expected output from all these notes and commits +i=$num_commits +while test $i -gt 0 +do + cat >>expect <<EXPECT_END + commit #$i + note for commit #$i +EXPECT_END + i=$(($i - 1)) +done + +test_expect_success 'add lots of commits and notes' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits | + grep "^ " > actual && + test_cmp expect actual + +' + +test_expect_success 'verify that lots of notes trigger a fanout scheme' ' + + # None of the entries in the top-level notes tree should be a full SHA1 + git ls-tree --name-only refs/notes/many_notes | + while read path + do + if test $(expr length "$path") -ge 40 + then + return 1 + fi + done + +' + +cat >>expect_non-note1 << EOF +This is not a note, but rather a regular file residing in a notes tree +EOF + +cat >>expect_non-note2 << EOF +Non-note file +EOF + +cat >>expect_non-note3 << EOF +Another non-note file +EOF + +test_expect_success 'verify that non-notes are untouched by a fanout change' ' + + git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual && + test_cmp expect_non-note1 actual && + git cat-file -p refs/notes/many_notes:deadbeef > actual && + test_cmp expect_non-note2 actual && + git cat-file -p refs/notes/many_notes:de/adbeef > actual && + test_cmp expect_non-note3 actual + +' +remaining_notes=10 +test_tick +cat >>input <<INPUT_END +commit refs/notes/many_notes +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +removing all notes but $remaining_notes +COMMIT +from refs/notes/many_notes^0 +INPUT_END + +i=$remaining_notes +while test $i -lt $num_commits +do + i=$(($i + 1)) + cat >>input <<INPUT_END +N 0000000000000000000000000000000000000000 :$i +INPUT_END +done + +i=$num_commits +rm expect +while test $i -gt 0 +do + cat >>expect <<EXPECT_END + commit #$i +EXPECT_END + if test $i -le $remaining_notes + then + cat >>expect <<EXPECT_END + note for commit #$i +EXPECT_END + fi + i=$(($i - 1)) +done + +test_expect_success 'remove lots of notes' ' + + git fast-import <input && + GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits | + grep "^ " > actual && + test_cmp expect actual + +' + +test_expect_success 'verify that removing notes trigger fanout consolidation' ' + + # All entries in the top-level notes tree should be a full SHA1 + git ls-tree --name-only -r refs/notes/many_notes | + while read path + do + # Explicitly ignore the non-note paths + test "$path" = "foobar/non-note.txt" && continue + test "$path" = "deadbeef" && continue + test "$path" = "de/adbeef" && continue + + if test $(expr length "$path") -ne 40 + then + return 1 + fi + done + +' + +test_expect_success 'verify that non-notes are untouched by a fanout change' ' + + git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual && + test_cmp expect_non-note1 actual && + git cat-file -p refs/notes/many_notes:deadbeef > actual && + test_cmp expect_non-note2 actual && + git cat-file -p refs/notes/many_notes:de/adbeef > actual && + test_cmp expect_non-note3 actual + +' + + +rm input expect +num_notes_refs=10 +num_commits=16 +some_commits=8 +# Create commits +fast_import_commits "refs/heads/more_commits" $num_commits input +# Create one note per above commit per notes ref +i=0 +while test $i -lt $num_notes_refs +do + i=$(($i + 1)) + fast_import_notes "refs/notes/more_notes_$i" $num_commits input +done +# Trigger branch reloading in git-fast-import by repeating the note creation +i=0 +while test $i -lt $num_notes_refs +do + i=$(($i + 1)) + fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)" +done +# Finally create the expected output from the notes in refs/notes/more_notes_1 +i=$num_commits +while test $i -gt 0 +do + note_data="note for commit #$i" + if test $i -le $some_commits + then + note_data="$note_data (2)" + fi + cat >>expect <<EXPECT_END + commit #$i + $note_data +EXPECT_END + i=$(($i - 1)) +done + +test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" ' + + git fast-import --active-branches=5 <input && + GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits | + grep "^ " > actual && + test_cmp expect actual + +' + +test_done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh new file mode 100755 index 0000000000..d43f37ccaf --- /dev/null +++ b/t/t9350-fast-export.sh @@ -0,0 +1,379 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='git fast-export' +. ./test-lib.sh + +test_expect_success 'setup' ' + + echo break it > file0 && + git add file0 && + test_tick && + echo Wohlauf > file && + git add file && + test_tick && + git commit -m initial && + echo die Luft > file && + echo geht frisch > file2 && + git add file file2 && + test_tick && + git commit -m second && + echo und > file2 && + test_tick && + git commit -m third file2 && + test_tick && + git tag rein && + git checkout -b wer HEAD^ && + echo lange > file2 + test_tick && + git commit -m sitzt file2 && + test_tick && + git tag -a -m valentin muss && + git merge -s ours master + +' + +test_expect_success 'fast-export | fast-import' ' + + MASTER=$(git rev-parse --verify master) && + REIN=$(git rev-parse --verify rein) && + WER=$(git rev-parse --verify wer) && + MUSS=$(git rev-parse --verify muss) && + mkdir new && + git --git-dir=new/.git init && + git fast-export --all | + (cd new && + git fast-import && + test $MASTER = $(git rev-parse --verify refs/heads/master) && + test $REIN = $(git rev-parse --verify refs/tags/rein) && + test $WER = $(git rev-parse --verify refs/heads/wer) && + test $MUSS = $(git rev-parse --verify refs/tags/muss)) + +' + +test_expect_success 'fast-export master~2..master' ' + + git fast-export master~2..master | + sed "s/master/partial/" | + (cd new && + git fast-import && + test $MASTER != $(git rev-parse --verify refs/heads/partial) && + git diff --exit-code master partial && + git diff --exit-code master^ partial^ && + test_must_fail git rev-parse partial~2) + +' + +test_expect_success 'iso-8859-1' ' + + git config i18n.commitencoding ISO8859-1 && + # use author and committer name in ISO-8859-1 to match it. + . "$TEST_DIRECTORY"/t3901-8859-1.txt && + test_tick && + echo rosten >file && + git commit -s -m den file && + git fast-export wer^..wer | + sed "s/wer/i18n/" | + (cd new && + git fast-import && + git cat-file commit i18n | grep "Ãéà óú") + +' +test_expect_success 'import/export-marks' ' + + git checkout -b marks master && + git fast-export --export-marks=tmp-marks HEAD && + test -s tmp-marks && + test $(wc -l < tmp-marks) -eq 3 && + test $( + git fast-export --import-marks=tmp-marks\ + --export-marks=tmp-marks HEAD | + grep ^commit | + wc -l) \ + -eq 0 && + echo change > file && + git commit -m "last commit" file && + test $( + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks HEAD | + grep ^commit\ | + wc -l) \ + -eq 1 && + test $(wc -l < tmp-marks) -eq 4 + +' + +cat > signed-tag-import << EOF +tag sign-your-name +from $(git rev-parse HEAD) +tagger C O Mitter <committer@example.com> 1112911993 -0700 +data 210 +A message for a sign +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.5 (GNU/Linux) + +fakedsignaturefakedsignaturefakedsignaturefakedsignaturfakedsign +aturefakedsignaturefake= +=/59v +-----END PGP SIGNATURE----- +EOF + +test_expect_success 'set up faked signed tag' ' + + cat signed-tag-import | git fast-import + +' + +test_expect_success 'signed-tags=abort' ' + + test_must_fail git fast-export --signed-tags=abort sign-your-name + +' + +test_expect_success 'signed-tags=verbatim' ' + + git fast-export --signed-tags=verbatim sign-your-name > output && + grep PGP output + +' + +test_expect_success 'signed-tags=strip' ' + + git fast-export --signed-tags=strip sign-your-name > output && + ! grep PGP output + +' + +test_expect_success 'setup submodule' ' + + git checkout -f master && + mkdir sub && + ( + cd sub && + git init && + echo test file > file && + git add file && + git commit -m sub_initial + ) && + git submodule add "`pwd`/sub" sub && + git commit -m initial && + test_tick && + ( + cd sub && + echo more data >> file && + git add file && + git commit -m sub_second + ) && + git add sub && + git commit -m second + +' + +test_expect_success 'submodule fast-export | fast-import' ' + + SUBENT1=$(git ls-tree master^ sub) && + SUBENT2=$(git ls-tree master sub) && + rm -rf new && + mkdir new && + git --git-dir=new/.git init && + git fast-export --signed-tags=strip --all | + (cd new && + git fast-import && + test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" && + test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" && + git checkout master && + git submodule init && + git submodule update && + cmp sub/file ../sub/file) + +' + +GIT_AUTHOR_NAME='A U Thor'; export GIT_AUTHOR_NAME +GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME + +test_expect_success 'setup copies' ' + + git config --unset i18n.commitencoding && + git checkout -b copy rein && + git mv file file3 && + git commit -m move1 && + test_tick && + cp file2 file4 && + git add file4 && + git mv file2 file5 && + git commit -m copy1 && + test_tick && + cp file3 file6 && + git add file6 && + git commit -m copy2 && + test_tick && + echo more text >> file6 && + echo even more text >> file6 && + git add file6 && + git commit -m modify && + test_tick && + cp file6 file7 && + echo test >> file7 && + git add file7 && + git commit -m copy_modify + +' + +test_expect_success 'fast-export -C -C | fast-import' ' + + ENTRY=$(git rev-parse --verify copy) && + rm -rf new && + mkdir new && + git --git-dir=new/.git init && + git fast-export -C -C --signed-tags=strip --all > output && + grep "^C \"file6\" \"file7\"\$" output && + cat output | + (cd new && + git fast-import && + test $ENTRY = $(git rev-parse --verify refs/heads/copy)) + +' + +test_expect_success 'fast-export | fast-import when master is tagged' ' + + git tag -m msg last && + git fast-export -C -C --signed-tags=strip --all > output && + test $(grep -c "^tag " output) = 3 + +' + +cat > tag-content << EOF +object $(git rev-parse HEAD) +type commit +tag rosten +EOF + +test_expect_success 'cope with tagger-less tags' ' + + TAG=$(git hash-object -t tag -w tag-content) && + git update-ref refs/tags/sonnenschein $TAG && + git fast-export -C -C --signed-tags=strip --all > output && + test $(grep -c "^tag " output) = 4 && + ! grep "Unspecified Tagger" output && + git fast-export -C -C --signed-tags=strip --all \ + --fake-missing-tagger > output && + test $(grep -c "^tag " output) = 4 && + grep "Unspecified Tagger" output + +' + +test_expect_success 'setup for limiting exports by PATH' ' + mkdir limit-by-paths && + ( + cd limit-by-paths && + git init && + echo hi > there && + git add there && + git commit -m "First file" && + echo foo > bar && + git add bar && + git commit -m "Second file" && + git tag -a -m msg mytag && + echo morefoo >> bar && + git add bar && + git commit -m "Change to second file" + ) +' + +cat > limit-by-paths/expected << EOF +blob +mark :1 +data 3 +hi + +reset refs/tags/mytag +commit refs/tags/mytag +mark :2 +author A U Thor <author@example.com> 1112912713 -0700 +committer C O Mitter <committer@example.com> 1112912713 -0700 +data 11 +First file +M 100644 :1 there + +EOF + +test_expect_success 'dropping tag of filtered out object' ' +( + cd limit-by-paths && + git fast-export --tag-of-filtered-object=drop mytag -- there > output && + test_cmp output expected +) +' + +cat >> limit-by-paths/expected << EOF +tag mytag +from :2 +tagger C O Mitter <committer@example.com> 1112912713 -0700 +data 4 +msg + +EOF + +test_expect_success 'rewriting tag of filtered out object' ' +( + cd limit-by-paths && + git fast-export --tag-of-filtered-object=rewrite mytag -- there > output && + test_cmp output expected +) +' + +cat > limit-by-paths/expected << EOF +blob +mark :1 +data 4 +foo + +blob +mark :2 +data 3 +hi + +reset refs/heads/master +commit refs/heads/master +mark :3 +author A U Thor <author@example.com> 1112912713 -0700 +committer C O Mitter <committer@example.com> 1112912713 -0700 +data 12 +Second file +M 100644 :1 bar +M 100644 :2 there + +EOF + +test_expect_failure 'no exact-ref revisions included' ' + ( + cd limit-by-paths && + git fast-export master~2..master~1 > output && + test_cmp output expected + ) +' + +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 //"` && + git tag tree_tag -m "tagging a tree" $HEAD_TREE && + git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE && + git tag tag-obj_tag -m "tagging a tag" tree_tag-obj && + git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj +' + +test_expect_success 'tree_tag' ' + mkdir result && + (cd result && git init) && + git fast-export tree_tag > fe-stream && + (cd result && git fast-import < ../fe-stream) +' + +# NEEDSWORK: not just check return status, but validate the output +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_done diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh new file mode 100755 index 0000000000..36c457e7f2 --- /dev/null +++ b/t/t9400-git-cvsserver-server.sh @@ -0,0 +1,520 @@ +#!/bin/sh +# +# Copyright (c) 2007 Frank Lichtenheld +# + +test_description='git-cvsserver access + +tests read access to a git repository with the +cvs CLI client via git-cvsserver server' + +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping git cvsserver tests, perl not available' + test_done +fi +cvs >/dev/null 2>&1 +if test $? -ne 1 +then + skip_all='skipping git-cvsserver tests, cvs not found' + test_done +fi +"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { + skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable' + test_done +} + +unset GIT_DIR GIT_CONFIG +WORKDIR=$(pwd) +SERVERDIR=$(pwd)/gitcvs.git +git_config="$SERVERDIR/config" +CVSROOT=":fork:$SERVERDIR" +CVSWORK="$(pwd)/cvswork" +CVS_SERVER=git-cvsserver +export CVSROOT CVS_SERVER + +rm -rf "$CVSWORK" "$SERVERDIR" +test_expect_success 'setup' ' + echo >empty && + git add empty && + git commit -q -m "First Commit" && + mkdir secondroot && + ( cd secondroot && + git init && + touch secondrootfile && + git add secondrootfile && + git commit -m "second root") && + 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.authdb "$SERVERDIR/auth.db" && + echo cvsuser:cvGVEarMLnhlA > "$SERVERDIR/auth.db" +' + +# note that cvs doesn't accept absolute pathnames +# as argument to co -d +test_expect_success 'basic checkout' \ + 'GIT_CONFIG="$git_config" cvs -Q co -d cvswork master && + test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))" = "empty/1.1/" + test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \$p))" = "secondrootfile/1.1/"' + +#------------------------ +# PSERVER AUTHENTICATION +#------------------------ + +cat >request-anonymous <<EOF +BEGIN AUTH REQUEST +$SERVERDIR +anonymous + +END AUTH REQUEST +EOF + +cat >request-git <<EOF +BEGIN AUTH REQUEST +$SERVERDIR +git + +END AUTH REQUEST +EOF + +cat >login-anonymous <<EOF +BEGIN VERIFICATION REQUEST +$SERVERDIR +anonymous + +END VERIFICATION REQUEST +EOF + +cat >login-git <<EOF +BEGIN VERIFICATION REQUEST +$SERVERDIR +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\$"' + +test_expect_success 'pserver authentication failure (non-anonymous user)' \ + 'if cat request-git | git-cvsserver pserver >log 2>&1 + then + false + else + true + 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\$"' + +test_expect_success 'pserver authentication failure (login/non-anonymous user)' \ + 'if cat login-git | git-cvsserver pserver >log 2>&1 + then + false + else + true + fi && + sed -ne \$p log | grep "^I HATE YOU\$"' + + +# misuse pserver authentication for testing of req_Root + +cat >request-relative <<EOF +BEGIN AUTH REQUEST +gitcvs.git +anonymous + +END AUTH REQUEST +EOF + +cat >request-conflict <<EOF +BEGIN AUTH REQUEST +$SERVERDIR +anonymous + +END AUTH REQUEST +Root $WORKDIR +EOF + +test_expect_success 'req_Root failure (relative pathname)' \ + 'if cat request-relative | git-cvsserver pserver >log 2>&1 + then + echo unexpected success + false + else + true + fi && + tail log | grep "^error 1 Root must be an absolute pathname$"' + +test_expect_success 'req_Root failure (conflicting roots)' \ + 'cat request-conflict | git-cvsserver pserver >log 2>&1 && + tail log | grep "^error 1 Conflicting roots specified$"' + +test_expect_success 'req_Root (strict paths)' \ + 'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + +test_expect_success 'req_Root failure (strict-paths)' ' + ! cat request-anonymous | + git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1 +' + +test_expect_success 'req_Root (w/o strict-paths)' \ + 'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + +test_expect_success 'req_Root failure (w/o strict-paths)' ' + ! cat request-anonymous | + git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1 +' + +cat >request-base <<EOF +BEGIN AUTH REQUEST +/gitcvs.git +anonymous + +END AUTH REQUEST +Root /gitcvs.git +EOF + +test_expect_success 'req_Root (base-path)' \ + 'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + +test_expect_success 'req_Root failure (base-path)' ' + ! cat request-anonymous | + git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1 +' + +GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1 + +test_expect_success 'req_Root (export-all)' \ + 'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + +test_expect_success 'req_Root failure (export-all w/o whitelist)' \ + '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)' + +test_expect_success 'req_Root (everything together)' \ + 'cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$"' + +GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1 + +#-------------- +# CONFIG TESTS +#-------------- + +test_expect_success 'gitcvs.enabled = false' \ + 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false && + if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 + then + echo unexpected cvs success + false + else + true + fi && + grep "GITCVS emulation disabled" cvs.log && + test ! -d cvswork2' + +rm -fr cvswork2 +test_expect_success 'gitcvs.ext.enabled = true' \ + 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 && + test_cmp cvswork cvswork2' + +rm -fr cvswork2 +test_expect_success 'gitcvs.ext.enabled = false' \ + 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled false && + GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && + if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 + then + echo unexpected cvs success + false + else + true + fi && + grep "GITCVS emulation disabled" cvs.log && + test ! -d cvswork2' + +rm -fr cvswork2 +test_expect_success 'gitcvs.dbname' \ + 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 && + test_cmp cvswork cvswork2 && + test -f "$SERVERDIR/gitcvs.ext.master.sqlite" && + cmp "$SERVERDIR/gitcvs.master.sqlite" "$SERVERDIR/gitcvs.ext.master.sqlite"' + +rm -fr cvswork2 +test_expect_success 'gitcvs.ext.dbname' \ + 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && + GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 && + test_cmp cvswork cvswork2 && + test -f "$SERVERDIR/gitcvs1.ext.master.sqlite" && + test ! -f "$SERVERDIR/gitcvs2.ext.master.sqlite" && + cmp "$SERVERDIR/gitcvs.master.sqlite" "$SERVERDIR/gitcvs1.ext.master.sqlite"' + + +#------------ +# CVS UPDATE +#------------ + +rm -fr "$SERVERDIR" +cd "$WORKDIR" && +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" || +exit 1 + +test_expect_success 'cvs update (create new file)' \ + 'echo testfile1 >testfile1 && + git add testfile1 && + git commit -q -m "Add testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" && + test_cmp testfile1 ../testfile1' + +cd "$WORKDIR" +test_expect_success 'cvs update (update existing file)' \ + 'echo line 2 >>testfile1 && + git add testfile1 && + git commit -q -m "Append to testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" && + test_cmp testfile1 ../testfile1' + +cd "$WORKDIR" +#TODO: cvsserver doesn't support update w/o -d +test_expect_failure "cvs update w/o -d doesn't create subdir (TODO)" ' + mkdir test && + echo >test/empty && + git add test && + git commit -q -m "Single Subdirectory" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test ! -d test +' + +cd "$WORKDIR" +test_expect_success 'cvs update (subdirectories)' \ + '(for dir in A A/B A/B/C A/D E; do + mkdir $dir && + echo "test file in $dir" >"$dir/file_in_$(echo $dir|sed -e "s#/# #g")" && + git add $dir; + done) && + git commit -q -m "deep sub directory structure" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update -d && + (for dir in A A/B A/B/C A/D E; do + filename="file_in_$(echo $dir|sed -e "s#/# #g")" && + if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" && + test_cmp "$dir/$filename" "../$dir/$filename"; then + : + else + echo >failure + fi + done) && + test ! -f failure' + +cd "$WORKDIR" +test_expect_success 'cvs update (delete file)' \ + 'git rm testfile1 && + git commit -q -m "Remove testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test -z "$(grep testfile1 CVS/Entries)" && + test ! -f testfile1' + +cd "$WORKDIR" +test_expect_success 'cvs update (re-add deleted file)' \ + 'echo readded testfile >testfile1 && + git add testfile1 && + git commit -q -m "Re-Add testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" && + test_cmp testfile1 ../testfile1' + +cd "$WORKDIR" +test_expect_success 'cvs update (merge)' \ + 'echo Line 0 >expected && + for i in 1 2 3 4 5 6 7 + do + echo Line $i >>merge + echo Line $i >>expected + done && + echo Line 8 >>expected && + git add merge && + git commit -q -m "Merge test (pre-merge)" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" && + test_cmp merge ../merge && + ( echo Line 0; cat merge ) >merge.tmp && + mv merge.tmp merge && + cd "$WORKDIR" && + echo Line 8 >>merge && + git add merge && + git commit -q -m "Merge test (merge)" && + git push gitcvs.git >/dev/null && + cd cvswork && + sleep 1 && touch merge && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../expected' + +cd "$WORKDIR" + +cat >expected.C <<EOF +<<<<<<< merge.mine +Line 0 +======= +LINE 0 +>>>>>>> merge.3 +EOF + +for i in 1 2 3 4 5 6 7 8 +do + echo Line $i >>expected.C +done + +test_expect_success 'cvs update (conflict merge)' \ + '( echo LINE 0; cat merge ) >merge.tmp && + mv merge.tmp merge && + git add merge && + git commit -q -m "Merge test (conflict)" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../expected.C' + +cd "$WORKDIR" +test_expect_success 'cvs update (-C)' \ + 'cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update -C && + test_cmp merge ../merge' + +cd "$WORKDIR" +test_expect_success 'cvs update (merge no-op)' \ + 'echo Line 9 >>merge && + cp merge cvswork/merge && + git add merge && + git commit -q -m "Merge test (no-op)" && + git push gitcvs.git >/dev/null && + cd cvswork && + sleep 1 && touch merge && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../merge' + +cd "$WORKDIR" +test_expect_success 'cvs update (-p)' ' + touch really-empty && + echo Line 1 > no-lf && + printf "Line 2" >> no-lf && + git add really-empty no-lf && + git commit -q -m "Update -p test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + rm -f failures && + for i in merge no-lf empty really-empty; do + GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out + test_cmp $i.out ../$i >>failures 2>&1 + done && + test -z "$(cat failures)" +' + +cd "$WORKDIR" +test_expect_success 'cvs update (module list supports packed refs)' ' + GIT_DIR="$SERVERDIR" git pack-refs --all && + GIT_CONFIG="$git_config" cvs -n up -d 2> out && + grep "cvs update: New directory \`master'\''" < out +' + +#------------ +# CVS STATUS +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs status' ' + mkdir status.dir && + echo Line > status.dir/status.file && + echo Line > status.file && + git add status.dir status.file && + git commit -q -m "Status test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out && + test $(wc -l <../out) = 2 +' + +cd "$WORKDIR" +test_expect_success 'cvs status (nonrecursive)' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out && + test $(wc -l <../out) = 1 +' + +cd "$WORKDIR" +test_expect_success 'cvs status (no subdirs in header)' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs status | grep ^File: >../out && + ! grep / <../out +' + +#------------ +# CVS CHECKOUT +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs co -c (shows module database)' ' + GIT_CONFIG="$git_config" cvs co -c > out && + grep "^master[ ]\+master$" < out && + ! grep -v "^master[ ]\+master$" < out +' + +#------------ +# CVS ANNOTATE +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs annotate' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs annotate merge >../out && + sed -e "s/ .*//" ../out >../actual && + for i in 3 1 1 1 1 1 1 1 2 4; do echo 1.$i; done >../expect && + test_cmp ../expect ../actual +' + +test_done diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh new file mode 100755 index 0000000000..925bd0fbed --- /dev/null +++ b/t/t9401-git-cvsserver-crlf.sh @@ -0,0 +1,332 @@ +#!/bin/sh +# +# Copyright (c) 2008 Matthew Ogilvie +# Parts adapted from other tests. +# + +test_description='git-cvsserver -kb modes + +tests -kb mode for binary files when accessing a git +repository using cvs CLI client via git-cvsserver server' + +. ./test-lib.sh + +marked_as () { + foundEntry="$(grep "^/$2/" "$1/CVS/Entries")" + if [ x"$foundEntry" = x"" ] ; then + echo "NOT FOUND: $1 $2 1 $3" >> "${WORKDIR}/marked.log" + return 1 + fi + test x"$(grep "^/$2/" "$1/CVS/Entries" | cut -d/ -f5)" = x"$3" + stat=$? + echo "$1 $2 $stat '$3'" >> "${WORKDIR}/marked.log" + return $stat +} + +not_present() { + foundEntry="$(grep "^/$2/" "$1/CVS/Entries")" + if [ -r "$1/$2" ] ; then + echo "Error: File still exists: $1 $2" >> "${WORKDIR}/marked.log" + return 1; + fi + if [ x"$foundEntry" != x"" ] ; then + echo "Error: should not have found: $1 $2" >> "${WORKDIR}/marked.log" + return 1; + else + echo "Correctly not found: $1 $2" >> "${WORKDIR}/marked.log" + return 0; + fi +} + +cvs >/dev/null 2>&1 +if test $? -ne 1 +then + skip_all='skipping git-cvsserver tests, cvs not found' + test_done +fi +if ! test_have_prereq PERL +then + skip_all='skipping git-cvsserver tests, perl not available' + test_done +fi +"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { + skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable' + test_done +} + +unset GIT_DIR GIT_CONFIG +WORKDIR=$(pwd) +SERVERDIR=$(pwd)/gitcvs.git +git_config="$SERVERDIR/config" +CVSROOT=":fork:$SERVERDIR" +CVSWORK="$(pwd)/cvswork" +CVS_SERVER=git-cvsserver +export CVSROOT CVS_SERVER + +rm -rf "$CVSWORK" "$SERVERDIR" +test_expect_success 'setup' ' + echo "Simple text file" >textfile.c && + echo "File with embedded NUL: Q <- there" | q_to_nul > binfile.bin && + mkdir subdir && + echo "Another text file" > subdir/file.h && + echo "Another binary: Q (this time CR)" | q_to_cr > subdir/withCr.bin && + echo "Mixed up NUL, but marked text: Q <- there" | q_to_nul > mixedUp.c + echo "Unspecified" > subdir/unspecified.other && + echo "/*.bin -crlf" > .gitattributes && + echo "/*.c crlf" >> .gitattributes && + echo "subdir/*.bin -crlf" >> .gitattributes && + echo "subdir/*.c crlf" >> .gitattributes && + echo "subdir/file.h crlf" >> .gitattributes && + git add .gitattributes textfile.c binfile.bin mixedUp.c subdir/* && + git commit -q -m "First Commit" && + 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" +' + +test_expect_success 'cvs co (default crlf)' ' + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + test x"$(grep '/-k' cvswork/CVS/Entries cvswork/subdir/CVS/Entries)" = x"" +' + +rm -rf cvswork +test_expect_success 'cvs co (allbinary)' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.allbinary true && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + marked_as cvswork textfile.c -kb && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes -kb && + marked_as cvswork mixedUp.c -kb && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h -kb && + marked_as cvswork/subdir unspecified.other -kb +' + +rm -rf cvswork cvs.log +test_expect_success 'cvs co (use attributes/allbinary)' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.usecrlfattr true && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes -kb && + marked_as cvswork mixedUp.c "" && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h "" && + marked_as cvswork/subdir unspecified.other -kb +' + +rm -rf cvswork +test_expect_success 'cvs co (use attributes)' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.allbinary false && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes "" && + marked_as cvswork mixedUp.c "" && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h "" && + marked_as cvswork/subdir unspecified.other "" +' + +test_expect_success 'adding files' ' + cd cvswork/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 .. && + 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 && + echo 'junk' > subdir/file.h && + echo 'hi' > subdir/newfile.c && + echo 'hello' >> binfile.bin && + 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 .. && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes "" && + marked_as cvswork mixedUp.c "" && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h "" && + marked_as cvswork/subdir unspecified.other "" && + marked_as cvswork/subdir newfile.bin -kb && + marked_as cvswork/subdir newfile.c "" && + echo "File with embedded NUL: Q <- there" | q_to_nul > tmpExpect1 && + echo "hello" >> tmpExpect1 && + cmp cvswork/binfile.bin tmpExpect1 +' + +rm -rf cvswork +test_expect_success 'cvs co (use attributes/guess)' ' + GIT_DIR="$SERVERDIR" git config gitcvs.allbinary guess && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes "" && + marked_as cvswork mixedUp.c "" && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h "" && + marked_as cvswork/subdir unspecified.other "" && + marked_as cvswork/subdir newfile.bin -kb && + marked_as cvswork/subdir newfile.c "" +' + +test_expect_success 'setup multi-line files' ' + ( echo "line 1" && + echo "line 2" && + echo "line 3" && + echo "line 4 with NUL: Q <-" ) | q_to_nul > multiline.c && + git add multiline.c && + ( echo "line 1" && + echo "line 2" && + echo "line 3" && + echo "line 4" ) | q_to_nul > multilineTxt.c && + git add multilineTxt.c && + git commit -q -m "multiline files" && + git push gitcvs.git >/dev/null +' + +rm -rf cvswork +test_expect_success 'cvs co (guess)' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.usecrlfattr false && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes "" && + marked_as cvswork mixedUp.c -kb && + marked_as cvswork multiline.c -kb && + marked_as cvswork multilineTxt.c "" && + marked_as cvswork/subdir withCr.bin -kb && + marked_as cvswork/subdir file.h "" && + marked_as cvswork/subdir unspecified.other "" && + marked_as cvswork/subdir newfile.bin "" && + marked_as cvswork/subdir newfile.c "" +' + +test_expect_success 'cvs co another copy (guess)' ' + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 && + marked_as cvswork2 textfile.c "" && + marked_as cvswork2 binfile.bin -kb && + marked_as cvswork2 .gitattributes "" && + marked_as cvswork2 mixedUp.c -kb && + marked_as cvswork2 multiline.c -kb && + marked_as cvswork2 multilineTxt.c "" && + marked_as cvswork2/subdir withCr.bin -kb && + marked_as cvswork2/subdir file.h "" && + marked_as cvswork2/subdir unspecified.other "" && + marked_as cvswork2/subdir newfile.bin "" && + marked_as cvswork2/subdir newfile.c "" +' + +test_expect_success 'add text (guess)' ' + cd cvswork && + echo "simpleText" > simpleText.c && + GIT_CONFIG="$git_config" cvs -Q add simpleText.c && + cd .. && + marked_as cvswork simpleText.c "" +' + +test_expect_success 'add bin (guess)' ' + cd cvswork && + echo "simpleBin: NUL: Q <- there" | q_to_nul > simpleBin.bin && + GIT_CONFIG="$git_config" cvs -Q add simpleBin.bin && + cd .. && + marked_as cvswork simpleBin.bin -kb +' + +test_expect_success 'remove files (guess)' ' + 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 ../.. && + 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 .. && + marked_as cvswork textfile.c "" && + marked_as cvswork binfile.bin -kb && + marked_as cvswork .gitattributes "" && + marked_as cvswork mixedUp.c -kb && + marked_as cvswork multiline.c -kb && + marked_as cvswork multilineTxt.c "" && + not_present cvswork/subdir withCr.bin && + not_present cvswork/subdir file.h && + marked_as cvswork/subdir unspecified.other "" && + marked_as cvswork/subdir newfile.bin "" && + marked_as cvswork/subdir newfile.c "" && + marked_as cvswork simpleBin.bin -kb && + marked_as cvswork simpleText.c "" +' + +test_expect_success 'update subdir of other copy (guess)' ' + cd cvswork2/subdir && + GIT_CONFIG="$git_config" cvs -Q update && + cd ../.. && + marked_as cvswork2 textfile.c "" && + marked_as cvswork2 binfile.bin -kb && + marked_as cvswork2 .gitattributes "" && + marked_as cvswork2 mixedUp.c -kb && + marked_as cvswork2 multiline.c -kb && + marked_as cvswork2 multilineTxt.c "" && + not_present cvswork2/subdir withCr.bin && + not_present cvswork2/subdir file.h && + marked_as cvswork2/subdir unspecified.other "" && + marked_as cvswork2/subdir newfile.bin "" && + marked_as cvswork2/subdir newfile.c "" && + not_present cvswork2 simpleBin.bin && + not_present cvswork2 simpleText.c +' + +echo "starting update/merge" >> "${WORKDIR}/marked.log" +test_expect_success 'update/merge full other copy (guess)' ' + git pull gitcvs.git master && + sed "s/3/replaced_3/" < multilineTxt.c > ml.temp && + mv ml.temp multilineTxt.c && + git add multilineTxt.c && + git commit -q -m "modify multiline file" >> "${WORKDIR}/marked.log" && + git push gitcvs.git >/dev/null && + 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 .. && + marked_as cvswork2 textfile.c "" && + marked_as cvswork2 binfile.bin -kb && + marked_as cvswork2 .gitattributes "" && + marked_as cvswork2 mixedUp.c -kb && + marked_as cvswork2 multiline.c -kb && + marked_as cvswork2 multilineTxt.c "" && + not_present cvswork2/subdir withCr.bin && + not_present cvswork2/subdir file.h && + marked_as cvswork2/subdir unspecified.other "" && + marked_as cvswork2/subdir newfile.bin "" && + marked_as cvswork2/subdir newfile.c "" && + marked_as cvswork2 simpleBin.bin -kb && + marked_as cvswork2 simpleText.c "" && + echo "line replaced_1" > tmpExpect2 && + echo "line 2" >> tmpExpect2 && + echo "line replaced_3" >> tmpExpect2 && + echo "line 4" | q_to_nul >> tmpExpect2 && + cmp cvswork2/multilineTxt.c tmpExpect2 +' + +test_done diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh new file mode 100755 index 0000000000..4f2b9b062b --- /dev/null +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -0,0 +1,679 @@ +#!/bin/sh +# +# Copyright (c) 2007 Jakub Narebski +# + +test_description='gitweb as standalone script (basic tests). + +This test runs gitweb (git web interface) as CGI script from +commandline, and checks that it would not write any errors +or warnings to log.' + + +. ./gitweb-lib.sh + +# ---------------------------------------------------------------------- +# no commits (empty, just initialized repository) + +test_expect_success \ + 'no commits: projects_list (implicit)' \ + 'gitweb_run' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: projects_index' \ + 'gitweb_run "a=project_index"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git summary (implicit)' \ + 'gitweb_run "p=.git"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git commit (implicit HEAD)' \ + 'gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git commitdiff (implicit HEAD)' \ + 'gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git tree (implicit HEAD)' \ + 'gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git heads' \ + 'gitweb_run "p=.git;a=heads"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'no commits: .git tags' \ + 'gitweb_run "p=.git;a=tags"' +test_debug 'cat gitweb.log' + + +# ---------------------------------------------------------------------- +# initial commit + +test_expect_success \ + 'Make initial commit' \ + 'echo "Not an empty file." > file && + git add file && + git commit -a -m "Initial commit." && + git branch b' + +test_expect_success \ + 'projects_list (implicit)' \ + 'gitweb_run' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'projects_index' \ + 'gitweb_run "a=project_index"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git summary (implicit)' \ + 'gitweb_run "p=.git"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commit (implicit HEAD)' \ + 'gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commitdiff (implicit HEAD, root commit)' \ + 'gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commitdiff_plain (implicit HEAD, root commit)' \ + 'gitweb_run "p=.git;a=commitdiff_plain"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commit (HEAD)' \ + 'gitweb_run "p=.git;a=commit;h=HEAD"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git tree (implicit HEAD)' \ + 'gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git blob (file)' \ + 'gitweb_run "p=.git;a=blob;f=file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git blob_plain (file)' \ + 'gitweb_run "p=.git;a=blob_plain;f=file"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# nonexistent objects + +test_expect_success \ + '.git commit (non-existent)' \ + 'gitweb_run "p=.git;a=commit;h=non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commitdiff (non-existent)' \ + 'gitweb_run "p=.git;a=commitdiff;h=non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git commitdiff (non-existent vs HEAD)' \ + 'gitweb_run "p=.git;a=commitdiff;hp=non-existent;h=HEAD"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git tree (0000000000000000000000000000000000000000)' \ + 'gitweb_run "p=.git;a=tree;h=0000000000000000000000000000000000000000"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git tag (0000000000000000000000000000000000000000)' \ + 'gitweb_run "p=.git;a=tag;h=0000000000000000000000000000000000000000"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git blob (non-existent)' \ + 'gitweb_run "p=.git;a=blob;f=non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + '.git blob_plain (non-existent)' \ + 'gitweb_run "p=.git;a=blob_plain;f=non-existent"' +test_debug 'cat gitweb.log' + + +# ---------------------------------------------------------------------- +# commitdiff testing (implicit, one implicit tree-ish) + +test_expect_success \ + 'commitdiff(0): root' \ + 'gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): file added' \ + 'echo "New file" > new_file && + git add new_file && + git commit -a -m "File added." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): mode change' \ + 'test_chmod +x new_file && + git commit -a -m "Mode changed." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): file renamed' \ + 'git mv new_file renamed_file && + git commit -a -m "File renamed." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success SYMLINKS \ + 'commitdiff(0): file to symlink' \ + 'rm renamed_file && + ln -s file renamed_file && + git commit -a -m "File to symlink." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): file deleted' \ + 'git rm renamed_file && + rm -f renamed_file && + git commit -a -m "File removed." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): file copied / new file' \ + 'cp file file2 && + git add file2 && + git commit -a -m "File copied." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): mode change and modified' \ + 'echo "New line" >> file2 && + test_chmod +x file2 && + git commit -a -m "Mode change and modification." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): renamed and modified' \ + 'cat >file2<<EOF && +Dominus regit me, +et nihil mihi deerit. +In loco pascuae ibi me collocavit, +super aquam refectionis educavit me; +animam meam convertit, +deduxit me super semitas jusitiae, +propter nomen suum. +EOF + git commit -a -m "File added." && + git mv file2 file3 && + echo "Propter nomen suum." >> file3 && + git commit -a -m "File rename and modification." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): renamed, mode change and modified' \ + 'git mv file3 file2 && + echo "Propter nomen suum." >> file2 && + test_chmod +x file2 && + git commit -a -m "File rename, mode change and modification." && + gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# commitdiff testing (taken from t4114-apply-typechange.sh) + +test_expect_success SYMLINKS 'setup typechange commits' ' + echo "hello world" > foo && + echo "hi planet" > bar && + git update-index --add foo bar && + git commit -m initial && + git branch initial && + rm -f foo && + ln -s bar foo && + git update-index foo && + git commit -m "foo symlinked to bar" && + git branch foo-symlinked-to-bar && + rm -f foo && + echo "how far is the sun?" > foo && + git update-index foo && + git commit -m "foo back to file" && + git branch foo-back-to-file && + rm -f foo && + git update-index --remove foo && + mkdir foo && + echo "if only I knew" > foo/baz && + git update-index --add foo/baz && + git commit -m "foo becomes a directory" && + git branch "foo-becomes-a-directory" && + echo "hello world" > foo/baz && + git update-index foo/baz && + git commit -m "foo/baz is the original foo" && + git branch foo-baz-renamed-from-foo + ' + +test_expect_success \ + 'commitdiff(2): file renamed from foo to foo/baz' \ + 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-baz-renamed-from-foo"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): file renamed from foo/baz to foo' \ + 'gitweb_run "p=.git;a=commitdiff;hp=foo-baz-renamed-from-foo;h=initial"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): directory becomes file' \ + 'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=initial"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): file becomes directory' \ + 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-becomes-a-directory"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): file becomes symlink' \ + 'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-symlinked-to-bar"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): symlink becomes file' \ + 'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-back-to-file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): symlink becomes directory' \ + 'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-becomes-a-directory"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(2): directory becomes symlink' \ + 'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=foo-symlinked-to-bar"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# commit, commitdiff: merge, large +test_expect_success \ + 'Create a merge' \ + 'git checkout b && + echo "Branch" >> b && + git add b && + git commit -a -m "On branch" && + git checkout master && + git pull . b' + +test_expect_success \ + 'commit(0): merge commit' \ + 'gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(0): merge commit' \ + 'gitweb_run "p=.git;a=commitdiff"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'Prepare large commit' \ + 'git checkout b && + echo "To be changed" > 01-change && + echo "To be renamed" > 02-pure-rename-from && + echo "To be deleted" > 03-delete && + echo "To be renamed and changed" > 04-rename-from && + echo "To have mode changed" > 05-mode-change && + echo "File to symlink" > 06-file-or-symlink && + echo "To be changed and have mode changed" > 07-change-mode-change && + git add 0* && + git commit -a -m "Prepare large commit" && + echo "Changed" > 01-change && + git mv 02-pure-rename-from 02-pure-rename-to && + git rm 03-delete && rm -f 03-delete && + echo "A new file" > 03-new && + git add 03-new && + git mv 04-rename-from 04-rename-to && + echo "Changed" >> 04-rename-to && + test_chmod +x 05-mode-change && + rm -f 06-file-or-symlink && + if test_have_prereq SYMLINKS; then + ln -s 01-change 06-file-or-symlink + else + printf %s 01-change > 06-file-or-symlink + fi && + echo "Changed and have mode changed" > 07-change-mode-change && + test_chmod +x 07-change-mode-change && + git commit -a -m "Large commit" && + git checkout master' + +test_expect_success \ + 'commit(1): large commit' \ + 'gitweb_run "p=.git;a=commit;h=b"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'commitdiff(1): large commit' \ + 'gitweb_run "p=.git;a=commitdiff;h=b"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# tags testing + +test_expect_success \ + 'tags: list of different types of tags' \ + 'git checkout master && + git tag -a -m "Tag commit object" tag-commit HEAD && + git tag -a -m "" tag-commit-nomessage HEAD && + git tag -a -m "Tag tag object" tag-tag tag-commit && + git tag -a -m "Tag tree object" tag-tree HEAD^{tree} && + git tag -a -m "Tag blob object" tag-blob HEAD:file && + git tag lightweight/tag-commit HEAD && + git tag lightweight/tag-tag tag-commit && + git tag lightweight/tag-tree HEAD^{tree} && + git tag lightweight/tag-blob HEAD:file && + gitweb_run "p=.git;a=tags"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'tag: Tag to commit object' \ + 'gitweb_run "p=.git;a=tag;h=tag-commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'tag: on lightweight tag (invalid)' \ + 'gitweb_run "p=.git;a=tag;h=lightweight/tag-commit"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# logs + +test_expect_success \ + 'logs: log (implicit HEAD)' \ + 'gitweb_run "p=.git;a=log"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'logs: shortlog (implicit HEAD)' \ + 'gitweb_run "p=.git;a=shortlog"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'logs: history (implicit HEAD, file)' \ + 'gitweb_run "p=.git;a=history;f=file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'logs: history (implicit HEAD, non-existent file)' \ + 'gitweb_run "p=.git;a=history;f=non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'logs: history (implicit HEAD, deleted file)' \ + 'git checkout master && + echo "to be deleted" > deleted_file && + git add deleted_file && + git commit -m "Add file to be deleted" && + git rm deleted_file && + git commit -m "Delete file" && + gitweb_run "p=.git;a=history;f=deleted_file"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# path_info links +test_expect_success \ + 'path_info: project' \ + 'gitweb_run "" "/.git"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/branch' \ + 'gitweb_run "" "/.git/b"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/branch:file' \ + 'gitweb_run "" "/.git/master:file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/branch:dir/' \ + 'gitweb_run "" "/.git/master:foo/"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/branch:file (non-existent)' \ + 'gitweb_run "" "/.git/master:non-existent"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/branch:dir/ (non-existent)' \ + 'gitweb_run "" "/.git/master:non-existent/"' +test_debug 'cat gitweb.log' + + +test_expect_success \ + 'path_info: project/branch:/file' \ + 'gitweb_run "" "/.git/master:/file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/:/file (implicit HEAD)' \ + 'gitweb_run "" "/.git/:/file"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'path_info: project/:/ (implicit HEAD, top tree)' \ + 'gitweb_run "" "/.git/:/"' +test_debug 'cat gitweb.log' + + +# ---------------------------------------------------------------------- +# feed generation + +test_expect_success \ + 'feeds: OPML' \ + 'gitweb_run "a=opml"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'feed: RSS' \ + 'gitweb_run "p=.git;a=rss"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'feed: Atom' \ + 'gitweb_run "p=.git;a=atom"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# encoding/decoding + +test_expect_success \ + 'encode(commit): utf8' \ + '. "$TEST_DIRECTORY"/t3901-utf8.txt && + echo "UTF-8" >> file && + git add file && + git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt && + gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'encode(commit): iso-8859-1' \ + '. "$TEST_DIRECTORY"/t3901-8859-1.txt && + echo "ISO-8859-1" >> file && + git add file && + git config i18n.commitencoding ISO-8859-1 && + git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt && + git config --unset i18n.commitencoding && + gitweb_run "p=.git;a=commit"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'encode(log): utf-8 and iso-8859-1' \ + 'gitweb_run "p=.git;a=log"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# extra options + +test_expect_success \ + 'opt: log --no-merges' \ + 'gitweb_run "p=.git;a=log;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: atom --no-merges' \ + 'gitweb_run "p=.git;a=log;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: "file" history --no-merges' \ + 'gitweb_run "p=.git;a=history;f=file;opt=--no-merges"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: log --no-such-option (invalid option)' \ + 'gitweb_run "p=.git;a=log;opt=--no-such-option"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'opt: tree --no-merges (invalid option for action)' \ + 'gitweb_run "p=.git;a=tree;opt=--no-merges"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# testing config_to_multi / cloneurl + +test_expect_success \ + 'URL: no project URLs, no base URL' \ + 'gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'URL: project URLs via gitweb.url' \ + 'git config --add gitweb.url git://example.com/git/trash.git && + git config --add gitweb.url http://example.com/git/trash.git && + gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +cat >.git/cloneurl <<\EOF +git://example.com/git/trash.git +http://example.com/git/trash.git +EOF + +test_expect_success \ + 'URL: project URLs via cloneurl file' \ + 'gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# gitweb config and repo config + +cat >>gitweb_config.perl <<\EOF + +# turn on override for each overridable feature +foreach my $key (keys %feature) { + if ($feature{$key}{'sub'}) { + $feature{$key}{'override'} = 1; + } +} +EOF + +test_expect_success \ + 'config override: projects list (implicit)' \ + 'gitweb_run' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'config override: tree view, features not overridden in repo config' \ + 'gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'config override: tree view, features disabled in repo config' \ + 'git config gitweb.blame no && + git config gitweb.snapshot none && + git config gitweb.avatar gravatar && + gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +test_expect_success \ + 'config override: tree view, features enabled in repo config (1)' \ + 'git config gitweb.blame yes && + git config gitweb.snapshot "zip,tgz, tbz2" && + gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +cat >.git/config <<\EOF +# testing noval and alternate separator +[gitweb] + blame + snapshot = zip tgz +EOF +test_expect_success \ + 'config override: tree view, features enabled in repo config (2)' \ + 'gitweb_run "p=.git;a=tree"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# non-ASCII in README.html + +test_expect_success \ + 'README.html with non-ASCII characters (utf-8)' \ + 'echo "<b>UTF-8 example:</b><br />" > .git/README.html && + cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html && + gitweb_run "p=.git;a=summary"' +test_debug 'cat gitweb.log' + +# ---------------------------------------------------------------------- +# syntax highlighting + +cat >>gitweb_config.perl <<\EOF +$feature{'highlight'}{'override'} = 1; +EOF + +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 +fi + +test_expect_success HIGHLIGHT \ + 'syntax highlighting (no highlight)' \ + '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)' \ + '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/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh new file mode 100755 index 0000000000..2487da1296 --- /dev/null +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -0,0 +1,138 @@ +#!/bin/sh +# +# Copyright (c) 2009 Mark Rada +# + +test_description='gitweb as standalone script (http status tests). + +This test runs gitweb (git web interface) as a CGI script from the +commandline, and checks that it returns the expected HTTP status +code and message.' + + +. ./gitweb-lib.sh + +# ---------------------------------------------------------------------- +# snapshot settings + +test_expect_success 'setup' " + test_commit 'SnapshotTests' 'i can has snapshot?' +" + + +cat >>gitweb_config.perl <<\EOF +$feature{'snapshot'}{'override'} = 0; +EOF + +test_expect_success \ + 'snapshots: tgz only default format enabled' \ + 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" && + grep "Status: 200 OK" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tbz2" && + grep "403 - Unsupported snapshot format" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=txz" && + grep "403 - Snapshot format not allowed" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" && + grep "403 - Unsupported snapshot format" gitweb.output' + + +cat >>gitweb_config.perl <<\EOF +$feature{'snapshot'}{'default'} = ['tgz','tbz2','txz','zip']; +EOF + +test_expect_success \ + 'snapshots: all enabled in default, use default disabled value' \ + 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" && + grep "Status: 200 OK" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tbz2" && + grep "Status: 200 OK" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=txz" && + grep "403 - Snapshot format not allowed" gitweb.output && + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" && + grep "Status: 200 OK" gitweb.output' + + +cat >>gitweb_config.perl <<\EOF +$known_snapshot_formats{'zip'}{'disabled'} = 1; +EOF + +test_expect_success \ + 'snapshots: zip explicitly disabled' \ + 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" && + grep "403 - Snapshot format not allowed" gitweb.output' +test_debug 'cat gitweb.output' + + +cat >>gitweb_config.perl <<\EOF +$known_snapshot_formats{'tgz'}{'disabled'} = 0; +EOF + +test_expect_success \ + 'snapshots: tgz explicitly enabled' \ + 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" && + grep "Status: 200 OK" gitweb.output' +test_debug 'cat gitweb.headers' + + +# ---------------------------------------------------------------------- +# snapshot hash ids + +test_expect_success 'snapshots: good tree-ish id' ' + gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" && + grep "Status: 200 OK" gitweb.output +' +test_debug 'cat gitweb.headers' + +test_expect_success 'snapshots: bad tree-ish id' ' + gitweb_run "p=.git;a=snapshot;h=frizzumFrazzum;sf=tgz" && + grep "404 - Object does not exist" gitweb.output +' +test_debug 'cat gitweb.output' + +test_expect_success 'snapshots: bad tree-ish id (tagged object)' ' + echo object > tag-object && + git add tag-object && + git commit -m "Object to be tagged" && + git tag tagged-object `git hash-object tag-object` && + gitweb_run "p=.git;a=snapshot;h=tagged-object;sf=tgz" && + grep "400 - Object is not a tree-ish" gitweb.output +' +test_debug 'cat gitweb.output' + +test_expect_success 'snapshots: good object id' ' + ID=`git rev-parse --verify HEAD` && + gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" && + grep "Status: 200 OK" gitweb.output +' +test_debug 'cat gitweb.headers' + +test_expect_success 'snapshots: bad object id' ' + gitweb_run "p=.git;a=snapshot;h=abcdef01234;sf=tgz" && + grep "404 - Object does not exist" gitweb.output +' +test_debug 'cat gitweb.output' + + +# ---------------------------------------------------------------------- +# load checking + +# always hit the load limit +cat >>gitweb_config.perl <<\EOF +our $maxload = -1; +EOF + +test_expect_success 'load checking: load too high (default action)' ' + gitweb_run "p=.git" && + grep "Status: 503 Service Unavailable" gitweb.headers && + grep "503 - The load average on the server is too high" gitweb.body +' +test_debug 'cat gitweb.log' # just in case +test_debug 'cat gitweb.headers' + +# turn off load checking +cat >>gitweb_config.perl <<\EOF +our $maxload = undef; +EOF + + +test_done diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh new file mode 100755 index 0000000000..dd83890001 --- /dev/null +++ b/t/t9502-gitweb-standalone-parse-output.sh @@ -0,0 +1,115 @@ +#!/bin/sh +# +# Copyright (c) 2009 Mark Rada +# + +test_description='gitweb as standalone script (parsing script output). + +This test runs gitweb (git web interface) as a CGI script from the +commandline, and checks that it produces the correct output, either +in the HTTP header or the actual script output.' + + +. ./gitweb-lib.sh + +# ---------------------------------------------------------------------- +# snapshot file name and prefix + +cat >>gitweb_config.perl <<\EOF + +$known_snapshot_formats{'tar'} = { + 'display' => 'tar', + 'type' => 'application/x-tar', + 'suffix' => '.tar', + 'format' => 'tar', +}; + +$feature{'snapshot'}{'default'} = ['tar']; +EOF + +# Call check_snapshot with the arguments "<basename> [<prefix>]" +# +# This will check that gitweb HTTP header contains proposed filename +# as <basename> with '.tar' suffix added, and that generated tarfile +# (gitweb message body) has <prefix> as prefix for al files in tarfile +# +# <prefix> default to <basename> +check_snapshot () { + basename=$1 + prefix=${2:-"$1"} + echo "basename=$basename" + grep "filename=.*$basename.tar" gitweb.headers >/dev/null 2>&1 && + "$TAR" tf gitweb.body >file_list && + ! grep -v "^$prefix/" file_list +} + +test_expect_success setup ' + test_commit first foo && + git branch xx/test && + FULL_ID=$(git rev-parse --verify HEAD) && + SHORT_ID=$(git rev-parse --verify --short=7 HEAD) +' +test_debug ' + echo "FULL_ID = $FULL_ID" + echo "SHORT_ID = $SHORT_ID" +' + +test_expect_success 'snapshot: full sha1' ' + gitweb_run "p=.git;a=snapshot;h=$FULL_ID;sf=tar" && + check_snapshot ".git-$SHORT_ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: shortened sha1' ' + gitweb_run "p=.git;a=snapshot;h=$SHORT_ID;sf=tar" && + check_snapshot ".git-$SHORT_ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: almost full sha1' ' + ID=$(git rev-parse --short=30 HEAD) && + gitweb_run "p=.git;a=snapshot;h=$ID;sf=tar" && + check_snapshot ".git-$SHORT_ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: HEAD' ' + gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tar" && + check_snapshot ".git-HEAD-$SHORT_ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: short branch name (master)' ' + gitweb_run "p=.git;a=snapshot;h=master;sf=tar" && + ID=$(git rev-parse --verify --short=7 master) && + check_snapshot ".git-master-$ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: short tag name (first)' ' + gitweb_run "p=.git;a=snapshot;h=first;sf=tar" && + ID=$(git rev-parse --verify --short=7 first) && + check_snapshot ".git-first-$ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: full branch name (refs/heads/master)' ' + gitweb_run "p=.git;a=snapshot;h=refs/heads/master;sf=tar" && + ID=$(git rev-parse --verify --short=7 master) && + check_snapshot ".git-master-$ID" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: full tag name (refs/tags/first)' ' + gitweb_run "p=.git;a=snapshot;h=refs/tags/first;sf=tar" && + check_snapshot ".git-first" +' +test_debug 'cat gitweb.headers && cat file_list' + +test_expect_success 'snapshot: hierarchical branch name (xx/test)' ' + gitweb_run "p=.git;a=snapshot;h=xx/test;sf=tar" && + ! grep "filename=.*/" gitweb.headers +' +test_debug 'cat gitweb.headers' + +test_done diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh new file mode 100755 index 0000000000..2eff9cd68c --- /dev/null +++ b/t/t9600-cvsimport.sh @@ -0,0 +1,161 @@ +#!/bin/sh + +test_description='git cvsimport basic tests' +. ./lib-cvs.sh + +if ! test_have_prereq PERL; then + skip_all='skipping git cvsimport tests, perl not available' + test_done +fi + +CVSROOT=$(pwd)/cvsroot +export CVSROOT + +test_expect_success 'setup cvsroot' '$CVS init' + +test_expect_success 'setup a cvs module' ' + + mkdir "$CVSROOT/module" && + $CVS co -d module-cvs module && + cd module-cvs && + cat <<EOF >o_fortuna && +O Fortuna +velut luna +statu variabilis, + +semper crescis +aut decrescis; +vita detestabilis + +nunc obdurat +et tunc curat +ludo mentis aciem, + +egestatem, +potestatem +dissolvit ut glaciem. +EOF + $CVS add o_fortuna && + cat <<EOF >message && +add "O Fortuna" lyrics + +These public domain lyrics make an excellent sample text. +EOF + $CVS commit -F message && + cd .. +' + +test_expect_success '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 '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 && + cat <<EOF >o_fortuna && +O Fortune, +like the moon +you are changeable, + +ever waxing +and waning; +hateful life + +first oppresses +and then soothes +as fancy takes it; + +poverty +and power +it melts them like ice. +EOF + cat <<EOF >message && +translate to English + +My Latin is terrible. +EOF + $CVS commit -F message && + cd .. +' + +test_expect_success 'update git module' ' + + cd module-git && + git cvsimport -a -R -z 0 module && + git merge origin && + cd .. && + test_cmp module-cvs/o_fortuna module-git/o_fortuna + +' + +test_expect_success 'update has correct .git/cvs-revisions' ' + + (cd module-git && + git log --format="o_fortuna 1.1 %H" -1 HEAD^ && + git log --format="o_fortuna 1.2 %H" -1 HEAD) > expected && + test_cmp expected module-git/.git/cvs-revisions +' + +test_expect_success 'update cvs module' ' + + cd module-cvs && + echo 1 >tick && + $CVS add tick && + $CVS commit -m 1 + cd .. + +' + +test_expect_success 'cvsimport.module config works' ' + + cd module-git && + git config cvsimport.module module && + git cvsimport -a -R -z0 && + git merge origin && + cd .. && + test_cmp module-cvs/tick module-git/tick + +' + +test_expect_success 'second update has correct .git/cvs-revisions' ' + + (cd module-git && + git log --format="o_fortuna 1.1 %H" -1 HEAD^^ && + git log --format="o_fortuna 1.2 %H" -1 HEAD^ + git log --format="tick 1.1 %H" -1 HEAD) > expected && + test_cmp expected module-git/.git/cvs-revisions +' + +test_expect_success 'import from a CVS working tree' ' + + $CVS co -d import-from-wt module && + 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_expect_success '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_done diff --git a/t/t9601-cvsimport-vendor-branch.sh b/t/t9601-cvsimport-vendor-branch.sh new file mode 100755 index 0000000000..3afaf56526 --- /dev/null +++ b/t/t9601-cvsimport-vendor-branch.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +# Description of the files in the repository: +# +# imported-once.txt: +# +# Imported once. 1.1 and 1.1.1.1 should be identical. +# +# imported-twice.txt: +# +# Imported twice. HEAD should reflect the contents of the +# second import (i.e., have the same contents as 1.1.1.2). +# +# imported-modified.txt: +# +# Imported, then modified on HEAD. HEAD should reflect the +# modification. +# +# imported-modified-imported.txt: +# +# Imported, then modified on HEAD, then imported again. +# +# added-imported.txt,v: +# +# Added with 'cvs add' to create 1.1, then imported with +# completely different contents to create 1.1.1.1, therefore the +# vendor branch was never the default branch. +# +# imported-anonymously.txt: +# +# Like imported-twice.txt, but with a vendor branch whose branch +# tag has been removed. + +test_description='git cvsimport handling of vendor branches' +. ./lib-cvs.sh + +CVSROOT="$TEST_DIRECTORY"/t9601/cvsroot +export CVSROOT + +test_expect_success '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 'check master out of git repository' 'test_git_co master' + +test_expect_success '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_cmp_branch_file master imported-twice.txt + +' + +test_expect_success '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_cmp_branch_file master imported-modified-imported.txt + +' + +test_expect_success '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_cmp_branch_file master imported-anonymously.txt + +' + +test_done diff --git a/t/t9601/cvsroot/.gitattributes b/t/t9601/cvsroot/.gitattributes new file mode 100644 index 0000000000..562b12e16e --- /dev/null +++ b/t/t9601/cvsroot/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/t/t9601/cvsroot/CVSROOT/.gitignore b/t/t9601/cvsroot/CVSROOT/.gitignore new file mode 100644 index 0000000000..3bb9b34173 --- /dev/null +++ b/t/t9601/cvsroot/CVSROOT/.gitignore @@ -0,0 +1,2 @@ +history +val-tags diff --git a/t/t9601/cvsroot/module/added-imported.txt,v b/t/t9601/cvsroot/module/added-imported.txt,v new file mode 100644 index 0000000000..5f83072ea4 --- /dev/null +++ b/t/t9601/cvsroot/module/added-imported.txt,v @@ -0,0 +1,44 @@ +head 1.1; +access; +symbols + vtag-4:1.1.1.1 + vbranchA:1.1.1; +locks; strict; +comment @# @; + + +1.1 +date 2004.02.09.15.43.15; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.16; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log +@Add a file to the working copy. +@ +text +@Adding this file, before importing it with different contents. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-4). +@ +text +@d1 1 +a1 1 +This is vtag-4 (on vbranchA) of added-then-imported.txt. +@ + diff --git a/t/t9601/cvsroot/module/imported-anonymously.txt,v b/t/t9601/cvsroot/module/imported-anonymously.txt,v new file mode 100644 index 0000000000..55e1b0ca5d --- /dev/null +++ b/t/t9601/cvsroot/module/imported-anonymously.txt,v @@ -0,0 +1,42 @@ +head 1.1; +branch 1.1.1; +access; +symbols + vtag-1:1.1.1.1; +locks; strict; +comment @# @; + + +1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log +@Initial revision +@ +text +@This is vtag-1 (on vbranchA) of imported-anonymously.txt. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-1). +@ +text +@@ + + diff --git a/t/t9601/cvsroot/module/imported-modified-imported.txt,v b/t/t9601/cvsroot/module/imported-modified-imported.txt,v new file mode 100644 index 0000000000..e5830aeb37 --- /dev/null +++ b/t/t9601/cvsroot/module/imported-modified-imported.txt,v @@ -0,0 +1,76 @@ +head 1.2; +access; +symbols + vtag-2:1.1.1.2 + vtag-1:1.1.1.1 + vbranchA:1.1.1; +locks; strict; +comment @# @; + + +1.2 +date 2004.02.09.15.43.14; author kfogel; state Exp; +branches; +next 1.1; + +1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next 1.1.1.2; + +1.1.1.2 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@First regular commit, to imported-modified-imported.txt, on HEAD. +@ +text +@This is a modification of imported-modified-imported.txt on HEAD. +It should supersede the version from the vendor branch. +@ + + +1.1 +log +@Initial revision +@ +text +@d1 2 +a2 1 +This is vtag-1 (on vbranchA) of imported-modified-imported.txt. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-1). +@ +text +@@ + + +1.1.1.2 +log +@Import (vbranchA, vtag-2). +@ +text +@d1 1 +a1 1 +This is vtag-2 (on vbranchA) of imported-modified-imported.txt. +@ + + diff --git a/t/t9601/cvsroot/module/imported-modified.txt,v b/t/t9601/cvsroot/module/imported-modified.txt,v new file mode 100644 index 0000000000..bbcfe447b9 --- /dev/null +++ b/t/t9601/cvsroot/module/imported-modified.txt,v @@ -0,0 +1,59 @@ +head 1.2; +access; +symbols + vtag-1:1.1.1.1 + vbranchA:1.1.1; +locks; strict; +comment @# @; + + +1.2 +date 2004.02.09.15.43.14; author kfogel; state Exp; +branches; +next 1.1; + +1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@Commit on HEAD. +@ +text +@This is a modification of imported-modified.txt on HEAD. +It should supersede the version from the vendor branch. +@ + + +1.1 +log +@Initial revision +@ +text +@d1 2 +a2 1 +This is vtag-1 (on vbranchA) of imported-modified.txt. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-1). +@ +text +@@ + + diff --git a/t/t9601/cvsroot/module/imported-once.txt,v b/t/t9601/cvsroot/module/imported-once.txt,v new file mode 100644 index 0000000000..c5dd82b12d --- /dev/null +++ b/t/t9601/cvsroot/module/imported-once.txt,v @@ -0,0 +1,43 @@ +head 1.1; +branch 1.1.1; +access; +symbols + vtag-1:1.1.1.1 + vbranchA:1.1.1; +locks; strict; +comment @# @; + + +1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log +@Initial revision +@ +text +@This is vtag-1 (on vbranchA) of imported-once.txt. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-1). +@ +text +@@ + + diff --git a/t/t9601/cvsroot/module/imported-twice.txt,v b/t/t9601/cvsroot/module/imported-twice.txt,v new file mode 100644 index 0000000000..d1f3f1b344 --- /dev/null +++ b/t/t9601/cvsroot/module/imported-twice.txt,v @@ -0,0 +1,60 @@ +head 1.1; +branch 1.1.1; +access; +symbols + vtag-2:1.1.1.2 + vtag-1:1.1.1.1 + vbranchA:1.1.1; +locks; strict; +comment @# @; + + +1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next 1.1.1.2; + +1.1.1.2 +date 2004.02.09.15.43.13; author kfogel; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log +@Initial revision +@ +text +@This is vtag-1 (on vbranchA) of imported-twice.txt. +@ + + +1.1.1.1 +log +@Import (vbranchA, vtag-1). +@ +text +@@ + + +1.1.1.2 +log +@Import (vbranchA, vtag-2). +@ +text +@d1 1 +a1 1 +This is vtag-2 (on vbranchA) of imported-twice.txt. +@ + + diff --git a/t/t9602-cvsimport-branches-tags.sh b/t/t9602-cvsimport-branches-tags.sh new file mode 100755 index 0000000000..67878b2d0c --- /dev/null +++ b/t/t9602-cvsimport-branches-tags.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# A description of the repository used for this test can be found in +# t9602/README. + +test_description='git cvsimport handling of branches and tags' +. ./lib-cvs.sh + +CVSROOT="$TEST_DIRECTORY"/t9602/cvsroot +export CVSROOT + +test_expect_success 'import module' ' + + git cvsimport -C module-git module + +' + +test_expect_success 'test branch master' ' + + test_cmp_branch_tree master + +' + +test_expect_success 'test branch vendorbranch' ' + + test_cmp_branch_tree vendorbranch + +' + +test_expect_failure 'test branch B_FROM_INITIALS' ' + + test_cmp_branch_tree B_FROM_INITIALS + +' + +test_expect_failure 'test branch B_FROM_INITIALS_BUT_ONE' ' + + test_cmp_branch_tree B_FROM_INITIALS_BUT_ONE + +' + +test_expect_failure 'test branch B_MIXED' ' + + test_cmp_branch_tree B_MIXED + +' + +test_expect_success 'test branch B_SPLIT' ' + + test_cmp_branch_tree B_SPLIT + +' + +test_expect_failure 'test tag vendortag' ' + + test_cmp_branch_tree vendortag + +' + +test_expect_success '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_cmp_branch_tree T_ALL_INITIAL_FILES_BUT_ONE + +' + +test_expect_failure 'test tag T_MIXED' ' + + test_cmp_branch_tree T_MIXED + +' + + +test_done diff --git a/t/t9602/README b/t/t9602/README new file mode 100644 index 0000000000..c231e0f26f --- /dev/null +++ b/t/t9602/README @@ -0,0 +1,62 @@ +This repository is for testing the ability to group revisions +correctly along tags and branches. Here is its history: + + 1. The initial import (revision 1.1 of everybody) created a + directory structure with a file named `default' in each dir: + + ./ + default + sub1/default + subsubA/default + subsubB/default + sub2/default + subsubA/default + sub3/default + + 2. Then tagged everyone with T_ALL_INITIAL_FILES. + + 3. Then tagged everyone except sub1/subsubB/default with + T_ALL_INITIAL_FILES_BUT_ONE. + + 4. Then created branch B_FROM_INITIALS on everyone. + + 5. Then created branch B_FROM_INITIALS_BUT_ONE on everyone except + /sub1/subsubB/default. + + 6. Then committed modifications to two files: sub3/default, and + sub1/subsubA/default. + + 7. Then committed a modification to all 7 files. + + 8. Then backdated sub3/default to revision 1.2, and + sub2/subsubA/default to revision 1.1, and tagged with T_MIXED. + + 9. Same as 8, but tagged with -b to create branch B_MIXED. + + 10. Switched the working copy to B_MIXED, and added + sub2/branch_B_MIXED_only. (That's why the RCS file is in + sub2/Attic/ -- it never existed on trunk.) + + 11. In one commit, modified default, sub1/default, and + sub2/subsubA/default, on branch B_MIXED. + + 12. Did "cvs up -A" on sub2/default, then in one commit, made a + change to sub2/default and sub2/branch_B_MIXED_only. So this + commit should be spread between the branch and the trunk. + + 13. Do "cvs up -A" to get everyone back to trunk, then make a new + branch B_SPLIT on everyone except sub1/subsubB/default,v. + + 14. Switch to branch B_SPLIT (see sub1/subsubB/default disappear) + and commit a change that affects everyone except sub3/default. + + 15. An hour or so later, "cvs up -A" to get sub1/subsubB/default + back, then commit a change on that file, on trunk. (It's + important that this change happened after the previous commits + on B_SPLIT.) + + 16. Branch sub1/subsubB/default to B_SPLIT, then "cvs up -r B_SPLIT" + to switch the whole working copy to the branch. + + 17. Commit a change on B_SPLIT, to sub1/subsubB/default and + sub3/default. diff --git a/t/t9602/cvsroot/.gitattributes b/t/t9602/cvsroot/.gitattributes new file mode 100644 index 0000000000..562b12e16e --- /dev/null +++ b/t/t9602/cvsroot/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/t/t9602/cvsroot/CVSROOT/.gitignore b/t/t9602/cvsroot/CVSROOT/.gitignore new file mode 100644 index 0000000000..3bb9b34173 --- /dev/null +++ b/t/t9602/cvsroot/CVSROOT/.gitignore @@ -0,0 +1,2 @@ +history +val-tags diff --git a/t/t9602/cvsroot/module/default,v b/t/t9602/cvsroot/module/default,v new file mode 100644 index 0000000000..3b68382a3b --- /dev/null +++ b/t/t9602/cvsroot/module/default,v @@ -0,0 +1,102 @@ +head 1.2; +access; +symbols + B_SPLIT:1.2.0.4 + B_MIXED:1.2.0.2 + T_MIXED:1.2 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.2 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches + 1.2.2.1 + 1.2.4.1; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.2.2.1 +date 2003.05.23.00.31.36; author jrandom; state Exp; +branches; +next ; + +1.2.4.1 +date 2003.06.03.03.20.31; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@Second commit to proj, affecting all 7 files. +@ +text +@This is the file `default' in the top level of the project. + +Every directory in the `proj' project has a file named `default'. + +This line was added in the second commit (affecting all 7 files). +@ + + +1.2.4.1 +log +@First change on branch B_SPLIT. + +This change excludes sub3/default, because it was not part of this +commit, and sub1/subsubB/default, which is not even on the branch yet. +@ +text +@a5 2 + +First change on branch B_SPLIT. +@ + + +1.2.2.1 +log +@Modify three files, on branch B_MIXED. +@ +text +@a5 2 + +This line was added on branch B_MIXED only (affecting 3 files). +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub1/default,v b/t/t9602/cvsroot/module/sub1/default,v new file mode 100644 index 0000000000..b7fdccdfdf --- /dev/null +++ b/t/t9602/cvsroot/module/sub1/default,v @@ -0,0 +1,102 @@ +head 1.2; +access; +symbols + B_SPLIT:1.2.0.4 + B_MIXED:1.2.0.2 + T_MIXED:1.2 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.2 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches + 1.2.2.1 + 1.2.4.1; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.2.2.1 +date 2003.05.23.00.31.36; author jrandom; state Exp; +branches; +next ; + +1.2.4.1 +date 2003.06.03.03.20.31; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@Second commit to proj, affecting all 7 files. +@ +text +@This is sub1/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added in the second commit (affecting all 7 files). +@ + + +1.2.4.1 +log +@First change on branch B_SPLIT. + +This change excludes sub3/default, because it was not part of this +commit, and sub1/subsubB/default, which is not even on the branch yet. +@ +text +@a5 2 + +First change on branch B_SPLIT. +@ + + +1.2.2.1 +log +@Modify three files, on branch B_MIXED. +@ +text +@a5 2 + +This line was added on branch B_MIXED only (affecting 3 files). +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub1/subsubA/default,v b/t/t9602/cvsroot/module/sub1/subsubA/default,v new file mode 100644 index 0000000000..472b7b2bd9 --- /dev/null +++ b/t/t9602/cvsroot/module/sub1/subsubA/default,v @@ -0,0 +1,101 @@ +head 1.3; +access; +symbols + B_SPLIT:1.3.0.4 + B_MIXED:1.3.0.2 + T_MIXED:1.3 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.3 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches + 1.3.4.1; +next 1.2; + +1.2 +date 2003.05.23.00.15.26; author jrandom; state Exp; +branches; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.3.4.1 +date 2003.06.03.03.20.31; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.3 +log +@Second commit to proj, affecting all 7 files. +@ +text +@This is sub1/subsubA/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added by the first commit (affecting two files). + +This line was added in the second commit (affecting all 7 files). +@ + + +1.3.4.1 +log +@First change on branch B_SPLIT. + +This change excludes sub3/default, because it was not part of this +commit, and sub1/subsubB/default, which is not even on the branch yet. +@ +text +@a7 2 + +First change on branch B_SPLIT. +@ + + +1.2 +log +@First commit to proj, affecting two files. +@ +text +@d6 2 +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub1/subsubB/default,v b/t/t9602/cvsroot/module/sub1/subsubB/default,v new file mode 100644 index 0000000000..fe6efa4554 --- /dev/null +++ b/t/t9602/cvsroot/module/sub1/subsubB/default,v @@ -0,0 +1,107 @@ +head 1.3; +access; +symbols + B_SPLIT:1.3.0.2 + B_MIXED:1.2.0.2 + T_MIXED:1.2 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.3 +date 2003.06.03.04.29.14; author jrandom; state Exp; +branches + 1.3.2.1; +next 1.2; + +1.2 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.3.2.1 +date 2003.06.03.04.33.13; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.3 +log +@A trunk change to sub1/subsubB/default. This was committed about an +hour after an earlier change that affected most files on branch +B_SPLIT. This file is not on that branch yet, but after this commit, +we'll branch to B_SPLIT, albeit rooted in a revision that didn't exist +at the time the rest of B_SPLIT was created. +@ +text +@This is sub1/subsubB/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added in the second commit (affecting all 7 files). + +This bit was committed on trunk about an hour after an earlier change +to everyone else on branch B_SPLIT. Afterwards, we'll finally branch +this file to B_SPLIT, but rooted in a revision that didn't exist at +the time the rest of B_SPLIT was created. +@ + + +1.3.2.1 +log +@This change affects sub3/default and sub1/subsubB/default, on branch +B_SPLIT. Note that the latter file did not even exist on this branch +until after some other files had had revisions committed on B_SPLIT. +@ +text +@a10 4 + +This change affects sub3/default and sub1/subsubB/default, on branch +B_SPLIT. Note that the latter file did not even exist on this branch +until after some other files had had revisions committed on B_SPLIT. +@ + + +1.2 +log +@Second commit to proj, affecting all 7 files. +@ +text +@d6 5 +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v b/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v new file mode 100644 index 0000000000..34c9789f2f --- /dev/null +++ b/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v @@ -0,0 +1,59 @@ +head 1.1; +access; +symbols + B_MIXED:1.1.0.2; +locks; strict; +comment @# @; + + +1.1 +date 2003.05.23.00.25.26; author jrandom; state dead; +branches + 1.1.2.1; +next ; + +1.1.2.1 +date 2003.05.23.00.25.26; author jrandom; state Exp; +branches; +next 1.1.2.2; + +1.1.2.2 +date 2003.05.23.00.48.51; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log +@file branch_B_MIXED_only was initially added on branch B_MIXED. +@ +text +@@ + + +1.1.2.1 +log +@Add a file on branch B_MIXED. +@ +text +@a0 1 +This file was added on branch B_MIXED. It never existed on trunk. +@ + + +1.1.2.2 +log +@A single commit affecting one file on branch B_MIXED and one on trunk. +@ +text +@a1 3 + +The same commit added these two lines here on branch B_MIXED, and two +similar lines to ./default on trunk. +@ + + diff --git a/t/t9602/cvsroot/module/sub2/default,v b/t/t9602/cvsroot/module/sub2/default,v new file mode 100644 index 0000000000..018f7f8ece --- /dev/null +++ b/t/t9602/cvsroot/module/sub2/default,v @@ -0,0 +1,102 @@ +head 1.3; +access; +symbols + B_SPLIT:1.3.0.2 + B_MIXED:1.2.0.2 + T_MIXED:1.2 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.3 +date 2003.05.23.00.48.51; author jrandom; state Exp; +branches + 1.3.2.1; +next 1.2; + +1.2 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.3.2.1 +date 2003.06.03.03.20.31; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.3 +log +@A single commit affecting one file on branch B_MIXED and one on trunk. +@ +text +@This is sub2/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added in the second commit (affecting all 7 files). + +The same commit added these two lines here on trunk, and two similar +lines to ./branch_B_MIXED_only on branch B_MIXED. +@ + + +1.3.2.1 +log +@First change on branch B_SPLIT. + +This change excludes sub3/default, because it was not part of this +commit, and sub1/subsubB/default, which is not even on the branch yet. +@ +text +@a8 2 + +First change on branch B_SPLIT. +@ + + +1.2 +log +@Second commit to proj, affecting all 7 files. +@ +text +@d6 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub2/subsubA/default,v b/t/t9602/cvsroot/module/sub2/subsubA/default,v new file mode 100644 index 0000000000..d13242cb09 --- /dev/null +++ b/t/t9602/cvsroot/module/sub2/subsubA/default,v @@ -0,0 +1,102 @@ +head 1.2; +access; +symbols + B_SPLIT:1.2.0.2 + B_MIXED:1.1.0.2 + T_MIXED:1.1 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.2 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches + 1.2.2.1; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1 + 1.1.2.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.1.2.1 +date 2003.05.23.00.31.36; author jrandom; state Exp; +branches; +next ; + +1.2.2.1 +date 2003.06.03.03.20.31; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@Second commit to proj, affecting all 7 files. +@ +text +@This is sub2/subsub2/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added in the second commit (affecting all 7 files). +@ + + +1.2.2.1 +log +@First change on branch B_SPLIT. + +This change excludes sub3/default, because it was not part of this +commit, and sub1/subsubB/default, which is not even on the branch yet. +@ +text +@a5 2 + +First change on branch B_SPLIT. +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.2.1 +log +@Modify three files, on branch B_MIXED. +@ +text +@a3 2 + +This line was added on branch B_MIXED only (affecting 3 files). +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9602/cvsroot/module/sub3/default,v b/t/t9602/cvsroot/module/sub3/default,v new file mode 100644 index 0000000000..88e4567434 --- /dev/null +++ b/t/t9602/cvsroot/module/sub3/default,v @@ -0,0 +1,102 @@ +head 1.3; +access; +symbols + B_SPLIT:1.3.0.2 + B_MIXED:1.2.0.2 + T_MIXED:1.2 + B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4 + B_FROM_INITIALS:1.1.1.1.0.2 + T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1 + T_ALL_INITIAL_FILES:1.1.1.1 + vendortag:1.1.1.1 + vendorbranch:1.1.1; +locks; strict; +comment @# @; + + +1.3 +date 2003.05.23.00.17.53; author jrandom; state Exp; +branches + 1.3.2.1; +next 1.2; + +1.2 +date 2003.05.23.00.15.26; author jrandom; state Exp; +branches; +next 1.1; + +1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches + 1.1.1.1; +next ; + +1.1.1.1 +date 2003.05.22.23.20.19; author jrandom; state Exp; +branches; +next ; + +1.3.2.1 +date 2003.06.03.04.33.13; author jrandom; state Exp; +branches; +next ; + + +desc +@@ + + +1.3 +log +@Second commit to proj, affecting all 7 files. +@ +text +@This is sub3/default. + +Every directory in the `proj' project has a file named `default'. + +This line was added by the first commit (affecting two files). + +This line was added in the second commit (affecting all 7 files). +@ + + +1.3.2.1 +log +@This change affects sub3/default and sub1/subsubB/default, on branch +B_SPLIT. Note that the latter file did not even exist on this branch +until after some other files had had revisions committed on B_SPLIT. +@ +text +@a7 4 + +This change affects sub3/default and sub1/subsubB/default, on branch +B_SPLIT. Note that the latter file did not even exist on this branch +until after some other files had had revisions committed on B_SPLIT. +@ + + +1.2 +log +@First commit to proj, affecting two files. +@ +text +@d6 2 +@ + + +1.1 +log +@Initial revision +@ +text +@d4 2 +@ + + +1.1.1.1 +log +@Initial import. +@ +text +@@ diff --git a/t/t9603-cvsimport-patchsets.sh b/t/t9603-cvsimport-patchsets.sh new file mode 100755 index 0000000000..958bdce4dd --- /dev/null +++ b/t/t9603-cvsimport-patchsets.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# Structure of the test cvs repository +# +# Message File:Content Commit Time +# Rev 1 a: 1.1 2009-02-21 19:11:43 +0100 +# Rev 2 a: 1.2 b: 1.1 2009-02-21 19:11:14 +0100 +# Rev 3 b: 1.2 2009-02-21 19:11:43 +0100 +# +# As you can see the commit of Rev 3 has the same time as +# Rev 1 this leads to a broken import because of a cvsps +# bug. + +test_description='git cvsimport testing for correct patchset estimation' +. ./lib-cvs.sh + +CVSROOT="$TEST_DIRECTORY"/t9603/cvsroot +export CVSROOT + +test_expect_failure 'import with criss cross times on revisions' ' + + git cvsimport -p"-x" -C module-git module && + 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 "Rev 4 +Rev 3 +Rev 2 +Rev 1" > expect-master && + test_cmp actual-master expect-master && + + echo "Rev 5 Branch A Wed Mar 11 19:09:10 2009 +0000 +Rev 4 Branch A Wed Mar 11 19:03:52 2009 +0000" > expect-A && + test_cmp actual-A expect-A +' + +test_done diff --git a/t/t9603/cvsroot/.gitattributes b/t/t9603/cvsroot/.gitattributes new file mode 100644 index 0000000000..562b12e16e --- /dev/null +++ b/t/t9603/cvsroot/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/t/t9603/cvsroot/CVSROOT/.gitignore b/t/t9603/cvsroot/CVSROOT/.gitignore new file mode 100644 index 0000000000..3bb9b34173 --- /dev/null +++ b/t/t9603/cvsroot/CVSROOT/.gitignore @@ -0,0 +1,2 @@ +history +val-tags diff --git a/t/t9603/cvsroot/module/a,v b/t/t9603/cvsroot/module/a,v new file mode 100644 index 0000000000..ba8fd5af23 --- /dev/null +++ b/t/t9603/cvsroot/module/a,v @@ -0,0 +1,74 @@ +head 1.2; +access; +symbols + A:1.2.0.2; +locks; strict; +comment @# @; + + +1.2 +date 2009.02.21.18.11.14; author tester; state Exp; +branches + 1.2.2.1; +next 1.1; + +1.1 +date 2009.02.21.18.11.43; author tester; state Exp; +branches; +next ; + +1.2.2.1 +date 2009.03.11.19.03.52; author tester; state Exp; +branches; +next 1.2.2.2; + +1.2.2.2 +date 2009.03.11.19.09.10; author tester; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log +@Rev 2 +@ +text +@1.2 +@ + + +1.2.2.1 +log +@Rev 4 Branch A +@ +text +@d1 1 +a1 1 +1.2.2.1 +@ + + +1.2.2.2 +log +@Rev 5 Branch A +@ +text +@d1 1 +a1 1 +1.2.2.2 +@ + + +1.1 +log +@Rev 1 +@ +text +@d1 1 +a1 1 +1.1 +@ diff --git a/t/t9603/cvsroot/module/b,v b/t/t9603/cvsroot/module/b,v new file mode 100644 index 0000000000..d26885518a --- /dev/null +++ b/t/t9603/cvsroot/module/b,v @@ -0,0 +1,90 @@ +head 1.3; +access; +symbols + A:1.2.0.2; +locks; strict; +comment @# @; + + +1.3 +date 2009.03.11.19.05.08; author tester; state Exp; +branches; +next 1.2; + +1.2 +date 2009.02.21.18.11.43; author tester; state Exp; +branches + 1.2.2.1; +next 1.1; + +1.1 +date 2009.02.21.18.11.14; author tester; state Exp; +branches; +next ; + +1.2.2.1 +date 2009.03.11.19.03.52; author tester; state Exp; +branches; +next 1.2.2.2; + +1.2.2.2 +date 2009.03.11.19.09.10; author tester; state Exp; +branches; +next ; + + +desc +@@ + + +1.3 +log +@Rev 4 +@ +text +@1.3 +@ + + +1.2 +log +@Rev 3 +@ +text +@d1 1 +a1 1 +1.2 +@ + + +1.2.2.1 +log +@Rev 4 Branch A +@ +text +@d1 1 +a1 1 +1.2.2.1 +@ + + +1.2.2.2 +log +@Rev 5 Branch A +@ +text +@d1 1 +a1 1 +1.2 +@ + + +1.1 +log +@Rev 2 +@ +text +@d1 1 +a1 1 +1.1 +@ diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh new file mode 100755 index 0000000000..3787186703 --- /dev/null +++ b/t/t9700-perl-git.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# +# Copyright (c) 2008 Lea Wiemann +# + +test_description='perl interface (Git.pm)' +. ./test-lib.sh + +if ! test_have_prereq PERL; then + skip_all='skipping perl interface tests, perl not available' + test_done +fi + +"$PERL_PATH" -MTest::More -e 0 2>/dev/null || { + skip_all="Perl Test::More unavailable, skipping test" + test_done +} + +# set up test repository + +test_expect_success \ + 'set up test repository' \ + 'echo "test file 1" > file1 && + echo "test file 2" > file2 && + mkdir directory1 && + echo "in directory1" >> directory1/file && + mkdir directory2 && + echo "in directory2" >> directory2/file && + git add . && + git commit -m "first commit" && + + echo "new file in subdir 2" > directory2/file2 && + git add . && + git commit -m "commit in directory2" && + + echo "changed file 1" > file1 && + git commit -a -m "second commit" && + + git config --add color.test.slot1 green && + git config --add test.string value && + git config --add test.dupstring value1 && + git config --add test.dupstring value2 && + git config --add test.booltrue true && + git config --add test.boolfalse no && + git config --add test.boolother other && + git config --add test.int 2k + ' + +# 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 + +test_done diff --git a/t/t9700/test.pl b/t/t9700/test.pl new file mode 100755 index 0000000000..671f38db2b --- /dev/null +++ b/t/t9700/test.pl @@ -0,0 +1,119 @@ +#!/usr/bin/perl +use lib (split(/:/, $ENV{GITPERLLIB})); + +use 5.006002; +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; + +BEGIN { use_ok('Git') } + +# set up +our $abs_repo_dir = cwd(); +ok(our $r = Git->repository(Directory => "."), "open repository"); + +# config +is($r->config("test.string"), "value", "config scalar: string"); +is_deeply([$r->config("test.dupstring")], ["value1", "value2"], + "config array: string"); +is($r->config("test.nonexistent"), undef, "config scalar: nonexistent"); +is_deeply([$r->config("test.nonexistent")], [], "config array: nonexistent"); +is($r->config_int("test.int"), 2048, "config_int: integer"); +is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent"); +ok($r->config_bool("test.booltrue"), "config_bool: true"); +ok(!$r->config_bool("test.boolfalse"), "config_bool: false"); +our $ansi_green = "\x1b[32m"; +is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color"); +# Cannot test $r->get_colorbool("color.foo")) because we do not +# control whether our STDOUT is a terminal. + +# Failure cases for config: +# Save and restore STDERR; we will probably extract this into a +# "dies_ok" method and possibly move the STDERR handling to Git.pm. +open our $tmpstderr, ">&STDERR" or die "cannot save STDERR"; close STDERR; +eval { $r->config("test.dupstring") }; +ok($@, "config: duplicate entry in scalar context fails"); +eval { $r->config_bool("test.boolother") }; +ok($@, "config_bool: non-boolean values fail"); +open STDERR, ">&", $tmpstderr or die "cannot restore STDERR"; + +# ident +like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/, + "ident scalar: author (type)"); +like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/, + "ident scalar: committer (type)"); +is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)"); +my ($name, $email, $time_tz) = $r->ident('author'); +is_deeply([$name, $email], ["A U Thor", "author\@example.com"], + "ident array: author"); +like($time_tz, qr/[0-9]+ \+0000/, "ident array: author"); +is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"], + "ident array: ident string"); +is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string"); + +# ident_person +is($r->ident_person("aUthor"), "A U Thor <author\@example.com>", + "ident_person: author (type)"); +is($r->ident_person("Name <email> 123 +0000"), "Name <email>", + "ident_person: ident string"); +is($r->ident_person("Name", "email", "123 +0000"), "Name <email>", + "ident_person: array"); + +# objects and hashes +ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)"); +my $tmpfile = "file.tmp"; +open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!"; +is($r->cat_blob($file1hash, \*TEMPFILE), 15, "cat_blob: size"); +our $blobcontents; +{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; } +is($blobcontents, "changed file 1\n", "cat_blob: data"); +close TEMPFILE or die "Failed writing to $tmpfile: $!"; +is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip"); +open TEMPFILE, ">$tmpfile" or die "Can't open $tmpfile: $!"; +print TEMPFILE my $test_text = "test blob, to be inserted\n"; +close TEMPFILE or die "Failed writing to $tmpfile: $!"; +like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/, + "hash_and_insert_object: returns hash"); +open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!"; +is($r->cat_blob($newhash, \*TEMPFILE), length $test_text, "cat_blob: roundtrip size"); +{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; } +is($blobcontents, $test_text, "cat_blob: roundtrip data"); +close TEMPFILE; +unlink $tmpfile; + +# paths +is($r->repo_path, $abs_repo_dir . "/.git", "repo_path"); +is($r->wc_path, $abs_repo_dir . "/", "wc_path"); +is($r->wc_subdir, "", "wc_subdir initial"); +$r->wc_chdir("directory1"); +is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir"); +is($r->config("test.string"), "value", "config after wc_chdir"); + +# Object generation in sub directory +chdir("directory2"); +my $r2 = Git->repository(); +is($r2->repo_path, $abs_repo_dir . "/.git", "repo_path (2)"); +is($r2->wc_path, $abs_repo_dir . "/", "wc_path (2)"); +is($r2->wc_subdir, "directory2/", "wc_subdir initial (2)"); + +# commands in sub directory +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 c0754747fb..e8f21d577c 100755..100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -2,20 +2,54 @@ # # 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. +case "$GIT_TEST_TEE_STARTED, $* " in +done,*) + # do not redirect again + ;; +*' --tee '*|*' --va'*) + mkdir -p test-results + BASE=test-results/$(basename "$0" .sh) + (GIT_TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1; + echo $? > $BASE.exit) | tee $BASE.out + test "$(cat $BASE.exit)" = 0 + exit + ;; +esac + +# Keep the original TERM for say_color +ORIGINAL_TERM=$TERM # For repeatability, reset the environment to known value. LANG=C LC_ALL=C PAGER=cat TZ=UTC -export LANG LC_ALL PAGER TZ +TERM=dumb +export LANG LC_ALL PAGER TERM TZ EDITOR=: -VISUAL=: +unset VISUAL +unset GIT_EDITOR unset AUTHOR_DATE unset AUTHOR_EMAIL unset AUTHOR_NAME unset COMMIT_AUTHOR_EMAIL unset COMMIT_AUTHOR_NAME +unset EMAIL unset GIT_ALTERNATE_OBJECT_DIRECTORIES unset GIT_AUTHOR_DATE GIT_AUTHOR_EMAIL=author@example.com @@ -25,16 +59,28 @@ GIT_COMMITTER_EMAIL=committer@example.com GIT_COMMITTER_NAME='C O Mitter' unset GIT_DIFF_OPTS unset GIT_DIR +unset GIT_WORK_TREE unset GIT_EXTERNAL_DIFF unset GIT_INDEX_FILE unset GIT_OBJECT_DIRECTORY +unset GIT_CEILING_DIRECTORIES unset SHA1_FILE_DIRECTORIES unset SHA1_FILE_DIRECTORY +unset GIT_NOTES_REF +unset GIT_NOTES_DISPLAY_REF +unset GIT_NOTES_REWRITE_REF +unset GIT_NOTES_REWRITE_MODE GIT_MERGE_VERBOSITY=5 export GIT_MERGE_VERBOSITY export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME -export EDITOR VISUAL +export EDITOR + +# Protect ourselves from common misconfiguration to export +# CDPATH into the environment +unset CDPATH + +unset GREP_OPTIONS case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in 1|2|true) @@ -45,25 +91,27 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in ;; esac +# Convenience +# +# A regexp to match 5 and 40 hexdigits +_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05" + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... # This test checks if command xyzzy does the right thing... # ' # . ./test-lib.sh - -error () { - echo "* error: $*" - trap - exit - exit 1 -} - -say () { - echo "* $*" -} - -test "${test_description}" != "" || -error "Test script did not set test_description." +[ "x$ORIGINAL_TERM" != "xdumb" ] && ( + TERM=$ORIGINAL_TERM && + export TERM && + [ -t 1 ] && + tput bold >/dev/null 2>&1 && + tput setaf 1 >/dev/null 2>&1 && + tput sgr0 >/dev/null 2>&1 + ) && + color=t while test "$#" -ne 0 do @@ -72,19 +120,77 @@ do debug=t; shift ;; -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate) immediate=t; shift ;; + -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests) + GIT_TEST_LONG=t; export GIT_TEST_LONG; shift ;; -h|--h|--he|--hel|--help) - echo "$test_description" - exit 0 ;; + help=t; shift ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; - --no-python) - # noop now... + -q|--q|--qu|--qui|--quie|--quiet) + # 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 ;; + --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) + valgrind=t; verbose=t; shift ;; + --tee) + shift ;; # was handled already + --root=*) + root=$(expr "z$1" : 'z[^=]*=\(.*\)') shift ;; *) - break ;; + echo "error: unknown test option '$1'" >&2; exit 1 ;; esac done +if test -n "$color"; then + say_color () { + ( + TERM=$ORIGINAL_TERM + export TERM + case "$1" in + error) tput bold; tput setaf 1;; # bold red + skip) tput bold; tput setaf 2;; # bold green + pass) tput setaf 2;; # green + info) tput setaf 3;; # brown + *) test -n "$quiet" && return;; + esac + shift + printf "%s" "$*" + tput sgr0 + echo + ) + } +else + say_color() { + test -z "$1" && test -n "$quiet" && return + shift + echo "$*" + } +fi + +error () { + say_color error "error: $*" + GIT_EXIT_OK=t + exit 1 +} + +say () { + say_color info "$*" +} + +test "${test_description}" != "" || +error "Test script did not set test_description." + +if test "$help" = "t" +then + echo "$test_description" + exit 0 +fi + exec 5>&1 if test "$verbose" = "t" then @@ -95,8 +201,68 @@ fi test_failure=0 test_count=0 +test_fixed=0 +test_broken=0 +test_success=0 -trap 'echo >&5 "FATAL: Unexpected exit with code $?"; exit 1' exit +test_external_has_tap=0 + +die () { + code=$? + if test -n "$GIT_EXIT_OK" + then + exit $code + else + echo >&5 "FATAL: Unexpected exit with code $code" + exit 1 + fi +} + +GIT_EXIT_OK= +trap 'die' EXIT + +# The semantics of the editor variables are that of invoking +# sh -c "$EDITOR \"$@\"" files ... +# +# If our trash directory contains shell metacharacters, they will be +# interpreted if we just set $EDITOR directly, so do a little dance with +# environment variables to work around this. +# +# In particular, quoting isn't enough, as the path may contain the same quote +# that we're using. +test_set_editor () { + FAKE_EDITOR="$1" + export FAKE_EDITOR + EDITOR='"$FAKE_EDITOR"' + export EDITOR +} + +test_decode_color () { + sed -e 's/.\[1m/<WHITE>/g' \ + -e 's/.\[31m/<RED>/g' \ + -e 's/.\[32m/<GREEN>/g' \ + -e 's/.\[33m/<YELLOW>/g' \ + -e 's/.\[34m/<BLUE>/g' \ + -e 's/.\[35m/<MAGENTA>/g' \ + -e 's/.\[36m/<CYAN>/g' \ + -e 's/.\[m/<RESET>/g' +} + +q_to_nul () { + perl -pe 'y/Q/\000/' +} + +q_to_cr () { + tr Q '\015' +} + +append_cr () { + sed -e 's/$/Q/' | tr Q '\015' +} + +remove_cr () { + tr '\015' Q | sed -e 's/Q$//' +} test_tick () { if test -z "${test_tick+set}" @@ -110,50 +276,126 @@ test_tick () { export GIT_COMMITTER_DATE GIT_AUTHOR_DATE } +# Call test_commit with the arguments "<message> [<file> [<contents>]]" +# +# This will commit a file with the given contents and the given commit +# message. It will also add a tag with <message> as name. +# +# Both <file> and <contents> default to <message>. + +test_commit () { + file=${2:-"$1.t"} + echo "${3-$1}" > "$file" && + git add "$file" && + test_tick && + git commit -m "$1" && + git tag "$1" +} + +# Call test_merge with the arguments "<message> <commit>", where <commit> +# can be a tag pointing to the commit-to-merge. + +test_merge () { + test_tick && + git merge -m "$1" "$2" && + git tag "$1" +} + +# This function helps systems where core.filemode=false is set. +# Use it instead of plain 'chmod +x' to set or unset the executable bit +# of a file in the working directory and add it to the index. + +test_chmod () { + chmod "$@" && + git update-index --add "--chmod=$@" +} + +# Use test_set_prereq to tell that a particular prerequisite is available. +# The prerequisite can later be checked for in two ways: +# +# - Explicitly using test_have_prereq. +# +# - Implicitly by specifying the prerequisite tag in the calls to +# test_expect_{success,failure,code}. +# +# The single parameter is the prerequisite tag (a simple word, in all +# capital letters by convention). + +test_set_prereq () { + satisfied="$satisfied$1 " +} +satisfied=" " + +test_have_prereq () { + case $satisfied in + *" $1 "*) + : yes, have it ;; + *) + ! : nope ;; + esac +} + # You are not expected to call test_ok_ and test_failure_ directly, use # the text_expect_* functions instead. test_ok_ () { - test_count=$(expr "$test_count" + 1) - say " ok $test_count: $@" + test_success=$(($test_success + 1)) + say_color "" "ok $test_count - $@" } test_failure_ () { - test_count=$(expr "$test_count" + 1) - test_failure=$(expr "$test_failure" + 1); - say "FAIL $test_count: $1" + test_failure=$(($test_failure + 1)) + say_color error "not ok - $test_count $1" shift - echo "$@" | sed -e 's/^/ /' - test "$immediate" = "" || { trap - exit; exit 1; } + echo "$@" | sed -e 's/^/# /' + test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; } +} + +test_known_broken_ok_ () { + test_fixed=$(($test_fixed+1)) + say_color "" "ok $test_count - $@ # TODO known breakage" } +test_known_broken_failure_ () { + test_broken=$(($test_broken+1)) + say_color skip "not ok $test_count - $@ # TODO known breakage" +} test_debug () { test "$debug" = "" || eval "$1" } 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 } test_skip () { - this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$') - this_test="$this_test.$(expr "$test_count" + 1)" + test_count=$(($test_count+1)) to_skip= for skp in $GIT_SKIP_TESTS do - case "$this_test" in + case $this_test.$test_count in $skp) to_skip=t + break esac done + if test -z "$to_skip" && test -n "$prereq" && + ! test_have_prereq "$prereq" + then + to_skip=t + fi case "$to_skip" in t) - say >&3 "skipping test: $@" - test_count=$(expr "$test_count" + 1) - say "skip $test_count: $1" + say_color skip >&3 "skipping test: $@" + say_color skip "ok $test_count # skip $1" : true ;; *) @@ -163,25 +405,27 @@ test_skip () { } test_expect_failure () { + test "$#" = 3 && { prereq=$1; shift; } || prereq= test "$#" = 2 || - error "bug in the test script: not 2 parameters to test-expect-failure" + error "bug in the test script: not 2 or 3 parameters to test-expect-failure" if ! test_skip "$@" then - say >&3 "expecting failure: $2" + say >&3 "checking known breakage: $2" test_run_ "$2" - if [ "$?" = 0 -a "$eval_ret" != 0 -a "$eval_ret" -lt 129 ] + if [ "$?" = 0 -a "$eval_ret" = 0 ] then - test_ok_ "$1" + test_known_broken_ok_ "$1" else - test_failure_ "$@" + test_known_broken_failure_ "$1" fi fi echo >&3 "" } test_expect_success () { + test "$#" = 3 && { prereq=$1; shift; } || prereq= test "$#" = 2 || - error "bug in the test script: not 2 parameters to test-expect-success" + error "bug in the test script: not 2 or 3 parameters to test-expect-success" if ! test_skip "$@" then say >&3 "expecting success: $2" @@ -197,8 +441,9 @@ test_expect_success () { } test_expect_code () { + test "$#" = 4 && { prereq=$1; shift; } || prereq= test "$#" = 3 || - error "bug in the test script: not 3 parameters to test-expect-code" + error "bug in the test script: not 3 or 4 parameters to test-expect-code" if ! test_skip "$@" then say >&3 "expecting exit code $1: $3" @@ -213,50 +458,332 @@ test_expect_code () { echo >&3 "" } -# Most tests can use the created repository, but some amy need to create more. +# test_external runs external test scripts that provide continuous +# test output about their progress, and succeeds/fails on +# zero/non-zero exit code. It outputs the test output on stdout even +# in non-verbose mode, and announces the external script with "# run +# <n>: ..." before running it. When providing relative paths, keep in +# mind that all scripts run in "trash directory". +# Usage: test_external description command arguments... +# Example: test_external 'Perl API' perl ../path/to/test.pl +test_external () { + test "$#" = 4 && { prereq=$1; shift; } || prereq= + test "$#" = 3 || + error >&5 "bug in the test script: not 3 or 4 parameters to test_external" + descr="$1" + shift + if ! test_skip "$descr" "$@" + then + # Announce the script to reduce confusion about the + # test output that follows. + say_color "" "# run $test_count: $descr ($*)" + # Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG + # to be able to use them in script + export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG + # Run command; redirect its stderr to &4 as in + # test_run_, but keep its stdout on our stdout even in + # non-verbose mode. + "$@" 2>&4 + if [ "$?" = 0 ] + then + if test $test_external_has_tap -eq 0; then + test_ok_ "$descr" + else + say_color "" "# test_external test $descr was ok" + test_success=$(($test_success + 1)) + fi + else + if test $test_external_has_tap -eq 0; then + test_failure_ "$descr" "$@" + else + say_color error "# test_external test $descr failed: $@" + test_failure=$(($test_failure + 1)) + fi + fi + fi +} + +# Like test_external, but in addition tests that the command generated +# no output on stderr. +test_external_without_stderr () { + # The temporary file has no (and must have no) security + # implications. + tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi + stderr="$tmp/git-external-stderr.$$.tmp" + test_external "$@" 4> "$stderr" + [ -f "$stderr" ] || error "Internal error: $stderr disappeared." + descr="no stderr: $1" + shift + say >&3 "# expecting no stderr from previous command" + if [ ! -s "$stderr" ]; then + rm "$stderr" + + if test $test_external_has_tap -eq 0; then + test_ok_ "$descr" + else + say_color "" "# test_external_without_stderr test $descr was ok" + test_success=$(($test_success + 1)) + fi + else + if [ "$verbose" = t ]; then + output=`echo; echo "# Stderr is:"; cat "$stderr"` + else + output= + fi + # rm first in case test_failure exits. + rm "$stderr" + if test $test_external_has_tap -eq 0; then + test_failure_ "$descr" "$@" "$output" + else + say_color error "# test_external_without_stderr test $descr failed: $@: $output" + test_failure=$(($test_failure + 1)) + fi + fi +} + +# This is not among top-level (test_expect_success | test_expect_failure) +# but is a prefix that can be used in the test script, like: +# +# test_expect_success 'complain and die' ' +# do something && +# do something else && +# test_must_fail git checkout ../outerspace +# ' +# +# Writing this as "! git checkout ../outerspace" is wrong, because +# the failure could be due to a segv. We want a controlled failure. + +test_must_fail () { + "$@" + test $? -gt 0 -a $? -le 129 -o $? -gt 192 +} + +# 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 () { + "$@" + test $? -ge 0 -a $? -le 129 -o $? -gt 192 +} + +# test_cmp is a helper function to compare actual and expected output. +# You can use it like: +# +# test_expect_success 'foo works' ' +# echo expected >expected && +# foo >actual && +# test_cmp expected actual +# ' +# +# This could be written as either "cmp" or "diff -u", but: +# - cmp's output is not nearly as easy to read as diff -u +# - not all diff versions understand "-u" + +test_cmp() { + $GIT_TEST_CMP "$@" +} + +# This function can be used to schedule some commands to be run +# unconditionally at the end of the test to restore sanity: +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# test_when_finished "git config --unset core.capslock" && +# hello world +# ' +# +# That would be roughly equivalent to +# +# test_expect_success 'test core.capslock' ' +# git config core.capslock true && +# hello world +# git config --unset core.capslock +# ' +# +# except that the greeting and config --unset must both succeed for +# the test to pass. + +test_when_finished () { + test_cleanup="{ $* + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" +} + +# Most tests can use the created repository, but some may need to create more. # Usage: test_create_repo <directory> test_create_repo () { test "$#" = 1 || error "bug in the test script: not 1 parameter to test-create-repo" owd=`pwd` repo="$1" - mkdir "$repo" + mkdir -p "$repo" cd "$repo" || error "Cannot setup test environment" - "$GIT_EXEC_PATH/git" init --template=$GIT_EXEC_PATH/templates/blt/ >/dev/null 2>&1 || + "$GIT_EXEC_PATH/git-init" "--template=$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" } - + test_done () { - trap - exit + GIT_EXIT_OK=t + 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 + + if test "$test_fixed" != 0 + then + 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)" + msg="remaining $(($test_count-$test_broken)) test(s)" + else + msg="$test_count test(s)" + fi case "$test_failure" in 0) - # We could: - # cd .. && rm -fr trash - # but that means we forbid any tests that use their own - # subdirectory from calling test_done without coming back - # to where they started from. - # The Makefile provided will clean this test area so - # we will leave things as they are. - - say "passed all $test_count test(s)" + # 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")" && + rm -rf "$(basename "$remove_trash")" + exit 0 ;; *) - say "failed $test_failure among $test_count test(s)" + 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 } # Test the binaries we have just built. The tests are kept in -# t/ subdirectory and are run in trash subdirectory. -PATH=$(pwd)/..:$PATH -GIT_EXEC_PATH=$(pwd)/.. +# t/ subdirectory and are run in 'trash directory' subdirectory. +TEST_DIRECTORY=$(pwd) +if test -n "$valgrind" +then + make_symlink () { + test -h "$2" && + test "$1" = "$(readlink "$2")" || { + # be super paranoid + if mkdir "$2".lock + then + rm -f "$2" && + ln -s "$1" "$2" && + rm -r "$2".lock + else + while test -d "$2".lock + do + say "Waiting for lock on $2." + sleep 1 + done + fi + } + } + + make_valgrind_symlink () { + # handle only executables + test -x "$1" || return + + base=$(basename "$1") + symlink_target=$TEST_DIRECTORY/../$base + # do not override scripts + if test -x "$symlink_target" && + test ! -d "$symlink_target" && + test "#!" != "$(head -c 2 < "$symlink_target")" + then + symlink_target=../valgrind.sh + fi + case "$base" in + *.sh|*.perl) + symlink_target=../unprocessed-script + esac + # create the link, or replace it if it is out of date + make_symlink "$symlink_target" "$GIT_VALGRIND/bin/$base" || exit + } + + # 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-* + do + make_valgrind_symlink $file + done + OLDIFS=$IFS + IFS=: + for path in $PATH + do + ls "$path"/git-* 2> /dev/null | + while read file + do + make_valgrind_symlink "$file" + done + done + IFS=$OLDIFS + PATH=$GIT_VALGRIND/bin:$PATH + GIT_EXEC_PATH=$GIT_VALGRIND/bin + export GIT_VALGRIND +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 + 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" + 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" + fi + with_dashes=t + fi + PATH="$git_bin_dir:$PATH" + GIT_EXEC_PATH=$TEST_DIRECTORY/.. + if test -n "$with_dashes" ; then + PATH="$TEST_DIRECTORY/..:$PATH" + fi +fi GIT_TEMPLATE_DIR=$(pwd)/../templates/blt -GIT_CONFIG=.git/config -export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG +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 + +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 export GITPERLLIB @@ -264,6 +791,15 @@ test -d ../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" + export GITPYTHONLIB + test -d ../git_remote_helpers/build || { + error "You haven't built git_remote_helpers yet, have you?" + } +fi + if ! test -x ../test-chmtime; then echo >&2 'You need to build test-chmtime:' echo >&2 'Run "make test-chmtime" in the source (toplevel) directory' @@ -271,26 +807,82 @@ if ! test -x ../test-chmtime; then fi # Test repository -test=trash -rm -fr "$test" -test_create_repo $test -cd "$test" +test="trash directory.$(basename "$0" .sh)" +test -n "$root" && test="$root/$test" +case "$test" in +/*) TRASH_DIRECTORY="$test" ;; + *) TRASH_DIRECTORY="$TEST_DIRECTORY/$test" ;; +esac +test ! -z "$debug" || remove_trash=$TRASH_DIRECTORY +rm -fr "$test" || { + GIT_EXIT_OK=t + echo >&5 "FATAL: Cannot prepare test area" + exit 1 +} + +test_create_repo "$test" +# Use -P to resolve symlinks in our working directory so that the cwd +# in subprocesses like git equals our $PWD (for pathname comparisons). +cd -P "$test" || exit 1 -this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$') +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) - say >&3 "skipping test $this_test altogether" - say "skip all tests in $this_test" + case "$this_test" in + $skp) + say_color skip >&3 "skipping test $this_test altogether" + skip_all="skip all tests in $this_test" test_done esac done + +# Provide an implementation of the 'yes' utility +yes () { + if test $# = 0 + then + y=y + else + y="$*" + fi + + while echo "$y" + do + : + done +} + +# Fix some commands on Windows +case $(uname -s) in +*MINGW*) + # Windows has its own (incompatible) sort and find + sort () { + /usr/bin/sort "$@" + } + find () { + /usr/bin/find "$@" + } + sum () { + md5sum "$@" + } + # git sees Windows-style pwd + pwd () { + builtin pwd -W + } + # no POSIX permissions + # backslashes in pathspec are converted to '/' + # exec does not inherit the PID + ;; +*) + test_set_prereq POSIXPERM + test_set_prereq BSLASHPSPEC + test_set_prereq EXECKEEPSPID + ;; +esac + +test -z "$NO_PERL" && test_set_prereq PERL +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 diff --git a/t/valgrind/.gitignore b/t/valgrind/.gitignore new file mode 100644 index 0000000000..d4ae6676d1 --- /dev/null +++ b/t/valgrind/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/templates diff --git a/t/valgrind/analyze.sh b/t/valgrind/analyze.sh new file mode 100755 index 0000000000..d8105d9fab --- /dev/null +++ b/t/valgrind/analyze.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +out_prefix=$(dirname "$0")/../test-results/valgrind.out +output= +count=0 +total_count=0 +missing_message= +new_line=' +' + +# start outputting the current valgrind error in $out_prefix.++$count, +# and the test case which failed in the corresponding .message file +start_output () { + test -z "$output" || return + + # progress + total_count=$(($total_count+1)) + test -t 2 && printf "\rFound %d errors" $total_count >&2 + + count=$(($count+1)) + output=$out_prefix.$count + : > $output + + echo "*** $1 ***" > $output.message +} + +finish_output () { + test ! -z "$output" || return + output= + + # if a test case has more than one valgrind error, we need to + # copy the last .message file to the previous errors + test -z "$missing_message" || { + while test $missing_message -lt $count + do + cp $out_prefix.$count.message \ + $out_prefix.$missing_message.message + missing_message=$(($missing_message+1)) + done + missing_message= + } +} + +# group the valgrind errors by backtrace +output_all () { + last_line= + j=0 + i=1 + while test $i -le $count + do + # output <number> <backtrace-in-one-line> + echo "$i $(tr '\n' ' ' < $out_prefix.$i)" + i=$(($i+1)) + done | + sort -t ' ' -k 2 | # order by <backtrace-in-one-line> + while read number line + do + # find duplicates, do not output backtrace twice + if test "$line" != "$last_line" + then + last_line=$line + j=$(($j+1)) + printf "\nValgrind error $j:\n\n" + cat $out_prefix.$number + printf "\nfound in:\n" + fi + # print the test case where this came from + printf "\n" + cat $out_prefix.$number.message + done +} + +handle_one () { + OLDIFS=$IFS + IFS="$new_line" + while read line + do + case "$line" in + # backtrace, possibly a new one + ==[0-9]*) + + # Does the current valgrind error have a message yet? + case "$output" in + *.message) + test -z "$missing_message" && + missing_message=$count + output= + esac + + start_output $(basename $1) + echo "$line" | + sed 's/==[0-9]*==/==valgrind==/' >> $output + ;; + # end of backtrace + '}') + test -z "$output" || { + echo "$line" >> $output + test $output = ${output%.message} && + output=$output.message + } + ;; + # end of test case + '') + finish_output + ;; + # normal line; if $output is set, print the line + *) + test -z "$output" || echo "$line" >> $output + ;; + esac + done < $1 + IFS=$OLDIFS + + # just to be safe + finish_output +} + +for test_script in "$(dirname "$0")"/../test-results/*.out +do + handle_one $test_script +done + +output_all diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp new file mode 100644 index 0000000000..9e013fa3b2 --- /dev/null +++ b/t/valgrind/default.supp @@ -0,0 +1,45 @@ +{ + ignore-zlib-errors-cond + Memcheck:Cond + obj:*libz.so* +} + +{ + ignore-zlib-errors-value8 + Memcheck:Value8 + obj:*libz.so* +} + +{ + ignore-zlib-errors-value4 + Memcheck:Value4 + obj:*libz.so* +} + +{ + ignore-ldso-cond + Memcheck:Cond + obj:*ld-*.so +} + +{ + ignore-ldso-addr8 + Memcheck:Addr8 + obj:*ld-*.so +} + +{ + ignore-ldso-addr4 + Memcheck:Addr4 + obj:*ld-*.so +} + +{ + writing-data-from-zlib-triggers-even-more-errors + Memcheck:Param + write(buf) + obj:/lib/ld-*.so + fun:write_in_full + fun:write_buffer + fun:write_loose_object +} diff --git a/t/valgrind/valgrind.sh b/t/valgrind/valgrind.sh new file mode 100755 index 0000000000..582b4dca94 --- /dev/null +++ b/t/valgrind/valgrind.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +base=$(basename "$0") + +TRACK_ORIGINS= + +VALGRIND_VERSION=$(valgrind --version) +VALGRIND_MAJOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*\([0-9]*\)') +VALGRIND_MINOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*[0-9]*\.\([0-9]*\)') +test 3 -gt "$VALGRIND_MAJOR" || +test 3 -eq "$VALGRIND_MAJOR" -a 4 -gt "$VALGRIND_MINOR" || +TRACK_ORIGINS=--track-origins=yes + +exec valgrind -q --error-exitcode=126 \ + --leak-check=no \ + --suppressions="$GIT_VALGRIND/default.supp" \ + --gen-suppressions=all \ + $TRACK_ORIGINS \ + --log-fd=4 \ + --input-fd=4 \ + $GIT_VALGRIND_OPTIONS \ + "$GIT_VALGRIND"/../../"$base" "$@" |