Set u+x on scripts.
[git-central.git] / scripts / refollow
1 #!/bin/sh
2
3 #
4 # Goes through the ensure-follows branches and makes sure
5 # the non-excused branches have it merged.
6 #
7
8 die() {
9         echo >&2 "$@"
10         exit 1
11 }
12
13 attempt_merge() {
14         source_branch=$1
15         remote_branch=$2
16
17         if [ "$source_branch" == "$remote_branch" ] ; then
18                 return
19         fi
20         if [[ $excused =~ " $remote_branch " ]] ; then
21                 return
22         fi
23         git branch -r --contains "$source_branch" | grep --quiet "origin/$remote_branch"
24         if [ $? -eq 0 ] ; then
25                 return
26         fi
27
28         echo -n "Merging $source_branch into $remote_branch..."
29
30         baserev=$(git merge-base "$source_branch" "origin/$remote_branch")
31         git read-tree -m --trivial $baserev "origin/$remote_branch" "$source_branch"
32         if [ $? -ne 0 ] ; then
33                 echo "failed merge"
34                 return
35         fi
36
37         new_tree=$(git write-tree)
38         new_commit=$(git commit-tree $new_tree -p "origin/$remote_branch" -p "$source_branch" <<FOO
39 Merge $source_branch into $remote_branch
40 FOO)
41         if [ "$new_commit" == "" ] ; then
42                 echo "failed commit"
43                 return
44         fi
45
46         git push origin "$new_commit:$remote_branch" >/dev/null 2>/dev/null
47         if [ $? -ne 0 ] ; then
48                 echo "failed push"
49                 return
50         fi
51
52         echo "succeeded"
53 }
54
55 gitconfig=$(git rev-parse origin/gitconfig)
56 if [ $? -ne 0 ] ; then
57         echo "gitconfig branch not found"
58         exit 1
59 fi
60
61 # The source branches
62 config_hash=$(git ls-tree $gitconfig | grep config | grep -oP '\w{40}')
63 branches=$(git cat-file blob "$config_hash" | grep hooks.update-ensure-follows.branches)
64 branches=("${branches#*=}")
65 excused=$(git cat-file blob "$config_hash" | grep hooks.update-ensure-follows.excused)
66 excused=" ${excused#*=} "
67
68 # We're going to merge stuff into the index, so make sure it's okay
69 git diff-index --cached --quiet HEAD -- || die "refusing to refollow--your index is not clean"
70
71 # Get the latest remote refs
72 git fetch
73
74 # So we can put the index back after we screw with it
75 original_head=$(git rev-parse HEAD)
76
77 for source_branch in ${branches[@]} ; do
78         git branch -r | grep -v HEAD | while read line ; do
79                 if [[ "$line" =~ origin/(.*) ]] ; then
80                         attempt_merge $source_branch ${BASH_REMATCH[1]}
81                 fi
82         done
83 done
84
85 # Put the index back
86 git read-tree "$original_head"
87