diff options
Diffstat (limited to 't')
546 files changed, 34413 insertions, 3450 deletions
diff --git a/t/.gitignore b/t/.gitignore index b27e280083..7dcbb232cd 100644 --- a/t/.gitignore +++ b/t/.gitignore @@ -1,2 +1,2 @@ -/trash directory +/trash directory* /test-results diff --git a/t/Makefile b/t/Makefile index 0d65cedaa6..bd09390d32 100644 --- a/t/Makefile +++ b/t/Makefile @@ -3,6 +3,8 @@ # Copyright (c) 2005 Junio C Hamano # +-include ../config.mak + #GIT_TEST_OPTS=--verbose --debug SHELL_PATH ?= $(SHELL) TAR ?= $(TAR) @@ -14,7 +16,8 @@ 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: pre-clean $(T) aggregate-results clean +all: pre-clean + $(MAKE) aggregate-results-and-cleanup $(T): @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) @@ -23,7 +26,11 @@ pre-clean: $(RM) -r test-results clean: - $(RM) -r 'trash directory' test-results + $(RM) -r 'trash directory'.* test-results + +aggregate-results-and-cleanup: $(T) + $(MAKE) aggregate-results + $(MAKE) clean aggregate-results: '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-* @@ -33,5 +40,7 @@ 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: pre-clean $(T) aggregate-results clean -.NOTPARALLEL: +valgrind: + GIT_TEST_OPTS=--valgrind $(MAKE) + +.PHONY: pre-clean $(T) aggregate-results clean valgrind @@ -39,7 +39,8 @@ this: * passed all 3 test(s) 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 @@ -58,6 +59,43 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate 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. + +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 -------------- @@ -212,6 +250,24 @@ 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. Tips for Writing Tests ---------------------- diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index cacb273aff..396b9653a3 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -114,7 +114,10 @@ test_expect_success \ test_expect_success \ 'some edit' \ 'mv file file.orig && - sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/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"' diff --git a/t/diff-lib.sh b/t/diff-lib.sh index 4bddeb591e..75a35fcd06 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. diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh new file mode 100644 index 0000000000..5a734b1b7b --- /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/gitweb.css'); +our \$logo = 'file:///$TEST_DIRECTORY/../gitweb/git-logo.png'; +our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/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 + say 'skipping gitweb tests, perl not available' + test_done +fi + +perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || { + say 'skipping gitweb tests, perl version is too old' + test_done +} + +gitweb_init diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh new file mode 100644 index 0000000000..4b3b793730 --- /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 + say '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*) + ;; +'') + say 'skipping cvsimport tests, cvsps not found' + test_done + ;; +*) + say '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 a841df2a9e..0f7f35ccc9 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -1,28 +1,36 @@ . ./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' : + say 'skipping git svn tests, NO_SVN_TESTS defined' + test_done +fi +if ! test_have_prereq PERL; then + say 'skipping git svn tests, perl not available' 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 +PERL=${PERL:-perl} svn >/dev/null 2>&1 if test $? -ne 1 then - test_expect_success 'skipping git-svn tests, svn not found' : + say '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 -w -e " use SVN::Core; use SVN::Repos; \$SVN::Core::VERSION gt '1.1.0' or exit(42); @@ -38,9 +46,8 @@ then else err='Perl SVN libraries not found or unusable, skipping test' fi - test_expect_success "$err" : + say "$err" test_done - exit fi rawsvnrepo="$svnrepo" @@ -50,6 +57,19 @@ 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 \ @@ -88,7 +108,7 @@ start_httpd () { mkdir "$GIT_DIR"/logs cat > "$GIT_DIR/httpd.conf" <<EOF -ServerName "git-svn test" +ServerName "git svn test" ServerRoot "$GIT_DIR" DocumentRoot "$GIT_DIR" PidFile "$GIT_DIR/httpd.pid" @@ -111,7 +131,7 @@ stop_httpd () { } convert_to_rev_db () { - perl -w -- - "$@" <<\EOF + $PERL -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]"; @@ -135,3 +155,19 @@ close $wr or die $!; close $rd or die $!; EOF } + +require_svnserve () { + if test -z "$SVNSERVE_PORT" + then + say '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 index dc473dfb53..28aff887b5 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -8,21 +8,46 @@ then say "skipping test, network testing disabled by default" say "(define GIT_TEST_HTTPD to enable)" test_done - exit fi -LIB_HTTPD_PATH=${LIB_HTTPD_PATH-'/usr/sbin/apache2'} +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="$PWD"/../lib-httpd +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 - say "skipping test, no web server found at '$LIB_HTTPD_PATH'" - test_done - exit + say "skipping test, no web server found at '$LIB_HTTPD_PATH'" + test_done fi HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \ @@ -36,17 +61,19 @@ then then say "skipping test, at least Apache version 2 is required" test_done - exit + fi + if ! test -d "$DEFAULT_HTTPD_MODULE_PATH" + then + say "Apache module directory not found. Skipping tests." + test_done fi - LIB_HTTPD_MODULE_PATH='/usr/lib/apache2/modules' + LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH" fi else error "Could not identify web server at '$LIB_HTTPD_PATH'" fi -HTTPD_PARA="" - prepare_httpd() { mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH" @@ -82,18 +109,25 @@ prepare_httpd() { } start_httpd() { - prepare_httpd + prepare_httpd >&3 2>&4 - trap 'stop_httpd; die' exit + 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 + -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start \ + >&3 2>&4 + if test $? -ne 0 + then + say "skipping test, web server setup failed" + trap 'die' EXIT + test_done + fi } stop_httpd() { - trap 'die' exit + trap 'die' EXIT "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ - -f "$TEST_PATH/apache.conf" -k stop + -f "$TEST_PATH/apache.conf" $HTTPD_PARA -k stop } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 4717c2d33b..4961505d1d 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -1,7 +1,40 @@ 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 @@ -20,7 +53,7 @@ SSLEngine On LoadModule dav_fs_module modules/mod_dav_fs.so DAVLockDB DAVLock - <Location /> + <Location /dumb/> Dav on </Location> </IfDefine> diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh new file mode 100644 index 0000000000..ce36f34d03 --- /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 + say '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-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/t0000-basic.sh b/t/t0000-basic.sh index 70df15cbd8..f4ca4fc85c 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -57,6 +57,21 @@ test_expect_failure 'pretend we have a known breakage' ' 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 ################################################################ # Basics of the basics @@ -100,12 +115,31 @@ test_expect_success \ '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' @@ -115,7 +149,7 @@ test_expect_success \ '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 @@ -127,14 +161,14 @@ cat >expected <<\EOF EOF test_expect_success \ 'validate git ls-files output for a known tree.' \ - 'diff current expected' + 'test_cmp expected current' test_expect_success \ 'writing tree out with git write-tree.' \ 'tree=$(git write-tree)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b' + 'test "$tree" = "$expectedtree"' test_expect_success \ 'showing tree with git ls-tree' \ @@ -145,16 +179,16 @@ cat >expected <<\EOF 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'git ls-tree output for a known tree.' \ - 'diff current expected' + '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 +$expectfilter >expected <<\EOF 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 @@ -166,7 +200,7 @@ cat >expected <<\EOF EOF test_expect_success \ 'git ls-tree -r output for a known tree.' \ - 'diff current expected' + 'test_cmp expected current' # But with -r -t we can have both. test_expect_success \ @@ -185,23 +219,23 @@ cat >expected <<\EOF 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'git ls-tree -r output for a known tree.' \ - 'diff current expected' + 'test_cmp expected current' test_expect_success \ 'writing partial tree out with git write-tree --prefix.' \ 'ptree=$(git write-tree --prefix=path3)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3' + 'test "$ptree" = "$expectedptree1"' test_expect_success \ 'writing partial tree out with git write-tree --prefix.' \ 'ptree=$(git write-tree --prefix=path3/subp3)' test_expect_success \ 'validate object ID for a known tree.' \ - 'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2' + 'test "$ptree" = "$expectedptree2"' cat >badobjects <<EOF 100644 blob 1000000000000000000000000000000000000000 dir/file1 @@ -234,7 +268,7 @@ test_expect_success \ 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 @@ -257,7 +291,7 @@ test_expect_success \ '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) && @@ -293,7 +327,7 @@ test_expect_success 'update-index D/F conflict' ' test $numpath0 = 1 ' -test_expect_success 'absolute path works as expected' ' +test_expect_success SYMLINKS 'absolute path works as expected' ' mkdir first && ln -s ../.git first/.git && mkdir second && diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 2a38d98cb4..5386504790 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -141,4 +141,154 @@ test_expect_success 'reinit' ' 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 --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_done diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh index 4db4ac44c9..cb144258cc 100755 --- a/t/t0002-gitfile.sh +++ b/t/t0002-gitfile.sh @@ -32,7 +32,7 @@ test_expect_success 'bad setup: invalid .git file format' ' echo "git rev-parse accepted an invalid .git file" false fi && - if ! grep -qe "Invalid gitfile format" .err + if ! grep "Invalid gitfile format" .err then echo "git rev-parse returned wrong error" false @@ -46,7 +46,7 @@ test_expect_success 'bad setup: invalid .git file path' ' echo "git rev-parse accepted an invalid .git file path" false fi && - if ! grep -qe "Not a git repository" .err + if ! grep "Not a git repository" .err then echo "git rev-parse returned wrong error" false diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 3d8e06a20f..1c77192eb3 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -47,6 +47,23 @@ test_expect_success 'attribute test' ' ' +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/* +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 && diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh index 63e1217e71..2342ac5788 100755 --- a/t/t0004-unwritable.sh +++ b/t/t0004-unwritable.sh @@ -15,7 +15,7 @@ test_expect_success setup ' ' -test_expect_success 'write-tree should notice unwritable repository' ' +test_expect_success POSIXPERM 'write-tree should notice unwritable repository' ' ( chmod a-w .git/objects .git/objects/?? && @@ -27,7 +27,7 @@ test_expect_success 'write-tree should notice unwritable repository' ' ' -test_expect_success 'commit should notice unwritable repository' ' +test_expect_success POSIXPERM 'commit should notice unwritable repository' ' ( chmod a-w .git/objects .git/objects/?? && @@ -39,7 +39,7 @@ test_expect_success 'commit should notice unwritable repository' ' ' -test_expect_success 'update-index should notice unwritable repository' ' +test_expect_success POSIXPERM 'update-index should notice unwritable repository' ' ( echo 6O >file && @@ -52,7 +52,7 @@ test_expect_success 'update-index should notice unwritable repository' ' ' -test_expect_success 'add should notice unwritable repository' ' +test_expect_success POSIXPERM 'add should notice unwritable repository' ' ( echo b >file && diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh new file mode 100755 index 0000000000..09f855af3e --- /dev/null +++ b/t/t0005-signals.sh @@ -0,0 +1,22 @@ +#!/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 + 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..75b02af86d --- /dev/null +++ b/t/t0006-date.sh @@ -0,0 +1,76 @@ +#!/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_${3:-success} "parse date ($1)" " + 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_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 1be7446d8d..c3e7e322a8 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -4,21 +4,8 @@ test_description='CRLF conversion' . ./test-lib.sh -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 <"$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 ' @@ -156,7 +143,7 @@ test_expect_success 'checkout with autocrlf=true' ' 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 @@ -180,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' ' for f in one dir/two do - if remove_cr "$f" >/dev/null + if has_cr "$f" then echo "Eh? $f" false @@ -245,7 +232,7 @@ test_expect_success 'apply patch (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 } @@ -272,7 +259,7 @@ test_expect_success 'apply patch --index (autocrlf=true)' ' 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 } @@ -285,7 +272,7 @@ test_expect_success '.gitattributes says two is binary' ' git config core.autocrlf true && git read-tree --reset -u HEAD && - if remove_cr dir/two >/dev/null + if has_cr dir/two then echo "Huh?" false @@ -293,7 +280,7 @@ test_expect_success '.gitattributes says two is binary' ' : happy fi && - if remove_cr one >/dev/null + if has_cr one then : happy else @@ -301,7 +288,7 @@ test_expect_success '.gitattributes says two is binary' ' false fi && - if remove_cr three >/dev/null + if has_cr three then echo "Huh?" false @@ -316,7 +303,7 @@ test_expect_success '.gitattributes says two is input' ' echo "two crlf=input" >.gitattributes && git read-tree --reset -u HEAD && - if remove_cr dir/two >/dev/null + if has_cr dir/two then echo "Huh?" false @@ -331,7 +318,7 @@ test_expect_success '.gitattributes says two and three are text' ' echo "t* crlf" >.gitattributes && git read-tree --reset -u HEAD && - if remove_cr dir/two >/dev/null + if has_cr dir/two then : happy else @@ -339,7 +326,7 @@ test_expect_success '.gitattributes says two and three are text' ' false fi && - if remove_cr three >/dev/null + if has_cr three then : happy else @@ -357,14 +344,14 @@ test_expect_success 'in-tree .gitattributes (1)' ' rm -rf tmp one dir .gitattributes patch.file three && git read-tree --reset -u HEAD && - if remove_cr one >/dev/null + if has_cr one then echo "Eh? one should not have CRLF" false else : happy fi && - remove_cr three >/dev/null || { + has_cr three || { echo "Eh? three should still have CRLF" false } @@ -376,14 +363,14 @@ test_expect_success 'in-tree .gitattributes (2)' ' git read-tree --reset HEAD && git checkout-index -f -q -u -a && - if remove_cr one >/dev/null + if has_cr one then echo "Eh? one should not have CRLF" false else : happy fi && - remove_cr three >/dev/null || { + has_cr three || { echo "Eh? three should still have CRLF" false } @@ -396,14 +383,14 @@ test_expect_success 'in-tree .gitattributes (3)' ' git checkout-index -u .gitattributes && git checkout-index -u one dir/two three && - if remove_cr one >/dev/null + if has_cr one then echo "Eh? one should not have CRLF" false else : happy fi && - remove_cr three >/dev/null || { + has_cr three || { echo "Eh? three should still have CRLF" false } @@ -416,19 +403,50 @@ test_expect_success 'in-tree .gitattributes (4)' ' git checkout-index -u one dir/two three && git checkout-index -u .gitattributes && - if remove_cr one >/dev/null + if has_cr one then echo "Eh? one should not have CRLF" false else : happy fi && - remove_cr three >/dev/null || { + 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 && diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 8fc39d77ce..6cb8d60ea2 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -4,7 +4,8 @@ test_description='blob conversion via gitattributes' . ./test-lib.sh -cat <<\EOF >rot13.sh +cat <<EOF >rot13.sh +#!$SHELL_PATH tr \ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \ 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM' diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh index 7d1ce2d056..7af3fbcc7b 100755 --- a/t/t0022-crlf-rename.sh +++ b/t/t0022-crlf-rename.sh @@ -6,13 +6,13 @@ test_description='ignore CR in CRLF sequence while computing similiarity' test_expect_success setup ' - cat ../t0022-crlf-rename.sh >sample && + cat "$TEST_DIRECTORY"/t0022-crlf-rename.sh >sample && git add sample && test_tick && git commit -m Initial && - sed -e "s/\$/
/" ../t0022-crlf-rename.sh >elpmas && + append_cr <"$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas && git add elpmas && rm -f sample && diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh index 6f8a4347d5..aaed725402 100755 --- a/t/t0023-crlf-am.sh +++ b/t/t0023-crlf-am.sh @@ -36,7 +36,7 @@ test_expect_success 'setup' ' test_expect_success 'am' ' - git am --binary -3 <patchfile && + git am -3 <patchfile && git diff-files --name-status --exit-code ' 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/t0040-parse-options.sh b/t/t0040-parse-options.sh index 03dbe00102..3d450ed379 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -12,12 +12,14 @@ 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> @@ -29,6 +31,10 @@ String options 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 @@ -47,15 +53,18 @@ test_expect_success 'test help' ' 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 > output 2> output.err && + 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 ' @@ -63,16 +72,18 @@ test_expect_success 'short options' ' 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 \ + --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\ > output 2> output.err && test ! -s output.err && test_cmp expect output @@ -82,17 +93,21 @@ 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 @@ -108,11 +123,13 @@ test_expect_success 'intermingled arguments' ' 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' ' @@ -135,11 +152,13 @@ test_expect_success 'ambiguously abbreviated option' ' 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)' ' @@ -161,11 +180,13 @@ test_expect_success 'detect possible typos' ' 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 @@ -177,12 +198,14 @@ test_expect_success 'keep some options as arguments' ' cat > expect <<EOF boolean: 0 -integer: 1 +integer: 0 +timestamp: 1 string: default abbrev: 7 verbose: 0 quiet: yes dry run: no +file: (not set) arg 00: foo EOF @@ -197,11 +220,13 @@ 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' ' @@ -223,11 +248,13 @@ test_expect_success 'OPT_CALLBACK() and callback errors work' ' 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' ' @@ -236,7 +263,76 @@ test_expect_success 'OPT_BIT() and OPT_SET_INT() work' ' test_cmp expect output ' -# --or4 -# --no-or4 +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 index b177174ef5..89282ccf7a 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -8,7 +8,9 @@ auml=`printf '\xc3\xa4'` aumlcdiar=`printf '\x61\xcc\x88'` case_insensitive= -test_expect_success 'see if we expect ' ' +unibad= +no_symlinks= +test_expect_success 'see what we expect' ' test_case=test_expect_success test_unicode=test_expect_success @@ -19,7 +21,6 @@ test_expect_success 'see if we expect ' ' then test_case=test_expect_failure case_insensitive=t - say "will test on a case insensitive filesystem" fi && rm -fr junk && mkdir junk && @@ -27,13 +28,26 @@ test_expect_success 'see if we expect ' ' case "$(cd junk && echo *)" in "$aumlcdiar") test_unicode=test_expect_failure - say "will test on a unicode corrupting filesystem" + unibad=t ;; *) ;; esac && - rm -fr junk + 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" ' @@ -48,6 +62,21 @@ test_expect_success "detection of case insensitive filesystem during repo init" ' 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 && @@ -85,7 +114,7 @@ $test_case 'add (with different case)' ' rm camelcase && echo 1 >CamelCase && git add CamelCase && - test $(git-ls-files | grep -i camelcase | wc -l) = 1 + test $(git ls-files | grep -i camelcase | wc -l) = 1 ' 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 index 6e7501f352..53cf1f8dc4 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -7,40 +7,91 @@ test_description='Test various path utilities' . ./test-lib.sh -norm_abs() { - test_expect_success "normalize absolute" \ - "test \$(test-path-utils normalize_absolute_path '$1') = '$2'" +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() { - test_expect_success "longest ancestor" \ - "test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'" + # 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'" } -norm_abs "" / -norm_abs / / -norm_abs // / -norm_abs /// / -norm_abs /. / -norm_abs /./ / -norm_abs /./.. / -norm_abs /../. / -norm_abs /./../.// / -norm_abs /dir/.. / -norm_abs /dir/sub/../.. / -norm_abs /dir /dir -norm_abs /dir// /dir -norm_abs /./dir /dir -norm_abs /dir/. /dir -norm_abs /dir///./ /dir -norm_abs /dir//sub/.. /dir -norm_abs /dir/sub/../ /dir -norm_abs //dir/sub/../. /dir -norm_abs /dir/s1/../s2/ /dir/s2 -norm_abs /d1/s1///s2/..//../s3/ /d1/s3 -norm_abs /d1/s1//../s2/../../d2 /d2 -norm_abs /d1/.../d2 /d1/.../d2 -norm_abs /d1/..././../d2 /d1/d2 +# 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 @@ -79,9 +130,13 @@ 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 +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 807fb83af8..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,9 +126,6 @@ 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 && test_cmp expected current diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 4b44e131b2..6327d205cb 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -5,7 +5,7 @@ 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 @@ -26,8 +26,6 @@ read_tree_twoway () { 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;' \ @@ -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 @@ -300,7 +298,7 @@ test_expect_success \ 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 && @@ -341,4 +339,55 @@ test_expect_success \ 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_done diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh index aa9dd580a6..0241329a08 100755 --- a/t/t1002-read-tree-m-u-2way.sh +++ b/t/t1002-read-tree-m-u-2way.sh @@ -10,10 +10,10 @@ 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" test_cmp expected current @@ -75,7 +75,7 @@ test_expect_success \ 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 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 && @@ -94,7 +94,7 @@ test_expect_success \ 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 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 && @@ -206,7 +206,7 @@ test_expect_success \ 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 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 && @@ -227,7 +227,7 @@ test_expect_success \ 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 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 && diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh index 570d3729bd..f19b4a2a4a 100755 --- a/t/t1004-read-tree-m-u-wf.sh +++ b/t/t1004-read-tree-m-u-wf.sh @@ -157,7 +157,7 @@ test_expect_success '3-way not overwriting local changes (their side)' ' ' -test_expect_success 'funny symlink in work tree' ' +test_expect_success SYMLINKS 'funny symlink in work tree' ' git reset --hard && git checkout -b sym-b side-b && @@ -177,7 +177,7 @@ test_expect_success 'funny symlink in work tree' ' ' -test_expect_success 'funny symlink in work tree, un-unlink-able' ' +test_expect_success SYMLINKS 'funny symlink in work tree, un-unlink-able' ' rm -fr a b && git reset --hard && @@ -189,7 +189,7 @@ test_expect_success 'funny symlink in work tree, un-unlink-able' ' ' # clean-up from the above test -chmod a+w a +chmod a+w a 2>/dev/null rm -fr a b test_expect_success 'D/F setup' ' diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh index b0d31f5a9b..849911683a 100755 --- a/t/t1005-read-tree-reset.sh +++ b/t/t1005-read-tree-reset.sh @@ -27,4 +27,64 @@ test_expect_success 'reset should work' ' 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/t1007-hash-object.sh b/t/t1007-hash-object.sh index 1ec0535138..fd98e445bf 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description="git-hash-object" +test_description="git hash-object" . ./test-lib.sh @@ -49,16 +49,28 @@ setup_repo # Argument checking test_expect_success "multiple '--stdin's are rejected" ' - test_must_fail git hash-object --stdin --stdin < example + echo example | test_must_fail git hash-object --stdin --stdin ' test_expect_success "Can't use --stdin and --stdin-paths together" ' - test_must_fail git hash-object --stdin --stdin-paths && - test_must_fail git hash-object --stdin-paths --stdin + 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" ' - test_must_fail git hash-object --stdin-paths hello < example + 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 --stdin-paths with --no-filters" ' + echo example | test_must_fail git hash-object --stdin-paths --no-filters +' + +test_expect_success "Can't use --path with --no-filters" ' + test_must_fail git hash-object --no-filters --path=foo ' # Behavior @@ -93,6 +105,42 @@ test_expect_success 'git hash-object --stdin file1 <file0 first operates on file 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 +' + pop_repo for args in "-w --stdin" "--stdin -w"; do 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..9956e3ad62 --- /dev/null +++ b/t/t1010-mktree.sh @@ -0,0 +1,71 @@ +#!/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_failure 'mktree reads ls-tree -r output (1)' ' + git mktree <all >actual && + test_cmp tree actual +' + +test_expect_failure 'mktree reads ls-tree -r output (2)' ' + git mktree <all.withsub >actual && + test_cmp tree.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 fc386ba033..210e594f6f 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -126,7 +126,7 @@ test_expect_success 'no file/rev ambiguity check inside a bare repo' ' cd foo.git && git show -s HEAD ' -test_expect_success 'detection should not be fooled by a symlink' ' +test_expect_success SYMLINKS 'detection should not be fooled by a symlink' ' cd "$HERE" && rm -fr foo.git && git clone -s .git another && diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index 7f7fc36734..c4414ff576 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -40,6 +40,6 @@ test_expect_success \ 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 09a8199335..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,39 +83,47 @@ 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_success 'git resolve now fails' ' test_must_fail git merge -m "Merge work in mybranch" mybranch ' @@ -112,52 +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] Merge work in mybranch ++* [master^2] Some work. ++* [master^] Some fun. +EOF + +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] Merged "mybranch" changes. +* [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 +' + +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 -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 ls-files --unmerged' ' + git ls-files --unmerged > ls-files-unmerged.output && + test_cmp ls-files-unmerged.expect ls-files-unmerged.output +' -# TODO: test git fetch +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_success '-> only packed objects' ' - ! find -type f .git/objects/[0-9a-f][0-9a-f] + 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 64567fb94d..f11f98c3ce 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -118,7 +118,14 @@ 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' @@ -336,10 +343,10 @@ test_expect_success 'get bool variable with empty value' \ 'git config --bool emptyvalue.variable > output && cmp output expect' -git config > output 2>&1 - -test_expect_success 'no arguments, but no crash' \ - "test $? = 129 && grep usage output" +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] @@ -373,7 +380,7 @@ 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)' \ - 'git config --file non-existing-config -l; test $? != 0' + 'test_must_fail git config --file non-existing-config -l' cat > other-config << EOF [ein] @@ -391,6 +398,17 @@ test_expect_success 'alternative GIT_CONFIG' 'cmp output expect' 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 @@ -453,6 +471,28 @@ EOF 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 @@ -654,6 +694,34 @@ test_expect_success 'set --bool-or-int' ' 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' + +cat >expect <<EOF +$HOME/ +/dev/null +foo~ +EOF + +test_expect_success '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 +' + +rm .git/config + git config quote.leading " test" git config quote.ending "test " git config quote.semicolon "test;test" @@ -726,7 +794,12 @@ echo >>result test_expect_success '--null --get-regexp' 'cmp result expect' -test_expect_success 'symlinked configuration' ' +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 && @@ -741,4 +814,14 @@ test_expect_success 'symlinked configuration' ' ' +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_done diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index dc85e8b60a..de42d21c92 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -7,6 +7,9 @@ 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 && ( @@ -17,9 +20,13 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' ' test $ret != "0" ' +modebits () { + ls -l "$1" | sed -e 's|^\(..........\).*|\1|' +} + for u in 002 022 do - test_expect_success "shared=1 does not clear bits preset by umask $u" ' + test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" ' mkdir sub && ( cd sub && umask $u && @@ -47,7 +54,7 @@ test_expect_success 'shared=all' ' test 2 = $(git config core.sharedrepository) ' -test_expect_success 'update-server-info honors core.sharedRepository' ' +test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' ' : > a1 && git add a1 && test_tick && @@ -78,12 +85,11 @@ do git config core.sharedrepository "$u" && umask 0277 && - test_expect_success "shared = $u ($y) ro" ' + test_expect_success POSIXPERM "shared = $u ($y) ro" ' rm -f .git/info/refs && git update-server-info && - actual="$(ls -l .git/info/refs)" && - actual=${actual%% *} && + actual="$(modebits .git/info/refs)" && test "x$actual" = "x-$y" || { ls -lt .git/info false @@ -91,12 +97,11 @@ do ' umask 077 && - test_expect_success "shared = $u ($x) rw" ' + test_expect_success POSIXPERM "shared = $u ($x) rw" ' rm -f .git/info/refs && git update-server-info && - actual="$(ls -l .git/info/refs)" && - actual=${actual%% *} && + actual="$(modebits .git/info/refs)" && test "x$actual" = "x-$x" || { ls -lt .git/info false @@ -106,7 +111,7 @@ do done -test_expect_success 'git reflog expire honors core.sharedRepository' ' +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)" && @@ -121,4 +126,45 @@ test_expect_success 'git reflog expire honors core.sharedRepository' ' 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/t1303-wacky-config.sh b/t/t1303-wacky-config.sh index f98f4c5179..080117c6bc 100755 --- a/t/t1303-wacky-config.sh +++ b/t/t1303-wacky-config.sh @@ -10,7 +10,7 @@ setup() { check() { echo "$2" >expected - git config --get "$1" >actual + git config --get "$1" >actual 2>&1 test_cmp actual expected } @@ -35,9 +35,16 @@ test_expect_success 'add key in different section' ' ' SECTION="test.q\"s\\sq'sp e.key" -test_expect_success 'make sure git-config escapes section names properly' ' +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/t1400-update-ref.sh b/t/t1400-update-ref.sh index b31e4b1ac6..54ba3df95f 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -75,6 +75,24 @@ test_expect_success "delete $m (by HEAD)" ' ' rm -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 " @@ -119,7 +137,7 @@ $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 \ @@ -150,7 +168,7 @@ $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 @@ -228,21 +246,21 @@ test_expect_success \ 'echo TEST >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 && + 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 && + 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 && + 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 && + GIT_COMMITTER_DATE="2005-05-26 23:45" git commit -F M && h_MERGED=$(git rev-parse --verify HEAD) && rm -f M' @@ -253,8 +271,8 @@ $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 \ 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..eb45afb018 --- /dev/null +++ b/t/t1402-check-ref-format.sh @@ -0,0 +1,61 @@ +#!/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' + +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 73f830db23..80af6b9b7e 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` && @@ -188,16 +186,30 @@ test_expect_success 'delete' ' test_tick && git commit -m tiger C && - test 5 = $(git reflog | wc -l) && + 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 4 = $(wc -l < 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 3 = $(wc -l < output) && + test $(($master_entry_count - 1)) = $(wc -l < output) && ! grep dragon < output ' diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh new file mode 100755 index 0000000000..c18ed8edf9 --- /dev/null +++ b/t/t1411-reflog-show.sh @@ -0,0 +1,67 @@ +#!/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 +' + +test_done diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh new file mode 100755 index 0000000000..49cae3ed52 --- /dev/null +++ b/t/t1450-fsck.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='git fsck random collection of tests' + +. ./test-lib.sh + +test_expect_success setup ' + test_commit A fileA one && + 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 + ) +' + +# 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 +' + +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 index 85da4caa7e..48ee07779d 100755 --- a/t/t1500-rev-parse.sh +++ b/t/t1500-rev-parse.sh @@ -26,21 +26,28 @@ test_rev_parse() { "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 +# label is-bare is-inside-git is-inside-work prefix git-dir + +ROOT=$(pwd) -test_rev_parse toplevel false false true '' +test_rev_parse toplevel false false true '' .git cd .git || exit 1 -test_rev_parse .git/ false true false '' +test_rev_parse .git/ false true false '' . cd objects || exit 1 -test_rev_parse .git/objects/ false true false '' +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/ +test_rev_parse subdirectory false false true sub/dir/ "$ROOT/.git" cd ../.. || exit 1 git config core.bare true diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index 2ee88d8a06..9df301211c 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -28,6 +28,7 @@ test_rev_parse() { [ $# -eq 0 ] && return } +EMPTY_TREE=$(git write-tree) mkdir -p work/sub/dir || exit 1 mv .git repo.git || exit 1 @@ -106,12 +107,92 @@ test_expect_success 'repo finds its work tree from work tree, too' ' ' test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' ' - cd repo.git/work/sub/dir && + (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 + 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 index 997002d4c4..e504058062 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -20,8 +20,7 @@ Extras EOF -test_expect_success 'test --parseopt help output' ' - git rev-parse --parseopt -- -h 2> output.err <<EOF +cat > optionspec << EOF some-command [options] <args>... some-command does foo and bar! @@ -37,7 +36,47 @@ 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 2> output.err < optionspec test_cmp expect.err output.err ' +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 +' + test_done diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh index 95244c9bcf..cc65394947 100755 --- a/t/t1503-rev-parse-verify.sh +++ b/t/t1503-rev-parse-verify.sh @@ -23,7 +23,7 @@ add_line_into_file() fi test_tick - git-commit --quiet -m "$MSG" $_file + git commit --quiet -m "$MSG" $_file } HASH1= diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh index 91b704a3a4..df5ad8c686 100755 --- a/t/t1504-ceiling-dirs.sh +++ b/t/t1504-ceiling-dirs.sh @@ -13,7 +13,7 @@ test_fail() { "git rev-parse --show-prefix" } -TRASH_ROOT="$(pwd)" +TRASH_ROOT="$PWD" ROOT_PARENT=$(dirname "$TRASH_ROOT") @@ -93,13 +93,13 @@ GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi" test_prefix subdir_ceil_at_subdi_slash "sub/dir/" -GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub" +GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub" test_fail second_of_two -GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar" +GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:/bar" test_fail first_of_two -GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar" +GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub:/bar" test_fail second_of_three 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/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh index f7e1a735ec..de3edb5d57 100755 --- a/t/t2000-checkout-cache-clash.sh +++ b/t/t2000-checkout-cache-clash.sh @@ -48,4 +48,13 @@ test_expect_success \ 'git checkout-index conflicting paths.' \ 'test -f path0 && test -d path1 && test -f path1/file1' +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 ef007532b1..98aa73e823 100755 --- a/t/t2001-checkout-cache-clash.sh +++ b/t/t2001-checkout-cache-clash.sh @@ -59,10 +59,10 @@ test_expect_success \ 'git read-tree -m $tree1 && git checkout-index -f -a' test_debug 'show_files $tree1' -ln -s path0 path1 -test_expect_success \ +test_expect_success SYMLINKS \ 'git update-index --add a symlink.' \ - 'git update-index --add path1' + 'ln -s path0 path1 && + git update-index --add path1' test_expect_success \ 'writing tree out with git write-tree' \ 'tree3=$(git write-tree)' diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh index 71894b3743..02a4fc5d36 100755 --- a/t/t2003-checkout-cache-mkdir.sh +++ b/t/t2003-checkout-cache-mkdir.sh @@ -19,7 +19,7 @@ test_expect_success \ echo rezrov >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 && @@ -59,7 +59,7 @@ test_expect_success \ 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 && @@ -71,7 +71,7 @@ test_expect_success \ 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 && @@ -82,7 +82,7 @@ test_expect_success \ 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 && diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index 39133b8c7a..36cca14d95 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -194,7 +194,7 @@ 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 && diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh index a84c5a6af9..9fa5610474 100755 --- a/t/t2005-checkout-index-symlinks.sh +++ b/t/t2005-checkout-index-symlinks.sh @@ -13,7 +13,7 @@ file if core.symlinks is false.' test_expect_success \ 'preparation' ' git config core.symlinks false && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && +l=$(printf file | git hash-object -t blob -w --stdin) && echo "120000 $l symlink" | git update-index --index-info' test_expect_success \ @@ -23,6 +23,6 @@ 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 index 0526fce163..20f33436d0 100755 --- a/t/t2007-checkout-symlink.sh +++ b/t/t2007-checkout-symlink.sh @@ -6,6 +6,12 @@ test_description='git checkout to switch between branches with symlink<->dir' . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + say "symbolic links not supported - skipping tests" + test_done +fi + test_expect_success setup ' mkdir frotz && 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..4d1c2e9e09 --- /dev/null +++ b/t/t2016-checkout-patch.sh @@ -0,0 +1,107 @@ +#!/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 +' + +# 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/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 index 88f268b9d7..b7131d8c08 100755 --- a/t/t2050-git-dir-relative.sh +++ b/t/t2050-git-dir-relative.sh @@ -26,8 +26,8 @@ chmod +x .git/hooks/post-commit' test_expect_success 'post-commit hook used ordinarily' ' echo initial >top && -git-add top -git-commit -m initial && +git add top +git commit -m initial && test -r "${COMMIT_FILE}" ' diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh index 6ef2dcfd8a..2df3fdde8b 100755 --- a/t/t2100-update-cache-badpath.sh +++ b/t/t2100-update-cache-badpath.sh @@ -26,7 +26,12 @@ 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 @@ -38,7 +43,12 @@ 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 diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh index 59b560bfdf..648184fd98 100755 --- a/t/t2101-update-index-reupdate.sh +++ b/t/t2101-update-index-reupdate.sh @@ -40,7 +40,7 @@ test_expect_success '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 diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh index 19d0894d26..1ed44ee503 100755 --- a/t/t2102-update-index-symlinks.sh +++ b/t/t2102-update-index-symlinks.sh @@ -13,12 +13,12 @@ even if a plain file is in the working tree if core.symlinks is false.' test_expect_success \ 'preparation' ' git config core.symlinks false && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && +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 && +printf new-file > symlink && git update-index symlink' test_expect_success \ 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/t2200-add-update.sh b/t/t2200-add-update.sh index f57a6e077c..912075063b 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -12,7 +12,7 @@ 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.' +without contents changes, and other conditions' . ./test-lib.sh @@ -26,7 +26,7 @@ test_expect_success setup ' echo initial >dir2/sub3 && git add check dir1 dir2 top foo && test_tick - git-commit -m initial && + git commit -m initial && echo changed >check && echo changed >top && @@ -40,20 +40,20 @@ test_expect_success update ' ' test_expect_success 'update noticed a removal' ' - test "$(git-ls-files dir1/sub1)" = "" + test "$(git ls-files dir1/sub1)" = "" ' test_expect_success 'update touched correct path' ' - test "$(git-diff-files --name-status dir2/sub3)" = "" + 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 "$(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 "$(git ls-files dir2/other)" = "" ' test_expect_success 'cache tree has not been corrupted' ' @@ -80,7 +80,7 @@ test_expect_success 'change gets noticed' ' ' -test_expect_success 'replace a file with a symlink' ' +test_expect_success SYMLINKS 'replace a file with a symlink' ' rm foo && ln -s top foo && @@ -128,4 +128,52 @@ test_expect_success 'add -n -u should not add but just report' ' ' +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_done diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh index d24c7d9e5f..2e8f702452 100755 --- a/t/t2201-add-update-typechange.sh +++ b/t/t2201-add-update-typechange.sh @@ -11,7 +11,13 @@ test_expect_success setup ' _empty=$(git hash-object --stdin <xyzzy) && >yomin && >caskly && - ln -s frotz nitfol && + 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 && @@ -29,7 +35,11 @@ test_expect_success modify ' >nitfol && # rezrov/bozbar disappears rm -fr rezrov && - ln -s xyzzy 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 && @@ -71,7 +81,7 @@ test_expect_success modify ' s/blob/000000/ } / nitfol/{ - s/ nitfol/ $_z40 T&/ + s/ nitfol/ $_z40 $T_letter&/ s/blob/100644/ } / rezrov.bozbar/{ 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/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 bc0a351392..86291e8399 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -13,12 +13,18 @@ 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 +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 @@ -28,6 +34,7 @@ git update-index --add path3-junk path3/file3 cat >expected1 <<EOF expected1 expected2 +expected3 output path0 path1 @@ -35,6 +42,8 @@ path2-junk path2/file2 EOF sed -e 's|path2/file2|path2/|' <expected1 >expected2 +cat <expected2 >expected3 +echo path4/ >>expected2 test_expect_success \ 'git ls-files --others to show output.' \ @@ -42,7 +51,7 @@ test_expect_success \ test_expect_success \ 'git ls-files --others should pick up symlinks.' \ - 'diff output expected1' + 'test_cmp expected1 output' test_expect_success \ 'git ls-files --others --directory to show output.' \ @@ -51,6 +60,14 @@ test_expect_success \ test_expect_success \ 'git ls-files --others --directory should not get confused.' \ - 'diff output expected2' + 'test_cmp expected2 output' + +test_expect_success \ + 'git ls-files --others --directory --no-empty-directory to show output.' \ + 'git ls-files --others --directory --no-empty-directory >output' + +test_expect_success \ + '--no-empty-directory hides empty directory' \ + '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 1caeacafa7..6d2f2b67ee 100755 --- a/t/t3001-ls-files-others-exclude.sh +++ b/t/t3001-ls-files-others-exclude.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,6 +64,8 @@ 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 \ @@ -79,9 +87,30 @@ test_expect_success \ >output && test_cmp expect output' -cat > excludes-file << EOF +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 && + 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 @@ -96,7 +125,7 @@ cat > expect << EOF # three/ EOF -test_expect_success 'git-status honours core.excludesfile' \ +test_expect_success 'git status honors core.excludesfile' \ 'test_cmp expect output' test_expect_success 'trailing slash in exclude allows directory match(1)' ' @@ -140,4 +169,49 @@ test_expect_success 'trailing slash in exclude forces directory match (2)' ' ' +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/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 ec14040637..95671c2053 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -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 @@ -52,8 +57,14 @@ test_expect_success \ 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 @@ -75,7 +86,7 @@ EOF test_expect_success \ 'validate git ls-files -k output.' \ - 'diff .output .expected' + 'test_cmp .expected .output' test_expect_success \ 'git ls-files -m to show modified files.' \ @@ -91,6 +102,6 @@ EOF test_expect_success \ 'validate git ls-files -m output.' \ - 'diff .output .expected' + '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 af8c4121ab..f4066cbc09 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -13,7 +13,7 @@ line. touch foo bar git update-index --add foo bar -git-commit -m "add foo bar" +git commit -m "add foo bar" test_expect_success \ 'git ls-files --error-unmatch should fail with unmatched path.' \ diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index aff360303a..9929f82021 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -241,7 +241,7 @@ test_expect_success 'merge-recursive simple' ' rm -fr [abcd] && git checkout -f "$c2" && - git-merge-recursive "$c0" -- "$c2" "$c1" + git merge-recursive "$c0" -- "$c2" "$c1" status=$? case "$status" in 1) @@ -269,12 +269,28 @@ test_expect_success 'merge-recursive result' ' ' +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" + git merge-recursive "$c0" -- "$c1" "$c5" status=$? case "$status" in 1) @@ -306,7 +322,7 @@ test_expect_success 'merge-recursive d/f simple' ' git reset --hard && git checkout -f "$c1" && - git-merge-recursive "$c0" -- "$c1" "$c3" + git merge-recursive "$c0" -- "$c1" "$c3" ' test_expect_success 'merge-recursive result' ' @@ -328,7 +344,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c1" && - git-merge-recursive "$c0" -- "$c1" "$c4" + git merge-recursive "$c0" -- "$c1" "$c4" status=$? case "$status" in 1) @@ -362,7 +378,7 @@ test_expect_success 'merge-recursive d/f conflict the other way' ' git reset --hard && git checkout -f "$c4" && - git-merge-recursive "$c0" -- "$c4" "$c1" + git merge-recursive "$c0" -- "$c4" "$c1" status=$? case "$status" in 1) @@ -396,7 +412,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c1" && - git-merge-recursive "$c0" -- "$c1" "$c6" + git merge-recursive "$c0" -- "$c1" "$c6" status=$? case "$status" in 1) @@ -430,7 +446,7 @@ test_expect_success 'merge-recursive d/f conflict' ' git reset --hard && git checkout -f "$c6" && - git-merge-recursive "$c0" -- "$c6" "$c1" + git merge-recursive "$c0" -- "$c6" "$c1" status=$? case "$status" in 1) @@ -524,4 +540,15 @@ test_expect_success 'reset and bind merge' ' ' +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_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/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index 6e6a2542a2..eee0d344d2 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -22,17 +22,27 @@ 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` && 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 test_cmp expected check @@ -41,7 +51,7 @@ test_output () { test_expect_success \ 'ls-tree plain' \ 'git ls-tree $tree >current && - cat >expected <<\EOF && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -51,7 +61,7 @@ EOF test_expect_success \ 'ls-tree recursive' \ 'git ls-tree -r $tree >current && - cat >expected <<\EOF && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 100644 blob X path2/baz/b @@ -63,7 +73,7 @@ EOF test_expect_success \ 'ls-tree recursive with -t' \ 'git ls-tree -r -t $tree >current && - cat >expected <<\EOF && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 040000 tree X path2 @@ -77,7 +87,7 @@ EOF test_expect_success \ 'ls-tree recursive with -d' \ 'git ls-tree -r -d $tree >current && - cat >expected <<\EOF && + make_expected <<\EOF && 040000 tree X path2 040000 tree X path2/baz EOF @@ -86,7 +96,7 @@ EOF test_expect_success \ 'ls-tree filtered with path' \ 'git ls-tree $tree path >current && - cat >expected <<\EOF && + make_expected <<\EOF && EOF test_output' @@ -96,7 +106,7 @@ EOF test_expect_success \ 'ls-tree filtered with path1 path0' \ 'git ls-tree $tree path1 path0 >current && - cat >expected <<\EOF && + make_expected <<\EOF && 100644 blob X path0 120000 blob X path1 EOF @@ -105,7 +115,7 @@ EOF test_expect_success \ 'ls-tree filtered with path0/' \ 'git ls-tree $tree path0/ >current && - cat >expected <<\EOF && + make_expected <<\EOF && EOF test_output' @@ -114,7 +124,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2' \ 'git ls-tree $tree path2 >current && - cat >expected <<\EOF && + make_expected <<\EOF && 040000 tree X path2 EOF test_output' @@ -123,7 +133,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2/' \ 'git ls-tree $tree path2/ >current && - cat >expected <<\EOF && + make_expected <<\EOF && 040000 tree X path2/baz 120000 blob X path2/bazbo 100644 blob X path2/foo @@ -135,7 +145,7 @@ EOF test_expect_success \ 'ls-tree filtered with path2/baz' \ 'git ls-tree $tree path2/baz >current && - cat >expected <<\EOF && + make_expected <<\EOF && 040000 tree X path2/baz EOF test_output' @@ -143,14 +153,14 @@ EOF test_expect_success \ 'ls-tree filtered with path2/bak' \ 'git ls-tree $tree path2/bak >current && - cat >expected <<\EOF && + 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 && + 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 4dd7d12bac..06654c6f82 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -39,8 +39,6 @@ test_expect_success \ 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 test_cmp expected check @@ -135,4 +133,95 @@ test_expect_success \ 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 7a83fbfe4f..e0b760513c 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -14,10 +14,10 @@ test_expect_success \ 'prepare a trivial repository' \ 'echo Hello > A && git update-index --add A && - git-commit -m "Initial commit." && + git commit -m "Initial commit." && echo World >> A && git update-index --add A && - git-commit -m "Second commit." && + git commit -m "Second commit." && HEAD=$(git rev-parse --verify HEAD)' test_expect_success \ @@ -112,7 +112,16 @@ test_expect_success 'config information was renamed, too' \ "test $(git config branch.s.dummy) = Hello && test_must_fail git config branch.s/s/dummy" -test_expect_success \ +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 && @@ -123,7 +132,7 @@ test_expect_success \ 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 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' @@ -131,7 +140,7 @@ test_expect_success 'test tracking setup via --track' \ 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 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' @@ -139,7 +148,7 @@ test_expect_success 'test tracking setup (non-wildcard, matching)' \ 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 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' @@ -148,7 +157,7 @@ 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 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' @@ -157,7 +166,7 @@ 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 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 && @@ -173,7 +182,7 @@ test_expect_success 'no tracking without .fetch entries' \ 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 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' @@ -185,7 +194,8 @@ test_expect_success 'test deleting branch deletes branch config' \ test_expect_success 'test deleting branch without config' \ 'git branch my7 s && - test "$(git branch -d my7 2>&1)" = "Deleted branch my7."' + 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 && @@ -209,7 +219,7 @@ 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 && + 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' @@ -228,7 +238,7 @@ 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 show-ref -q refs/remotes/local/o || git fetch local) && git branch mybase && git branch --track myr1 mybase && test "$(git config branch.myr1.remote)" = . && @@ -240,7 +250,7 @@ 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 show-ref -q refs/remotes/local/o || git fetch local) && git branch mybase2 && git branch --track myr2 mybase && test "$(git config branch.myr2.remote)" = . && @@ -252,7 +262,7 @@ 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 show-ref -q refs/remotes/local/o || git fetch local) && git branch mybase3 && git branch --track myr3 mybase2 && test "$(git config branch.myr3.remote)" = . && @@ -264,7 +274,7 @@ 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 show-ref -q refs/remotes/local/o || git fetch local) && git branch mybase4 && git branch --track myr4 mybase2 && test "$(git config branch.myr4.remote)" = . && @@ -276,7 +286,7 @@ 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 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 && @@ -287,7 +297,7 @@ 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 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 && @@ -298,7 +308,7 @@ 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 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 && @@ -309,7 +319,7 @@ 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 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 && @@ -320,7 +330,7 @@ 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 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 && @@ -330,7 +340,7 @@ test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' ' 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 show-ref -q refs/remotes/local/o || git fetch local) && git branch mybase10 && git branch --track myr10 mybase2 && test "$(git config branch.myr10.remote)" = . && @@ -341,7 +351,7 @@ test_expect_success 'autosetuprebase unconfigured on a tracked local branch' ' 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 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 && @@ -351,7 +361,7 @@ test_expect_success 'autosetuprebase unconfigured on untracked local branch' ' 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 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 && @@ -362,7 +372,7 @@ 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 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 && @@ -373,7 +383,7 @@ 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 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 && @@ -384,7 +394,7 @@ 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 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 && @@ -395,7 +405,7 @@ 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 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 && @@ -406,7 +416,7 @@ 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 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 && @@ -417,7 +427,7 @@ 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 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 && @@ -428,7 +438,7 @@ 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 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 && @@ -439,7 +449,7 @@ 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 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 && @@ -458,4 +468,30 @@ test_expect_success 'detect misconfigured autosetuprebase (no value)' ' 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/t3202-show-branch-octopus.sh b/t/t3202-show-branch-octopus.sh index 7fe4a6ecb0..0a5d5e669f 100755 --- a/t/t3202-show-branch-octopus.sh +++ b/t/t3202-show-branch-octopus.sh @@ -56,4 +56,12 @@ test_expect_success 'show-branch with more than 8 branches' ' ' +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 c2dec1c632..413019acaf 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -17,7 +17,7 @@ test_expect_success \ 'prepare a trivial repository' \ 'echo Hello > A && git update-index --add A && - git-commit -m "Initial commit." && + git commit -m "Initial commit." && HEAD=$(git rev-parse --verify HEAD)' SHA1= @@ -96,8 +96,15 @@ test_expect_success \ 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 tag foo && git pack-refs --all --prune && git show-ref >all-of-them && git pack-refs && diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index 0574ef1f10..db46d53e82 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -21,7 +21,7 @@ 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" || { diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh new file mode 100755 index 0000000000..5d9604b815 --- /dev/null +++ b/t/t3301-notes.sh @@ -0,0 +1,209 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test commit notes' + +. ./test-lib.sh + +cat > fake_editor.sh << \EOF +echo "$MSG" > "$1" +echo "$MSG" >& 2 +EOF +chmod a+x fake_editor.sh +VISUAL=./fake_editor.sh +export VISUAL + +test_expect_success 'cannot annotate non-existing HEAD' ' + (MSG=3 && export MSG && test_must_fail git notes edit) +' + +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 edit) && + (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF && + test_must_fail git notes show) +' + +test_expect_success 'refusing to edit in refs/heads/' ' + (MSG=1 GIT_NOTES_REF=refs/heads/bogus && + export MSG GIT_NOTES_REF && + test_must_fail git notes edit) +' + +test_expect_success 'refusing to edit 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 'create notes' ' + git config core.notesRef refs/notes/commits && + MSG=b1 git notes edit && + test ! -f .git/new-notes && + 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 edit +' + +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 -m and -F notes (setup)' ' + : > a4 && + git add a4 && + test_tick && + git commit -m 4th && + echo "xyzzy" > note5 && + git notes edit -m spam -F note5 -m "foo +bar +baz" +' + +whitespace=" " +cat > expect-m-and-F << EOF +commit 15023535574ded8b1a89052b32673f84cf9582b8 +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:16:13 2005 -0700 + + 4th + +Notes: + spam +$whitespace + xyzzy +$whitespace + foo + bar + baz +EOF + +printf "\n" >> expect-m-and-F +cat expect-multiline >> expect-m-and-F + +test_expect_success 'show -m and -F notes' ' + git log -3 > output && + test_cmp expect-m-and-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: + spam +$whitespace + xyzzy +$whitespace + foo + bar + baz +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 spam output +' + +test_expect_success 'git format-patch does not show notes' ' + git format-patch -1 --stdout >output && + ! grep spam output +' + +test_expect_success 'git format-patch --show-notes does show notes' ' + git format-patch --show-notes -1 --stdout >output && + grep spam 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 spam output" + ' +done + +test_done diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh new file mode 100755 index 0000000000..ee84fc4884 --- /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" && { + say 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..edc4bc8841 --- /dev/null +++ b/t/t3303-notes-subtrees.sh @@ -0,0 +1,188 @@ +#!/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 4/36-fanout' 'test_sha1_based "s|^....|&/|"' +test_expect_success 'verify notes in 4/36-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_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 4/36-fanout and 2/38-fanout' 'test_same_notes "s|^..|&/|" "s|^....|&/|"' +test_expect_success 'verify same notes in 4/36-fanout and 2/38-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 4/36-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"' +test_expect_success 'verify same notes in 4/36-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 4/36-fanout concatenated with 2/38-fanout' 'test_concatenated_notes "s|^..|&/|" "s|^....|&/|"' +test_expect_success 'verify notes in 4/36-fanout concatenated with 2/38-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 4/36-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"' +test_expect_success 'verify notes in 4/36-fanout concatenated with 2/2/36-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..256687ffb5 --- /dev/null +++ b/t/t3304-notes-mixed.sh @@ -0,0 +1,172 @@ +#!/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 + +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 + +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 +' + +test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 91bb5e1d9e..4314ad2d66 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -3,9 +3,10 @@ # 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 @@ -14,17 +15,18 @@ export GIT_AUTHOR_EMAIL test_expect_success \ 'prepare repository with topic branches' \ - 'echo First > A && + 'git config core.logAllRefUpdates true && + echo First > A && git update-index --add A && - git-commit -m "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 commit -m "Add B." && git checkout -f master && echo Third >> A && git update-index A && - git-commit -m "Modify A." && + git commit -m "Modify A." && git checkout -b side my-topic-branch && echo Side >> C && git add C && @@ -40,13 +42,48 @@ test_expect_success \ 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_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 "<>")' +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 && @@ -78,10 +115,40 @@ test_expect_success 'rebase a single mode change' ' git checkout -b modechange HEAD^ && echo 1 > X && git add X && - chmod a+x A && + test_chmod +x A && test_tick && - git commit -m modechange A X && + 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 +' + +test_expect_success 'rebase -q is quiet' ' + rm B && + git checkout -b quiet topic && + git rebase -q master > output.out 2>&1 && + test ! -s output.out +' + +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_done diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh index 166ddb1447..aea6685984 100755 --- a/t/t3401-rebase-partial.sh +++ b/t/t3401-rebase-partial.sh @@ -15,29 +15,29 @@ test_expect_success \ 'prepare repository with topic branch' \ 'echo First > A && git update-index --add A && - git-commit -m "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 commit -m "Add B." && echo AnotherSecond > C && git update-index --add C && - git-commit -m "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 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 checkout -f my-topic-branch && git branch master-merge master && git branch my-topic-branch-merge my-topic-branch ' @@ -49,13 +49,13 @@ test_debug \ ' test_expect_success \ - 'rebase topic branch against new master and check git-am did not get halted' \ - 'git-rebase master && test ! -d .git/rebase-apply' + '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 && + 'git checkout -f my-topic-branch-merge && + git rebase --merge master-merge && test ! -d .git/rebase-merge' test_done diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 0d33c71daa..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 ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ffe3dd97b7..4e3513709e 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -10,91 +10,51 @@ that the result still makes sense. ' . ./test-lib.sh -# set up two branches like this: +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +# Set up the repository like this: # -# A - B - C - D - E +# one - two - three - four (conflict-branch) +# / +# A - B - C - D - E (master) +# | \ +# | F - G - H (branch1) +# | \ +# \ I (branch2) # \ -# F - G - H -# \ -# I +# J - K - L - M (no-conflict-branch) # -# where B, D and G touch the same file. +# where A, B, D and G all touch file1, and one, two, three, four all +# touch file "conflict". test_expect_success 'setup' ' - : > file1 && - git add file1 && - test_tick && - git commit -m A && - git tag A && - echo 1 > file1 && - test_tick && - git commit -m B file1 && - : > file2 && - git add file2 && - test_tick && - git commit -m C && - echo 2 > file1 && - test_tick && - git commit -m D file1 && - : > file3 && - git add file3 && - test_tick && - git commit -m E && + 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 && - : > file4 && - git add file4 && - test_tick && - git commit -m F && - git tag F && - echo 3 > file1 && - test_tick && - git commit -m G file1 && - : > file5 && - git add file5 && - test_tick && - git commit -m H && + test_commit F file4 && + test_commit G file1 && + test_commit H file5 && git checkout -b branch2 F && - : > file6 && - git add file6 && - test_tick && - git commit -m I && - git tag I -' - -echo "#!$SHELL_PATH" >fake-editor.sh -cat >> fake-editor.sh <<\EOF -case "$1" in -*/COMMIT_EDITMSG) - 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" -cat "$1".tmp -action=pick -for line in $FAKE_LINES; do - case $line in - squash|edit) - action="$line";; - *) - echo sed -n "${line}s/^pick/$action/p" - sed -n "${line}p" < "$1".tmp - sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1" - action=pick;; - esac -done -EOF - -test_set_editor "$(pwd)/fake-editor.sh" -chmod a+x fake-editor.sh + 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 +' 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) @@ -140,19 +100,20 @@ test_expect_success 'exchange two commits' ' cat > expect << EOF diff --git a/file1 b/file1 -index e69de29..00750ed 100644 +index f70f10e..fd79235 100644 --- a/file1 +++ b/file1 -@@ -0,0 +1 @@ -+3 +@@ -1 +1 @@ +-A ++G EOF cat > expect2 << EOF -<<<<<<< HEAD:file1 -2 +<<<<<<< HEAD +D ======= -3 ->>>>>>> b7ca976... G:file1 +G +>>>>>>> 51047de... G EOF test_expect_success 'stop on conflicting pick' ' @@ -161,7 +122,7 @@ test_expect_success 'stop on conflicting pick' ' 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 | + 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) @@ -190,7 +151,8 @@ test_expect_success 'squash' ' test_tick && GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 && echo "******************************" && - FAKE_LINES="1 squash 2" git rebase -i --onto master HEAD~2 && + 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) ' @@ -202,6 +164,9 @@ test_expect_success 'retain authorship when squashing' ' 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) ' @@ -235,6 +200,9 @@ test_expect_success 'preserve merges with -p' ' 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^^^) && @@ -244,6 +212,18 @@ test_expect_success 'preserve merges with -p' ' 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^ && @@ -267,30 +247,113 @@ test_expect_success 'verbose flag is heeded, even after --continue' ' 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' ' - for n in one two three four - do - echo $n >> file$n && - git add file$n && - git commit -m $n - done && + git checkout -b squash-works no-conflict-branch && one=$(git rev-parse HEAD~3) && - FAKE_LINES="1 squash 3 2" git rebase -i 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' ' - for n in one two three four - do - echo $n >> conflict && - git add conflict && - git commit -m $n - done && + git checkout -b interrupted-squash conflict-branch && one=$(git rev-parse HEAD~3) && ( FAKE_LINES="1 squash 3 2" && @@ -307,12 +370,7 @@ test_expect_success 'interrupted squash works as expected' ' ' test_expect_success 'interrupted squash works as expected (case 2)' ' - for n in one two three four - do - echo $n >> conflict && - git add conflict && - git commit -m $n - done && + git checkout -b interrupted-squash2 conflict-branch && one=$(git rev-parse HEAD~3) && ( FAKE_LINES="3 squash 1 2" && @@ -355,6 +413,38 @@ test_expect_success '--continue tries to commit, even for "edit"' ' 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) && @@ -401,4 +491,66 @@ test_expect_success 'rebase with a file named HEAD in worktree' ' ' +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_done diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index 5391080943..85fc7c4af8 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -22,7 +22,8 @@ test_expect_success setup ' git checkout topic && quick_one A && quick_one B && - quick_one Z + quick_one Z && + git tag start ' @@ -41,4 +42,24 @@ test_expect_success 'rebase -m' ' ' +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 index 4de550a632..2999e78937 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -52,7 +52,7 @@ testrebase() { test -d "$dotest" && test_must_fail git rebase --skip && test $(git rev-parse HEAD) = $(git rev-parse master) && - git-rebase --abort && + git rebase --abort && test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) && test ! -d "$dotest" ' diff --git a/t/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh index e12cd578e8..2062b858bb 100755 --- a/t/t3408-rebase-multi-line.sh +++ b/t/t3408-rebase-multi-line.sh @@ -32,8 +32,8 @@ 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 && + 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 ' 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/t3500-cherry.sh b/t/t3500-cherry.sh index 4911c48378..dadbbc2a9f 100755 --- a/t/t3500-cherry.sh +++ b/t/t3500-cherry.sh @@ -17,25 +17,25 @@ 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 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 commit -m "Add B." && sleep 2 && echo AnotherSecond > C && git update-index --add C && - git-commit -m "Add C." && + 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 commit -m "Modify A." && expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* + .*" ' diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 6da212825a..7f858151d4 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -45,6 +45,7 @@ test_expect_success 'cherry-pick after renaming branch' ' git checkout rename2 && git cherry-pick added && + test $(git rev-parse HEAD^) = $(git rev-parse rename2) && test -f opos && grep "Add extra line at the end" opos @@ -54,6 +55,7 @@ test_expect_success 'revert after renaming branch' ' git checkout rename1 && git revert added && + test $(git rev-parse HEAD^) = $(git rev-parse rename1) && test -f spoo && ! grep "Add extra line at the end" spoo @@ -64,7 +66,7 @@ test_expect_success 'revert forbidden on dirty working tree' ' echo content >extra_file && git add extra_file && test_must_fail git revert HEAD 2>errors && - grep "Dirty index" errors + grep "Your local changes would be overwritten by " errors ' 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/t3600-rm.sh b/t/t3600-rm.sh index 79c06adf1f..0aaf0ad84b 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -12,30 +12,37 @@ 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 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 # arranged. -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-file +chmod a-w . +rm -f test-file 2>/dev/null +if test -f test-file +then + test_set_prereq RO_DIR +else + say 'skipping removal failure test (perhaps running as root?)' +fi +chmod 775 . +rm -f test-file test_expect_success \ 'Pre-check that foo exists and is in index before git rm foo' \ @@ -100,20 +107,16 @@ test_expect_success \ 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \ 'git rm -- -q' -test "$test_tabs" = y && test_expect_success \ +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_success \ - 'Test that "git rm -f" fails if its rm fails' \ - 'test_must_fail 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' \ @@ -187,6 +190,19 @@ test_expect_success 'but with -f it should work.' ' 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' ' mkdir -p frotz && echo qfwfq >frotz/nitfol && @@ -219,14 +235,48 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' ' 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 + (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 7d123d17fc..85eb0fbf96 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -30,7 +30,7 @@ test_expect_success \ *) 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 && @@ -51,7 +51,7 @@ test_expect_success \ *) 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 && @@ -61,7 +61,7 @@ test_expect_success 'git add: filemode=0 should not get confused by symlink' ' esac ' -test_expect_success \ +test_expect_success SYMLINKS \ 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && ln -s xfoo2 xfoo3 && @@ -179,7 +179,7 @@ test_expect_success 'git add --refresh' ' test -z "`git diff-index HEAD -- foo`" ' -test_expect_success 'git add should fail atomically upon an unreadable file' ' +test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable file' ' git reset --hard && date >foo1 && date >foo2 && @@ -190,7 +190,7 @@ test_expect_success 'git add should fail atomically upon an unreadable file' ' rm -f foo2 -test_expect_success 'git add --ignore-errors' ' +test_expect_success POSIXPERM 'git add --ignore-errors' ' git reset --hard && date >foo1 && date >foo2 && @@ -201,7 +201,7 @@ test_expect_success 'git add --ignore-errors' ' rm -f foo2 -test_expect_success 'git add (add.ignore-errors)' ' +test_expect_success POSIXPERM 'git add (add.ignore-errors)' ' git config add.ignore-errors 1 && git reset --hard && date >foo1 && @@ -212,7 +212,7 @@ test_expect_success 'git add (add.ignore-errors)' ' ' rm -f foo2 -test_expect_success 'git add (add.ignore-errors = false)' ' +test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' ' git config add.ignore-errors 0 && git reset --hard && date >foo1 && @@ -221,5 +221,38 @@ test_expect_success 'git add (add.ignore-errors = false)' ' 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_done diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index e95663d8e6..b6eba6a839 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -3,6 +3,11 @@ test_description='add -i basic tests' . ./test-lib.sh +if ! test_have_prereq PERL; then + say 'skipping git add -i tests, perl not available' + test_done +fi + test_expect_success 'setup (initial)' ' echo content >file && git add file && @@ -133,12 +138,28 @@ test_expect_success 'real edit works' ' 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)' + say 'skipping filemode tests (filesystem does not properly support modes)' else + test_set_prereq FILEMODE +fi -test_expect_success 'patch does not affect mode' ' +test_expect_success FILEMODE 'patch does not affect mode' ' git reset --hard && echo content >>file && chmod +x file && @@ -147,7 +168,7 @@ test_expect_success 'patch does not affect mode' ' git diff file | grep "new mode" ' -test_expect_success 'stage mode but not hunk' ' +test_expect_success FILEMODE 'stage mode but not hunk' ' git reset --hard && echo content >>file && chmod +x file && @@ -156,7 +177,92 @@ test_expect_success 'stage mode but not hunk' ' git diff file | grep "+content" ' -fi + +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 c851db8ca9..6fb027ba57 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 @@ -14,7 +14,7 @@ test_description='git-mktag: tag object verify test' check_verify_failure () { expect="$2" test_expect_success "$1" ' - ( test_must_fail git-mktag <tag.sig 2>message ) && + ( test_must_fail git mktag <tag.sig 2>message ) && grep "$expect" message ' } @@ -24,7 +24,7 @@ check_verify_failure () { # for the tag. echo Hello >A git update-index --add A -git-commit -m "Initial commit" +git commit -m "Initial commit" head=$(git rev-parse --verify HEAD) ############################################################ @@ -222,7 +222,7 @@ EOF test_expect_success \ 'allow empty tag email' \ - 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message' + 'git mktag <tag.sig >.git/refs/tags/mytag 2>message' ############################################################ # 16. disallow spaces in tag email @@ -350,14 +350,14 @@ 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' ############################################################ # 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 883281dbd6..256c4c9701 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -9,16 +9,24 @@ test_description='commit and log output encodings' compare_with () { git show -s $1 | sed -e '1,/^$/d' -e 's/^ //' >current && - test_cmp current "$2" + 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) && + C=$(git commit-tree $T <"$TEST_DIRECTORY"/t3900/1-UTF-8.txt) && git update-ref HEAD $C && - git-tag C0 + git tag C0 ' test_expect_success 'no encoding header for base case' ' @@ -26,17 +34,17 @@ test_expect_success 'no encoding header for base case' ' 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 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") && @@ -53,17 +61,17 @@ test_expect_success 'config to remove customization' ' 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 @@ -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 + 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 + if test "$J" = ISO-2022-JP + then + ICONV=$J + else + ICONV= + fi git config i18n.logoutputencoding $J - for H in EUCJP ISO-2022-JP + 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 235f372832..31a5770b34 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -17,9 +17,9 @@ check_encoding () { 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 @@ -35,7 +35,7 @@ test_expect_success setup ' # 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,9 +55,9 @@ 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 && @@ -68,14 +68,14 @@ test_expect_success setup ' ' 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=20=F3=FA?=" out-l1 && - grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l2 && - grep "^From: =?ISO-8859-1?q?=C1=E9=ED=20=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)' ' @@ -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.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 ' @@ -149,7 +149,7 @@ test_expect_success 'cherry-pick(U/U)' ' 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^ && @@ -162,9 +162,9 @@ 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^ && @@ -178,8 +178,8 @@ 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.logoutputencoding ISO8859-1 && + . "$TEST_DIRECTORY"/t3901-utf8.txt && git reset --hard master && git cherry-pick side^ && @@ -193,9 +193,9 @@ 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^ && @@ -208,33 +208,33 @@ test_expect_success 'cherry-pick(L/U)' ' test_expect_success 'rebase --merge (U/U)' ' 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.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 index fe4fb5116a..29103f65dc 100755 --- a/t/t3902-quoted.sh +++ b/t/t3902-quoted.sh @@ -7,12 +7,6 @@ test_description='quoted output' . ./test-lib.sh -P1='pathname with HT' -: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || { - echo >&2 'Filesystem does not support HT in names' - test_done -} - FN='濱野' GN='ç´”' HT=' ' @@ -20,7 +14,7 @@ LF=' ' DQ='"' -echo foo > "Name and an${HT}HT" +echo foo 2>/dev/null > "Name and an${HT}HT" test -f "Name and an${HT}HT" || { # since FAT/NTFS does not allow tabs in filenames, skip this test say 'Your filesystem does not allow tabs in filenames, test skipped.' @@ -31,7 +25,7 @@ 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" + "With SP in it" "$FN/file" do eval "$1" done @@ -39,6 +33,7 @@ for_each_name () { test_expect_success setup ' + mkdir "$FN" && for_each_name "echo initial >\"\$name\"" git add . && git commit -q -m Initial && @@ -60,6 +55,7 @@ With SP in it "\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 @@ -73,6 +69,7 @@ With SP in it "濱野\nç´”" 濱野 ç´” "濱野\"ç´”" +濱野/file 濱野純 EOF @@ -103,6 +100,13 @@ test_expect_success 'check fully quoted output from diff-tree' ' ' +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 @@ -136,4 +140,11 @@ test_expect_success 'check fully quoted output from diff-tree' ' ' +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 index 8d4804b658..476e5ec038 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Johannes E Schindelin # -test_description='Test git-stash' +test_description='Test git stash' . ./test-lib.sh @@ -177,4 +177,55 @@ test_expect_success 'stash branch' ' 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_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 c44b27aeb2..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 diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index a32692417d..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 diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index a4cfde6b29..18695ce821 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 @@ -169,6 +169,20 @@ test_expect_success \ 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 && @@ -244,4 +258,12 @@ test_expect_success \ 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 8b1f875286..c6130c4019 100755 --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -7,11 +7,11 @@ 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) && @@ -99,7 +99,7 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && + '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, diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index 3d25be7a67..a4da1196a9 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -10,7 +10,13 @@ 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 + say 'Symbolic links not supported, skipping tests.' + test_done +fi test_expect_success \ 'prepare reference tree' \ diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh index 6630017312..1ba359d478 100755 --- a/t/t4005-diff-rename-2.sh +++ b/t/t4005-diff-rename-2.sh @@ -7,11 +7,11 @@ 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) && @@ -71,7 +71,7 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && git update-index --add --remove COPYING COPYING.1' git diff-index -C --find-copies-harder $tree >current diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index 4e92fce1d0..ff8c2f7532 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -15,24 +15,11 @@ test_expect_success \ 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 diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh index 104a4e1492..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 26c2e4aa65..e19ca65885 100755 --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -22,12 +22,12 @@ 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 && + 'cat "$TEST_DIRECTORY"/../README >file0 && + cat "$TEST_DIRECTORY"/../COPYING >file1 && git update-index --add file0 file1 && tree=$(git write-tree) && echo "$tree"' @@ -99,7 +99,7 @@ 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 && @@ -114,7 +114,7 @@ cat >expected <<\EOF :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 EOF -test_expect_success \ +test_expect_success SYMLINKS \ 'validate result of -B (#5)' \ 'compare_diff_raw expected current' @@ -129,7 +129,7 @@ cat >expected <<\EOF :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' @@ -144,7 +144,7 @@ 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' diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh index d2b45e7b8f..de3f17478e 100755 --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -7,11 +7,11 @@ 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) && @@ -78,7 +78,7 @@ test_expect_success \ test_expect_success \ 'prepare work tree once again' \ - 'cat ../../COPYING >COPYING && + 'cat "$TEST_DIRECTORY"/../COPYING >COPYING && git update-index --add --remove COPYING COPYING.1' git diff-index -z -C --find-copies-harder $tree >current diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index ad3d9e4845..94df7ae53a 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -10,7 +10,7 @@ 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 \ @@ -62,4 +62,12 @@ test_expect_success \ '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 c6d13693ba..d7e327cc5b 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 + say 'Symbolic links not supported, skipping tests.' + test_done +fi cat > expected << EOF diff --git a/frotz b/frotz @@ -82,4 +88,11 @@ test_expect_success \ 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 eced1f30fb..bc46563afc 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \ 'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d && git update-index --add a b c d && echo git >a && - cat ../test4012.png >b && + cat "$TEST_DIRECTORY"/test4012.png >b && echo git >c && cat b b >d' @@ -25,11 +25,11 @@ cat > expected <<\EOF EOF test_expect_success 'diff without --binary' \ 'git diff | git apply --stat --summary >current && - cmp current expected' + test_cmp expected current' test_expect_success 'diff with --binary' \ 'git diff --binary | git apply --stat --summary >current && - cmp current expected' + 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. @@ -61,7 +61,7 @@ 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' \ @@ -72,9 +72,26 @@ test_expect_success 'diff-index with --binary' \ git apply --stat --summary current' test_expect_success 'apply binary patch' \ - 'git-reset --hard && + '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 9337b81064..8e3694ed5b 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -74,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 @@ -97,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" ' @@ -203,6 +206,11 @@ log --root -c --patch-with-stat --summary master log --root --cc --patch-with-stat --summary 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 @@ -236,11 +244,15 @@ 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 @@ -258,6 +270,10 @@ 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.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_--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_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 cf6891f748..ce49bd676e 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master @@ -2,7 +2,7 @@ $ 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" @@ -19,10 +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: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Disposition: attachment; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -61,7 +63,7 @@ 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" @@ -75,10 +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: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" +Content-Disposition: attachment; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -107,7 +111,7 @@ 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" @@ -122,10 +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: attachment; 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 fe0258720c..5f1b23863b 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ @@ -2,7 +2,7 @@ $ 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" @@ -19,10 +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: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" +Content-Disposition: attachment; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -61,7 +63,7 @@ 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" @@ -75,10 +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: attachment; 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 9ff828ee9d..4a2364abc2 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side @@ -17,10 +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: attachment; 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 index a8093be7ca..ca3f60bf0e 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master @@ -2,7 +2,7 @@ $ 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] Second +Subject: [TESTCASE 1/3] Second MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" @@ -19,10 +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: inline; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -61,7 +63,7 @@ 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: [TESTCASE] Third +Subject: [TESTCASE 2/3] Third MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" @@ -75,10 +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: inline; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -107,7 +111,7 @@ 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: [TESTCASE] Side +Subject: [TESTCASE 3/3] Side MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n" @@ -122,10 +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: inline; filename="0003-Side.patch" diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master index aa110c0e7f..08f23014bc 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master @@ -2,7 +2,7 @@ $ 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] 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" @@ -19,10 +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: inline; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -61,7 +63,7 @@ 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" @@ -75,10 +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: inline; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 @@ -107,7 +111,7 @@ 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" @@ -122,10 +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: inline; filename="0003-Side.patch" diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ index 95e9ea4c59..07f1230d31 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ @@ -2,7 +2,7 @@ $ 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] 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" @@ -19,10 +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: inline; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 @@ -61,7 +63,7 @@ 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" @@ -75,10 +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: inline; filename="0002-Third.patch" diff --git a/dir/sub b/dir/sub index 8422d40..cead32e 100644 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ index b8e81e1552..29e00ab8af 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ @@ -19,10 +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: inline; filename="0001-Second.patch" diff --git a/dir/sub b/dir/sub index 35d242b..8422d40 100644 diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side index 86ae923d71..67633d424a 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side @@ -17,10 +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: inline; filename="0001-Side.patch" diff --git a/dir/sub b/dir/sub index 35d242b..7289e35 100644 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_-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_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 7fe853c20d..f2a2aaa2b9 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Junio C Hamano # -test_description='Format-patch skipping already incorporated patches' +test_description='various format-patch tests' . ./test-lib.sh @@ -16,9 +16,7 @@ test_expect_success setup ' git checkout -b side && for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file && - chmod +x elif && - git update-index file elif && - git update-index --chmod=+x elif && + test_chmod +x elif && git commit -m "Side changes #1" && for i in D E F; do echo "$i"; done >>file && @@ -95,9 +93,9 @@ test_expect_success 'extra headers' ' 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 + sed -e "/^\$/q" patch2 > hdrs2 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 && + grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2 ' @@ -106,9 +104,9 @@ 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 + sed -e "/^\$/q" patch3 > hdrs3 && + grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 && + grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3 ' @@ -117,17 +115,32 @@ 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 + 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 + 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 'multiple files' ' @@ -138,56 +151,243 @@ test_expect_success 'multiple files' ' 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 ' -test_expect_success 'thread' ' +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 - rm -rf patches/ && +test_expect_success 'no threading' ' git checkout side && - git format-patch --thread -o patches/ master && - FIRST_MID=$(grep "Message-Id:" patches/0001-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") && - for i in patches/0002-* patches/0003-* - do - grep "References: $FIRST_MID" $i && - grep "In-Reply-To: $FIRST_MID" $i || break - done + check_threading expect.no-threading master ' -test_expect_success 'thread in-reply-to' ' +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 - rm -rf patches/ && - git checkout side && - git format-patch --in-reply-to="<test.message>" --thread -o patches/ master && - FIRST_MID="<test.message>" && - for i in patches/* - do - grep "References: $FIRST_MID" $i && - grep "In-Reply-To: $FIRST_MID" $i || break - done +test_expect_success 'thread' ' + check_threading expect.thread --thread master ' -test_expect_success 'thread cover-letter' ' +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 - rm -rf patches/ && - git checkout side && - git format-patch --cover-letter --thread -o patches/ master && - FIRST_MID=$(grep "Message-Id:" patches/0000-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") && - for i in patches/0001-* patches/0002-* patches/0003-* - do - grep "References: $FIRST_MID" $i && - grep "In-Reply-To: $FIRST_MID" $i || break - done +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 +' - rm -rf patches/ && - git checkout side && - git format-patch --cover-letter --in-reply-to="<test.message>" --thread -o patches/ master && - FIRST_MID="<test.message>" && - for i in patches/* - do - grep "References: $FIRST_MID" $i && - grep "In-Reply-To: $FIRST_MID" $i || break - done +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' ' @@ -206,9 +406,9 @@ 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 && + ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch && git format-patch --cover-letter -1 -M && - grep "file => foo .* 0 *$" 0000-cover-letter.patch + grep "file => foo .* 0 *\$" 0000-cover-letter.patch ' @@ -225,9 +425,136 @@ 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 && + 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_done diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index a27fccc8dc..90f3342373 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 @@ -93,11 +93,15 @@ 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' '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 @@ -116,6 +120,27 @@ index d99af23..8b32fb5 100644 EOF git diff -b > out test_expect_success 'another test, with -b' 'test_cmp expect out' +git diff -b --ignore-space-at-eol > out +test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out' + +tr 'Q' '\015' << EOF > expect +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' ' @@ -335,10 +360,56 @@ test_expect_success 'line numbers in --check output are correct' ' ' -test_expect_success 'checkdiff detects trailing blank lines' ' +test_expect_success 'checkdiff detects new trailing blank lines (1)' ' echo "foo();" >x && echo "" >>x && - git diff --check | grep "ends with blank" + 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 +' + +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 f07035ab7e..55eb5f83f1 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" || { + say 'Your filesystem does not allow tabs in filenames, test skipped.' test_done } diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 833d6cbcfc..5b10e976a3 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -32,7 +32,18 @@ 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" ' @@ -54,7 +65,20 @@ test_expect_success 'custom pattern' ' test_expect_success 'last regexp must not be negated' ' git config diff.java.funcname "!static" && - test_must_fail git diff --no-index Beer.java Beer-correct.java + 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 index 0d9cbb6261..f6d1f1ebab 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -13,17 +13,34 @@ test_expect_success setup ' echo " HT and SP indent" >>F && echo "With trailing SP " >>F && echo "Carriage ReturnQ" | tr Q "\015" >>F && - echo "No problem" >>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 ' - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT error >/dev/null && @@ -36,9 +53,7 @@ test_expect_success default ' test_expect_success 'without -trail' ' git config core.whitespace -trail - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT error >/dev/null && @@ -52,9 +67,7 @@ test_expect_success 'without -trail (attribute)' ' git config --unset core.whitespace echo "F whitespace=-trail" >.gitattributes - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT error >/dev/null && @@ -68,9 +81,7 @@ test_expect_success 'without -space' ' rm -f .gitattributes git config core.whitespace -space - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT normal >/dev/null && @@ -84,9 +95,7 @@ test_expect_success 'without -space (attribute)' ' git config --unset core.whitespace echo "F whitespace=-space" >.gitattributes - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT normal >/dev/null && @@ -100,9 +109,7 @@ test_expect_success 'with indent-non-tab only' ' rm -f .gitattributes git config core.whitespace indent,-trailing,-space - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight error >/dev/null && grep HT normal >/dev/null && @@ -116,9 +123,7 @@ test_expect_success 'with indent-non-tab only (attribute)' ' git config --unset core.whitespace echo "F whitespace=indent,-trailing,-space" >.gitattributes - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight error >/dev/null && grep HT normal >/dev/null && @@ -132,9 +137,7 @@ test_expect_success 'with cr-at-eol' ' rm -f .gitattributes git config core.whitespace cr-at-eol - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT error >/dev/null && @@ -148,9 +151,7 @@ test_expect_success 'with cr-at-eol (attribute)' ' git config --unset core.whitespace echo "F whitespace=trailing,cr-at-eol" >.gitattributes - git diff --color >output - grep "$blue_grep" output >error - grep -v "$blue_grep" output >normal + prepare_output grep Eight normal >/dev/null && grep HT error >/dev/null && @@ -160,4 +161,42 @@ test_expect_success 'with cr-at-eol (attribute)' ' ' +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 index 637b4e19d5..a7602cf923 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -43,6 +43,13 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' ' ' +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 && @@ -68,6 +75,13 @@ test_expect_success 'diff attribute should apply only to diff' ' ' +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 && @@ -94,6 +108,13 @@ test_expect_success 'diff attribute should apply only to diff' ' ' +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 @@ -104,7 +125,48 @@ echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file test_expect_success 'force diff with "diff"' ' echo >.gitattributes "file diff" && git diff >actual && - test_cmp ../t4020/diff.NUL 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/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh index 43d64bbd82..709b3231ca 100755 --- a/t/t4021-format-patch-numbered.sh +++ b/t/t4021-format-patch-numbered.sh @@ -45,17 +45,22 @@ test_numbered() { grep "^Subject: \[PATCH 2/2\]" $1 } -test_expect_success 'Default: no numbered' ' +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 && - test_no_numbered patch0 + git format-patch --stdout HEAD~2 >patch0.multiple && + test_numbered patch0.multiple ' test_expect_success 'Use --numbered' ' - git format-patch --numbered --stdout HEAD~2 >patch1 && - test_numbered patch1 + git format-patch --numbered --stdout HEAD~1 >patch1 && + test_single_numbered patch1 ' @@ -81,6 +86,13 @@ test_expect_success 'format.numbered && --no-numbered' ' ' +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 @@ -103,4 +115,10 @@ test_expect_success 'format.numbered = auto && --no-numbered' ' ' +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 index bf996fc414..2a537a21e8 100755 --- a/t/t4022-diff-rewrite.sh +++ b/t/t4022-diff-rewrite.sh @@ -6,12 +6,12 @@ test_description='rewrite diff' test_expect_success setup ' - cat ../../COPYING >test && + cat "$TEST_DIRECTORY"/../COPYING >test && git add test && tr \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \ "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \ - <../../COPYING >test + <"$TEST_DIRECTORY"/../COPYING >test ' diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh index 4dbfc6e8b7..9bdf6596d8 100755 --- a/t/t4023-diff-rename-typechange.sh +++ b/t/t4023-diff-rename-typechange.sh @@ -4,24 +4,30 @@ test_description='typechange rename detection' . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + say 'Symbolic links not supported, skipping tests.' + test_done +fi + test_expect_success setup ' rm -f foo bar && - cat ../../COPYING >foo && + 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 ../../COPYING >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 ../../COPYING >foo && + cat "$TEST_DIRECTORY"/../COPYING >foo && git add foo && git commit -a -m Third && git tag three && @@ -35,15 +41,15 @@ test_expect_success setup ' # This is purely for sanity check rm -f foo bar && - cat ../../COPYING >foo && - cat ../../Makefile >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 ../../Makefile >foo && - cat ../../COPYING >bar && + cat "$TEST_DIRECTORY"/../Makefile >foo && + cat "$TEST_DIRECTORY"/../COPYING >bar && git add foo bar && git commit -a -m Sixth && git tag six diff --git a/t/t4026-color.sh b/t/t4026-color.sh index b61e5169f4..5ade44c043 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -66,4 +66,21 @@ 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 index ba6679c6e4..83c1914771 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -3,7 +3,7 @@ test_description='difference in submodules' . ./test-lib.sh -. ../diff-lib.sh +. "$TEST_DIRECTORY"/diff-lib.sh _z40=0000000000000000000000000000000000000000 test_expect_success setup ' @@ -32,7 +32,8 @@ test_expect_success setup ' cd sub && git rev-list HEAD ) && - echo ":160000 160000 $3 $_z40 M sub" >expect + echo ":160000 160000 $3 $_z40 M sub" >expect && + subtip=$3 subprev=$2 ' test_expect_success 'git diff --raw HEAD' ' @@ -50,6 +51,87 @@ test_expect_success 'git diff-files --raw' ' 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 +' + +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 +' + test_expect_success 'git diff (empty submodule dir)' ' : >empty && rm -rf sub/* sub/.git && @@ -57,4 +139,43 @@ test_expect_success 'git diff (empty submodule dir)' ' 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/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..2e2e103b31 --- /dev/null +++ b/t/t4034-diff-words.sh @@ -0,0 +1,212 @@ +#!/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 + +' + +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]+" +' + +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=. + +' + +test_done diff --git a/t/t4017-quiet.sh b/t/t4035-diff-quiet.sh index e747e84227..e747e84227 100755 --- a/t/t4017-quiet.sh +++ b/t/t4035-diff-quiet.sh diff --git a/t/t4021-format-patch-signer-mime.sh b/t/t4036-format-patch-signer-mime.sh index ba43f18549..ba43f18549 100755 --- a/t/t4021-format-patch-signer-mime.sh +++ b/t/t4036-format-patch-signer-mime.sh 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..7584efa36b --- /dev/null +++ b/t/t4038-diff-combined.sh @@ -0,0 +1,84 @@ +#!/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_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.sh b/t/t4041-diff-submodule.sh new file mode 100755 index 0000000000..464305405a --- /dev/null +++ b/t/t4041-diff-submodule.sh @@ -0,0 +1,327 @@ +#!/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 $head6..$head6-dirty: +EOF +" + +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 $head6..$head6-dirty: +EOF +" + +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 $head6..$head6-dirty: +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 $head6..$head8-dirty: + > change +EOF +" + +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 $head6..$head8-dirty: + > change +EOF +" + +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 $head6..$head8-dirty: + > 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_done diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index e0c67740a5..9b433de836 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -17,13 +17,13 @@ do test_expect_success "$title" ' git apply --stat --summary \ <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current && - test_cmp ../t4100/t-apply-$num.expect 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 ../t4100/t-apply-$num.expect current + test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current ' done <<\EOF rename diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh index da8abcf364..e3443d004d 100755 --- a/t/t4101-apply-nonl.sh +++ b/t/t4101-apply-nonl.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 d42abff1ad..1597965241 100755 --- a/t/t4102-apply-rename.sh +++ b/t/t4102-apply-rename.sh @@ -31,14 +31,16 @@ test_expect_success setup \ test_expect_success apply \ '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 && test "$(cat foo)" = "This is foo"' diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index 7da0b4bb8b..ad4cc1a757 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -21,16 +21,16 @@ cat file1 >file2 cat file1 >file4 git update-index --add --remove file1 file2 file4 -git-commit -m 'Initial Version' 2>/dev/null +git commit -m 'Initial Version' 2>/dev/null -git-checkout -b binary +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 commit -m 'Second Version' git diff-tree -p master binary >B.diff git diff-tree -p -C master binary >C.diff @@ -39,47 +39,47 @@ 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 checkout master git apply --stat --summary B.diff' test_expect_success 'stat binary diff (copy) -- should not fail.' \ - 'git-checkout master + 'git checkout master git apply --stat --summary C.diff' test_expect_success 'check binary diff -- should fail.' \ - 'git-checkout master && + 'git checkout master && test_must_fail git apply --check B.diff' test_expect_success 'check binary diff (copy) -- should fail.' \ - 'git-checkout master && + 'git checkout master && test_must_fail git apply --check C.diff' test_expect_success \ 'check incomplete binary diff with replacement -- should fail.' ' - git-checkout master && + git checkout master && test_must_fail git apply --check --allow-binary-replacement B.diff ' test_expect_success \ 'check incomplete binary diff with replacement (copy) -- should fail.' ' - git-checkout master && + 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 checkout master git apply --check --allow-binary-replacement BF.diff' test_expect_success 'check binary diff with replacement (copy).' \ - 'git-checkout master + '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 + git reset --hard && + git checkout -f master } test_expect_success 'apply binary diff -- should fail.' \ diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh index e7e2913de7..0e3ce3611d 100755 --- a/t/t4104-apply-boundary.sh +++ b/t/t4104-apply-boundary.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 && @@ -95,7 +104,7 @@ do 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 /" \ 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/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index 55334927ab..99ec13dd53 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -9,6 +9,12 @@ test_description='git apply should not get confused with type changes. . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + say 'Symbolic links not supported, skipping tests.' + test_done +fi + test_expect_success 'setup repository and commits' ' 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 9ace578f17..b852e58980 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -9,6 +9,12 @@ test_description='git apply symlinks and partial files . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + say 'Symbolic links not supported, skipping tests.' + test_done +fi + test_expect_success setup ' ln -s path1/path2/path3/path4/path5 link1 && diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index f92e259cc6..65f2e4c3ef 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -20,10 +20,10 @@ 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 "/^[BQ]/d" <file2.orig >file2 && + cat file1 > file2 && echo Q | tr -d "\\012" >>file2 && cat file1 >file1.mods && cat file2 >file2.mods && diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh index 83d4ba6798..b463b4f05c 100755 --- a/t/t4120-apply-popt.sh +++ b/t/t4120-apply-popt.sh @@ -22,4 +22,9 @@ 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/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 841773f75f..0d3c1d5dd5 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -3,6 +3,12 @@ test_description='apply to deeper directory without getting fooled with symlink' . ./test-lib.sh +if ! test_have_prereq SYMLINKS +then + say 'Symbolic links not supported, skipping tests.' + test_done +fi + lecho () { for l_ do diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh index 85f3da2b98..ca26397590 100755 --- a/t/t4124-apply-ws-rule.sh +++ b/t/t4124-apply-ws-rule.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='core.whitespace rules and git-apply' +test_description='core.whitespace rules and git apply' . ./test-lib.sh @@ -148,4 +148,117 @@ do 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_done diff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh index 3b471b641b..9671de7999 100755 --- a/t/t4125-apply-ws-fuzz.sh +++ b/t/t4125-apply-ws-fuzz.sh @@ -37,11 +37,11 @@ test_expect_success setup ' # 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 && + 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 + sed -e "s/ \$//" file-1 >file-fixed ' diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh index 1f859dd908..3a8202ea93 100755 --- a/t/t4127-apply-same-fn.sh +++ b/t/t4127-apply-same-fn.sh @@ -26,7 +26,7 @@ test_expect_success 'apply same filename with independent changes' ' git diff >> patch0 && cp same_fn same_fn2 && git reset --hard && - git-apply patch0 && + git apply patch0 && diff same_fn same_fn2 ' @@ -39,7 +39,7 @@ test_expect_success 'apply same filename with overlapping changes' ' git diff >> patch0 && cp same_fn same_fn2 && git reset --hard && - git-apply patch0 && + git apply patch0 && diff same_fn same_fn2 ' diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh index 2dd0c75f96..6cc741a634 100755 --- a/t/t4128-apply-root.sh +++ b/t/t4128-apply-root.sh @@ -40,4 +40,73 @@ test_expect_success 'apply --directory -p (2) ' ' ' +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/t4150-am.sh b/t/t4150-am.sh index 6e6aaf5936..810b04b817 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -77,6 +77,18 @@ test_expect_success setup ' 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 && @@ -108,6 +120,24 @@ test_expect_success 'am applies patch correctly' ' 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" @@ -164,8 +194,8 @@ 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 | - grep -q -F "Re: Re: Re: [PATCH 1/5 v2] third" + 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' ' @@ -180,6 +210,17 @@ test_expect_success 'am -3 falls back to 3-way merge' ' 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 && @@ -257,4 +298,67 @@ test_expect_success 'am works from file (absolute path given) in subdirectory' ' 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 index f45ab0a2e8..2b912d7728 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -17,10 +17,12 @@ test_expect_success setup ' 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 initial && + git format-patch --no-numbered initial && git checkout -b side initial && echo local change >file-2-expect ' @@ -42,14 +44,14 @@ do ' test_expect_success "am$with3 --skip continue after failed am$with3" ' - test_must_fail git-am$with3 --skip >output && + test_must_fail git am$with3 --skip >output && test "$(grep "^Applying" output)" = "Applying: 6" && test_cmp file-2-expect file-2 && test ! -f .git/rr-cache/MERGE_RR ' test_expect_success "am --abort goes back after failed am$with3" ' - git-am --abort && + git am --abort && git rev-parse HEAD >actual && git rev-parse initial >expect && test_cmp expect actual && diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index b68ab11f29..bb402c3780 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -57,7 +57,7 @@ test_expect_success 'conflicting merge' ' test_must_fail git merge first ' -sha1=$(sed -e 's/ .*//' .git/MERGE_RR) +sha1=$(perl -pe 's/ .*//' .git/MERGE_RR) rr=.git/rr-cache/$sha1 test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage" @@ -190,8 +190,6 @@ test_expect_success 'file2 added differently in two branches' ' git add file2 && git commit -m version2 && test_must_fail git merge fourth && - sha1=$(sed -e "s/ .*//" .git/MERGE_RR) && - rr=.git/rr-cache/$sha1 && echo Cello > file2 && git add file2 && git commit -m resolution @@ -219,7 +217,22 @@ test_expect_success 'rerere.autoupdate' ' 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 index 405b971191..a01e55bf6b 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -52,4 +52,32 @@ GIT_DIR=non-existing git shortlog -w < log > out test_expect_success 'shortlog from non-git directory' '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 index 4c8af45f83..1dc224f6fb 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -16,27 +16,92 @@ test_expect_success setup ' test_tick && git commit -m second && - mkdir a && - echo ni >a/two && - git add a/two && + git mv one ichi && test_tick && git commit -m third && - echo san >a/three && - git add a/three && + cp ichi ein && + git add ein && test_tick && git commit -m fourth && - git rm a/three && + mkdir a && + echo ni >a/two && + git add a/two && test_tick && - git commit -m fifth + 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 fourth ; echo third ; echo initial) && + expect=$(echo fifth ; echo fourth ; echo third ; echo initial) && test "$actual" = "$expect" || { echo Oops echo "Actual: $actual" @@ -60,7 +125,7 @@ test_expect_success 'diff-filter=M' ' test_expect_success 'diff-filter=D' ' actual=$(git log --pretty="format:%s" --diff-filter=D HEAD) && - expect=$(echo fifth) && + expect=$(echo sixth ; echo third) && test "$actual" = "$expect" || { echo Oops echo "Actual: $actual" @@ -69,7 +134,258 @@ test_expect_success 'diff-filter=D' ' ' +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_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..04f7bae850 --- /dev/null +++ b/t/t4204-patch-id.sh @@ -0,0 +1,38 @@ +#!/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 +' + +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_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/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 3f1e25d921..27bfba55bd 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -25,7 +25,6 @@ commit id embedding: ' . ./test-lib.sh -TAR=${TAR:-tar} UNZIP=${UNZIP:-unzip} SUBSTFORMAT=%H%n @@ -38,7 +37,11 @@ test_expect_success \ cp /bin/sh a/bin && printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 && printf "A not substituted O" >a/substfile2 && - ln -s a a/l1 && + 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) && @@ -47,7 +50,7 @@ test_expect_success \ test_expect_success \ 'add ignored file' \ 'echo ignore me >a/ignored && - echo ignored export-ignore >.gitattributes' + echo ignored export-ignore >.git/info/attributes' test_expect_success \ 'add files to repository' \ @@ -59,6 +62,11 @@ test_expect_success \ 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' @@ -72,29 +80,45 @@ test_expect_success \ test_expect_success \ 'git archive vs. git tar-tree' \ - 'diff b.tar b2.tar' + '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 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' \ 'mkdir extract && - $TAR xf b.tar -C extract a/a && - perl -e '\''print((stat("extract/a/a"))[9], "\n")'\'' >b.mtime && + "$TAR" xf b.tar -C extract a/a && + test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime && echo "1117231200" >expected.mtime && - diff expected.mtime b.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' + 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' \ @@ -106,12 +130,12 @@ test_expect_success \ 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' \ @@ -119,56 +143,79 @@ test_expect_success \ test_expect_success \ 'create archives with substfiles' \ - 'echo "substfile?" export-subst >a/.gitattributes && + '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 && - rm a/.gitattributes' + mv .git/info/attributes.before .git/info/attributes' test_expect_success \ 'extract substfiles' \ - '(mkdir f && cd f && $TAR xf -) <f.tar' + '(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 && - diff f/a/substfile1.expected f/a/substfile1 && - diff a/substfile2 f/a/substfile2 + 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' + '(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 && - diff g/prefix/a/substfile1.expected g/prefix/a/substfile1 && - diff a/substfile2 g/prefix/a/substfile2 + 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 - echo "Skipping ZIP tests, because unzip was not found" - test_done - exit + say "Skipping ZIP tests, because unzip was not found" +else + test_set_prereq UNZIP fi -test_expect_success \ +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' @@ -176,16 +223,16 @@ test_expect_success \ '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' @@ -193,4 +240,16 @@ 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 e9f3e72c7e..ebc36c1758 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -8,27 +8,62 @@ 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` = 10' + 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. ../t5100/nul-plain && - cmp ../t5100/nul-plain 001 && + 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) @@ -36,10 +71,21 @@ test_expect_success 'respect NULs' ' test_expect_success 'Preserve NULs out of MIME encoded message' ' - git mailsplit -d5 -o. ../t5100/nul-b64.in && - cmp ../t5100/nul-b64.in 00001 && + git mailsplit -d5 -o. "$TEST_DIRECTORY"/t5100/nul-b64.in && + test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.in 00001 && git mailinfo msg patch <00001 && - cmp ../t5100/nul-b64.expect patch + 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 ' 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/0010 b/t/t5100/0010 deleted file mode 100644 index f5892c9da7..0000000000 --- a/t/t5100/0010 +++ /dev/null @@ -1,35 +0,0 @@ -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 - 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/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/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..9577238685 --- /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/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 aba57f922b..de1031241d 100644 --- a/t/t5100/sample.mbox +++ b/t/t5100/sample.mbox @@ -2,7 +2,10 @@ 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. @@ -96,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 @@ -215,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 @@ -223,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 @@ -465,3 +468,218 @@ index 962aa34..2d1520f 100644 -- 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/t5300-pack-object.sh b/t/t5300-pack-object.sh index 645583f9d7..7649b810b1 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,11 +13,12 @@ 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 | perl -pe "y/\\000/$i/" >$i && - git update-index --add $i || return 1 - done && + 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` && { @@ -180,6 +181,23 @@ test_expect_success \ 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 \ @@ -187,6 +205,12 @@ test_expect_success \ test-3-${packname_3}.idx' test_expect_success \ + '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 && @@ -198,7 +222,7 @@ test_expect_success \ test_expect_success \ 'verify-pack catches a corrupted pack signature' \ 'cat test-1-${packname_1}.pack >test-3.pack && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && if git verify-pack test-3.idx then false else :; @@ -207,7 +231,7 @@ test_expect_success \ test_expect_success \ 'verify-pack catches a corrupted pack version' \ 'cat test-1-${packname_1}.pack >test-3.pack && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && if git verify-pack test-3.idx then false else :; @@ -216,7 +240,7 @@ test_expect_success \ 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 && - dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && if git verify-pack test-3.idx then false else :; @@ -227,7 +251,7 @@ test_expect_success \ 'l=`wc -c <test-3.idx` && l=`expr $l - 20` && cat test-1-${packname_1}.pack >test-3.pack && - dd if=/dev/zero of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && + 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 :; @@ -236,47 +260,30 @@ test_expect_success \ test_expect_success \ 'build pack index for an existing pack' \ 'cat test-1-${packname_1}.pack >test-3.pack && - git-index-pack -o tmp.idx 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 && cat test-2-${packname_2}.pack >test-3.pack && - git-index-pack -o tmp.idx test-2-${packname_2}.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 && + 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 && + git index-pack test-3.pack && cmp test-3.idx test-3-${packname_3}.idx && :' -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' - -test_expect_success \ - 'honor pack.packSizeLimit' \ - 'git config pack.packSizeLimit 200 && - packname_4=$(git pack-objects test-4 <obj-list) && - test 3 = $(ls test-4-*.pack | wc -l)' - test_expect_success 'unpacking with --strict' ' - git config --unset pack.packsizelimit && for j in a b c d e f g do for i in 0 1 2 3 4 5 6 7 8 9 @@ -369,4 +376,42 @@ test_expect_success 'index-pack with --strict' ' ) ' +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 073ac0c6f9..0a24e61ff9 100755 --- a/t/t5301-sliding-window.sh +++ b/t/t5301-sliding-window.sh @@ -19,7 +19,7 @@ test_expect_success \ tree=`git write-tree` && commit1=`git commit-tree $tree </dev/null` && git update-ref HEAD $commit1 && - git-repack -a -d && + git repack -a -d && test "`git count-objects`" = "0 objects, 0 kilobytes" && pack1=`ls .git/objects/pack/*.pack` && test -f "$pack1"' @@ -45,7 +45,7 @@ test_expect_success \ git config core.packedGitLimit 512 && commit2=`git commit-tree $tree -p $commit1 </dev/null` && git update-ref HEAD $commit2 && - git-repack -a -d && + git repack -a -d && test "`git count-objects`" = "0 objects, 0 kilobytes" && pack2=`ls .git/objects/pack/*.pack` && test -f "$pack2" diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 0639772ac4..4360e77d31 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -10,14 +10,20 @@ test_expect_success \ 'setup' \ 'rm -rf .git git init && + git config pack.threads 1 && i=1 && - while test $i -le 100 + while test $i -le 100 do - i=`printf '%03i' $i` - echo $i >file_$i && - test-genrandom "$i" 8192 >>file_$i && - git update-index --add file_$i && - i=`expr $i + 1` || return 1 + 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 && @@ -48,11 +54,11 @@ test_expect_success \ test_expect_success \ 'index-pack with index version 1' \ - 'git-index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"' + '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"' + 'git index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"' test_expect_success \ 'index-pack results should match pack-objects ones' \ @@ -63,38 +69,58 @@ 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)' -have_64bits= if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) || ! (echo "$msg" | grep "pack too large .* off_t") then - have_64bits=t + test_set_prereq OFF64_T else say "skipping tests concerning 64-bit offsets" fi -test "$have_64bits" && -test_expect_success \ +test_expect_success OFF64_T \ 'index v2: verify a pack with some 64-bit offsets' \ 'git verify-pack -v "test-3-${pack3}.pack"' -test "$have_64bits" && -test_expect_success \ +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 "$have_64bits" && -test_expect_success \ +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"' + 'git index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"' -test "$have_64bits" && -test_expect_success \ +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 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" && @@ -102,19 +128,22 @@ test_expect_success \ test_expect_success \ '[index v1] 2) create a stealth corruption in a delta base reference' \ - '# this test assumes a delta smaller than 16 bytes at the end of the pack - git show-index <1.idx | sort -n | sed -ne \$p | ( - read delta_offs delta_sha1 && - git cat-file blob "$delta_sha1" > blob_1 && - chmod +w ".git/objects/pack/pack-${pack1}.pack" && - dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \ - if=".git/objects/pack/pack-${pack1}.idx" skip=$((256 * 4 + 4)) \ - bs=1 count=20 conv=notrunc && - git cat-file blob "$delta_sha1" > blob_2 )' + '# 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' \ - '! cmp blob_1 blob_2' + 'test -f file_101_foo1 && ! cmp file_101 file_101_foo1' test_expect_success \ '[index v1] 4) confirm that the pack is actually corrupted' \ @@ -132,7 +161,7 @@ test_expect_success \ 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 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" && @@ -140,19 +169,22 @@ test_expect_success \ test_expect_success \ '[index v2] 2) create a stealth corruption in a delta base reference' \ - '# this test assumes a delta smaller than 16 bytes at the end of the pack - git show-index <1.idx | sort -n | sed -ne \$p | ( - read delta_offs delta_sha1 delta_crc && - git cat-file blob "$delta_sha1" > blob_3 && - chmod +w ".git/objects/pack/pack-${pack1}.pack" && - dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \ - if=".git/objects/pack/pack-${pack1}.idx" skip=$((8 + 256 * 4)) \ - bs=1 count=20 conv=notrunc && - git cat-file blob "$delta_sha1" > blob_4 )' + '# 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' \ - '! cmp blob_3 blob_4' + 'test -f file_101_foo2 && ! cmp file_101 file_101_foo2' test_expect_success \ '[index v2] 4) confirm that the pack is actually corrupted' \ @@ -160,16 +192,19 @@ test_expect_success \ 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 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 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" && - dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \ - bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + 0)) && + 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 ) && @@ -177,4 +212,14 @@ test_expect_success \ ".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 index 31b20b21d2..5f6cd4f333 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -41,14 +41,22 @@ create_new_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 if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs && + 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 && @@ -60,7 +68,7 @@ test_expect_success \ test_expect_success \ 'create corruption in header of first object' \ - 'do_corrupt_object $blob_1 0 && + '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' @@ -119,7 +127,7 @@ test_expect_success \ 'create corruption in header of first delta' \ 'create_new_pack && git prune-packed && - do_corrupt_object $blob_2 0 && + 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' @@ -134,6 +142,15 @@ test_expect_success \ 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 && @@ -153,10 +170,19 @@ test_expect_success \ 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 && + 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' @@ -171,17 +197,75 @@ test_expect_success \ git cat-file blob $blob_3 > /dev/null' test_expect_success \ - 'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \ + '... 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 && + 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 \ - '... and a redundant pack allows for full recovery too' \ + '... 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 && @@ -191,4 +275,13 @@ test_expect_success \ 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 index 9fd9d07000..3c6687abec 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -6,6 +6,17 @@ 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 && @@ -21,7 +32,7 @@ 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 && + test-chmtime =-86501 .git/objects/tmp_1.pack && git prune --expire 1.day && test -f $orig_pack && test -f .git/objects/tmp_2.pack && @@ -31,15 +42,11 @@ test_expect_success 'prune stale packs' ' test_expect_success 'prune --expire' ' - before=$(git count-objects | sed "s/ .*//") && - BLOB=$(echo aleph | 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 && + 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 && + test-chmtime =-86500 $BLOB_FILE && git prune --expire 1.day && test $before = $(git count-objects | sed "s/ .*//") && ! test -f $BLOB_FILE @@ -48,16 +55,12 @@ test_expect_success 'prune --expire' ' test_expect_success 'gc: implicit prune --expire' ' - 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-chmtime -$((86400*14-30)) $BLOB_FILE && + 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 -$((86400*14+1)) $BLOB_FILE && + test-chmtime =-$((2*$week+1)) $BLOB_FILE && git gc && test $before = $(git count-objects | sed "s/ .*//") && ! test -f $BLOB_FILE @@ -112,4 +115,51 @@ test_expect_success 'prune: do not prune heads listed as an argument' ' ' +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 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 index fb471a08c6..b061864a87 100755 --- a/t/t5305-include-tag.sh +++ b/t/t5305-include-tag.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-pack-object --include-tag' +test_description='git pack-object --include-tag' . ./test-lib.sh TRASH=`pwd` 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 68c2ae688c..c718253673 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -31,10 +31,8 @@ test_expect_success setup ' parent=$commit || return 1 done && git update-ref HEAD "$commit" && - git-clone ./. victim && - cd victim && - git log && - cd .. && + git clone ./. victim && + ( cd victim && git config receive.denyCurrentBranch warn && git log ) && git update-ref HEAD "$zero" && parent=$zero && i=0 && @@ -59,77 +57,85 @@ 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 \ - '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 - then - # should have been left as it was! - false - else - true - fi && +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/.git/ master && - cmp victim/.git/refs/heads/master .git/refs/heads/master + git send-pack --force ./victim master && + victim_head=$(cd victim && git rev-parse --verify master) && + test "$victim_head" = "$pushed_head" ' 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 + ( cd victim && git branch extra master ) && + git send-pack ./victim :extra master && + ( cd victim && + test_must_fail git rev-parse --verify extra ) ' -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 '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 \ - 'pushing with --force should be denied with denyNonFastforwards' ' - cd victim && - git config receive.denyNonFastforwards true && - cd .. && - git update-ref refs/heads/master master^ || return 1 - git-send-pack --force ./victim/.git/ master && return 1 - ! test_cmp .git/refs/heads/master victim/.git/refs/heads/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 \ - 'pushing does not include non-head refs' ' - mkdir parent && cd parent && - git-init && touch file && git-add file && git-commit -m add && - cd .. && - git-clone parent child && cd child && git-push --all && - cd ../parent && - git-branch -a >branches && ! grep origin/master branches +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 && - echo two >file && git-commit -a -m two && - cd .. && - git-clone parent child && cd child && git-reset --hard HEAD^ + 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() { @@ -145,30 +151,52 @@ rewound_push_failed() { fi } -test_expect_success \ - 'pushing explicit refspecs respects forcing' ' +test_expect_success 'pushing explicit refspecs respects forcing' ' rewound_push_setup && - if git-send-pack ../parent/.git refs/heads/master:refs/heads/master - then - false - else - true - fi && rewound_push_failed && - git-send-pack ../parent/.git +refs/heads/master:refs/heads/master && - rewound_push_succeeded + 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" ' -test_expect_success \ - 'pushing wildcard refspecs respects forcing' ' +test_expect_success 'pushing wildcard refspecs respects forcing' ' rewound_push_setup && - if git-send-pack ../parent/.git refs/heads/*:refs/heads/* - then - false - else - true - fi && rewound_push_failed && - git-send-pack ../parent/.git +refs/heads/*:refs/heads/* && - rewound_push_succeeded + 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 '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 ee769d6695..17bcb0b040 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -17,22 +17,22 @@ test_expect_success setup ' 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 ./. victim && - GIT_DIR=victim/.git 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/pre-receive <<'EOF' +cat >victim.git/hooks/pre-receive <<'EOF' #!/bin/sh 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/pre-receive +chmod u+x victim.git/hooks/pre-receive -cat >victim/.git/hooks/update <<'EOF' +cat >victim.git/hooks/update <<'EOF' #!/bin/sh echo "$@" >>$GIT_DIR/update.args read x; printf %s "$x" >$GIT_DIR/update.stdin @@ -40,77 +40,77 @@ echo STDOUT update $1 echo STDERR update $1 >&2 test "$1" = refs/heads/master || exit EOF -chmod u+x victim/.git/hooks/update +chmod u+x victim.git/hooks/update -cat >victim/.git/hooks/post-receive <<'EOF' +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 +chmod u+x victim.git/hooks/post-receive -cat >victim/.git/hooks/post-update <<'EOF' +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 ' - test_must_fail git-send-pack --force ./victim/.git \ + 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 $(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/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 -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_cmp - victim.git/pre-receive.stdin ' test_expect_success 'update hook arguments' ' (echo refs/heads/master $commit0 $commit1; echo refs/heads/tofail $commit1 $commit0 - ) | test_cmp - victim/.git/update.args + ) | 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_cmp - victim.git/post-receive.stdin ' test_expect_success 'post-update hook arguments' ' echo refs/heads/master | - test_cmp - victim/.git/post-update.args + test_cmp - victim.git/post-update.args ' test_expect_success 'all hook stdin is /dev/null' ' - ! test -s victim/.git/update.stdin && - ! test -s victim/.git/post-update.stdin + ! test -s victim.git/update.stdin && + ! 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 -s victim.git/pre-receive.args && + ! test -s victim.git/post-receive.args ' test_expect_success 'send-pack produced no output' ' @@ -118,20 +118,21 @@ test_expect_success 'send-pack produced no output' ' ' cat <<EOF >expect -STDOUT pre-receive -STDERR pre-receive -STDOUT update refs/heads/master -STDERR update refs/heads/master -STDOUT update refs/heads/tofail -STDERR update refs/heads/tofail -STDOUT post-receive -STDERR post-receive -STDOUT post-update -STDERR post-update +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 ^STD send.err >actual && - test_cmp - actual <expect + 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 index 1394047a8d..6eb2ffd6ec 100755 --- a/t/t5402-post-merge-hook.sh +++ b/t/t5402-post-merge-hook.sh @@ -16,9 +16,9 @@ test_expect_success setup ' tree1=$(git write-tree) && commit1=$(echo modify | git commit-tree $tree1 -p $commit0) && git update-ref refs/heads/master $commit0 && - git-clone ./. clone1 && + git clone ./. clone1 && GIT_DIR=clone1/.git git update-index --add a && - git-clone ./. clone2 && + git clone ./. clone2 && GIT_DIR=clone2/.git git update-index --add a ' diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh index 823239a251..d05a9138b4 100755 --- a/t/t5403-post-checkout-hook.sh +++ b/t/t5403-post-checkout-hook.sh @@ -7,19 +7,19 @@ 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 -a new2 && - echo Data for commit1. >clone2/b && - GIT_DIR=clone2/.git git add clone2/b && - GIT_DIR=clone2/.git git commit -m new2 + 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 @@ -71,4 +71,18 @@ test_expect_success 'post-checkout receives the right args when not switching br 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/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh index 86abc62271..4bda18a662 100755 --- a/t/t5405-send-pack-rewind.sh +++ b/t/t5405-send-pack-rewind.sh @@ -8,11 +8,12 @@ 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 .. master:master + git fetch --update-head-ok .. master:master ) && >file2 && git add file2 && test_tick && diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 362cf7e928..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) - eval "$name=$commit; export $name" - 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 "file://$(pwd)/." 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_success "pull in shallow repo with missing merge base" \ - "(cd shallow && test_must_fail 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 index 16eadd6b68..1037a723fe 100755 --- a/t/t5502-quickfetch.sh +++ b/t/t5502-quickfetch.sh @@ -119,4 +119,24 @@ test_expect_success 'quickfetch should not copy from alternate' ' ' +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 index 4074e23ffa..d5db75d826 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -4,6 +4,12 @@ test_description='test automatic tag following' . ./test-lib.sh +case $(uname -s) in +*MINGW*) + say "GIT_DEBUG_SEND_PACK not supported - skipping tests" + test_done +esac + # End state of the repository: # # T - tag1 S - tag2 diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index be9ee9326f..a82c5ffa1c 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -28,7 +28,7 @@ tokens_match () { } check_remote_track () { - actual=$(git remote show "$1" | sed -n -e '$p') && + actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p') shift && tokens_match "$*" "$actual" } @@ -107,46 +107,106 @@ test_expect_success 'remove remote' ' ) ' +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 - URL: $(pwd)/one/.git - Remote branch merged with 'git pull' while on branch master + 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 - New remote branch (next fetch will store in remotes/origin) - master - Tracked remote branches - side master - Local branches pushed with 'git push' - master:upstream +refs/tags/lastbackup + 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 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 remote.origin.push \ - refs/heads/master:refs/heads/upstream && - git config --add remote.origin.push \ - +refs/tags/lastbackup && - git remote show origin > output && + 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 - URL: $(pwd)/one/.git - Remote branch merged with 'git pull' while on branch master + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one + HEAD branch: (not queried) + Remote branches: (status not queried) master - Tracked remote branches - master side - Local branches pushed with 'git push' - master:upstream +refs/tags/lastbackup + 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' ' @@ -167,9 +227,49 @@ test_expect_success 'prune' ' 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/.git +URL: $(pwd)/one * [would prune] origin/side2 EOF @@ -188,7 +288,7 @@ test_expect_success 'prune --dry-run' ' test_expect_success 'add --mirror && prune' ' (mkdir mirror && cd mirror && - git init && + git init --bare && git remote add --mirror -f origin ../one) && (cd one && git branch -m side2 side) && @@ -265,6 +365,17 @@ test_expect_success 'update with arguments' ' ' +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 @@ -308,12 +419,26 @@ test_expect_success 'update default (overridden, with funny whitespace)' ' ' +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 "^ *HEAD$" < output && ! grep -i stale < output) ' @@ -324,4 +449,303 @@ test_expect_success 'reject adding remote with an invalid 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 + ) 2>err && + 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 '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 13d1d826c2..169af1edde 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 && @@ -111,7 +116,7 @@ test_expect_success 'fetch must not resolve short tag name' ' test_expect_success 'fetch must not resolve short remote name' ' cd "$D" && - git-update-ref refs/remotes/six/HEAD HEAD + git update-ref refs/remotes/six/HEAD HEAD mkdir six && cd six && @@ -146,6 +151,7 @@ test_expect_success 'unbundle 1' ' test_must_fail git fetch "$D/bundle1" master:master ' + test_expect_success 'bundle 1 has only 3 files ' ' cd "$D" && ( @@ -156,8 +162,7 @@ test_expect_success 'bundle 1 has only 3 files ' ' cat ) <bundle1 >bundle.pack && git index-pack bundle.pack && - verify=$(git verify-pack -v bundle.pack) && - test 4 = $(echo "$verify" | wc -l) + test_bundle_object_count bundle.pack 3 ' test_expect_success 'unbundle 2' ' @@ -180,7 +185,7 @@ test_expect_success 'bundle does not prerequisite objects' ' cat ) <bundle3 >bundle.pack && git index-pack bundle.pack && - test 4 = $(git verify-pack -v bundle.pack | wc -l) + test_bundle_object_count bundle.pack 3 ' test_expect_success 'bundle should be able to create a full history' ' @@ -191,38 +196,39 @@ test_expect_success 'bundle should be able to create a full history' ' ' -test "$TEST_RSYNC" && { +! 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 && - git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master && - git gc --prune && - test $(git rev-parse master) = $(cd .. && git rev-parse master) && - git fsck --full + (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 && + mkdir rsynced2 && + (cd rsynced2 && git init) && - git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master && - cd ../rsynced2 && - git gc --prune && - test $(git rev-parse master) = $(cd .. && git rev-parse master) && - git fsck --full + (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' ' - cd .. && mkdir rsynced3 && (cd rsynced3 && git init) && - git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git && - cd rsynced3 && - test $(git rev-parse master) = $(cd .. && git rev-parse master) && - git fsck --full + git push --all "rsync:$(pwd)/rsynced3/.git" && + (cd rsynced3 && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full) ' } @@ -303,4 +309,47 @@ test_expect_success 'pushing nonexistent branch by mistake should not segv' ' ' +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 "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 index 22ba380034..c28932216b 100755 --- a/t/t5511-refspec.sh +++ b/t/t5511-refspec.sh @@ -72,4 +72,16 @@ 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/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 8becbc3f38..dbb927dec8 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -129,11 +129,10 @@ do '' | '#'*) continue ;; esac test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'` - cnt=`expr $test_count + 1` - pfx=`printf "%04d" $cnt` - expect_f="../../t5515/fetch.$test" + pfx=`printf "%04d" $test_count` + expect_f="$TEST_DIRECTORY/t5515/fetch.$test" actual_f="$pfx-fetch.$test" - expect_r="../../t5515/refs.$test" + expect_r="$TEST_DIRECTORY/t5515/refs.$test" actual_r="$pfx-refs.$test" test_expect_success "$cmd" ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index f0030ad00e..0f04b2e894 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -12,6 +12,7 @@ mk_empty () { ( cd testrepo && git init && + git config receive.denyCurrentBranch warn && mv .git/hooks .git/hooks-disabled ) } @@ -39,6 +40,11 @@ mk_test () { ) } +mk_child() { + rm -rf "$1" && + git clone testrepo "$1" +} + check_push_result () { ( cd testrepo && @@ -117,6 +123,23 @@ test_expect_success 'fetch with insteadOf' ' ) ' +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 && @@ -157,6 +180,36 @@ test_expect_success 'push with insteadOf' ' ) ' +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 && @@ -414,6 +467,19 @@ test_expect_success 'push with config remote.*.push = HEAD' ' 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 && @@ -425,29 +491,47 @@ test_expect_success 'push with dry-run' ' test_expect_success 'push updates local refs' ' - rm -rf parent child && - mkdir parent && - (cd parent && git init && - echo one >foo && git add foo && git commit -m one) && - git clone parent child && + mk_test heads/master && + mk_child child && (cd child && - echo two >foo && git commit -a -m two && + 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' ' - rm -rf parent child && - mkdir parent && - (cd parent && git init && - echo one >foo && git add foo && git commit -m one && - echo exit 1 >.git/hooks/pre-receive && - chmod +x .git/hooks/pre-receive) && - git clone parent child && + mk_test heads/master && + mk_child child && + mkdir testrepo/.git/hooks && + echo exit 1 >testrepo/.git/hooks/pre-receive && + chmod +x testrepo/.git/hooks/pre-receive && (cd child && - echo two >foo && git commit -a -m two && + git pull .. master test_must_fail git push && test $(git rev-parse master) != \ $(git rev-parse remotes/origin/master)) @@ -456,11 +540,124 @@ test_expect_success 'push does not update local refs on failure' ' test_expect_success 'allow deleting an invalid remote ref' ' - pwd && + 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_done diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh index ea49dedbf8..e2ad260508 100755 --- a/t/t5517-push-mirror.sh +++ b/t/t5517-push-mirror.sh @@ -19,7 +19,8 @@ mk_repo_pair () { mkdir mirror && ( cd mirror && - git init + git init && + git config receive.denyCurrentBranch warn ) && mkdir master && ( diff --git a/t/t5518-fetch-exit-status.sh b/t/t5518-fetch-exit-status.sh index c6bc65faa0..c2060bb870 100755 --- a/t/t5518-fetch-exit-status.sh +++ b/t/t5518-fetch-exit-status.sh @@ -22,7 +22,7 @@ test_expect_success setup ' git commit -a -m next ' -test_expect_success 'non fast forward fetch' ' +test_expect_success 'non-fast-forward fetch' ' test_must_fail git fetch . master:side 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 997b2db827..dd2ee842e0 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -29,6 +29,18 @@ test_expect_success 'checking the results' ' diff file cloned/file ' +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 && @@ -80,20 +92,47 @@ 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 && @@ -110,4 +149,15 @@ test_expect_success 'pull --rebase dies early with dirty working directory' ' ' +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..83e2e8ab80 --- /dev/null +++ b/t/t5521-pull-options.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='pull options' + +. ./test-lib.sh + +D=`pwd` + +test_expect_success 'setup' ' + mkdir parent && + (cd parent && git init && + echo one >file && git add file && + git commit -m one) +' + +cd "$D" + +test_expect_success 'git pull -q' ' + mkdir clonedq && + cd clonedq && + git pull -q "$D/parent" >out 2>err && + test ! -s out +' + +cd "$D" + +test_expect_success 'git pull' ' + mkdir cloned && + cd cloned && + git pull "$D/parent" >out 2>err && + test -s out +' +cd "$D" + +test_expect_success 'git pull -v' ' + mkdir clonedv && + cd clonedv && + git pull -v "$D/parent" >out 2>err && + test -s out +' + +cd "$D" + +test_expect_success 'git pull -v -q' ' + mkdir clonedvq && + cd clonedvq && + git pull -v -q "$D/parent" >out 2>err && + test ! -s out +' + +cd "$D" + +test_expect_success 'git pull -q -v' ' + mkdir clonedqv && + cd clonedqv && + git pull -q -v "$D/parent" >out 2>err && + test -s out +' + +test_done diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh new file mode 100755 index 0000000000..7206817ca1 --- /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 + say '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 index 1a15817cd5..a696b8791b 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -30,11 +30,12 @@ test_expect_success 'fsck fails' ' test_must_fail git fsck ' -test_expect_success 'upload-pack fails due to error in pack-objects' ' +test_expect_success 'upload-pack fails due to error in pack-objects packing' ' ! echo "0032want $(git rev-parse HEAD) 00000009done -0000" | git-upload-pack . > /dev/null 2> output.err && +0000" | git upload-pack . > /dev/null 2> output.err && + grep "unable to read" output.err && grep "pack-objects died" output.err ' @@ -51,9 +52,21 @@ test_expect_success 'fsck fails' ' test_expect_success 'upload-pack fails due to error in rev-list' ' ! echo "0032want $(git rev-parse HEAD) +0034shallow $(git rev-parse HEAD^)00000009done +0000" | git upload-pack . > /dev/null 2> output.err && + # 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' ' + + ! echo "0032want $(git rev-parse HEAD) 00000009done -0000" | git-upload-pack . > /dev/null 2> output.err && - grep "waitpid (async) failed" output.err +0000" | git upload-pack . > /dev/null 2> output.err && + grep "bad tree object" output.err && + grep "pack-objects died" output.err ' test_expect_success 'create empty repository' ' 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 index f8c17cd96c..bb18f8bfc4 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -3,30 +3,23 @@ # Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at> # -test_description='test http-push +test_description='test WebDAV http-push This test runs various sanity checks on http-push.' . ./test-lib.sh -ROOT_PATH="$PWD" -LIB_HTTPD_DAV=t - if git http-push > /dev/null 2>&1 || [ $? -eq 128 ] then say "skipping test, USE_CURL_MULTI is not defined" test_done - exit fi -. ../lib-httpd.sh - -if ! start_httpd >&3 2>&4 -then - say "skipping test, web server setup failed" - test_done - exit -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" && @@ -41,27 +34,80 @@ test_expect_success 'setup remote repository' ' git clone --bare test_repo test_repo.git && cd test_repo.git && git --bare update-server-info && - chmod +x hooks/post-update && + 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/test_repo.git test_repo_clone + git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone ' -test_expect_failure 'push to remote repository' ' +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 && - [ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ] + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD = $(git rev-parse --verify HEAD)) ' -test_expect_failure 'create and delete remote branch' ' +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 && @@ -69,13 +115,28 @@ test_expect_failure 'create and delete remote branch' ' test_tick && git commit -m dev && git push origin dev && - git fetch && git push origin :dev && - git branch -d -r origin/dev && - git fetch && 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] " + +' + stop_httpd test_done diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh new file mode 100755 index 0000000000..53f54a2789 --- /dev/null +++ b/t/t5541-http-push.sh @@ -0,0 +1,132 @@ +#!/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 + say '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" +' + +test_expect_success 'clone remote repository' ' + cd "$ROOT_PATH" && + 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_expect_success 'non-fast-forward push fails' ' + cd "$ROOT_PATH"/test_repo_clone && + git checkout master && + echo "changed" > path2 && + git commit -a -m path2 --amend && + + HEAD=$(git rev-parse --verify HEAD) && + !(git push -v origin >output 2>&1) && + (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && + test $HEAD != $(git rev-parse --verify HEAD)) +' + +test_expect_success 'non-fast-forward push show ref status' ' + grep "^ ! \[rejected\][ ]*master -> master (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 +' + +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. + !(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..8cfce969bc --- /dev/null +++ b/t/t5550-http-fetch.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='test dumb fetching over http via static file' +. ./test-lib.sh + +if test -n "$NO_CURL"; then + say 'skipping test, git built without http support' + 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 '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..7faa31a299 --- /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 + say '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..8c6d0b2f20 --- /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 + say '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 3c013e2b6a..ee06d28649 100755 --- a/t/t5600-clone-fail-cleanup.sh +++ b/t/t5600-clone-fail-cleanup.sh @@ -3,9 +3,9 @@ # 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.' @@ -13,7 +13,7 @@ remove the directory before attempting a clone again.' test_expect_success \ 'clone of non-existent source should fail' \ - 'test_must_fail git-clone foo bar' + 'test_must_fail git clone foo bar' test_expect_success \ 'failed clone should not leave a directory' \ @@ -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_success \ 'clone of non-existent (relative to $PWD) source should fail' \ - 'test_must_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 index d785b3df78..214756731b 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -31,6 +31,12 @@ test_expect_success 'clone with excess parameters (2)' ' ' +test_expect_success 'output from clone' ' + rm -fr dst && + git clone -n "file://$(pwd)/src" dst >output && + test $(grep Initialized output | wc -l) = 1 +' + test_expect_success 'clone does not keep pack' ' rm -fr dst && @@ -70,4 +76,104 @@ test_expect_success 'clone creates intermediate directories for bare repo' ' ' +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_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/t5701-clone-local.sh b/t/t5701-clone-local.sh index 8dfaaa456e..8b4c356cd2 100755 --- a/t/t5701-clone-local.sh +++ b/t/t5701-clone-local.sh @@ -11,8 +11,8 @@ test_expect_success 'preparing origin repository' ' 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 HEAD && - git bundle create b2.bundle --all && + git bundle create b1.bundle --all && + git bundle create b2.bundle master && mkdir dir && cp b1.bundle dir/b3 cp b1.bundle b4 @@ -116,4 +116,32 @@ test_expect_success 'bundle clone with nonexistent HEAD' ' 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 index 328e4d9a33..02cb024723 100755 --- a/t/t5702-clone-options.sh +++ b/t/t5702-clone-options.sh @@ -19,4 +19,18 @@ test_expect_success 'clone -o' ' ' +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..a8f4419e61 --- /dev/null +++ b/t/t5704-bundle.sh @@ -0,0 +1,33 @@ +#!/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_done diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh new file mode 100755 index 0000000000..adfaae8c5b --- /dev/null +++ b/t/t5705-clone-2gb.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='Test cloning a repository larger than 2 gigabyte' +. ./test-lib.sh + +test -z "$GIT_TEST_CLONE_2GB" && +say "Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" && +test_done && +exit + +test_expect_success 'setup' ' + + git config pack.compression 0 && + git config pack.depth 0 && + blobsize=$((20*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' ' + + git clone --bare --no-hardlinks . clone + +' + +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/t6000lib.sh b/t/t6000lib.sh index f55627b641..985d517a1c 100755..100644 --- a/t/t6000lib.sh +++ b/t/t6000lib.sh @@ -1,3 +1,5 @@ +: included from 6002 and others + [ -d .git/refs/tags ] || mkdir -p .git/refs/tags :> sed.script diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index 8f5de097ec..b4e8fbaa5e 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -5,7 +5,7 @@ test_description='Tests git rev-list --bisect functionality' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions # usage: test_bisection max-diff bisect-option head ^prune... # diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh index 5daa0be8cc..2c73f2da7b 100755 --- a/t/t6003-rev-list-topo-order.sh +++ b/t/t6003-rev-list-topo-order.sh @@ -6,7 +6,7 @@ test_description='Tests git rev-list --topo-order functionality' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions list_duplicates() { diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index 9176484db2..b0047d3c6b 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -6,19 +6,26 @@ test_description='git rev-list --pretty=format test' 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" +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 && +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 @@ -101,6 +108,13 @@ 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 @@ -110,7 +124,7 @@ 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 + echo change2 >foo && git commit -a -F commit-msg ' test_format complex-encoding %e <<'EOF' @@ -139,6 +153,12 @@ 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) && @@ -149,4 +169,44 @@ test_expect_success 'empty email' ' } ' +test_expect_success 'del LF before empty (1)' ' + git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual && + test $(wc -l <actual) = 2 +' + +test_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 '"%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 '%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_done diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh index b6e57b2426..0144d9e858 100755 --- a/t/t6010-merge-base.sh +++ b/t/t6010-merge-base.sh @@ -108,4 +108,70 @@ test_expect_success 'compute merge-base (all)' \ 'MB=$(git merge-base --all PL PR) && expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"' +# 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 '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 '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/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..8d3fa7d014 --- /dev/null +++ b/t/t6018-rev-list-glob.sh @@ -0,0 +1,195 @@ +#!/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 && + git update-ref refs/remotes/foo/baz master +' + +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 --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 --remotes=foo' ' + + compare rev-list "foo/baz" "--remotes=foo" + +' + +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/t6023-merge-file.sh b/t/t6023-merge-file.sh index f674c48cab..6291307cd0 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -54,6 +54,12 @@ 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" @@ -136,12 +142,12 @@ 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 ../test4012.png new1.txt 2> merge.err && + 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 +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' ' @@ -150,8 +156,8 @@ test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' ' ' -sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit;/" < new6.txt > new8.txt -sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt +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' ' @@ -161,4 +167,48 @@ test_expect_success 'ZEALOUS_ALNUM' ' ' +cat >expect <<\EOF +Dominus regit me, +<<<<<<< new8.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; +======= +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 +' + test_done diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index 802d0d06eb..b3fbf659c0 100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -65,18 +65,18 @@ test_expect_success "combined merge conflicts" " " cat > expect << EOF -<<<<<<< HEAD:a1 +<<<<<<< HEAD F ======= G ->>>>>>> G:a1 +>>>>>>> G EOF 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 @@ -93,8 +93,30 @@ test_expect_success 'refuse to merge binary files' ' git add binary-file && git commit -m binary2 && test_must_fail git merge F > merge.out 2> merge.err && - grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \ - 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 fc58456a11..433c4de08f 100755 --- a/t/t6025-merge-symlinks.sh +++ b/t/t6025-merge-symlinks.sh @@ -5,7 +5,7 @@ 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 @@ -15,25 +15,25 @@ test_expect_success \ git config core.symlinks false && > file && git add file && -git-commit -m initial && +git commit -m initial && git branch b-symlink && git branch b-file && -l=$(echo -n file | git-hash-object -t blob -w --stdin) && +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=$(echo -n file-different | git-hash-object -t blob -w --stdin) && +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 && +git commit -m b-symlink && +git checkout b-file && echo plain-file > symlink && git add symlink && -git-commit -m b-file' +git commit -m b-file' test_expect_success \ 'merge master into b-symlink, which has a different symbolic link' ' -git-checkout b-symlink && -test_must_fail git-merge master' +git checkout b-symlink && +test_must_fail git merge master' test_expect_success \ 'the merge result must be a file' ' @@ -41,8 +41,8 @@ test -f symlink' test_expect_success \ 'merge master into b-file, which has a file instead of a symbolic link' ' -git-reset --hard && git-checkout b-file && -test_must_fail 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' ' @@ -50,9 +50,9 @@ test -f symlink' test_expect_success \ 'merge b-file, which has a file instead of a symbolic link, into master' ' -git-reset --hard && -git-checkout master && -test_must_fail 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 index 56fc341768..5e439972be 100755 --- a/t/t6026-merge-attr.sh +++ b/t/t6026-merge-attr.sh @@ -70,6 +70,18 @@ test_expect_success 'check merge result in working tree' ' ' +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 @@ -106,9 +118,9 @@ test_expect_success 'custom merge backend' ' 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) && + 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 && @@ -133,13 +145,35 @@ test_expect_success 'custom merge backend' ' 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) && + 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 index 92ca1f0f8c..b519626ca0 100755 --- a/t/t6027-merge-binary.sh +++ b/t/t6027-merge-binary.sh @@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files' test_expect_success setup ' - cat ../test4012.png >m && + cat "$TEST_DIRECTORY"/test4012.png >m && git add m && git ls-files -s | sed -e "s/ 0 / 1 /" >E1 && test_tick && diff --git a/t/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh index f8f3e3ff2c..a91644e3b2 100755 --- a/t/t6028-merge-up-to-date.sh +++ b/t/t6028-merge-up-to-date.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='merge fast forward and up to date' +test_description='merge fast-forward and up to date' . ./test-lib.sh diff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh index 5bbfa44e8d..3900d9f61f 100755 --- a/t/t6029-merge-subtree.sh +++ b/t/t6029-merge-subtree.sh @@ -52,6 +52,7 @@ test_expect_success 'initial merge' ' 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" @@ -65,9 +66,10 @@ test_expect_success 'merge update' ' 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 master && + git pull -s subtree gui master2 && git ls-files -s >actual && ( echo "100644 $o3 0 git-gui/git-gui.sh" @@ -76,4 +78,47 @@ test_expect_success 'merge update' ' 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 index 0626544823..c51865fdbc 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -2,7 +2,7 @@ # # Copyright (c) 2007 Christian Couder # -test_description='Tests git-bisect functionality' +test_description='Tests git bisect functionality' exec </dev/null @@ -23,7 +23,7 @@ add_line_into_file() fi test_tick - git-commit --quiet -m "$MSG" $_file + git commit --quiet -m "$MSG" $_file } HASH1= @@ -76,7 +76,7 @@ test_expect_success 'bisect fails if given any junk instead of revs' ' 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_must_fail ls .git/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 && @@ -175,7 +175,7 @@ test_expect_success 'bisect skip: successfull result' ' git bisect start $HASH4 $HASH1 && git bisect skip && git bisect bad > my_bisect_log.txt && - grep "$HASH2 is first bad commit" my_bisect_log.txt && + grep "$HASH2 is the first bad commit" my_bisect_log.txt && git bisect reset ' @@ -224,6 +224,31 @@ test_expect_success 'bisect skip: cannot tell between 2 commits' ' 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 \ @@ -236,7 +261,7 @@ test_expect_success \ git bisect good $HASH1 && git bisect bad $HASH4 && git bisect run ./test_script.sh > my_bisect_log.txt && - grep "$HASH3 is first bad commit" 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 @@ -249,7 +274,7 @@ test_expect_success \ chmod +x test_script.sh && git bisect start $HASH4 $HASH1 && git bisect run ./test_script.sh > my_bisect_log.txt && - grep "$HASH4 is first bad commit" 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 @@ -262,14 +287,14 @@ test_expect_success 'bisect skip: add line and then a new test' ' git bisect start $HASH5 $HASH1 && git bisect skip && git bisect good > my_bisect_log.txt && - grep "$HASH5 is first bad commit" 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 first bad commit" my_bisect_log.txt && + grep "$HASH5 is the first bad commit" my_bisect_log.txt && git bisect reset ' @@ -310,11 +335,28 @@ test_expect_success 'bisect run & skip: find first bad' ' chmod +x test_script.sh && git bisect start $HASH7 $HASH1 && git bisect run ./test_script.sh > my_bisect_log.txt && - grep "$HASH6 is first bad commit" my_bisect_log.txt + grep "$HASH6 is the first bad commit" my_bisect_log.txt ' -test_expect_success 'bisect starting with a detached HEAD' ' +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) && @@ -343,13 +385,188 @@ test_expect_success 'bisect does not create a "bisect" branch' ' rev_hash6=$(git rev-parse --verify HEAD) && test "$rev_hash6" = "$HASH6" && git bisect good > my_bisect_log.txt && - grep "$HASH7 is first bad commit" 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_done diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh index 8073e0c3ef..8a3304fb0b 100755 --- a/t/t6031-merge-recursive.sh +++ b/t/t6031-merge-recursive.sh @@ -3,8 +3,10 @@ test_description='merge-recursive: handle file mode' . ./test-lib.sh -# Note that we follow "chmod +x F" with "update-index --chmod=+x F" to -# help filesystems that do not have the executable bit. +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 && @@ -15,11 +17,14 @@ test_expect_success 'mode change in one branch: keep changed version' ' git add dummy && git commit -m a && git checkout -b b1 master && - chmod +x file1 && - git update-index --chmod=+x file1 && + 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 ' @@ -28,8 +33,7 @@ test_expect_success 'mode change in both branches: expect conflict' ' git checkout -b a2 master && : >file2 && H=$(git hash-object file2) && - chmod +x file2 && - git update-index --add --chmod=+x file2 && + test_chmod +x file2 && git commit -m a2 && git checkout -b b2 master && : >file2 && @@ -46,6 +50,10 @@ test_expect_success 'mode change in both branches: expect conflict' ' 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 ' diff --git a/t/t6033-merge-crlf.sh b/t/t6033-merge-crlf.sh index 75d9602de4..e8d65eefb5 100755 --- a/t/t6033-merge-crlf.sh +++ b/t/t6033-merge-crlf.sh @@ -1,13 +1,5 @@ #!/bin/sh -append_cr () { - sed -e 's/$/Q/' | tr Q '\015' -} - -remove_cr () { - tr '\015' Q | sed -e 's/Q$//' -} - test_description='merge conflict in crlf repo b---M 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..3202e1de6d --- /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 + say '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 index aac212e936..1785e178a4 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -29,7 +29,9 @@ test_expect_success setup ' 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' @@ -53,7 +55,13 @@ test_expect_success 'checkout' ' ( cd test && git checkout b1 ) >actual && - grep -e "have 1 and 1 different" 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' ' @@ -61,10 +69,45 @@ test_expect_success 'status' ' cd test && git checkout b1 >/dev/null && # reports nothing to commit - test_must_fail git status + test_must_fail git commit --dry-run ) >actual && - grep -e "have 1 and 1 different" 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..203ffdb17a --- /dev/null +++ b/t/t6050-replace.sh @@ -0,0 +1,224 @@ +#!/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_done diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index efc831363e..f105fab98e 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -6,7 +6,7 @@ test_description='Test git rev-parse with different parent options' . ./test-lib.sh -. ../t6000lib.sh # t6xxx specific functions +. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions date >path0 git update-index --add path0 @@ -28,6 +28,8 @@ test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != 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_expect_success 'repack for next test' 'git repack -a -d' test_expect_success 'short SHA-1 works' ' diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 2fb672c3b4..065deadc29 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -31,57 +31,59 @@ check_describe () { test_expect_success setup ' test_tick && - echo one >file && git add file && git-commit -m initial && + 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 && + 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 && + 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 && + git tag -a -m D D && 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 + git commit -m x ' @@ -90,16 +92,28 @@ check_describe A-* HEAD^ check_describe D-* HEAD^^ check_describe A-* HEAD^^2 check_describe B HEAD^^2^ +check_describe D-* 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 ' @@ -117,6 +131,20 @@ test_expect_success 'rename tag Q back to 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 && diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index bc74349416..42f6fff373 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -83,13 +83,13 @@ test_expect_success 'merge-msg test #1' ' ' cat >expected <<EOF -Merge branch 'left' of ../$test +Merge branch 'left' of $(pwd) EOF test_expect_success 'merge-msg test #2' ' git checkout master && - git fetch ../"$test" left && + git fetch "$(pwd)" left && git fmt-merge-msg <.git/FETCH_HEAD >actual && test_cmp expected actual @@ -208,4 +208,36 @@ test_expect_success 'merge-msg test #5-2' ' 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 && + setdate && + 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 && + setdate && + 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_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index a3c8941c72..8052c86ad3 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -26,6 +26,13 @@ test_expect_success 'Create sample commit with known timestamp' ' 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 ;; @@ -39,6 +46,7 @@ test_atom() { } 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 @@ -68,6 +76,7 @@ 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 @@ -97,27 +106,27 @@ 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_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 + 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 + 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 + test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads ' cat >expected <<\EOF @@ -203,27 +212,30 @@ test_expect_success 'Check format "rfc2822" date fields output' ' 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 && + 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 && + 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 @@ -244,6 +256,7 @@ test_expect_success 'Quoting style: python' ' cat >expected <<\EOF "refs/heads/master" +"refs/remotes/origin/master" "refs/tags/testtag" EOF @@ -262,4 +275,79 @@ for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do " 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 +' + +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 336cfaa1c5..65a35d94a0 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -6,9 +6,9 @@ test_description='git mv in subdirs' test_expect_success \ 'prepare reference tree' \ 'mkdir path0 path1 && - cp ../../COPYING path0/COPYING && + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && git add path0/COPYING && - git-commit -m add -a' + git commit -m add -a' test_expect_success \ 'moving the file out of subdirectory' \ @@ -17,7 +17,7 @@ test_expect_success \ # 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' \ @@ -31,7 +31,7 @@ test_expect_success \ # 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' \ @@ -39,10 +39,43 @@ test_expect_success \ 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 && + 'cp "$TEST_DIRECTORY"/../README path0/README && git add path0/README && - git-commit -m add2 -a' + git commit -m add2 -a' test_expect_success \ 'moving whole subdirectory' \ @@ -50,7 +83,7 @@ test_expect_success \ test_expect_success \ 'commiting the change' \ - 'git-commit -m dir-move -a' + 'git commit -m dir-move -a' test_expect_success \ 'checking the commit' \ @@ -69,7 +102,7 @@ test_expect_success \ test_expect_success \ 'commiting the change' \ - 'git-commit -m dir-move -a' + 'git commit -m dir-move -a' test_expect_success \ 'checking the commit' \ @@ -156,4 +189,70 @@ test_expect_success 'absolute pathname outside should fail' '( )' +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 index c8b4f65f38..ebae1522c8 100755 --- a/t/t7002-grep.sh +++ b/t/t7002-grep.sh @@ -8,6 +8,16 @@ 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 @@ -16,15 +26,25 @@ test_expect_success setup ' 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 && - git add file x y z 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 @@ -43,6 +63,12 @@ do diff 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 @@ -108,9 +134,389 @@ do ' test_expect_success "grep -c $L (no /dev/null)" ' - ! git grep -c test $H | grep -q /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 --grep=Thu --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 '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/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index a0ab096c8f..0da13a8d6b 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-filter-branch' +test_description='git filter-branch' . ./test-lib.sh make_commit () { @@ -32,22 +32,40 @@ test_expect_success 'setup' ' H=$(git rev-parse H) test_expect_success 'rewrite identically' ' - git-filter-branch branch + 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) + (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 + git filter-branch -f --tree-filter "mv d doh || :" HEAD ' test_expect_success 'test that the file was renamed' ' @@ -58,7 +76,7 @@ test_expect_success 'test that the file was renamed' ' ' test_expect_success 'rewrite, renaming a specific directory' ' - git-filter-branch -f --tree-filter "mv dir diroh || :" HEAD + git filter-branch -f --tree-filter "mv dir diroh || :" HEAD ' test_expect_success 'test that the directory was renamed' ' @@ -73,7 +91,7 @@ test_expect_success 'test that the directory was renamed' ' git tag oldD HEAD~4 test_expect_success 'rewrite one branch, keeping a side branch' ' git branch modD oldD && - git-filter-branch -f --tree-filter "mv b boh || :" D..modD + git filter-branch -f --tree-filter "mv b boh || :" D..modD ' test_expect_success 'common ancestor is still common (unchanged)' ' @@ -96,13 +114,17 @@ test_expect_success 'filter subdirectory only' ' test_tick && git commit -m "again not subdir" && git branch sub && - git-filter-branch -f --subdirectory-filter subdir refs/heads/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 + 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' ' @@ -120,7 +142,7 @@ test_expect_success 'more setup' ' test_expect_success 'use index-filter to move into a subdirectory' ' git branch directorymoved && - git-filter-branch -f --index-filter \ + git filter-branch -f --index-filter \ "git ls-files -s | sed \"s-\\t-&newsubdir/-\" | GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \ git update-index --index-info && @@ -129,7 +151,7 @@ test_expect_success 'use index-filter to move into a subdirectory' ' 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_must_fail git filter-branch -f --msg-filter false HEAD && test $old = $(git rev-parse HEAD) && rm -rf .git-rewrite ' @@ -140,7 +162,7 @@ test_expect_success 'author information is preserved' ' test_tick && GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips && git branch preserved-author && - git-filter-branch -f --msg-filter "cat; \ + git filter-branch -f --msg-filter "cat; \ test \$GIT_COMMIT != $(git rev-parse master) || \ echo Hallo" \ preserved-author && @@ -152,7 +174,7 @@ test_expect_success "remove a certain author's commits" ' test_tick && git commit -m i i && git branch removed-author && - git-filter-branch -f --commit-filter "\ + git filter-branch -f --commit-filter "\ if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\ then\ skip_commit \"\$@\"; @@ -250,4 +272,77 @@ test_expect_success 'Tag name filtering strips gpg signature' ' 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 index bc7ce2cbbb..73dbc4360b 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Carlos Rica # -test_description='git-tag +test_description='git tag Tests for operations with tags.' @@ -22,25 +22,25 @@ test_expect_success 'listing all tags in an empty tree should succeed' ' ' 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 `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 && + 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 && + 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 && + test_must_fail git tag mytagnorev aaaaaaaaaaa && ! tag_exists mytagnorev ' @@ -54,32 +54,32 @@ test_expect_success 'creating a tag using default HEAD should succeed' ' ' test_expect_success 'listing all tags if one exists should succeed' ' - git-tag -l && - git-tag + 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 + 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' + 'git tag -l mytag' test_expect_success \ 'listing a tag using a matching pattern should output that tag' \ - 'test `git-tag -l mytag` = mytag' + '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' + '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' + 'test `git tag -l xxx | wc -l` -eq 0' # special cases for creating tags: @@ -89,13 +89,13 @@ test_expect_success \ test_expect_success \ 'trying to create a tag with a non-valid name should fail' ' - test `git-tag -l | wc -l` -eq 1 && + 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 `git tag -l | wc -l` -eq 1 ' test_expect_success 'creating a tag using HEAD directly should succeed' ' @@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' ' test_expect_success 'trying to delete an unknown tag should fail' ' ! tag_exists unknown-tag && - test_must_fail git-tag -d unknown-tag + test_must_fail git tag -d unknown-tag ' cat >expect <<EOF @@ -117,7 +117,7 @@ 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 -d && git tag -l > actual && test_cmp expect actual ' @@ -125,7 +125,7 @@ test_expect_success \ 'deleting two existing tags in one command should succeed' ' tag_exists mytag && tag_exists myhead && - git-tag -d mytag myhead && + git tag -d mytag myhead && ! tag_exists mytag && ! tag_exists myhead ' @@ -133,7 +133,7 @@ test_expect_success \ test_expect_success \ 'creating a tag with the name of another deleted one should succeed' ' ! tag_exists mytag && - git-tag mytag && + git tag mytag && tag_exists mytag ' @@ -141,13 +141,13 @@ 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 && + 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' + 'test_must_fail git tag -d mytag' # listing various tags with pattern matching: @@ -185,8 +185,9 @@ cba EOF test_expect_success \ 'listing tags with substring as pattern must print those matching' ' - git-tag -l "*a*" > actual && - test_cmp expect actual + rm *a* && + git tag -l "*a*" > current && + test_cmp expect current ' cat >expect <<EOF @@ -195,7 +196,7 @@ v1.0.1 EOF test_expect_success \ 'listing tags with a suffix as pattern must print those matching' ' - git-tag -l "*.1" > actual && + git tag -l "*.1" > actual && test_cmp expect actual ' @@ -205,7 +206,7 @@ t211 EOF test_expect_success \ 'listing tags with a prefix as pattern must print those matching' ' - git-tag -l "t21*" > actual && + git tag -l "t21*" > actual && test_cmp expect actual ' @@ -214,7 +215,7 @@ a1 EOF test_expect_success \ 'listing tags using a name as pattern must print that one matching' ' - git-tag -l a1 > actual && + git tag -l a1 > actual && test_cmp expect actual ' @@ -223,7 +224,7 @@ v1.0 EOF test_expect_success \ 'listing tags using a name as pattern must print that one matching' ' - git-tag -l v1.0 > actual && + git tag -l v1.0 > actual && test_cmp expect actual ' @@ -233,14 +234,14 @@ v1.1.3 EOF test_expect_success \ 'listing tags with ? in the pattern should print those matching' ' - git-tag -l "v1.?.?" > actual && + 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 && + git tag -l "v.*" > actual && test_cmp expect actual ' @@ -252,7 +253,7 @@ v1.1.3 EOF test_expect_success \ 'listing tags using v* should print only those having v' ' - git-tag -l "v*" > actual && + git tag -l "v*" > actual && test_cmp expect actual ' @@ -260,21 +261,21 @@ test_expect_success \ test_expect_success \ 'a non-annotated tag created without parameters should point to HEAD' ' - git-tag non-annotated-tag && + 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_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_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' + 'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2' # creating annotated tags: @@ -300,7 +301,7 @@ 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 && + git tag -m "A message" annotated-tag && get_tag_msg annotated-tag >actual && test_cmp expect actual ' @@ -313,7 +314,7 @@ 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 && + git tag -F msgfile file-annotated-tag && get_tag_msg file-annotated-tag >actual && test_cmp expect actual ' @@ -325,7 +326,7 @@ 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 && + git tag -F - stdin-annotated-tag <inputmsg && get_tag_msg stdin-annotated-tag >actual && test_cmp expect actual ' @@ -334,7 +335,7 @@ 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 && + test_must_fail git tag -F nonexistingfile notag && ! tag_exists notag ' @@ -343,11 +344,11 @@ test_expect_success \ echo "message file 1" >msgfile1 && echo "message file 2" >msgfile2 && ! tag_exists msgtag && - test_must_fail git-tag -m "message 1" -F msgfile1 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 && + test_must_fail git tag -F msgfile1 -m "message 1" msgtag && ! tag_exists msgtag && - test_must_fail git-tag -m "message 1" -F msgfile1 \ + test_must_fail git tag -m "message 1" -F msgfile1 \ -m "message 2" msgtag && ! tag_exists msgtag ' @@ -357,7 +358,7 @@ test_expect_success \ 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 && + git tag -m "" empty-annotated-tag && get_tag_msg empty-annotated-tag >actual && test_cmp expect actual ' @@ -366,7 +367,7 @@ test_expect_success \ 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 && + git tag -F emptyfile emptyfile-annotated-tag && get_tag_msg emptyfile-annotated-tag >actual && test_cmp expect actual ' @@ -387,7 +388,7 @@ 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 && + git tag -F blanksfile blanks-annotated-tag && get_tag_msg blanks-annotated-tag >actual && test_cmp expect actual ' @@ -395,7 +396,7 @@ test_expect_success \ 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 && + git tag -m " " blank-annotated-tag && get_tag_msg blank-annotated-tag >actual && test_cmp expect actual ' @@ -406,7 +407,7 @@ 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 && + git tag -F blankfile blankfile-annotated-tag && get_tag_msg blankfile-annotated-tag >actual && test_cmp expect actual ' @@ -415,7 +416,7 @@ 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 && + git tag -F blanknonlfile blanknonlfile-annotated-tag && get_tag_msg blanknonlfile-annotated-tag >actual && test_cmp expect actual ' @@ -450,7 +451,7 @@ Last line. EOF test_expect_success \ 'creating a tag using a -F messagefile with #comments should succeed' ' - git-tag -F commentsfile comments-annotated-tag && + git tag -F commentsfile comments-annotated-tag && get_tag_msg comments-annotated-tag >actual && test_cmp expect actual ' @@ -458,7 +459,7 @@ test_expect_success \ 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 && + git tag -m "#comment" comment-annotated-tag && get_tag_msg comment-annotated-tag >actual && test_cmp expect actual ' @@ -469,7 +470,7 @@ 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 && + git tag -F commentfile commentfile-annotated-tag && get_tag_msg commentfile-annotated-tag >actual && test_cmp expect actual ' @@ -478,7 +479,7 @@ 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 && + git tag -F commentnonlfile commentnonlfile-annotated-tag && get_tag_msg commentnonlfile-annotated-tag >actual && test_cmp expect actual ' @@ -487,51 +488,51 @@ test_expect_success \ test_expect_success \ 'listing the one-line message of a non-signed tag should succeed' ' - git-tag -m "A msg" tag-one-line && + git tag -m "A msg" tag-one-line && echo "tag-one-line" >expect && - git-tag -l | grep "^tag-one-line" >actual && + git tag -l | grep "^tag-one-line" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^tag-one-line" >actual && + git tag -n0 -l | grep "^tag-one-line" >actual && test_cmp expect actual && - git-tag -n0 -l tag-one-line >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 && + git tag -n1 -l | grep "^tag-one-line" >actual && test_cmp expect actual && - git-tag -n -l | grep "^tag-one-line" >actual && + git tag -n -l | grep "^tag-one-line" >actual && test_cmp expect actual && - git-tag -n1 -l tag-one-line >actual && + git tag -n1 -l tag-one-line >actual && test_cmp expect actual && - git-tag -n2 -l tag-one-line >actual && + git tag -n2 -l tag-one-line >actual && test_cmp expect actual && - git-tag -n999 -l tag-one-line >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 && + git tag -m "" tag-zero-lines && echo "tag-zero-lines" >expect && - git-tag -l | grep "^tag-zero-lines" >actual && + git tag -l | grep "^tag-zero-lines" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^tag-zero-lines" >actual && + git tag -n0 -l | grep "^tag-zero-lines" >actual && test_cmp expect actual && - git-tag -n0 -l tag-zero-lines >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 && + git tag -n1 -l | grep "^tag-zero-lines" >actual && test_cmp expect actual && - git-tag -n -l | grep "^tag-zero-lines" >actual && + git tag -n -l | grep "^tag-zero-lines" >actual && test_cmp expect actual && - git-tag -n1 -l tag-zero-lines >actual && + git tag -n1 -l tag-zero-lines >actual && test_cmp expect actual && - git-tag -n2 -l tag-zero-lines >actual && + git tag -n2 -l tag-zero-lines >actual && test_cmp expect actual && - git-tag -n999 -l tag-zero-lines >actual && + git tag -n999 -l tag-zero-lines >actual && test_cmp expect actual ' @@ -540,92 +541,91 @@ 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 && + git tag -F annotagmsg tag-lines && echo "tag-lines" >expect && - git-tag -l | grep "^tag-lines" >actual && + git tag -l | grep "^tag-lines" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^tag-lines" >actual && + git tag -n0 -l | grep "^tag-lines" >actual && test_cmp expect actual && - git-tag -n0 -l tag-lines >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 && + git tag -n1 -l | grep "^tag-lines" >actual && test_cmp expect actual && - git-tag -n -l | grep "^tag-lines" >actual && + git tag -n -l | grep "^tag-lines" >actual && test_cmp expect actual && - git-tag -n1 -l tag-lines >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 && + git tag -n2 -l | grep "^ *tag.line" >actual && test_cmp expect actual && - git-tag -n2 -l tag-lines >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 && + git tag -n3 -l | grep "^ *tag.line" >actual && test_cmp expect actual && - git-tag -n3 -l tag-lines >actual && + git tag -n3 -l tag-lines >actual && test_cmp expect actual && - git-tag -n4 -l | grep "^ *tag.line" >actual && + git tag -n4 -l | grep "^ *tag.line" >actual && test_cmp expect actual && - git-tag -n4 -l tag-lines >actual && + git tag -n4 -l tag-lines >actual && test_cmp expect actual && - git-tag -n99 -l | grep "^ *tag.line" >actual && + git tag -n99 -l | grep "^ *tag.line" >actual && test_cmp expect actual && - git-tag -n99 -l tag-lines >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 +gpg --version >/dev/null 2>/dev/null if [ $? -eq 127 ]; then - echo "gpg not found - skipping tag signing and verification tests" - test_done - exit + 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 \ +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_must_fail git tag -v annotated-tag ' -test_expect_success \ +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_must_fail git tag -v file-annotated-tag ' -test_expect_success \ +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 + test_must_fail git tag -v annotated-tag file-annotated-tag ' # creating and verifying signed tags: -# 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'*) - echo "Skipping signed tag tests, because a bug in 1.0.6 version" - test_done - exit - ;; -esac - # 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 ../t7004 ./gpghome +cp -R "$TEST_DIRECTORY"/t7004 ./gpghome chmod 0700 gpghome GNUPGHOME="$(pwd)/gpghome" export GNUPGHOME @@ -633,8 +633,8 @@ 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 'creating a signed tag with -m message should succeed' ' - git-tag -s -m "A signed tag message" signed-tag && +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 ' @@ -642,7 +642,7 @@ test_expect_success 'creating a signed tag with -m message should succeed' ' get_tag_header u-signed-tag $commit commit $time >expect echo 'Another message' >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success 'sign with a given key id' ' +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 && @@ -650,14 +650,14 @@ test_expect_success 'sign with a given key id' ' ' -test_expect_success 'sign with an unknown id (1)' ' +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 'sign with an unknown id (2)' ' +test_expect_success GPG 'sign with an unknown id (2)' ' test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag @@ -674,8 +674,8 @@ chmod +x fakeeditor get_tag_header implied-sign $commit commit $time >expect ./fakeeditor >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success '-u implies signed tag' ' - GIT_EDITOR=./fakeeditor git-tag -u CDDE430D implied-sign && +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 ' @@ -687,9 +687,9 @@ EOF get_tag_header file-signed-tag $commit commit $time >expect cat sigmsgfile >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with -F messagefile should succeed' ' - git-tag -s -F sigmsgfile file-signed-tag && + git tag -s -F sigmsgfile file-signed-tag && get_tag_msg file-signed-tag >actual && test_cmp expect actual ' @@ -701,8 +701,8 @@ EOF get_tag_header stdin-signed-tag $commit commit $time >expect cat siginputmsg >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success 'creating a signed tag with -F - should succeed' ' - git-tag -s -F - stdin-signed-tag <siginputmsg && +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 ' @@ -710,64 +710,64 @@ test_expect_success 'creating a signed tag with -F - should succeed' ' get_tag_header implied-annotate $commit commit $time >expect ./fakeeditor >>expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success '-s implies annotated tag' ' - GIT_EDITOR=./fakeeditor git-tag -s implied-annotate && +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 \ +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 && + test_must_fail git tag -s -F nonexistingfile nosigtag && ! tag_exists nosigtag ' -test_expect_success 'verifying a signed tag should succeed' \ - 'git-tag -v signed-tag' +test_expect_success GPG 'verifying a signed tag should succeed' \ + 'git tag -v signed-tag' -test_expect_success 'verifying two signed tags in one command should succeed' \ - 'git-tag -v signed-tag file-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 \ +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 \ + 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_must_fail git tag -v signed-tag annotated-tag file-signed-tag ' -test_expect_success 'verifying a forged tag should fail' ' +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 + 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 \ +test_expect_success GPG \ 'creating a signed tag with an empty -m message should succeed' ' - git-tag -s -m "" empty-signed-tag && + git tag -s -m "" empty-signed-tag && get_tag_msg empty-signed-tag >actual && test_cmp expect actual && - git-tag -v empty-signed-tag + 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 \ +test_expect_success GPG \ 'creating a signed tag with an empty -F messagefile should succeed' ' - git-tag -s -F sigemptyfile emptyfile-signed-tag && + 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 + git tag -v emptyfile-signed-tag ' printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile @@ -785,22 +785,22 @@ Trailing spaces Trailing blank lines EOF echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'extra blanks in the message for a signed tag should be removed' ' - git-tag -s -F sigblanksfile blanks-signed-tag && + 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 + git tag -v blanks-signed-tag ' get_tag_header blank-signed-tag $commit commit $time >expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with a blank -m message should succeed' ' - git-tag -s -m " " blank-signed-tag && + git tag -s -m " " blank-signed-tag && get_tag_msg blank-signed-tag >actual && test_cmp expect actual && - git-tag -v blank-signed-tag + git tag -v blank-signed-tag ' echo ' ' >sigblankfile @@ -808,23 +808,23 @@ echo '' >>sigblankfile echo ' ' >>sigblankfile get_tag_header blankfile-signed-tag $commit commit $time >expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with blank -F file with spaces should succeed' ' - git-tag -s -F sigblankfile blankfile-signed-tag && + 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 + 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 \ +test_expect_success GPG \ 'creating a signed tag with spaces and no newline should succeed' ' - git-tag -s -F sigblanknonlfile blanknonlfile-signed-tag && + git tag -s -F sigblanknonlfile blanknonlfile-signed-tag && get_tag_msg blanknonlfile-signed-tag >actual && test_cmp expect actual && - git-tag -v signed-tag + git tag -v signed-tag ' # messages with commented lines for signed tags: @@ -856,22 +856,22 @@ Another line. Last line. EOF echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with a -F file with #comments should succeed' ' - git-tag -s -F sigcommentsfile comments-signed-tag && + 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 + git tag -v comments-signed-tag ' get_tag_header comment-signed-tag $commit commit $time >expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with #commented -m message should succeed' ' - git-tag -s -m "#comment" comment-signed-tag && + 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 + git tag -v comment-signed-tag ' echo '#comment' >sigcommentfile @@ -879,118 +879,118 @@ echo '' >>sigcommentfile echo '####' >>sigcommentfile get_tag_header commentfile-signed-tag $commit commit $time >expect echo '-----BEGIN PGP SIGNATURE-----' >>expect -test_expect_success \ +test_expect_success GPG \ 'creating a signed tag with #commented -F messagefile should succeed' ' - git-tag -s -F sigcommentfile commentfile-signed-tag && + 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 + 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 \ +test_expect_success GPG \ 'creating a signed tag with a #comment and no newline should succeed' ' - git-tag -s -F sigcommentnonlfile commentnonlfile-signed-tag && + 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 + git tag -v commentnonlfile-signed-tag ' # listing messages for signed tags: -test_expect_success \ +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 && + git tag -s -m "A message line signed" stag-one-line && echo "stag-one-line" >expect && - git-tag -l | grep "^stag-one-line" >actual && + git tag -l | grep "^stag-one-line" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^stag-one-line" >actual && + git tag -n0 -l | grep "^stag-one-line" >actual && test_cmp expect actual && - git-tag -n0 -l stag-one-line >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 && + git tag -n1 -l | grep "^stag-one-line" >actual && test_cmp expect actual && - git-tag -n -l | grep "^stag-one-line" >actual && + git tag -n -l | grep "^stag-one-line" >actual && test_cmp expect actual && - git-tag -n1 -l stag-one-line >actual && + git tag -n1 -l stag-one-line >actual && test_cmp expect actual && - git-tag -n2 -l stag-one-line >actual && + git tag -n2 -l stag-one-line >actual && test_cmp expect actual && - git-tag -n999 -l stag-one-line >actual && + git tag -n999 -l stag-one-line >actual && test_cmp expect actual ' -test_expect_success \ +test_expect_success GPG \ 'listing the zero-lines message of a signed tag should succeed' ' - git-tag -s -m "" stag-zero-lines && + git tag -s -m "" stag-zero-lines && echo "stag-zero-lines" >expect && - git-tag -l | grep "^stag-zero-lines" >actual && + git tag -l | grep "^stag-zero-lines" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^stag-zero-lines" >actual && + git tag -n0 -l | grep "^stag-zero-lines" >actual && test_cmp expect actual && - git-tag -n0 -l stag-zero-lines >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 && + git tag -n1 -l | grep "^stag-zero-lines" >actual && test_cmp expect actual && - git-tag -n -l | grep "^stag-zero-lines" >actual && + git tag -n -l | grep "^stag-zero-lines" >actual && test_cmp expect actual && - git-tag -n1 -l stag-zero-lines >actual && + git tag -n1 -l stag-zero-lines >actual && test_cmp expect actual && - git-tag -n2 -l stag-zero-lines >actual && + git tag -n2 -l stag-zero-lines >actual && test_cmp expect actual && - git-tag -n999 -l stag-zero-lines >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 \ +test_expect_success GPG \ 'listing many message lines of a signed tag should succeed' ' - git-tag -s -F sigtagmsg stag-lines && + git tag -s -F sigtagmsg stag-lines && echo "stag-lines" >expect && - git-tag -l | grep "^stag-lines" >actual && + git tag -l | grep "^stag-lines" >actual && test_cmp expect actual && - git-tag -n0 -l | grep "^stag-lines" >actual && + git tag -n0 -l | grep "^stag-lines" >actual && test_cmp expect actual && - git-tag -n0 -l stag-lines >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 && + git tag -n1 -l | grep "^stag-lines" >actual && test_cmp expect actual && - git-tag -n -l | grep "^stag-lines" >actual && + git tag -n -l | grep "^stag-lines" >actual && test_cmp expect actual && - git-tag -n1 -l stag-lines >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 && + git tag -n2 -l | grep "^ *stag.line" >actual && test_cmp expect actual && - git-tag -n2 -l stag-lines >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 && + git tag -n3 -l | grep "^ *stag.line" >actual && test_cmp expect actual && - git-tag -n3 -l stag-lines >actual && + git tag -n3 -l stag-lines >actual && test_cmp expect actual && - git-tag -n4 -l | grep "^ *stag.line" >actual && + git tag -n4 -l | grep "^ *stag.line" >actual && test_cmp expect actual && - git-tag -n4 -l stag-lines >actual && + git tag -n4 -l stag-lines >actual && test_cmp expect actual && - git-tag -n99 -l | grep "^ *stag.line" >actual && + git tag -n99 -l | grep "^ *stag.line" >actual && test_cmp expect actual && - git-tag -n99 -l stag-lines >actual && + git tag -n99 -l stag-lines >actual && test_cmp expect actual ' @@ -998,14 +998,14 @@ test_expect_success \ tree=$(git rev-parse HEAD^{tree}) blob=$(git rev-parse HEAD:foo) -tag=$(git rev-parse signed-tag) +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 \ +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} && + 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 ' @@ -1013,9 +1013,9 @@ test_expect_success \ 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 \ +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 && + 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 ' @@ -1023,29 +1023,29 @@ test_expect_success \ 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 \ +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 && + 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 \ - 'git-tag -s fails if gpg is misconfigured' \ +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 \ +test_expect_success GPG \ 'verify signed tag fails when public key is not present' \ - 'test_must_fail git-tag -v signed-tag' + 'test_must_fail git tag -v signed-tag' test_expect_success \ - 'git-tag -a fails if tag annotation is empty' ' + 'git tag -a fails if tag annotation is empty' ' ! (GIT_EDITOR=cat git tag -a initial-comment) ' @@ -1070,4 +1070,150 @@ test_expect_success \ 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/t7005-editor.sh b/t/t7005-editor.sh index 2d919d69ef..5257f4d261 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -4,26 +4,40 @@ test_description='GIT_EDITOR, core.editor, and stuff' . ./test-lib.sh -for i in GIT_EDITOR core_editor EDITOR VISUAL vi +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 -unset vi -mv e-vi.sh vi -unset EDITOR VISUAL GIT_EDITOR + +if ! test -z "$vi" +then + mv e-$vi.sh $vi +fi test_expect_success setup ' - msg="Hand edited" && + msg="Hand-edited" && + test_commit "$msg" && echo "$msg" >expect && - git add vi && - test_tick && - git commit -m "$msg" && - git show -s --pretty=oneline | - sed -e "s/^[0-9a-f]* //" >actual && + git show -s --format=%s > actual && diff actual expect ' @@ -41,9 +55,19 @@ test_expect_success 'dumb should error out when falling back on vi' ' 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 +for i in $vi EDITOR VISUAL core_editor GIT_EDITOR do echo "Edited by $i" >expect unset EDITOR VISUAL GIT_EDITOR @@ -67,7 +91,7 @@ done unset EDITOR VISUAL GIT_EDITOR git config --unset-all core.editor -for i in vi EDITOR VISUAL core_editor GIT_EDITOR +for i in $vi EDITOR VISUAL core_editor GIT_EDITOR do echo "Edited by $i" >expect case "$i" in @@ -87,30 +111,26 @@ do ' done +if ! echo 'echo space > "$1"' > "e space.sh" +then + say "Skipping; FS does not support spaces in filenames" + test_done +fi + test_expect_success 'editor with a space' ' - if echo "echo space > \"\$1\"" > "e space.sh" - then - chmod a+x "e space.sh" && - GIT_EDITOR="./e\ space.sh" git commit --amend && - test space = "$(git show -s --pretty=format:%s)" - else - say "Skipping; FS does not support spaces in filenames" - fi + 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' ' - if test -f "e space.sh" - then - git config core.editor \"./e\ space.sh\" && - git commit --amend && - test space = "$(git show -s --pretty=format:%s)" - else - say "Skipping; FS does not support spaces in filenames" - fi + git config core.editor \"./e\ space.sh\" && + git commit --amend && + test space = "$(git show -s --pretty=format:%s)" ' 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/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..8d8b1c0e25 --- /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 +' + +test_expect_failure 'git-apply adds file' false +test_expect_failure 'git-apply updates file' false +test_expect_failure 'git-apply removes file' false +test_expect_failure 'git-mv to skip-worktree' false +test_expect_failure 'git-mv from skip-worktree' false +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 0d9874bfd7..96e163f084 100755 --- a/t/t7101-reset.sh +++ b/t/t7101-reset.sh @@ -3,33 +3,33 @@ # 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 && + cp "$TEST_DIRECTORY"/../COPYING path0/COPYING && git add path0/COPYING && - git-commit -m add -a' + 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 && + 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' + 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' \ diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 29f5678b4c..b8cf2603a1 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -3,9 +3,9 @@ # Copyright (c) 2007 Carlos Rica # -test_description='git-reset +test_description='git reset -Documented tests for git-reset' +Documented tests for git reset' . ./test-lib.sh @@ -139,19 +139,19 @@ test_expect_success \ test_expect_success \ 'resetting to HEAD with no changes should succeed and do nothing' ' git reset --hard && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset --hard HEAD && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset --soft && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset --soft HEAD && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset --mixed && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset --mixed HEAD && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset && - check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc + check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc && git reset HEAD && check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc ' @@ -419,7 +419,8 @@ test_expect_success 'resetting an unmodified path is a no-op' ' ' cat > expect << EOF -file2: locally modified +Unstaged changes after reset: +M file2 EOF test_expect_success '--mixed refreshes the index' ' diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh index cdecebe456..afb55b3a46 100755 --- a/t/t7103-reset-bare.sh +++ b/t/t7103-reset-bare.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-reset in a bare repository' +test_description='git reset in a bare repository' . ./test-lib.sh test_expect_success 'setup non-bare' ' @@ -11,16 +11,48 @@ test_expect_success 'setup non-bare' ' 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 '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' ' - test_must_fail git reset --hard HEAD^ +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 'mixed reset is not allowed in bare' ' + test_must_fail git reset --mixed HEAD^ ' -test_expect_success 'soft reset is allowed' ' +test_expect_success 'soft reset is allowed in bare' ' git reset --soft HEAD^ && test "`git show --pretty=format:%s | head -n 1`" = "one" ' 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..8704d00196 --- /dev/null +++ b/t/t7110-reset-merge.sh @@ -0,0 +1,183 @@ +#!/bin/sh +# +# Copyright (c) 2009 Christian Couder +# + +test_description='Tests for "git reset --merge"' + +. ./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: 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: 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: 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" +' + +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 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)" +' + +test_expect_success '--merge with added/deleted' ' + 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_done diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh new file mode 100755 index 0000000000..de896c948d --- /dev/null +++ b/t/t7111-reset-table.sh @@ -0,0 +1,113 @@ +#!/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 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 +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 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 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 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 +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 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 +EOF + +test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 9ad5d635a2..d20ed61b48 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -3,7 +3,7 @@ # 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. @@ -166,19 +166,31 @@ test_expect_success 'checkout -m with merge conflict' ' ! test -s current ' -test_expect_success 'checkout to detach HEAD' ' +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 && - (cat >messages.expect <<EOF -Note: moving to "renamer^" which isn'"'"'t a local branch -If you want to create a new branch from this checkout, you may do so -(now or later) by using -b with the checkout command again. Example: - git checkout -b <new_branch_name> -HEAD is now at 7329388... Initial A one, A two -EOF -) && - test_cmp messages.expect 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" && @@ -330,11 +342,273 @@ test_expect_success \ 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 w/--track from non-branch HEAD fails' ' - git checkout -b delete-me master && - rm .git/refs/heads/delete-me && - test refs/heads/delete-me = "$(git symbolic-ref HEAD)" && - test_must_fail git checkout --track -b track' + '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 "|||||||" + 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 "|||||||" + 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 index 2b51c0d7d8..7d8ed68bef 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Michael Spang # -test_description='git-clean basic tests' +test_description='git clean basic tests' . ./test-lib.sh @@ -16,17 +16,36 @@ test_expect_success 'setup' ' echo build >.gitignore && echo \*.o >>.gitignore && git add . && - git-commit -m setup && + git commit -m setup && touch src/part2.c README && git add . ' -test_expect_success 'git-clean' ' +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 && + git clean && test -f Makefile && test -f README && test -f src/part1.c && @@ -39,11 +58,11 @@ test_expect_success 'git-clean' ' ' -test_expect_success 'git-clean src/' ' +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/ && + git clean src/ && test -f Makefile && test -f README && test -f src/part1.c && @@ -56,11 +75,11 @@ test_expect_success 'git-clean src/' ' ' -test_expect_success 'git-clean src/ src/' ' +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/ && + git clean src/ src/ && test -f Makefile && test -f README && test -f src/part1.c && @@ -73,11 +92,11 @@ test_expect_success 'git-clean src/ src/' ' ' -test_expect_success 'git-clean with prefix' ' +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) && + (cd src/ && git clean) && test -f Makefile && test -f README && test -f src/part1.c && @@ -91,7 +110,7 @@ test_expect_success 'git-clean with prefix' ' ' -test_expect_success 'git-clean with relative prefix' ' +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 && @@ -106,7 +125,7 @@ test_expect_success 'git-clean with relative prefix' ' } ' -test_expect_success 'git-clean with absolute path' ' +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 && @@ -121,7 +140,7 @@ test_expect_success 'git-clean with absolute path' ' } ' -test_expect_success 'git-clean with out of work tree relative path' ' +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 && @@ -131,7 +150,7 @@ test_expect_success 'git-clean with out of work tree relative path' ' ) ' -test_expect_success 'git-clean with out of work tree absolute path' ' +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 && @@ -142,11 +161,11 @@ test_expect_success 'git-clean with out of work tree absolute path' ' ) ' -test_expect_success 'git-clean -d with prefix and path' ' +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/) && + (cd src/ && git clean -d feature/) && test -f Makefile && test -f README && test -f src/part1.c && @@ -160,12 +179,12 @@ test_expect_success 'git-clean -d with prefix and path' ' ' -test_expect_success 'git-clean symbolic link' ' +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 && + git clean && test -f Makefile && test -f README && test -f src/part1.c && @@ -179,10 +198,10 @@ test_expect_success 'git-clean symbolic link' ' ' -test_expect_success 'git-clean with wildcard' ' +test_expect_success 'git clean with wildcard' ' touch a.clean b.clean other.c && - git-clean "*.clean" && + git clean "*.clean" && test -f Makefile && test -f README && test -f src/part1.c && @@ -193,11 +212,11 @@ test_expect_success 'git-clean with wildcard' ' ' -test_expect_success 'git-clean -n' ' +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 && + git clean -n && test -f Makefile && test -f README && test -f src/part1.c && @@ -210,11 +229,11 @@ test_expect_success 'git-clean -n' ' ' -test_expect_success 'git-clean -d' ' +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 && + git clean -d && test -f Makefile && test -f README && test -f src/part1.c && @@ -227,11 +246,11 @@ test_expect_success 'git-clean -d' ' ' -test_expect_success 'git-clean -d src/ examples/' ' +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/ && + git clean -d src/ examples/ && test -f Makefile && test -f README && test -f src/part1.c && @@ -245,11 +264,11 @@ test_expect_success 'git-clean -d src/ examples/' ' ' -test_expect_success 'git-clean -x' ' +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 && + git clean -x && test -f Makefile && test -f README && test -f src/part1.c && @@ -262,11 +281,11 @@ test_expect_success 'git-clean -x' ' ' -test_expect_success 'git-clean -d -x' ' +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 && + git clean -d -x && test -f Makefile && test -f README && test -f src/part1.c && @@ -279,11 +298,11 @@ test_expect_success 'git-clean -d -x' ' ' -test_expect_success 'git-clean -X' ' +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 && + git clean -X && test -f Makefile && test -f README && test -f src/part1.c && @@ -296,11 +315,11 @@ test_expect_success 'git-clean -X' ' ' -test_expect_success 'git-clean -d -X' ' +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 && + git clean -d -X && test -f Makefile && test -f README && test -f src/part1.c && @@ -331,7 +350,7 @@ 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 && + git clean -n && test -f Makefile && test -f README && test -f src/part1.c && @@ -346,7 +365,7 @@ test_expect_success 'clean.requireForce and -n' ' test_expect_success 'clean.requireForce and -f' ' - git-clean -f && + git clean -f && test -f README && test -f src/part1.c && test -f src/part2.c && @@ -373,11 +392,50 @@ test_expect_success 'removal failure' ' mkdir foo && touch foo/bar && - exec <foo/bar && - chmod 0 foo && - test_must_fail git clean -f -d + (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 index cbc0c34ce2..1a4dc5f893 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -6,7 +6,7 @@ test_description='Basic porcelain support for submodules This test tries to verify basic sanity of the init, update and status -subcommands of git-submodule. +subcommands of git submodule. ' . ./test-lib.sh @@ -22,16 +22,16 @@ subcommands of git-submodule. # test_expect_success 'Prepare submodule testing' ' : > t && - git-add t && - git-commit -m "initial commit" && + git add t && + git commit -m "initial commit" && git branch initial HEAD && 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 && + git commit -m "submodule commit 1" && + git tag -a -m "rev-1" rev-1 && rev1=$(git rev-parse HEAD) && if test -z "$rev1" then @@ -42,13 +42,72 @@ test_expect_success 'Prepare submodule testing' ' echo a >a && echo z >z && git add a init z && - git-commit -m "super commit 1" && + git commit -m "super commit 1" && mv init .subrepo && GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git ' +test_expect_success 'Prepare submodule add testing' ' + submodurl=$(pwd) + ( + mkdir addtest && + cd addtest && + git init + ) +' + +test_expect_success 'submodule add' ' + ( + cd addtest && + git submodule add "$submodurl" submod && + git submodule init + ) +' + +test_expect_success 'submodule add --branch' ' + ( + cd addtest && + git submodule add -b initial "$submodurl" submod-branch && + git submodule init && + cd submod-branch && + git branch | grep initial + ) +' + +test_expect_success 'submodule add with ./ in path' ' + ( + cd addtest && + git submodule add "$submodurl" ././dotsubmod/./frotz/./ && + git submodule init + ) +' + +test_expect_success 'submodule add with // in path' ' + ( + cd addtest && + git submodule add "$submodurl" slashslashsubmod///frotz// && + git submodule init + ) +' + +test_expect_success 'submodule add with /.. in path' ' + ( + cd addtest && + git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. && + git submodule init + ) +' + +test_expect_success 'submodule add with ./, /.. and // in path' ' + ( + cd addtest && + git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. && + git submodule init + ) +' + test_expect_success 'status should fail for unmapped paths' ' - if git-submodule status + if git submodule status then echo "[OOPS] submodule status succeeded" false @@ -60,16 +119,16 @@ test_expect_success 'status should fail for unmapped paths' ' ' test_expect_success 'status should only print one line' ' - lines=$(git-submodule status | wc -l) && + lines=$(git submodule status | wc -l) && test $lines = 1 ' test_expect_success 'status should initially be "missing"' ' - git-submodule status | grep "^-$rev1" + git submodule status | grep "^-$rev1" ' test_expect_success 'init should register submodule url in .git/config' ' - git-submodule init && + git submodule init && url=$(git config submodule.example.url) && if test "$url" != "git://example.com/init.git" then @@ -84,7 +143,7 @@ test_expect_success 'init should register submodule url in .git/config' ' test_expect_success 'update should fail when path is used by a file' ' echo "hello" >init && - if git-submodule update + if git submodule update then echo "[OOPS] update should have failed" false @@ -100,7 +159,7 @@ test_expect_success 'update should fail when path is used by a file' ' test_expect_success 'update should fail when path is used by a nonempty directory' ' mkdir init && echo "hello" >init/a && - if git-submodule update + if git submodule update then echo "[OOPS] update should have failed" false @@ -116,7 +175,7 @@ test_expect_success 'update should fail when path is used by a nonempty director test_expect_success 'update should work when path is an empty dir' ' rm -rf init && mkdir init && - git-submodule update && + git submodule update && head=$(cd init && git rev-parse HEAD) && if test -z "$head" then @@ -130,14 +189,14 @@ test_expect_success 'update should work when path is an empty dir' ' ' test_expect_success 'status should be "up-to-date" after update' ' - git-submodule status | grep "^ $rev1" + git submodule status | grep "^ $rev1" ' test_expect_success 'status should be "modified" after submodule commit' ' cd init && echo b >b && git add b && - git-commit -m "submodule commit 2" && + git commit -m "submodule commit 2" && rev2=$(git rev-parse HEAD) && cd .. && if test -z "$rev2" @@ -145,19 +204,19 @@ test_expect_success 'status should be "modified" after submodule commit' ' echo "[OOPS] submodule git rev-parse returned nothing" false fi && - git-submodule status | grep "^+$rev2" + git submodule status | grep "^+$rev2" ' test_expect_success 'the --cached sha1 should be rev1' ' - git-submodule --cached status | grep "^+$rev1" + git submodule --cached status | grep "^+$rev1" ' test_expect_success 'git diff should report the SHA1 of the new submodule commit' ' - git-diff | grep "^+Subproject commit $rev2" + git diff | grep "^+Subproject commit $rev2" ' test_expect_success 'update should checkout rev1' ' - git-submodule update init && + git submodule update init && head=$(cd init && git rev-parse HEAD) && if test -z "$head" then @@ -171,12 +230,12 @@ test_expect_success 'update should checkout rev1' ' ' test_expect_success 'status should be "up-to-date" after update' ' - git-submodule status | grep "^ $rev1" + git submodule status | grep "^ $rev1" ' test_expect_success 'checkout superproject with subproject already present' ' - git-checkout initial && - git-checkout master + git checkout initial && + git checkout master ' test_expect_success 'apply submodule diff' ' @@ -188,8 +247,8 @@ test_expect_success 'apply submodule diff' ' git commit -m "change subproject" ) && git update-index --add init && - git-commit -m "change init" && - git-format-patch -1 --stdout >P.diff && + git commit -m "change init" && + git format-patch -1 --stdout >P.diff && git checkout second && git apply --index P.diff && D=$(git diff --cached master) && @@ -209,4 +268,67 @@ test_expect_success 'update --init' ' ' +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 index bf12dbdeef..d3c039f724 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -5,7 +5,7 @@ test_description='Summary support for submodules -This test tries to verify the sanity of summary subcommand of git-submodule. +This test tries to verify the sanity of summary subcommand of git submodule. ' . ./test-lib.sh @@ -56,6 +56,15 @@ test_expect_success 'modified submodule(forward)' " 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 && @@ -114,6 +123,15 @@ test_expect_success 'typechanged submodule(submodule->blob), --cached' " 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)' " @@ -195,7 +213,7 @@ EOF test_expect_success '--for-status' " git submodule summary --for-status HEAD^ >actual && test_cmp actual - <<EOF -# Modified submodules: +# Submodule changes to be committed: # # * sm1 $head6...0000000: # @@ -205,4 +223,8 @@ test_expect_success '--for-status' " EOF " +test_expect_success 'fail when using --files together with --cached' " + test_must_fail git submodule summary --files --cached +" + 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..9a21f783d3 --- /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..8e2449d244 --- /dev/null +++ b/t/t7406-submodule-update.sh @@ -0,0 +1,198 @@ +#!/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 && + (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" + ) +' + +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 submodule.rebasing.url git://non-existing/git && + git config submodule.rebasing.path does-not-matter && + git config 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 submodule.merging.url git://non-existing/git && + git config submodule.merging.path does-not-matter && + git config 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..2a527750ce --- /dev/null +++ b/t/t7407-submodule-foreach.sh @@ -0,0 +1,237 @@ +#!/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) + +cat > expect <<EOF +Entering 'sub1' +foo1-sub1-$sub1sha1 +Entering 'sub3' +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 \$name-\$path-\$sha1" > ../actual + ) && + 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 index d89f91a6fb..9f5c3edb03 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Steven Grimm # -test_description='git-commit +test_description='git commit Tests for selected commit options.' @@ -46,15 +46,24 @@ test_expect_success 'unedited template with comments should not commit' ' ' test_expect_success 'a Signed-off-by line by itself should not commit' ' - ! GIT_EDITOR=../t7500/add-signed-off git commit --template "$TEMPLATE" + ( + 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' ' - ! GIT_EDITOR=../t7500/add-comments git commit --template "$TEMPLATE" + ( + 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' ' - GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit --template "$TEMPLATE" + ) && commit_msg_is "template linecommit message" ' @@ -62,7 +71,10 @@ test_expect_success '-t option should be short for --template' ' echo "short template" > "$TEMPLATE" && echo "new content" >> foo && git add foo && - GIT_EDITOR=../t7500/add-content git commit -t "$TEMPLATE" && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit -t "$TEMPLATE" + ) && commit_msg_is "short templatecommit message" ' @@ -71,7 +83,10 @@ test_expect_success 'config-specified template should commit' ' git config commit.template "$TEMPLATE" && echo "more content" >> foo && git add foo && - GIT_EDITOR=../t7500/add-content git commit && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit + ) && git config --unset commit.template && commit_msg_is "new templatecommit message" ' @@ -79,7 +94,7 @@ test_expect_success 'config-specified template should commit' ' test_expect_success 'explicit commit message should override template' ' echo "still more content" >> foo && git add foo && - GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" \ + GIT_EDITOR="$TEST_DIRECTORY"/t7500/add-content git commit --template "$TEMPLATE" \ -m "command line msg" && commit_msg_is "command line msg" ' @@ -88,8 +103,10 @@ test_expect_success 'commit message from file should override template' ' echo "content galore" >> foo && git add foo && echo "standard input msg" | - GIT_EDITOR=../t7500/add-content git commit \ - --template "$TEMPLATE" --file - && + ( + test_set_editor "$TEST_DIRECTORY"/t7500/add-content && + git commit --template "$TEMPLATE" --file - + ) && commit_msg_is "standard input msg" ' @@ -132,10 +149,48 @@ EOF test_expect_success '--signoff' ' echo "yet another content *narf*" >> foo && - echo "zort" | - GIT_EDITOR=../t7500/add-content git commit -s -F - foo && - git cat-file commit HEAD | sed "1,/^$/d" > output && - diff expect output + 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_done diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 0edd9ddf73..7940901d47 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -6,7 +6,7 @@ # FIXME: Test the various index usages, -i and -o, test reflog, # signoff -test_description='git-commit' +test_description='git commit' . ./test-lib.sh test_tick @@ -14,52 +14,52 @@ test_tick test_expect_success \ "initial status" \ "echo 'bongo bongo' >file && - git-add file && \ - git-status | grep 'Initial commit'" + git add file && \ + git status | grep 'Initial commit'" test_expect_success \ "fail initial amend" \ - "test_must_fail git-commit --amend" + "test_must_fail git commit --amend" test_expect_success \ "initial commit" \ - "git-commit -m initial" + "git commit -m initial" test_expect_success \ "invalid options 1" \ - "test_must_fail git-commit -m foo -m bar -F file" + "test_must_fail git commit -m foo -m bar -F file" test_expect_success \ "invalid options 2" \ - "test_must_fail git-commit -C HEAD -m illegal" + "test_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_must_fail git commit -m foo -a file" -test_expect_success \ +test_expect_success PERL \ "using paths with --interactive" \ "echo bong-o-bong >file && - ! (echo 7 | git-commit -m foo --interactive 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_must_fail git commit -C bogus" test_expect_success \ "testing nothing to commit" \ - "test_must_fail git-commit -m initial" + "test_must_fail git commit -m initial" test_expect_success \ "next commit" \ "echo 'bongo bongo bongo' >file \ - git-commit -m next -a" + git commit -m next -a" test_expect_success \ "commit message from non-existing file" \ "echo 'more bongo: bongo bongo bongo bongo' >file && \ - test_must_fail git-commit -F gah -a" + test_must_fail git commit -F gah -a" # Empty except stray tabs and spaces on a few lines. sed -e 's/@$//' >msg <<EOF @@ -70,12 +70,12 @@ Signed-off-by: hula EOF test_expect_success \ "empty commit message" \ - "test_must_fail git-commit -F msg -a" + "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" + git commit -F msg -a" cat >editor <<\EOF #!/bin/sh @@ -86,16 +86,16 @@ chmod 755 editor test_expect_success \ "amend commit" \ - "VISUAL=./editor git-commit --amend" + "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_must_fail git commit -F msg -m amending ." test_expect_success \ "using message from other commit" \ - "git-commit -C HEAD^ ." + "git commit -C HEAD^ ." cat >editor <<\EOF #!/bin/sh @@ -107,26 +107,50 @@ chmod 755 editor test_expect_success \ "editing message from other commit" \ "echo 'hula hula' >file && \ - VISUAL=./editor git-commit -c HEAD^ -a" + 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" + 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" + 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'" + "echo 7 | git commit --interactive | grep 'What now'" test_expect_success \ "showing committed revisions" \ - "git-rev-list HEAD >current" + "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. @@ -140,8 +164,8 @@ d381ac431806e53f3dd7ac2f1ae0534f36d738b9 EOF test_expect_success \ - 'validate git-rev-list output.' \ - 'diff current expected' + 'validate git rev-list output.' \ + 'test_cmp expected current' test_expect_success 'partial commit that involves removal (1)' ' @@ -151,7 +175,7 @@ test_expect_success 'partial commit that involves removal (1)' ' git commit -m "Partial: add elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "A elif" >expected && - diff expected current + test_cmp expected current ' @@ -160,7 +184,7 @@ 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 && - diff expected current + test_cmp expected current ' @@ -171,7 +195,7 @@ test_expect_success 'partial commit that involves removal (3)' ' git commit -m "Partial: modify elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "M elif" >expected && - diff expected current + test_cmp expected current ' @@ -187,7 +211,22 @@ test_expect_success 'amend commit to fix author' ' expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && - diff expected 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 ' @@ -227,6 +266,47 @@ $existing" && ' +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 && @@ -256,7 +336,7 @@ test_expect_success 'amend commit to fix author' ' expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && - diff expected current + test_cmp expected current ' diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 4f2682ea80..844fb43c6d 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -89,6 +89,14 @@ test_expect_success 'verbose' ' ' +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 && @@ -141,8 +149,8 @@ test_expect_success 'cleanup commit messages (strip,-F)' ' echo "sample -# Please enter the commit message for your changes. -# (Comment lines starting with '#' will not be included)" >expect +# 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)' ' @@ -226,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF # kill -TERM command added below. EOF -test_expect_success 'a SIGTERM should break locks' ' +test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' ' echo >>negative && ! "$SHELL_PATH" -c '\'' echo kill -TERM $$ >> .git/FAKE_EDITOR @@ -250,4 +258,122 @@ test_expect_success 'Hand committing of a redundant merge removes dups' ' ' +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/t7502-status.sh b/t/t7502-status.sh deleted file mode 100755 index 38a48b57c7..0000000000 --- a/t/t7502-status.sh +++ /dev/null @@ -1,384 +0,0 @@ -#!/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) -# -# 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: -# (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) -# -# 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: -# (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) -# -# 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 -# 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) -# -# 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 -# 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) -# -# 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 -# 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) -# -# 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 <<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 'status of partial commit excluding new file in index' ' - git status dir1/modified >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) -# -# 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 -' - -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) -# -# modified: dir1/modified -# -# Modified submodules: -# -# * 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 -# On branch master -# Changed but not updated: -# (use "git add <file>..." to update what will be committed) -# -# 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 status >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) -# -# modified: dir1/modified -# -# Modified submodules: -# -# * 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 (--amend)' ' - git config status.submodulesummary 10 && - git status --amend >output && - test_cmp expect output -' - -test_done diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh index b069095995..8528f64c8d 100755 --- a/t/t7503-pre-commit-hook.sh +++ b/t/t7503-pre-commit-hook.sh @@ -69,7 +69,7 @@ test_expect_success '--no-verify with failing hook' ' ' chmod -x "$HOOK" -test_expect_success 'with non-executable hook' ' +test_expect_success POSIXPERM 'with non-executable hook' ' echo "content" >> file && git add file && @@ -77,7 +77,7 @@ test_expect_success 'with non-executable hook' ' ' -test_expect_success '--no-verify with non-executable hook' ' +test_expect_success POSIXPERM '--no-verify with non-executable hook' ' echo "more content" >> file && git add file && diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh index 47680e6df4..1f53ea8090 100755 --- a/t/t7504-commit-msg-hook.sh +++ b/t/t7504-commit-msg-hook.sh @@ -136,7 +136,7 @@ test_expect_success '--no-verify with failing hook (editor)' ' ' chmod -x "$HOOK" -test_expect_success 'with non-executable hook' ' +test_expect_success POSIXPERM 'with non-executable hook' ' echo "content" >> file && git add file && @@ -144,7 +144,7 @@ test_expect_success 'with non-executable hook' ' ' -test_expect_success 'with non-executable hook (editor)' ' +test_expect_success POSIXPERM 'with non-executable hook (editor)' ' echo "content again" >> file && git add file && @@ -153,7 +153,7 @@ test_expect_success 'with non-executable hook (editor)' ' ' -test_expect_success '--no-verify with non-executable hook' ' +test_expect_success POSIXPERM '--no-verify with non-executable hook' ' echo "more content" >> file && git add file && @@ -161,7 +161,7 @@ test_expect_success '--no-verify with non-executable hook' ' ' -test_expect_success '--no-verify with non-executable hook (editor)' ' +test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' ' echo "even more content" >> file && git add file && diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index cd6c7c8342..ff189624d4 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -32,7 +32,7 @@ echo "#!$SHELL_PATH" > "$HOOK" cat >> "$HOOK" <<'EOF' if test "$2" = commit; then - source=$(git-rev-parse "$3") + source=$(git rev-parse "$3") else source=${2-default} fi diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index a75130cdbb..253c334319 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -1,38 +1,91 @@ #!/bin/sh -test_description='git-status for submodule' +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" && - cd .. && - git add sub && + 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 | - grep "nothing to commit" + git status >output && + grep "nothing to commit" output ' -test_expect_success 'status -a clean' ' - git status -a | - grep "nothing to commit" + +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" 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" 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" output +' + +test_expect_success 'status with untracked file in submodule (porcelain)' ' + git status --porcelain >output && + diff output - <<-\EOF + M sub + EOF ' + test_expect_success 'rm submodule contents' ' rm -rf sub/* sub/.git ' + test_expect_success 'status clean (empty submodule dir)' ' - git status | - grep "nothing to commit" + git status >output && + grep "nothing to commit" output ' + test_expect_success 'status -a clean (empty submodule dir)' ' - git status -a | - grep "nothing to commit" + 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..556d0faa77 --- /dev/null +++ b/t/t7508-status.sh @@ -0,0 +1,696 @@ +#!/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 + M dir1/modified +A dir2/added +?? dir1/untracked +?? dir2/modified +?? dir2/untracked +?? expect +?? output +?? untracked +EOF + +test_expect_success 'status -s (2)' ' + + 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 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 + 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 + 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 + +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 +' + +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_done diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh new file mode 100755 index 0000000000..d52c060b06 --- /dev/null +++ b/t/t7509-commit.sh @@ -0,0 +1,114 @@ +#!/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 +' + +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 index 5eeb6c2b27..57f6d2bae7 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Lars Hjemli # -test_description='git-merge +test_description='git merge Testing basic merge operations/option parsing.' @@ -230,6 +230,10 @@ test_expect_success 'test option parsing' ' 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 && @@ -239,6 +243,16 @@ test_expect_success 'merge c0 with 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 && @@ -259,6 +273,14 @@ test_expect_success 'merge c1 with c2 and 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 && @@ -299,6 +321,17 @@ test_expect_success 'merge c0 with c1 (squash)' ' 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 && @@ -310,6 +343,13 @@ test_expect_success 'merge c1 with c2 (squash)' ' 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 && @@ -428,6 +468,11 @@ test_expect_success 'combining --squash and --no-ff is refused' ' 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" && @@ -488,4 +533,72 @@ test_expect_success 'merge c1 with c1 and 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 && + sleep 1 && + touch 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 index 55aa6b5f27..7ba94ea99b 100755 --- a/t/t7601-merge-pull-config.sh +++ b/t/t7601-merge-pull-config.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-merge +test_description='git merge Testing pull.* configuration parsing.' diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index fcb8285746..2746169514 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-merge +test_description='git merge Testing octopus merge with more than 25 refs.' @@ -49,4 +49,55 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' ' 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 index 17b19dc11f..7e17eb490d 100755 --- a/t/t7603-merge-reduce-heads.sh +++ b/t/t7603-merge-reduce-heads.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-merge +test_description='git merge Testing octopus merge when reducing parents to independent branches.' @@ -60,4 +60,57 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' ' 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 index 6081677d23..269cfdf267 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-merge +test_description='git merge Testing merge when using a custom message for the merge commit.' @@ -22,15 +22,12 @@ test_expect_success 'setup' ' git tag c2 ' -cat >expected <<\EOF -custom message -Merge commit 'c2' -EOF test_expect_success 'merge c2 with a custom message' ' git reset --hard c1 && + echo >expected "custom message" && git merge -m "custom message" c2 && - git cat-file commit HEAD | sed -e "1,/^$/d" > actual && + git cat-file commit HEAD | sed -e "1,/^$/d" >actual && test_cmp expected actual ' diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh index ee21a107fd..0cb9d11f21 100755 --- a/t/t7605-merge-resolve.sh +++ b/t/t7605-merge-resolve.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-merge +test_description='git merge Testing the resolve strategy.' @@ -36,7 +36,9 @@ test_expect_success 'merge c1 to c2' ' git diff --exit-code && test -f c0.c && test -f c1.c && - test -f c2.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)' ' 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 index 9285071c47..e768c3eb2d 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -3,44 +3,87 @@ # Copyright (c) 2008 Charles Bailey # -test_description='git-mergetool +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 && - git add 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 && - git add file1 file2 && + echo branch1 sub >subdir/file3 && + git add file1 file2 subdir/file3 && git commit -m "branch1 changes" && - git checkout -b branch2 master && - echo branch2 change >file1 && - echo branch2 newfile >file2 && - git add file1 file2 && - git commit -m "branch2 changes" && + git checkout master && echo master updated >file1 && echo master new >file2 && - git add file1 file2 && - git commit -m "master updates" -' + echo master new sub >subdir/file3 && + git add file1 file2 subdir/file3 && + git commit -m "master updates" && -test_expect_success 'custom mergetool' ' git config merge.tool mytool && git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" && - git config mergetool.mytool.trustExitCode true && - git checkout branch1 && + 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 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" && - git commit -m "branch1 resolved with mergetool" + 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..f4aa054750 --- /dev/null +++ b/t/t7700-repack.sh @@ -0,0 +1,165 @@ +#!/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 . && + 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 && + 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 && + 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^ && + sleep 1 && + git reflog expire --expire=now --expire-unreachable=now --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=now --expire-unreachable=now --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 index 31c340fd38..5babdf26e6 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='git-repack works correctly' +test_description='git repack works correctly' . ./test-lib.sh @@ -8,7 +8,7 @@ fsha1= csha1= tsha1= -test_expect_success '-A option leaves unreachable objects unpacked' ' +test_expect_success '-A with -d option leaves unreachable objects unpacked' ' echo content > file1 && git add . && git commit -m initial_commit && @@ -29,7 +29,7 @@ test_expect_success '-A option leaves unreachable objects unpacked' ' git repack -A -d -l && # verify objects are packed in repository test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx | - grep -e "^$fsha1 " -e "^$csha1 " -e "^$tsha1 " | + egrep "^($fsha1|$csha1|$tsha1) " | sort | uniq | wc -l) && git show $fsha1 && git show $csha1 && @@ -41,7 +41,7 @@ test_expect_success '-A option leaves unreachable objects unpacked' ' git repack -A -d -l && # verify objects are retained unpacked test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx | - grep -e "^$fsha1 " -e "^$csha1 " -e "^$tsha1 " | + egrep "^($fsha1|$csha1|$tsha1) " | sort | uniq | wc -l) && git show $fsha1 && git show $csha1 && @@ -50,15 +50,13 @@ test_expect_success '-A option leaves unreachable objects unpacked' ' compare_mtimes () { - perl -e 'my $reference = shift; - foreach my $file (@ARGV) { - exit(1) unless(-f $file && -M $file == -M $reference); - } - exit(0); - ' -- "$@" + read tref rest && + while read t rest; do + test "$tref" = "$t" || break + done } -test_expect_success 'unpacked objects receive timestamp of pack file' ' +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/|") && @@ -75,7 +73,21 @@ test_expect_success 'unpacked objects receive timestamp of pack file' ' git branch -D transient_branch && sleep 1 && git repack -A -l && - compare_mtimes "$packfile" "$fsha1path" "$csha1path" "$tsha1path" + 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..19c72f55bf --- /dev/null +++ b/t/t7800-difftool.sh @@ -0,0 +1,267 @@ +#!/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 + say '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 +' + +# 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/t8001-annotate.sh b/t/t8001-annotate.sh index eabec2e06e..45cb60ea4b 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -4,7 +4,7 @@ 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 92ece30fa9..597cf0486f 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -4,6 +4,6 @@ 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 index 966bb0a61a..3bbddd03cb 100755 --- a/t/t8003-blame.sh +++ b/t/t8003-blame.sh @@ -129,4 +129,42 @@ test_expect_success 'blame wholesale copy and more' ' ' +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_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/t9001-send-email.sh b/t/t9001-send-email.sh index 1c857cf4ab..c09f375288 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1,8 +1,13 @@ #!/bin/sh -test_description='git-send-email' +test_description='git send-email' . ./test-lib.sh +if ! test_have_prereq PERL; then + say 'skipping git send-email tests, perl not available' + test_done +fi + PROG='git send-email' test_expect_success \ 'prepare reference tree' \ @@ -32,31 +37,118 @@ clean_fake_sendmail() { } 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 || { + say 'No 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 commandline1 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>,<cc@example.com>,<author@example.com>,<bcc@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> +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 @@ -70,6 +162,7 @@ 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 \ @@ -84,6 +177,38 @@ test_expect_success '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 @@ -104,12 +229,34 @@ 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" \ - --no-validate \ + --novalidate \ $patches longline.patch \ 2>errors ' @@ -148,15 +295,13 @@ test_set_editor "$(pwd)/fake-editor" test_expect_success '--compose works' ' clean_fake_sendmail && - echo y | \ - GIT_SEND_EMAIL_NOTTY=1 \ - git send-email \ - --compose --subject foo \ - --from="Example <nobody@example.com>" \ - --to=nobody@example.com \ - --smtp-server="$(pwd)/fake.sendmail" \ - $patches \ - 2>errors + 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' ' @@ -167,16 +312,25 @@ test_expect_success 'second message is patch' ' grep "Subject:.*Second" msgtxt2 ' -cat >expected-show-all-headers <<\EOF +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>,<cc@example.com>,<author@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> +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 @@ -185,10 +339,10 @@ X-Mailer: X-MAILER-STRING Result: OK EOF -test_expect_success 'sendemail.cc set' ' - git config sendemail.cc cc@example.com && +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 \ @@ -196,20 +350,32 @@ test_expect_success 'sendemail.cc set' ' 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 + >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-show-all-headers <<\EOF +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>,<author@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> +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 @@ -220,17 +386,315 @@ 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 \ - --dry-run \ - --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-show-all-headers && - test_cmp expected-show-all-headers actual-show-all-headers + --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' ' @@ -239,9 +703,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' echo "echo utf8 body: à éìöú >>\"\$1\"" ) >fake-editor-utf8 && chmod +x fake-editor-utf8 && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject foo \ --from="Example <nobody@example.com>" \ @@ -249,7 +711,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' --smtp-server="$(pwd)/fake.sendmail" \ $patches && grep "^utf8 body" msgtxt1 && - grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 + grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' test_expect_success '--compose respects user mime type' ' @@ -263,9 +725,7 @@ test_expect_success '--compose respects user mime type' ' echo " echo utf8 body: à éìöú) >\"\$1\"" ) >fake-editor-utf8-mime && chmod +x fake-editor-utf8-mime && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject foo \ --from="Example <nobody@example.com>" \ @@ -274,14 +734,12 @@ test_expect_success '--compose respects user mime type' ' $patches && grep "^utf8 body" msgtxt1 && grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 && - ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 + ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1 ' test_expect_success '--compose adds MIME for utf8 subject' ' clean_fake_sendmail && - echo y | \ GIT_EDITOR="\"$(pwd)/fake-editor\"" \ - GIT_SEND_EMAIL_NOTTY=1 \ git send-email \ --compose --subject utf8-sübjëct \ --from="Example <nobody@example.com>" \ @@ -289,7 +747,109 @@ test_expect_success '--compose adds MIME for utf8 subject' ' --smtp-server="$(pwd)/fake.sendmail" \ $patches && grep "^fake edit" msgtxt1 && - grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" 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_done diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 843a5013b9..570e0359e4 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -3,24 +3,24 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-svn basic tests' +test_description='git svn basic tests' GIT_SVN_LC_ALL=${LC_ALL:-$LANG} +. ./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 - -say '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 && @@ -31,27 +31,27 @@ test_expect_success \ 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"' name='try a deep --rmdir with a commit' test_expect_success "$name" ' - git checkout -f -b mybranch remotes/git-svn && + 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" && + 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' @@ -63,62 +63,62 @@ test_expect_success "$name" " git update-index --remove dir/file && git update-index --add dir/file/file && git commit -m '$name' && - test_must_fail git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch" || true + 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_success "$name" ' rm -rf dir "$GIT_DIR"/index && - git checkout -f -b mybranch2 remotes/git-svn && + 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" && - test_must_fail git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch2' || true + 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_success "$name" ' rm -f "$GIT_DIR"/index && - git checkout -f -b mybranch3 remotes/git-svn && + git checkout -f -b mybranch3 ${remotes_git_svn} && rm 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" && - test_must_fail git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch3' || true + 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_success "$name" ' rm -f "$GIT_DIR"/index && - git checkout -f -b mybranch4 remotes/git-svn && + 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" && - test_must_fail git-svn set-tree --find-copies-harder --rmdir \ - remotes/git-svn..mybranch4' || true + 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 && + 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" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && test ! -x "$SVN_TREE"/exec.sh' @@ -127,9 +127,9 @@ 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" && + git svn set-tree --find-copies-harder --rmdir \ + ${remotes_git_svn}..mybranch5 && + svn_cmd up "$SVN_TREE" && test -x "$SVN_TREE"/exec.sh' @@ -139,9 +139,9 @@ test_expect_success "$name" ' 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" && + 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' @@ -151,9 +151,9 @@ test_expect_success "$name" ' 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" && + 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' @@ -164,40 +164,35 @@ test_expect_success "$name" ' 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" && + 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' -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 - say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)" -fi +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 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 @@ -215,45 +210,64 @@ test_expect_success "$name" "test_cmp a expected" 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 + bar:refs/${remotes_git_svn} && + test_must_fail git svn migrate " 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" + "^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 --minimize-url -i bar "$svnrepo/bar" && + git svn init --minimize-url -i bar "$svnrepo/bar" && git config --get svn-remote.svn.fetch \ "^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 f420796c31..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,29 +26,29 @@ 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 --no-auto-props -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 @@ -57,25 +57,25 @@ 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'" @@ -140,12 +140,14 @@ test_expect_success 'test show-ignore' " cd test_wc && mkdir -p deeply/nested/directory && touch deeply/nested/directory/.keep && - svn add deeply && - svn up && - svn propset -R svn:ignore 'no-such-file*' . - svn commit -m 'propset svn:ignore' + 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 " @@ -161,8 +163,8 @@ cat >create-ignore-index.expect <<\EOF EOF test_expect_success 'test create-ignore' " - git-svn fetch && git pull . remotes/git-svn && - git-svn 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 && @@ -171,6 +173,7 @@ test_expect_success 'test create-ignore' " " cat >prop.expect <<\EOF + no-such-file* EOF @@ -182,15 +185,15 @@ EOF # 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 && + 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 \ + 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 + 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 @@ -210,8 +213,8 @@ Properties on 'nested/directory/.keep': EOF test_expect_success 'test proplist' " - git-svn proplist . | cmp - prop.expect && - git-svn proplist nested/directory/.keep | cmp - prop2.expect + 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 0e7ce34b9b..028fb19e09 100755 --- a/t/t9102-git-svn-deep-rmdir.sh +++ b/t/t9102-git-svn-deep-rmdir.sh @@ -1,5 +1,5 @@ #!/bin/sh -test_description='git-svn rmdir' +test_description='git svn rmdir' . ./lib-git-svn.sh test_expect_success 'initialize repo' ' @@ -9,21 +9,21 @@ test_expect_success 'initialize repo' ' 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' ' 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 svn set-tree --rmdir HEAD && + svn_cmd ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1 ' diff --git a/t/t9103-git-svn-tracked-directory-removed.sh b/t/t9103-git-svn-tracked-directory-removed.sh index 9ffd8458ef..3413164cb1 100755 --- a/t/t9103-git-svn-tracked-directory-removed.sh +++ b/t/t9103-git-svn-tracked-directory-removed.sh @@ -3,22 +3,22 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn tracking removed top-level path' +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 import -m initial import "$svnrepo" && + svn_cmd import -m initial import "$svnrepo" && rm -rf import && - svn co "$svnrepo"/trunk trunk && + svn_cmd co "$svnrepo"/trunk trunk && echo bye bye >> trunk/README && - svn rm -m "gone" "$svnrepo"/trunk && + svn_cmd rm -m "gone" "$svnrepo"/trunk && rm -rf trunk && mkdir trunk && echo "new" > trunk/FOLLOWME && - svn import -m "new trunk" trunk "$svnrepo"/trunk + svn_cmd import -m "new trunk" trunk "$svnrepo"/trunk ' test_expect_success 'clone repo with git' ' diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index 4d964e2db7..bbfd7f4793 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -3,7 +3,7 @@ # Copyright (c) 2006 Eric Wong # -test_description='git-svn fetching' +test_description='git svn fetching' . ./lib-git-svn.sh test_expect_success 'initialize repo' ' @@ -11,24 +11,24 @@ test_expect_success 'initialize repo' ' 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 trunk thunk && + 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 --minimize-url -i thunk "$svnrepo"/thunk && - git-svn fetch -i thunk && + 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 |\ @@ -43,7 +43,7 @@ test_expect_success 'init and fetch from one svn-remote' ' trunk:refs/remotes/svn/trunk && git config --add svn-remote.svn.fetch \ thunk:refs/remotes/svn/thunk && - git-svn fetch -i 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 |\ @@ -51,14 +51,14 @@ test_expect_success 'init and fetch from one svn-remote' ' ' test_expect_success 'follow deleted parent' ' - (svn cp -m "resurrecting trunk as junk" \ + (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 && + 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`" @@ -69,9 +69,9 @@ test_expect_success 'follow larger parent' ' 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 --minimize-url -i larger \ + git svn init --minimize-url -i larger \ "$svnrepo"/another-larger/trunk/thunk/bump/thud && - git-svn fetch -i larger && + git svn fetch -i larger && git rev-parse --verify refs/remotes/larger && git rev-parse --verify \ refs/remotes/larger-parent/trunk/thunk/bump/thud && @@ -92,15 +92,15 @@ test_expect_success 'follow higher-level parent' ' cd .. svn mkdir -m "new glob at top level" "$svnrepo"/glob && svn mv -m "move blob down a level" "$svnrepo"/blob "$svnrepo"/glob/blob && - git-svn init --minimize-url -i blob "$svnrepo"/glob/blob && - git-svn fetch -i blob + git svn init --minimize-url -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 --minimize-url -i glob "$svnrepo"/glob && - git-svn fetch -i glob && + 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 ' @@ -120,7 +120,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' ' cd import && 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 && @@ -129,19 +129,19 @@ test_expect_success 'follow-parent avoids deleting relevant info' ' poke native/t/c.t && svn commit -m "reorg test" && cd .. && - git-svn init --minimize-url -i 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 && + 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 --minimize-url -i r9270-d \ + 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 && + 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`" && @@ -149,21 +149,63 @@ test_expect_success "track initial change if it was only made to parent" ' "`git rev-parse r9270-d~1`" ' +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 cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob && - git-svn multi-fetch && + 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 + 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 63230367bb..dd48e9cba8 100755 --- a/t/t9105-git-svn-commit-diff.sh +++ b/t/t9105-git-svn-commit-diff.sh @@ -1,14 +1,14 @@ #!/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' ' 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 && @@ -26,17 +26,17 @@ prev=`git rev-parse --verify HEAD^1` 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 && + 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 --minimize-url "$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 ' diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh index 83896e9687..12f21b700e 100755 --- a/t/t9106-git-svn-commit-diff-clobber.sh +++ b/t/t9106-git-svn-commit-diff-clobber.sh @@ -1,25 +1,25 @@ #!/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' ' 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 && + 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 ' @@ -27,7 +27,7 @@ test_expect_success 'commit change from svn side' ' test_expect_success 'commit conflicting change from git' ' echo second line from git >> file && git commit -a -m "second line from git" && - test_must_fail git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo" + test_must_fail git svn commit-diff -r1 HEAD~1 HEAD "$svnrepo" ' test_expect_success 'commit complementing change from git' ' @@ -36,48 +36,48 @@ test_expect_success 'commit complementing change from git' ' 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 svn commit-diff -r2 HEAD~1 HEAD "$svnrepo" ' 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 co "$svnrepo" t.svn && + 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" && - test_must_fail git-svn dcommit + 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 co "$svnrepo" t.svn && + svn_cmd co "$svnrepo" t.svn && cd t.svn && echo third line from svn >> file && poke file && - svn commit -m "third line from svn" && + 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 && +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' && diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index d9b553ad55..901b8e09fb 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -1,6 +1,6 @@ #!/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' ' @@ -12,36 +12,34 @@ test_expect_success 'setup old-looking metadata' ' 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' ' +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 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" + ":refs/${remotes_git_svn}" ' test_expect_success 'initialize a multi-repository repo' ' - git-svn init "$svnrepo" -T trunk -t tags -b branches && + 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 \ @@ -56,12 +54,20 @@ test_expect_success 'initialize a multi-repository repo' ' 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 + $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 && @@ -79,36 +85,36 @@ test_expect_success 'migrate --minimize on old inited layout' ' rm -rf "$GIT_DIR"/svn && for i in `cat fetch.out`; do path=`expr $i : "\([^:]*\):.*$"` - ref=`expr $i : "[^:]*:refs/remotes/\(.*\)$"` + 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 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 + 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_map.UUID" ' - git-svn fetch -i trunk && - test -z "$(ls "$GIT_DIR"/svn/trunk/.rev_db.* 2>/dev/null)" && - expect="$(ls "$GIT_DIR"/svn/trunk/.rev_map.*)" && + 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/trunk/.rev_db.* 2>/dev/null)" && - test ! -e "$GIT_DIR"/svn/trunk/.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" ' diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh index f6f71d0545..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 @@ -14,30 +14,31 @@ 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 && + 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 && + 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 && poke branches/start/src/a/readme && - svn commit -m "hi" && - svn up && - svn cp branches/start tags/end && + 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 && poke tags/end/src/a/readme && - svn commit -m "the end" && + 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 .. && + 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" && @@ -45,14 +46,15 @@ test_expect_success 'test refspec globbing' ' "branches/*/src/a:refs/remotes/branches/*" && git config --add svn-remote.svn.tags\ "tags/*/src/a:refs/remotes/tags/*" && - git-svn multi-fetch && + git svn multi-fetch && git log --pretty=oneline refs/remotes/tags/end | \ sed -e "s/^.\{41\}//" > output.end && - cmp expect.end 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`" + "`git rev-parse refs/remotes/trunk`" && + test_must_fail git rev-parse refs/remotes/tags/end@3 ' echo try to try > expect.two @@ -66,12 +68,13 @@ test_expect_success 'test left-hand-side only globbing' ' "branches/*:refs/remotes/two/branches/*" && git config --add svn-remote.two.tags \ "tags/*:refs/remotes/two/tags/*" && - cd tmp && + ( + 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 && + 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` = \ @@ -80,7 +83,29 @@ test_expect_success 'test left-hand-side only globbing' ' `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 + 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 04d2a65c08..a06e4c5b8e 100755 --- a/t/t9110-git-svn-use-svm-props.sh +++ b/t/t9110-git-svn-use-svm-props.sh @@ -3,18 +3,18 @@ # 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 --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 \ + 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 + git svn fetch --all ' uuid=161ce429-a9dd-4828-af4a-52023f968c89 @@ -22,40 +22,40 @@ 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$' && + grep '^${git_svn_id}: $bar_url@12 $uuid$' && git cat-file commit refs/remotes/bar~1 | \ - grep '^git-svn-id: $bar_url@11 $uuid$' && + grep '^${git_svn_id}: $bar_url@11 $uuid$' && git cat-file commit refs/remotes/bar~2 | \ - grep '^git-svn-id: $bar_url@10 $uuid$' && + grep '^${git_svn_id}: $bar_url@10 $uuid$' && git cat-file commit refs/remotes/bar~3 | \ - grep '^git-svn-id: $bar_url@9 $uuid$' && + grep '^${git_svn_id}: $bar_url@9 $uuid$' && git cat-file commit refs/remotes/bar~4 | \ - grep '^git-svn-id: $bar_url@6 $uuid$' && + grep '^${git_svn_id}: $bar_url@6 $uuid$' && git cat-file commit refs/remotes/bar~5 | \ - grep '^git-svn-id: $bar_url@1 $uuid$' + 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$' + 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$' && + grep '^${git_svn_id}: $dir_url@2 $uuid$' && git cat-file commit refs/remotes/dir~1 | \ - grep '^git-svn-id: $dir_url@1 $uuid$' + grep '^${git_svn_id}: $dir_url@1 $uuid$' " test_expect_success 'find commit based on SVN revision number' " - git-svn find-rev r12 | + git svn find-rev r12 | grep `git rev-parse HEAD` " test_expect_success 'empty rebase' " - git-svn 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 a8d74dcd3a..bd081c2ec3 100755 --- a/t/t9111-git-svn-use-svnsync-props.sh +++ b/t/t9111-git-svn-use-svnsync-props.sh @@ -3,17 +3,17 @@ # 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 --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 && + 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 + git svn fetch --all ' uuid=161ce429-a9dd-4828-af4a-52023f968c89 @@ -21,31 +21,31 @@ 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$' && + grep '^${git_svn_id}: $bar_url@12 $uuid$' && git cat-file commit refs/remotes/bar~1 | \ - grep '^git-svn-id: $bar_url@11 $uuid$' && + grep '^${git_svn_id}: $bar_url@11 $uuid$' && git cat-file commit refs/remotes/bar~2 | \ - grep '^git-svn-id: $bar_url@10 $uuid$' && + grep '^${git_svn_id}: $bar_url@10 $uuid$' && git cat-file commit refs/remotes/bar~3 | \ - grep '^git-svn-id: $bar_url@9 $uuid$' && + grep '^${git_svn_id}: $bar_url@9 $uuid$' && git cat-file commit refs/remotes/bar~4 | \ - grep '^git-svn-id: $bar_url@6 $uuid$' && + grep '^${git_svn_id}: $bar_url@6 $uuid$' && git cat-file commit refs/remotes/bar~5 | \ - grep '^git-svn-id: $bar_url@1 $uuid$' + 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$' + 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$' && + grep '^${git_svn_id}: $dir_url@2 $uuid$' && git cat-file commit refs/remotes/dir~1 | \ - grep '^git-svn-id: $dir_url@1 $uuid$' + grep '^${git_svn_id}: $dir_url@1 $uuid$' " test_done diff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh index d470a920e4..a61d6716d2 100755 --- a/t/t9112-git-svn-md5less-file.sh +++ b/t/t9112-git-svn-md5less-file.sh @@ -42,6 +42,6 @@ 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_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 index 8da8ce58eb..e8479cec7a 100755 --- a/t/t9113-git-svn-dcommit-new-file.sh +++ b/t/t9113-git-svn-dcommit-new-file.sh @@ -8,26 +8,15 @@ # 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' +test_description='git svn dcommit new files over svn:// test' . ./lib-git-svn.sh -if test -z "$SVNSERVE_PORT" -then - say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)' - test_done - exit -fi - -start_svnserve () { - svnserve --listen-port $SVNSERVE_PORT \ - --root "$rawsvnrepo" \ - --listen-once \ - --listen-host 127.0.0.1 & -} +require_svnserve test_expect_success 'start tracking an empty repo' ' - svn mkdir -m "empty dir" "$svnrepo"/empty-dir && + 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 && diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index 61d7781616..84f7c9b4bb 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Eric Wong # Based on a script by Joakim Tjernlund <joakim.tjernlund@transmode.se> -test_description='git-svn dcommit handles merges' +test_description='git svn dcommit handles merges' . ./lib-git-svn.sh @@ -35,12 +35,12 @@ EOF } test_expect_success 'setup svn repository' ' - svn co "$svnrepo" mysvnwork && + svn_cmd co "$svnrepo" mysvnwork && mkdir -p mysvnwork/trunk && cd mysvnwork && big_text_block >> trunk/README && - svn add trunk && - svn ci -m "first commit" trunk && + svn_cmd add trunk && + svn_cmd ci -m "first commit" trunk && cd .. ' diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh index f0fbd3aff7..767799e7a7 100755 --- a/t/t9115-git-svn-dcommit-funky-renames.sh +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -3,12 +3,12 @@ # Copyright (c) 2007 Eric Wong -test_description='git-svn dcommit can commit renames of files with ugly names' +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" < ../t9115/funky-names.dump && + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump && start_httpd gtk+ ' @@ -19,7 +19,7 @@ test_expect_success 'init and fetch repository' ' ' test_expect_success 'create file in existing ugly and empty dir' ' - mkdir "#{bad_directory_name}" && + 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" && @@ -37,7 +37,7 @@ test_expect_success 'rename pretty file' ' git update-index --add pretty && git commit -m "pretty :x" && git svn dcommit && - mkdir regular_dir_name && + mkdir -p regular_dir_name && git mv pretty regular_dir_name/pretty && git commit -m "moved pretty file" && git svn dcommit @@ -75,7 +75,7 @@ test_expect_success 'make a commit to test rebase' ' git svn dcommit ' -test_expect_success 'git-svn rebase works inside a fresh-cloned repository' ' +test_expect_success 'git svn rebase works inside a fresh-cloned repository' ' cd test-rebase && git svn rebase && test -e test-rebase-main && diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh index 4b2cc878f6..0374a7476b 100755 --- a/t/t9116-git-svn-log.sh +++ b/t/t9116-git-svn-log.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn log tests' +test_description='git svn log tests' . ./lib-git-svn.sh test_expect_success 'setup repository and import' ' @@ -14,10 +14,10 @@ test_expect_success 'setup repository and import' ' 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" -T trunk -b branches -t tags && - git-svn fetch && + 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 && diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh index 7a689bb1cd..b7ef9e2589 100755 --- a/t/t9117-git-svn-init-clone.sh +++ b/t/t9117-git-svn-init-clone.sh @@ -3,7 +3,7 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn init/clone tests' +test_description='git svn init/clone tests' . ./lib-git-svn.sh @@ -16,7 +16,7 @@ cd tmp test_expect_success 'setup svnrepo' ' mkdir project project/trunk project/branches project/tags && echo foo > project/trunk/foo && - svn import -m "$test_description" project "$svnrepo"/project && + svn_cmd import -m "$test_description" project "$svnrepo"/project && rm -rf project ' diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index 3281cbd347..ac52bff0ef 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -3,18 +3,24 @@ # Copyright (c) 2007 Eric Wong # -test_description='git-svn funky branch names' +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 import -m "$test_description" project "$svnrepo/pr ject" && + svn_cmd import -m "$test_description" project "$svnrepo/pr ject" && rm -rf project && - svn cp -m "fun" "$svnrepo/pr ject/trunk" \ + svn_cmd cp -m "fun" "$svnrepo/pr ject/trunk" \ "$svnrepo/pr ject/branches/fun plugin" && - svn cp -m "more fun!" "$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" && start_httpd ' @@ -23,6 +29,7 @@ test_expect_success 'test clone with funky branch names' ' cd project && git rev-parse "refs/remotes/fun%20plugin" && git rev-parse "refs/remotes/more%20fun%20plugin!" && + git rev-parse "refs/remotes/$scary_ref" && cd .. ' @@ -35,6 +42,15 @@ test_expect_success 'test dcommit to funky branch' " cd .. " +test_expect_success 'test dcommit to scary branch' ' + cd project && + git reset --hard "refs/remotes/$scary_ref" && + echo urls are scary >> foo && + git commit -m "eep" -- foo && + git svn dcommit && + cd .. + ' + stop_httpd test_done diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh index cc61911593..95741cbbac 100755 --- a/t/t9119-git-svn-info.sh +++ b/t/t9119-git-svn-info.sh @@ -2,23 +2,41 @@ # # Copyright (c) 2007 David D. Kilzer -test_description='git-svn info' +test_description='git svn info' . ./lib-git-svn.sh -say 'skipping svn-info test (has a race undiagnosed yet)' -test_done + +# Tested with: svn, version 1.4.4 (r25188) +v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'` +case $v in +1.[45].*) + ;; +*) + say "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; - die "$ARGV[0] does not exist" if ! -e $ARGV[0]; - my @s = stat $ARGV[0]; - utime $s[8], $s[9], $ARGV[1]; - ' "$1" "$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" } -test_expect_success 'setup repository and import' " +quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')" + +test_expect_success 'setup repository and import' ' mkdir info && cd info && echo FIRST > A && @@ -27,82 +45,94 @@ test_expect_success 'setup repository and import' " mkdir directory && touch directory/.placeholder && ln -s directory symlink-directory && - svn import -m 'initial' . $svnrepo && + 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 && + git svn init "$svnrepo" && + git svn fetch && cd .. && - svn co $svnrepo svnwc && - ptouch svnwc/file gitwc/file && - ptouch svnwc/directory gitwc/directory && - ptouch svnwc/symlink-file gitwc/symlink-file && - ptouch svnwc/symlink-directory gitwc/symlink-directory - " + 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 && - git-diff expected.info actual.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) = $svnrepo + 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 && - git-diff expected.info-dot actual.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 .) = $svnrepo + 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 && - git-diff expected.info-file actual.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) = "$svnrepo/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 && - git-diff expected.info-directory actual.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) = "$svnrepo/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 && - git-diff expected.info-symlink-file actual.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) \ - = "$svnrepo/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) \ + (cd gitwc; git svn info symlink-directory) \ > actual.info-symlink-directory && - git-diff expected.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) \ - = "$svnrepo/symlink-directory" + test "$(cd gitwc; git svn info --url symlink-directory)" \ + = "$quoted_svnrepo/symlink-directory" ' test_expect_success 'info added-file' " @@ -113,16 +143,16 @@ test_expect_success 'info added-file' " cp gitwc/added-file svnwc/added-file && ptouch gitwc/added-file svnwc/added-file && cd svnwc && - svn add added-file > /dev/null && + 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 && - git-diff expected.info-added-file actual.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) \ - = "$svnrepo/added-file" + test "$(cd gitwc; git svn info --url added-file)" \ + = "$quoted_svnrepo/added-file" ' test_expect_success 'info added-directory' " @@ -130,21 +160,21 @@ test_expect_success 'info added-directory' " ptouch gitwc/added-directory svnwc/added-directory && touch gitwc/added-directory/.placeholder && cd svnwc && - svn add added-directory > /dev/null && + 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) \ + (cd gitwc; git svn info added-directory) \ > actual.info-added-directory && - git-diff expected.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) \ - = "$svnrepo/added-directory" + test "$(cd gitwc; git svn info --url added-directory)" \ + = "$quoted_svnrepo/added-directory" ' test_expect_success 'info added-symlink-file' " @@ -154,20 +184,20 @@ test_expect_success 'info added-symlink-file' " cd .. && cd svnwc && ln -s added-file added-symlink-file && - svn add added-symlink-file > /dev/null && + 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) \ + (cd gitwc; git svn info added-symlink-file) \ > actual.info-added-symlink-file && - git-diff expected.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) \ - = "$svnrepo/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' " @@ -177,20 +207,20 @@ test_expect_success 'info added-symlink-directory' " cd .. && cd svnwc && ln -s added-directory added-symlink-directory && - svn add added-symlink-directory > /dev/null && + 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) \ + (cd gitwc; git svn info added-symlink-directory) \ > actual.info-added-symlink-directory && - git-diff expected.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) \ - = "$svnrepo/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 @@ -203,20 +233,20 @@ test_expect_success 'info deleted-file' " git rm -f file > /dev/null && cd .. && cd svnwc && - svn rm --force file > /dev/null && + 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) | + (cd gitwc; git svn info file) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > actual.info-deleted-file && - git-diff expected.info-deleted-file 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) \ - = "$svnrepo/file" + test "$(cd gitwc; git svn info --url file)" \ + = "$quoted_svnrepo/file" ' test_expect_success 'info deleted-directory' " @@ -224,20 +254,20 @@ test_expect_success 'info deleted-directory' " git rm -r -f directory > /dev/null && cd .. && cd svnwc && - svn rm --force directory > /dev/null && + 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) | + (cd gitwc; git svn info directory) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > actual.info-deleted-directory && - git-diff expected.info-deleted-directory 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) \ - = "$svnrepo/directory" + test "$(cd gitwc; git svn info --url directory)" \ + = "$quoted_svnrepo/directory" ' test_expect_success 'info deleted-symlink-file' " @@ -245,21 +275,21 @@ test_expect_success 'info deleted-symlink-file' " git rm -f symlink-file > /dev/null && cd .. && cd svnwc && - svn rm --force symlink-file > /dev/null && + 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) | + (cd gitwc; git svn info symlink-file) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > actual.info-deleted-symlink-file && - git-diff expected.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) \ - = "$svnrepo/symlink-file" + test "$(cd gitwc; git svn info --url symlink-file)" \ + = "$quoted_svnrepo/symlink-file" ' test_expect_success 'info deleted-symlink-directory' " @@ -267,21 +297,21 @@ test_expect_success 'info deleted-symlink-directory' " git rm -f symlink-directory > /dev/null && cd .. && cd svnwc && - svn rm --force symlink-directory > /dev/null && + 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) | + (cd gitwc; git svn info symlink-directory) | sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \ > actual.info-deleted-symlink-directory && - git-diff expected.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) \ - = "$svnrepo/symlink-directory" + test "$(cd gitwc; git svn info --url symlink-directory)" \ + = "$quoted_svnrepo/symlink-directory" ' # NOTE: git does not have the concept of replaced objects, @@ -289,82 +319,59 @@ test_expect_success 'info --url symlink-directory (deleted)' ' test_expect_success 'info unknown-file' " echo two > gitwc/unknown-file && - cp gitwc/unknown-file svnwc/unknown-file && - ptouch gitwc/unknown-file svnwc/unknown-file && - (cd svnwc; svn info unknown-file) 2> expected.info-unknown-file && - (cd gitwc; git-svn info unknown-file) 2> actual.info-unknown-file && - git-diff expected.info-unknown-file actual.info-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' ' - test -z $(cd gitwc; git-svn info --url unknown-file \ - 2> ../actual.info--url-unknown-file) && - git-diff expected.info-unknown-file actual.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 && - ptouch gitwc/unknown-directory svnwc/unknown-directory && - touch gitwc/unknown-directory/.placeholder && - (cd svnwc; svn info unknown-directory) \ - 2> expected.info-unknown-directory && - (cd gitwc; git-svn info unknown-directory) \ - 2> actual.info-unknown-directory && - git-diff expected.info-unknown-directory actual.info-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' ' - test -z $(cd gitwc; git-svn info --url unknown-directory \ - 2> ../actual.info--url-unknown-directory) && - git-diff expected.info-unknown-directory \ - actual.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 svnwc && - ln -s unknown-file unknown-symlink-file && - cd .. && - ptouch gitwc/unknown-symlink-file svnwc/unknown-symlink-file && - (cd svnwc; svn info unknown-symlink-file) \ - 2> expected.info-unknown-symlink-file && - (cd gitwc; git-svn info unknown-symlink-file) \ - 2> actual.info-unknown-symlink-file && - git-diff expected.info-unknown-symlink-file \ - actual.info-unknown-symlink-file + (cd gitwc; test_must_fail git svn info unknown-symlink-file) \ + 2> actual.info-unknown-symlink-file && + grep unknown-symlink-file actual.info-unknown-symlink-file " test_expect_success 'info --url unknown-symlink-file' ' - test -z $(cd gitwc; git-svn info --url unknown-symlink-file \ - 2> ../actual.info--url-unknown-symlink-file) && - git-diff expected.info-unknown-symlink-file \ - actual.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 svnwc && - ln -s unknown-directory unknown-symlink-directory && - cd .. && - ptouch gitwc/unknown-symlink-directory \ - svnwc/unknown-symlink-directory && - (cd svnwc; svn info unknown-symlink-directory) \ - 2> expected.info-unknown-symlink-directory && - (cd gitwc; git-svn info unknown-symlink-directory) \ - 2> actual.info-unknown-symlink-directory && - git-diff expected.info-unknown-symlink-directory \ - actual.info-unknown-symlink-directory + (cd gitwc; test_must_fail git svn info unknown-symlink-directory) \ + 2> actual.info-unknown-symlink-directory && + grep unknown-symlink-directory actual.info-unknown-symlink-directory " test_expect_success 'info --url unknown-symlink-directory' ' - test -z $(cd gitwc; git-svn info --url unknown-symlink-directory \ - 2> ../actual.info--url-unknown-symlink-directory) && - git-diff expected.info-unknown-symlink-directory \ - actual.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 index 5979e133b9..9d9ebd533c 100755 --- a/t/t9120-git-svn-clone-with-percent-escapes.sh +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -3,28 +3,75 @@ # Copyright (c) 2008 Kevin Ballard # -test_description='git-svn clone with percent escapes' +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 import -m "$test_description" project "$svnrepo/pr ject" && + 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 ' -if test "$SVN_HTTPD_PORT" = "" -then - test_expect_failure 'test clone with percent escapes - needs SVN_HTTPD_PORT set' 'false' -else - 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 .. - ' -fi +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 diff --git a/t/t9121-git-svn-fetch-renamed-dir.sh b/t/t9121-git-svn-fetch-renamed-dir.sh index 99230b0810..000cad37c6 100755 --- a/t/t9121-git-svn-fetch-renamed-dir.sh +++ b/t/t9121-git-svn-fetch-renamed-dir.sh @@ -3,12 +3,12 @@ # Copyright (c) 2008 Santhosh Kumar Mani -test_description='git-svn can fetch renamed directories' +test_description='git svn can fetch renamed directories' . ./lib-git-svn.sh test_expect_success 'load repository with renamed directory' ' - svnadmin load -q "$rawsvnrepo" < ../t9121/renamed-dir.dump + svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9121/renamed-dir.dump ' test_expect_success 'init and fetch repository' ' diff --git a/t/t9122-git-svn-author.sh b/t/t9122-git-svn-author.sh index 1190576a65..30013b7bb9 100755 --- a/t/t9122-git-svn-author.sh +++ b/t/t9122-git-svn-author.sh @@ -4,16 +4,16 @@ test_description='git svn authorship' . ./lib-git-svn.sh test_expect_success 'setup svn repository' ' - svn checkout "$svnrepo" work.svn && + svn_cmd checkout "$svnrepo" work.svn && ( cd work.svn && echo >file - svn add file - svn commit -m "first commit" file + svn_cmd add file + svn_cmd commit -m "first commit" file ) ' -test_expect_success 'interact with it via git-svn' ' +test_expect_success 'interact with it via git svn' ' mkdir work.git && ( cd work.git && @@ -74,10 +74,10 @@ test_expect_success 'interact with it via git-svn' ' # Make sure there are no svn commit messages with excess blank lines ( cd work.svn && - svn up && + svn_cmd up && - test $(svn log -r2:2 | wc -l) = 5 && - test $(svn log -r4:4 | wc -l) = 7 + test $(svn_cmd log -r2:2 | wc -l) = 5 && + test $(svn_cmd log -r4:4 | wc -l) = 7 ) ' diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh index c18878fad1..045521615c 100755 --- a/t/t9123-git-svn-rebuild-with-rewriteroot.sh +++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh @@ -3,21 +3,21 @@ # Copyright (c) 2008 Jan Krüger # -test_description='git-svn respects rewriteRoot during rebuild' +test_description='git svn respects rewriteRoot during rebuild' . ./lib-git-svn.sh mkdir import cd import touch foo - 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 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 + git checkout -b mybranch ${remotes_git_svn} ' test_expect_success 'remove rev_map' ' 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..b9224bdb20 --- /dev/null +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -0,0 +1,95 @@ +#!/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" +} + +compare_svn_head_with () { + # extract just the log message and strip out committer info. + # don't use --limit here since svn 1.1.x doesn't have it, + LC_ALL=en_US.UTF-8 svn log `git svn info --url` | perl -w -e ' + 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 + +if locale -a |grep -q en_US.utf8; then + test_set_prereq UTF8 +else + say "UTF-8 locale not available, test skipped" +fi + +test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' ' + ( + cd ISO8859-1 && + 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/t9106-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh index bc37db9d62..636ca0abb9 100755 --- a/t/t9106-git-svn-dcommit-clobber-series.sh +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -1,14 +1,14 @@ #!/bin/sh # # Copyright (c) 2007 Eric Wong -test_description='git-svn dcommit clobber series' +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 import -m "initial" . "$svnrepo" && + svn_cmd import -m "initial" . "$svnrepo" && cd .. && git svn init "$svnrepo" && git svn fetch && @@ -18,14 +18,14 @@ test_expect_success 'initialize repo' ' 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 co "$svnrepo" tmp && + 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 commit -m "58 => 5588, 61 => 6611" && + svn_cmd commit -m "58 => 5588, 61 => 6611" && cd .. ' @@ -46,7 +46,7 @@ test_expect_success 'change file but in unrelated area' " test x\"\`sed -n -e 7p < file\`\" = x7777 && git commit -m '4 => 4444, 7 => 7777' file && git svn dcommit && - svn up tmp && + svn_cmd up tmp && cd tmp && test x\"\`sed -n -e 4p < file\`\" = x4444 && test x\"\`sed -n -e 7p < file\`\" = x7777 && 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..99f69c6a0b --- /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..53581425c4 --- /dev/null +++ b/t/t9150-svk-mergetickets.sh @@ -0,0 +1,24 @@ +#!/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 \ + -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..3569c62096 --- /dev/null +++ b/t/t9151-svn-mergeinfo.sh @@ -0,0 +1,41 @@ +#!/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 \ + -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_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..3d73f140f8 --- /dev/null +++ b/t/t9151/make-svnmerge-dump @@ -0,0 +1,222 @@ +#!/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 "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 +i=$(commit $i "make partial branch") +svn cp trunk/subdir branches/partial + +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 +i=$(commit $i "tagging v1.0") +svn cp trunk tags/v1.0 + +say "Branching BUGFIX from v1.0" +svn update +i=$(commit $i "make bugfix branch from tag") +svn cp tags/v1.0 branches/bugfix + +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..ebf386ebd5 --- /dev/null +++ b/t/t9151/svn-mergeinfo.dump @@ -0,0 +1,1922 @@ +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: 135 +Content-length: 135 + +K 7 +svn:log +V 37 +(r25) add subdirectory to left branch +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:46.052649Z +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: 26 +Prop-content-length: 123 +Content-length: 123 + +K 7 +svn:log +V 25 +(r26) merge left to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:49.040783Z +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-25 +/branches/left-sub:4-19 +/branches/right:2-22 +PROPS-END + + +Node-path: trunk/subdir +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 25 +Node-copyfrom-path: branches/left/subdir + + +Revision-number: 27 +Prop-content-length: 118 +Content-length: 118 + +K 7 +svn:log +V 20 +(r28) partial update +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:53.049037Z +PROPS-END + +Node-path: branches/partial +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 26 +Node-copyfrom-path: trunk/subdir + + +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: 28 +Prop-content-length: 126 +Content-length: 126 + +K 7 +svn:log +V 28 +(r29) merge partial to trunk +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:14:56.041526Z +PROPS-END + +Node-path: trunk/subdir +Node-kind: dir +Node-action: change +Prop-content-length: 142 +Content-length: 142 + +K 13 +svn:mergeinfo +V 106 +/branches/left/subdir:2-25 +/branches/left-sub/subdir:4-19 +/branches/partial:27 +/branches/right/subdir:2-22 +PROPS-END + + +Node-path: trunk/subdir/palindromes +Node-kind: file +Node-action: add +Node-copyfrom-rev: 27 +Node-copyfrom-path: branches/partial/palindromes +Text-copy-source-md5: 5d1c2024fb5efc4eef812856df1b080c +Text-copy-source-sha1: 5f8509ddd14c91a52864dd1447344e706f9bbc69 + + +Revision-number: 29 +Prop-content-length: 131 +Content-length: 131 + +K 7 +svn:log +V 33 +(r31) make bugfix branch from tag +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:15:00.039761Z +PROPS-END + +Node-path: tags/v1.0 +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 28 +Node-copyfrom-path: trunk + + +Revision-number: 30 +Prop-content-length: 120 +Content-length: 120 + +K 7 +svn:log +V 22 +(r32) commit to bugfix +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:15:03.043218Z +PROPS-END + +Node-path: branches/bugfix +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 29 +Node-copyfrom-path: tags/v1.0 + + +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: 31 +Prop-content-length: 125 +Content-length: 125 + +K 7 +svn:log +V 27 +(r33) Merge BUGFIX to TRUNK +K 10 +svn:author +V 3 +adm +K 8 +svn:date +V 27 +2010-01-19T04:15:06.043723Z +PROPS-END + +Node-path: trunk +Node-kind: dir +Node-action: change +Prop-content-length: 133 +Content-length: 133 + +K 13 +svn:mergeinfo +V 98 +/branches/bugfix:30 +/branches/left:2-25 +/branches/left-sub:4-19 +/branches/right:2-22 +/tags/v1.0:29 +PROPS-END + + +Node-path: trunk/subdir +Node-kind: dir +Node-action: change +Prop-content-length: 190 +Content-length: 190 + +K 13 +svn:mergeinfo +V 154 +/branches/bugfix/subdir:30 +/branches/left/subdir:2-25 +/branches/left-sub/subdir:4-19 +/branches/partial:27 +/branches/right/subdir:2-22 +/tags/v1.0/subdir:29 +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 3e32e84e6c..fc3795dc98 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -6,12 +6,16 @@ test_description='Test export of commits to CVS' . ./test-lib.sh +if ! test_have_prereq PERL; then + say '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' : + say 'skipping git cvsexportcommit tests, cvs not found' test_done - exit fi CVSROOT=$(pwd)/cvsroot @@ -45,8 +49,8 @@ test_expect_success \ '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 && @@ -71,8 +75,8 @@ 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" && @@ -91,7 +95,7 @@ test_expect_success \ diff 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 && @@ -160,24 +164,24 @@ 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 && + 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 + git cvsexportcommit -c $id check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/" )' @@ -197,12 +201,12 @@ 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 && + 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/" @@ -222,14 +226,15 @@ test_expect_success \ git commit -a -m "Update two" && id=$(git rev-list --max-count=1 HEAD) && (cd "$CVSWORK" && - test_must_fail git-cvsexportcommit -c $id + test_must_fail git cvsexportcommit -c $id )' -case "$(git 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 && @@ -239,12 +244,10 @@ 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 && @@ -285,6 +288,27 @@ test_expect_success 'check files before directories' ' ' +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" && @@ -292,7 +316,7 @@ test_expect_success 'commit a file with leading spaces in the name' ' 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/|release-notes/1.2/" && + check_entries "$CVSWORK" " space/1.1/|DS/1.1/|attic_gremlin/1.3/|release-notes/1.2/" && test_cmp "$CVSWORK/ space" " space" ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 1fc06c5a23..131f032988 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,10 +56,16 @@ 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 fast-import --export-marks=marks.out <input && git whatchanged master' test_expect_success \ 'A: verify pack' \ @@ -102,6 +108,18 @@ test_expect_success \ 'git cat-file blob master:file4 >actual && test_cmp expect actual' cat >expect <<EOF +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` @@ -113,7 +131,7 @@ test_expect_success \ test_expect_success \ 'A: verify marks import' \ - 'git-fast-import \ + 'git fast-import \ --import-marks=marks.out \ --export-marks=marks.new \ </dev/null && @@ -133,7 +151,7 @@ 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 fast-import --import-marks=marks.out <input && git whatchanged verify--import-marks' test_expect_success \ 'A: verify pack' \ @@ -166,7 +184,7 @@ M 755 0000000000000000000000000000000000000001 zero1 INPUT_END test_expect_success 'B: fail on invalid blob sha1' ' - test_must_fail git-fast-import <input + test_must_fail git fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -181,7 +199,7 @@ from refs/heads/master INPUT_END test_expect_success 'B: fail on invalid branch name ".badbranchname"' ' - test_must_fail git-fast-import <input + test_must_fail git fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -196,7 +214,7 @@ 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 + test_must_fail git fast-import <input ' rm -f .git/objects/pack_* .git/objects/index_* @@ -212,7 +230,7 @@ from refs/heads/master INPUT_END test_expect_success \ 'B: accept branch name "TEMP_TAG"' \ - 'git-fast-import <input && + 'git fast-import <input && test -f .git/TEMP_TAG && test `git rev-parse master` = `git rev-parse TEMP_TAG^`' rm -f .git/TEMP_TAG @@ -221,7 +239,7 @@ rm -f .git/TEMP_TAG ### series C ### -newf=`echo hi newf | git-hash-object -w --stdin` +newf=`echo hi newf | git hash-object -w --stdin` oldf=`git rev-parse --verify master:file2` test_tick cat >input <<INPUT_END @@ -239,7 +257,7 @@ D file3 INPUT_END test_expect_success \ 'C: incremental import create pack from stdin' \ - 'git-fast-import <input && + 'git fast-import <input && git whatchanged branch' test_expect_success \ 'C: verify pack' \ @@ -297,7 +315,7 @@ EOF INPUT_END test_expect_success \ 'D: inline data in commit' \ - 'git-fast-import <input && + 'git fast-import <input && git whatchanged branch' test_expect_success \ 'D: verify pack' \ @@ -340,11 +358,11 @@ from refs/heads/branch^0 INPUT_END test_expect_success 'E: rfc2822 date, --date-format=raw' ' - test_must_fail git-fast-import --date-format=raw <input + 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' @@ -381,7 +399,7 @@ 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 @@ -431,7 +449,7 @@ 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' @@ -467,7 +485,7 @@ EOF INPUT_END test_expect_success \ 'H: deletall, add 1' \ - 'git-fast-import <input && + 'git fast-import <input && git whatchanged H' test_expect_success \ 'H: verify pack' \ @@ -507,7 +525,7 @@ 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` @@ -541,7 +559,7 @@ 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` && @@ -571,7 +589,7 @@ 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` \ @@ -623,7 +641,7 @@ EXPECT_END test_expect_success \ 'L: verify internal tree sorting' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree --abbrev --raw L^ L >output && test_cmp expect output' @@ -649,7 +667,7 @@ cat >expect <<EOF EOF test_expect_success \ 'M: rename file in same subdirectory' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree -M -r M1^ M1 >actual && compare_diff_raw expect actual' @@ -670,7 +688,7 @@ cat >expect <<EOF EOF test_expect_success \ 'M: rename file to new subdirectory' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree -M -r M2^ M2 >actual && compare_diff_raw expect actual' @@ -691,7 +709,7 @@ cat >expect <<EOF EOF test_expect_success \ 'M: rename subdirectory to new subdirectory' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree -M -r M3^ M3 >actual && compare_diff_raw expect actual' @@ -717,7 +735,7 @@ cat >expect <<EOF EOF test_expect_success \ 'N: copy file in same subdirectory' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree -C --find-copies-harder -r N1^ N1 >actual && compare_diff_raw expect actual' @@ -751,7 +769,7 @@ cat >expect <<EOF EOF test_expect_success \ 'N: copy then modify subdirectory' \ - 'git-fast-import <input && + 'git fast-import <input && git diff-tree -C --find-copies-harder -r N2^^ N2 >actual && compare_diff_raw expect actual' @@ -775,8 +793,8 @@ INPUT_END test_expect_success \ 'N: copy dirty subdirectory' \ - 'git-fast-import <input && - test `git-rev-parse N2^{tree}` = `git-rev-parse N3^{tree}`' + 'git fast-import <input && + test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`' ### ### series O @@ -815,8 +833,8 @@ INPUT_END test_expect_success \ 'O: comments are all skipped' \ - 'git-fast-import <input && - test `git-rev-parse N3` = `git-rev-parse O1`' + 'git fast-import <input && + test `git rev-parse N3` = `git rev-parse O1`' cat >input <<INPUT_END commit refs/heads/O2 @@ -836,8 +854,8 @@ 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`' + 'git fast-import <input && + test `git rev-parse N3` = `git rev-parse O2`' test_expect_success \ 'O: repack before next test' \ @@ -881,7 +899,7 @@ commits INPUT_END test_expect_success \ 'O: blank lines not necessary after other commands' \ - 'git-fast-import <input && + '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 && @@ -914,7 +932,7 @@ progress I'm done! INPUT_END test_expect_success \ 'O: progress outputs as requested by input' \ - 'git-fast-import <input >actual && + 'git fast-import <input >actual && grep "progress " <input >expect && test_cmp expect actual' @@ -979,18 +997,18 @@ INPUT_END test_expect_success \ 'P: supermodule & submodule mix' \ - 'git-fast-import <input && + 'git fast-import <input && git checkout subuse1 && rm -rf sub && mkdir sub && cd sub && git init && - git fetch .. refs/heads/sub:refs/heads/master && + 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^) +SUBLAST=$(git rev-parse --verify sub) +SUBPREV=$(git rev-parse --verify sub^) cat >input <<INPUT_END blob @@ -1024,8 +1042,8 @@ 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)' + git fast-import <input && + test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)' test_tick cat >input <<INPUT_END @@ -1045,7 +1063,7 @@ DATA INPUT_END test_expect_success 'P: fail on inline gitlink' ' - ! git-fast-import <input' + test_must_fail git fast-import <input' test_tick cat >input <<INPUT_END @@ -1068,6 +1086,500 @@ M 160000 :1 sub INPUT_END test_expect_success 'P: fail on blob mark in gitlink' ' - ! git-fast-import <input' + 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-export.sh b/t/t9301-fast-export.sh deleted file mode 100755 index 8324f6e3bd..0000000000 --- a/t/t9301-fast-export.sh +++ /dev/null @@ -1,188 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2007 Johannes E. Schindelin -# - -test_description='git-fast-export' -. ./test-lib.sh - -test_expect_success 'setup' ' - - 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 master..partial && - git diff master^..partial^ && - test_must_fail git rev-parse partial~2) - -' - -test_expect_success 'iso-8859-1' ' - - git config i18n.commitencoding ISO-8859-1 && - # use author and committer name in ISO-8859-1 to match it. - . ../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 && - cd .. && - 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 && - cd .. && - 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) - -' - -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..356964e53a --- /dev/null +++ b/t/t9350-fast-export.sh @@ -0,0 +1,374 @@ +#!/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 && + cd .. && + 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 && + cd .. && + 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" && + cd .. +' + +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 && + cd .. +' + +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 && + cd .. +' + +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 && + cd .. +' + + +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 index 4b91f8d4c4..4327eb8baa 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -10,17 +10,19 @@ cvs CLI client via git-cvsserver server' . ./test-lib.sh +if ! test_have_prereq PERL; then + say 'skipping git cvsserver tests, perl not available' + test_done +fi cvs >/dev/null 2>&1 if test $? -ne 1 then - test_expect_success 'skipping git-cvsserver tests, cvs not found' : + say 'skipping git-cvsserver tests, cvs not found' test_done - exit fi -perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { - test_expect_success 'skipping git-cvsserver tests, Perl SQLite interface unavailable' : +"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { + say 'skipping git-cvsserver tests, Perl SQLite interface unavailable' test_done - exit } unset GIT_DIR GIT_CONFIG @@ -44,7 +46,7 @@ test_expect_success 'setup' ' git add secondrootfile && git commit -m "second root") && git pull secondroot master && - git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 && + 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" ' @@ -94,7 +96,7 @@ EOF test_expect_success 'pserver authentication' \ 'cat request-anonymous | git-cvsserver pserver >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU$"' + 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 @@ -103,11 +105,11 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \ else true fi && - sed -ne \$p log | grep "^I HATE YOU$"' + sed -ne \$p log | grep "^I HATE YOU\$"' test_expect_success 'pserver authentication (login)' \ 'cat login-anonymous | git-cvsserver pserver >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU$"' + 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 @@ -116,7 +118,7 @@ test_expect_success 'pserver authentication failure (login/non-anonymous user)' else true fi && - sed -ne \$p log | grep "^I HATE YOU$"' + sed -ne \$p log | grep "^I HATE YOU\$"' # misuse pserver authentication for testing of req_Root @@ -154,7 +156,7 @@ test_expect_success 'req_Root failure (conflicting roots)' \ 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$"' + sed -ne \$p log | grep "^I LOVE YOU\$"' test_expect_success 'req_Root failure (strict-paths)' ' ! cat request-anonymous | @@ -163,7 +165,7 @@ test_expect_success 'req_Root failure (strict-paths)' ' 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$"' + sed -ne \$p log | grep "^I LOVE YOU\$"' test_expect_success 'req_Root failure (w/o strict-paths)' ' ! cat request-anonymous | @@ -181,7 +183,7 @@ 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$"' + sed -ne \$p log | grep "^I LOVE YOU\$"' test_expect_success 'req_Root failure (base-path)' ' ! cat request-anonymous | @@ -192,14 +194,14 @@ 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$"' + 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$"' + sed -ne \$p log | grep "^I LOVE YOU\$"' GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1 @@ -267,7 +269,7 @@ test_expect_success 'gitcvs.ext.dbname' \ rm -fr "$SERVERDIR" cd "$WORKDIR" && -git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 && +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 @@ -424,7 +426,7 @@ cd "$WORKDIR" test_expect_success 'cvs update (-p)' ' touch really-empty && echo Line 1 > no-lf && - echo -n Line 2 >> 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 && @@ -488,4 +490,17 @@ test_expect_success 'cvs co -c (shows module database)' ' ! 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 index e27a1c5f85..ed7b513f3e 100755 --- a/t/t9401-git-cvsserver-crlf.sh +++ b/t/t9401-git-cvsserver-crlf.sh @@ -11,14 +11,6 @@ repository using cvs CLI client via git-cvsserver server' . ./test-lib.sh -q_to_nul () { - perl -pe 'y/Q/\000/' -} - -q_to_cr () { - tr Q '\015' -} - marked_as () { foundEntry="$(grep "^/$2/" "$1/CVS/Entries")" if [ x"$foundEntry" = x"" ] ; then @@ -49,14 +41,17 @@ not_present() { cvs >/dev/null 2>&1 if test $? -ne 1 then - test_expect_success 'skipping git-cvsserver tests, cvs not found' : + say 'skipping git-cvsserver tests, cvs not found' + test_done +fi +if ! test_have_prereq PERL +then + say 'skipping git-cvsserver tests, perl not available' test_done - exit fi -perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { - test_expect_success 'skipping git-cvsserver tests, Perl SQLite interface unavailable' : +"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || { + say 'skipping git-cvsserver tests, Perl SQLite interface unavailable' test_done - exit } unset GIT_DIR GIT_CONFIG @@ -84,7 +79,7 @@ test_expect_success 'setup' ' 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 --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 && + 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" ' diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index ae7082be1d..2fc7fdb124 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -9,75 +9,8 @@ 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_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:///$safe_pwd/../../gitweb/gitweb.css"); -our \$logo = "file:///$safe_pwd/../../gitweb/git-logo.png"; -our \$favicon = "file:///$safe_pwd/../../gitweb/git-favicon.png"; -our \$projects_list = ""; -our \$export_ok = ""; -our \$strict_export = ""; -EOF - - cat >.git/description <<EOF -$0 test repository -EOF -} - -gitweb_run () { - GATEWAY_INTERFACE="CGI/1.1" - HTTP_ACCEPT="*/*" - REQUEST_METHOD="GET" - QUERY_STRING=""$1"" - PATH_INFO=""$2"" - export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD 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 -- "$(pwd)/../../gitweb/gitweb.perl" \ - >/dev/null 2>gitweb.log && - if grep -q -s "^[[]" gitweb.log >/dev/null; then false; else true; fi - - # gitweb.log is left for debugging -} - -safe_chmod () { - chmod "$1" "$2" && - if [ "$(git config --get core.filemode)" = false ] - then - git update-index --chmod="$1" "$2" - fi -} - -. ./test-lib.sh - -perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || { - test_expect_success 'skipping gitweb tests, perl version is too old' : - test_done - exit -} - -gitweb_init +. ./gitweb-lib.sh # ---------------------------------------------------------------------- # no commits (empty, just initialized repository) @@ -240,7 +173,7 @@ test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): mode change' \ - 'safe_chmod +x new_file && + 'test_chmod +x new_file && git commit -a -m "Mode changed." && gitweb_run "p=.git;a=commitdiff"' test_debug 'cat gitweb.log' @@ -252,7 +185,7 @@ test_expect_success \ gitweb_run "p=.git;a=commitdiff"' test_debug 'cat gitweb.log' -test_expect_success \ +test_expect_success SYMLINKS \ 'commitdiff(0): file to symlink' \ 'rm renamed_file && ln -s file renamed_file && @@ -279,7 +212,7 @@ test_debug 'cat gitweb.log' test_expect_success \ 'commitdiff(0): mode change and modified' \ 'echo "New line" >> file2 && - safe_chmod +x file2 && + test_chmod +x file2 && git commit -a -m "Mode change and modification." && gitweb_run "p=.git;a=commitdiff"' test_debug 'cat gitweb.log' @@ -306,7 +239,7 @@ test_expect_success \ 'commitdiff(0): renamed, mode change and modified' \ 'git mv file3 file2 && echo "Propter nomen suum." >> file2 && - safe_chmod +x 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' @@ -314,7 +247,7 @@ test_debug 'cat gitweb.log' # ---------------------------------------------------------------------- # commitdiff testing (taken from t4114-apply-typechange.sh) -test_expect_success 'setup typechange commits' ' +test_expect_success SYMLINKS 'setup typechange commits' ' echo "hello world" > foo && echo "hi planet" > bar && git update-index --add foo bar && @@ -423,10 +356,15 @@ test_expect_success \ git add 03-new && git mv 04-rename-from 04-rename-to && echo "Changed" >> 04-rename-to && - safe_chmod +x 05-mode-change && - rm -f 06-file-or-symlink && ln -s 01-change 06-file-or-symlink && + 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 && - safe_chmod +x 07-change-mode-change && + test_chmod +x 07-change-mode-change && git commit -a -m "Large commit" && git checkout master' @@ -503,6 +441,55 @@ test_expect_success \ 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 \ @@ -525,20 +512,20 @@ test_debug 'cat gitweb.log' test_expect_success \ 'encode(commit): utf8' \ - '. ../t3901-utf8.txt && + '. "$TEST_DIRECTORY"/t3901-utf8.txt && echo "UTF-8" >> file && git add file && - git commit -F ../t3900/1-UTF-8.txt && + 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' \ - '. ../t3901-8859-1.txt && + '. "$TEST_DIRECTORY"/t3901-8859-1.txt && echo "ISO-8859-1" >> file && git add file && git config i18n.commitencoding ISO-8859-1 && - git commit -F ../t3900/ISO-8859-1.txt && + 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' @@ -608,20 +595,48 @@ cat >>gitweb_config.perl <<EOF \$feature{'blame'}{'override'} = 1; \$feature{'snapshot'}{'override'} = 1; +\$feature{'avatar'}{'override'} = 1; EOF 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' \ + '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' + 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..d196cc5ca9 --- /dev/null +++ b/t/t9501-gitweb-standalone-http-status.sh @@ -0,0 +1,137 @@ +#!/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_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 index 0d7786a8c7..363345faef 100755 --- a/t/t9600-cvsimport.sh +++ b/t/t9600-cvsimport.sh @@ -1,44 +1,22 @@ #!/bin/sh -test_description='git-cvsimport basic tests' -. ./test-lib.sh +test_description='git cvsimport basic tests' +. ./lib-cvs.sh -CVSROOT=$(pwd)/cvsroot -export CVSROOT -unset CVS_SERVER -# for clean cvsps cache -HOME=$(pwd) -export HOME - -if ! type cvs >/dev/null 2>&1 -then - say 'skipping cvsimport tests, cvs not found' +if ! test_have_prereq PERL; then + say 'skipping git cvsimport tests, perl not available' test_done - exit fi -cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'` -case "$cvsps_version" in -2.1 | 2.2*) - ;; -'') - say 'skipping cvsimport tests, cvsps not found' - test_done - exit - ;; -*) - say 'skipping cvsimport tests, unsupported cvsps version' - test_done - exit - ;; -esac +CVSROOT=$(pwd)/cvsroot +export CVSROOT -test_expect_success 'setup cvsroot' 'cvs init' +test_expect_success 'setup cvsroot' '$CVS init' test_expect_success 'setup a cvs module' ' mkdir "$CVSROOT/module" && - cvs co -d module-cvs module && + $CVS co -d module-cvs module && cd module-cvs && cat <<EOF >o_fortuna && O Fortuna @@ -57,13 +35,13 @@ egestatem, potestatem dissolvit ut glaciem. EOF - cvs add o_fortuna && + $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 && + $CVS commit -F message && cd .. ' @@ -101,7 +79,7 @@ translate to English My Latin is terrible. EOF - cvs commit -F message && + $CVS commit -F message && cd .. ' @@ -119,8 +97,8 @@ test_expect_success 'update cvs module' ' cd module-cvs && echo 1 >tick && - cvs add tick && - cvs commit -m 1 + $CVS add tick && + $CVS commit -m 1 cd .. ' @@ -138,7 +116,7 @@ test_expect_success 'cvsimport.module config works' ' test_expect_success 'import from a CVS working tree' ' - cvs co -d import-from-wt module && + $CVS co -d import-from-wt module && cd import-from-wt && git cvsimport -a -z0 && echo 1 >expect && @@ -148,4 +126,6 @@ test_expect_success 'import from a CVS working tree' ' ' +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 index 9706ee5773..8686086dde 100755 --- a/t/t9700-perl-git.sh +++ b/t/t9700-perl-git.sh @@ -6,8 +6,13 @@ test_description='perl interface (Git.pm)' . ./test-lib.sh -perl -MTest::More -e 0 2>/dev/null || { - say_color skip "Perl Test::More unavailable, skipping test" +if ! test_have_prereq PERL; then + say 'skipping perl interface tests, perl not available' + test_done +fi + +"$PERL_PATH" -MTest::More -e 0 2>/dev/null || { + say "Perl Test::More unavailable, skipping test" test_done } @@ -24,21 +29,25 @@ test_expect_success \ 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 + 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 ' test_external_without_stderr \ 'Perl API' \ - perl ../t9700/test.pl + "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl test_done diff --git a/t/t9700/test.pl b/t/t9700/test.pl index 4d2312548a..666722d9bf 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -9,15 +9,11 @@ use Test::More qw(no_plan); use Cwd; use File::Basename; -use File::Temp; BEGIN { use_ok('Git') } # set up -our $repo_dir = "trash directory"; -our $abs_repo_dir = Cwd->cwd; -die "this must be run by calling the t/t97* shell script(s)\n" - if basename(Cwd->cwd) ne $repo_dir; +our $abs_repo_dir = cwd(); ok(our $r = Git->repository(Directory => "."), "open repository"); # config @@ -38,7 +34,7 @@ is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color"); # 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; +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") }; @@ -69,32 +65,43 @@ is($r->ident_person("Name", "email", "123 +0000"), "Name <email>", # objects and hashes ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)"); -our $tmpfile = File::Temp->new; -is($r->cat_blob($file1hash, $tmpfile), 15, "cat_blob: size"); +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 $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; } is($blobcontents, "changed file 1\n", "cat_blob: data"); -seek $tmpfile, 0, 0; +close TEMPFILE or die "Failed writing to $tmpfile: $!"; is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip"); -$tmpfile = File::Temp->new(); -print $tmpfile my $test_text = "test blob, to be inserted\n"; +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"); -$tmpfile = File::Temp->new; -is($r->cat_blob($newhash, $tmpfile), length $test_text, "cat_blob: roundtrip size"); -{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +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, "./.git", "repo_path"); +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"); -TODO: { - local $TODO = "commands do not work after wc_chdir"; - # Failure output is active even in non-verbose mode and thus - # annoying. Hence we skip these tests as long as they fail. - todo_skip 'config after wc_chdir', 1; - is($r->config("color.string"), "value", "config 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'); diff --git a/t/test-lib.sh b/t/test-lib.sh index 11c027571b..afd3053f96 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -3,6 +3,22 @@ # Copyright (c) 2005 Junio C Hamano # +# 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 @@ -14,7 +30,7 @@ TZ=UTC TERM=dumb export LANG LC_ALL PAGER TERM TZ EDITOR=: -VISUAL=: +unset VISUAL unset GIT_EDITOR unset AUTHOR_DATE unset AUTHOR_EMAIL @@ -42,7 +58,7 @@ 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 GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u} # Protect ourselves from common misconfiguration to export @@ -58,6 +74,12 @@ 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... @@ -82,20 +104,29 @@ do -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) - export GIT_TEST_LONG=t; shift ;; + GIT_TEST_LONG=t; export GIT_TEST_LONG; shift ;; -h|--h|--he|--hel|--help) help=t; shift ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; -q|--q|--qu|--qui|--quie|--quiet) quiet=t; shift ;; + --with-dashes) + with_dashes=t; shift ;; --no-color) color=; shift ;; --no-python) # noop now... shift ;; + --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) + valgrind=t; verbose=t; shift ;; + --tee) + shift ;; # was handled already + --root=*) + root=$(expr "z$1" : 'z[^=]*=\(.*\)') + shift ;; *) - break ;; + echo "error: unknown test option '$1'" >&2; exit 1 ;; esac done @@ -112,8 +143,9 @@ if test -n "$color"; then *) test -n "$quiet" && return;; esac shift - echo "* $*" + printf "* %s" "$*" tput sgr0 + echo ) } else @@ -126,7 +158,7 @@ fi error () { say_color error "error: $*" - trap - exit + GIT_EXIT_OK=t exit 1 } @@ -158,11 +190,18 @@ test_broken=0 test_success=0 die () { - echo >&5 "FATAL: Unexpected exit with code $?" - exit 1 + code=$? + if test -n "$GIT_EXIT_OK" + then + exit $code + else + echo >&5 "FATAL: Unexpected exit with code $code" + exit 1 + fi } -trap 'die' exit +GIT_EXIT_OK= +trap 'die' EXIT # The semantics of the editor variables are that of invoking # sh -c "$EDITOR \"$@\"" files ... @@ -176,8 +215,35 @@ trap 'die' exit test_set_editor () { FAKE_EDITOR="$1" export FAKE_EDITOR - VISUAL='"$FAKE_EDITOR"' - export VISUAL + 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 () { @@ -192,32 +258,87 @@ 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) - test_success=$(expr "$test_success" + 1) + test_success=$(($test_success + 1)) say_color "" " ok $test_count: $@" } test_failure_ () { - test_count=$(expr "$test_count" + 1) - test_failure=$(expr "$test_failure" + 1); + test_failure=$(($test_failure + 1)) say_color error "FAIL $test_count: $1" shift echo "$@" | sed -e 's/^/ /' - test "$immediate" = "" || { trap - exit; exit 1; } + test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; } } test_known_broken_ok_ () { - test_count=$(expr "$test_count" + 1) test_fixed=$(($test_fixed+1)) say_color "" " FIXED $test_count: $@" } test_known_broken_failure_ () { - test_count=$(expr "$test_count" + 1) test_broken=$(($test_broken+1)) say_color skip " still broken $test_count: $@" } @@ -233,20 +354,23 @@ test_run_ () { } 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 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_color skip >&3 "skipping test: $@" - test_count=$(expr "$test_count" + 1) say_color skip "skip $test_count: $1" : true ;; @@ -257,8 +381,9 @@ 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 "checking known breakage: $2" @@ -267,15 +392,16 @@ test_expect_failure () { then test_known_broken_ok_ "$1" else - test_known_broken_failure_ "$1" + 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" @@ -291,8 +417,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" @@ -316,15 +443,16 @@ test_expect_code () { # Usage: test_external description command arguments... # Example: test_external 'Perl API' perl ../path/to/test.pl test_external () { - test "$#" -eq 3 || - error >&5 "bug in the test script: not 3 parameters to 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 $(expr "$test_count" + 1): $descr ($*)" + say_color "" " run $test_count: $descr ($*)" # Run command; redirect its stderr to &4 as in # test_run_, but keep its stdout on our stdout even in # non-verbose mode. @@ -406,19 +534,19 @@ test_create_repo () { 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/" >&3 2>&4 || + "$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%-*}-$$" + test_results_path="$test_results_dir/${0%.sh}-$$" echo "total $test_count" >> $test_results_path echo "success $test_success" >> $test_results_path @@ -440,15 +568,12 @@ test_done () { fi case "$test_failure" in 0) - # We could: - # cd .. && rm -fr 'trash directory' - # 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_color pass "passed all $msg" + + test -d "$remove_trash" && + cd "$(dirname "$remove_trash")" && + rm -rf "$(basename "$remove_trash")" + exit 0 ;; *) @@ -461,33 +586,127 @@ test_done () { # Test the binaries we have just built. The tests are kept in # t/ subdirectory and are run in 'trash directory' subdirectory. TEST_DIRECTORY=$(pwd) -PATH=$TEST_DIRECTORY/..:$PATH -GIT_EXEC_PATH=$(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 unset GIT_CONFIG -unset GIT_CONFIG_LOCAL 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 + GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git export GITPERLLIB 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' exit 1 fi -. ../GIT-BUILD-OPTIONS - # Test repository -test="trash directory" +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" || { - trap - exit + GIT_EXIT_OK=t echo >&5 "FATAL: Cannot prepare test area" exit 1 } @@ -497,7 +716,8 @@ test_create_repo "$test" # 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= @@ -515,3 +735,53 @@ do 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" "$@" |