]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/git/arcgit
MFV: r357927
[FreeBSD/FreeBSD.git] / tools / tools / git / arcgit
1 #!/bin/sh
2 #
3 # Copyright (c) 2015 Ryan Stone. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13 #
14 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 # SUCH DAMAGE.
25 #
26 # $FreeBSD$
27
28 # This script is used to submit a series of git commits to Differential.  Each
29 # commit is submitted as a separate review.  For each review, this script will
30 # create a branch called review_DXXXX (e.g. review_D2185 for Differential
31 # revision D2185).  When you need to make a change to a review, checkout the
32 # review_D2185 branch, commit your change with "git commit --fixup HEAD".  To\
33 # upload the change to Differential, use the command:
34 #   $ arc diff --update D2185 review_D2185_base
35 #
36 # When your reviews are complete, merge all of the review_DXXXX branches
37 # together, and then do a git rebase -ik to meld the code review fixes into the
38 # commit that they fixed.  Now you have a clean series of patches to commit to
39 # svn.
40
41 usage()
42 {
43         echo "Usage: arcgit <-c commit | -r commit1~..commit2> [-R reviewer] " >&2
44         echo "       [-C subscriber] [-T testplan] [-n]" >&2
45 }
46
47 error()
48 {
49         echo "$@" >&2
50         usage
51         rm -f $phab_before $phab_after $arc_msg
52         exit 1
53 }
54
55 create_review()
56 {
57         local commit phab_id arc_dir
58         unset phab_before phab_after arc_msg
59         commit=$1
60
61         phab_before=`mktemp -t arcoutput`
62         phab_after=`mktemp -t arcoutput`
63         echo "Create review for '`git show $commit -s --oneline`'"
64
65         if [ -n "$dry_run" ]
66         then
67                 return
68         fi
69
70         git checkout $commit > /dev/null || error "Could not checkout $commit"
71
72         arc_dir="$(git rev-parse --git-dir)/arc"
73         arc_msg="$arc_dir/create-message"
74         mkdir -p $arc_dir
75         git show -s --format='%B' HEAD > $arc_msg
76         echo >> $arc_msg
77         echo "Test Plan:" >> $arc_msg
78         cat $test_plan >> $arc_msg
79         echo >> $arc_msg
80         echo "Reviewers:" >> $arc_msg
81         echo "$reviewers" >> $arc_msg
82         echo >> $arc_msg
83         echo "Subscribers:" >> $arc_msg
84         echo "$cc_list" >> $arc_msg
85         echo >> $arc_msg
86
87         arc list > $phab_before
88         yes | env EDITOR=true arc diff --create --allow-untracked HEAD~
89         arc list > $phab_after
90
91         headline="$(git show $commit -s --format=%s)"
92         phab_id=`comm -13 "$phab_before" "$phab_after" | fgrep "$headline" \
93             | egrep -o 'D[0-9]+:' | tr -d ':'`
94
95         if [ -z "$phab_id" ]
96         then
97                 error "Could not get review ID"
98         fi
99
100         git branch review_${phab_id}_base HEAD~
101
102         git checkout -b review_$phab_id
103         cat - <<EOF | git commit --allow-empty -F -
104 squash! $headline
105
106 Differential Revision:  https://reviews.freebsd.org/$phab_id
107 Reviewed by:
108 EOF
109 }
110
111 unset range test_plan reviewers cc_list dry_run
112
113 while getopts ":c:C:nr:R:T:" o
114 do
115         case "$o" in
116         c)
117                 range="${OPTARG}~..${OPTARG}"
118                 ;;
119         C)
120                 if [ -z "$cc_list" ]
121                 then
122                         cc_list="$OPTARG"
123                 else
124                         cc_list="$cc_list, $OPTARG"
125                 fi
126                 ;;
127         n)
128                 dry_run=1
129                 ;;
130         r)
131                 range=$OPTARG
132                 ;;
133         R)
134                 if [ -z "$reviewers" ]
135                 then
136                         reviewers="$OPTARG"
137                 else
138                         reviewers="$reviewers, $OPTARG"
139                 fi
140                 ;;
141         T)
142                 test_plan=$OPTARG
143                 ;;
144         *)
145                 error "Unrecognized argument '-$OPTARG'"
146         esac
147 done
148
149 shift $((OPTIND - 1))
150 OPTIND=1
151
152 if [ -n "$1" ]
153 then
154         error "Unrecognized argument $1"
155 fi
156
157 if [ -z "$range" ]
158 then
159         error "-c or -r argument is mandatory"
160 fi
161
162 if [ -n "$test_plan" -a ! -r "$test_plan" ]
163 then
164         error "$test_plan is not readable"
165 fi
166
167 if ! type git > /dev/null 2> /dev/null
168 then
169         error "Install devel/git first"
170 fi
171
172 if ! type arc > /dev/null 2> /dev/null
173 then
174         error "Install devel/arcanist first"
175 fi
176
177 git update-index -q --refresh
178 if ! git diff-index --quiet --cached HEAD
179 then
180         error "index is unclean"
181 fi
182
183 if ! git diff-files --quiet
184 then
185         error "Working directory is unclean"
186 fi
187
188 if git ls-files --other --error-unmatch . > /dev/null 2> /dev/null
189 then
190         error "Working directory contains untracked files"
191 fi
192
193 # We have to do a git checkout in order to run arc, so save the original branch
194 # so that we can check it out again once we're done.
195 if ! orig_branch=$(git symbolic-ref --short -q HEAD)
196 then
197         orig_branch=$(git show -s --pretty='%H' HEAD)
198 fi
199
200 git log --format=%H $range | tail -r | while read -r commit
201 do
202         create_review $commit < /dev/null
203 done
204
205 # Note that due to the use of the pipeline above, the body of the while loop
206 # above runs in a subshell.  If it exits with an error, execution resumes
207 # here rather than exiting the script, so we have to cache the right exit code
208 # and return it when we're done cleaning up.
209 code=$?
210
211 git checkout $orig_branch
212
213 exit $code
214