Handle double posting when multiple branches are pointing to the same commit.
authorStephen Haberman <stephen@exigencecorp.com>
Wed, 20 Aug 2008 22:52:48 +0000 (17:52 -0500)
committerStephen Haberman <stephen@exigencecorp.com>
Wed, 20 Aug 2008 22:52:48 +0000 (17:52 -0500)
cbas/post-receive
server/functions [new file with mode: 0644]
server/post-receive-email
server/post-receive-trac
tests/t2202-2.txt
tests/t2202-3.txt [new file with mode: 0644]
tests/t2202-4.txt [new file with mode: 0644]
tests/t2202-server-post-receive-email-branches.sh
tests/t3000-server-post-receive-trac.sh [new file with mode: 0644]

index 8c24392..18b97f1 100755 (executable)
@@ -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 (file)
index 0000000..533bbd5
--- /dev/null
@@ -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/}
+}
+
index 0f5ef61..26253cf 100755 (executable)
@@ -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
index 11f5ac7..828da27 100644 (file)
@@ -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
 
index 6ad6464..d556be0 100644 (file)
@@ -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 (file)
index 0000000..27c82d7
--- /dev/null
@@ -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 (file)
index 0000000..02a5d66
--- /dev/null
@@ -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
index b6b8f16..b98c37e 100644 (file)
@@ -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 (file)
index 0000000..38e4262
--- /dev/null
@@ -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
+