#!/bin/sh
head=$(git rev-parse HEAD)
-branch=$(git symbolic-ref --quiet HEAD)
+
+# Watch out for the very first commit in the repo because we use head^ later
+git rev-parse --verify --quiet "$head^" >/dev/null
if [ $? -ne 0 ] ; then
- echo "unknown"
- exit 1
+ echo "0"
+ exit 0
fi
-case "$branch" in
- refs/heads/*)
- branch=${branch##refs/heads/}
- ;;
- *)
- echo "unknown"
- exit 1
- ;;
-esac
-
-# Ensure pushed
-git branch -r --contains $head | grep --quiet "origin/$branch"
-if [ $? -ne 0 ] ; then
- echo "$branch has not been pushed"
+# A --- B --- C stable
+# |\ /
+# | D ----- E topic1
+# \ /
+# F --- G topic2
+#
+# topic1 stable result
+# D A contains, merge base=A
+# D C contains, merge base=A
+# E A contains, merge base=E
+# E C contains, merge base=A
+
+#
+# * --- * --------- * stable
+# |\ \
+# | A --- B ---- C topic1
+# \ /
+# D --- E --- F topic2
+#
+# F: contains=topic1,topic2
+# C: contains=topic1
+
+contains=($(git branch -r --contains $head))
+if [ ${#contains[@]} -eq 0 ] ; then
+ echo "$head has not been pushed"
exit 1
fi
-# Handle stable special to look for the annotated tag
-if [ "$branch" == "stable" ] ; then
- describe=$(git describe $head 2>/dev/null)
+potential=" "
+for branch in ${contains[@]} ; do
+ branch=${branch##origin/}
+ #echo "branch=$branch"
+
+ # Walk back until we hit a baserev that is not the branch_tip itself (because it was merged)
+ branch_tip=$(git rev-parse origin/$branch)
+ stable_rev=$(git rev-parse origin/stable)
+ stable_base=$(git merge-base "$branch_tip" "$stable_rev")
+
+ # echo "stable_base=$stable_base"
+ while [ "$stable_base" == "$branch_tip" ] ; do
+ stable_rev=$(git rev-parse "${stable_rev}^")
+ stable_base=$(git merge-base "$branch_tip" "$stable_rev")
+ done
+ # echo "stable_base=$stable_base"
+
+ git rev-list --first-parent $stable_base..$branch_tip | grep --quiet "$head"
if [ $? -eq 0 ] ; then
- echo "$describe"
- else
- echo "stable-$head"
+ if [ "$branch" == "stable" ] ; then
+ describe=$(git describe $head 2>/dev/null)
+ if [ $? -eq 0 ] ; then
+ potential="$potential $describe"
+ else
+ potential="$potential stable-$head"
+ fi
+ else
+ number=$(git rev-list --first-parent "$stable_base..$head" | wc -l)
+ potential="$potential $branch-$number"
+ fi
fi
- exit 0
-fi
+done
-number=$(git rev-list --first-parent "$head" ^origin/stable | wc -l)
-echo "$branch-$number"
+potential=($potential)
+if [ ${#potential[@]} -eq 1 ] ; then
+ echo "${potential[0]}"
+else
+ echo "unknown"
+fi
exit 0
fi
+# The tip must always be new
+already=$(git branch --contains "$newrev")
+if [ "$already" != "" ] ; then
+ already=${already## }
+ echo "----------------------------------------------------"
+ echo
+ echo "$short_refname is already referred to by $already"
+ echo
+ echo "----------------------------------------------------"
+ exit 1
+fi
+
if [ "$short_refname" == "stable" ] ; then
# Stable enforcement
# It is already changed but error message should chagne
git checkout topic1 &&
! git push origin topic1 2>push.err &&
- cat push.err | grep "topic1 has been merged into stable"
+ cat push.err | grep "topic1 has been merged into stable" &&
+ git reset --hard HEAD^
'
test_expect_success 'topic3 cannot initially be created on stable' '
git checkout -b topic3 stable &&
! git push origin topic3 2>push.err &&
- cat push.err | grep "Creating a branch must include new commits"
+ cat push.err | grep "Creating a branch must include new commits" &&
+
+ echo "$test_name" >a.topic3 &&
+ git add a.topic3 &&
+ git commit -m "$test_name" &&
+ git push origin topic3
+'
+
+test_expect_success 'topic4 cannot point to the same place as topic4' '
+ git checkout -b topic4 topic3 &&
+ echo "$test_name" >a.topic4 &&
+ git add a.topic4 &&
+ git commit -m "making topic4" &&
+ git push origin topic4 &&
+
+ ! git push origin topic4:topic3 2>push.err &&
+ cat push.err | grep "topic3 is already referred to by topic4"
'
test_done
git push origin stable
'
-test_expect_success 'tattoo 0' '
+# tattoo makes assumptions based on the update stable hook sanity checks
+install_update_hook 'update-stable'
+
+test_expect_success 'tattoo of first commit' '
+ gc-tattoo | grep 0
+'
+
+test_expect_success 'tattoo 1' '
git checkout -b topic1 &&
+ echo "$test_name" >a.topic1 &&
+ git add a.topic1 &&
+ git commit -a -m "move topic1-1" &&
git push origin topic1 &&
- gc-tattoo | grep topic1-0
+ gc-tattoo | grep topic1-1
'
-test_expect_success 'tattoo 1' '
+test_expect_success 'tattoo 2' '
echo "$test_name" >a &&
- git commit -a -m "make topic1-1" &&
+ git commit -a -m "make topic1-2" &&
git push origin topic1 &&
- gc-tattoo | grep topic1-1
+ gc-tattoo | grep topic1-2
'
-test_expect_success 'merge topic2 topic1 as tattoo 2' '
+test_expect_success 'merge topic2 into topic1 as tattoo 3' '
git checkout -b topic2 stable &&
echo "$test_name" >a.topic2 &&
- git add a.topic2
- git commit -m "make topic2" &&
+ git add a.topic2 &&
+ git commit -m "make topic2-1" &&
git push origin topic2 &&
- gc-tattoo | grep topic2-1
+ gc-tattoo | grep topic2-1 &&
git checkout topic1 &&
git merge topic2 &&
git push origin topic1 &&
- gc-tattoo | grep topic1-2
-'
+ gc-tattoo | grep topic1-3 &&
-test_expect_success 'stable without a tag' '
- git checkout stable &&
- head=$(git rev-parse HEAD) &&
- gc-tattoo | grep "stable-$head"
-'
-
-test_expect_success 'stable with a tag' '
- git tag -m "1.0" 1.0 &&
- gc-tattoo | grep "1.0"
+ git checkout topic2 &&
+ gc-tattoo | grep topic2-1
'
test_expect_success 'fails if not pushed' '
git checkout topic1 &&
echo "$test_name" >a &&
- git commit -a -m "make topic1-3" &&
- gc-tattoo | grep "topic1 has not been pushed"
+ git commit -a -m "make topic1-4" &&
+ head=$(git rev-parse HEAD) &&
+ gc-tattoo | grep "$head has not been pushed" &&
+ git push origin topic1 &&
+ gc-tattoo | grep topic1-4
'
test_expect_success 'stable fails if not pushed' '
git checkout stable &&
git merge --no-ff topic1 &&
- gc-tattoo | grep "stable has not been pushed"
+ head=$(git rev-parse HEAD) &&
+ gc-tattoo | grep "$head has not been pushed" &&
+ git push &&
+ gc-tattoo | grep "stable-$head"
+'
+
+test_expect_success 'stable without a tag' '
+ git checkout stable &&
+ head=$(git rev-parse HEAD) &&
+ gc-tattoo | grep "stable-$head"
+'
+
+test_expect_success 'stable with a tag' '
+ git tag -m "1.0" 1.0 &&
+ gc-tattoo | grep "1.0"
'
test_expect_success 'use origin stable not local' '
- git checkout topic1 &&
- git push origin topic1 &&
- gc-tattoo | grep "topic1-3"
+ git checkout origin/stable &&
+ git branch -d stable &&
+ git checkout topic2 &&
+ gc-tattoo | grep "topic2-1"
'
test_done