Statistics
| Branch: | Tag: | Revision:

root / devel / review @ ab6536ba

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