From a5599ba96059d45719413148b09f345a3ccaeed9 Mon Sep 17 00:00:00 2001 From: Stephen Haberman Date: Wed, 20 Aug 2008 17:52:48 -0500 Subject: [PATCH] Handle double posting when multiple branches are pointing to the same commit. --- cbas/post-receive | 5 ++ server/functions | 32 ++++++++++ server/post-receive-email | 18 ++++-- server/post-receive-trac | 13 ++-- tests/t2202-2.txt | 2 +- tests/t2202-3.txt | 20 ++++++ tests/t2202-4.txt | 35 +++++++++++ ...2202-server-post-receive-email-branches.sh | 28 +++++++++ tests/t3000-server-post-receive-trac.sh | 63 +++++++++++++++++++ 9 files changed, 201 insertions(+), 15 deletions(-) create mode 100644 server/functions create mode 100644 tests/t2202-3.txt create mode 100644 tests/t2202-4.txt create mode 100644 tests/t3000-server-post-receive-trac.sh diff --git a/cbas/post-receive b/cbas/post-receive index 8c24392..18b97f1 100755 --- a/cbas/post-receive +++ b/cbas/post-receive @@ -9,6 +9,11 @@ while read newref oldref refname ; do input="$input$newref $oldref $refname$nl" done +export LD_LIBRARY_PATH=/home/BIPFS/shaberman/local/lib +export PYTHON=/home/BIPFS/shaberman/local/bin/python +export POST_RECEIVE_TRAC=/srv/git/hooks/server/post-receive-trac.py +export TRAC_ENV=/srv/trac/cbas + echo -n "$input" | sh /srv/git/hooks/server/post-receive-email echo -n "$input" | sh /srv/git/hooks/server/post-receive-trac echo -n "$input" | sh /srv/git/hooks/server/post-receive-git-config diff --git a/server/functions b/server/functions new file mode 100644 index 0000000..533bbd5 --- /dev/null +++ b/server/functions @@ -0,0 +1,32 @@ +#!/bin/sh + +# Sets: new_commits +# Assumes: $oldrev, $newrev, and $refname +# +# This is for use in post receive hooks, as it assumes the refname has moved and +# is now newrev, we need to discard it. This is down with bash string replace, +# as it will replace only the first match, compared to the canonical "grep -v" +# approach which will throw out multiple matches if the same commit is referred +# to by multiple branches. +function set_new_commits() { + nl=$'\n' + + # Get all the current branches, not'd as we want only new ones + new_commits=$(git rev-parse --not --branches) + + # Strip off the not current branch + new_hash=$(git rev-parse $refname) + new_commits=${new_commits/^$new_hash/} + + # Put back newrev without the not + new_commits=${new_commits}${nl}${newrev} + + # Put in ^oldrev if it's not a new branch + if [ "$oldrev" != "0000000000000000000000000000000000000000" ] ; then + new_commits=${new_commits}${nl}^${oldrev} + fi + + new_commits=${new_commits/$nl$nl/$nl} + new_commits=${new_commits/#$nl/} +} + diff --git a/server/post-receive-email b/server/post-receive-email index 0f5ef61..26253cf 100755 --- a/server/post-receive-email +++ b/server/post-receive-email @@ -45,6 +45,8 @@ # ---------------------------- Functions +. $(dirname $0)/functions + # # Top level email generation function. This decides what type of update # this is and calls the appropriate body-generation routine after outputting @@ -222,13 +224,18 @@ generate_create_branch_email() # ref that were previously not accessible # (see generate_update_branch_email for the explanation of this # command) - git rev-parse --not --branches | grep -v $(git rev-parse $refname) | git rev-list --pretty --reverse --stdin $newrev + + set_new_commits + echo "$new_commits" | git rev-list --pretty --reverse --stdin echo $LOGEND echo "" echo "Summary of changes:" - oldest_new=$(git rev-parse --not --branches | grep -v $(git rev-parse $refname) | git rev-list --stdin $newrev | tail -n 1) - git diff-tree --stat -p $oldest_new^..$newrev + + oldest_new=$(echo "$new_commits" | git rev-list --stdin | tail -n 1) + if [ "$oldest_new" != "" ] ; then + git diff-tree --stat -p $oldest_new^..$newrev + fi } # @@ -387,8 +394,9 @@ generate_update_branch_email() echo "" echo $LOGBEGIN - git rev-parse --not --branches | grep -v $(git rev-parse $refname) | - git rev-list --reverse --pretty --stdin $oldrev..$newrev + + set_new_commits + echo "$new_commits" | git rev-list --reverse --pretty --stdin # XXX: Need a way of detecting whether git rev-list actually # outputted anything, so that we can issue a "no new diff --git a/server/post-receive-trac b/server/post-receive-trac index 11f5ac7..828da27 100644 --- a/server/post-receive-trac +++ b/server/post-receive-trac @@ -1,16 +1,11 @@ #!/bin/sh -export LD_LIBRARY_PATH=/home/BIPFS/shaberman/local/lib -TRAC_ENV=/srv/trac/cbas +. $(dirname $0)/functions while read oldrev newrev refname ; do - if expr "$oldrev" : '0*$' >/dev/null - then - git rev-parse --not --branches | grep -v $(git rev-parse $refname) | git rev-list --reverse --stdin $newrev - else - git rev-parse --not --branches | grep -v $(git rev-parse $refname) | git rev-list --reverse --stdin $oldrev..$newrev - fi | while read commit ; do - /home/BIPFS/shaberman/local/bin/python /srv/git/hooks/server/post-receive-trac.py "$TRAC_ENV" "$commit" + set_new_commits + echo "$new_commits" | git rev-list --reverse --stdin | while read commit ; do + "$PYTHON" "$POST_RECEIVE_TRAC" "$TRAC_ENV" "$commit" done done diff --git a/tests/t2202-2.txt b/tests/t2202-2.txt index 6ad6464..d556be0 100644 --- a/tests/t2202-2.txt +++ b/tests/t2202-2.txt @@ -10,7 +10,7 @@ The branch, topic has been deleted was $old_commit_hash ----------------------------------------------------------------------- -$old_commit_hash create branch on topic 2 +$old_commit_hash update branch with existing commits does not replay them on topic ----------------------------------------------------------------------- diff --git a/tests/t2202-3.txt b/tests/t2202-3.txt new file mode 100644 index 0000000..27c82d7 --- /dev/null +++ b/tests/t2202-3.txt @@ -0,0 +1,20 @@ +From: author@payflex.com +To: commits@list.com +Subject: [cbas] topic2 branch created. $existing_commit_hash +X-Git-Refname: refs/heads/topic2 +X-Git-Reftype: branch +X-Git-Oldrev: 0000000000000000000000000000000000000000 +X-Git-Newrev: $existing_commit_hash + +The branch, topic2 has been created + at $existing_commit_hash (commit) + +- Log ----------------------------------------------------------------- +----------------------------------------------------------------------- + +Summary of changes: + + +hooks/post-receive +-- +cbas diff --git a/tests/t2202-4.txt b/tests/t2202-4.txt new file mode 100644 index 0000000..02a5d66 --- /dev/null +++ b/tests/t2202-4.txt @@ -0,0 +1,35 @@ +From: author@payflex.com +To: commits@list.com +Subject: [cbas] topic branch updated. $existing_commit_hash +X-Git-Refname: refs/heads/topic +X-Git-Reftype: branch +X-Git-Oldrev: $old_commit_hash +X-Git-Newrev: $existing_commit_hash + +The branch, topic has been updated + via $existing_commit_hash (commit) + from $old_commit_hash (commit) + +Those revisions listed above that are new to this repository have +not appeared on any other notification email; so we list those +revisions in full, below. + +- Log ----------------------------------------------------------------- +----------------------------------------------------------------------- + +Summary of changes: + a | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/a b/a +index 8516a40..5c0be09 100644 +--- a/a ++++ b/a +@@ -1 +1 @@ +-create branch 2 ++update branch with existing commits does not replay them + + +hooks/post-receive +-- +cbas diff --git a/tests/t2202-server-post-receive-email-branches.sh b/tests/t2202-server-post-receive-email-branches.sh index b6b8f16..b98c37e 100644 --- a/tests/t2202-server-post-receive-email-branches.sh +++ b/tests/t2202-server-post-receive-email-branches.sh @@ -41,6 +41,34 @@ test_expect_success 'create branch' ' test_cmp 1.txt server/.git/refs.heads.topic.out ' +test_expect_success 'create branch with existing commits does not replay them' ' + git checkout -b topic2 topic && + existing_commit_hash=$(git rev-parse HEAD) && + existing_commit_date=$(git log -n 1 --pretty=format:%cd HEAD) && + + git push origin topic2 && + + interpolate ../t2202-3.txt 3.txt existing_commit_hash existing_commit_date && + test_cmp 3.txt server/.git/refs.heads.topic2.out +' + +test_expect_success 'update branch with existing commits does not replay them' ' + # Put a commit on topic2, then fast foward topic to it + git checkout topic2 && + echo "$test_name" >a && + git commit -a -m "$test_name on topic" && + git push && + + git checkout topic && + old_commit_hash=$(git rev-parse HEAD) && + git merge topic2 && + existing_commit_hash=$(git rev-parse HEAD) && + git push && + + interpolate ../t2202-4.txt 4.txt old_commit_hash existing_commit_hash && + test_cmp 4.txt server/.git/refs.heads.topic.out +' + test_expect_success 'delete branch' ' old_commit_hash=$(git rev-parse HEAD) && git push origin :refs/heads/topic && diff --git a/tests/t3000-server-post-receive-trac.sh b/tests/t3000-server-post-receive-trac.sh new file mode 100644 index 0000000..38e4262 --- /dev/null +++ b/tests/t3000-server-post-receive-trac.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +test_description='server update lock check' + +. ./test-lib.sh + +export PYTHON=echo +export POST_RECEIVE_TRAC=/foo/post-receive-trac.py +export TRAC_ENV=/foo/trac + +test_expect_success 'setup' ' + echo "setup" >a && + git add a && + git commit -m "setup" && + git clone ./. server && + rm -fr server/.git/hooks && + git remote add origin ./server +' + +install_post_receive_hook 'post-receive-trac' + +test_expect_success 'new branch' ' + git checkout -b topic1 master && + echo "$test_name" >a && + git commit -a -m "changed on topic1" && + new_commit_hash=$(git rev-parse HEAD) && + git push origin topic1 2>push.err && + cat push.err | grep "/foo/post-receive-trac.py /foo/trac $new_commit_hash" +' + +test_expect_success 'new branch with already existing does not double tap' ' + git checkout -b topic2 topic1 && + existing_commit_hash=$(git rev-parse HEAD) && + git push origin topic2 2>push.err && + ! cat push.err | grep "/foo/post-receive-trac.py /foo/trac $existing_commit_hash" +' + +test_expect_success 'update branch' ' + # Already on topic2 + echo "$test_name" >a && + git commit -a -m "changed on topic2" && + new_commit_hash=$(git rev-parse HEAD) && + git push origin topic2 2>push.err && + cat push.err | grep "/foo/post-receive-trac.py /foo/trac $new_commit_hash" +' + +test_expect_success 'update branch to an already published commit does not double tap' ' + # Make topic1 catch up to topic2, which will be a fast forward that does need re-tapped + git checkout topic2 && + topic2_hash=$(git rev-parse HEAD) && + + git checkout topic1 && + git merge topic2 && + topic1_hash=$(git rev-parse HEAD) && + + git push 2>push.err && + + ! cat push.err | grep "/foo/post-receive-trac.py /foo/trac $topic2_hash" + ! cat push.err | grep "/foo/post-receive-trac.py /foo/trac $topic1_hash" +' + +test_done + -- 2.39.5