From 2f7355d8b215c7e4be731c98e513fc70090b94ad Mon Sep 17 00:00:00 2001 From: Stephen Haberman Date: Thu, 28 Aug 2008 11:03:58 -0500 Subject: [PATCH] Better tattoo. --- scripts/gc-tattoo | 93 +++++++++++++------ server/update-stable | 12 +++ tests/t2102-server-update-stable-candidate.sh | 21 ++++- tests/t5500-script-tattoo.sh | 72 ++++++++------ 4 files changed, 143 insertions(+), 55 deletions(-) diff --git a/scripts/gc-tattoo b/scripts/gc-tattoo index 7ad1e54..8244c04 100644 --- a/scripts/gc-tattoo +++ b/scripts/gc-tattoo @@ -1,40 +1,79 @@ #!/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 diff --git a/server/update-stable b/server/update-stable index 020cd90..c816750 100644 --- a/server/update-stable +++ b/server/update-stable @@ -81,6 +81,18 @@ if [ "$change_type" != "update" ] ; then 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 diff --git a/tests/t2102-server-update-stable-candidate.sh b/tests/t2102-server-update-stable-candidate.sh index 8a5711d..c62391d 100644 --- a/tests/t2102-server-update-stable-candidate.sh +++ b/tests/t2102-server-update-stable-candidate.sh @@ -82,13 +82,30 @@ test_expect_success 'topic1 cannot be changed' ' # 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 diff --git a/tests/t5500-script-tattoo.sh b/tests/t5500-script-tattoo.sh index 7352183..bab6dd2 100644 --- a/tests/t5500-script-tattoo.sh +++ b/tests/t5500-script-tattoo.sh @@ -17,61 +17,81 @@ test_expect_success 'setup' ' 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 -- 2.39.5