3 # Copyright (C) 2009 Google Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 # To set user mappings, use this command:
21 # git config gnt-review.johndoe 'John Doe <johndoe@example.com>'
23 # To disable strict mode (enabled by default):
24 # git config gnt-review.strict false
26 # To enable strict mode:
27 # git config gnt-review.strict true
31 # Get absolute path to myself
33 me=$(readlink -f "$me_plain")
38 grep -q '^Reviewed-by: ' "$msgfile" && return
41 my $reviewer = $ENV{"REVIEWER"};
42 defined($reviewer) or $reviewer = "";
45 if ($sob == 0 and m/^Signed-off-by:/) {
48 } elsif ($sob == 1 and not m/^Signed-off-by:/) {
49 print "Reviewed-by: $reviewer\n";
57 print "Reviewed-by: $reviewer\n";
75 return $name unless $name;
77 my @cmd = ("git", "config", "--get", "gnt-review.$name");
79 open(my $fh, "-|", @cmd) or die "Command \"@cmd\" failed: $!";
80 my $output = do { local $/ = undef; <$fh> };
89 unless (defined $strict) {
90 @cmd = ("git", "config", "--get", "--bool", "gnt-review.strict");
92 open($fh, "-|", @cmd) or die "Command \"@cmd\" failed: $!";
93 $output = do { local $/ = undef; <$fh> };
96 $strict = ($? != 0 or not $output or $output !~ m/^false$/);
99 if ($strict and $name !~ m/^.+<.+\@.+>$/) {
107 if (m/^Reviewed-by:(.*)$/) {
109 # Ignore empty entries
112 # Normalize whitespace
113 $_ =~ s/(^\s+|\s+$)//g;
117 $_ = map_username($_);
124 @names = grep(!$saw{$_}++, @names);
127 foreach (sort @names) {
128 print "Reviewed-by: $_\n";
135 exit($error? 33 : 0);
140 [[ "$?" == 33 ]] && return 1
144 if ! grep -q '^Reviewed-by: ' "$msgfile"
146 echo 'Missing Reviewed-by: line' >&2
156 local editor=${EDITOR:-vi}
159 case "$(basename "$editor")" in
161 # Start edit mode at Reviewed-by: line
162 args='+/^Reviewed-by: +nohlsearch +startinsert!'
169 $editor $args "$filename"
176 trap "rm -f $tmpf" EXIT
178 cp "$msgfile" "$tmpf"
182 add_reviewed_by "$tmpf"
186 replace_users "$tmpf" && break
189 cp "$tmpf" "$msgfile"
193 local rev="$1" target_branch="$2"
195 echo "Copying commit $rev ..."
197 git cherry-pick -n "$rev"
198 GIT_EDITOR="$me --commit-editor \"\$@\"" git commit -c "$rev" -s
202 echo "Usage: $me_plain [from..to] <target-branch>" >&2
203 echo " If not passed from..to defaults to target-branch..HEAD" >&2
208 local range target_branch
213 range="$target_branch..$(git rev-parse HEAD)"
218 if [[ "$range" != *..* ]]; then
227 git checkout "$target_branch"
228 local old_head=$(git rev-parse HEAD)
230 for rev in $(git rev-list --reverse "$range")
235 git log "$old_head..$target_branch"
238 if [[ "$1" == --commit-editor ]]