diff options
Diffstat (limited to 't')
57 files changed, 8268 insertions, 0 deletions
diff --git a/t/Makefile b/t/Makefile new file mode 100644 index 0000000000..6882e23be5 --- /dev/null +++ b/t/Makefile @@ -0,0 +1,15 @@ +# Run tests +# +# Copyright (c) 2005 Junio C Hamano +# + +#GIT_TEST_OPTS=--verbose --debug + +T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) + +all: + @$(foreach t,$T,echo "*** $t ***"; sh $t $(GIT_TEST_OPTS) || exit; ) + @rm -fr trash + +clean: + rm -fr trash diff --git a/t/README b/t/README new file mode 100644 index 0000000000..ab47ef9c5e --- /dev/null +++ b/t/README @@ -0,0 +1,208 @@ +Core GIT Tests +============== + +This directory holds many test scripts for core GIT tools. The +first part of this short document describes how to run the tests +and read their output. + +When fixing the tools or adding enhancements, you are strongly +encouraged to add tests in this directory to cover what you are +trying to fix or enhance. The later part of this short document +describes how your test scripts should be organized. + + +Running Tests +------------- + +The easiest way to run tests is to say "make". This runs all +the tests. + + *** t0000-basic.sh *** + * ok 1: .git/objects should be empty after git-init-db in an empty repo. + * ok 2: .git/objects should have 256 subdirectories. + * ok 3: git-update-cache without --add should fail adding. + ... + * ok 23: no diff after checkout and git-update-cache --refresh. + * passed all 23 test(s) + *** t0100-environment-names.sh *** + * ok 1: using old names should issue warnings. + * ok 2: using old names but having new names should not issue warnings. + ... + +Or you can run each test individually from command line, like +this: + + $ sh ./t3001-ls-files-killed.sh + * ok 1: git-update-cache --add to add various paths. + * ok 2: git-ls-files -k to show killed files. + * ok 3: validate git-ls-files -k output. + * passed all 3 test(s) + +You can pass --verbose (or -v), --debug (or -d), and --immediate +(or -i) command line argument to the test. + +--verbose:: + This makes the test more verbose. Specifically, the + command being run and their output if any are also + output. + +--debug:: + This may help the person who is developing a new test. + It causes the command defined with test_debug to run. + +--immediate:: + This causes the test to immediately exit upon the first + failed test. + + +Naming Tests +------------ + +The test files are named as: + + tNNNN-commandname-details.sh + +where N is a decimal digit. + +First digit tells the family: + + 0 - the absolute basics and global stuff + 1 - the basic commands concerning database + 2 - the basic commands concerning the working tree + 3 - the other basic commands (e.g. ls-files) + 4 - the diff commands + 5 - the pull and exporting commands + 6 - the revision tree commands (even e.g. merge-base) + +Second digit tells the particular command we are testing. + +Third digit (optionally) tells the particular switch or group of switches +we are testing. + +If you create files under t/ directory (i.e. here) that is not +the top-level test script, never name the file to match the above +pattern. The Makefile here considers all such files as the +top-level test script and tries to run all of them. A care is +especially needed if you are creating a common test library +file, similar to test-lib.sh, because such a library file may +not be suitable for standalone execution. + + +Writing Tests +------------- + +The test script is written as a shell script. It should start +with the standard "#!/bin/sh" with copyright notices, and an +assignment to variable 'test_description', like this: + + #!/bin/sh + # + # Copyright (c) 2005 Junio C Hamano + # + + test_description='xxx test (option --frotz) + + This test registers the following structure in the cache + and tries to run git-ls-files with option --frotz.' + + +Source 'test-lib.sh' +-------------------- + +After assigning test_description, the test script should source +test-lib.sh like this: + + . ./test-lib.sh + +This test harness library does the following things: + + - If the script is invoked with command line argument --help + (or -h), it shows the test_description and exits. + + - Creates an empty test directory with an empty .git/objects + database and chdir(2) into it. This directory is 't/trash' + if you must know, but I do not think you care. + + - Defines standard test helper functions for your scripts to + use. These functions are designed to make all scripts behave + consistently when command line arguments --verbose (or -v), + --debug (or -d), and --immediate (or -i) is given. + + +End with test_done +------------------ + +Your script will be a sequence of tests, using helper functions +from the test harness library. At the end of the script, call +'test_done'. + + +Test harness library +-------------------- + +There are a handful helper functions defined in the test harness +library for your script to use. + + - test_expect_success <message> <script> + + This takes two strings as parameter, and evaluates the + <script>. If it yields success, test is considered + successful. <message> should state what it is testing. + + Example: + + test_expect_success \ + 'git-write-tree should be able to write an empty tree.' \ + 'tree=$(git-write-tree)' + + - test_expect_failure <message> <script> + + This is the opposite of test_expect_success. If <script> + yields success, test is considered a failure. + + Example: + + test_expect_failure \ + 'git-update-cache without --add should fail adding.' \ + 'git-update-cache should-be-empty' + + - test_debug <script> + + This takes a single argument, <script>, and evaluates it only + when the test script is started with --debug command line + argument. This is primarily meant for use during the + development of a new test script. + + - test_done + + Your test script must have test_done at the end. Its purpose + is to summarize successes and failures in the test script and + exit with an appropriate error code. + + +Tips for Writing Tests +---------------------- + +As with any programming projects, existing programs are the best +source of the information. However, do _not_ emulate +t0000-basic.sh when writing your tests. The test is special in +that it tries to validate the very core of GIT. For example, it +knows that there will be 256 subdirectories under .git/objects/, +and it knows that the object ID of an empty tree is a certain +40-byte string. This is deliberately done so in t0000-basic.sh +because the things the very basic core test tries to achieve is +to serve as a basis for people who are changing the GIT internal +drastically. For these people, after making certain changes, +not seeing failures from the basic test _is_ a failure. And +such drastic changes to the core GIT that even changes these +otherwise supposedly stable object IDs should be accompanied by +an update to t0000-basic.sh. + +However, other tests that simply rely on basic parts of the core +GIT working properly should not have that level of intimate +knowledge of the core GIT internals. If all the test scripts +hardcoded the object IDs like t0000-basic.sh does, that defeats +the purpose of t0000-basic.sh, which is to isolate that level of +validation in one place. Your test also ends up needing +updating when such a change to the internal happens, so do _not_ +do it and leave the low level of validation to t0000-basic.sh. diff --git a/t/diff-lib.sh b/t/diff-lib.sh new file mode 100755 index 0000000000..a912f435aa --- /dev/null +++ b/t/diff-lib.sh @@ -0,0 +1,35 @@ +: + +_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. + # Ignore them while comparing. + # Also we do not check SHA1 hash generation in this test, which + # is a job for t0000-basic.sh + + sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 + sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} + +sanitize_diff_raw_z='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/' +compare_diff_raw_z () { + # When heuristics are improved, the score numbers would change. + # Ignore them while comparing. + # Also we do not check SHA1 hash generation in this test, which + # is a job for t0000-basic.sh + + tr '\0' '\012' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 + tr '\0' '\012' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} + +compare_diff_patch () { + # When heuristics are improved, the score numbers would change. + # Ignore them while comparing. + sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$1" >.tmp-1 + sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$2" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} diff --git a/t/lib-read-tree-m-3way.sh b/t/lib-read-tree-m-3way.sh new file mode 100755 index 0000000000..d6645b4f42 --- /dev/null +++ b/t/lib-read-tree-m-3way.sh @@ -0,0 +1,158 @@ +: Included from t1000-read-tree-m-3way.sh and others +# Original tree. +mkdir Z +for a in N D M +do + for b in N D M + do + p=$a$b + echo This is $p from the original tree. >$p + echo This is Z/$p from the original tree. >Z/$p + test_expect_success \ + "adding test file $p and Z/$p" \ + 'git-update-cache --add $p && + git-update-cache --add Z/$p' + done +done +echo This is SS from the original tree. >SS +test_expect_success \ + 'adding test file SS' \ + 'git-update-cache --add SS' +cat >TT <<\EOF +This is a trivial merge sample text. +Branch A is expected to upcase this word, here. +There are some filler lines to avoid diff context +conflicts here, +like this one, +and this one, +and this one is yet another one of them. +At the very end, here comes another line, that is +the word, expected to be upcased by Branch B. +This concludes the trivial merge sample file. +EOF +test_expect_success \ + 'adding test file TT' \ + 'git-update-cache --add TT' +test_expect_success \ + 'prepare initial tree' \ + 'tree_O=$(git-write-tree)' + +################################################################ +# Branch A and B makes the changes according to the above matrix. + +################################################################ +# Branch A + +to_remove=$(echo D? Z/D?) +rm -f $to_remove +test_expect_success \ + 'change in branch A (removal)' \ + 'git-update-cache --remove $to_remove' + +for p in M? Z/M? +do + echo This is modified $p in the branch A. >$p + test_expect_success \ + 'change in branch A (modification)' \ + "git-update-cache $p" +done + +for p in AN AA Z/AN Z/AA +do + echo This is added $p in the branch A. >$p + test_expect_success \ + 'change in branch A (addition)' \ + "git-update-cache --add $p" +done + +echo This is SS from the modified tree. >SS +echo This is LL from the modified tree. >LL +test_expect_success \ + 'change in branch A (addition)' \ + 'git-update-cache --add LL && + git-update-cache SS' +mv TT TT- +sed -e '/Branch A/s/word/WORD/g' <TT- >TT +rm -f TT- +test_expect_success \ + 'change in branch A (edit)' \ + 'git-update-cache TT' + +mkdir DF +echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF +test_expect_success \ + 'change in branch A (change file to directory)' \ + 'git-update-cache --add DF/DF' + +test_expect_success \ + 'recording branch A tree' \ + 'tree_A=$(git-write-tree)' + +################################################################ +# Branch B +# Start from O + +rm -rf [NDMASLT][NDMASLT] Z DF +mkdir Z +test_expect_success \ + 'reading original tree and checking out' \ + 'git-read-tree $tree_O && + git-checkout-cache -a' + +to_remove=$(echo ?D Z/?D) +rm -f $to_remove +test_expect_success \ + 'change in branch B (removal)' \ + "git-update-cache --remove $to_remove" + +for p in ?M Z/?M +do + echo This is modified $p in the branch B. >$p + test_expect_success \ + 'change in branch B (modification)' \ + "git-update-cache $p" +done + +for p in NA AA Z/NA Z/AA +do + echo This is added $p in the branch B. >$p + test_expect_success \ + 'change in branch B (addition)' \ + "git-update-cache --add $p" +done +echo This is SS from the modified tree. >SS +echo This is LL from the modified tree. >LL +test_expect_success \ + 'change in branch B (addition and modification)' \ + 'git-update-cache --add LL && + git-update-cache SS' +mv TT TT- +sed -e '/Branch B/s/word/WORD/g' <TT- >TT +rm -f TT- +test_expect_success \ + 'change in branch B (modification)' \ + 'git-update-cache TT' + +echo Branch B makes a file at DF. >DF +test_expect_success \ + 'change in branch B (addition of a file to conflict with directory)' \ + 'git-update-cache --add DF' + +test_expect_success \ + 'recording branch B tree' \ + 'tree_B=$(git-write-tree)' + +test_expect_success \ + 'keep contents of 3 trees for easy access' \ + 'rm -f .git/index && + git-read-tree $tree_O && + mkdir .orig-O && + git-checkout-cache --prefix=.orig-O/ -f -q -a && + rm -f .git/index && + git-read-tree $tree_A && + mkdir .orig-A && + git-checkout-cache --prefix=.orig-A/ -f -q -a && + rm -f .git/index && + git-read-tree $tree_B && + mkdir .orig-B && + git-checkout-cache --prefix=.orig-B/ -f -q -a' diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh new file mode 100755 index 0000000000..547488bd25 --- /dev/null +++ b/t/t0000-basic.sh @@ -0,0 +1,179 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Test the very basics part #1. + +The rest of the test suite does not check the basic operation of git +plumbing commands to work very carefully. Their job is to concentrate +on tricky features that caused bugs in the past to detect regression. + +This test runs very basic features, like registering things in cache, +writing tree, etc. + +Note that this test *deliberately* hard-codes many expected object +IDs. When object ID computation changes, like in the previous case of +swapping compression and hashing order, the person who is making the +modification *should* take notice and update the test vectors here. +' +. ./test-lib.sh + +################################################################ +# init-db has been done in an empty repository. +# make sure it is empty. + +find .git/objects -type f -print >should-be-empty +test_expect_success \ + '.git/objects should be empty after git-init-db in an empty repo.' \ + 'cmp -s /dev/null should-be-empty' + +# also it should have 257 subdirectories. 258 is counting "objects" +find .git/objects -type d -print >full-of-directories +test_expect_success \ + '.git/objects should have 257 subdirectories.' \ + 'test $(wc -l < full-of-directories) = 258' + +################################################################ +# Basics of the basics + +# updating a new file without --add should fail. +test_expect_failure \ + 'git-update-cache without --add should fail adding.' \ + 'git-update-cache should-be-empty' + +# and with --add it should succeed, even if it is empty (it used to fail). +test_expect_success \ + 'git-update-cache with --add should succeed.' \ + 'git-update-cache --add should-be-empty' + +test_expect_success \ + 'writing tree out with git-write-tree' \ + 'tree=$(git-write-tree)' + +# we know the shape and contents of the tree and know the object ID for it. +test_expect_success \ + 'validate object ID of a known tree.' \ + 'test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a' + +# Removing paths. +rm -f should-be-empty full-of-directories +test_expect_failure \ + 'git-update-cache without --remove should fail removing.' \ + 'git-update-cache should-be-empty' + +test_expect_success \ + 'git-update-cache with --remove should be able to remove.' \ + 'git-update-cache --remove should-be-empty' + +# Empty tree can be written with recent write-tree. +test_expect_success \ + 'git-write-tree should be able to write an empty tree.' \ + 'tree=$(git-write-tree)' + +test_expect_success \ + 'validate object ID of a known tree.' \ + 'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904' + +# Various types of objects +mkdir path2 path3 path3/subp3 +for p in path0 path2/file2 path3/file3 path3/subp3/file3 +do + echo "hello $p" >$p + ln -s "hello $p" ${p}sym +done +test_expect_success \ + 'adding various types of objects with git-update-cache --add.' \ + 'find path* ! -type d -print0 | xargs -0 git-update-cache --add' + +# Show them and see that matches what we expect. +test_expect_success \ + 'showing stage with git-ls-files --stage' \ + 'git-ls-files --stage >current' + +cat >expected <<\EOF +100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0 +120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym +100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2 +120000 d8ce161addc5173867a3c3c730924388daedbc38 0 path2/file2sym +100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0 path3/file3 +120000 8599103969b43aff7e430efea79ca4636466794f 0 path3/file3sym +100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0 path3/subp3/file3 +120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0 path3/subp3/file3sym +EOF +test_expect_success \ + 'validate git-ls-files output for a known tree.' \ + 'diff current expected' + +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_expect_success \ + 'showing tree with git-ls-tree' \ + 'git-ls-tree $tree >current' +cat >expected <<\EOF +100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 +120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym +040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 +040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 +EOF +test_expect_success \ + 'git-ls-tree output for a known tree.' \ + 'diff current expected' + +test_expect_success \ + 'showing tree with git-ls-tree -r' \ + 'git-ls-tree -r $tree >current' +cat >expected <<\EOF +100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 +120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym +040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 +100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 +120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym +040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 +100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 +120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym +040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 +100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 +120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym +EOF +test_expect_success \ + 'git-ls-tree -r output for a known tree.' \ + 'diff current expected' + +################################################################ +rm .git/index +test_expect_success \ + 'git-read-tree followed by write-tree should be idempotent.' \ + 'git-read-tree $tree && + test -f .git/index && + newtree=$(git-write-tree) && + test "$newtree" = "$tree"' + +cat >expected <<\EOF +:100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0 +:120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym +:100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2 +:120000 120000 d8ce161addc5173867a3c3c730924388daedbc38 0000000000000000000000000000000000000000 M path2/file2sym +:100644 100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0000000000000000000000000000000000000000 M path3/file3 +:120000 120000 8599103969b43aff7e430efea79ca4636466794f 0000000000000000000000000000000000000000 M path3/file3sym +:100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M path3/subp3/file3 +:120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M path3/subp3/file3sym +EOF +test_expect_success \ + 'validate git-diff-files output for a know cache/work tree state.' \ + 'git-diff-files >current && diff >/dev/null -b current expected' + +test_expect_success \ + 'git-update-cache --refresh should succeed.' \ + 'git-update-cache --refresh' + +test_expect_success \ + 'no diff after checkout and git-update-cache --refresh.' \ + 'git-diff-files >current && cmp -s current /dev/null' + +test_done diff --git a/t/t0100-environment-names.sh b/t/t0100-environment-names.sh new file mode 100755 index 0000000000..9f851bc114 --- /dev/null +++ b/t/t0100-environment-names.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='general environment name warning test. + +This test makes sure that use of deprecated environment variables +trigger the warnings from gitenv().' + +env_vars='GIT_AUTHOR_DATE:AUTHOR_DATE +GIT_AUTHOR_EMAIL:AUTHOR_EMAIL +GIT_AUTHOR_NAME:AUTHOR_NAME +GIT_COMMITTER_EMAIL:COMMIT_AUTHOR_EMAIL +GIT_COMMITTER_NAME:COMMIT_AUTHOR_NAME +GIT_ALTERNATE_OBJECT_DIRECTORIES:SHA1_FILE_DIRECTORIES +GIT_OBJECT_DIRECTORY:SHA1_FILE_DIRECTORY +' + +. ./test-lib.sh + +export_them () { + for ev in $env_vars + do + new=$(expr "$ev" : '\(.*\):') + old=$(expr "$ev" : '.*:\(.*\)') + # Build and eval the following: + # case "${VAR+set}" in set) export VAR;; esac + evstr='case "${'$new'+set}" in set) export '$new';; esac' + eval "$evstr" + evstr='case "${'$old'+set}" in set) export '$old';; esac' + eval "$evstr" + done +} + +date >path0 +git-update-cache --add path0 +tree=$(git-write-tree) + +AUTHOR_DATE='Wed May 11 23:55:18 2005' +AUTHOR_EMAIL='author@example.xz' +AUTHOR_NAME='A U Thor' +COMMIT_AUTHOR_EMAIL='author@example.xz' +COMMIT_AUTHOR_NAME='A U Thor' +SHA1_FILE_DIRECTORY=.git/objects + +export_them + +echo 'foo' | git-commit-tree $tree >/dev/null 2>errmsg +cat >expected-err <<\EOF +warning: Attempting to use SHA1_FILE_DIRECTORY +warning: GIT environment variables have been renamed. +warning: Please adjust your scripts and environment. +warning: old AUTHOR_DATE => new GIT_AUTHOR_DATE +warning: old AUTHOR_EMAIL => new GIT_AUTHOR_EMAIL +warning: old AUTHOR_NAME => new GIT_AUTHOR_NAME +warning: old COMMIT_AUTHOR_EMAIL => new GIT_COMMITTER_EMAIL +warning: old COMMIT_AUTHOR_NAME => new GIT_COMMITTER_NAME +warning: old SHA1_FILE_DIRECTORY => new GIT_OBJECT_DIRECTORY +EOF +sed -ne '/^warning: /p' <errmsg >generated-err + +test_expect_success \ + 'using old names should issue warnings.' \ + 'cmp generated-err expected-err' + +for ev in $env_vars +do + new=$(expr "$ev" : '\(.*\):') + old=$(expr "$ev" : '.*:\(.*\)') + # Build and eval the following: + # NEWENV=$OLDENV + evstr="$new=\$$old" + eval "$evstr" +done +export_them +echo 'foo' | git-commit-tree $tree >/dev/null 2>errmsg +sed -ne '/^warning: /p' <errmsg >generated-err + +test_expect_success \ + 'using old names but having new names should not issue warnings.' \ + 'cmp generated-err /dev/null' + +test_done diff --git a/t/t0110-environment-names-old.sh b/t/t0110-environment-names-old.sh new file mode 100755 index 0000000000..c548b9b497 --- /dev/null +++ b/t/t0110-environment-names-old.sh @@ -0,0 +1,132 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Using new and old environment names. + +This test makes sure that use of deprecated environment variables +still works, using both new and old names makes new one take precedence, +and GIT_DIR and GIT_ALTERNATE_OBJECT_DIRECTORIES mechanism works.' + +env_vars='GIT_AUTHOR_DATE:AUTHOR_DATE +GIT_AUTHOR_EMAIL:AUTHOR_EMAIL +GIT_AUTHOR_NAME:AUTHOR_NAME +GIT_COMMITTER_EMAIL:COMMIT_AUTHOR_EMAIL +GIT_COMMITTER_NAME:COMMIT_AUTHOR_NAME +GIT_ALTERNATE_OBJECT_DIRECTORIES:SHA1_FILE_DIRECTORIES +GIT_OBJECT_DIRECTORY:SHA1_FILE_DIRECTORY +' + +. ./test-lib.sh + +export_them () { + for ev in $env_vars + do + new=$(expr "$ev" : '\(.*\):') + old=$(expr "$ev" : '.*:\(.*\)') + # Build and eval the following: + # case "${VAR+set}" in set) export VAR;; esac + evstr='case "${'$new'+set}" in set) export '$new';; esac' + eval "$evstr" + evstr='case "${'$old'+set}" in set) export '$old';; esac' + eval "$evstr" + done +} + +SHA1_FILE_DIRECTORY=.svn/objects ;# whoa +export SHA1_FILE_DIRECTORY + +rm -fr .git +mkdir .svn +test_expect_success \ + 'using SHA1_FILE_DIRECTORY in git-init-db' \ + 'git-init-db && test -d .svn/objects/cb' + +unset SHA1_FILE_DIRECTORY +GIT_DIR=.svn +export GIT_DIR +rm -fr .git .svn +mkdir .svn +test_expect_success \ + 'using GIT_DIR in git-init-db' \ + 'git-init-db && test -d .svn/objects/cb' + +date >path0 +test_expect_success \ + 'using GIT_DIR in git-update-cache' \ + 'git-update-cache --add path0 && test -f .svn/index' + +sedScript='s|\(..\)|.svn/objects/\1/|' + +test_expect_success \ + 'using GIT_DIR in git-write-tree' \ + 'tree=$(git-write-tree) && + test -f $(echo "$tree" | sed -e "$sedScript")' + +AUTHOR_DATE='Sat May 14 00:00:00 2005 -0000' +AUTHOR_EMAIL='author@example.xz' +AUTHOR_NAME='A U Thor' +COMMIT_AUTHOR_EMAIL='author@example.xz' +COMMIT_AUTHOR_NAME='A U Thor' +export_them + +test_expect_success \ + 'using GIT_DIR and old variable names in git-commit-tree' \ + 'commit=$(echo foo | git-commit-tree $tree) && + test -f $(echo "$commit" | sed -e "$sedScript")' + +test_expect_success \ + 'using GIT_DIR in git-cat-file' \ + 'git-cat-file commit $commit >current' + +cat >expected <<\EOF +author A U Thor <author@example.xz> +committer A U Thor <author@example.xz> +EOF +test_expect_success \ + 'verify old AUTHOR variables were used correctly in commit' \ + 'sed -ne '\''/^\(author\)/s|>.*|>|p'\'' -e'\''/^\(committer\)/s|>.*|>|p'\''\ current > out && cmp out expected' + +unset GIT_DIR +test_expect_success \ + 'git-init-db without GIT_DIR' \ + 'git-init-db && test -d .git && test -d .git/objects/ef' + +SHA1_FILE_DIRECTORIES=.svn/objects +export SHA1_FILE_DIRECTORIES + +test_expect_success \ + 'using SHA1_FILE_DIRECTORIES with git-ls-tree' \ + 'git-ls-tree $commit && git-ls-tree $tree' + +GIT_AUTHOR_DATE='Sat May 14 12:00:00 2005 -0000' +GIT_AUTHOR_EMAIL='rohtua@example.xz' +GIT_AUTHOR_NAME='R O Htua' +GIT_COMMITTER_EMAIL='rohtua@example.xz' +GIT_COMMITTER_NAME='R O Htua' +export_them + +sedScript='s|\(..\)|.git/objects/\1/|' +test_expect_success \ + 'using new author variables with git-commit-tree' \ + 'commit2=$(echo foo | git-commit-tree $tree) && + test -f $(echo "$commit2" | sed -e "$sedScript")' + +GIT_ALTERNATE_OBJECT_DIRECTORIES=.git/objects +GIT_DIR=nowhere +export GIT_DIR GIT_ALTERNATE_OBJECT_DIRECTORIES + +test_expect_success \ + 'git-cat-file with GIT_DIR and GIT_ALTERNATE_OBJECT_DIRECTORIES' \ + 'git-cat-file commit $commit2 >current' + +cat >expected <<\EOF +author R O Htua <rohtua@example.xz> +committer R O Htua <rohtua@example.xz> +EOF +test_expect_success \ + 'verify new AUTHOR variables were used correctly in commit.' \ + 'sed -ne '\''/^\(author\)/s|>.*|>|p'\'' -e'\''/^\(committer\)/s|>.*|>|p'\''\ current > out && cmp out expected' + +test_done diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh new file mode 100755 index 0000000000..89f0e81f23 --- /dev/null +++ b/t/t1000-read-tree-m-3way.sh @@ -0,0 +1,517 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Three way merge with read-tree -m + +This test tries three-way merge with read-tree -m + +There is one ancestor (called O for Original) and two branches A +and B derived from it. We want to do a 3-way merge between A and +B, using O as the common ancestor. + + merge A O B + +Decisions are made by comparing contents of O, A and B pathname +by pathname. The result is determined by the following guiding +principle: + + - If only A does something to it and B does not touch it, take + whatever A does. + + - If only B does something to it and A does not touch it, take + whatever B does. + + - If both A and B does something but in the same way, take + whatever they do. + + - If A and B does something but different things, we need a + 3-way merge: + + - We cannot do anything about the following cases: + + * O does not have it. A and B both must be adding to the + same path independently. + + * A deletes it. B must be modifying. + + - Otherwise, A and B are modifying. Run 3-way merge. + +First, the case matrix. + + - Vertical axis is for A'\''s actions. + - Horizontal axis is for B'\''s actions. + +.----------------------------------------------------------------. +| A B | No Action | Delete | Modify | Add | +|------------+------------+------------+------------+------------| +| No Action | | | | | +| | select O | delete | select B | select B | +| | | | | | +|------------+------------+------------+------------+------------| +| Delete | | | ********** | can | +| | delete | delete | merge | not | +| | | | | happen | +|------------+------------+------------+------------+------------| +| Modify | | ********** | ?????????? | can | +| | select A | merge | select A=B | not | +| | | | merge | happen | +|------------+------------+------------+------------+------------| +| Add | | can | can | ?????????? | +| | select A | not | not | select A=B | +| | | happen | happen | merge | +.----------------------------------------------------------------. + +In addition: + + SS: a special case of MM, where A and B makes the same modification. + LL: a special case of AA, where A and B creates the same file. + TT: a special case of MM, where A and B makes mergeable changes. + DF: a special case, where A makes a directory and B makes a file. + +' +. ./test-lib.sh +. ../lib-read-tree-m-3way.sh + +################################################################ +# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT +# and #5ALT trivial merges. + +cat >expected <<\EOF +100644 X 2 AA +100644 X 3 AA +100644 X 0 AN +100644 X 1 DD +100644 X 3 DF +100644 X 2 DF/DF +100644 X 1 DM +100644 X 3 DM +100644 X 1 DN +100644 X 3 DN +100644 X 0 LL +100644 X 1 MD +100644 X 2 MD +100644 X 1 MM +100644 X 2 MM +100644 X 3 MM +100644 X 0 MN +100644 X 0 NA +100644 X 1 ND +100644 X 2 ND +100644 X 0 NM +100644 X 0 NN +100644 X 0 SS +100644 X 1 TT +100644 X 2 TT +100644 X 3 TT +100644 X 2 Z/AA +100644 X 3 Z/AA +100644 X 0 Z/AN +100644 X 1 Z/DD +100644 X 1 Z/DM +100644 X 3 Z/DM +100644 X 1 Z/DN +100644 X 3 Z/DN +100644 X 1 Z/MD +100644 X 2 Z/MD +100644 X 1 Z/MM +100644 X 2 Z/MM +100644 X 3 Z/MM +100644 X 0 Z/MN +100644 X 0 Z/NA +100644 X 1 Z/ND +100644 X 2 Z/ND +100644 X 0 Z/NM +100644 X 0 Z/NN +EOF + +_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" + +check_result () { + git-ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current && + diff -u expected current +} + +# This is done on an empty work directory, which is the normal +# merge person behaviour. +test_expect_success \ + '3-way merge with git-read-tree -m, empty cache' \ + "rm -fr [NDMALTS][NDMALTSF] Z && + rm .git/index && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +# This starts out with the first head, which is the normal +# patch submitter behaviour. +test_expect_success \ + '3-way merge with git-read-tree -m, match H' \ + "rm -fr [NDMALTS][NDMALTSF] Z && + rm .git/index && + git-read-tree $tree_A && + git-checkout-cache -f -u -a && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +: <<\END_OF_CASE_TABLE + +We have so far tested only empty index and clean-and-matching-A index +case which are trivial. Make sure index requirements are also +checked. The table also lists alternative semantics which is not +currently implemented. + +"git-diff-tree -m O A B" + + O A B result index requirements +------------------------------------------------------------------- + 1 missing missing missing - must not exist. + ------------------------------------------------------------------ + 2 missing missing exists no merge must not exist. + ------------------------------------ + (ALT) take B* must match B, if exists. + ------------------------------------------------------------------ + 3 missing exists missing no merge must match A and be + up-to-date, if exists. + ------------------------------------ + (ALT) take A* must match A, if exists. + ------------------------------------------------------------------ + 4 missing exists A!=B no merge must match A and be + up-to-date, if exists. + ------------------------------------------------------------------ + 5 missing exists A==B no merge must match A and be + up-to-date, if exists. + ------------------------------------ + (ALT) take A must match A, if exists. + ------------------------------------------------------------------ + 6 exists missing missing no merge must not exist. + ------------------------------------ + (ALT) remove must not exist. + ------------------------------------------------------------------ + 7 exists missing O!=B no merge must not exist. + ------------------------------------------------------------------ + 8 exists missing O==B no merge must not exist. + ------------------------------------ + (ALT) remove must not exist. + ------------------------------------------------------------------ + 9 exists O!=A missing no merge must match A and be + up-to-date, if exists. + ------------------------------------------------------------------ + 10 exists O==A missing no merge must match A and be + up-to-date, if exists. + ------------------------------------ + (ALT) remove ditto + ------------------------------------------------------------------ + 11 exists O!=A O!=B no merge must match A and be + A!=B up-to-date, if exists. + ------------------------------------------------------------------ + 12 exists O!=A O!=B take A must match A, if exists. + A==B + ------------------------------------------------------------------ + 13 exists O!=A O==B take A must match A, if exists. + ------------------------------------------------------------------ + 14 exists O==A O!=B take B must match A and be + be up-to-date, if exists. + ------------------------------------ + (ALT) take B if exists, must either (1) + match A and be up-to-date, + or (2) match B. + ------------------------------------------------------------------ + 15 exists O==A O==B take B must match A if exists. +------------------------------------------------------------------- + +Note: if we want to implement 2ALT and 3ALT we need to be careful. +The tree A may contain DF (file) when tree B require DF to be a +directory by having DF/DF (file). + +END_OF_CASE_TABLE + +test_expect_failure \ + '1 - must not have an entry not in A.' \ + "rm -f .git/index XX && + echo XX >XX && + git-update-cache --add XX && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '2 - must match B in !O && !A && B case.' \ + "rm -f .git/index NA && + cp .orig-B/NA NA && + git-update-cache --add NA && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '2 - matching B alone is OK in !O && !A && B case.' \ + "rm -f .git/index NA && + cp .orig-B/NA NA && + git-update-cache --add NA && + echo extra >>NA && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '3 - must match A in !O && A && !B case.' \ + "rm -f .git/index AN && + cp .orig-A/AN AN && + git-update-cache --add AN && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '3 - matching A alone is OK in !O && A && !B case.' \ + "rm -f .git/index AN && + cp .orig-A/AN AN && + git-update-cache --add AN && + echo extra >>AN && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '3 (fail) - must match A in !O && A && !B case.' \ + "rm -f .git/index AN && + cp .orig-A/AN AN && + echo extra >>AN && + git-update-cache --add AN && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '4 - must match and be up-to-date in !O && A && B && A!=B case.' \ + "rm -f .git/index AA && + cp .orig-A/AA AA && + git-update-cache --add AA && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \ + "rm -f .git/index AA && + cp .orig-A/AA AA && + git-update-cache --add AA && + echo extra >>AA && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' \ + "rm -f .git/index AA && + cp .orig-A/AA AA && + echo extra >>AA && + git-update-cache --add AA && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '5 - must match in !O && A && B && A==B case.' \ + "rm -f .git/index LL && + cp .orig-A/LL LL && + git-update-cache --add LL && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '5 - must match in !O && A && B && A==B case.' \ + "rm -f .git/index LL && + cp .orig-A/LL LL && + git-update-cache --add LL && + echo extra >>LL && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '5 (fail) - must match A in !O && A && B && A==B case.' \ + "rm -f .git/index LL && + cp .orig-A/LL LL && + echo extra >>LL && + git-update-cache --add LL && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '6 - must not exist in O && !A && !B case' \ + "rm -f .git/index DD && + echo DD >DD + git-update-cache --add DD && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '7 - must not exist in O && !A && B && O!=B case' \ + "rm -f .git/index DM && + cp .orig-B/DM DM && + git-update-cache --add DM && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '8 - must not exist in O && !A && B && O==B case' \ + "rm -f .git/index DN && + cp .orig-B/DN DN && + git-update-cache --add DN && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '9 - must match and be up-to-date in O && A && !B && O!=A case' \ + "rm -f .git/index MD && + cp .orig-A/MD MD && + git-update-cache --add MD && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \ + "rm -f .git/index MD && + cp .orig-A/MD MD && + git-update-cache --add MD && + echo extra >>MD && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' \ + "rm -f .git/index MD && + cp .orig-A/MD MD && + echo extra >>MD && + git-update-cache --add MD && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '10 - must match and be up-to-date in O && A && !B && O==A case' \ + "rm -f .git/index ND && + cp .orig-A/ND ND && + git-update-cache --add ND && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \ + "rm -f .git/index ND && + cp .orig-A/ND ND && + git-update-cache --add ND && + echo extra >>ND && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' \ + "rm -f .git/index ND && + cp .orig-A/ND ND && + echo extra >>ND && + git-update-cache --add ND && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ + "rm -f .git/index MM && + cp .orig-A/MM MM && + git-update-cache --add MM && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ + "rm -f .git/index MM && + cp .orig-A/MM MM && + git-update-cache --add MM && + echo extra >>MM && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ + "rm -f .git/index MM && + cp .orig-A/MM MM && + echo extra >>MM && + git-update-cache --add MM && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '12 - must match A in O && A && B && O!=A && A==B case' \ + "rm -f .git/index SS && + cp .orig-A/SS SS && + git-update-cache --add SS && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '12 - must match A in O && A && B && O!=A && A==B case' \ + "rm -f .git/index SS && + cp .orig-A/SS SS && + git-update-cache --add SS && + echo extra >>SS && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '12 (fail) - must match A in O && A && B && O!=A && A==B case' \ + "rm -f .git/index SS && + cp .orig-A/SS SS && + echo extra >>SS && + git-update-cache --add SS && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '13 - must match A in O && A && B && O!=A && O==B case' \ + "rm -f .git/index MN && + cp .orig-A/MN MN && + git-update-cache --add MN && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '13 - must match A in O && A && B && O!=A && O==B case' \ + "rm -f .git/index MN && + cp .orig-A/MN MN && + git-update-cache --add MN && + echo extra >>MN && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' \ + "rm -f .git/index NM && + cp .orig-A/NM NM && + git-update-cache --add NM && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '14 - may match B in O && A && B && O==A && O!=B case' \ + "rm -f .git/index NM && + cp .orig-B/NM NM && + git-update-cache --add NM && + echo extra >>NM && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \ + "rm -f .git/index NM && + cp .orig-A/NM NM && + git-update-cache --add NM && + echo extra >>NM && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_failure \ + '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' \ + "rm -f .git/index NM && + cp .orig-A/NM NM && + echo extra >>NM && + git-update-cache --add NM && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_expect_success \ + '15 - must match A in O && A && B && O==A && O==B case' \ + "rm -f .git/index NN && + cp .orig-A/NN NN && + git-update-cache --add NN && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_success \ + '15 - must match A in O && A && B && O==A && O==B case' \ + "rm -f .git/index NN && + cp .orig-A/NN NN && + git-update-cache --add NN && + echo extra >>NN && + git-read-tree -m $tree_O $tree_A $tree_B && + check_result" + +test_expect_failure \ + '15 (fail) - must match A in O && A && B && O==A && O==B case' \ + "rm -f .git/index NN && + cp .orig-A/NN NN && + echo extra >>NN && + git-update-cache --add NN && + git-read-tree -m $tree_O $tree_A $tree_B" + +test_done diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh new file mode 100755 index 0000000000..b3e6bd57d0 --- /dev/null +++ b/t/t1001-read-tree-m-2way.sh @@ -0,0 +1,344 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Two way merge with read-tree -m $H $M + +This test tries two-way merge (aka fast forward with carry forward). + +There is the head (called H) and another commit (called M), which is +simply ahead of H. The index and the work tree contains a state that +is derived from H, but may also have local changes. This test checks +all the combinations described in the two-tree merge "carry forward" +rules, found in <Documentation/git-rev-tree.txt>. + +In the test, these paths are used: + bozbar - in H, stays in M, modified from bozbar to gnusto + frotz - not in H added in M + nitfol - in H, stays in M unmodified + rezrov - in H, deleted in M + yomin - not in H nor M +' +. ./test-lib.sh + +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;' \ + -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \ + "$1" + diff -u expected current +} + +check_cache_at () { + clean_if_empty=`git-diff-files "$1"` + case "$clean_if_empty" in + '') echo "$1: clean" ;; + ?*) echo "$1: dirty" ;; + esac + case "$2,$clean_if_empty" in + clean,) : ;; + clean,?*) false ;; + dirty,) false ;; + dirty,?*) : ;; + esac +} + +cat >bozbar-old <<\EOF +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 +successfully merge independent changes made to later +lines (such as this one), avoiding line conflicts. +EOF + +sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new + +test_expect_success \ + setup \ + 'echo frotz >frotz && + echo nitfol >nitfol && + cat bozbar-old >bozbar && + echo rezrov >rezrov && + echo yomin >yomin && + git-update-cache --add nitfol bozbar rezrov && + treeH=`git-write-tree` && + echo treeH $treeH && + git-ls-tree $treeH && + + cat bozbar-new >bozbar && + git-update-cache --add frotz bozbar --force-remove rezrov && + git-ls-files --stage >M.out && + treeM=`git-write-tree` && + echo treeM $treeM && + git-ls-tree $treeM && + git-diff-tree $treeH $treeM' + +test_expect_success \ + '1, 2, 3 - no carry forward' \ + 'rm -f .git/index && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >1-3.out && + diff -u M.out 1-3.out && + check_cache_at bozbar dirty && + check_cache_at frotz dirty && + check_cache_at nitfol dirty' + +echo '+100644 X 0 yomin' >expected + +test_expect_success \ + '4 - carry forward local addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + git-update-cache --add yomin && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >4.out || exit + diff -u M.out 4.out >4diff.out + compare_change 4diff.out expected && + check_cache_at yomin clean' + +test_expect_success \ + '5 - carry forward local addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo yomin >yomin && + git-update-cache --add yomin && + echo yomin yomin >yomin && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >5.out || exit + diff -u M.out 5.out >5diff.out + compare_change 5diff.out expected && + check_cache_at yomin dirty' + +test_expect_success \ + '6 - local addition already has the same.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + git-update-cache --add frotz && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >6.out && + diff -u M.out 6.out && + check_cache_at frotz clean' + +test_expect_success \ + '7 - local addition already has the same.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz >frotz && + git-update-cache --add frotz && + echo frotz frotz >frotz && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >7.out && + diff -u M.out 7.out && + check_cache_at frotz dirty' + +test_expect_success \ + '8 - conflicting addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz frotz >frotz && + git-update-cache --add frotz && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '9 - conflicting addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz frotz >frotz && + git-update-cache --add frotz && + echo frotz >frotz && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '10 - path removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov >rezrov && + git-update-cache --add rezrov && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >10.out && + diff -u M.out 10.out' + +test_expect_success \ + '11 - dirty path removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov rezrov >rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '12 - unmatching local changes being removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '13 - unmatching local changes being removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov >rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +cat >expected <<EOF +-100644 X 0 nitfol ++100644 X 0 nitfol +EOF + +test_expect_success \ + '14 - unchanged in two heads.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >14.out || exit + diff -u M.out 14.out >14diff.out + compare_change 14diff.out expected && + check_cache_at nitfol clean' + +test_expect_success \ + '15 - unchanged in two heads.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + echo nitfol nitfol nitfol >nitfol && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >15.out || exit + diff -u M.out 15.out >15diff.out + compare_change 15diff.out expected && + check_cache_at nitfol dirty' + +test_expect_success \ + '16 - conflicting local change.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '17 - conflicting local change.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + echo bozbar bozbar bozbar >bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '18 - local change already having a good result.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-new >bozbar && + git-update-cache --add bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >18.out && + diff -u M.out 18.out && + check_cache_at bozbar clean' + +test_expect_success \ + '19 - local change already having a good result, further modified.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-new >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >19.out && + diff -u M.out 19.out && + check_cache_at bozbar dirty' + +test_expect_success \ + '20 - no local change, use new tree.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-old >bozbar && + git-update-cache --add bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >20.out && + diff -u M.out 20.out && + check_cache_at bozbar dirty' + +test_expect_success \ + '21 - no local change, dirty cache.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-old >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +# This fails with straight two-way fast forward. +test_expect_success \ + '22 - local change cache updated.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + sed -e "s/such as/SUCH AS/" bozbar-old >bozbar && + git-update-cache --add bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +# Also make sure we did not break DF vs DF/DF case. +test_expect_success \ + 'DF vs DF/DF case setup.' \ + 'rm -f .git/index && + echo DF >DF && + git-update-cache --add DF && + treeDF=`git-write-tree` && + echo treeDF $treeDF && + git-ls-tree $treeDF && + + rm -f DF && + mkdir DF && + echo DF/DF >DF/DF && + git-update-cache --add --remove DF DF/DF && + treeDFDF=`git-write-tree` && + echo treeDFDF $treeDFDF && + git-ls-tree $treeDFDF && + git-ls-files --stage >DFDF.out' + +test_expect_success \ + 'DF vs DF/DF case test.' \ + 'rm -f .git/index && + rm -fr DF && + echo DF >DF && + git-update-cache --add DF && + read_tree_twoway $treeDF $treeDFDF && + git-ls-files --stage >DFDFcheck.out && + diff -u DFDF.out DFDFcheck.out && + check_cache_at DF/DF dirty && + :' + +test_done diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh new file mode 100755 index 0000000000..2f1ee79698 --- /dev/null +++ b/t/t1002-read-tree-m-u-2way.sh @@ -0,0 +1,324 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Two way merge with read-tree -m -u $H $M + +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 '/^--- /d; /^+++ /d; /^@@ /d;' \ + -e 's/^\(.[0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /' "$1" + diff -u expected current +} + +check_cache_at () { + clean_if_empty=`git-diff-files "$1"` + case "$clean_if_empty" in + '') echo "$1: clean" ;; + ?*) echo "$1: dirty" ;; + esac + case "$2,$clean_if_empty" in + clean,) : ;; + clean,?*) false ;; + dirty,) false ;; + dirty,?*) : ;; + esac +} + +test_expect_success \ + setup \ + 'echo frotz >frotz && + echo nitfol >nitfol && + echo bozbar >bozbar && + echo rezrov >rezrov && + echo yomin >yomin && + git-update-cache --add nitfol bozbar rezrov && + treeH=`git-write-tree` && + echo treeH $treeH && + git-ls-tree $treeH && + + echo gnusto >bozbar && + git-update-cache --add frotz bozbar --force-remove rezrov && + git-ls-files --stage >M.out && + treeM=`git-write-tree` && + echo treeM $treeM && + git-ls-tree $treeM && + sum bozbar frotz nitfol >M.sum && + git-diff-tree $treeH $treeM' + +test_expect_success \ + '1, 2, 3 - no carry forward' \ + 'rm -f .git/index && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >1-3.out && + cmp M.out 1-3.out && + sum bozbar frotz nitfol >actual3.sum && + cmp M.sum actual3.sum && + check_cache_at bozbar clean && + check_cache_at frotz clean && + check_cache_at nitfol clean' + +echo '+100644 X 0 yomin' >expected + +test_expect_success \ + '4 - carry forward local addition.' \ + 'rm -f .git/index && + git-update-cache --add yomin && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >4.out || exit + diff --unified=0 M.out 4.out >4diff.out + compare_change 4diff.out expected && + check_cache_at yomin clean && + sum bozbar frotz nitfol >actual4.sum && + cmp M.sum actual4.sum && + echo yomin >yomin1 && + diff yomin yomin1 && + rm -f yomin1' + +test_expect_success \ + '5 - carry forward local addition.' \ + 'rm -f .git/index && + echo yomin >yomin && + git-update-cache --add yomin && + echo yomin yomin >yomin && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >5.out || exit + diff --unified=0 M.out 5.out >5diff.out + compare_change 5diff.out expected && + check_cache_at yomin dirty && + sum bozbar frotz nitfol >actual5.sum && + cmp M.sum actual5.sum && + : dirty index should have prevented -u from checking it out. && + echo yomin yomin >yomin1 && + diff yomin yomin1 && + rm -f yomin1' + +test_expect_success \ + '6 - local addition already has the same.' \ + 'rm -f .git/index && + git-update-cache --add frotz && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >6.out && + diff --unified=0 M.out 6.out && + check_cache_at frotz clean && + sum bozbar frotz nitfol >actual3.sum && + cmp M.sum actual3.sum && + echo frotz >frotz1 && + diff frotz frotz1 && + rm -f frotz1' + +test_expect_success \ + '7 - local addition already has the same.' \ + 'rm -f .git/index && + echo frotz >frotz && + git-update-cache --add frotz && + echo frotz frotz >frotz && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >7.out && + diff --unified=0 M.out 7.out && + check_cache_at frotz dirty && + sum bozbar frotz nitfol >actual7.sum && + if cmp M.sum actual7.sum; then false; else :; fi && + : dirty index should have prevented -u from checking it out. && + echo frotz frotz >frotz1 && + diff frotz frotz1 && + rm -f frotz1' + +test_expect_success \ + '8 - conflicting addition.' \ + 'rm -f .git/index && + echo frotz frotz >frotz && + git-update-cache --add frotz && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '9 - conflicting addition.' \ + 'rm -f .git/index && + echo frotz frotz >frotz && + git-update-cache --add frotz && + echo frotz >frotz && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '10 - path removed.' \ + 'rm -f .git/index && + echo rezrov >rezrov && + git-update-cache --add rezrov && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >10.out && + cmp M.out 10.out && + sum bozbar frotz nitfol >actual10.sum && + cmp M.sum actual10.sum' + +test_expect_success \ + '11 - dirty path removed.' \ + 'rm -f .git/index && + echo rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov rezrov >rezrov && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '12 - unmatching local changes being removed.' \ + 'rm -f .git/index && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '13 - unmatching local changes being removed.' \ + 'rm -f .git/index && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov >rezrov && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +cat >expected <<EOF +-100644 X 0 nitfol ++100644 X 0 nitfol +EOF + +test_expect_success \ + '14 - unchanged in two heads.' \ + 'rm -f .git/index && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >14.out || exit + diff --unified=0 M.out 14.out >14diff.out + compare_change 14diff.out expected && + sum bozbar frotz >actual14.sum && + grep -v nitfol M.sum > expected14.sum && + cmp expected14.sum actual14.sum && + sum bozbar frotz nitfol >actual14a.sum && + if cmp M.sum actual14a.sum; then false; else :; fi && + check_cache_at nitfol clean && + echo nitfol nitfol >nitfol1 && + diff nitfol nitfol1 && + rm -f nitfol1' + +test_expect_success \ + '15 - unchanged in two heads.' \ + 'rm -f .git/index && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + echo nitfol nitfol nitfol >nitfol && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >15.out || exit + diff --unified=0 M.out 15.out >15diff.out + compare_change 15diff.out expected && + check_cache_at nitfol dirty && + sum bozbar frotz >actual15.sum && + grep -v nitfol M.sum > expected15.sum && + cmp expected15.sum actual15.sum && + sum bozbar frotz nitfol >actual15a.sum && + if cmp M.sum actual15a.sum; then false; else :; fi && + echo nitfol nitfol nitfol >nitfol1 && + diff nitfol nitfol1 && + rm -f nitfol1' + +test_expect_success \ + '16 - conflicting local change.' \ + 'rm -f .git/index && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '17 - conflicting local change.' \ + 'rm -f .git/index && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + echo bozbar bozbar bozbar >bozbar && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '18 - local change already having a good result.' \ + 'rm -f .git/index && + echo gnusto >bozbar && + git-update-cache --add bozbar && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >18.out && + diff --unified=0 M.out 18.out && + check_cache_at bozbar clean && + sum bozbar frotz nitfol >actual18.sum && + cmp M.sum actual18.sum' + +test_expect_success \ + '19 - local change already having a good result, further modified.' \ + 'rm -f .git/index && + echo gnusto >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >19.out && + diff --unified=0 M.out 19.out && + check_cache_at bozbar dirty && + sum frotz nitfol >actual19.sum && + grep -v bozbar M.sum > expected19.sum && + cmp expected19.sum actual19.sum && + sum bozbar frotz nitfol >actual19a.sum && + if cmp M.sum actual19a.sum; then false; else :; fi && + echo gnusto gnusto >bozbar1 && + diff bozbar bozbar1 && + rm -f bozbar1' + +test_expect_success \ + '20 - no local change, use new tree.' \ + 'rm -f .git/index && + echo bozbar >bozbar && + git-update-cache --add bozbar && + git-read-tree -m -u $treeH $treeM && + git-ls-files --stage >20.out && + diff --unified=0 M.out 20.out && + check_cache_at bozbar clean && + sum bozbar frotz nitfol >actual20.sum && + cmp M.sum actual20.sum' + +test_expect_success \ + '21 - no local change, dirty cache.' \ + 'rm -f .git/index && + echo bozbar >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + if git-read-tree -m -u $treeH $treeM; then false; else :; fi' + +# Also make sure we did not break DF vs DF/DF case. +test_expect_success \ + 'DF vs DF/DF case setup.' \ + 'rm -f .git/index && + echo DF >DF && + git-update-cache --add DF && + treeDF=`git-write-tree` && + echo treeDF $treeDF && + git-ls-tree $treeDF && + + rm -f DF && + mkdir DF && + echo DF/DF >DF/DF && + git-update-cache --add --remove DF DF/DF && + treeDFDF=`git-write-tree` && + echo treeDFDF $treeDFDF && + git-ls-tree $treeDFDF && + git-ls-files --stage >DFDF.out' + +test_expect_success \ + 'DF vs DF/DF case test.' \ + 'rm -f .git/index && + rm -fr DF && + echo DF >DF && + git-update-cache --add DF && + git-read-tree -m -u $treeDF $treeDFDF && + git-ls-files --stage >DFDFcheck.out && + diff --unified=0 DFDF.out DFDFcheck.out && + check_cache_at DF/DF clean' + +test_done diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh new file mode 100755 index 0000000000..d80752ddd5 --- /dev/null +++ b/t/t1005-read-tree-m-2way-emu23.sh @@ -0,0 +1,422 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Two way merge with read-tree --emu23 $H $M + +This test tries two-way merge (aka fast forward with carry forward). + +There is the head (called H) and another commit (called M), which is +simply ahead of H. The index and the work tree contains a state that +is derived from H, but may also have local changes. This test checks +all the combinations described in the two-tree merge "carry forward" +rules, found in <Documentation/git-rev-tree.txt>. + +In the test, these paths are used: + bozbar - in H, stays in M, modified from bozbar to gnusto + frotz - not in H added in M + nitfol - in H, stays in M unmodified + rezrov - in H, deleted in M + yomin - not in H nor M +' +. ./test-lib.sh + +read_tree_twoway () { + git-read-tree --emu23 "$1" "$2" && + git-ls-files --stage && + git-merge-cache git-merge-one-file-script -a && + git-ls-files --stage +} + +_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" +compare_change () { + sed -n >current \ + -e '/^--- /d; /^+++ /d; /^@@ /d;' \ + -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \ + "$1" + diff -u expected current +} + +check_cache_at () { + clean_if_empty=`git-diff-files "$1"` + case "$clean_if_empty" in + '') echo "$1: clean" ;; + ?*) echo "$1: dirty" ;; + esac + case "$2,$clean_if_empty" in + clean,) : ;; + clean,?*) false ;; + dirty,) false ;; + dirty,?*) : ;; + esac +} + +check_stages () { + cat >expected_stages + git-ls-files --stage | sed -e "s/ $_x40 / X /" >current_stages + diff -u expected_stages current_stages +} + +cat >bozbar-old <<\EOF +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 +successfully merge independent changes made to later +lines (such as this one), avoiding line conflicts. +EOF + +sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new + +test_expect_success \ + setup \ + 'echo frotz >frotz && + echo nitfol >nitfol && + cat bozbar-old >bozbar && + echo rezrov >rezrov && + echo yomin >yomin && + git-update-cache --add nitfol bozbar rezrov && + treeH=`git-write-tree` && + echo treeH $treeH && + git-ls-tree $treeH && + + cat bozbar-new >bozbar && + git-update-cache --add frotz bozbar --force-remove rezrov && + git-ls-files --stage >M.out && + treeM=`git-write-tree` && + echo treeM $treeM && + git-ls-tree $treeM && + git-diff-tree $treeH $treeM' + +# "read-tree -m H I+H M" but I is empty so this is "read-tree -m H H M". +# +# bozbar [O && A && B && O==A && O!=B (#14) ==> B] take M by read-tree +# frotz [!O && !A && B (#2) ==> B] take M by read-tree +# nitfol [O && A && B && O==A && O==B (#15) ==> B] take M by read-tree +# rezrov [O && A && !B && O==A (#10) ==> no merge] removed by script +# +# Earlier one did not have #2ALT so taking M was done by the script, +# which also updated the work tree and making frotz clean. With #2ALT, +# this is resolved by read-tree itself and the path is left dirty +# because we are not testing "read-tree -u --emu23". +test_expect_success \ + '1, 2, 3 - no carry forward' \ + 'rm -f .git/index && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >1-3.out && + diff -u M.out 1-3.out && + check_cache_at bozbar dirty && + check_cache_at frotz dirty && # same as pure 2-way again. + check_cache_at nitfol dirty' + +echo '+100644 X 0 yomin' >expected + +test_expect_success \ + '4 - carry forward local addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + git-update-cache --add yomin && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >4.out || exit + diff -u M.out 4.out >4diff.out + compare_change 4diff.out expected && + check_cache_at yomin clean' + +# "read-tree -m H I+H M" where !H && !M; so (I+H) not being up-to-date +# should not matter. Thanks to #3ALT, this is now possible. +test_expect_success \ + '5 - carry forward local addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo yomin >yomin && + git-update-cache --add yomin && + echo yomin yomin >yomin && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >5.out || exit + diff -u M.out 5.out >5diff.out + compare_change 5diff.out expected && + check_cache_at yomin dirty' + +# "read-tree -m H I+H M" where !H && M && (I+H) == M, so this should +# succeed (even the entry is clean), now thanks to #5ALT. +test_expect_success \ + '6 - local addition already has the same.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + git-update-cache --add frotz && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >6.out && + diff -u M.out 6.out && + check_cache_at frotz clean' + +# Exactly the same pattern as above but with dirty cache. This also +# should succeed, now thanks to #5ALT. +test_expect_success \ + '7 - local addition already has the same.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz >frotz && + git-update-cache --add frotz && + echo frotz frotz >frotz && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >7.out && + diff -u M.out 7.out && + check_cache_at frotz dirty' + +test_expect_success \ + '8 - conflicting addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz frotz >frotz && + git-update-cache --add frotz && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '9 - conflicting addition.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo frotz frotz >frotz && + git-update-cache --add frotz && + echo frotz >frotz && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '10 - path removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov >rezrov && + git-update-cache --add rezrov && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >10.out && + diff -u M.out 10.out' + +test_expect_success \ + '11 - dirty path removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov rezrov >rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '12 - unmatching local changes being removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '13 - unmatching local changes being removed.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo rezrov rezrov >rezrov && + git-update-cache --add rezrov && + echo rezrov >rezrov && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +cat >expected <<EOF +-100644 X 0 nitfol ++100644 X 0 nitfol +EOF + +test_expect_success \ + '14 - unchanged in two heads.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >14.out || exit + diff -u M.out 14.out >14diff.out + compare_change 14diff.out expected && + check_cache_at nitfol clean' + +test_expect_success \ + '15 - unchanged in two heads.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo nitfol nitfol >nitfol && + git-update-cache --add nitfol && + echo nitfol nitfol nitfol >nitfol && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >15.out || exit + diff -u M.out 15.out >15diff.out + compare_change 15diff.out expected && + check_cache_at nitfol dirty' + +# This is different from straight 2-way merge in that it leaves +# three stages of bozbar in the index file without failing, so +# the user can run git-diff-stages to examine the situation. +# With #2ALT, frotz is resolved internally. +test_expect_success \ + '16 - conflicting local change.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + git-read-tree --emu23 $treeH $treeM && + check_stages' <<\EOF +100644 X 1 bozbar +100644 X 2 bozbar +100644 X 3 bozbar +100644 X 0 frotz +100644 X 0 nitfol +100644 X 1 rezrov +100644 X 2 rezrov +EOF + +test_expect_success \ + '17 - conflicting local change.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + echo bozbar bozbar >bozbar && + git-update-cache --add bozbar && + echo bozbar bozbar bozbar >bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +test_expect_success \ + '18 - local change already having a good result.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-new >bozbar && + git-update-cache --add bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >18.out && + diff -u M.out 18.out && + check_cache_at bozbar clean' + +test_expect_success \ + '19 - local change already having a good result, further modified.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-new >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >19.out && + diff -u M.out 19.out && + check_cache_at bozbar dirty' + +test_expect_success \ + '20 - no local change, use new tree.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-old >bozbar && + git-update-cache --add bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >20.out && + diff -u M.out 20.out && + check_cache_at bozbar dirty' + +test_expect_success \ + '21 - no local change, dirty cache.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + cat bozbar-old >bozbar && + git-update-cache --add bozbar && + echo gnusto gnusto >bozbar && + if read_tree_twoway $treeH $treeM; then false; else :; fi' + +echo '-100644 X 0 bozbar ++100644 X 0 bozbar' >expected + +# This fails with straight two-way fast forward, but emu23 +# can merge them. +test_expect_success \ + '22 - local change cache updated.' \ + 'rm -f .git/index && + git-read-tree $treeH && + git-checkout-cache -u -f -q -a && + sed -e "s/such as/SUCH AS/" bozbar-old >bozbar && + git-update-cache --add bozbar && + read_tree_twoway $treeH $treeM && + git-ls-files --stage >22.out || exit + diff -u M.out 22.out >22diff.out + compare_change 22diff.out && + check_cache_at bozbar clean' + +# Also make sure we did not break DF vs DF/DF case. +test_expect_success \ + 'DF vs DF/DF case setup.' \ + 'rm -f .git/index && + echo DF >DF && + git-update-cache --add DF && + treeDF=`git-write-tree` && + echo treeDF $treeDF && + git-ls-tree $treeDF && + git-ls-files --stage >DF.out + + rm -f DF && + mkdir DF && + echo DF/DF >DF/DF && + git-update-cache --add --remove DF DF/DF && + treeDFDF=`git-write-tree` && + echo treeDFDF $treeDFDF && + git-ls-tree $treeDFDF && + git-ls-files --stage >DFDF.out' + +test_expect_success \ + 'DF vs DF/DF case test (#1)' \ + 'rm -f .git/index && + rm -fr DF && + echo DF >DF && + git-update-cache --add DF && + read_tree_twoway $treeDF $treeDFDF && + git-ls-files --stage >DFDFcheck.out && + diff -u DFDF.out DFDFcheck.out && + check_cache_at DF/DF clean && # different from pure 2-way + :' + +# The other way around +test_expect_success \ + 'DF vs DF/DF case test (#2)' \ + 'rm -f .git/index && + rm -fr DF && + mkdir DF && + echo DF/DF >DF/DF && + git-update-cache --add DF/DF && + read_tree_twoway $treeDFDF $treeDF && + git-ls-files --stage >DFDFcheck.out && + diff -u DF.out DFDFcheck.out && + check_cache_at DF clean && # different from pure 2-way + :' + +# Emu23 can grok I having more than H. Make sure we did not +# botch the conflict tests (fixed). +test_expect_success \ + 'DF vs DF/DF case test (#3).' \ + 'rm -f .git/index && + rm -fr DF && + mkdir DF && + echo DF/DF >DF/DF && + git-update-cache --add DF/DF && + # This should fail because I and H have a conflict + # at DF. + if git-read-tree --emu23 $treeDF $treeDFDF + then false + else true + fi' + +test_done diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh new file mode 100755 index 0000000000..e59f724f2a --- /dev/null +++ b/t/t1100-commit-tree-options.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Copyright (C) 2005 Rene Scharfe +# + +test_description='git-commit-tree options test + +This test checks that git-commit-tree can create a specific commit +object by defining all environment variables that it understands. +' + +. ./test-lib.sh + +cat >expected <<EOF +tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +author Author Name <author@email> 1117148400 +0000 +committer Committer Name <committer@email> 1117150200 +0000 + +comment text +EOF + +test_expect_success \ + 'test preparation: write empty tree' \ + 'git-write-tree >treeid' + +test_expect_success \ + 'construct commit' \ + 'echo comment text | + GIT_AUTHOR_NAME="Author Name" \ + GIT_AUTHOR_EMAIL="author@email" \ + GIT_AUTHOR_DATE="2005-05-26 23:00" \ + GIT_COMMITTER_NAME="Committer Name" \ + GIT_COMMITTER_EMAIL="committer@email" \ + GIT_COMMITTER_DATE="2005-05-26 23:30" \ + TZ= git-commit-tree `cat treeid` >commitid 2>/dev/null' + +test_expect_success \ + 'read commit' \ + 'git-cat-file commit `cat commitid` >commit' + +test_expect_success \ + 'compare commit' \ + 'diff expected commit' + +test_done diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh new file mode 100755 index 0000000000..a2c42602da --- /dev/null +++ b/t/t2000-checkout-cache-clash.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-checkout-cache test. + +This test registers the following filesystem structure in the +cache: + + path0 - a file + path1/file1 - a file in a directory + +And then tries to checkout in a work tree that has the following: + + path0/file0 - a file in a directory + path1 - a file + +The git-checkout-cache command should fail when attempting to checkout +path0, finding it is occupied by a directory, and path1/file1, finding +path1 is occupied by a non-directory. With "-f" flag, it should remove +the conflicting paths and succeed. +' +. ./test-lib.sh + +date >path0 +mkdir path1 +date >path1/file1 + +test_expect_success \ + 'git-update-cache --add various paths.' \ + 'git-update-cache --add path0 path1/file1' + +rm -fr path0 path1 +mkdir path0 +date >path0/file0 +date >path1 + +test_expect_failure \ + 'git-checkout-cache without -f should fail on conflicting work tree.' \ + 'git-checkout-cache -a' + +test_expect_success \ + 'git-checkout-cache with -f should succeed.' \ + 'git-checkout-cache -f -a' + +test_expect_success \ + 'git-checkout-cache conflicting paths.' \ + 'test -f path0 && test -d path1 && test -f path1/file1' + +test_done + + diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh new file mode 100755 index 0000000000..f0e3d1d8c3 --- /dev/null +++ b/t/t2001-checkout-cache-clash.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-checkout-cache test. + +This test registers the following filesystem structure in the cache: + + path0/file0 - a file in a directory + path1/file1 - a file in a directory + +and attempts to check it out when the work tree has: + + path0/file0 - a file in a directory + path1 - a symlink pointing at "path0" + +Checkout cache should fail to extract path1/file1 because the leading +path path1 is occupied by a non-directory. With "-f" it should remove +the symlink path1 and create directory path1 and file path1/file1. +' +. ./test-lib.sh + +show_files() { + # show filesystem files, just [-dl] for type and name + find path? -ls | + sed -e 's/^[0-9]* * [0-9]* * \([-bcdl]\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \1 /' + # what's in the cache, just mode and name + git-ls-files --stage | + sed -e 's/^\([0-9]*\) [0-9a-f]* [0-3] /ca: \1 /' + # what's in the tree, just mode and name. + git-ls-tree -r "$1" | + sed -e 's/^\([0-9]*\) [^ ]* [0-9a-f]* /tr: \1 /' +} + +mkdir path0 +date >path0/file0 +test_expect_success \ + 'git-update-cache --add path0/file0' \ + 'git-update-cache --add path0/file0' +test_expect_success \ + 'writing tree out with git-write-tree' \ + 'tree1=$(git-write-tree)' +test_debug 'show_files $tree1' + +mkdir path1 +date >path1/file1 +test_expect_success \ + 'git-update-cache --add path1/file1' \ + 'git-update-cache --add path1/file1' +test_expect_success \ + 'writing tree out with git-write-tree' \ + 'tree2=$(git-write-tree)' +test_debug 'show_files $tree2' + +rm -fr path1 +test_expect_success \ + 'read previously written tree and checkout.' \ + 'git-read-tree -m $tree1 && git-checkout-cache -f -a' +test_debug 'show_files $tree1' + +ln -s path0 path1 +test_expect_success \ + 'git-update-cache --add a symlink.' \ + 'git-update-cache --add path1' +test_expect_success \ + 'writing tree out with git-write-tree' \ + 'tree3=$(git-write-tree)' +test_debug 'show_files $tree3' + +# Morten says "Got that?" here. +# Test begins. + +test_expect_success \ + 'read previously written tree and checkout.' \ + 'git-read-tree $tree2 && git-checkout-cache -f -a' +test_debug show_files $tree2 + +test_expect_success \ + 'checking out conflicting path with -f' \ + 'test ! -h path0 && test -d path0 && + test ! -h path1 && test -d path1 && + test ! -h path0/file0 && test -f path0/file0 && + test ! -h path1/file1 && test -f path1/file1' + +test_done + diff --git a/t/t2002-checkout-cache-u.sh b/t/t2002-checkout-cache-u.sh new file mode 100755 index 0000000000..69146acc3a --- /dev/null +++ b/t/t2002-checkout-cache-u.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-checkout-cache -u test. + +With -u flag, git-checkout-cache internally runs the equivalent of +git-update-cache --refresh on the checked out entry.' + +. ./test-lib.sh + +test_expect_success \ +'preparation' ' +echo frotz >path0 && +git-update-cache --add path0 && +t=$(git-write-tree)' + +test_expect_failure \ +'without -u, git-checkout-cache smudges stat information.' ' +rm -f path0 && +git-read-tree $t && +git-checkout-cache -f -a && +git-diff-files | diff - /dev/null' + +test_expect_success \ +'with -u, git-checkout-cache picks up stat information from new files.' ' +rm -f path0 && +git-read-tree $t && +git-checkout-cache -u -f -a && +git-diff-files | diff - /dev/null' + +test_done diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh new file mode 100755 index 0000000000..6ec28179be --- /dev/null +++ b/t/t2003-checkout-cache-mkdir.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-checkout-cache --prefix test. + +This test makes sure that --prefix option works as advertised, and +also verifies that such leading path may contain symlinks, unlike +the GIT controlled paths. +' + +. ./test-lib.sh + +test_expect_success \ + 'setup' \ + 'mkdir path1 && + echo frotz >path0 && + echo rezrov >path1/file1 && + git-update-cache --add path0 path1/file1' + +test_expect_success \ + 'have symlink in place where dir is expected.' \ + 'rm -fr path0 path1 && + mkdir path2 && + ln -s path2 path1 && + git-checkout-cache -f -a && + test ! -h path1 && test -d path1 && + test -f path1/file1 && test ! -f path2/file1' + +test_expect_success \ + 'use --prefix=path2/' \ + 'rm -fr path0 path1 path2 && + mkdir path2 && + git-checkout-cache --prefix=path2/ -f -a && + test -f path2/path0 && + test -f path2/path1/file1 && + test ! -f path0 && + test ! -f path1/file1' + +test_expect_success \ + 'use --prefix=tmp-' \ + 'rm -fr path0 path1 path2 tmp* && + git-checkout-cache --prefix=tmp- -f -a && + test -f tmp-path0 && + test -f tmp-path1/file1 && + test ! -f path0 && + test ! -f path1/file1' + +test_expect_success \ + 'use --prefix=tmp- but with a conflicting file and dir' \ + 'rm -fr path0 path1 path2 tmp* && + echo nitfol >tmp-path1 && + mkdir tmp-path0 && + git-checkout-cache --prefix=tmp- -f -a && + test -f tmp-path0 && + test -f tmp-path1/file1 && + test ! -f path0 && + test ! -f path1/file1' + +# Linus fix #1 +test_expect_success \ + 'use --prefix=tmp/orary/ where tmp is a symlink' \ + 'rm -fr path0 path1 path2 tmp* && + mkdir tmp1 tmp1/orary && + ln -s tmp1 tmp && + git-checkout-cache --prefix=tmp/orary/ -f -a && + test -d tmp1/orary && + test -f tmp1/orary/path0 && + test -f tmp1/orary/path1/file1 && + test -h tmp' + +# Linus fix #2 +test_expect_success \ + 'use --prefix=tmp/orary- where tmp is a symlink' \ + 'rm -fr path0 path1 path2 tmp* && + mkdir tmp1 && + ln -s tmp1 tmp && + git-checkout-cache --prefix=tmp/orary- -f -a && + test -f tmp1/orary-path0 && + test -f tmp1/orary-path1/file1 && + test -h tmp' + +# Linus fix #3 +test_expect_success \ + 'use --prefix=tmp- where tmp-path1 is a symlink' \ + 'rm -fr path0 path1 path2 tmp* && + mkdir tmp1 && + ln -s tmp1 tmp-path1 && + git-checkout-cache --prefix=tmp- -f -a && + test -f tmp-path0 && + test ! -h tmp-path1 && + test -d tmp-path1 && + test -f tmp-path1/file1' + diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh new file mode 100755 index 0000000000..86b7375c6c --- /dev/null +++ b/t/t2100-update-cache-badpath.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-update-cache nonsense-path test. + +This test creates the following structure in the cache: + + path0 - a file + path1 - a symlink + path2/file2 - a file in a directory + path3/file3 - a file in a directory + +and tries to git-update-cache --add the following: + + path0/file0 - a file in a directory + path1/file1 - a file in a directory + path2 - a file + path3 - a symlink + +All of the attempts should fail. +' + +. ./test-lib.sh + +mkdir path2 path3 +date >path0 +ln -s xyzzy path1 +date >path2/file2 +date >path3/file3 + +test_expect_success \ + 'git-update-cache --add to add various paths.' \ + 'git-update-cache --add -- path0 path1 path2/file2 path3/file3' + +rm -fr path? + +mkdir path0 path1 +date >path2 +ln -s frotz path3 +date >path0/file0 +date >path1/file1 + +for p in path0/file0 path1/file1 path2 path3 +do + test_expect_failure \ + "git-update-cache to add conflicting path $p should fail." \ + "git-update-cache --add -- $p" +done +test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh new file mode 100755 index 0000000000..1f461e3e81 --- /dev/null +++ b/t/t3000-ls-files-others.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-ls-files test (--others should pick up symlinks). + +This test runs git-ls-files --others with the following on the +filesystem. + + path0 - a file + path1 - a symlink + path2/file2 - a file in a directory +' +. ./test-lib.sh + +date >path0 +ln -s xyzzy path1 +mkdir path2 +date >path2/file2 +test_expect_success \ + 'git-ls-files --others to show output.' \ + 'git-ls-files --others >output' +cat >expected <<EOF +output +path0 +path1 +path2/file2 +EOF + +test_expect_success \ + 'git-ls-files --others should pick up symlinks.' \ + 'diff output expected' +test_done diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh new file mode 100755 index 0000000000..dbff346c0a --- /dev/null +++ b/t/t3001-ls-files-others-exclude.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-ls-files --others --exclude + +This test runs git-ls-files --others and tests --exclude patterns. +' + +. ./test-lib.sh + +rm -fr one three +for dir in . one one/two three +do + mkdir -p $dir && + for i in 1 2 3 4 5 6 7 8 + do + >$dir/a.$i + done +done + +cat >expect <<EOF +a.2 +a.4 +a.5 +a.8 +one/a.3 +one/a.4 +one/a.5 +one/a.7 +one/two/a.2 +one/two/a.3 +one/two/a.5 +one/two/a.7 +one/two/a.8 +three/a.2 +three/a.3 +three/a.4 +three/a.5 +three/a.8 +EOF + +echo '.gitignore +output +expect +.gitignore +*.7 +!*.8' >.git/ignore + +echo '*.1 +/*.3 +!*.6' >.gitignore +echo '*.2 +two/*.4 +!*.7 +*.8' >one/.gitignore +echo '!*.2 +!*.8' >one/two/.gitignore + +test_expect_success \ + 'git-ls-files --others with various exclude options.' \ + 'git-ls-files --others \ + --exclude=\*.6 \ + --exclude-per-directory=.gitignore \ + --exclude-from=.git/ignore \ + >output && + diff -u expect output' diff --git a/t/t3010-ls-files-killed.sh b/t/t3010-ls-files-killed.sh new file mode 100755 index 0000000000..c4d6d2163f --- /dev/null +++ b/t/t3010-ls-files-killed.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-ls-files -k flag test. + +This test prepares the following in the cache: + + path0 - a file + path1 - a symlink + path2/file2 - a file in a directory + path3/file3 - a file in a directory + +and the following on the filesystem: + + path0/file0 - a file in a directory + path1/file1 - a file in a directory + path2 - a file + path3 - a symlink + path4 - a file + path5 - a symlink + path6/file6 - a file in a directory + +git-ls-files -k should report that existing filesystem +objects except path4, path5 and path6/file6 to be killed. +' +. ./test-lib.sh + +date >path0 +ln -s xyzzy path1 +mkdir path2 path3 +date >path2/file2 +date >path3/file3 +test_expect_success \ + 'git-update-cache --add to add various paths.' \ + "git-update-cache --add -- path0 path1 path?/file?" + +rm -fr path? +date >path2 +ln -s frotz path3 +ln -s nitfol path5 +mkdir path0 path1 path6 +date >path0/file0 +date >path1/file1 +date >path6/file6 + +test_expect_success \ + 'git-ls-files -k to show killed files.' \ + 'git-ls-files -k >.output' +cat >.expected <<EOF +path0/file0 +path1/file1 +path2 +path3 +EOF + +test_expect_success \ + 'validate git-ls-files -k output.' \ + 'diff .output .expected' +test_done diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh new file mode 100755 index 0000000000..61a7c7f642 --- /dev/null +++ b/t/t3100-ls-tree-restrict.sh @@ -0,0 +1,131 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-ls-tree test. + +This test runs git-ls-tree with the following in a tree. + + path0 - a file + path1 - a symlink + path2/foo - a file in a directory + path2/bazbo - a symlink in a directory + path2/baz/b - a file in a directory in a directory + +The new path restriction code should do the right thing for path2 and +path2/baz. Also path0/ should snow nothing. +' +. ./test-lib.sh + +test_expect_success \ + 'setup' \ + 'mkdir path2 path2/baz && + echo Hi >path0 && + ln -s path0 path1 && + 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-cache --add && + tree=`git-write-tree` && + echo $tree' + +_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" +test_output () { + sed -e "s/ $_x40 / X /" <current >check + diff -u expected check +} + +test_expect_success \ + 'ls-tree plain' \ + 'git-ls-tree $tree >current && + cat >expected <<\EOF && +100644 blob X path0 +120000 blob X path1 +040000 tree X path2 +EOF + test_output' + +test_expect_success \ + 'ls-tree recursive' \ + 'git-ls-tree -r $tree >current && + cat >expected <<\EOF && +100644 blob X path0 +120000 blob X path1 +040000 tree X path2 +040000 tree X path2/baz +100644 blob X path2/baz/b +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path' \ + 'git-ls-tree $tree path >current && + cat >expected <<\EOF && +EOF + test_output' + + +test_expect_success \ + 'ls-tree filtered with path1 path0' \ + 'git-ls-tree $tree path1 path0 >current && + cat >expected <<\EOF && +120000 blob X path1 +100644 blob X path0 +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path0/' \ + 'git-ls-tree $tree path0/ >current && + cat >expected <<\EOF && +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2' \ + 'git-ls-tree $tree path2 >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2/baz' \ + 'git-ls-tree $tree path2/baz >current && + cat >expected <<\EOF && +040000 tree X path2/baz +100644 blob X path2/baz/b +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2' \ + 'git-ls-tree $tree path2 >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2/' \ + 'git-ls-tree $tree path2/ >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_done diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh new file mode 100755 index 0000000000..3accb14f00 --- /dev/null +++ b/t/t4000-diff-format.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Test built-in diff output engine. + +' +. ./test-lib.sh + +echo >path0 'Line 1 +Line 2 +line 3' +cat path0 >path1 +chmod +x path1 + +test_expect_success \ + 'update-cache --add two files with and without +x.' \ + 'git-update-cache --add path0 path1' + +mv path0 path0- +sed -e 's/line/Line/' <path0- >path0 +chmod +x path0 +rm -f path1 +test_expect_success \ + 'git-diff-files -p after editing work tree.' \ + 'git-diff-files -p >current' +cat >expected <<\EOF +diff --git a/path0 b/path0 +old mode 100644 +new mode 100755 +--- a/path0 ++++ b/path0 +@@ -1,3 +1,3 @@ + Line 1 + Line 2 +-line 3 ++Line 3 +diff --git a/path1 b/path1 +deleted file mode 100755 +--- a/path1 ++++ /dev/null +@@ -1,3 +0,0 @@ +-Line 1 +-Line 2 +-line 3 +EOF + +test_expect_success \ + 'validate git-diff-files -p output.' \ + 'cmp -s current expected' + +test_expect_success \ + 'build same diff using git-diff-helper.' \ + 'git-diff-files -z | git-diff-helper -z >current' + + +test_expect_success \ + 'validate git-diff-helper output.' \ + 'cmp -s current expected' + +test_done diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh new file mode 100755 index 0000000000..80edae6682 --- /dev/null +++ b/t/t4001-diff-rename.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Test rename detection in diff engine. + +' +. ./test-lib.sh + +echo >path0 'Line 1 +Line 2 +Line 3 +Line 4 +Line 5 +Line 6 +Line 7 +Line 8 +Line 9 +Line 10 +line 11 +Line 12 +Line 13 +Line 14 +Line 15 +' + +test_expect_success \ + 'update-cache --add a file.' \ + 'git-update-cache --add path0' + +test_expect_success \ + 'write that tree.' \ + 'tree=$(git-write-tree) && echo $tree' + +sed -e 's/line/Line/' <path0 >path1 +rm -f path0 +test_expect_success \ + 'renamed and edited the file.' \ + 'git-update-cache --add --remove path0 path1' + +test_expect_success \ + 'git-diff-cache -p -M after rename and editing.' \ + 'git-diff-cache -p -M $tree >current' +cat >expected <<\EOF +diff --git a/path0 b/path1 +rename from path0 +rename to path1 +--- a/path0 ++++ b/path1 +@@ -8,7 +8,7 @@ Line 7 + Line 8 + Line 9 + Line 10 +-line 11 ++Line 11 + Line 12 + Line 13 + Line 14 +EOF + +test_expect_success \ + 'validate the output.' \ + 'diff -I "similarity.*" >/dev/null current expected' + +test_done diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh new file mode 100755 index 0000000000..03fc4b9830 --- /dev/null +++ b/t/t4002-diff-basic.sh @@ -0,0 +1,247 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Test diff raw-output. + +' +. ./test-lib.sh +. ../lib-read-tree-m-3way.sh + +cat >.test-plain-OA <<\EOF +:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA +:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A AN +:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD +:000000 040000 0000000000000000000000000000000000000000 6d50f65d3bdab91c63444294d38f08aeff328e42 A DF +:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D DM +:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D DN +:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL +:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M MD +:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M MM +:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M MN +:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS +:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M TT +:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 5e5f22072bb39f6e12cf663a57cb634c76eefb49 M Z +EOF + +cat >.test-recursive-OA <<\EOF +:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA +:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A AN +:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD +:000000 100644 0000000000000000000000000000000000000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 A DF/DF +:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D DM +:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D DN +:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL +:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M MD +:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M MM +:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M MN +:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS +:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M TT +:000000 100644 0000000000000000000000000000000000000000 8acb8e9750e3f644bf323fcf3d338849db106c77 A Z/AA +:000000 100644 0000000000000000000000000000000000000000 087494262084cefee7ed484d20c8dc0580791272 A Z/AN +:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D Z/DD +:100644 000000 9b541b2275c06e3a7b13f28badf5294e2ae63df4 0000000000000000000000000000000000000000 D Z/DM +:100644 000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a 0000000000000000000000000000000000000000 D Z/DN +:100644 100644 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 M Z/MD +:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 61422ba9c2c873416061a88cd40a59a35b576474 M Z/MM +:100644 100644 b16d7b25b869f2beb124efa53467d8a1550ad694 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd M Z/MN +EOF +cat >.test-plain-OB <<\EOF +:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A AA +:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD +:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF +:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M DM +:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL +:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D MD +:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM +:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA +:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND +:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM +:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS +:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT +:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 1ba523955d5160681af65cb776411f574c1e8155 M Z +EOF +cat >.test-recursive-OB <<\EOF +:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A AA +:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD +:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF +:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M DM +:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL +:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D MD +:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM +:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA +:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND +:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM +:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS +:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT +:000000 100644 0000000000000000000000000000000000000000 6c0b99286d0bce551ac4a7b3dff8b706edff3715 A Z/AA +:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D Z/DD +:100644 100644 9b541b2275c06e3a7b13f28badf5294e2ae63df4 d77371d15817fcaa57eeec27f770c505ba974ec1 M Z/DM +:100644 000000 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 0000000000000000000000000000000000000000 D Z/MD +:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 697aad7715a1e7306ca76290a3dd4208fbaeddfa M Z/MM +:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A Z/NA +:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D Z/ND +:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M Z/NM +EOF +cat >.test-plain-AB <<\EOF +:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M AA +:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D AN +:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF +:040000 000000 6d50f65d3bdab91c63444294d38f08aeff328e42 0000000000000000000000000000000000000000 D DF +:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A DM +:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A DN +:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D MD +:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM +:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M MN +:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA +:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND +:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM +:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT +:040000 040000 5e5f22072bb39f6e12cf663a57cb634c76eefb49 1ba523955d5160681af65cb776411f574c1e8155 M Z +EOF +cat >.test-recursive-AB <<\EOF +:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M AA +:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D AN +:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF +:100644 000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 0000000000000000000000000000000000000000 D DF/DF +:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A DM +:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A DN +:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D MD +:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM +:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M MN +:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA +:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND +:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM +:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT +:100644 100644 8acb8e9750e3f644bf323fcf3d338849db106c77 6c0b99286d0bce551ac4a7b3dff8b706edff3715 M Z/AA +:100644 000000 087494262084cefee7ed484d20c8dc0580791272 0000000000000000000000000000000000000000 D Z/AN +:000000 100644 0000000000000000000000000000000000000000 d77371d15817fcaa57eeec27f770c505ba974ec1 A Z/DM +:000000 100644 0000000000000000000000000000000000000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a A Z/DN +:100644 000000 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 0000000000000000000000000000000000000000 D Z/MD +:100644 100644 61422ba9c2c873416061a88cd40a59a35b576474 697aad7715a1e7306ca76290a3dd4208fbaeddfa M Z/MM +:100644 100644 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd b16d7b25b869f2beb124efa53467d8a1550ad694 M Z/MN +:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A Z/NA +:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D Z/ND +:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M Z/NM +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" +z40='0000000000000000000000000000000000000000' +cmp_diff_files_output () { + # diff-files never reports additions. Also it does not fill in the + # object ID for the changed files because it wants you to look at the + # filesystem. + sed <"$2" >.test-tmp \ + -e '/^:000000 /d;s/'$x40'\( [MCRNDU][0-9]*\) /'$z40'\1 /' && + diff "$1" .test-tmp +} + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree $tree_O $tree_A >.test-a && + cmp -s .test-a .test-plain-OA' + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree -r $tree_O $tree_A >.test-a && + cmp -s .test-a .test-recursive-OA' + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree $tree_O $tree_B >.test-a && + cmp -s .test-a .test-plain-OB' + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree -r $tree_O $tree_B >.test-a && + cmp -s .test-a .test-recursive-OB' + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree $tree_A $tree_B >.test-a && + cmp -s .test-a .test-plain-AB' + +test_expect_success \ + 'diff-tree of known trees.' \ + 'git-diff-tree -r $tree_A $tree_B >.test-a && + cmp -s .test-a .test-recursive-AB' + +test_expect_success \ + 'diff-cache O with A in cache' \ + 'git-read-tree $tree_A && + git-diff-cache --cached $tree_O >.test-a && + cmp -s .test-a .test-recursive-OA' + +test_expect_success \ + 'diff-cache O with B in cache' \ + 'git-read-tree $tree_B && + git-diff-cache --cached $tree_O >.test-a && + cmp -s .test-a .test-recursive-OB' + +test_expect_success \ + 'diff-cache A with B in cache' \ + 'git-read-tree $tree_B && + git-diff-cache --cached $tree_A >.test-a && + cmp -s .test-a .test-recursive-AB' + +test_expect_success \ + 'diff-files with O in cache and A checked out' \ + 'rm -fr Z [A-Z][A-Z] && + git-read-tree $tree_A && + git-checkout-cache -f -a && + git-read-tree -m $tree_O || (exit 1) + git-update-cache --refresh >/dev/null ;# this can exit non-zero + git-diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-OA' + +test_expect_success \ + 'diff-files with O in cache and B checked out' \ + 'rm -fr Z [A-Z][A-Z] && + git-read-tree $tree_B && + git-checkout-cache -f -a && + git-read-tree -m $tree_O || (exit 1) + git-update-cache --refresh >/dev/null ;# this can exit non-zero + git-diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-OB' + +test_expect_success \ + 'diff-files with A in cache and B checked out' \ + 'rm -fr Z [A-Z][A-Z] && + git-read-tree $tree_B && + git-checkout-cache -f -a && + git-read-tree -m $tree_A || (exit 1) + git-update-cache --refresh >/dev/null ;# this can exit non-zero + git-diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-AB' + +################################################################ +# Now we have established the baseline, we do not have to +# rely on individual object ID values that much. + +test_expect_success \ + 'diff-tree O A == diff-tree -R A O' \ + 'git-diff-tree $tree_O $tree_A >.test-a && + git-diff-tree -R $tree_A $tree_O >.test-b && + cmp -s .test-a .test-b' + +test_expect_success \ + 'diff-tree -r O A == diff-tree -r -R A O' \ + 'git-diff-tree -r $tree_O $tree_A >.test-a && + git-diff-tree -r -R $tree_A $tree_O >.test-b && + cmp -s .test-a .test-b' + +test_expect_success \ + 'diff-tree B A == diff-tree -R A B' \ + 'git-diff-tree $tree_B $tree_A >.test-a && + git-diff-tree -R $tree_A $tree_B >.test-b && + cmp -s .test-a .test-b' + +test_expect_success \ + 'diff-tree -r B A == diff-tree -r -R A B' \ + 'git-diff-tree -r $tree_B $tree_A >.test-a && + git-diff-tree -r -R $tree_A $tree_B >.test-b && + cmp -s .test-a .test-b' + +test_done diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh new file mode 100755 index 0000000000..8e3091abb6 --- /dev/null +++ b/t/t4003-diff-rename-1.sh @@ -0,0 +1,128 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='More rename detection + +' +. ./test-lib.sh +. ../diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success \ + 'prepare reference tree' \ + 'cat ../../COPYING >COPYING && + echo frotz >rezrov && + git-update-cache --add COPYING rezrov && + tree=$(git-write-tree) && + echo $tree' + +test_expect_success \ + 'prepare work tree' \ + 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && + sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && + rm -f COPYING && + git-update-cache --add --remove COPYING COPYING.?' + +# tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, +# both are slightly edited, and unchanged rezrov. So we say you +# copy-and-edit one, and rename-and-edit the other. We do not say +# anything about rezrov. + +GIT_DIFF_OPTS=--unified=0 git-diff-cache -M -p $tree >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +diff --git a/COPYING b/COPYING.2 +rename from COPYING +rename to COPYING.2 +--- a/COPYING ++++ b/COPYING.2 +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#1)' \ + 'compare_diff_patch current expected' + +test_expect_success \ + 'prepare work tree again' \ + 'mv COPYING.2 COPYING && + git-update-cache --add --remove COPYING COPYING.1 COPYING.2' + +# tree has COPYING and rezrov. work tree has COPYING and COPYING.1, +# both are slightly edited, and unchanged rezrov. So we say you +# edited one, and copy-and-edit the other. We do not say +# anything about rezrov. + +GIT_DIFF_OPTS=--unified=0 git-diff-cache -C -p $tree >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING +--- a/COPYING ++++ b/COPYING +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#2)' \ + 'compare_diff_patch current expected' + +test_expect_success \ + 'prepare work tree once again' \ + 'cat ../../COPYING >COPYING && + git-update-cache --add --remove COPYING COPYING.1' + +# tree has COPYING and rezrov. work tree has COPYING and COPYING.1, +# but COPYING is not edited. We say you copy-and-edit COPYING.1; this +# is only possible because -C mode now reports the unmodified file to +# the diff-core. Unchanged rezrov, although being fed to +# git-diff-cache as well, should not be mentioned. + +GIT_DIFF_OPTS=--unified=0 \ + git-diff-cache -C --find-copies-harder -p $tree >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#3)' \ + 'compare_diff_patch current expected' + +test_done diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh new file mode 100755 index 0000000000..010dd87eef --- /dev/null +++ b/t/t4004-diff-rename-symlink.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='More rename detection tests. + +The rename detection logic should be able to detect pure rename or +copy of symbolic links, but should not produce rename/copy followed +by an edit for them. +' +. ./test-lib.sh + +test_expect_success \ + 'prepare reference tree' \ + 'echo xyzzy | tr -d '\\\\'012 >yomin && + ln -s xyzzy frotz && + git-update-cache --add frotz yomin && + tree=$(git-write-tree) && + echo $tree' + +test_expect_success \ + 'prepare work tree' \ + 'mv frotz rezrov && + rm -f yomin && + ln -s xyzzy nitfol && + ln -s xzzzy bozbar && + git-update-cache --add --remove frotz rezrov nitfol bozbar yomin' + +# tree has frotz pointing at xyzzy, and yomin that contains xyzzy to +# confuse things. work tree has rezrov (xyzzy) nitfol (xyzzy) and +# bozbar (xzzzy). +# rezrov and nitfol are rename/copy of frotz and bozbar should be +# a new creation. + +GIT_DIFF_OPTS=--unified=0 git-diff-cache -M -p $tree >current +cat >expected <<\EOF +diff --git a/bozbar b/bozbar +new file mode 120000 +--- /dev/null ++++ b/bozbar +@@ -0,0 +1 @@ ++xzzzy +\ No newline at end of file +diff --git a/frotz b/nitfol +similarity index 100% +copy from frotz +copy to nitfol +diff --git a/frotz b/rezrov +similarity index 100% +rename from frotz +rename to rezrov +diff --git a/yomin b/yomin +deleted file mode 100644 +--- a/yomin ++++ /dev/null +@@ -1 +0,0 @@ +-xyzzy +\ No newline at end of file +EOF + +test_expect_success \ + 'validate diff output' \ + 'diff -u current expected' + +test_done diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh new file mode 100755 index 0000000000..cee06e4c5d --- /dev/null +++ b/t/t4005-diff-rename-2.sh @@ -0,0 +1,166 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Same rename detection as t4003 but testing diff-raw. + +' +. ./test-lib.sh +. ../diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success \ + 'prepare reference tree' \ + 'cat ../../COPYING >COPYING && + echo frotz >rezrov && + git-update-cache --add COPYING rezrov && + tree=$(git-write-tree) && + echo $tree' + +test_expect_success \ + 'prepare work tree' \ + 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && + sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && + rm -f COPYING && + git-update-cache --add --remove COPYING COPYING.?' + +# tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, +# both are slightly edited, and unchanged rezrov. We say COPYING.1 +# and COPYING.2 are based on COPYING, and do not say anything about +# rezrov. + +git-diff-cache -M $tree >current + +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234 COPYING COPYING.2 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#1)' \ + 'compare_diff_raw current expected' + +# make sure diff-helper can grok it. +mv expected diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +diff --git a/COPYING b/COPYING.2 +rename from COPYING +rename to COPYING.2 +--- a/COPYING ++++ b/COPYING.2 +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +EOF + +test_expect_success \ + 'validate output from diff-helper (#1)' \ + 'compare_diff_patch current expected' + +################################################################ + +test_expect_success \ + 'prepare work tree again' \ + 'mv COPYING.2 COPYING && + git-update-cache --add --remove COPYING COPYING.1 COPYING.2' + +# tree has COPYING and rezrov. work tree has COPYING and COPYING.1, +# both are slightly edited, and unchanged rezrov. We say COPYING.1 +# is based on COPYING and COPYING is still there, and do not say anything +# about rezrov. + +git-diff-cache -C $tree >current +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M COPYING +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#2)' \ + 'compare_diff_raw current expected' + +# make sure diff-helper can grok it. +mv expected diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING +--- a/COPYING ++++ b/COPYING +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from diff-helper (#2)' \ + 'compare_diff_patch current expected' + +################################################################ + +# tree has COPYING and rezrov. work tree has the same COPYING and +# copy-edited COPYING.1, and unchanged rezrov. We should not say +# anything about rezrov nor COPYING, since the revised again diff-raw +# nows how to say Copy. + +test_expect_success \ + 'prepare work tree once again' \ + 'cat ../../COPYING >COPYING && + git-update-cache --add --remove COPYING COPYING.1' + +git-diff-cache -C --find-copies-harder $tree >current +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#3)' \ + 'compare_diff_raw current expected' + +# make sure diff-helper can grok it. +mv expected diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from diff-helper (#3)' \ + 'compare_diff_patch current expected' + +test_done diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh new file mode 100755 index 0000000000..90fd21ff1f --- /dev/null +++ b/t/t4006-diff-mode.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Test mode change diffs. + +' +. ./test-lib.sh + +test_expect_success \ + 'setup' \ + 'echo frotz >rezrov && + git-update-cache --add rezrov && + tree=`git-write-tree` && + echo $tree' + +test_expect_success \ + 'chmod' \ + 'chmod +x rezrov && + git-update-cache rezrov && + git-diff-cache $tree >current' + +_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" +sed -e 's/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' <current >check +echo ":100644 100755 X X M rezrov" >expected + +test_expect_success \ + 'verify' \ + 'diff -u expected check' + +test_done + diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh new file mode 100755 index 0000000000..042390aa8f --- /dev/null +++ b/t/t4007-rename-3.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +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-cache --add path0/COPYING && + tree=$(git-write-tree) && + echo $tree' + +test_expect_success \ + 'prepare work tree' \ + 'cp path0/COPYING path1/COPYING && + git-update-cache --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-cache -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' + +# 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. +# However when we say we care only about path1, we should just see +# path1/COPYING suddenly appearing from nowhere, not detected as +# a copy from path0/COPYING. + +git-diff-cache -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-cache --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-cache -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' + +# 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-cache -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_done diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh new file mode 100755 index 0000000000..4c971c9f04 --- /dev/null +++ b/t/t4008-diff-break-rewrite.sh @@ -0,0 +1,188 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Break and then rename + +We have two very different files, file0 and file1, registered in a tree. + +We update file1 so drastically that it is more similar to file0, and +then remove file0. With -B, changes to file1 should be broken into +separate delete and create, resulting in removal of file0, removal of +original file1 and creation of completely rewritten file1. + +Further, with -B and -M together, these three modifications should +turn into rename-edit of file0 into file1. + +Starting from the same two files in the tree, we swap file0 and file1. +With -B, this should be detected as two complete rewrites, resulting in +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_expect_success \ + setup \ + 'cat ../../README >file0 && + cat ../../COPYING >file1 && + git-update-cache --add file0 file1 && + tree=$(git-write-tree) && + echo "$tree"' + +test_expect_success \ + 'change file1 with copy-edit of file0 and remove file0' \ + 'sed -e "s/git/GIT/" file0 >file1 && + rm -f file0 && + git-update-cache --remove file0 file1' + +test_expect_success \ + 'run diff with -B' \ + 'git-diff-cache -B --cached "$tree" >current' + +cat >expected <<\EOF +:100644 000000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 0000000000000000000000000000000000000000 D file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 11e331465a89c394dc25c780de230043750c1ec8 M100 file1 +EOF + +test_expect_success \ + 'validate result of -B (#1)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'run diff with -B and -M' \ + 'git-diff-cache -B -M "$tree" >current' + +cat >expected <<\EOF +:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c R100 file0 file1 +EOF + +test_expect_success \ + 'validate result of -B -M (#2)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'swap file0 and file1' \ + 'rm -f file0 file1 && + git-read-tree -m $tree && + git-checkout-cache -f -u -a && + mv file0 tmp && + mv file1 file0 && + mv tmp file1 && + git-update-cache file0 file1' + +test_expect_success \ + 'run diff with -B' \ + 'git-diff-cache -B "$tree" >current' + +cat >expected <<\EOF +:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 6ff87c4664981e4397625791c8ea3bbb5f2279a3 M100 file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 +EOF + +test_expect_success \ + 'validate result of -B (#3)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'run diff with -B and -M' \ + 'git-diff-cache -B -M "$tree" >current' + +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 R100 file1 file0 +:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R100 file0 file1 +EOF + +test_expect_success \ + 'validate result of -B -M (#4)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'make file0 into something completely different' \ + 'rm -f file0 && + ln -s frotz file0 && + git-update-cache file0 file1' + +test_expect_success \ + 'run diff with -B' \ + 'git-diff-cache -B "$tree" >current' + +cat >expected <<\EOF +:100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 +EOF + +test_expect_success \ + 'validate result of -B (#5)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'run diff with -B' \ + 'git-diff-cache -B -M "$tree" >current' + +# This should not mistake file0 as the copy source of new file1 +# due to type differences. +cat >expected <<\EOF +:100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1 +EOF + +test_expect_success \ + 'validate result of -B -M (#6)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'run diff with -M' \ + 'git-diff-cache -M "$tree" >current' + +# This should not mistake file0 as the copy source of new file1 +# due to type differences. +cat >expected <<\EOF +:100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M file1 +EOF + +test_expect_success \ + 'validate result of -M (#7)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'file1 edited to look like file0 and file0 rename-edited to file2' \ + 'rm -f file0 file1 && + git-read-tree -m $tree && + git-checkout-cache -f -u -a && + sed -e "s/git/GIT/" file0 >file1 && + sed -e "s/git/GET/" file0 >file2 && + rm -f file0 + git-update-cache --add --remove file0 file1 file2' + +test_expect_success \ + 'run diff with -B' \ + 'git-diff-cache -B "$tree" >current' + +cat >expected <<\EOF +:100644 000000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 0000000000000000000000000000000000000000 D file0 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 08bb2fb671deff4c03a4d4a0a1315dff98d5732c M100 file1 +:000000 100644 0000000000000000000000000000000000000000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 A file2 +EOF + +test_expect_success \ + 'validate result of -B (#8)' \ + 'compare_diff_raw expected current' + +test_expect_success \ + 'run diff with -B -M' \ + 'git-diff-cache -B -M "$tree" >current' + +cat >expected <<\EOF +:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095 file0 file1 +:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 59f832e5c8b3f7e486be15ad0cd3e95ba9af8998 R095 file0 file2 +EOF + +test_expect_success \ + 'validate result of -B -M (#9)' \ + 'compare_diff_raw expected current' + +test_done diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh new file mode 100755 index 0000000000..6229a5bf1a --- /dev/null +++ b/t/t4009-diff-rename-4.sh @@ -0,0 +1,175 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +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_expect_success \ + 'prepare reference tree' \ + 'cat ../../COPYING >COPYING && + echo frotz >rezrov && + git-update-cache --add COPYING rezrov && + tree=$(git-write-tree) && + echo $tree' + +test_expect_success \ + 'prepare work tree' \ + 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && + sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && + rm -f COPYING && + git-update-cache --add --remove COPYING COPYING.?' + +# tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, +# both are slightly edited, and unchanged rezrov. We say COPYING.1 +# and COPYING.2 are based on COPYING, and do not say anything about +# rezrov. + +git-diff-cache -z -M $tree >current + +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +COPYING +COPYING.1 +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234 +COPYING +COPYING.2 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#1)' \ + 'compare_diff_raw_z current expected' + +# make sure diff-helper can grok it. +mv current diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper -z <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +diff --git a/COPYING b/COPYING.2 +rename from COPYING +rename to COPYING.2 +--- a/COPYING ++++ b/COPYING.2 +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +EOF + +test_expect_success \ + 'validate output from diff-helper (#1)' \ + 'compare_diff_patch current expected' + +################################################################ + +test_expect_success \ + 'prepare work tree again' \ + 'mv COPYING.2 COPYING && + git-update-cache --add --remove COPYING COPYING.1 COPYING.2' + +# tree has COPYING and rezrov. work tree has COPYING and COPYING.1, +# both are slightly edited, and unchanged rezrov. We say COPYING.1 +# is based on COPYING and COPYING is still there, and do not say anything +# about rezrov. + +git-diff-cache -z -C $tree >current +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M +COPYING +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +COPYING +COPYING.1 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#2)' \ + 'compare_diff_raw_z current expected' + +# make sure diff-helper can grok it. +mv current diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper -z <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING +--- a/COPYING ++++ b/COPYING +@@ -2 +2 @@ +- Note that the only valid version of the GPL as far as this project ++ Note that the only valid version of the G.P.L as far as this project +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ HOWEVER, in order to allow a migration to G.P.Lv3 if that seems like +@@ -12 +12 @@ +- This file is licensed under the GPL v2, or a later version ++ This file is licensed under the G.P.L v2, or a later version +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from diff-helper (#2)' \ + 'compare_diff_patch current expected' + +################################################################ + +# tree has COPYING and rezrov. work tree has the same COPYING and +# copy-edited COPYING.1, and unchanged rezrov. We should not say +# anything about rezrov nor COPYING, since the revised again diff-raw +# nows how to say Copy. + +test_expect_success \ + 'prepare work tree once again' \ + 'cat ../../COPYING >COPYING && + git-update-cache --add --remove COPYING COPYING.1' + +git-diff-cache -z -C --find-copies-harder $tree >current +cat >expected <<\EOF +:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +COPYING +COPYING.1 +EOF + +test_expect_success \ + 'validate output from rename/copy detection (#3)' \ + 'compare_diff_raw_z current expected' + +# make sure diff-helper can grok it. +mv current diff-raw +GIT_DIFF_OPTS=--unified=0 git-diff-helper -z <diff-raw >current +cat >expected <<\EOF +diff --git a/COPYING b/COPYING.1 +copy from COPYING +copy to COPYING.1 +--- a/COPYING ++++ b/COPYING.1 +@@ -6 +6 @@ +- HOWEVER, in order to allow a migration to GPLv3 if that seems like ++ However, in order to allow a migration to GPLv3 if that seems like +EOF + +test_expect_success \ + 'validate output from diff-helper (#3)' \ + 'compare_diff_patch current expected' + +test_done diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh new file mode 100755 index 0000000000..9f2c6f6aa2 --- /dev/null +++ b/t/t4010-diff-pathspec.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Pathspec restrictions + +Prepare: + file0 + path1/file1 +' +. ./test-lib.sh +. ../diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success \ + setup \ + 'echo frotz >file0 && + mkdir path1 && + echo rezrov >path1/file1 && + git-update-cache --add file0 path1/file1 && + tree=`git-write-tree` && + echo "$tree" && + echo nitfol >file0 && + echo yomin >path1/file1 && + git-update-cache file0 path1/file1' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to path should show nothing' \ + 'git-diff-cache --cached $tree path >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1 should show path1/file1' \ + 'git-diff-cache --cached $tree path1 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1/ should show path1/file1' \ + 'git-diff-cache --cached $tree path1/ >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M file0 +EOF +test_expect_success \ + 'limit to file0 should show file0' \ + 'git-diff-cache --cached $tree file0 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to file0/ should emit nothing.' \ + 'git-diff-cache --cached $tree file0/ >current && + compare_diff_raw current expected' + +test_done diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh new file mode 100755 index 0000000000..6579f06b05 --- /dev/null +++ b/t/t4100-apply-stat.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-apply --stat --summary test. + +' +. ./test-lib.sh + +test_expect_success \ + 'rename' \ + 'git-apply --stat --summary <../t4100/t-apply-1.patch >current && + diff -u ../t4100/t-apply-1.expect current' + +test_expect_success \ + 'copy' \ + 'git-apply --stat --summary <../t4100/t-apply-2.patch >current && + diff -u ../t4100/t-apply-2.expect current' + +test_expect_success \ + 'rewrite' \ + 'git-apply --stat --summary <../t4100/t-apply-3.patch >current && + diff -u ../t4100/t-apply-3.expect current' + +test_expect_success \ + 'mode' \ + 'git-apply --stat --summary <../t4100/t-apply-4.patch >current && + diff -u ../t4100/t-apply-4.expect current' + +test_expect_success \ + 'non git' \ + 'git-apply --stat --summary <../t4100/t-apply-5.patch >current && + diff -u ../t4100/t-apply-5.expect current' + +test_expect_success \ + 'non git' \ + 'git-apply --stat --summary <../t4100/t-apply-6.patch >current && + diff -u ../t4100/t-apply-6.expect current' + +test_expect_success \ + 'non git' \ + 'git-apply --stat --summary <../t4100/t-apply-7.patch >current && + diff -u ../t4100/t-apply-7.expect current' + +test_done + diff --git a/t/t4100/t-apply-1.expect b/t/t4100/t-apply-1.expect new file mode 100644 index 0000000000..540e64db85 --- /dev/null +++ b/t/t4100/t-apply-1.expect @@ -0,0 +1,11 @@ + Documentation/git-ssh-pull.txt | 12 ++++++------ + Documentation/git-ssh-push.txt | 10 +++++----- + Documentation/git.txt | 6 +++--- + Makefile | 6 +++--- + ssh-pull.c | 4 ++-- + ssh-push.c | 14 +++++++------- + 6 files changed, 26 insertions(+), 26 deletions(-) + rename Documentation/{git-rpull.txt => git-ssh-pull.txt} (90%) + rename Documentation/{git-rpush.txt => git-ssh-push.txt} (71%) + rename rpull.c => ssh-pull.c (97%) + rename rpush.c => ssh-push.c (93%) diff --git a/t/t4100/t-apply-1.patch b/t/t4100/t-apply-1.patch new file mode 100644 index 0000000000..de587517f4 --- /dev/null +++ b/t/t4100/t-apply-1.patch @@ -0,0 +1,194 @@ +418aaf847a8b3ffffb4f777a2dd5262ca5ce0ef7 (from dc93841715dfa9a9cdda6f2c4a25eec831ea7aa0) +diff --git a/Documentation/git-rpull.txt b/Documentation/git-ssh-pull.txt +similarity index 90% +rename from Documentation/git-rpull.txt +rename to Documentation/git-ssh-pull.txt +--- a/Documentation/git-rpull.txt ++++ b/Documentation/git-ssh-pull.txt +@@ -1,21 +1,21 @@ +-git-rpull(1) +-============ ++git-ssh-pull(1) ++=============== + v0.1, May 2005 + + NAME + ---- +-git-rpull - Pulls from a remote repository over ssh connection ++git-ssh-pull - Pulls from a remote repository over ssh connection + + + + SYNOPSIS + -------- +-'git-rpull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url ++'git-ssh-pull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url + + DESCRIPTION + ----------- +-Pulls from a remote repository over ssh connection, invoking git-rpush on +-the other end. ++Pulls from a remote repository over ssh connection, invoking git-ssh-push ++on the other end. + + OPTIONS + ------- +diff --git a/Documentation/git-rpush.txt b/Documentation/git-ssh-push.txt +similarity index 71% +rename from Documentation/git-rpush.txt +rename to Documentation/git-ssh-push.txt +--- a/Documentation/git-rpush.txt ++++ b/Documentation/git-ssh-push.txt +@@ -1,19 +1,19 @@ +-git-rpush(1) +-============ ++git-ssh-push(1) ++=============== + v0.1, May 2005 + + NAME + ---- +-git-rpush - Helper "server-side" program used by git-rpull ++git-ssh-push - Helper "server-side" program used by git-ssh-pull + + + SYNOPSIS + -------- +-'git-rpush' ++'git-ssh-push' + + DESCRIPTION + ----------- +-Helper "server-side" program used by git-rpull. ++Helper "server-side" program used by git-ssh-pull. + + + Author +diff --git a/Documentation/git.txt b/Documentation/git.txt +--- a/Documentation/git.txt ++++ b/Documentation/git.txt +@@ -148,7 +148,7 @@ link:git-resolve-script.html[git-resolve + link:git-tag-script.html[git-tag-script]:: + An example script to create a tag object signed with GPG + +-link:git-rpull.html[git-rpull]:: ++link:git-ssh-pull.html[git-ssh-pull]:: + Pulls from a remote repository over ssh connection + + Interogators: +@@ -156,8 +156,8 @@ Interogators: + link:git-diff-helper.html[git-diff-helper]:: + Generates patch format output for git-diff-* + +-link:git-rpush.html[git-rpush]:: +- Helper "server-side" program used by git-rpull ++link:git-ssh-push.html[git-ssh-push]:: ++ Helper "server-side" program used by git-ssh-pull + + + +diff --git a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files + git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ + git-check-files git-ls-tree git-merge-base git-merge-cache \ + git-unpack-file git-export git-diff-cache git-convert-cache \ +- git-http-pull git-rpush git-rpull git-rev-list git-mktag \ ++ git-http-pull git-ssh-push git-ssh-pull git-rev-list git-mktag \ + git-diff-helper git-tar-tree git-local-pull git-write-blob \ + git-get-tar-commit-id git-mkdelta git-apply git-stripspace + +@@ -105,8 +105,8 @@ git-diff-cache: diff-cache.c + git-convert-cache: convert-cache.c + git-http-pull: http-pull.c pull.c + git-local-pull: local-pull.c pull.c +-git-rpush: rsh.c +-git-rpull: rsh.c pull.c ++git-ssh-push: rsh.c ++git-ssh-pull: rsh.c pull.c + git-rev-list: rev-list.c + git-mktag: mktag.c + git-diff-helper: diff-helper.c +diff --git a/rpull.c b/ssh-pull.c +similarity index 97% +rename from rpull.c +rename to ssh-pull.c +--- a/rpull.c ++++ b/ssh-pull.c +@@ -64,13 +64,13 @@ int main(int argc, char **argv) + arg++; + } + if (argc < arg + 2) { +- usage("git-rpull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url"); ++ usage("git-ssh-pull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url"); + return 1; + } + commit_id = argv[arg]; + url = argv[arg + 1]; + +- if (setup_connection(&fd_in, &fd_out, "git-rpush", url, arg, argv + 1)) ++ if (setup_connection(&fd_in, &fd_out, "git-ssh-push", url, arg, argv + 1)) + return 1; + + if (get_version()) +diff --git a/rpush.c b/ssh-push.c +similarity index 93% +rename from rpush.c +rename to ssh-push.c +--- a/rpush.c ++++ b/ssh-push.c +@@ -16,7 +16,7 @@ int serve_object(int fd_in, int fd_out) + do { + size = read(fd_in, sha1 + posn, 20 - posn); + if (size < 0) { +- perror("git-rpush: read "); ++ perror("git-ssh-push: read "); + return -1; + } + if (!size) +@@ -30,7 +30,7 @@ int serve_object(int fd_in, int fd_out) + buf = map_sha1_file(sha1, &objsize); + + if (!buf) { +- fprintf(stderr, "git-rpush: could not find %s\n", ++ fprintf(stderr, "git-ssh-push: could not find %s\n", + sha1_to_hex(sha1)); + remote = -1; + } +@@ -45,9 +45,9 @@ int serve_object(int fd_in, int fd_out) + size = write(fd_out, buf + posn, objsize - posn); + if (size <= 0) { + if (!size) { +- fprintf(stderr, "git-rpush: write closed"); ++ fprintf(stderr, "git-ssh-push: write closed"); + } else { +- perror("git-rpush: write "); ++ perror("git-ssh-push: write "); + } + return -1; + } +@@ -71,7 +71,7 @@ void service(int fd_in, int fd_out) { + retval = read(fd_in, &type, 1); + if (retval < 1) { + if (retval < 0) +- perror("rpush: read "); ++ perror("git-ssh-push: read "); + return; + } + if (type == 'v' && serve_version(fd_in, fd_out)) +@@ -91,12 +91,12 @@ int main(int argc, char **argv) + arg++; + } + if (argc < arg + 2) { +- usage("git-rpush [-c] [-t] [-a] commit-id url"); ++ usage("git-ssh-push [-c] [-t] [-a] commit-id url"); + return 1; + } + commit_id = argv[arg]; + url = argv[arg + 1]; +- if (setup_connection(&fd_in, &fd_out, "git-rpull", url, arg, argv + 1)) ++ if (setup_connection(&fd_in, &fd_out, "git-ssh-pull", url, arg, argv + 1)) + return 1; + + service(fd_in, fd_out); diff --git a/t/t4100/t-apply-2.expect b/t/t4100/t-apply-2.expect new file mode 100644 index 0000000000..d1e6459749 --- /dev/null +++ b/t/t4100/t-apply-2.expect @@ -0,0 +1,5 @@ + Makefile | 2 +- + git-fetch-script | 5 ----- + git-pull-script | 34 +--------------------------------- + 3 files changed, 2 insertions(+), 39 deletions(-) + copy git-pull-script => git-fetch-script (87%) diff --git a/t/t4100/t-apply-2.patch b/t/t4100/t-apply-2.patch new file mode 100644 index 0000000000..cfdc80885b --- /dev/null +++ b/t/t4100/t-apply-2.patch @@ -0,0 +1,72 @@ +7ef76925d9c19ef74874e1735e2436e56d0c4897 (from 6b14d7faf0bad026a81a27bac07b47691f621b8f) +diff --git a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -20,7 +20,7 @@ INSTALL=install + + SCRIPTS=git-apply-patch-script git-merge-one-file-script git-prune-script \ + git-pull-script git-tag-script git-resolve-script git-whatchanged \ +- git-deltafy-script ++ git-deltafy-script git-fetch-script + + PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + git-read-tree git-commit-tree git-cat-file git-fsck-cache \ +diff --git a/git-pull-script b/git-fetch-script +similarity index 87% +copy from git-pull-script +copy to git-fetch-script +--- a/git-pull-script ++++ b/git-fetch-script +@@ -39,8 +39,3 @@ download_one "$merge_repo/$merge_name" " + + echo "Getting object database" + download_objects "$merge_repo" "$(cat "$GIT_DIR"/MERGE_HEAD)" +- +-git-resolve-script \ +- "$(cat "$GIT_DIR"/HEAD)" \ +- "$(cat "$GIT_DIR"/MERGE_HEAD)" \ +- "$merge_repo" +diff --git a/git-pull-script b/git-pull-script +--- a/git-pull-script ++++ b/git-pull-script +@@ -6,39 +6,7 @@ merge_name=${2:-HEAD} + : ${GIT_DIR=.git} + : ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} + +-download_one () { +- # remote_path="$1" local_file="$2" +- case "$1" in +- http://*) +- wget -q -O "$2" "$1" ;; +- /*) +- test -f "$1" && cat >"$2" "$1" ;; +- *) +- rsync -L "$1" "$2" ;; +- esac +-} +- +-download_objects () { +- # remote_repo="$1" head_sha1="$2" +- case "$1" in +- http://*) +- git-http-pull -a "$2" "$1/" +- ;; +- /*) +- git-local-pull -l -a "$2" "$1/" +- ;; +- *) +- rsync -avz --ignore-existing \ +- "$1/objects/." "$GIT_OBJECT_DIRECTORY"/. +- ;; +- esac +-} +- +-echo "Getting remote $merge_name" +-download_one "$merge_repo/$merge_name" "$GIT_DIR"/MERGE_HEAD +- +-echo "Getting object database" +-download_objects "$merge_repo" "$(cat "$GIT_DIR"/MERGE_HEAD)" ++git-fetch-script "$merge_repo" "$merge_name" + + git-resolve-script \ + "$(cat "$GIT_DIR"/HEAD)" \ diff --git a/t/t4100/t-apply-3.expect b/t/t4100/t-apply-3.expect new file mode 100644 index 0000000000..912a552a7a --- /dev/null +++ b/t/t4100/t-apply-3.expect @@ -0,0 +1,7 @@ + Documentation/git-ls-tree.txt | 20 +- + ls-tree.c | 459 ++++++++++++++++++++++------------------- + t/t3100-ls-tree-restrict.sh | 3 + tree.c | 2 + tree.h | 1 + 5 files changed, 262 insertions(+), 223 deletions(-) + rewrite ls-tree.c (82%) diff --git a/t/t4100/t-apply-3.patch b/t/t4100/t-apply-3.patch new file mode 100644 index 0000000000..90cdbaa5bb --- /dev/null +++ b/t/t4100/t-apply-3.patch @@ -0,0 +1,567 @@ +6af1f0192ff8740fe77db7cf02c739ccfbdf119c (from 2bc2564145835996734d6ed5d1880f85b17233d6) +diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt +--- a/Documentation/git-ls-tree.txt ++++ b/Documentation/git-ls-tree.txt +@@ -4,23 +4,26 @@ v0.1, May 2005 + + NAME + ---- +-git-ls-tree - Displays a tree object in human readable form ++git-ls-tree - Lists the contents of a tree object. + + + SYNOPSIS + -------- +-'git-ls-tree' [-r] [-z] <tree-ish> [paths...] ++'git-ls-tree' [-d] [-r] [-z] <tree-ish> [paths...] + + DESCRIPTION + ----------- +-Converts the tree object to a human readable (and script processable) +-form. ++Lists the contents of a tree object, like what "/bin/ls -a" does ++in the current working directory. + + OPTIONS + ------- + <tree-ish>:: + Id of a tree. + ++-d:: ++ show only the named tree entry itself, not its children ++ + -r:: + recurse into sub-trees + +@@ -28,18 +31,19 @@ OPTIONS + \0 line termination on output + + paths:: +- Optionally, restrict the output of git-ls-tree to specific +- paths. Directories will only list their tree blob ids. +- Implies -r. ++ When paths are given, shows them. Otherwise implicitly ++ uses the root level of the tree as the sole path argument. ++ + + Output Format + ------------- +- <mode>\t <type>\t <object>\t <file> ++ <mode> SP <type> SP <object> TAB <file> + + + Author + ------ + Written by Linus Torvalds <torvalds@osdl.org> ++Completely rewritten from scratch by Junio C Hamano <junkio@cox.net> + + Documentation + -------------- +diff --git a/ls-tree.c b/ls-tree.c +dissimilarity index 82% +--- ls-tree.c ++++ ls-tree.c +@@ -1,212 +1,247 @@ +-/* +- * GIT - The information manager from hell +- * +- * Copyright (C) Linus Torvalds, 2005 +- */ +-#include "cache.h" +- +-static int line_termination = '\n'; +-static int recursive = 0; +- +-struct path_prefix { +- struct path_prefix *prev; +- const char *name; +-}; +- +-#define DEBUG(fmt, ...) +- +-static int string_path_prefix(char *buff, size_t blen, struct path_prefix *prefix) +-{ +- int len = 0; +- if (prefix) { +- if (prefix->prev) { +- len = string_path_prefix(buff,blen,prefix->prev); +- buff += len; +- blen -= len; +- if (blen > 0) { +- *buff = '/'; +- len++; +- buff++; +- blen--; +- } +- } +- strncpy(buff,prefix->name,blen); +- return len + strlen(prefix->name); +- } +- +- return 0; +-} +- +-static void print_path_prefix(struct path_prefix *prefix) +-{ +- if (prefix) { +- if (prefix->prev) { +- print_path_prefix(prefix->prev); +- putchar('/'); +- } +- fputs(prefix->name, stdout); +- } +-} +- +-/* +- * return: +- * -1 if prefix is *not* a subset of path +- * 0 if prefix == path +- * 1 if prefix is a subset of path +- */ +-static int pathcmp(const char *path, struct path_prefix *prefix) +-{ +- char buff[PATH_MAX]; +- int len,slen; +- +- if (prefix == NULL) +- return 1; +- +- len = string_path_prefix(buff, sizeof buff, prefix); +- slen = strlen(path); +- +- if (slen < len) +- return -1; +- +- if (strncmp(path,buff,len) == 0) { +- if (slen == len) +- return 0; +- else +- return 1; +- } +- +- return -1; +-} +- +-/* +- * match may be NULL, or a *sorted* list of paths +- */ +-static void list_recursive(void *buffer, +- const char *type, +- unsigned long size, +- struct path_prefix *prefix, +- char **match, int matches) +-{ +- struct path_prefix this_prefix; +- this_prefix.prev = prefix; +- +- if (strcmp(type, "tree")) +- die("expected a 'tree' node"); +- +- if (matches) +- recursive = 1; +- +- while (size) { +- int namelen = strlen(buffer)+1; +- void *eltbuf = NULL; +- char elttype[20]; +- unsigned long eltsize; +- unsigned char *sha1 = buffer + namelen; +- char *path = strchr(buffer, ' ') + 1; +- unsigned int mode; +- const char *matched = NULL; +- int mtype = -1; +- int mindex; +- +- if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1) +- die("corrupt 'tree' file"); +- buffer = sha1 + 20; +- size -= namelen + 20; +- +- this_prefix.name = path; +- for ( mindex = 0; mindex < matches; mindex++) { +- mtype = pathcmp(match[mindex],&this_prefix); +- if (mtype >= 0) { +- matched = match[mindex]; +- break; +- } +- } +- +- /* +- * If we're not matching, or if this is an exact match, +- * print out the info +- */ +- if (!matches || (matched != NULL && mtype == 0)) { +- printf("%06o %s %s\t", mode, +- S_ISDIR(mode) ? "tree" : "blob", +- sha1_to_hex(sha1)); +- print_path_prefix(&this_prefix); +- putchar(line_termination); +- } +- +- if (! recursive || ! S_ISDIR(mode)) +- continue; +- +- if (matches && ! matched) +- continue; +- +- if (! (eltbuf = read_sha1_file(sha1, elttype, &eltsize)) ) { +- error("cannot read %s", sha1_to_hex(sha1)); +- continue; +- } +- +- /* If this is an exact directory match, we may have +- * directory files following this path. Match on them. +- * Otherwise, we're at a pach subcomponent, and we need +- * to try to match again. +- */ +- if (mtype == 0) +- mindex++; +- +- list_recursive(eltbuf, elttype, eltsize, &this_prefix, &match[mindex], matches-mindex); +- free(eltbuf); +- } +-} +- +-static int qcmp(const void *a, const void *b) +-{ +- return strcmp(*(char **)a, *(char **)b); +-} +- +-static int list(unsigned char *sha1,char **path) +-{ +- void *buffer; +- unsigned long size; +- int npaths; +- +- for (npaths = 0; path[npaths] != NULL; npaths++) +- ; +- +- qsort(path,npaths,sizeof(char *),qcmp); +- +- buffer = read_object_with_reference(sha1, "tree", &size, NULL); +- if (!buffer) +- die("unable to read sha1 file"); +- list_recursive(buffer, "tree", size, NULL, path, npaths); +- free(buffer); +- return 0; +-} +- +-static const char *ls_tree_usage = "git-ls-tree [-r] [-z] <key> [paths...]"; +- +-int main(int argc, char **argv) +-{ +- unsigned char sha1[20]; +- +- while (1 < argc && argv[1][0] == '-') { +- switch (argv[1][1]) { +- case 'z': +- line_termination = 0; +- break; +- case 'r': +- recursive = 1; +- break; +- default: +- usage(ls_tree_usage); +- } +- argc--; argv++; +- } +- +- if (argc < 2) +- usage(ls_tree_usage); +- if (get_sha1(argv[1], sha1) < 0) +- usage(ls_tree_usage); +- if (list(sha1, &argv[2]) < 0) +- die("list failed"); +- return 0; +-} ++/* ++ * GIT - The information manager from hell ++ * ++ * Copyright (C) Linus Torvalds, 2005 ++ */ ++#include "cache.h" ++#include "blob.h" ++#include "tree.h" ++ ++static int line_termination = '\n'; ++#define LS_RECURSIVE 1 ++#define LS_TREE_ONLY 2 ++static int ls_options = 0; ++ ++static struct tree_entry_list root_entry; ++ ++static void prepare_root(unsigned char *sha1) ++{ ++ unsigned char rsha[20]; ++ unsigned long size; ++ void *buf; ++ struct tree *root_tree; ++ ++ buf = read_object_with_reference(sha1, "tree", &size, rsha); ++ free(buf); ++ if (!buf) ++ die("Could not read %s", sha1_to_hex(sha1)); ++ ++ root_tree = lookup_tree(rsha); ++ if (!root_tree) ++ die("Could not read %s", sha1_to_hex(sha1)); ++ ++ /* Prepare a fake entry */ ++ root_entry.directory = 1; ++ root_entry.executable = root_entry.symlink = 0; ++ root_entry.mode = S_IFDIR; ++ root_entry.name = ""; ++ root_entry.item.tree = root_tree; ++ root_entry.parent = NULL; ++} ++ ++static int prepare_children(struct tree_entry_list *elem) ++{ ++ if (!elem->directory) ++ return -1; ++ if (!elem->item.tree->object.parsed) { ++ struct tree_entry_list *e; ++ if (parse_tree(elem->item.tree)) ++ return -1; ++ /* Set up the parent link */ ++ for (e = elem->item.tree->entries; e; e = e->next) ++ e->parent = elem; ++ } ++ return 0; ++} ++ ++static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem, ++ const char *path, ++ const char *path_end) ++{ ++ const char *ep; ++ int len; ++ ++ while (path < path_end) { ++ if (prepare_children(elem)) ++ return NULL; ++ ++ /* In elem->tree->entries, find the one that has name ++ * that matches what is between path and ep. ++ */ ++ elem = elem->item.tree->entries; ++ ++ ep = strchr(path, '/'); ++ if (!ep || path_end <= ep) ++ ep = path_end; ++ len = ep - path; ++ ++ while (elem) { ++ if ((strlen(elem->name) == len) && ++ !strncmp(elem->name, path, len)) ++ break; ++ elem = elem->next; ++ } ++ if (path_end <= ep || !elem) ++ return elem; ++ while (*ep == '/' && ep < path_end) ++ ep++; ++ path = ep; ++ } ++ return NULL; ++} ++ ++static struct tree_entry_list *find_entry(const char *path, ++ const char *path_end) ++{ ++ /* Find tree element, descending from root, that ++ * corresponds to the named path, lazily expanding ++ * the tree if possible. ++ */ ++ if (path == path_end) { ++ /* Special. This is the root level */ ++ return &root_entry; ++ } ++ return find_entry_0(&root_entry, path, path_end); ++} ++ ++static void show_entry_name(struct tree_entry_list *e) ++{ ++ /* This is yucky. The root level is there for ++ * our convenience but we really want to do a ++ * forest. ++ */ ++ if (e->parent && e->parent != &root_entry) { ++ show_entry_name(e->parent); ++ putchar('/'); ++ } ++ printf("%s", e->name); ++} ++ ++static const char *entry_type(struct tree_entry_list *e) ++{ ++ return (e->directory ? "tree" : "blob"); ++} ++ ++static const char *entry_hex(struct tree_entry_list *e) ++{ ++ return sha1_to_hex(e->directory ++ ? e->item.tree->object.sha1 ++ : e->item.blob->object.sha1); ++} ++ ++/* forward declaration for mutually recursive routines */ ++static int show_entry(struct tree_entry_list *, int); ++ ++static int show_children(struct tree_entry_list *e, int level) ++{ ++ if (prepare_children(e)) ++ die("internal error: ls-tree show_children called with non tree"); ++ e = e->item.tree->entries; ++ while (e) { ++ show_entry(e, level); ++ e = e->next; ++ } ++ return 0; ++} ++ ++static int show_entry(struct tree_entry_list *e, int level) ++{ ++ int err = 0; ++ ++ if (e != &root_entry) { ++ printf("%06o %s %s ", e->mode, entry_type(e), ++ entry_hex(e)); ++ show_entry_name(e); ++ putchar(line_termination); ++ } ++ ++ if (e->directory) { ++ /* If this is a directory, we have the following cases: ++ * (1) This is the top-level request (explicit path from the ++ * command line, or "root" if there is no command line). ++ * a. Without any flag. We show direct children. We do not ++ * recurse into them. ++ * b. With -r. We do recurse into children. ++ * c. With -d. We do not recurse into children. ++ * (2) We came here because our caller is either (1-a) or ++ * (1-b). ++ * a. Without any flag. We do not show our children (which ++ * are grandchildren for the original request). ++ * b. With -r. We continue to recurse into our children. ++ * c. With -d. We should not have come here to begin with. ++ */ ++ if (level == 0 && !(ls_options & LS_TREE_ONLY)) ++ /* case (1)-a and (1)-b */ ++ err = err | show_children(e, level+1); ++ else if (level && ls_options & LS_RECURSIVE) ++ /* case (2)-b */ ++ err = err | show_children(e, level+1); ++ } ++ return err; ++} ++ ++static int list_one(const char *path, const char *path_end) ++{ ++ int err = 0; ++ struct tree_entry_list *e = find_entry(path, path_end); ++ if (!e) { ++ /* traditionally ls-tree does not complain about ++ * missing path. We may change this later to match ++ * what "/bin/ls -a" does, which is to complain. ++ */ ++ return err; ++ } ++ err = err | show_entry(e, 0); ++ return err; ++} ++ ++static int list(char **path) ++{ ++ int i; ++ int err = 0; ++ for (i = 0; path[i]; i++) { ++ int len = strlen(path[i]); ++ while (0 <= len && path[i][len] == '/') ++ len--; ++ err = err | list_one(path[i], path[i] + len); ++ } ++ return err; ++} ++ ++static const char *ls_tree_usage = ++ "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"; ++ ++int main(int argc, char **argv) ++{ ++ static char *path0[] = { "", NULL }; ++ char **path; ++ unsigned char sha1[20]; ++ ++ while (1 < argc && argv[1][0] == '-') { ++ switch (argv[1][1]) { ++ case 'z': ++ line_termination = 0; ++ break; ++ case 'r': ++ ls_options |= LS_RECURSIVE; ++ break; ++ case 'd': ++ ls_options |= LS_TREE_ONLY; ++ break; ++ default: ++ usage(ls_tree_usage); ++ } ++ argc--; argv++; ++ } ++ ++ if (argc < 2) ++ usage(ls_tree_usage); ++ if (get_sha1(argv[1], sha1) < 0) ++ usage(ls_tree_usage); ++ ++ path = (argc == 2) ? path0 : (argv + 2); ++ prepare_root(sha1); ++ if (list(path) < 0) ++ die("list failed"); ++ return 0; ++} +diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh +--- a/t/t3100-ls-tree-restrict.sh ++++ b/t/t3100-ls-tree-restrict.sh +@@ -74,8 +74,8 @@ test_expect_success \ + 'ls-tree filtered' \ + 'git-ls-tree $tree path1 path0 >current && + cat >expected <<\EOF && +-100644 blob X path0 + 120000 blob X path1 ++100644 blob X path0 + EOF + test_output' + +@@ -85,7 +85,6 @@ test_expect_success \ + cat >expected <<\EOF && + 040000 tree X path2 + 040000 tree X path2/baz +-100644 blob X path2/baz/b + 120000 blob X path2/bazbo + 100644 blob X path2/foo + EOF +diff --git a/tree.c b/tree.c +--- a/tree.c ++++ b/tree.c +@@ -133,7 +133,7 @@ int parse_tree_buffer(struct tree *item, + } + if (obj) + add_ref(&item->object, obj); +- ++ entry->parent = NULL; /* needs to be filled by the user */ + *list_p = entry; + list_p = &entry->next; + } +diff --git a/tree.h b/tree.h +--- a/tree.h ++++ b/tree.h +@@ -16,6 +16,7 @@ struct tree_entry_list { + struct tree *tree; + struct blob *blob; + } item; ++ struct tree_entry_list *parent; + }; + + struct tree { diff --git a/t/t4100/t-apply-4.expect b/t/t4100/t-apply-4.expect new file mode 100644 index 0000000000..1ec028b3d0 --- /dev/null +++ b/t/t4100/t-apply-4.expect @@ -0,0 +1,5 @@ + t/t0000-basic.sh | 0 + t/test-lib.sh | 0 + 2 files changed, 0 insertions(+), 0 deletions(-) + mode change 100644 => 100755 t/t0000-basic.sh + mode change 100644 => 100755 t/test-lib.sh diff --git a/t/t4100/t-apply-4.patch b/t/t4100/t-apply-4.patch new file mode 100644 index 0000000000..4a56ab5cf4 --- /dev/null +++ b/t/t4100/t-apply-4.patch @@ -0,0 +1,7 @@ +ceede59ea90cebad52ba9c8263fef3fb6ef17593 (from 368f99d57e8ed17243f2e164431449d48bfca2fb) +diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh +old mode 100644 +new mode 100755 +diff --git a/t/test-lib.sh b/t/test-lib.sh +old mode 100644 +new mode 100755 diff --git a/t/t4100/t-apply-5.expect b/t/t4100/t-apply-5.expect new file mode 100644 index 0000000000..b387df15d4 --- /dev/null +++ b/t/t4100/t-apply-5.expect @@ -0,0 +1,19 @@ + Documentation/git-rpull.txt | 50 ------------------- + Documentation/git-rpush.txt | 30 ------------ + Documentation/git-ssh-pull.txt | 50 +++++++++++++++++++ + Documentation/git-ssh-push.txt | 30 ++++++++++++ + Documentation/git.txt | 6 +- + Makefile | 6 +- + rpull.c | 83 -------------------------------- + rpush.c | 104 ---------------------------------------- + ssh-pull.c | 83 ++++++++++++++++++++++++++++++++ + ssh-push.c | 104 ++++++++++++++++++++++++++++++++++++++++ + 10 files changed, 273 insertions(+), 273 deletions(-) + delete Documentation/git-rpull.txt + delete Documentation/git-rpush.txt + create Documentation/git-ssh-pull.txt + create Documentation/git-ssh-push.txt + delete rpull.c + delete rpush.c + create ssh-pull.c + create ssh-push.c diff --git a/t/t4100/t-apply-5.patch b/t/t4100/t-apply-5.patch new file mode 100644 index 0000000000..de11623d1b --- /dev/null +++ b/t/t4100/t-apply-5.patch @@ -0,0 +1,612 @@ +diff a/Documentation/git-rpull.txt b/Documentation/git-rpull.txt +--- a/Documentation/git-rpull.txt ++++ /dev/null +@@ -1,50 +0,0 @@ +-git-rpull(1) +-============ +-v0.1, May 2005 +- +-NAME +----- +-git-rpull - Pulls from a remote repository over ssh connection +- +- +- +-SYNOPSIS +--------- +-'git-rpull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url +- +-DESCRIPTION +------------ +-Pulls from a remote repository over ssh connection, invoking git-rpush on +-the other end. +- +-OPTIONS +-------- +--c:: +- Get the commit objects. +--t:: +- Get trees associated with the commit objects. +--a:: +- Get all the objects. +--d:: +- Do not check for delta base objects (use this option +- only when you know the remote repository is not +- deltified). +---recover:: +- Check dependency of deltified object more carefully than +- usual, to recover after earlier pull that was interrupted. +--v:: +- Report what is downloaded. +- +- +-Author +------- +-Written by Linus Torvalds <torvalds@osdl.org> +- +-Documentation +--------------- +-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>. +- +-GIT +---- +-Part of the link:git.html[git] suite +- +diff a/Documentation/git-rpush.txt b/Documentation/git-rpush.txt +--- a/Documentation/git-rpush.txt ++++ /dev/null +@@ -1,30 +0,0 @@ +-git-rpush(1) +-============ +-v0.1, May 2005 +- +-NAME +----- +-git-rpush - Helper "server-side" program used by git-rpull +- +- +-SYNOPSIS +--------- +-'git-rpush' +- +-DESCRIPTION +------------ +-Helper "server-side" program used by git-rpull. +- +- +-Author +------- +-Written by Linus Torvalds <torvalds@osdl.org> +- +-Documentation +--------------- +-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>. +- +-GIT +---- +-Part of the link:git.html[git] suite +- +diff a/Documentation/git-ssh-pull.txt b/Documentation/git-ssh-pull.txt +--- /dev/null ++++ b/Documentation/git-ssh-pull.txt +@@ -0,0 +1,50 @@ ++git-ssh-pull(1) ++=============== ++v0.1, May 2005 ++ ++NAME ++---- ++git-ssh-pull - Pulls from a remote repository over ssh connection ++ ++ ++ ++SYNOPSIS ++-------- ++'git-ssh-pull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url ++ ++DESCRIPTION ++----------- ++Pulls from a remote repository over ssh connection, invoking git-ssh-push ++on the other end. ++ ++OPTIONS ++------- ++-c:: ++ Get the commit objects. ++-t:: ++ Get trees associated with the commit objects. ++-a:: ++ Get all the objects. ++-d:: ++ Do not check for delta base objects (use this option ++ only when you know the remote repository is not ++ deltified). ++--recover:: ++ Check dependency of deltified object more carefully than ++ usual, to recover after earlier pull that was interrupted. ++-v:: ++ Report what is downloaded. ++ ++ ++Author ++------ ++Written by Linus Torvalds <torvalds@osdl.org> ++ ++Documentation ++-------------- ++Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>. ++ ++GIT ++--- ++Part of the link:git.html[git] suite ++ +diff a/Documentation/git-ssh-push.txt b/Documentation/git-ssh-push.txt +--- /dev/null ++++ b/Documentation/git-ssh-push.txt +@@ -0,0 +1,30 @@ ++git-ssh-push(1) ++=============== ++v0.1, May 2005 ++ ++NAME ++---- ++git-ssh-push - Helper "server-side" program used by git-ssh-pull ++ ++ ++SYNOPSIS ++-------- ++'git-ssh-push' ++ ++DESCRIPTION ++----------- ++Helper "server-side" program used by git-ssh-pull. ++ ++ ++Author ++------ ++Written by Linus Torvalds <torvalds@osdl.org> ++ ++Documentation ++-------------- ++Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>. ++ ++GIT ++--- ++Part of the link:git.html[git] suite ++ +diff a/Documentation/git.txt b/Documentation/git.txt +--- a/Documentation/git.txt ++++ b/Documentation/git.txt +@@ -148,7 +148,7 @@ link:git-resolve-script.html[git-resolve + link:git-tag-script.html[git-tag-script]:: + An example script to create a tag object signed with GPG + +-link:git-rpull.html[git-rpull]:: ++link:git-ssh-pull.html[git-ssh-pull]:: + Pulls from a remote repository over ssh connection + + Interogators: +@@ -156,8 +156,8 @@ Interogators: + link:git-diff-helper.html[git-diff-helper]:: + Generates patch format output for git-diff-* + +-link:git-rpush.html[git-rpush]:: +- Helper "server-side" program used by git-rpull ++link:git-ssh-push.html[git-ssh-push]:: ++ Helper "server-side" program used by git-ssh-pull + + + +diff a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -30,7 +30,7 @@ PROG= git-update-cache git-diff-files + git-checkout-cache git-diff-tree git-rev-tree git-ls-files \ + git-check-files git-ls-tree git-merge-base git-merge-cache \ + git-unpack-file git-export git-diff-cache git-convert-cache \ +- git-http-pull git-rpush git-rpull git-rev-list git-mktag \ ++ git-http-pull git-ssh-push git-ssh-pull git-rev-list git-mktag \ + git-diff-helper git-tar-tree git-local-pull git-write-blob \ + git-get-tar-commit-id git-mkdelta git-apply git-stripspace + +@@ -105,8 +105,8 @@ git-diff-cache: diff-cache.c + git-convert-cache: convert-cache.c + git-http-pull: http-pull.c pull.c + git-local-pull: local-pull.c pull.c +-git-rpush: rsh.c +-git-rpull: rsh.c pull.c ++git-ssh-push: rsh.c ++git-ssh-pull: rsh.c pull.c + git-rev-list: rev-list.c + git-mktag: mktag.c + git-diff-helper: diff-helper.c +diff a/rpull.c b/rpull.c +--- a/rpull.c ++++ /dev/null +@@ -1,83 +0,0 @@ +-#include "cache.h" +-#include "commit.h" +-#include "rsh.h" +-#include "pull.h" +- +-static int fd_in; +-static int fd_out; +- +-static unsigned char remote_version = 0; +-static unsigned char local_version = 1; +- +-int fetch(unsigned char *sha1) +-{ +- int ret; +- signed char remote; +- char type = 'o'; +- if (has_sha1_file(sha1)) +- return 0; +- write(fd_out, &type, 1); +- write(fd_out, sha1, 20); +- if (read(fd_in, &remote, 1) < 1) +- return -1; +- if (remote < 0) +- return remote; +- ret = write_sha1_from_fd(sha1, fd_in); +- if (!ret) +- pull_say("got %s\n", sha1_to_hex(sha1)); +- return ret; +-} +- +-int get_version(void) +-{ +- char type = 'v'; +- write(fd_out, &type, 1); +- write(fd_out, &local_version, 1); +- if (read(fd_in, &remote_version, 1) < 1) { +- return error("Couldn't read version from remote end"); +- } +- return 0; +-} +- +-int main(int argc, char **argv) +-{ +- char *commit_id; +- char *url; +- int arg = 1; +- +- while (arg < argc && argv[arg][0] == '-') { +- if (argv[arg][1] == 't') { +- get_tree = 1; +- } else if (argv[arg][1] == 'c') { +- get_history = 1; +- } else if (argv[arg][1] == 'd') { +- get_delta = 0; +- } else if (!strcmp(argv[arg], "--recover")) { +- get_delta = 2; +- } else if (argv[arg][1] == 'a') { +- get_all = 1; +- get_tree = 1; +- get_history = 1; +- } else if (argv[arg][1] == 'v') { +- get_verbosely = 1; +- } +- arg++; +- } +- if (argc < arg + 2) { +- usage("git-rpull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url"); +- return 1; +- } +- commit_id = argv[arg]; +- url = argv[arg + 1]; +- +- if (setup_connection(&fd_in, &fd_out, "git-rpush", url, arg, argv + 1)) +- return 1; +- +- if (get_version()) +- return 1; +- +- if (pull(commit_id)) +- return 1; +- +- return 0; +-} +diff a/rpush.c b/rpush.c +--- a/rpush.c ++++ /dev/null +@@ -1,104 +0,0 @@ +-#include "cache.h" +-#include "rsh.h" +-#include <sys/socket.h> +-#include <errno.h> +- +-unsigned char local_version = 1; +-unsigned char remote_version = 0; +- +-int serve_object(int fd_in, int fd_out) { +- ssize_t size; +- int posn = 0; +- char sha1[20]; +- unsigned long objsize; +- void *buf; +- signed char remote; +- do { +- size = read(fd_in, sha1 + posn, 20 - posn); +- if (size < 0) { +- perror("git-rpush: read "); +- return -1; +- } +- if (!size) +- return -1; +- posn += size; +- } while (posn < 20); +- +- /* fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); */ +- remote = 0; +- +- buf = map_sha1_file(sha1, &objsize); +- +- if (!buf) { +- fprintf(stderr, "git-rpush: could not find %s\n", +- sha1_to_hex(sha1)); +- remote = -1; +- } +- +- write(fd_out, &remote, 1); +- +- if (remote < 0) +- return 0; +- +- posn = 0; +- do { +- size = write(fd_out, buf + posn, objsize - posn); +- if (size <= 0) { +- if (!size) { +- fprintf(stderr, "git-rpush: write closed"); +- } else { +- perror("git-rpush: write "); +- } +- return -1; +- } +- posn += size; +- } while (posn < objsize); +- return 0; +-} +- +-int serve_version(int fd_in, int fd_out) +-{ +- if (read(fd_in, &remote_version, 1) < 1) +- return -1; +- write(fd_out, &local_version, 1); +- return 0; +-} +- +-void service(int fd_in, int fd_out) { +- char type; +- int retval; +- do { +- retval = read(fd_in, &type, 1); +- if (retval < 1) { +- if (retval < 0) +- perror("rpush: read "); +- return; +- } +- if (type == 'v' && serve_version(fd_in, fd_out)) +- return; +- if (type == 'o' && serve_object(fd_in, fd_out)) +- return; +- } while (1); +-} +- +-int main(int argc, char **argv) +-{ +- int arg = 1; +- char *commit_id; +- char *url; +- int fd_in, fd_out; +- while (arg < argc && argv[arg][0] == '-') { +- arg++; +- } +- if (argc < arg + 2) { +- usage("git-rpush [-c] [-t] [-a] commit-id url"); +- return 1; +- } +- commit_id = argv[arg]; +- url = argv[arg + 1]; +- if (setup_connection(&fd_in, &fd_out, "git-rpull", url, arg, argv + 1)) +- return 1; +- +- service(fd_in, fd_out); +- return 0; +-} +diff a/ssh-pull.c b/ssh-pull.c +--- /dev/null ++++ b/ssh-pull.c +@@ -0,0 +1,83 @@ ++#include "cache.h" ++#include "commit.h" ++#include "rsh.h" ++#include "pull.h" ++ ++static int fd_in; ++static int fd_out; ++ ++static unsigned char remote_version = 0; ++static unsigned char local_version = 1; ++ ++int fetch(unsigned char *sha1) ++{ ++ int ret; ++ signed char remote; ++ char type = 'o'; ++ if (has_sha1_file(sha1)) ++ return 0; ++ write(fd_out, &type, 1); ++ write(fd_out, sha1, 20); ++ if (read(fd_in, &remote, 1) < 1) ++ return -1; ++ if (remote < 0) ++ return remote; ++ ret = write_sha1_from_fd(sha1, fd_in); ++ if (!ret) ++ pull_say("got %s\n", sha1_to_hex(sha1)); ++ return ret; ++} ++ ++int get_version(void) ++{ ++ char type = 'v'; ++ write(fd_out, &type, 1); ++ write(fd_out, &local_version, 1); ++ if (read(fd_in, &remote_version, 1) < 1) { ++ return error("Couldn't read version from remote end"); ++ } ++ return 0; ++} ++ ++int main(int argc, char **argv) ++{ ++ char *commit_id; ++ char *url; ++ int arg = 1; ++ ++ while (arg < argc && argv[arg][0] == '-') { ++ if (argv[arg][1] == 't') { ++ get_tree = 1; ++ } else if (argv[arg][1] == 'c') { ++ get_history = 1; ++ } else if (argv[arg][1] == 'd') { ++ get_delta = 0; ++ } else if (!strcmp(argv[arg], "--recover")) { ++ get_delta = 2; ++ } else if (argv[arg][1] == 'a') { ++ get_all = 1; ++ get_tree = 1; ++ get_history = 1; ++ } else if (argv[arg][1] == 'v') { ++ get_verbosely = 1; ++ } ++ arg++; ++ } ++ if (argc < arg + 2) { ++ usage("git-ssh-pull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url"); ++ return 1; ++ } ++ commit_id = argv[arg]; ++ url = argv[arg + 1]; ++ ++ if (setup_connection(&fd_in, &fd_out, "git-ssh-push", url, arg, argv + 1)) ++ return 1; ++ ++ if (get_version()) ++ return 1; ++ ++ if (pull(commit_id)) ++ return 1; ++ ++ return 0; ++} +diff a/ssh-push.c b/ssh-push.c +--- /dev/null ++++ b/ssh-push.c +@@ -0,0 +1,104 @@ ++#include "cache.h" ++#include "rsh.h" ++#include <sys/socket.h> ++#include <errno.h> ++ ++unsigned char local_version = 1; ++unsigned char remote_version = 0; ++ ++int serve_object(int fd_in, int fd_out) { ++ ssize_t size; ++ int posn = 0; ++ char sha1[20]; ++ unsigned long objsize; ++ void *buf; ++ signed char remote; ++ do { ++ size = read(fd_in, sha1 + posn, 20 - posn); ++ if (size < 0) { ++ perror("git-ssh-push: read "); ++ return -1; ++ } ++ if (!size) ++ return -1; ++ posn += size; ++ } while (posn < 20); ++ ++ /* fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); */ ++ remote = 0; ++ ++ buf = map_sha1_file(sha1, &objsize); ++ ++ if (!buf) { ++ fprintf(stderr, "git-ssh-push: could not find %s\n", ++ sha1_to_hex(sha1)); ++ remote = -1; ++ } ++ ++ write(fd_out, &remote, 1); ++ ++ if (remote < 0) ++ return 0; ++ ++ posn = 0; ++ do { ++ size = write(fd_out, buf + posn, objsize - posn); ++ if (size <= 0) { ++ if (!size) { ++ fprintf(stderr, "git-ssh-push: write closed"); ++ } else { ++ perror("git-ssh-push: write "); ++ } ++ return -1; ++ } ++ posn += size; ++ } while (posn < objsize); ++ return 0; ++} ++ ++int serve_version(int fd_in, int fd_out) ++{ ++ if (read(fd_in, &remote_version, 1) < 1) ++ return -1; ++ write(fd_out, &local_version, 1); ++ return 0; ++} ++ ++void service(int fd_in, int fd_out) { ++ char type; ++ int retval; ++ do { ++ retval = read(fd_in, &type, 1); ++ if (retval < 1) { ++ if (retval < 0) ++ perror("git-ssh-push: read "); ++ return; ++ } ++ if (type == 'v' && serve_version(fd_in, fd_out)) ++ return; ++ if (type == 'o' && serve_object(fd_in, fd_out)) ++ return; ++ } while (1); ++} ++ ++int main(int argc, char **argv) ++{ ++ int arg = 1; ++ char *commit_id; ++ char *url; ++ int fd_in, fd_out; ++ while (arg < argc && argv[arg][0] == '-') { ++ arg++; ++ } ++ if (argc < arg + 2) { ++ usage("git-ssh-push [-c] [-t] [-a] commit-id url"); ++ return 1; ++ } ++ commit_id = argv[arg]; ++ url = argv[arg + 1]; ++ if (setup_connection(&fd_in, &fd_out, "git-ssh-pull", url, arg, argv + 1)) ++ return 1; ++ ++ service(fd_in, fd_out); ++ return 0; ++} diff --git a/t/t4100/t-apply-6.expect b/t/t4100/t-apply-6.expect new file mode 100644 index 0000000000..1c343d459e --- /dev/null +++ b/t/t4100/t-apply-6.expect @@ -0,0 +1,5 @@ + Makefile | 2 +- + git-fetch-script | 41 +++++++++++++++++++++++++++++++++++++++++ + git-pull-script | 34 +--------------------------------- + 3 files changed, 43 insertions(+), 34 deletions(-) + create git-fetch-script diff --git a/t/t4100/t-apply-6.patch b/t/t4100/t-apply-6.patch new file mode 100644 index 0000000000..d9753637fc --- /dev/null +++ b/t/t4100/t-apply-6.patch @@ -0,0 +1,101 @@ +diff a/Makefile b/Makefile +--- a/Makefile ++++ b/Makefile +@@ -20,7 +20,7 @@ INSTALL=install + + SCRIPTS=git-apply-patch-script git-merge-one-file-script git-prune-script \ + git-pull-script git-tag-script git-resolve-script git-whatchanged \ +- git-deltafy-script ++ git-deltafy-script git-fetch-script + + PROG= git-update-cache git-diff-files git-init-db git-write-tree \ + git-read-tree git-commit-tree git-cat-file git-fsck-cache \ +diff a/git-fetch-script b/git-fetch-script +--- /dev/null ++++ b/git-fetch-script +@@ -0,0 +1,41 @@ ++#!/bin/sh ++# ++merge_repo=$1 ++merge_name=${2:-HEAD} ++ ++: ${GIT_DIR=.git} ++: ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} ++ ++download_one () { ++ # remote_path="$1" local_file="$2" ++ case "$1" in ++ http://*) ++ wget -q -O "$2" "$1" ;; ++ /*) ++ test -f "$1" && cat >"$2" "$1" ;; ++ *) ++ rsync -L "$1" "$2" ;; ++ esac ++} ++ ++download_objects () { ++ # remote_repo="$1" head_sha1="$2" ++ case "$1" in ++ http://*) ++ git-http-pull -a "$2" "$1/" ++ ;; ++ /*) ++ git-local-pull -l -a "$2" "$1/" ++ ;; ++ *) ++ rsync -avz --ignore-existing \ ++ "$1/objects/." "$GIT_OBJECT_DIRECTORY"/. ++ ;; ++ esac ++} ++ ++echo "Getting remote $merge_name" ++download_one "$merge_repo/$merge_name" "$GIT_DIR"/MERGE_HEAD ++ ++echo "Getting object database" ++download_objects "$merge_repo" "$(cat "$GIT_DIR"/MERGE_HEAD)" +diff a/git-pull-script b/git-pull-script +--- a/git-pull-script ++++ b/git-pull-script +@@ -6,39 +6,7 @@ merge_name=${2:-HEAD} + : ${GIT_DIR=.git} + : ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} + +-download_one () { +- # remote_path="$1" local_file="$2" +- case "$1" in +- http://*) +- wget -q -O "$2" "$1" ;; +- /*) +- test -f "$1" && cat >"$2" "$1" ;; +- *) +- rsync -L "$1" "$2" ;; +- esac +-} +- +-download_objects () { +- # remote_repo="$1" head_sha1="$2" +- case "$1" in +- http://*) +- git-http-pull -a "$2" "$1/" +- ;; +- /*) +- git-local-pull -l -a "$2" "$1/" +- ;; +- *) +- rsync -avz --ignore-existing \ +- "$1/objects/." "$GIT_OBJECT_DIRECTORY"/. +- ;; +- esac +-} +- +-echo "Getting remote $merge_name" +-download_one "$merge_repo/$merge_name" "$GIT_DIR"/MERGE_HEAD +- +-echo "Getting object database" +-download_objects "$merge_repo" "$(cat "$GIT_DIR"/MERGE_HEAD)" ++git-fetch-script "$merge_repo" "$merge_name" + + git-resolve-script \ + "$(cat "$GIT_DIR"/HEAD)" \ diff --git a/t/t4100/t-apply-7.expect b/t/t4100/t-apply-7.expect new file mode 100644 index 0000000000..1283164d99 --- /dev/null +++ b/t/t4100/t-apply-7.expect @@ -0,0 +1,6 @@ + Documentation/git-ls-tree.txt | 20 +- + ls-tree.c | 333 +++++++++++++++++++++++------------------ + t/t3100-ls-tree-restrict.sh | 3 + tree.c | 2 + tree.h | 1 + 5 files changed, 199 insertions(+), 160 deletions(-) diff --git a/t/t4100/t-apply-7.patch b/t/t4100/t-apply-7.patch new file mode 100644 index 0000000000..07c6589e74 --- /dev/null +++ b/t/t4100/t-apply-7.patch @@ -0,0 +1,494 @@ +diff a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt +--- a/Documentation/git-ls-tree.txt ++++ b/Documentation/git-ls-tree.txt +@@ -4,23 +4,26 @@ v0.1, May 2005 + + NAME + ---- +-git-ls-tree - Displays a tree object in human readable form ++git-ls-tree - Lists the contents of a tree object. + + + SYNOPSIS + -------- +-'git-ls-tree' [-r] [-z] <tree-ish> [paths...] ++'git-ls-tree' [-d] [-r] [-z] <tree-ish> [paths...] + + DESCRIPTION + ----------- +-Converts the tree object to a human readable (and script processable) +-form. ++Lists the contents of a tree object, like what "/bin/ls -a" does ++in the current working directory. + + OPTIONS + ------- + <tree-ish>:: + Id of a tree. + ++-d:: ++ show only the named tree entry itself, not its children ++ + -r:: + recurse into sub-trees + +@@ -28,18 +31,19 @@ OPTIONS + \0 line termination on output + + paths:: +- Optionally, restrict the output of git-ls-tree to specific +- paths. Directories will only list their tree blob ids. +- Implies -r. ++ When paths are given, shows them. Otherwise implicitly ++ uses the root level of the tree as the sole path argument. ++ + + Output Format + ------------- +- <mode>\t <type>\t <object>\t <file> ++ <mode> SP <type> SP <object> TAB <file> + + + Author + ------ + Written by Linus Torvalds <torvalds@osdl.org> ++Completely rewritten from scratch by Junio C Hamano <junkio@cox.net> + + Documentation + -------------- +diff a/ls-tree.c b/ls-tree.c +--- a/ls-tree.c ++++ b/ls-tree.c +@@ -4,188 +4,217 @@ + * Copyright (C) Linus Torvalds, 2005 + */ + #include "cache.h" ++#include "blob.h" ++#include "tree.h" + + static int line_termination = '\n'; +-static int recursive = 0; ++#define LS_RECURSIVE 1 ++#define LS_TREE_ONLY 2 ++static int ls_options = 0; + +-struct path_prefix { +- struct path_prefix *prev; +- const char *name; +-}; +- +-#define DEBUG(fmt, ...) +- +-static int string_path_prefix(char *buff, size_t blen, struct path_prefix *prefix) +-{ +- int len = 0; +- if (prefix) { +- if (prefix->prev) { +- len = string_path_prefix(buff,blen,prefix->prev); +- buff += len; +- blen -= len; +- if (blen > 0) { +- *buff = '/'; +- len++; +- buff++; +- blen--; +- } +- } +- strncpy(buff,prefix->name,blen); +- return len + strlen(prefix->name); +- } ++static struct tree_entry_list root_entry; + +- return 0; ++static void prepare_root(unsigned char *sha1) ++{ ++ unsigned char rsha[20]; ++ unsigned long size; ++ void *buf; ++ struct tree *root_tree; ++ ++ buf = read_object_with_reference(sha1, "tree", &size, rsha); ++ free(buf); ++ if (!buf) ++ die("Could not read %s", sha1_to_hex(sha1)); ++ ++ root_tree = lookup_tree(rsha); ++ if (!root_tree) ++ die("Could not read %s", sha1_to_hex(sha1)); ++ ++ /* Prepare a fake entry */ ++ root_entry.directory = 1; ++ root_entry.executable = root_entry.symlink = 0; ++ root_entry.mode = S_IFDIR; ++ root_entry.name = ""; ++ root_entry.item.tree = root_tree; ++ root_entry.parent = NULL; + } + +-static void print_path_prefix(struct path_prefix *prefix) ++static int prepare_children(struct tree_entry_list *elem) + { +- if (prefix) { +- if (prefix->prev) { +- print_path_prefix(prefix->prev); +- putchar('/'); +- } +- fputs(prefix->name, stdout); ++ if (!elem->directory) ++ return -1; ++ if (!elem->item.tree->object.parsed) { ++ struct tree_entry_list *e; ++ if (parse_tree(elem->item.tree)) ++ return -1; ++ /* Set up the parent link */ ++ for (e = elem->item.tree->entries; e; e = e->next) ++ e->parent = elem; + } ++ return 0; + } + +-/* +- * return: +- * -1 if prefix is *not* a subset of path +- * 0 if prefix == path +- * 1 if prefix is a subset of path +- */ +-static int pathcmp(const char *path, struct path_prefix *prefix) +-{ +- char buff[PATH_MAX]; +- int len,slen; ++static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem, ++ const char *path, ++ const char *path_end) ++{ ++ const char *ep; ++ int len; ++ ++ while (path < path_end) { ++ if (prepare_children(elem)) ++ return NULL; + +- if (prefix == NULL) +- return 1; ++ /* In elem->tree->entries, find the one that has name ++ * that matches what is between path and ep. ++ */ ++ elem = elem->item.tree->entries; + +- len = string_path_prefix(buff, sizeof buff, prefix); +- slen = strlen(path); ++ ep = strchr(path, '/'); ++ if (!ep || path_end <= ep) ++ ep = path_end; ++ len = ep - path; ++ ++ while (elem) { ++ if ((strlen(elem->name) == len) && ++ !strncmp(elem->name, path, len)) ++ break; ++ elem = elem->next; ++ } ++ if (path_end <= ep || !elem) ++ return elem; ++ while (*ep == '/' && ep < path_end) ++ ep++; ++ path = ep; ++ } ++ return NULL; ++} + +- if (slen < len) +- return -1; ++static struct tree_entry_list *find_entry(const char *path, ++ const char *path_end) ++{ ++ /* Find tree element, descending from root, that ++ * corresponds to the named path, lazily expanding ++ * the tree if possible. ++ */ ++ if (path == path_end) { ++ /* Special. This is the root level */ ++ return &root_entry; ++ } ++ return find_entry_0(&root_entry, path, path_end); ++} + +- if (strncmp(path,buff,len) == 0) { +- if (slen == len) +- return 0; +- else +- return 1; ++static void show_entry_name(struct tree_entry_list *e) ++{ ++ /* This is yucky. The root level is there for ++ * our convenience but we really want to do a ++ * forest. ++ */ ++ if (e->parent && e->parent != &root_entry) { ++ show_entry_name(e->parent); ++ putchar('/'); + } ++ printf("%s", e->name); ++} + +- return -1; +-} ++static const char *entry_type(struct tree_entry_list *e) ++{ ++ return (e->directory ? "tree" : "blob"); ++} + +-/* +- * match may be NULL, or a *sorted* list of paths +- */ +-static void list_recursive(void *buffer, +- const char *type, +- unsigned long size, +- struct path_prefix *prefix, +- char **match, int matches) +-{ +- struct path_prefix this_prefix; +- this_prefix.prev = prefix; +- +- if (strcmp(type, "tree")) +- die("expected a 'tree' node"); +- +- if (matches) +- recursive = 1; +- +- while (size) { +- int namelen = strlen(buffer)+1; +- void *eltbuf = NULL; +- char elttype[20]; +- unsigned long eltsize; +- unsigned char *sha1 = buffer + namelen; +- char *path = strchr(buffer, ' ') + 1; +- unsigned int mode; +- const char *matched = NULL; +- int mtype = -1; +- int mindex; +- +- if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1) +- die("corrupt 'tree' file"); +- buffer = sha1 + 20; +- size -= namelen + 20; +- +- this_prefix.name = path; +- for ( mindex = 0; mindex < matches; mindex++) { +- mtype = pathcmp(match[mindex],&this_prefix); +- if (mtype >= 0) { +- matched = match[mindex]; +- break; +- } +- } ++static const char *entry_hex(struct tree_entry_list *e) ++{ ++ return sha1_to_hex(e->directory ++ ? e->item.tree->object.sha1 ++ : e->item.blob->object.sha1); ++} + +- /* +- * If we're not matching, or if this is an exact match, +- * print out the info +- */ +- if (!matches || (matched != NULL && mtype == 0)) { +- printf("%06o %s %s\t", mode, +- S_ISDIR(mode) ? "tree" : "blob", +- sha1_to_hex(sha1)); +- print_path_prefix(&this_prefix); +- putchar(line_termination); +- } ++/* forward declaration for mutually recursive routines */ ++static int show_entry(struct tree_entry_list *, int); + +- if (! recursive || ! S_ISDIR(mode)) +- continue; ++static int show_children(struct tree_entry_list *e, int level) ++{ ++ if (prepare_children(e)) ++ die("internal error: ls-tree show_children called with non tree"); ++ e = e->item.tree->entries; ++ while (e) { ++ show_entry(e, level); ++ e = e->next; ++ } ++ return 0; ++} + +- if (matches && ! matched) +- continue; ++static int show_entry(struct tree_entry_list *e, int level) ++{ ++ int err = 0; + +- if (! (eltbuf = read_sha1_file(sha1, elttype, &eltsize)) ) { +- error("cannot read %s", sha1_to_hex(sha1)); +- continue; +- } ++ if (e != &root_entry) { ++ printf("%06o %s %s ", e->mode, entry_type(e), ++ entry_hex(e)); ++ show_entry_name(e); ++ putchar(line_termination); ++ } + +- /* If this is an exact directory match, we may have +- * directory files following this path. Match on them. +- * Otherwise, we're at a pach subcomponent, and we need +- * to try to match again. ++ if (e->directory) { ++ /* If this is a directory, we have the following cases: ++ * (1) This is the top-level request (explicit path from the ++ * command line, or "root" if there is no command line). ++ * a. Without any flag. We show direct children. We do not ++ * recurse into them. ++ * b. With -r. We do recurse into children. ++ * c. With -d. We do not recurse into children. ++ * (2) We came here because our caller is either (1-a) or ++ * (1-b). ++ * a. Without any flag. We do not show our children (which ++ * are grandchildren for the original request). ++ * b. With -r. We continue to recurse into our children. ++ * c. With -d. We should not have come here to begin with. + */ +- if (mtype == 0) +- mindex++; +- +- list_recursive(eltbuf, elttype, eltsize, &this_prefix, &match[mindex], matches-mindex); +- free(eltbuf); ++ if (level == 0 && !(ls_options & LS_TREE_ONLY)) ++ /* case (1)-a and (1)-b */ ++ err = err | show_children(e, level+1); ++ else if (level && ls_options & LS_RECURSIVE) ++ /* case (2)-b */ ++ err = err | show_children(e, level+1); + } ++ return err; + } + +-static int qcmp(const void *a, const void *b) ++static int list_one(const char *path, const char *path_end) + { +- return strcmp(*(char **)a, *(char **)b); ++ int err = 0; ++ struct tree_entry_list *e = find_entry(path, path_end); ++ if (!e) { ++ /* traditionally ls-tree does not complain about ++ * missing path. We may change this later to match ++ * what "/bin/ls -a" does, which is to complain. ++ */ ++ return err; ++ } ++ err = err | show_entry(e, 0); ++ return err; + } + +-static int list(unsigned char *sha1,char **path) ++static int list(char **path) + { +- void *buffer; +- unsigned long size; +- int npaths; +- +- for (npaths = 0; path[npaths] != NULL; npaths++) +- ; +- +- qsort(path,npaths,sizeof(char *),qcmp); +- +- buffer = read_object_with_reference(sha1, "tree", &size, NULL); +- if (!buffer) +- die("unable to read sha1 file"); +- list_recursive(buffer, "tree", size, NULL, path, npaths); +- free(buffer); +- return 0; ++ int i; ++ int err = 0; ++ for (i = 0; path[i]; i++) { ++ int len = strlen(path[i]); ++ while (0 <= len && path[i][len] == '/') ++ len--; ++ err = err | list_one(path[i], path[i] + len); ++ } ++ return err; + } + +-static const char *ls_tree_usage = "git-ls-tree [-r] [-z] <key> [paths...]"; ++static const char *ls_tree_usage = ++ "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"; + + int main(int argc, char **argv) + { ++ static char *path0[] = { "", NULL }; ++ char **path; + unsigned char sha1[20]; + + while (1 < argc && argv[1][0] == '-') { +@@ -194,7 +223,10 @@ int main(int argc, char **argv) + line_termination = 0; + break; + case 'r': +- recursive = 1; ++ ls_options |= LS_RECURSIVE; ++ break; ++ case 'd': ++ ls_options |= LS_TREE_ONLY; + break; + default: + usage(ls_tree_usage); +@@ -206,7 +238,10 @@ int main(int argc, char **argv) + usage(ls_tree_usage); + if (get_sha1(argv[1], sha1) < 0) + usage(ls_tree_usage); +- if (list(sha1, &argv[2]) < 0) ++ ++ path = (argc == 2) ? path0 : (argv + 2); ++ prepare_root(sha1); ++ if (list(path) < 0) + die("list failed"); + return 0; + } +diff a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh +--- a/t/t3100-ls-tree-restrict.sh ++++ b/t/t3100-ls-tree-restrict.sh +@@ -74,8 +74,8 @@ test_expect_success \ + 'ls-tree filtered' \ + 'git-ls-tree $tree path1 path0 >current && + cat >expected <<\EOF && +-100644 blob X path0 + 120000 blob X path1 ++100644 blob X path0 + EOF + test_output' + +@@ -85,7 +85,6 @@ test_expect_success \ + cat >expected <<\EOF && + 040000 tree X path2 + 040000 tree X path2/baz +-100644 blob X path2/baz/b + 120000 blob X path2/bazbo + 100644 blob X path2/foo + EOF +diff a/tree.c b/tree.c +--- a/tree.c ++++ b/tree.c +@@ -133,7 +133,7 @@ int parse_tree_buffer(struct tree *item, + } + if (obj) + add_ref(&item->object, obj); +- ++ entry->parent = NULL; /* needs to be filled by the user */ + *list_p = entry; + list_p = &entry->next; + } +diff a/tree.h b/tree.h +--- a/tree.h ++++ b/tree.h +@@ -16,6 +16,7 @@ struct tree_entry_list { + struct tree *tree; + struct blob *blob; + } item; ++ struct tree_entry_list *parent; + }; + + struct tree { diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh new file mode 100755 index 0000000000..380ef15a27 --- /dev/null +++ b/t/t4101-apply-nonl.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-apply should handle files with incomplete lines. + +' +. ./test-lib.sh + +# setup + +(echo a; echo b) >frotz.0 +(echo a; echo b; echo c) >frotz.1 +(echo a; echo b | tr -d '\012') >frotz.2 +(echo a; echo c; echo b | tr -d '\012') >frotz.3 + +for i in 0 1 2 3 +do + for j in 0 1 2 3 + do + test $i -eq $j && continue + diff -u frotz.$i frotz.$j | + sed -e ' + /^---/s|.*|--- a/frotz| + /^+++/s|.*|+++ b/frotz|' >diff.$i-$j + cat frotz.$i >frotz + test_expect_success \ + "apply diff between $i and $j" \ + "git-apply <diff.$i-$j && diff frotz.$j frotz" + done +done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh new file mode 100755 index 0000000000..6d72ed34c1 --- /dev/null +++ b/t/t5000-tar-tree.sh @@ -0,0 +1,94 @@ +#!/bin/sh +# +# Copyright (C) 2005 Rene Scharfe +# + +test_description='git-tar-tree and git-get-tar-commit-id test + +This test covers the topics of file contents, commit date handling and +commit id embedding: + + The contents of the repository is compared to the extracted tar + archive. The repository contains simple text files, symlinks and a + binary file (/bin/sh). Only pathes shorter than 99 characters are + used. + + git-tar-tree applies the commit date to every file in the archive it + creates. The test sets the commit date to a specific value and checks + if the tar archive contains that value. + + When giving git-tar-tree a commit id (in contrast to a tree id) it + embeds this commit id into the tar archive as a comment. The test + checks the ability of git-get-tar-commit-id to figure it out from the + tar file. + +' + +. ./test-lib.sh + +test_expect_success \ + 'populate workdir' \ + 'mkdir a b c && + echo simple textfile >a/a && + mkdir a/bin && + cp /bin/sh a/bin && + ln -s a a/l1 && + (cd a && find .) | sort >a.lst' + +test_expect_success \ + 'add files to repository' \ + 'find a -type f | xargs git-update-cache --add && + find a -type l | xargs git-update-cache --add && + treeid=`git-write-tree` && + echo $treeid >treeid && + TZ= GIT_COMMITTER_DATE="2005-05-27 22:00:00" \ + git-commit-tree $treeid </dev/null >.git/HEAD' + +test_expect_success \ + 'git-tar-tree' \ + 'git-tar-tree HEAD >b.tar' + +test_expect_success \ + 'validate file modification time' \ + 'TZ= tar tvf b.tar a/a | + awk \{print\ \$4,\ \(length\(\$5\)\<7\)\ ?\ \$5\":00\"\ :\ \$5\} \ + >b.mtime && + echo "2005-05-27 22:00:00" >expected.mtime && + diff expected.mtime b.mtime' + +test_expect_success \ + 'git-get-tar-commit-id' \ + 'git-get-tar-commit-id <b.tar >b.commitid && + diff .git/HEAD b.commitid' + +test_expect_success \ + 'extract tar archive' \ + '(cd b && tar xf -) <b.tar' + +test_expect_success \ + 'validate filenames' \ + '(cd b/a && find .) | sort >b.lst && + diff a.lst b.lst' + +test_expect_success \ + 'validate file contents' \ + 'diff -r a b/a' + +test_expect_success \ + 'git-tar-tree with prefix' \ + 'git-tar-tree HEAD prefix >c.tar' + +test_expect_success \ + 'extract tar archive with prefix' \ + '(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_expect_success \ + 'validate file contents with prefix' \ + 'diff -r a c/prefix/a' + +test_done diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh new file mode 100755 index 0000000000..b0b9329573 --- /dev/null +++ b/t/t5300-pack-object.sh @@ -0,0 +1,168 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git-pack-object + +' +. ./test-lib.sh + +TRASH=`pwd` + +test_expect_success \ + 'setup' \ + 'rm -f .git/index* + for i in a b c + do + dd if=/dev/zero bs=4k count=1 | tr "\\0" $i >$i && + git-update-cache --add $i || exit + done && + cat c >d && echo foo >>d && git-update-cache --add d && + tree=`git-write-tree` && + commit=`git-commit-tree $tree </dev/null` && { + echo $tree && + echo $commit && + git-ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" + } >obj-list && { + git-diff-tree --root -p $commit && + while read object + do + t=`git-cat-file -t $object` && + git-cat-file $t $object || exit 1 + done <obj-list + } >expect' + +test_expect_success \ + 'pack without delta' \ + 'packname_1=$(git-pack-objects --window=0 test-1 <obj-list)' + +rm -fr .git2 +mkdir .git2 + +test_expect_success \ + 'unpack without delta' \ + "GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + git-init-db && + git-unpack-objects -n <test-1-${packname_1}.pack && + git-unpack-objects <test-1-${packname_1}.pack" + +unset GIT_OBJECT_DIRECTORY +cd $TRASH/.git2 + +test_expect_success \ + 'check unpack without delta' \ + '(cd ../.git && find objects -type f -print) | + while read path + do + cmp $path ../.git/$path || { + echo $path differs. + exit 1 + } + done' +cd $TRASH + +test_expect_success \ + 'pack with delta' \ + 'pwd && + packname_2=$(git-pack-objects test-2 <obj-list)' + +rm -fr .git2 +mkdir .git2 + +test_expect_success \ + 'unpack with delta' \ + 'GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + git-init-db && + git-unpack-objects -n <test-2-${packname_2}.pack && + git-unpack-objects <test-2-${packname_2}.pack' + +unset GIT_OBJECT_DIRECTORY +cd $TRASH/.git2 +test_expect_success \ + 'check unpack with delta' \ + '(cd ../.git && find objects -type f -print) | + while read path + do + cmp $path ../.git/$path || { + echo $path differs. + exit 1 + } + done' +cd $TRASH + +rm -fr .git2 +mkdir .git2 + +test_expect_success \ + 'use packed objects' \ + 'GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + git-init-db && + cp test-1-${packname_1}.pack test-1-${packname_1}.idx .git2/objects/pack && { + git-diff-tree --root -p $commit && + while read object + do + t=`git-cat-file -t $object` && + git-cat-file $t $object || exit 1 + done <obj-list + } >current && + diff expect current' + + +test_expect_success \ + 'use packed deltified objects' \ + 'GIT_OBJECT_DIRECTORY=.git2/objects && + export GIT_OBJECT_DIRECTORY && + rm -f .git2/objects/pack/test-?.idx && + cp test-2-${packname_2}.pack test-2-${packname_2}.idx .git2/objects/pack && { + git-diff-tree --root -p $commit && + while read object + do + t=`git-cat-file -t $object` && + git-cat-file $t $object || exit 1 + done <obj-list + } >current && + diff expect current' + +unset GIT_OBJECT_DIRECTORY + +test_expect_success \ + 'verify pack' \ + 'git-verify-pack test-1-${packname_1}.idx test-2-${packname_2}.idx' + +test_expect_success \ + 'corrupt a pack and see if verify catches' \ + 'cp test-1-${packname_1}.idx test-3.idx && + cp test-2-${packname_2}.pack test-3.pack && + if git-verify-pack test-3.idx + then false + else :; + fi && + + cp test-1-${packname_1}.pack test-3.pack && + dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && + if git-verify-pack test-3.idx + then false + else :; + fi && + + cp test-1-${packname_1}.pack test-3.pack && + dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && + if git-verify-pack test-3.idx + then false + else :; + fi && + + cp test-1-${packname_1}.pack test-3.pack && + dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && + if git-verify-pack test-3.idx + then false + else :; + fi && + + :' + +test_done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh new file mode 100755 index 0000000000..19a8f122c7 --- /dev/null +++ b/t/t5400-send-pack.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='See why rewinding head breaks send-pack + +' +. ./test-lib.sh + +cnt='1' +test_expect_success setup ' + tree=$(git-write-tree) && + commit=$(echo "Commit #0" | git-commit-tree $tree) && + zero=$commit && + parent=$zero && + for i in $cnt + do + sleep 1 && + commit=$(echo "Commit #$i" | git-commit-tree $tree -p $parent) && + parent=$commit || exit + done && + echo "$commit" >.git/HEAD && + git clone -l ./. victim && + cd victim && + git log && + cd .. && + echo $zero >.git/HEAD && + parent=$zero && + for i in $cnt + do + sleep 1 && + commit=$(echo "Rebase #$i" | git-commit-tree $tree -p $parent) && + parent=$commit || exit + done && + echo "$commit" >.git/HEAD && + echo Rebase && + git log' + +test_expect_success \ + 'pushing rewound head should not barf but require --force' ' + # should not fail but refuse to update. + git-send-pack ./victim/.git/ master && + if cmp victim/.git/refs/heads/master .git/refs/heads/master + then + # should have been left as it was! + false + else + true + fi && + # this should update + git-send-pack --force ./victim/.git/ master && + cmp victim/.git/refs/heads/master .git/refs/heads/master +' diff --git a/t/t6000lib.sh b/t/t6000lib.sh new file mode 100755 index 0000000000..01f796e9c8 --- /dev/null +++ b/t/t6000lib.sh @@ -0,0 +1,109 @@ +[ -d .git/refs/tags ] || mkdir -p .git/refs/tags + +:> sed.script + +# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags +tag() +{ + _tag=$1 + [ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist" + cat .git/refs/tags/$_tag +} + +# Generate a commit using the text specified to make it unique and the tree +# named by the tag specified. +unique_commit() +{ + _text=$1 + _tree=$2 + shift 2 + echo $_text | git-commit-tree $(tag $_tree) "$@" +} + +# Save the output of a command into the tag specified. Prepend +# a substitution script for the tag onto the front of sed.script +save_tag() +{ + _tag=$1 + [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..." + shift 1 + "$@" >.git/refs/tags/$_tag + + echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp + cat sed.script >> sed.script.tmp + rm sed.script + mv sed.script.tmp sed.script +} + +# Replace unhelpful sha1 hashses with their symbolic equivalents +entag() +{ + sed -f sed.script +} + +# Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL +# tag to a specified value. Restore the original value on return. +as_author() +{ + _author=$1 + shift 1 + _save=$GIT_AUTHOR_EMAIL + + export GIT_AUTHOR_EMAIL="$_author" + "$@" + export GIT_AUTHOR_EMAIL="$_save" +} + +commit_date() +{ + _commit=$1 + git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" +} + +on_committer_date() +{ + _date=$1 + shift 1 + GIT_COMMITTER_DATE=$_date "$@" +} + +# Execute a command and suppress any error output. +hide_error() +{ + "$@" 2>/dev/null +} + +check_output() +{ + _name=$1 + shift 1 + if eval "$*" | entag > $_name.actual + then + diff $_name.expected $_name.actual + else + return 1; + fi +} + +# Turn a reasonable test description into a reasonable test name. +# All alphanums translated into -'s which are then compressed and stripped +# from front and back. +name_from_description() +{ + tr "'" '-' | tr '~`!@#$%^&*()_+={}[]|\;:"<>,/? ' '-' | tr -s '-' | tr '[A-Z]' '[a-z]' | sed "s/^-*//;s/-*\$//" +} + + +# Execute the test described by the first argument, by eval'ing +# command line specified in the 2nd argument. Check the status code +# is zero and that the output matches the stream read from +# stdin. +test_output_expect_success() +{ + _description=$1 + _test=$2 + [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF" + _name=$(echo $_description | name_from_description) + cat > $_name.expected + test_expect_success "$_description" "check_output $_name \"$_test\"" +} diff --git a/t/t6001-rev-list-merge-order.sh b/t/t6001-rev-list-merge-order.sh new file mode 100755 index 0000000000..7fe744e834 --- /dev/null +++ b/t/t6001-rev-list-merge-order.sh @@ -0,0 +1,462 @@ +#!/bin/sh +# +# Copyright (c) 2005 Jon Seymour +# + +test_description='Tests git-rev-list --merge-order functionality' + +. ./test-lib.sh +. ../t6000lib.sh # t6xxx specific functions + +if git-rev-list --merge-order 2>&1 | grep 'OpenSSL not linked' >/dev/null +then + test_expect_success 'skipping merge-order test' : + test_done + exit +fi + +# test-case specific test function +check_adjacency() +{ + read previous + echo "= $previous" + while read next + do + if ! (git-cat-file commit $previous | grep "^parent $next" >/dev/null) + then + echo "^ $next" + else + echo "| $next" + fi + previous=$next + done +} + +list_duplicates() +{ + "$@" | sort | uniq -d +} + +grep_stderr() +{ + args=$1 + shift 1 + "$@" 2>&1 | grep "$args" +} + +date >path0 +git-update-cache --add path0 +save_tag tree git-write-tree +on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree +on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root +on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0 +on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1 +on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2 +on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0 +on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0 +on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1 +on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1 +on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2 +on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2 +on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2 +on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1 +on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2 +on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3 +on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3 +on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4 +on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3 +on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4 +on_committer_date "1971-08-16 00:00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3 +on_committer_date "1971-08-16 00:00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4 +on_committer_date "1971-08-16 00:00:21" hide_error save_tag alt_root unique_commit alt_root tree +on_committer_date "1971-08-16 00:00:22" save_tag r0 unique_commit r0 tree -p alt_root +on_committer_date "1971-08-16 00:00:23" save_tag r1 unique_commit r1 tree -p r0 +on_committer_date "1971-08-16 00:00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1 +on_committer_date "1971-08-16 00:00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5 + + +# +# note: as of 20/6, it isn't possible to create duplicate parents, so this +# can't be tested. +# +#on_committer_date "1971-08-16 00:00:20" save_tag m3 unique_commit m3 tree -p c3 -p a4 -p c3 +hide_error save_tag e1 as_author e@example.com unique_commit e1 tree +save_tag e2 as_author e@example.com unique_commit e2 tree -p e1 +save_tag f1 as_author f@example.com unique_commit f1 tree -p e1 +save_tag e3 as_author e@example.com unique_commit e3 tree -p e2 +save_tag f2 as_author f@example.com unique_commit f2 tree -p f1 +save_tag e4 as_author e@example.com unique_commit e4 tree -p e3 -p f2 +save_tag e5 as_author e@example.com unique_commit e5 tree -p e4 +save_tag f3 as_author f@example.com unique_commit f3 tree -p f2 +save_tag f4 as_author f@example.com unique_commit f4 tree -p f3 +save_tag e6 as_author e@example.com unique_commit e6 tree -p e5 -p f4 +save_tag f5 as_author f@example.com unique_commit f5 tree -p f4 +save_tag f6 as_author f@example.com unique_commit f6 tree -p f5 -p e6 +save_tag e7 as_author e@example.com unique_commit e7 tree -p e6 +save_tag e8 as_author e@example.com unique_commit e8 tree -p e7 +save_tag e9 as_author e@example.com unique_commit e9 tree -p e8 +save_tag f7 as_author f@example.com unique_commit f7 tree -p f6 +save_tag f8 as_author f@example.com unique_commit f8 tree -p f7 +save_tag f9 as_author f@example.com unique_commit f9 tree -p f8 +save_tag e10 as_author e@example.com unique_commit e1 tree -p e9 -p f8 + +hide_error save_tag g0 unique_commit g0 tree +save_tag g1 unique_commit g1 tree -p g0 +save_tag h1 unique_commit g2 tree -p g0 +save_tag g2 unique_commit g3 tree -p g1 -p h1 +save_tag h2 unique_commit g4 tree -p g2 +save_tag g3 unique_commit g5 tree -p g2 +save_tag g4 unique_commit g6 tree -p g3 -p h2 + +tag l5 > .git/HEAD + +test_expect_success 'rev-list has correct number of entries' 'git-rev-list HEAD | wc -l | tr -s " "' <<EOF +19 +EOF + +normal_adjacency_count=$(git-rev-list HEAD | check_adjacency | grep -c "\^" | tr -d ' ') +merge_order_adjacency_count=$(git-rev-list --merge-order HEAD | check_adjacency | grep -c "\^" | tr -d ' ') +test_expect_success '--merge-order produces as many or fewer discontinuities' '[ $merge_order_adjacency_count -le $normal_adjacency_count ]' +test_output_expect_success 'simple merge order' 'git-rev-list --merge-order --show-breaks HEAD' <<EOF += l5 +| l4 +| l3 += a4 +| c3 +| c2 +| c1 +^ b4 +| b3 +| b2 +| b1 +^ a3 +| a2 +| a1 += a0 +| l2 +| l1 +| l0 += root +EOF + +test_output_expect_success 'two diamonds merge order (g6)' 'git-rev-list --merge-order --show-breaks g4' <<EOF += g4 +| h2 +^ g3 += g2 +| h1 +^ g1 += g0 +EOF + +test_output_expect_success 'multiple heads' 'git-rev-list --merge-order a3 b3 c3' <<EOF +c3 +c2 +c1 +b3 +b2 +b1 +a3 +a2 +a1 +a0 +l2 +l1 +l0 +root +EOF + +test_output_expect_success 'multiple heads, prune at a1' 'git-rev-list --merge-order a3 b3 c3 ^a1' <<EOF +c3 +c2 +c1 +b3 +b2 +b1 +a3 +a2 +EOF + +test_output_expect_success 'multiple heads, prune at l1' 'git-rev-list --merge-order a3 b3 c3 ^l1' <<EOF +c3 +c2 +c1 +b3 +b2 +b1 +a3 +a2 +a1 +a0 +l2 +EOF + +test_output_expect_success 'cross-epoch, head at l5, prune at l1' 'git-rev-list --merge-order l5 ^l1' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +b3 +b2 +b1 +a3 +a2 +a1 +a0 +l2 +EOF + +test_output_expect_success 'duplicated head arguments' 'git-rev-list --merge-order l5 l5 ^l1' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +b3 +b2 +b1 +a3 +a2 +a1 +a0 +l2 +EOF + +test_output_expect_success 'prune near merge' 'git-rev-list --merge-order a4 ^c3' <<EOF +a4 +b4 +b3 +a3 +a2 +a1 +EOF + +test_output_expect_success "head has no parent" 'git-rev-list --merge-order --show-breaks root' <<EOF += root +EOF + +test_output_expect_success "two nodes - one head, one base" 'git-rev-list --merge-order --show-breaks l0' <<EOF += l0 += root +EOF + +test_output_expect_success "three nodes one head, one internal, one base" 'git-rev-list --merge-order --show-breaks l1' <<EOF += l1 +| l0 += root +EOF + +test_output_expect_success "linear prune l2 ^root" 'git-rev-list --merge-order --show-breaks l2 ^root' <<EOF +^ l2 +| l1 +| l0 +EOF + +test_output_expect_success "linear prune l2 ^l0" 'git-rev-list --merge-order --show-breaks l2 ^l0' <<EOF +^ l2 +| l1 +EOF + +test_output_expect_success "linear prune l2 ^l1" 'git-rev-list --merge-order --show-breaks l2 ^l1' <<EOF +^ l2 +EOF + +test_output_expect_success "linear prune l5 ^a4" 'git-rev-list --merge-order --show-breaks l5 ^a4' <<EOF +^ l5 +| l4 +| l3 +EOF + +test_output_expect_success "linear prune l5 ^l3" 'git-rev-list --merge-order --show-breaks l5 ^l3' <<EOF +^ l5 +| l4 +EOF + +test_output_expect_success "linear prune l5 ^l4" 'git-rev-list --merge-order --show-breaks l5 ^l4' <<EOF +^ l5 +EOF + +test_output_expect_success "max-count 10 - merge order" 'git-rev-list --merge-order --show-breaks --max-count=10 l5' <<EOF += l5 +| l4 +| l3 += a4 +| c3 +| c2 +| c1 +^ b4 +| b3 +| b2 +EOF + +test_output_expect_success "max-count 10 - non merge order" 'git-rev-list --max-count=10 l5' <<EOF +l5 +l4 +l3 +a4 +b4 +a3 +a2 +c3 +c2 +b3 +EOF + +test_output_expect_success '--max-age=c3, no --merge-order' "git-rev-list --max-age=$(commit_date c3) l5" <<EOF +l5 +l4 +l3 +a4 +b4 +a3 +a2 +c3 +EOF + +test_output_expect_success '--max-age=c3, --merge-order' "git-rev-list --merge-order --max-age=$(commit_date c3) l5" <<EOF +l5 +l4 +l3 +a4 +c3 +b4 +a3 +a2 +EOF + +test_output_expect_success 'one specified head reachable from another a4, c3, --merge-order' "list_duplicates git-rev-list --merge-order a4 c3" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another c3, a4, --merge-order' "list_duplicates git-rev-list --merge-order c3 a4" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another a4, c3, no --merge-order' "list_duplicates git-rev-list a4 c3" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another c3, a4, no --merge-order' "list_duplicates git-rev-list c3 a4" <<EOF +EOF + +test_output_expect_success 'graph with c3 and a4 parents of head' "list_duplicates git-rev-list m1" <<EOF +EOF + +test_output_expect_success 'graph with a4 and c3 parents of head' "list_duplicates git-rev-list m2" <<EOF +EOF + +test_expect_success "head ^head --merge-order" 'git-rev-list --merge-order --show-breaks a3 ^a3' <<EOF +EOF + +# +# can't test this now - duplicate parents can't be created +# +#test_output_expect_success 'duplicate parents' 'git-rev-list --parents --merge-order --show-breaks m3' <<EOF +#= m3 c3 a4 c3 +#| a4 c3 b4 a3 +#| b4 a3 b3 +#| b3 b2 +#^ a3 a2 +#| a2 a1 +#| a1 a0 +#^ c3 c2 +#| c2 b2 c1 +#| b2 b1 +#^ c1 b1 +#| b1 a0 +#= a0 l2 +#| l2 l1 +#| l1 l0 +#| l0 root +#= root +#EOF + +test_expect_success "head ^head no --merge-order" 'git-rev-list a3 ^a3' <<EOF +EOF + +test_output_expect_success 'simple merge order (l5r1)' 'git-rev-list --merge-order --show-breaks l5r1' <<EOF += l5r1 +| r1 +| r0 +| alt_root +^ l5 +| l4 +| l3 +| a4 +| c3 +| c2 +| c1 +^ b4 +| b3 +| b2 +| b1 +^ a3 +| a2 +| a1 +| a0 +| l2 +| l1 +| l0 += root +EOF + +test_output_expect_success 'simple merge order (r1l5)' 'git-rev-list --merge-order --show-breaks r1l5' <<EOF += r1l5 +| l5 +| l4 +| l3 +| a4 +| c3 +| c2 +| c1 +^ b4 +| b3 +| b2 +| b1 +^ a3 +| a2 +| a1 +| a0 +| l2 +| l1 +| l0 +| root +^ r1 +| r0 += alt_root +EOF + +test_output_expect_success "don't print things unreachable from one branch" "git-rev-list a3 ^b3 --merge-order" <<EOF +a3 +a2 +a1 +EOF + +test_output_expect_success "--merge-order a4 l3" "git-rev-list --merge-order a4 l3" <<EOF +l3 +a4 +c3 +c2 +c1 +b4 +b3 +b2 +b1 +a3 +a2 +a1 +a0 +l2 +l1 +l0 +root +EOF + +# +# + +test_done diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh new file mode 100755 index 0000000000..99d86ae5ae --- /dev/null +++ b/t/t6002-rev-list-bisect.sh @@ -0,0 +1,241 @@ +#!/bin/sh +# +# Copyright (c) 2005 Jon Seymour +# +test_description='Tests git-rev-list --bisect functionality' + +. ./test-lib.sh +. ../t6000lib.sh # t6xxx specific functions + +bc_expr() +{ +bc <<EOF +scale=1 +define abs(x) { + if (x>=0) { return (x); } else { return (-x); } +} +define floor(x) { + save=scale; scale=0; result=x/1; scale=save; return (result); +} +$* +EOF +} + +# usage: test_bisection max-diff bisect-option head ^prune... +# +# e.g. test_bisection 1 --bisect l1 ^l0 +# +test_bisection_diff() +{ + _max_diff=$1 + _bisect_option=$2 + shift 2 + _bisection=$(git-rev-list $_bisect_option "$@") + _list_size=$(git-rev-list "$@" | wc -l) + _head=$1 + shift 1 + _bisection_size=$(git-rev-list $_bisection "$@" | wc -l) + [ -n "$_list_size" -a -n "$_bisection_size" ] || error "test_bisection_diff failed" + test_expect_success "bisection diff $_bisect_option $_head $* <= $_max_diff" "[ $(bc_expr "floor(abs($_list_size/2)-$_bisection_size)") -le $_max_diff ]" +} + +date >path0 +git-update-cache --add path0 +save_tag tree git-write-tree +on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree +on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root +on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0 +on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1 +on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2 +on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0 +on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0 +on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1 +on_committer_date "1971-08-16 00:00:08" save_tag b2 unique_commit b2 tree -p b1 +on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2 +on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2 +on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2 +on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1 +on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2 +on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3 +on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3 +on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4 +on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3 +on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4 +tag l5 > .git/HEAD + + +# E +# / \ +# e1 | +# | | +# e2 | +# | | +# e3 | +# | | +# e4 | +# | | +# | f1 +# | | +# | f2 +# | | +# | f3 +# | | +# | f4 +# | | +# e5 | +# | | +# e6 | +# | | +# e7 | +# | | +# e8 | +# \ / +# F + + +on_committer_date "1971-08-16 00:00:00" hide_error save_tag F unique_commit F tree +on_committer_date "1971-08-16 00:00:01" save_tag e8 unique_commit e8 tree -p F +on_committer_date "1971-08-16 00:00:02" save_tag e7 unique_commit e7 tree -p e8 +on_committer_date "1971-08-16 00:00:03" save_tag e6 unique_commit e6 tree -p e7 +on_committer_date "1971-08-16 00:00:04" save_tag e5 unique_commit e5 tree -p e6 +on_committer_date "1971-08-16 00:00:05" save_tag f4 unique_commit f4 tree -p F +on_committer_date "1971-08-16 00:00:06" save_tag f3 unique_commit f3 tree -p f4 +on_committer_date "1971-08-16 00:00:07" save_tag f2 unique_commit f2 tree -p f3 +on_committer_date "1971-08-16 00:00:08" save_tag f1 unique_commit f1 tree -p f2 +on_committer_date "1971-08-16 00:00:09" save_tag e4 unique_commit e4 tree -p e5 +on_committer_date "1971-08-16 00:00:10" save_tag e3 unique_commit e3 tree -p e4 +on_committer_date "1971-08-16 00:00:11" save_tag e2 unique_commit e2 tree -p e3 +on_committer_date "1971-08-16 00:00:12" save_tag e1 unique_commit e1 tree -p e2 +on_committer_date "1971-08-16 00:00:13" save_tag E unique_commit E tree -p e1 -p f1 + +on_committer_date "1971-08-16 00:00:00" hide_error save_tag U unique_commit U tree +on_committer_date "1971-08-16 00:00:01" save_tag u0 unique_commit u0 tree -p U +on_committer_date "1971-08-16 00:00:01" save_tag u1 unique_commit u1 tree -p u0 +on_committer_date "1971-08-16 00:00:02" save_tag u2 unique_commit u2 tree -p u0 +on_committer_date "1971-08-16 00:00:03" save_tag u3 unique_commit u3 tree -p u0 +on_committer_date "1971-08-16 00:00:04" save_tag u4 unique_commit u4 tree -p u0 +on_committer_date "1971-08-16 00:00:05" save_tag u5 unique_commit u5 tree -p u0 +on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5 + +test_sequence() +{ + _bisect_option=$1 + + test_bisection_diff 0 $_bisect_option l0 ^root + test_bisection_diff 0 $_bisect_option l1 ^root + test_bisection_diff 0 $_bisect_option l2 ^root + test_bisection_diff 0 $_bisect_option a0 ^root + test_bisection_diff 0 $_bisect_option a1 ^root + test_bisection_diff 0 $_bisect_option a2 ^root + test_bisection_diff 0 $_bisect_option a3 ^root + test_bisection_diff 0 $_bisect_option b1 ^root + test_bisection_diff 0 $_bisect_option b2 ^root + test_bisection_diff 0 $_bisect_option b3 ^root + test_bisection_diff 0 $_bisect_option c1 ^root + test_bisection_diff 0 $_bisect_option c2 ^root + test_bisection_diff 0 $_bisect_option c3 ^root + test_bisection_diff 0 $_bisect_option E ^F + test_bisection_diff 0 $_bisect_option e1 ^F + test_bisection_diff 0 $_bisect_option e2 ^F + test_bisection_diff 0 $_bisect_option e3 ^F + test_bisection_diff 0 $_bisect_option e4 ^F + test_bisection_diff 0 $_bisect_option e5 ^F + test_bisection_diff 0 $_bisect_option e6 ^F + test_bisection_diff 0 $_bisect_option e7 ^F + test_bisection_diff 0 $_bisect_option f1 ^F + test_bisection_diff 0 $_bisect_option f2 ^F + test_bisection_diff 0 $_bisect_option f3 ^F + test_bisection_diff 0 $_bisect_option f4 ^F + test_bisection_diff 0 $_bisect_option E ^F + + test_bisection_diff 1 $_bisect_option V ^U + test_bisection_diff 0 $_bisect_option V ^U ^u1 ^u2 ^u3 + test_bisection_diff 0 $_bisect_option u1 ^U + test_bisection_diff 0 $_bisect_option u2 ^U + test_bisection_diff 0 $_bisect_option u3 ^U + test_bisection_diff 0 $_bisect_option u4 ^U + test_bisection_diff 0 $_bisect_option u5 ^U + +# +# the following illustrate's Linus' binary bug blatt idea. +# +# assume the bug is actually at l3, but you don't know that - all you know is that l3 is broken +# and it wasn't broken before +# +# keep bisecting the list, advancing the "bad" head and accumulating "good" heads until +# the bisection point is the head - this is the bad point. +# + +test_output_expect_success "--bisect l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF +c3 +EOF + +test_output_expect_success "$_bisect_option l5 ^root ^c3" 'git-rev-list $_bisect_option l5 ^root ^c3' <<EOF +b4 +EOF + +test_output_expect_success "$_bisect_option l5 ^root ^c3 ^b4" 'git-rev-list $_bisect_option l5 ^c3 ^b4' <<EOF +l3 +EOF + +test_output_expect_success "$_bisect_option l3 ^root ^c3 ^b4" 'git-rev-list $_bisect_option l3 ^root ^c3 ^b4' <<EOF +a4 +EOF + +test_output_expect_success "$_bisect_option l5 ^b3 ^a3 ^b4 ^a4" 'git-rev-list $_bisect_option l3 ^b3 ^a3 ^a4' <<EOF +l3 +EOF + +# +# if l3 is bad, then l4 is bad too - so advance the bad pointer by making b4 the known bad head +# + +test_output_expect_success "$_bisect_option l4 ^a2 ^a3 ^b ^a4" 'git-rev-list $_bisect_option l4 ^a2 ^a3 ^a4' <<EOF +l3 +EOF + +test_output_expect_success "$_bisect_option l3 ^a2 ^a3 ^b ^a4" 'git-rev-list $_bisect_option l3 ^a2 ^a3 ^a4' <<EOF +l3 +EOF + +# found! + +# +# as another example, let's consider a4 to be the bad head, in which case +# + +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF +c2 +EOF + +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2' <<EOF +c3 +EOF + +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4 ^c2 ^c3' <<EOF +a4 +EOF + +# found! + +# +# or consider c3 to be the bad head +# + +test_output_expect_success "$_bisect_option a4 ^a2 ^a3 ^b4" 'git-rev-list $_bisect_option a4 ^a2 ^a3 ^b4' <<EOF +c2 +EOF + +test_output_expect_success "$_bisect_option c3 ^a2 ^a3 ^b4 ^c2" 'git-rev-list $_bisect_option c3 ^a2 ^a3 ^b4 ^c2' <<EOF +c3 +EOF + +# found! + +} + +test_sequence "--bisect" + +# +# +test_done diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh new file mode 100755 index 0000000000..eb41f86a1b --- /dev/null +++ b/t/t6003-rev-list-topo-order.sh @@ -0,0 +1,408 @@ +#!/bin/sh +# +# Copyright (c) 2005 Jon Seymour +# + +test_description='Tests git-rev-list --topo-order functionality' + +. ./test-lib.sh +. ../t6000lib.sh # t6xxx specific functions + +list_duplicates() +{ + "$@" | sort | uniq -d +} + +date >path0 +git-update-cache --add path0 +save_tag tree git-write-tree +on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree +on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root +on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0 +on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1 +on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2 +on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0 +on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0 +on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1 +on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1 +on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2 +on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2 +on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2 +on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1 +on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2 +on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3 +on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3 +on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4 +on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3 +on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4 +on_committer_date "1971-08-16 00:00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3 +on_committer_date "1971-08-16 00:00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4 +on_committer_date "1971-08-16 00:00:21" hide_error save_tag alt_root unique_commit alt_root tree +on_committer_date "1971-08-16 00:00:22" save_tag r0 unique_commit r0 tree -p alt_root +on_committer_date "1971-08-16 00:00:23" save_tag r1 unique_commit r1 tree -p r0 +on_committer_date "1971-08-16 00:00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1 +on_committer_date "1971-08-16 00:00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5 + + +# +# note: as of 20/6, it isn't possible to create duplicate parents, so this +# can't be tested. +# +#on_committer_date "1971-08-16 00:00:20" save_tag m3 unique_commit m3 tree -p c3 -p a4 -p c3 +hide_error save_tag e1 as_author e@example.com unique_commit e1 tree +save_tag e2 as_author e@example.com unique_commit e2 tree -p e1 +save_tag f1 as_author f@example.com unique_commit f1 tree -p e1 +save_tag e3 as_author e@example.com unique_commit e3 tree -p e2 +save_tag f2 as_author f@example.com unique_commit f2 tree -p f1 +save_tag e4 as_author e@example.com unique_commit e4 tree -p e3 -p f2 +save_tag e5 as_author e@example.com unique_commit e5 tree -p e4 +save_tag f3 as_author f@example.com unique_commit f3 tree -p f2 +save_tag f4 as_author f@example.com unique_commit f4 tree -p f3 +save_tag e6 as_author e@example.com unique_commit e6 tree -p e5 -p f4 +save_tag f5 as_author f@example.com unique_commit f5 tree -p f4 +save_tag f6 as_author f@example.com unique_commit f6 tree -p f5 -p e6 +save_tag e7 as_author e@example.com unique_commit e7 tree -p e6 +save_tag e8 as_author e@example.com unique_commit e8 tree -p e7 +save_tag e9 as_author e@example.com unique_commit e9 tree -p e8 +save_tag f7 as_author f@example.com unique_commit f7 tree -p f6 +save_tag f8 as_author f@example.com unique_commit f8 tree -p f7 +save_tag f9 as_author f@example.com unique_commit f9 tree -p f8 +save_tag e10 as_author e@example.com unique_commit e1 tree -p e9 -p f8 + +hide_error save_tag g0 unique_commit g0 tree +save_tag g1 unique_commit g1 tree -p g0 +save_tag h1 unique_commit g2 tree -p g0 +save_tag g2 unique_commit g3 tree -p g1 -p h1 +save_tag h2 unique_commit g4 tree -p g2 +save_tag g3 unique_commit g5 tree -p g2 +save_tag g4 unique_commit g6 tree -p g3 -p h2 + +tag l5 > .git/HEAD + +test_expect_success 'rev-list has correct number of entries' 'git-rev-list HEAD | wc -l | tr -s " "' <<EOF +19 +EOF + +test_output_expect_success 'simple topo order' 'git-rev-list --topo-order HEAD' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +l1 +l0 +root +EOF + +test_output_expect_success 'two diamonds topo order (g6)' 'git-rev-list --topo-order g4' <<EOF +g4 +h2 +g3 +g2 +h1 +g1 +g0 +EOF + +test_output_expect_success 'multiple heads' 'git-rev-list --topo-order a3 b3 c3' <<EOF +b3 +c3 +c2 +b2 +c1 +b1 +a3 +a2 +a1 +a0 +l2 +l1 +l0 +root +EOF + +test_output_expect_success 'multiple heads, prune at a1' 'git-rev-list --topo-order a3 b3 c3 ^a1' <<EOF +b3 +c3 +c2 +b2 +c1 +b1 +a3 +a2 +EOF + +test_output_expect_success 'multiple heads, prune at l1' 'git-rev-list --topo-order a3 b3 c3 ^l1' <<EOF +b3 +c3 +c2 +b2 +c1 +b1 +a3 +a2 +a1 +a0 +l2 +EOF + +test_output_expect_success 'cross-epoch, head at l5, prune at l1' 'git-rev-list --topo-order l5 ^l1' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +EOF + +test_output_expect_success 'duplicated head arguments' 'git-rev-list --topo-order l5 l5 ^l1' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +EOF + +test_output_expect_success 'prune near topo' 'git-rev-list --topo-order a4 ^c3' <<EOF +a4 +b4 +a3 +a2 +a1 +b3 +EOF + +test_output_expect_success "head has no parent" 'git-rev-list --topo-order root' <<EOF +root +EOF + +test_output_expect_success "two nodes - one head, one base" 'git-rev-list --topo-order l0' <<EOF +l0 +root +EOF + +test_output_expect_success "three nodes one head, one internal, one base" 'git-rev-list --topo-order l1' <<EOF +l1 +l0 +root +EOF + +test_output_expect_success "linear prune l2 ^root" 'git-rev-list --topo-order l2 ^root' <<EOF +l2 +l1 +l0 +EOF + +test_output_expect_success "linear prune l2 ^l0" 'git-rev-list --topo-order l2 ^l0' <<EOF +l2 +l1 +EOF + +test_output_expect_success "linear prune l2 ^l1" 'git-rev-list --topo-order l2 ^l1' <<EOF +l2 +EOF + +test_output_expect_success "linear prune l5 ^a4" 'git-rev-list --topo-order l5 ^a4' <<EOF +l5 +l4 +l3 +EOF + +test_output_expect_success "linear prune l5 ^l3" 'git-rev-list --topo-order l5 ^l3' <<EOF +l5 +l4 +EOF + +test_output_expect_success "linear prune l5 ^l4" 'git-rev-list --topo-order l5 ^l4' <<EOF +l5 +EOF + +test_output_expect_success "max-count 10 - topo order" 'git-rev-list --topo-order --max-count=10 l5' <<EOF +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +EOF + +test_output_expect_success "max-count 10 - non topo order" 'git-rev-list --max-count=10 l5' <<EOF +l5 +l4 +l3 +a4 +b4 +a3 +a2 +c3 +c2 +b3 +EOF + +test_output_expect_success '--max-age=c3, no --topo-order' "git-rev-list --max-age=$(commit_date c3) l5" <<EOF +l5 +l4 +l3 +a4 +b4 +a3 +a2 +c3 +EOF + +# +# this test fails on --topo-order - a fix is required +# +#test_output_expect_success '--max-age=c3, --topo-order' "git-rev-list --topo-order --max-age=$(commit_date c3) l5" <<EOF +#l5 +#l4 +#l3 +#a4 +#c3 +#b4 +#a3 +#a2 +#EOF + +test_output_expect_success 'one specified head reachable from another a4, c3, --topo-order' "list_duplicates git-rev-list --topo-order a4 c3" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another c3, a4, --topo-order' "list_duplicates git-rev-list --topo-order c3 a4" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another a4, c3, no --topo-order' "list_duplicates git-rev-list a4 c3" <<EOF +EOF + +test_output_expect_success 'one specified head reachable from another c3, a4, no --topo-order' "list_duplicates git-rev-list c3 a4" <<EOF +EOF + +test_output_expect_success 'graph with c3 and a4 parents of head' "list_duplicates git-rev-list m1" <<EOF +EOF + +test_output_expect_success 'graph with a4 and c3 parents of head' "list_duplicates git-rev-list m2" <<EOF +EOF + +test_expect_success "head ^head --topo-order" 'git-rev-list --topo-order a3 ^a3' <<EOF +EOF + +test_expect_success "head ^head no --topo-order" 'git-rev-list a3 ^a3' <<EOF +EOF + +test_output_expect_success 'simple topo order (l5r1)' 'git-rev-list --topo-order l5r1' <<EOF +l5r1 +r1 +r0 +alt_root +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +l1 +l0 +root +EOF + +test_output_expect_success 'simple topo order (r1l5)' 'git-rev-list --topo-order r1l5' <<EOF +r1l5 +l5 +l4 +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +l1 +l0 +root +r1 +r0 +alt_root +EOF + +test_output_expect_success "don't print things unreachable from one branch" "git-rev-list a3 ^b3 --topo-order" <<EOF +a3 +a2 +a1 +EOF + +test_output_expect_success "--topo-order a4 l3" "git-rev-list --topo-order a4 l3" <<EOF +l3 +a4 +c3 +c2 +c1 +b4 +a3 +a2 +a1 +b3 +b2 +b1 +a0 +l2 +l1 +l0 +root +EOF + +# +# + +test_done diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh new file mode 100644 index 0000000000..4f57a28f69 --- /dev/null +++ b/t/t6101-rev-parse-parents.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright (c) 2005 Johannes Schindelin +# + +test_description='Test git-rev-parse with different parent options' + +. ./test-lib.sh +. ../t6000lib.sh # t6xxx specific functions + +date >path0 +git-update-cache --add path0 +save_tag tree git-write-tree +hide_error save_tag start unique_commit "start" tree +save_tag second unique_commit "second" tree -p start +hide_error save_tag start2 unique_commit "start2" tree +save_tag two_parents unique_commit "next" tree -p second -p start2 +save_tag final unique_commit "final" tree -p two_parents + +test_expect_success 'start is valid' 'git-rev-parse start | grep "^[0-9a-f]\{40\}$"' +test_expect_success 'start^0' "test $(cat .git/refs/tags/start) = $(git-rev-parse start^0)" +test_expect_success 'start^1 not valid' "test $(git-rev-parse start^1) = start^1" +test_expect_success 'second^1 = second^' "test $(git-rev-parse second^1) = $(git-rev-parse second^)" +test_expect_success 'final^1^1^1' "test $(git-rev-parse start) = $(git-rev-parse final^1^1^1)" +test_expect_success 'final^1^1^1 = final^^^' "test $(git-rev-parse final^1^1^1) = $(git-rev-parse final^^^)" +test_expect_success 'final^1^2' "test $(git-rev-parse start2) = $(git-rev-parse final^1^2)" +test_expect_success 'final^1^2 != final^1^1' "test $(git-rev-parse final^1^2) != $(git-rev-parse final^1^1)" +test_expect_success 'final^1^3 not valid' "test $(git-rev-parse final^1^3) = final^1^3" +test_expect_failure '--verify start2^1' 'git-rev-parse --verify start2^1' +test_expect_success '--verify start2^0' 'git-rev-parse --verify start2^0' + +test_done + diff --git a/t/test-lib.sh b/t/test-lib.sh new file mode 100755 index 0000000000..f97f8eb395 --- /dev/null +++ b/t/test-lib.sh @@ -0,0 +1,152 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +# For repeatability, reset the environment to known value. +LANG=C +TZ=UTC +export LANG TZ +unset AUTHOR_DATE +unset AUTHOR_EMAIL +unset AUTHOR_NAME +unset COMMIT_AUTHOR_EMAIL +unset COMMIT_AUTHOR_NAME +unset GIT_ALTERNATE_OBJECT_DIRECTORIES +unset GIT_AUTHOR_DATE +unset GIT_AUTHOR_EMAIL +unset GIT_AUTHOR_NAME +unset GIT_COMMITTER_EMAIL +unset GIT_COMMITTER_NAME +unset GIT_DIFF_OPTS +unset GIT_DIR +unset GIT_EXTERNAL_DIFF +unset GIT_INDEX_FILE +unset GIT_OBJECT_DIRECTORY +unset SHA1_FILE_DIRECTORIES +unset SHA1_FILE_DIRECTORY + +# Each test should start with something like this, after copyright notices: +# +# test_description='Description of this test... +# This test checks if command xyzzy does the right thing... +# ' +# . ./test-lib.sh + +error () { + echo "* error: $*" + exit 1 +} + +say () { + echo "* $*" +} + +test "${test_description}" != "" || +error "Test script did not set test_description." + +while test "$#" -ne 0 +do + case "$1" in + -d|--d|--de|--deb|--debu|--debug) + debug=t; shift ;; + -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate) + immediate=t; shift ;; + -h|--h|--he|--hel|--help) + echo "$test_description" + exit 0 ;; + -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) + verbose=t; shift ;; + *) + break ;; + esac +done + +if test "$verbose" = "t" +then + exec 4>&2 3>&1 +else + exec 4>/dev/null 3>/dev/null +fi + +test_failure=0 +test_count=0 + + +# You are not expected to call test_ok_ and test_failure_ directly, use +# the text_expect_* functions instead. + +test_ok_ () { + test_count=$(expr "$test_count" + 1) + say " ok $test_count: $@" +} + +test_failure_ () { + test_count=$(expr "$test_count" + 1) + test_failure=$(expr "$test_failure" + 1); + say "FAIL $test_count: $1" + shift + echo "$@" | sed -e 's/^/ /' + test "$immediate" == "" || exit 1 +} + + +test_debug () { + test "$debug" == "" || eval "$1" +} + +test_expect_failure () { + test "$#" == 2 || + error "bug in the test script: not 2 parameters to test-expect-failure" + say >&3 "expecting failure: $2" + if eval >&3 2>&4 "$2" + then + test_failure_ "$@" + else + test_ok_ "$1" + fi +} + +test_expect_success () { + test "$#" == 2 || + error "bug in the test script: not 2 parameters to test-expect-success" + say >&3 "expecting success: $2" + if eval >&3 2>&4 "$2" + then + test_ok_ "$1" + else + test_failure_ "$@" + fi +} + +test_done () { + case "$test_failure" in + 0) + # We could: + # cd .. && rm -fr trash + # but that means we forbid any tests that use their own + # subdirectory from calling test_done without coming back + # to where they started from. + # The Makefile provided will clean this test area so + # we will leave things as they are. + + say "passed all $test_count test(s)" + exit 0 ;; + + *) + say "failed $test_failure among $test_count test(s)" + exit 1 ;; + + esac +} + +# Test the binaries we have just built. The tests are kept in +# t/ subdirectory and are run in trash subdirectory. +PATH=$(pwd)/..:$PATH + +# Test repository +test=trash +rm -fr "$test" +mkdir "$test" +cd "$test" +git-init-db 2>/dev/null || error "cannot run git-init-db" |