root / devel / review @ 1a732a74
History | View | Annotate | Download (4.6 kB)
1 | 42c067b7 | Michael Hanselmann | #!/bin/bash |
---|---|---|---|
2 | 42c067b7 | Michael Hanselmann | |
3 | 42c067b7 | Michael Hanselmann | # Copyright (C) 2009 Google Inc. |
4 | 42c067b7 | Michael Hanselmann | # |
5 | 42c067b7 | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify |
6 | 42c067b7 | Michael Hanselmann | # it under the terms of the GNU General Public License as published by |
7 | 42c067b7 | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or |
8 | 42c067b7 | Michael Hanselmann | # (at your option) any later version. |
9 | 42c067b7 | Michael Hanselmann | # |
10 | 42c067b7 | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but |
11 | 42c067b7 | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | 42c067b7 | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | 42c067b7 | Michael Hanselmann | # General Public License for more details. |
14 | 42c067b7 | Michael Hanselmann | # |
15 | 42c067b7 | Michael Hanselmann | # You should have received a copy of the GNU General Public License |
16 | 42c067b7 | Michael Hanselmann | # along with this program; if not, write to the Free Software |
17 | 42c067b7 | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | 42c067b7 | Michael Hanselmann | # 02110-1301, USA. |
19 | 42c067b7 | Michael Hanselmann | |
20 | 42c067b7 | Michael Hanselmann | # To set user mappings, use this command: |
21 | 926feaf1 | Manuel Franceschini | # git config gnt-review.johndoe 'John Doe <johndoe@example.com>' |
22 | 42c067b7 | Michael Hanselmann | |
23 | c69a43c8 | Michael Hanselmann | # To disable strict mode (enabled by default): |
24 | c69a43c8 | Michael Hanselmann | # git config gnt-review.strict false |
25 | c69a43c8 | Michael Hanselmann | |
26 | c69a43c8 | Michael Hanselmann | # To enable strict mode: |
27 | c69a43c8 | Michael Hanselmann | # git config gnt-review.strict true |
28 | c69a43c8 | Michael Hanselmann | |
29 | 42c067b7 | Michael Hanselmann | set -e |
30 | 42c067b7 | Michael Hanselmann | |
31 | 42c067b7 | Michael Hanselmann | # Get absolute path to myself |
32 | 42c067b7 | Michael Hanselmann | me_plain="$0" |
33 | 42c067b7 | Michael Hanselmann | me=$(readlink -f "$me_plain") |
34 | 42c067b7 | Michael Hanselmann | |
35 | 42c067b7 | Michael Hanselmann | add_reviewed_by() { |
36 | 42c067b7 | Michael Hanselmann | local msgfile="$1" |
37 | 42c067b7 | Michael Hanselmann | |
38 | 42c067b7 | Michael Hanselmann | grep -q '^Reviewed-by: ' "$msgfile" && return |
39 | 42c067b7 | Michael Hanselmann | |
40 | 42c067b7 | Michael Hanselmann | perl -i -e ' |
41 | d2d66df0 | Klaus Aehlig | my $reviewer = $ENV{"REVIEWER"}; |
42 | d2d66df0 | Klaus Aehlig | defined($reviewer) or $reviewer = ""; |
43 | 42c067b7 | Michael Hanselmann | my $sob = 0; |
44 | 42c067b7 | Michael Hanselmann | while (<>) { |
45 | 42c067b7 | Michael Hanselmann | if ($sob == 0 and m/^Signed-off-by:/) { |
46 | 42c067b7 | Michael Hanselmann | $sob = 1; |
47 | 42c067b7 | Michael Hanselmann | |
48 | 42c067b7 | Michael Hanselmann | } elsif ($sob == 1 and not m/^Signed-off-by:/) { |
49 | d2d66df0 | Klaus Aehlig | print "Reviewed-by: $reviewer\n"; |
50 | 42c067b7 | Michael Hanselmann | $sob = -1; |
51 | 42c067b7 | Michael Hanselmann | } |
52 | 42c067b7 | Michael Hanselmann | |
53 | 42c067b7 | Michael Hanselmann | print; |
54 | 42c067b7 | Michael Hanselmann | } |
55 | 42c067b7 | Michael Hanselmann | |
56 | 42c067b7 | Michael Hanselmann | if ($sob == 1) { |
57 | d2d66df0 | Klaus Aehlig | print "Reviewed-by: $reviewer\n"; |
58 | 42c067b7 | Michael Hanselmann | } |
59 | 42c067b7 | Michael Hanselmann | ' "$msgfile" |
60 | 42c067b7 | Michael Hanselmann | } |
61 | 42c067b7 | Michael Hanselmann | |
62 | 42c067b7 | Michael Hanselmann | replace_users() { |
63 | 42c067b7 | Michael Hanselmann | local msgfile="$1" |
64 | 42c067b7 | Michael Hanselmann | |
65 | c69a43c8 | Michael Hanselmann | if perl -i -e ' |
66 | c69a43c8 | Michael Hanselmann | use strict; |
67 | c69a43c8 | Michael Hanselmann | use warnings; |
68 | c69a43c8 | Michael Hanselmann | |
69 | c69a43c8 | Michael Hanselmann | my $error = 0; |
70 | c69a43c8 | Michael Hanselmann | my $strict; |
71 | c69a43c8 | Michael Hanselmann | |
72 | 42c067b7 | Michael Hanselmann | sub map_username { |
73 | 42c067b7 | Michael Hanselmann | my ($name) = @_; |
74 | 42c067b7 | Michael Hanselmann | |
75 | 42c067b7 | Michael Hanselmann | return $name unless $name; |
76 | 42c067b7 | Michael Hanselmann | |
77 | 42c067b7 | Michael Hanselmann | my @cmd = ("git", "config", "--get", "gnt-review.$name"); |
78 | 42c067b7 | Michael Hanselmann | |
79 | 42c067b7 | Michael Hanselmann | open(my $fh, "-|", @cmd) or die "Command \"@cmd\" failed: $!"; |
80 | 42c067b7 | Michael Hanselmann | my $output = do { local $/ = undef; <$fh> }; |
81 | 42c067b7 | Michael Hanselmann | close($fh); |
82 | 42c067b7 | Michael Hanselmann | |
83 | 42c067b7 | Michael Hanselmann | if ($? == 0) { |
84 | 42c067b7 | Michael Hanselmann | chomp $output; |
85 | 42c067b7 | Michael Hanselmann | $output =~ s/\s+/ /; |
86 | 42c067b7 | Michael Hanselmann | return $output; |
87 | 42c067b7 | Michael Hanselmann | } |
88 | 42c067b7 | Michael Hanselmann | |
89 | c69a43c8 | Michael Hanselmann | unless (defined $strict) { |
90 | c69a43c8 | Michael Hanselmann | @cmd = ("git", "config", "--get", "--bool", "gnt-review.strict"); |
91 | c69a43c8 | Michael Hanselmann | |
92 | c69a43c8 | Michael Hanselmann | open($fh, "-|", @cmd) or die "Command \"@cmd\" failed: $!"; |
93 | c69a43c8 | Michael Hanselmann | $output = do { local $/ = undef; <$fh> }; |
94 | c69a43c8 | Michael Hanselmann | close($fh); |
95 | c69a43c8 | Michael Hanselmann | |
96 | c69a43c8 | Michael Hanselmann | $strict = ($? != 0 or not $output or $output !~ m/^false$/); |
97 | c69a43c8 | Michael Hanselmann | } |
98 | c69a43c8 | Michael Hanselmann | |
99 | c69a43c8 | Michael Hanselmann | if ($strict and $name !~ m/^.+<.+\@.+>$/) { |
100 | c69a43c8 | Michael Hanselmann | $error = 1; |
101 | c69a43c8 | Michael Hanselmann | } |
102 | c69a43c8 | Michael Hanselmann | |
103 | 42c067b7 | Michael Hanselmann | return $name; |
104 | 42c067b7 | Michael Hanselmann | } |
105 | 42c067b7 | Michael Hanselmann | |
106 | 42c067b7 | Michael Hanselmann | while (<>) { |
107 | 42c067b7 | Michael Hanselmann | if (m/^Reviewed-by:(.*)$/) { |
108 | 42c067b7 | Michael Hanselmann | my @names = grep { |
109 | 42c067b7 | Michael Hanselmann | # Ignore empty entries |
110 | 42c067b7 | Michael Hanselmann | !/^$/ |
111 | 42c067b7 | Michael Hanselmann | } map { |
112 | 42c067b7 | Michael Hanselmann | # Normalize whitespace |
113 | 42c067b7 | Michael Hanselmann | $_ =~ s/(^\s+|\s+$)//g; |
114 | 42c067b7 | Michael Hanselmann | $_ =~ s/\s+/ /g; |
115 | 42c067b7 | Michael Hanselmann | |
116 | 42c067b7 | Michael Hanselmann | # Map names |
117 | 42c067b7 | Michael Hanselmann | $_ = map_username($_); |
118 | 42c067b7 | Michael Hanselmann | |
119 | 42c067b7 | Michael Hanselmann | $_; |
120 | 42c067b7 | Michael Hanselmann | } split(m/,/, $1); |
121 | 42c067b7 | Michael Hanselmann | |
122 | c69a43c8 | Michael Hanselmann | # Get unique names |
123 | c69a43c8 | Michael Hanselmann | my %saw; |
124 | c69a43c8 | Michael Hanselmann | @names = grep(!$saw{$_}++, @names); |
125 | c69a43c8 | Michael Hanselmann | undef %saw; |
126 | c69a43c8 | Michael Hanselmann | |
127 | 42c067b7 | Michael Hanselmann | foreach (sort @names) { |
128 | 42c067b7 | Michael Hanselmann | print "Reviewed-by: $_\n"; |
129 | 42c067b7 | Michael Hanselmann | } |
130 | 42c067b7 | Michael Hanselmann | } else { |
131 | 42c067b7 | Michael Hanselmann | print; |
132 | 42c067b7 | Michael Hanselmann | } |
133 | 42c067b7 | Michael Hanselmann | } |
134 | c69a43c8 | Michael Hanselmann | |
135 | c69a43c8 | Michael Hanselmann | exit($error? 33 : 0); |
136 | 42c067b7 | Michael Hanselmann | ' "$msgfile" |
137 | c69a43c8 | Michael Hanselmann | then |
138 | c69a43c8 | Michael Hanselmann | : |
139 | c69a43c8 | Michael Hanselmann | else |
140 | c69a43c8 | Michael Hanselmann | [[ "$?" == 33 ]] && return 1 |
141 | c69a43c8 | Michael Hanselmann | exit 1 |
142 | c69a43c8 | Michael Hanselmann | fi |
143 | 42c067b7 | Michael Hanselmann | |
144 | 42c067b7 | Michael Hanselmann | if ! grep -q '^Reviewed-by: ' "$msgfile" |
145 | 42c067b7 | Michael Hanselmann | then |
146 | 42c067b7 | Michael Hanselmann | echo 'Missing Reviewed-by: line' >&2 |
147 | 42c067b7 | Michael Hanselmann | sleep 1 |
148 | 42c067b7 | Michael Hanselmann | return 1 |
149 | 42c067b7 | Michael Hanselmann | fi |
150 | 42c067b7 | Michael Hanselmann | |
151 | 42c067b7 | Michael Hanselmann | return 0 |
152 | 42c067b7 | Michael Hanselmann | } |
153 | 42c067b7 | Michael Hanselmann | |
154 | 42c067b7 | Michael Hanselmann | run_editor() { |
155 | 42c067b7 | Michael Hanselmann | local filename="$1" |
156 | 42c067b7 | Michael Hanselmann | local editor=${EDITOR:-vi} |
157 | 42c067b7 | Michael Hanselmann | local args |
158 | 42c067b7 | Michael Hanselmann | |
159 | 42c067b7 | Michael Hanselmann | case "$(basename "$editor")" in |
160 | 42c067b7 | Michael Hanselmann | vi* | *vim) |
161 | 42c067b7 | Michael Hanselmann | # Start edit mode at Reviewed-by: line |
162 | 42c067b7 | Michael Hanselmann | args='+/^Reviewed-by: +nohlsearch +startinsert!' |
163 | 42c067b7 | Michael Hanselmann | ;; |
164 | 42c067b7 | Michael Hanselmann | *) |
165 | 42c067b7 | Michael Hanselmann | args= |
166 | 42c067b7 | Michael Hanselmann | ;; |
167 | 42c067b7 | Michael Hanselmann | esac |
168 | 42c067b7 | Michael Hanselmann | |
169 | 42c067b7 | Michael Hanselmann | $editor $args "$filename" |
170 | 42c067b7 | Michael Hanselmann | } |
171 | 42c067b7 | Michael Hanselmann | |
172 | 42c067b7 | Michael Hanselmann | commit_editor() { |
173 | 42c067b7 | Michael Hanselmann | local msgfile="$1" |
174 | 42c067b7 | Michael Hanselmann | |
175 | 42c067b7 | Michael Hanselmann | local tmpf=$(mktemp) |
176 | 42c067b7 | Michael Hanselmann | trap "rm -f $tmpf" EXIT |
177 | 42c067b7 | Michael Hanselmann | |
178 | 42c067b7 | Michael Hanselmann | cp "$msgfile" "$tmpf" |
179 | 42c067b7 | Michael Hanselmann | |
180 | 42c067b7 | Michael Hanselmann | while : |
181 | 42c067b7 | Michael Hanselmann | do |
182 | 42c067b7 | Michael Hanselmann | add_reviewed_by "$tmpf" |
183 | 42c067b7 | Michael Hanselmann | |
184 | 42c067b7 | Michael Hanselmann | run_editor "$tmpf" |
185 | 42c067b7 | Michael Hanselmann | |
186 | 42c067b7 | Michael Hanselmann | replace_users "$tmpf" && break |
187 | 42c067b7 | Michael Hanselmann | done |
188 | 42c067b7 | Michael Hanselmann | |
189 | 42c067b7 | Michael Hanselmann | cp "$tmpf" "$msgfile" |
190 | 42c067b7 | Michael Hanselmann | } |
191 | 42c067b7 | Michael Hanselmann | |
192 | 42c067b7 | Michael Hanselmann | copy_commit() { |
193 | 42c067b7 | Michael Hanselmann | local rev="$1" target_branch="$2" |
194 | 42c067b7 | Michael Hanselmann | |
195 | 42c067b7 | Michael Hanselmann | echo "Copying commit $rev ..." |
196 | 42c067b7 | Michael Hanselmann | |
197 | 42c067b7 | Michael Hanselmann | git cherry-pick -n "$rev" |
198 | 42c067b7 | Michael Hanselmann | GIT_EDITOR="$me --commit-editor \"\$@\"" git commit -c "$rev" -s |
199 | 42c067b7 | Michael Hanselmann | } |
200 | 42c067b7 | Michael Hanselmann | |
201 | 53726a00 | Guido Trotter | usage() { |
202 | 53726a00 | Guido Trotter | echo "Usage: $me_plain [from..to] <target-branch>" >&2 |
203 | 53726a00 | Guido Trotter | echo " If not passed from..to defaults to target-branch..HEAD" >&2 |
204 | 53726a00 | Guido Trotter | exit 1 |
205 | 53726a00 | Guido Trotter | } |
206 | 42c067b7 | Michael Hanselmann | |
207 | 53726a00 | Guido Trotter | main() { |
208 | 53726a00 | Guido Trotter | local range target_branch |
209 | 53726a00 | Guido Trotter | |
210 | 53726a00 | Guido Trotter | case "$#" in |
211 | 53726a00 | Guido Trotter | 1) |
212 | 53726a00 | Guido Trotter | target_branch="$1" |
213 | 53726a00 | Guido Trotter | range="$target_branch..$(git rev-parse HEAD)" |
214 | 53726a00 | Guido Trotter | ;; |
215 | 53726a00 | Guido Trotter | 2) |
216 | 53726a00 | Guido Trotter | range="$1" |
217 | 53726a00 | Guido Trotter | target_branch="$2" |
218 | 53726a00 | Guido Trotter | if [[ "$range" != *..* ]]; then |
219 | 53726a00 | Guido Trotter | usage |
220 | 53726a00 | Guido Trotter | fi |
221 | 53726a00 | Guido Trotter | ;; |
222 | 53726a00 | Guido Trotter | *) |
223 | 53726a00 | Guido Trotter | usage |
224 | 53726a00 | Guido Trotter | ;; |
225 | 53726a00 | Guido Trotter | esac |
226 | 42c067b7 | Michael Hanselmann | |
227 | 42c067b7 | Michael Hanselmann | git checkout "$target_branch" |
228 | 42c067b7 | Michael Hanselmann | local old_head=$(git rev-parse HEAD) |
229 | 42c067b7 | Michael Hanselmann | |
230 | 42c067b7 | Michael Hanselmann | for rev in $(git rev-list --reverse "$range") |
231 | 42c067b7 | Michael Hanselmann | do |
232 | 42c067b7 | Michael Hanselmann | copy_commit "$rev" |
233 | 42c067b7 | Michael Hanselmann | done |
234 | 42c067b7 | Michael Hanselmann | |
235 | 42c067b7 | Michael Hanselmann | git log "$old_head..$target_branch" |
236 | 42c067b7 | Michael Hanselmann | } |
237 | 42c067b7 | Michael Hanselmann | |
238 | 42c067b7 | Michael Hanselmann | if [[ "$1" == --commit-editor ]] |
239 | 42c067b7 | Michael Hanselmann | then |
240 | 42c067b7 | Michael Hanselmann | shift |
241 | 42c067b7 | Michael Hanselmann | commit_editor "$@" |
242 | 42c067b7 | Michael Hanselmann | else |
243 | 42c067b7 | Michael Hanselmann | main "$@" |
244 | 42c067b7 | Michael Hanselmann | fi |