From: Stephen Haberman Date: Mon, 25 Aug 2008 05:33:01 +0000 (-0500) Subject: Proactive refollow. X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f21c2532f990071c271ea3b78e1d6b6b05a951a6;p=git-central.git Proactive refollow. --- diff --git a/scripts/gc-refollow b/scripts/gc-refollow new file mode 100644 index 0000000..35a6369 --- /dev/null +++ b/scripts/gc-refollow @@ -0,0 +1,87 @@ +#!/bin/sh + +# +# Goes through the ensure-follows branches and makes sure +# the non-excused branches have it merged. +# + +die() { + echo >&2 "$@" + exit 1 +} + +attempt_merge() { + source_branch=$1 + remote_branch=$2 + + if [ "$source_branch" == "$remote_branch" ] ; then + return + fi + if [[ $excused =~ " $remote_branch " ]] ; then + return + fi + git branch -r --contains "$source_branch" | grep --quiet "origin/$remote_branch" + if [ $? -eq 0 ] ; then + return + fi + + echo -n "Merging $source_branch into $remote_branch..." + + baserev=$(git merge-base "$source_branch" "origin/$remote_branch") + git read-tree -m --trivial $baserev "origin/$remote_branch" "$source_branch" + if [ $? -ne 0 ] ; then + echo "failed merge" + return + fi + + new_tree=$(git write-tree) + new_commit=$(git commit-tree $new_tree -p "origin/$remote_branch" -p "$source_branch" </dev/null 2>/dev/null + if [ $? -ne 0 ] ; then + echo "failed push" + return + fi + + echo "succeeded" +} + +gitconfig=$(git rev-parse origin/gitconfig) +if [ $? -ne 0 ] ; then + echo "gitconfig branch not found" + exit 1 +fi + +# The source branches +config_hash=$(git ls-tree $gitconfig | grep config | grep -oP '\w{40}') +branches=$(git cat-file blob "$config_hash" | grep hooks.update-ensure-follows.branches) +branches=("${branches#*=}") +excused=$(git cat-file blob "$config_hash" | grep hooks.update-ensure-follows.excused) +excused=" ${excused#*=} " + +# We're going to merge stuff into the index, so make sure it's okay +git diff-index --cached --quiet HEAD -- || die "refusing to refollow--your index is not clean" + +# Get the latest remote refs +git fetch + +# So we can put the index back after we screw with it +original_head=$(git rev-parse HEAD) + +for source_branch in ${branches[@]} ; do + git branch -r | grep -v HEAD | while read line ; do + if [[ "$line" =~ origin/(.*) ]] ; then + attempt_merge $source_branch ${BASH_REMATCH[1]} + fi + done +done + +# Put the index back +git read-tree "$original_head" + diff --git a/tests/t5400-script-refollow.sh b/tests/t5400-script-refollow.sh new file mode 100644 index 0000000..911f177 --- /dev/null +++ b/tests/t5400-script-refollow.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='script refollow' + +. ./test-lib.sh + +export PATH=$PATH:../../scripts + +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 && + git checkout -b stable && + git push origin stable +' + +test_expect_success 'setup gitconfig' ' + make-gitconfig-branch && + git checkout gitconfig && + echo "hooks.update-ensure-follows.branches=stable" >>config && + echo "hooks.update-ensure-follows.excused=master gitconfig" >>config && + git commit -a -m "enable update-ensure-follows" && + git push origin gitconfig +' + +test_expect_success 'make topic1 then move stable' ' + git checkout -b topic1 stable && + echo "$test_name" >a.topic1 && + git add a.topic1 && + git commit -m "$test_name on topic1" && + git push origin topic1 && + + git checkout stable && + echo "$test_name" >a && + git commit -a -m "$test_name on stable" && + git push +' + +test_expect_success 'refollow fails with dirty index' ' + echo "$test_name" >a && + git add a && + ! gc-refollow 2>refollow.err && + cat refollow.err | grep "refusing to refollow--your index is not clean" && + ! git reset a +' + +test_expect_success 'refollow topic1 onto stable' ' + echo "$test_name" >a && + git commit -a -m "move stable" && + git push origin stable && + gc-refollow >refollow.out && + cat refollow.out | grep "Merging stable into topic1...succeeded" + + git checkout topic1 && + git pull origin topic1 && + cat a | grep "$test_name" +' + +test_expect_success 'refollow does not double tap' ' + # Still on topic1 + head=$(git rev-parse HEAD) && + gc-refollow && + git pull origin topic1 && + git rev-parse HEAD | grep $head +' + +test_expect_success 'refollow respects excused' ' + git checkout gitconfig && + head=$(git rev-parse HEAD) && + + git checkout stable && + echo "$test_name" >a && + git commit -a -m "move stable" && + git push origin stable && + + gc-refollow && + + git checkout gitconfig && + git pull origin gitconfig && + git rev-parse HEAD | grep $head +' + +test_expect_success 'refollow continues on conflict' ' + git checkout -b topic2 stable && + echo "$test_name" >a && + git commit -a -m "create topic2" && + git push origin topic2 && + + git checkout stable && + echo "$test_name" >a && + git commit -a -m "move stable" && + git push origin stable && + + gc-refollow > refollow.out && + cat refollow.out | grep "Merging stable into topic1...succeeded" + cat refollow.out | grep "Merging stable into topic2...failed merge" +' + +test_done +