ec54f0d9ad
And test cases for that check, as well as for an error if no prefix is specified at all.
318 lines
7.5 KiB
Bash
Executable File
318 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
|
. shellopts.sh
|
|
set -e
|
|
|
|
create()
|
|
{
|
|
echo "$1" >"$1"
|
|
git add "$1"
|
|
}
|
|
|
|
check()
|
|
{
|
|
echo
|
|
echo "check:" "$@"
|
|
if "$@"; then
|
|
echo ok
|
|
return 0
|
|
else
|
|
echo FAILED
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_equal()
|
|
{
|
|
echo
|
|
echo "check a:" "{$1}"
|
|
echo " b:" "{$2}"
|
|
if [ "$1" = "$2" ]; then
|
|
return 0
|
|
else
|
|
echo FAILED
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
fixnl()
|
|
{
|
|
t=""
|
|
while read x; do
|
|
t="$t$x "
|
|
done
|
|
echo $t
|
|
}
|
|
|
|
multiline()
|
|
{
|
|
while read x; do
|
|
set -- $x
|
|
for d in "$@"; do
|
|
echo "$d"
|
|
done
|
|
done
|
|
}
|
|
|
|
undo()
|
|
{
|
|
git reset --hard HEAD~
|
|
}
|
|
|
|
last_commit_message()
|
|
{
|
|
git log --format=%s -1
|
|
}
|
|
|
|
rm -rf mainline subproj
|
|
mkdir mainline subproj
|
|
|
|
cd subproj
|
|
git init
|
|
|
|
create sub1
|
|
git commit -m 'sub1'
|
|
git branch sub1
|
|
git branch -m master subproj
|
|
check true
|
|
|
|
create sub2
|
|
git commit -m 'sub2'
|
|
git branch sub2
|
|
|
|
create sub3
|
|
git commit -m 'sub3'
|
|
git branch sub3
|
|
|
|
cd ../mainline
|
|
git init
|
|
create main4
|
|
git commit -m 'main4'
|
|
git branch -m master mainline
|
|
git branch subdir
|
|
|
|
git fetch ../subproj sub1
|
|
git branch sub1 FETCH_HEAD
|
|
|
|
# check if --message works for add
|
|
git subtree add --prefix=subdir --message="Added subproject" sub1
|
|
check_equal "$(last_commit_message)" "Added subproject"
|
|
undo
|
|
|
|
# check if --message works as -m and --prefix as -P
|
|
git subtree add -P subdir -m "Added subproject using git subtree" sub1
|
|
check_equal "$(last_commit_message)" "Added subproject using git subtree"
|
|
undo
|
|
|
|
# check if --message works with squash too
|
|
git subtree add -P subdir -m "Added subproject with squash" --squash sub1
|
|
check_equal "$(last_commit_message)" "Added subproject with squash"
|
|
undo
|
|
|
|
git subtree add --prefix=subdir/ FETCH_HEAD
|
|
check_equal "$(last_commit_message)" "Add 'subdir/' from commit '$(git rev-parse sub1)'"
|
|
|
|
# this shouldn't actually do anything, since FETCH_HEAD is already a parent
|
|
git merge -m 'merge -s -ours' -s ours FETCH_HEAD
|
|
|
|
create subdir/main-sub5
|
|
git commit -m 'main-sub5'
|
|
|
|
create main6
|
|
git commit -m 'main6 boring'
|
|
|
|
create subdir/main-sub7
|
|
git commit -m 'main-sub7'
|
|
|
|
git fetch ../subproj sub2
|
|
git branch sub2 FETCH_HEAD
|
|
|
|
# check if --message works for merge
|
|
git subtree merge --prefix=subdir -m "Merged changes from subproject" sub2
|
|
check_equal "$(last_commit_message)" "Merged changes from subproject"
|
|
undo
|
|
|
|
# check if --message for merge works with squash too
|
|
git subtree merge --prefix subdir -m "Merged changes from subproject using squash" --squash sub2
|
|
check_equal "$(last_commit_message)" "Merged changes from subproject using squash"
|
|
undo
|
|
|
|
git subtree merge --prefix=subdir FETCH_HEAD
|
|
git branch pre-split
|
|
check_equal "$(last_commit_message)" "Merge commit '$(git rev-parse sub2)' into mainline"
|
|
|
|
# Check that prefix argument is required for split (exits with warning and exit status = 1)
|
|
! result=$(git subtree split 2>&1)
|
|
check_equal "You must provide the --prefix option." "$result"
|
|
|
|
# Check that the <prefix> exists for a split.
|
|
! result=$(git subtree split --prefix=non-existent-directory 2>&1)
|
|
check_equal "non-existent-directory does not exist." "$result"
|
|
|
|
# check if --message works for split+rejoin
|
|
spl1=$(git subtree split --annotate='*' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)
|
|
echo "spl1={$spl1}"
|
|
git branch spl1 "$spl1"
|
|
check_equal "$(last_commit_message)" "Split & rejoin"
|
|
undo
|
|
|
|
# check split with --branch
|
|
git subtree split --annotate='*' --prefix subdir --onto FETCH_HEAD --branch splitbr1
|
|
check_equal "$(git rev-parse splitbr1)" "$spl1"
|
|
|
|
# check split with --branch for an existing branch
|
|
git branch splitbr2 sub1
|
|
git subtree split --annotate='*' --prefix subdir --onto FETCH_HEAD --branch splitbr2
|
|
check_equal "$(git rev-parse splitbr2)" "$spl1"
|
|
|
|
# check split with --branch for an incompatible branch
|
|
result=$(git subtree split --prefix subdir --onto FETCH_HEAD --branch subdir || echo "caught error")
|
|
check_equal "$result" "caught error"
|
|
|
|
|
|
git subtree split --annotate='*' --prefix subdir --onto FETCH_HEAD --rejoin
|
|
check_equal "$(last_commit_message)" "Split 'subdir/' into commit '$spl1'"
|
|
|
|
create subdir/main-sub8
|
|
git commit -m 'main-sub8'
|
|
|
|
cd ../subproj
|
|
git fetch ../mainline spl1
|
|
git branch spl1 FETCH_HEAD
|
|
git merge FETCH_HEAD
|
|
|
|
create sub9
|
|
git commit -m 'sub9'
|
|
|
|
cd ../mainline
|
|
split2=$(git subtree split --annotate='*' --prefix subdir/ --rejoin)
|
|
git branch split2 "$split2"
|
|
|
|
create subdir/main-sub10
|
|
git commit -m 'main-sub10'
|
|
|
|
spl3=$(git subtree split --annotate='*' --prefix subdir --rejoin)
|
|
git branch spl3 "$spl3"
|
|
|
|
cd ../subproj
|
|
git fetch ../mainline 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=$(echo $chkms | multiline | sed 's,^,subdir/,' | fixnl)
|
|
chks="sub1 sub2 sub3 sub9"
|
|
chks_sub=$(echo $chks | multiline | sed 's,^,subdir/,' | fixnl)
|
|
|
|
# make sure exactly the right set of files ends up in the subproj
|
|
subfiles=$(git ls-files | fixnl)
|
|
check_equal "$subfiles" "$chkms $chks"
|
|
|
|
# make sure the subproj history *only* contains commits that affect the subdir.
|
|
allchanges=$(git log --name-only --pretty=format:'' | sort | fixnl)
|
|
check_equal "$allchanges" "$chkms $chks"
|
|
|
|
cd ../mainline
|
|
git fetch ../subproj subproj-merge-spl3
|
|
git branch subproj-merge-spl3 FETCH_HEAD
|
|
git subtree pull --prefix=subdir ../subproj subproj-merge-spl3
|
|
|
|
# make sure exactly the right set of files ends up in the mainline
|
|
mainfiles=$(git ls-files | fixnl)
|
|
check_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
|
|
|
|
# make sure each filename changed exactly once in the entire history.
|
|
# 'main-sub??' and '/subdir/main-sub??' both change, because those are the
|
|
# changes that were split into their own history. And 'subdir/sub??' never
|
|
# change, since they were *only* changed in the subtree branch.
|
|
allchanges=$(git log --name-only --pretty=format:'' | sort | fixnl)
|
|
check_equal "$allchanges" "$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"
|
|
|
|
# make sure the --rejoin commits never make it into subproj
|
|
check_equal "$(git log --pretty=format:'%s' HEAD^2 | grep -i split)" ""
|
|
|
|
# make sure no 'git subtree' tagged commits make it into subproj. (They're
|
|
# meaningless to subproj since one side of the merge refers to the mainline)
|
|
check_equal "$(git log --pretty=format:'%s%n%b' HEAD^2 | grep 'git-subtree.*:')" ""
|
|
|
|
|
|
# check if split can find proper base without --onto
|
|
# prepare second pair of repositories
|
|
mkdir test2
|
|
cd test2
|
|
|
|
mkdir main
|
|
cd main
|
|
git init
|
|
create main1
|
|
git commit -m "main1"
|
|
|
|
cd ..
|
|
mkdir sub
|
|
cd sub
|
|
git init
|
|
create sub2
|
|
git commit -m "sub2"
|
|
|
|
cd ../main
|
|
git fetch ../sub master
|
|
git branch sub2 FETCH_HEAD
|
|
git subtree add --prefix subdir sub2
|
|
|
|
cd ../sub
|
|
create sub3
|
|
git commit -m "sub3"
|
|
|
|
cd ../main
|
|
git fetch ../sub master
|
|
git branch sub3 FETCH_HEAD
|
|
git subtree merge --prefix subdir sub3
|
|
|
|
create subdir/main-sub4
|
|
git commit -m "main-sub4"
|
|
git subtree split --prefix subdir --branch mainsub4
|
|
|
|
# at this point, the new commit's parent should be sub3
|
|
# if it's not, something went wrong (the "newparent" of "master~" commit should have been sub3,
|
|
# but it wasn't, because it's cache was not set to itself)
|
|
check_equal "$(git log --format=%P -1 mainsub4)" "$(git rev-parse sub3)"
|
|
|
|
|
|
|
|
# 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.
|
|
joincommits()
|
|
{
|
|
commit=
|
|
all=
|
|
while read x y; do
|
|
echo "{$x}" >&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"
|
|
}
|
|
x=
|
|
git log --pretty=format:'commit: %H' | joincommits |
|
|
( while read commit a b; do
|
|
echo "Verifying commit $commit"
|
|
check_equal "$b" ""
|
|
x=1
|
|
done
|
|
check_equal "$x" 1
|
|
) || exit 1
|
|
|
|
echo
|
|
echo 'ok'
|