X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=tests%2Ftartree-edit;h=40bd6e9620974f376a4cbcd57c9aaec782df7964;hp=2e0c01791b8f6a77352ea257f63c25043cf68c31;hb=63911b5d576e7250c132d117c53e66aaf34b7f47;hpb=3aaec06aaaaa6a500d99437317c82b316163e397 diff --git a/tests/tartree-edit b/tests/tartree-edit index 2e0c0179..40bd6e96 100755 --- a/tests/tartree-edit +++ b/tests/tartree-edit @@ -2,10 +2,74 @@ set -e fail () { echo >&2 "$0: $*"; exit 1; } +play=.git/tartree-edit-work + +git_manip_play () { + local wd; wd=$(pwd) + case "$wd" in + *.edit) fail "bad idea to run gitfetchinfo into a .edit tree!" ;; + esac + rm -rf $play + mkdir $play +} + +gitfetchdiff_list () { + git for-each-ref --format '%(refname) %(objectname)' \ + refs/remotes/"$1" \ + | sed 's/^refs\/remotes\/[^\/]*\///' \ + | sort >"$play/$2" +} + +gitfetchdiff () { + local how="$1" + local a="$2" + local b="$3" + git_manip_play + + rrab=refs/remotes/"$a+$b" + + ulf=\ +"delete refs/remotes/$a/%l +delete refs/remotes/$b/%l +" + case "$how" in + diff) + git for-each-ref --format 'delete %(refname)' $rrab \ + | git update-ref --stdin + ;; + merge) + ulf=\ +"create $rrab/%l +$ulf" + ;; + *) + fail "internal error bad how ($how)" + ;; + esac + + gitfetchdiff_list "$a" a + gitfetchdiff_list "$b" b + + diff --old-line-format='' --new-line-format='' \ + --unchanged-line-format="$ulf" \ + $play/a $play/b >$play/updates \ + || test $? = 1 + + git update-ref --stdin <$play/updates + exit 0 +} + case "$#.$1" in 2.edit|2.done) mode="$1"; arg="$2" ;; -2.-*) fail "no options understood" ;; -*) fail "usage: tartree-edit edit|done DIRECTORY" ;; +3.gitfetchinfo) mode="$1"; arg="$2"; remote="$3" ;; +3.gitfetchinfo-diff) gitfetchdiff diff "$2" "$3" ;; +3.gitfetchinfo-merge) gitfetchdiff merge "$2" "$3" ;; +?.-*) fail "no options understood" ;; +*) fail "usage: + tartree-edit edit|done DIRECTORY|TARBALL + tartree-edit gitfetchinfo DIRECTORY|TARBALL REMOTE + tartree-edit gitfetchinfo-merge REMOTE-A REMOTE-B" ;; + # we don't document gitfetchinfo-diff because it's rather poor esac case "$arg" in @@ -39,6 +103,83 @@ tryat_edit () { fi } +gitfetchinfo_perhaps_commit () { + local m="$1" + set +e + git diff --cached --quiet --exit-code HEAD + local rc=$? + set -e + case "$rc" in + 0) return ;; + 1) git commit --allow-empty --author='tartree-edit <>' -m "$m" ;; + *) fail "git diff failed ($rc)" ;; + esac +} + +tryat_gitfetchinfo () { + git_manip_play + + if test -d "$b.edit"; then + cp -a "$b.edit"/. "$play"/. + else + exec 3<"$b.tar" + tar -C $play -f - <&3 -x + exec 3<&- + fi + + local innerwd; innerwd="$(echo $play/*)" + + git for-each-ref --format='%(refname)' refs/remotes >$play/l + perl -w -ne ' + our %remerge; + use strict; + chomp; + next unless m#^refs/remotes/([^/]+)/#; + my $old = $_; + my $ab = $1; + my $rhs = $'\''; + my @ab = split /\+/, $ab; + next unless @ab == 2; + next unless (grep { $_ eq "'"$remote"'" } @ab) == 1; + $remerge{"@ab"} = 1; + print "update refs/remotes/$_/$rhs $old\n" or die $! foreach @ab; + print "delete $old\n" or die $!; + END { + open REMERGE, ">&3" or die $!; + print REMERGE "$_\n" or die $! foreach sort keys %remerge; + close REMERGE or die $!; + } + ' <$play/l >$play/unmerge 3>$play/remerge + git update-ref --stdin <$play/unmerge + + git remote remove "$remote" 2>/dev/null ||: + git remote add "$remote" $innerwd + git fetch --no-tags -p "$remote" \ + +"HEAD:refs/remotes/$remote/TT-HEAD" + cd $innerwd + GIT_AUTHOR_DATE=$(git log -n1 --pretty=format:'%ai') + GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE + git checkout -b WORKTREE + gitfetchinfo_perhaps_commit 'UNCOMMITTED INDEX' + git add -Af . + gitfetchinfo_perhaps_commit 'UNCOMMITTED WORKING TREE' + cd ../../.. + git fetch --no-tags "$remote" --refmap \ + +"refs/*:refs/remotes/$remote/*" \ + +"refs/*:refs/remotes/$remote/*" + + exec 3<$play/remerge + # $play will be destroyed by what follows, but we have + # an fd open onto remerge, so this will work + while read <&3 a b; do + echo "Updating gitfetchinfo-merge $a $b" + "$0" gitfetchinfo-merge $a $b + done + + exit 0 +} + tryat_done () { local b="$1" if test -d "$b.edit"; then