From db912f569002e00ab208346e9d5a5fe311e7b591 Mon Sep 17 00:00:00 2001 From: Stephen Haberman Date: Sun, 24 Aug 2008 16:31:11 -0500 Subject: [PATCH] Upgrade update-stable to enforce candidate/topic as well. For now we're still doing the topic is locked upon candidate creation. I'd still prefer remerging. --- server/update-stable | 137 ++++++++++++------ tests/t2102-server-update-stable-candidate.sh | 89 ++++++++++++ 2 files changed, 180 insertions(+), 46 deletions(-) create mode 100644 tests/t2102-server-update-stable-candidate.sh diff --git a/server/update-stable b/server/update-stable index 6c89e51..fb1a8e6 100644 --- a/server/update-stable +++ b/server/update-stable @@ -1,10 +1,18 @@ #!/bin/sh # -# This enforces stable only moving in the approved way, which -# is via empty (no change) merge commits. The rationale is that -# in the DAG we want a simple, one-commit move from each release -# to the next. +# This enforces stable/candidate/topic patterns. +# +# Specifically: +# +# * stable must be moved 1 merge commit at a time (see below) +# * candidates/topics are frozen once merged into stable +# * topics are frozen once merged into candidates +# +# For DAG aesthetics, we prefer stable only moving in the approved way, +# which is via empty (no change) merge commits. The rationale is that +# in the DAG we want a simple, one-commit move from each release to the +# next. # # We started out with: # @@ -40,56 +48,93 @@ refname="$1" oldrev="$2" newrev="$3" -if expr "$oldrev" : '0*$' >/dev/null ; then +. $(dirname $0)/functions +set_change_type + +if [[ "$refname" =~ refs/heads/(.*) ]] ; then + short_refname=${refname##refs/heads/} +else exit 0 fi -if [ "$refname" != "refs/heads/stable" ] ; then +# create/delete is okay +if [ "$change_type" != "update" ] ; then exit 0 fi -# read backwards: -# - all commits from old..new -# - unless they were already pointed to by a branch -# = all new commits on stable -count=$(git rev-parse --not --branches | git rev-list --stdin $oldrev..$newrev | wc -l) -if [ "$count" -ne "1" ] ; then - echo "----------------------------------------------------" - echo - echo "Moving stable must entail a single commit" - echo - echo "----------------------------------------------------" - exit 1 -fi +if [ "$short_refname" == "stable" ] ; then + # Stable enforcement -number_of_parents=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | wc -l) -if [ "$number_of_parents" -ne "2" ] ; then - echo "----------------------------------------------------" - echo - echo "Moving stable must entail a merge commit" - echo - echo "----------------------------------------------------" - exit 1 -fi + # read backwards: + # - all commits from old..new + # - unless they were already pointed to by a branch + # = all new commits on stable + count=$(git rev-parse --not --branches | git rev-list --stdin $oldrev..$newrev | wc -l) + if [ "$count" -ne "1" ] ; then + echo "----------------------------------------------------" + echo + echo "Moving stable must entail a single commit" + echo + echo "----------------------------------------------------" + exit 1 + fi -first_parent=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | head --lines=1) -if [ "$first_parent" != "$oldrev" ] ; then - echo "----------------------------------------------------" - echo - echo "Moving stable must have the previous stable as the first parent" - echo - echo "----------------------------------------------------" - exit 1 -fi + number_of_parents=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | wc -l) + if [ "$number_of_parents" -ne "2" ] ; then + echo "----------------------------------------------------" + echo + echo "Moving stable must entail a merge commit" + echo + echo "----------------------------------------------------" + exit 1 + fi + + first_parent=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | head --lines=1) + if [ "$first_parent" != "$oldrev" ] ; then + echo "----------------------------------------------------" + echo + echo "Moving stable must have the previous stable as the first parent" + echo + echo "----------------------------------------------------" + exit 1 + fi + + second_parent=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | tail --lines=1) + changed_lines=$(git diff $second_parent..$newrev | wc -l) + if [ "$changed_lines" -ne "0" ] ; then + echo "----------------------------------------------------" + echo + echo "Moving stable must not result in any changes from $second_parent" + echo + echo "----------------------------------------------------" + exit 1 + fi +else + # Check if candidate/topic is already in stable + git branch --contains "$oldrev" | grep stable >/dev/null + if [ $? -eq 0 ] ; then + echo "----------------------------------------------------" + echo + echo "$short_refname has been merged into stable" + echo + echo "----------------------------------------------------" + exit 1 + fi + + # For now candidates can mix amongst each other so early exit + if [[ "$refname" =~ refs/heads/candidate(.*) ]] ; then + exit 0 + fi -second_parent=$(git rev-list --no-walk --parents $newrev | sed 's/ /\n/g' | grep -v $newrev | tail --lines=1) -changed_lines=$(git diff $second_parent..$newrev | wc -l) -if [ "$changed_lines" -ne "0" ] ; then - echo "----------------------------------------------------" - echo - echo "Moving stable must not result in any changes from $second_parent" - echo - echo "----------------------------------------------------" - exit 1 + # Check if topic is already in candidates + candidate=$(git branch --contains "$oldrev" | grep -oP candidate.* --max-count=1) + if [ $? -eq 0 ] ; then + echo "----------------------------------------------------" + echo + echo "$short_refname has been merged into $candidate" + echo + echo "----------------------------------------------------" + exit 1 + fi fi diff --git a/tests/t2102-server-update-stable-candidate.sh b/tests/t2102-server-update-stable-candidate.sh new file mode 100644 index 0000000..45f1782 --- /dev/null +++ b/tests/t2102-server-update-stable-candidate.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +test_description='server update candidate enforcer' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo setup >a && + git add a && + git commit -m "a" && + git clone ./. server && + git remote add origin ./server && + rm -fr server/.git/hooks +' + +# setup the update hook +install_update_hook 'update-stable' + +test_expect_success 'initial stable commit works' ' + # do one stable-less commit + echo $test_name >a && + git commit -a -m "$test_name" && + git push origin master && + + git checkout -b stable && + git push origin stable && + git config --add branch.stable.remote origin && + git config --add branch.stable.merge refs/heads/stable +' + +test_expect_success 'create topic1 and topic2' ' + git checkout -b topic1 stable && + echo "$test_name topic1" >a.topic1 && + git add a.topic1 && + git commit -m "start topic1" && + + git checkout -b topic2 stable && + echo "$test_name topic2" >a.topic2 && + git add a.topic2 && + git commit -m "start topic2" && + + git push origin topic2 topic1 +' + +test_expect_success 'create candidate1' ' + git checkout -b candidate1 stable && + git merge topic1 topic2 && + git push origin candidate1 +' + +test_expect_success 'topic1 cannot be changed' ' + git checkout topic1 && + echo "$test_name" >a.topic1 && + git commit -a -m "$test_name" && + ! git push origin topic1 2>push.err && + cat push.err | grep "topic1 has been merged into candidate1" +' + +test_expect_success 'candidate1 can be changed' ' + git checkout candidate1 && + echo "$test_name" >a.topic1 && + git commit -a -m "$test_name" && + git push origin candidate1 +' + +test_expect_success 'merge candidate into stable' ' + git checkout stable && + git merge candidate1 --no-ff && + git push origin stable +' + +test_expect_success 'candidate cannot be changed' ' + git checkout candidate1 && + echo "$test_name" >a.topic1 && + git commit -a -m "$test_name" && + ! git push origin candidate1 2>push.err && + cat push.err | grep "candidate1 has been merged into stable" + ! cat push.err | grep "candidate1 has been merged into candidate1" +' + +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" +' + +test_done + -- 2.20.1