From b0638aa2f8f7fa4e9c5d8569ee30b64fc21fba32 Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:30 -0600 Subject: [PATCH 1/7] contrib/subtree: Clean and refactor test code Mostly prepare for the later tests refactoring. This moves some common code to helper functions and generally cleans things up to be more presentable. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/Makefile | 31 +++++++-- contrib/subtree/t/t7900-subtree.sh | 103 +++++++++++++++-------------- 2 files changed, 79 insertions(+), 55 deletions(-) diff --git a/contrib/subtree/t/Makefile b/contrib/subtree/t/Makefile index c864810389..276898eb6b 100644 --- a/contrib/subtree/t/Makefile +++ b/contrib/subtree/t/Makefile @@ -13,11 +13,23 @@ TAR ?= $(TAR) RM ?= rm -f PROVE ?= prove DEFAULT_TEST_TARGET ?= test +TEST_LINT ?= test-lint + +ifdef TEST_OUTPUT_DIRECTORY +TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results +else +TEST_RESULTS_DIRECTORY = ../../../t/test-results +endif # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) +PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) +TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY)) -T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) +T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) +TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh)) +TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh)) +THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh))) all: $(DEFAULT_TEST_TARGET) @@ -26,20 +38,22 @@ test: pre-clean $(TEST_LINT) prove: pre-clean $(TEST_LINT) @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS) - $(MAKE) clean + $(MAKE) clean-except-prove-cache $(T): @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) pre-clean: - $(RM) -r test-results + $(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)' -clean: - $(RM) -r 'trash directory'.* test-results +clean-except-prove-cache: + $(RM) -r 'trash directory'.* '$(TEST_RESULTS_DIRECTORY_SQ)' $(RM) -r valgrind/bin + +clean: clean-except-prove-cache $(RM) .prove -test-lint: test-lint-duplicates test-lint-executable +test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax test-lint-duplicates: @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \ @@ -51,12 +65,15 @@ test-lint-executable: test -z "$$bad" || { \ echo >&2 "non-executable tests:" $$bad; exit 1; } +test-lint-shell-syntax: + @'$(PERL_PATH_SQ)' ../../../t/check-non-portable-shell.pl $(T) $(THELPERS) + aggregate-results-and-cleanup: $(T) $(MAKE) aggregate-results $(MAKE) clean aggregate-results: - for f in ../../../t/test-results/t*-*.counts; do \ + for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \ echo "$$f"; \ done | '$(SHELL_PATH_SQ)' ../../../t/aggregate-results.sh diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index dfbe443dea..f9dda3d6f9 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -5,7 +5,7 @@ # test_description='Basic porcelain support for subtrees -This test verifies the basic operation of the merge, pull, add +This test verifies the basic operation of the add, pull, merge and split subcommands of git subtree. ' @@ -20,7 +20,6 @@ create() git add "$1" } - check_equal() { test_debug 'echo' @@ -38,6 +37,30 @@ undo() git reset --hard HEAD~ } +# Make sure no patch changes more than one file. +# The original set of commits changed only one file each. +# A multi-file change would imply that we pruned commits +# too aggressively. +join_commits() +{ + commit= + all= + while read x y; do + if [ -z "$x" ]; then + continue + elif [ "$x" = "commit:" ]; then + if [ -n "$commit" ]; then + echo "$commit $all" + all= + fi + commit="$y" + else + all="$all $y" + fi + done + echo "$commit $all" +} + last_commit_message() { git log --pretty=format:%s -1 @@ -123,9 +146,11 @@ test_expect_success 'add subproj to mainline' ' check_equal ''"$(last_commit_message)"'' "Add '"'sub dir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'" ' -# this shouldn't actually do anything, since FETCH_HEAD is already a parent -test_expect_success 'merge fetched subproj' ' - git merge -m "merge -s -ours" -s ours FETCH_HEAD +test_expect_success 'merge the added subproj again, should do nothing' ' + # this shouldn not actually do anything, since FETCH_HEAD + # is already a parent + result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && + check_equal "${result}" "Already up-to-date." ' test_expect_success 'add main-sub5' ' @@ -167,7 +192,7 @@ test_expect_success 'merge new subproj history into subdir' ' undo ' -test_expect_success 'Check that prefix argument is required for split' ' +test_expect_success 'split requires option --prefix' ' echo "You must provide the --prefix option." > expected && test_must_fail git subtree split > actual 2>&1 && test_debug "printf '"'"'expected: '"'"'" && @@ -178,15 +203,15 @@ test_expect_success 'Check that prefix argument is required for split' ' rm -f expected actual ' -test_expect_success 'Check that the exists for a split' ' - echo "'"'"'non-existent-directory'"'"'" does not exist\; use "'"'"'git subtree add'"'"'" > expected && +test_expect_success 'split requires path given by option --prefix must exist' ' + echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected && test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 && test_debug "printf '"'"'expected: '"'"'" && test_debug "cat expected" && test_debug "printf '"'"'actual: '"'"'" && test_debug "cat actual" && - test_cmp expected actual -# rm -f expected actual + test_cmp expected actual && + rm -f expected actual ' test_expect_success 'check if --message works for split+rejoin' ' @@ -279,18 +304,22 @@ test_expect_success 'merge split into subproj' ' chkm="main4 main6" + chkms="main-sub10 main-sub5 main-sub7 main-sub8" + chkms_sub=$(cat <&2 - if [ -z "$x" ]; then - continue - elif [ "$x" = "commit:" ]; then - if [ -n "$commit" ]; then - echo "$commit $all" - all= - fi - commit="$y" - else - all="$all $y" - fi - done - echo "$commit $all" -} - test_expect_success 'verify one file change per commit' ' x= && - list=''"$(git log --pretty=format:'"'commit: %H'"' | joincommits)"'' && + list=''"$(git log --pretty=format:'"'commit: %H'"' | join_commits)"'' && # test_debug "echo HERE" && # test_debug "echo ''"$list"''" && - (git log --pretty=format:'"'commit: %H'"' | joincommits | + git log --pretty=format:'"'commit: %H'"' | join_commits | ( while read commit a b; do test_debug "echo Verifying commit "''"$commit"'' test_debug "echo a: "''"$a"'' @@ -468,15 +475,15 @@ test_expect_success 'verify one file change per commit' ' check_equal "$b" "" x=1 done - check_equal "$x" 1 - )) + check_equal "$x" "1" + ) ' # test push cd ../.. -mkdir test-push +mkdir -p test-push cd test-push From a686701184bc9e3d54b2870455f3ff276360299e Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:31 -0600 Subject: [PATCH 2/7] contrib/subtree: Add test for missing subtree Test that a merge from a non-existant subtree fails. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/t7900-subtree.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index f9dda3d6f9..4471786f50 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -123,6 +123,10 @@ test_expect_success 'no pull from non-existant subtree' ' test_must_fail git subtree pull --prefix="sub dir" ./"sub proj" sub1 ' +test_expect_success 'no merge from non-existent subtree' ' + test_must_fail git subtree merge --prefix="sub dir" FETCH_HEAD +' + test_expect_success 'check if --message works for add' ' git subtree add --prefix="sub dir" --message="Added subproject" sub1 && check_equal ''"$(last_commit_message)"'' "Added subproject" && From c9924996c95cfcc7633448e7ee8b88f440ccbd2b Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:32 -0600 Subject: [PATCH 3/7] contrib/subtree: Add tests for subtree add Add some tests to check various options to subtree add. These test various combinations of --message, --prefix and --squash. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/t7900-subtree.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 4471786f50..1fa59918c7 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -127,12 +127,24 @@ test_expect_success 'no merge from non-existent subtree' ' test_must_fail git subtree merge --prefix="sub dir" FETCH_HEAD ' +test_expect_success 'add subproj as subtree into sub dir/ with --prefix' ' + git subtree add --prefix="sub dir" sub1 && + check_equal "$(last_commit_message)" "Add '\''sub dir/'\'' from commit '\''$(git rev-parse sub1)'\''" && + undo +' + test_expect_success 'check if --message works for add' ' git subtree add --prefix="sub dir" --message="Added subproject" sub1 && check_equal ''"$(last_commit_message)"'' "Added subproject" && undo ' +test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' ' + git subtree add --prefix="sub dir" --message="Added subproject" sub1 && + check_equal "$(last_commit_message)" "Added subproject" && + undo +' + test_expect_success 'check if --message works as -m and --prefix as -P' ' git subtree add -P "sub dir" -m "Added subproject using git subtree" sub1 && check_equal ''"$(last_commit_message)"'' "Added subproject using git subtree" && @@ -145,6 +157,13 @@ test_expect_success 'check if --message works with squash too' ' undo ' +test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' ' + git subtree add --prefix="sub dir" --message="Added subproject with squash" --squash sub1 && + check_equal "$(last_commit_message)" "Added subproject with squash" && + undo +' + +# Maybe delete test_expect_success 'add subproj to mainline' ' git subtree add --prefix="sub dir"/ FETCH_HEAD && check_equal ''"$(last_commit_message)"'' "Add '"'sub dir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'" From 4f96fcc9a2a2d756c5523c49a57f97b53c9cadb6 Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:33 -0600 Subject: [PATCH 4/7] contrib/subtree: Add merge tests Add some tests for various merge operations. Test combinations of merge with --message, --prefix and --squash. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/t7900-subtree.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 1fa59918c7..7d59a1a89d 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -210,11 +210,22 @@ test_expect_success 'check if --message for merge works with squash too' ' test_expect_success 'merge new subproj history into subdir' ' git subtree merge --prefix="sub dir" FETCH_HEAD && - git branch pre-split && check_equal ''"$(last_commit_message)"'' "Merge commit '"'"'"$(git rev-parse sub2)"'"'"' into mainline" && undo ' +test_expect_success 'merge new subproj history into subdir/ with --prefix and --message' ' + git subtree merge --prefix="sub dir" --message="Merged changes from subproject" FETCH_HEAD && + check_equal "$(last_commit_message)" "Merged changes from subproject" && + undo +' + +test_expect_success 'merge new subproj history into subdir/ with --squash and --prefix and --message' ' + git subtree merge --prefix="sub dir" --message="Merged changes from subproject using squash" --squash FETCH_HEAD && + check_equal "$(last_commit_message)" "Merged changes from subproject using squash" && + undo +' + test_expect_success 'split requires option --prefix' ' echo "You must provide the --prefix option." > expected && test_must_fail git subtree split > actual 2>&1 && From 4fe2e33cc961328ea24e821692abc305d28e8ddb Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:34 -0600 Subject: [PATCH 5/7] contrib/subtree: Add split tests Add tests to check various options to split. Check combinations of --prefix, --message, --annotate, --branch and --rejoin. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/t7900-subtree.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 7d59a1a89d..625019486a 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -250,7 +250,6 @@ test_expect_success 'split requires path given by option --prefix must exist' ' test_expect_success 'check if --message works for split+rejoin' ' spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' && - git branch spl1 "$spl1" && check_equal ''"$(last_commit_message)"'' "Split & rejoin" && undo ' @@ -282,7 +281,21 @@ test_expect_success 'check split with --branch for an incompatible branch' ' test_must_fail git subtree split --prefix "sub dir" --onto FETCH_HEAD --branch subdir ' -test_expect_success 'check split+rejoin' ' +test_expect_success 'split sub dir/ with --rejoin' ' + spl1=$(git subtree split --prefix="sub dir" --annotate="*") && + git branch spl1 "$spl1" && + git subtree split --prefix="sub dir" --annotate="*" --rejoin && + check_equal "$(last_commit_message)" "Split '\''sub dir/'\'' into commit '\''$spl1'\''" && + undo +' + +test_expect_success 'split sub dir/ with --rejoin and --message' ' + git subtree split --prefix="sub dir" --message="Split & rejoin" --annotate="*" --rejoin && + check_equal "$(last_commit_message)" "Split & rejoin" && + undo +' + +test_expect_success 'check split+rejoin+onto' ' spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' && undo && git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --rejoin && From 43711746bd01eff9d8bac658bf1d6a39151088f2 Mon Sep 17 00:00:00 2001 From: Techlive Zheng Date: Thu, 12 Nov 2015 20:32:35 -0600 Subject: [PATCH 6/7] contrib/subtree: Make each test self-contained Each test runs a full repository creation and any subtree actions needed to perform the test. Each test starts with a clean slate, making debugging and post-mortem analysis much easier. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/t/t7900-subtree.sh | 1268 ++++++++++++++++++---------- 1 file changed, 845 insertions(+), 423 deletions(-) diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 625019486a..2683d7d479 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -14,6 +14,15 @@ export TEST_DIRECTORY . ../../../t/test-lib.sh +subtree_test_create_repo() +{ + test_create_repo "$1" + ( + cd $1 + git config log.date relative + ) +} + create() { echo "$1" >"$1" @@ -61,515 +70,928 @@ join_commits() echo "$commit $all" } +test_create_commit() ( + repo=$1 + commit=$2 + cd "$repo" + mkdir -p $(dirname "$commit") \ + || error "Could not create directory for commit" + echo "$commit" >"$commit" + git add "$commit" || error "Could not add commit" + git commit -m "$commit" || error "Could not commit" +) + last_commit_message() { git log --pretty=format:%s -1 } -test_expect_success 'init subproj' ' - test_create_repo "sub proj" -' +subtree_test_count=0 +next_test() { + subtree_test_count=$(($subtree_test_count+1)) +} -# To the subproject! -cd ./"sub proj" - -test_expect_success 'add sub1' ' - create sub1 && - git commit -m "sub1" && - git branch sub1 && - git branch -m master subproj -' - -# Save this hash for testing later. - -subdir_hash=$(git rev-parse HEAD) - -test_expect_success 'add sub2' ' - create sub2 && - git commit -m "sub2" && - git branch sub2 -' - -test_expect_success 'add sub3' ' - create sub3 && - git commit -m "sub3" && - git branch sub3 -' - -# Back to mainline -cd .. - -test_expect_success 'enable log.date=relative to catch errors' ' - git config log.date relative -' - -test_expect_success 'add main4' ' - create main4 && - git commit -m "main4" && - git branch -m master mainline && - git branch subdir -' - -test_expect_success 'fetch subproj history' ' - git fetch ./"sub proj" sub1 && - git branch sub1 FETCH_HEAD -' - -test_expect_success 'no subtree exists in main tree' ' - test_must_fail git subtree merge --prefix="sub dir" sub1 -' - -test_expect_success 'no pull from non-existant subtree' ' - test_must_fail git subtree pull --prefix="sub dir" ./"sub proj" sub1 -' +# +# Tests for 'git subtree add' +# +next_test test_expect_success 'no merge from non-existent subtree' ' - test_must_fail git subtree merge --prefix="sub dir" FETCH_HEAD + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + test_must_fail git subtree merge --prefix="sub dir" FETCH_HEAD + ) ' +next_test +test_expect_success 'no pull from non-existent subtree' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + test_must_fail git subtree pull --prefix="sub dir" ./"sub proj" master + )' + +next_test test_expect_success 'add subproj as subtree into sub dir/ with --prefix' ' - git subtree add --prefix="sub dir" sub1 && - check_equal "$(last_commit_message)" "Add '\''sub dir/'\'' from commit '\''$(git rev-parse sub1)'\''" && - undo -' - -test_expect_success 'check if --message works for add' ' - git subtree add --prefix="sub dir" --message="Added subproject" sub1 && - check_equal ''"$(last_commit_message)"'' "Added subproject" && - undo + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD && + check_equal "$(last_commit_message)" "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) ' +next_test test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' ' - git subtree add --prefix="sub dir" --message="Added subproject" sub1 && - check_equal "$(last_commit_message)" "Added subproject" && - undo + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" --message="Added subproject" FETCH_HEAD && + check_equal "$(last_commit_message)" "Added subproject" + ) ' -test_expect_success 'check if --message works as -m and --prefix as -P' ' - git subtree add -P "sub dir" -m "Added subproject using git subtree" sub1 && - check_equal ''"$(last_commit_message)"'' "Added subproject using git subtree" && - undo -' - -test_expect_success 'check if --message works with squash too' ' - git subtree add -P "sub dir" -m "Added subproject with squash" --squash sub1 && - check_equal ''"$(last_commit_message)"'' "Added subproject with squash" && - undo +next_test +test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P and --message as -m' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add -P "sub dir" -m "Added subproject" FETCH_HEAD && + check_equal "$(last_commit_message)" "Added subproject" + ) ' +next_test test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' ' - git subtree add --prefix="sub dir" --message="Added subproject with squash" --squash sub1 && - check_equal "$(last_commit_message)" "Added subproject with squash" && - undo + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" --message="Added subproject with squash" --squash FETCH_HEAD && + check_equal "$(last_commit_message)" "Added subproject with squash" + ) ' -# Maybe delete -test_expect_success 'add subproj to mainline' ' - git subtree add --prefix="sub dir"/ FETCH_HEAD && - check_equal ''"$(last_commit_message)"'' "Add '"'sub dir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'" +# +# Tests for 'git subtree merge' +# + +next_test +test_expect_success 'merge new subproj history into sub dir/ with --prefix' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count/sub proj" sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) ' +next_test +test_expect_success 'merge new subproj history into sub dir/ with --prefix and --message' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count/sub proj" sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" --message="Merged changes from subproject" FETCH_HEAD && + check_equal "$(last_commit_message)" "Merged changes from subproject" + ) +' + +next_test +test_expect_success 'merge new subproj history into sub dir/ with --squash and --prefix and --message' ' + subtree_test_create_repo "$subtree_test_count/sub proj" && + subtree_test_create_repo "$subtree_test_count" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count/sub proj" sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" --message="Merged changes from subproject using squash" --squash FETCH_HEAD && + check_equal "$(last_commit_message)" "Merged changes from subproject using squash" + ) +' + +next_test test_expect_success 'merge the added subproj again, should do nothing' ' - # this shouldn not actually do anything, since FETCH_HEAD - # is already a parent - result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && - check_equal "${result}" "Already up-to-date." + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD && + # this shouldn not actually do anything, since FETCH_HEAD + # is already a parent + result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && + check_equal "${result}" "Already up-to-date." + ) ' -test_expect_success 'add main-sub5' ' - create "sub dir/main-sub5" && - git commit -m "main-sub5" -' - -test_expect_success 'add main6' ' - create main6 && - git commit -m "main6 boring" -' - -test_expect_success 'add main-sub7' ' - create "sub dir/main-sub7" && - git commit -m "main-sub7" -' - -test_expect_success 'fetch new subproj history' ' - git fetch ./"sub proj" sub2 && - git branch sub2 FETCH_HEAD -' - -test_expect_success 'check if --message works for merge' ' - git subtree merge --prefix="sub dir" -m "Merged changes from subproject" sub2 && - check_equal ''"$(last_commit_message)"'' "Merged changes from subproject" && - undo -' - -test_expect_success 'check if --message for merge works with squash too' ' - git subtree merge --prefix "sub dir" -m "Merged changes from subproject using squash" --squash sub2 && - check_equal ''"$(last_commit_message)"'' "Merged changes from subproject using squash" && - undo -' - -test_expect_success 'merge new subproj history into subdir' ' - git subtree merge --prefix="sub dir" FETCH_HEAD && - check_equal ''"$(last_commit_message)"'' "Merge commit '"'"'"$(git rev-parse sub2)"'"'"' into mainline" && - undo -' - -test_expect_success 'merge new subproj history into subdir/ with --prefix and --message' ' - git subtree merge --prefix="sub dir" --message="Merged changes from subproject" FETCH_HEAD && - check_equal "$(last_commit_message)" "Merged changes from subproject" && - undo -' - -test_expect_success 'merge new subproj history into subdir/ with --squash and --prefix and --message' ' - git subtree merge --prefix="sub dir" --message="Merged changes from subproject using squash" --squash FETCH_HEAD && - check_equal "$(last_commit_message)" "Merged changes from subproject using squash" && - undo -' +# +# Tests for 'git subtree split' +# +next_test test_expect_success 'split requires option --prefix' ' - echo "You must provide the --prefix option." > expected && - test_must_fail git subtree split > actual 2>&1 && - test_debug "printf '"'"'expected: '"'"'" && - test_debug "cat expected" && - test_debug "printf '"'"'actual: '"'"'" && - test_debug "cat actual" && - test_cmp expected actual && - rm -f expected actual + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD && + echo "You must provide the --prefix option." > expected && + test_must_fail git subtree split > actual 2>&1 && + test_debug "printf '"expected: "'" && + test_debug "cat expected" && + test_debug "printf '"actual: "'" && + test_debug "cat actual" && + test_cmp expected actual + ) ' +next_test test_expect_success 'split requires path given by option --prefix must exist' ' - echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected && - test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 && - test_debug "printf '"'"'expected: '"'"'" && - test_debug "cat expected" && - test_debug "printf '"'"'actual: '"'"'" && - test_debug "cat actual" && - test_cmp expected actual && - rm -f expected actual -' - -test_expect_success 'check if --message works for split+rejoin' ' - spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' && - check_equal ''"$(last_commit_message)"'' "Split & rejoin" && - undo -' - -test_expect_success 'check split with --branch' ' - spl1=$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin) && - undo && - git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --branch splitbr1 && - check_equal ''"$(git rev-parse splitbr1)"'' "$spl1" -' - -test_expect_success 'check hash of split' ' - spl1=$(git subtree split --prefix "sub dir") && - git subtree split --prefix "sub dir" --branch splitbr1test && - check_equal ''"$(git rev-parse splitbr1test)"'' "$spl1" && - new_hash=$(git rev-parse splitbr1test~2) && - check_equal ''"$new_hash"'' "$subdir_hash" -' - -test_expect_success 'check split with --branch for an existing branch' ' - spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' && - undo && - git branch splitbr2 sub1 && - git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --branch splitbr2 && - check_equal ''"$(git rev-parse splitbr2)"'' "$spl1" -' - -test_expect_success 'check split with --branch for an incompatible branch' ' - test_must_fail git subtree split --prefix "sub dir" --onto FETCH_HEAD --branch subdir + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD && + echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected && + test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 && + test_debug "printf '"expected: "'" && + test_debug "cat expected" && + test_debug "printf '"actual: "'" && + test_debug "cat actual" && + test_cmp expected actual + ) ' +next_test test_expect_success 'split sub dir/ with --rejoin' ' - spl1=$(git subtree split --prefix="sub dir" --annotate="*") && - git branch spl1 "$spl1" && - git subtree split --prefix="sub dir" --annotate="*" --rejoin && - check_equal "$(last_commit_message)" "Split '\''sub dir/'\'' into commit '\''$spl1'\''" && - undo -' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") && + git subtree split --prefix="sub dir" --annotate="*" --rejoin && + check_equal "$(last_commit_message)" "Split '\''sub dir/'\'' into commit '\''$split_hash'\''" + ) + ' +next_test test_expect_success 'split sub dir/ with --rejoin and --message' ' - git subtree split --prefix="sub dir" --message="Split & rejoin" --annotate="*" --rejoin && - check_equal "$(last_commit_message)" "Split & rejoin" && - undo + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + git subtree split --prefix="sub dir" --message="Split & rejoin" --annotate="*" --rejoin && + check_equal "$(last_commit_message)" "Split & rejoin" + ) ' -test_expect_success 'check split+rejoin+onto' ' - spl1=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' && - undo && - git subtree split --annotate='"'*'"' --prefix "sub dir" --onto FETCH_HEAD --rejoin && - check_equal ''"$(last_commit_message)"'' "Split '"'"'sub dir/'"'"' into commit '"'"'"$spl1"'"'"'" +next_test +test_expect_success 'split "sub dir"/ with --branch' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br && + check_equal "$(git rev-parse subproj-br)" "$split_hash" + ) ' -test_expect_success 'add main-sub8' ' - create "sub dir/main-sub8" && - git commit -m "main-sub8" +next_test +test_expect_success 'check hash of split' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br && + check_equal "$(git rev-parse subproj-br)" "$split_hash" && + # Check hash of split + new_hash=$(git rev-parse subproj-br^2) && + ( + cd ./"sub proj" && + subdir_hash=$(git rev-parse HEAD) && + check_equal ''"$new_hash"'' "$subdir_hash" + ) + ) ' -# To the subproject! -cd ./"sub proj" - -test_expect_success 'merge split into subproj' ' - git fetch .. spl1 && - git branch spl1 FETCH_HEAD && - git merge FETCH_HEAD +next_test +test_expect_success 'split "sub dir"/ with --branch for an existing branch' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git branch subproj-br FETCH_HEAD && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br && + check_equal "$(git rev-parse subproj-br)" "$split_hash" + ) ' -test_expect_success 'add sub9' ' - create sub9 && - git commit -m "sub9" +next_test +test_expect_success 'split "sub dir"/ with --branch for an incompatible branch' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git branch init HEAD && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + test_must_fail git subtree split --prefix="sub dir" --branch init + ) ' -# Back to mainline -cd .. +# +# Validity checking +# -test_expect_success 'split for sub8' ' - split2=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir/" --rejoin)"'' && - git branch split2 "$split2" -' +next_test +test_expect_success 'make sure exactly the right set of files ends up in the subproj' ' + subtree_test_create_repo "$subtree_test_count" && + subtree_test_create_repo "$subtree_test_count/sub proj" && + test_create_commit "$subtree_test_count" main1 && + test_create_commit "$subtree_test_count/sub proj" sub1 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub1 && + test_create_commit "$subtree_test_count" main2 && + test_create_commit "$subtree_test_count/sub proj" sub2 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub2 && + ( + cd "$subtree_test_count" && + git fetch ./"sub proj" master && + git subtree merge --prefix="sub dir" FETCH_HEAD && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin + ) && + test_create_commit "$subtree_test_count/sub proj" sub3 && + test_create_commit "$subtree_test_count" "sub dir"/main-sub3 && + ( + cd "$subtree_test_count/sub proj" && + git fetch .. subproj-br && + git merge FETCH_HEAD + ) && + test_create_commit "$subtree_test_count/sub proj" sub4 && + ( + cd "$subtree_test_count" && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin + ) && + test_create_commit "$subtree_test_count" "sub dir"/main-sub4 && + ( + cd "$subtree_test_count" && + git subtree split --prefix="sub dir" --annotate="*" --branch subproj-br --rejoin + ) && + ( + cd "$subtree_test_count/sub proj" && + git fetch .. subproj-br && + git merge FETCH_HEAD && -test_expect_success 'add main-sub10' ' - create "sub dir/main-sub10" && - git commit -m "main-sub10" -' - -test_expect_success 'split for sub10' ' - spl3=''"$(git subtree split --annotate='"'*'"' --prefix "sub dir" --rejoin)"'' && - git branch spl3 "$spl3" -' - -# To the subproject! -cd ./"sub proj" - -test_expect_success 'merge split into subproj' ' - git fetch .. spl3 && - git branch spl3 FETCH_HEAD && - git merge FETCH_HEAD && - git branch subproj-merge-spl3 -' - -chkm="main4 -main6" - -chkms="main-sub10 -main-sub5 -main-sub7 -main-sub8" - -chkms_sub=$(cat < Date: Thu, 12 Nov 2015 20:32:36 -0600 Subject: [PATCH 7/7] contrib/subtree: Handle '--prefix' argument with a slash appended 'git subtree merge' will fail if the argument of '--prefix' has a slash appended. Signed-off-by: Techlive Zheng Signed-off-by: David A. Greene Signed-off-by: Jeff King --- contrib/subtree/git-subtree.sh | 2 +- contrib/subtree/t/t7900-subtree.sh | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 308b777b0a..edf36f8c36 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -90,7 +90,7 @@ while [ $# -gt 0 ]; do --annotate) annotate="$1"; shift ;; --no-annotate) annotate= ;; -b) branch="$1"; shift ;; - -P) prefix="$1"; shift ;; + -P) prefix="${1%/}"; shift ;; -m) message="$1"; shift ;; --no-prefix) prefix= ;; --onto) onto="$1"; shift ;; diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 2683d7d479..751aee3a0c 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -257,6 +257,26 @@ test_expect_success 'merge the added subproj again, should do nothing' ' ) ' +next_test +test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' ' + test_create_repo "$test_count" && + test_create_repo "$test_count/subproj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/subproj" sub1 && + ( + cd "$test_count" && + git fetch ./subproj master && + git subtree add --prefix=subdir/ FETCH_HEAD + ) && + test_create_commit "$test_count/subproj" sub2 && + ( + cd "$test_count" && + git fetch ./subproj master && + git subtree merge --prefix=subdir/ FETCH_HEAD && + check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) +' + # # Tests for 'git subtree split' #