Revision 42c067b7

b/devel/review
1
#!/bin/bash
2

  
3
# Copyright (C) 2009 Google Inc.
4
#
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.
9
#
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.
14
#
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
18
# 02110-1301, USA.
19

  
20
# To set user mappings, use this command:
21
#   git config gnt-review.johndoe 'John Doe <johndoe@domain.tld>'
22

  
23
set -e
24

  
25
# Get absolute path to myself
26
me_plain="$0"
27
me=$(readlink -f "$me_plain")
28

  
29
add_reviewed_by() {
30
  local msgfile="$1"
31

  
32
  grep -q '^Reviewed-by: ' "$msgfile" && return
33

  
34
  perl -i -e '
35
  my $sob = 0;
36
  while (<>) {
37
    if ($sob == 0 and m/^Signed-off-by:/) {
38
      $sob = 1;
39

  
40
    } elsif ($sob == 1 and not m/^Signed-off-by:/) {
41
      print "Reviewed-by: \n";
42
      $sob = -1;
43
    }
44

  
45
    print;
46
  }
47

  
48
  if ($sob == 1) {
49
    print "Reviewed-by: \n";
50
  }
51
  ' "$msgfile"
52
}
53

  
54
replace_users() {
55
  local msgfile="$1"
56

  
57
  perl -i -e '
58
  sub map_username {
59
    my ($name) = @_;
60

  
61
    return $name unless $name;
62

  
63
    my @cmd = ("git", "config", "--get", "gnt-review.$name");
64

  
65
    open(my $fh, "-|", @cmd) or die "Command \"@cmd\" failed: $!";
66
    my $output = do { local $/ = undef; <$fh> };
67
    close($fh);
68

  
69
    if ($? == 0) {
70
      chomp $output;
71
      $output =~ s/\s+/ /;
72
      return $output;
73
    }
74

  
75
    return $name;
76
  }
77

  
78
  while (<>) {
79
    if (m/^Reviewed-by:(.*)$/) {
80
      my @names = grep {
81
        # Ignore empty entries
82
        !/^$/
83
      } map {
84
        # Normalize whitespace
85
        $_ =~ s/(^\s+|\s+$)//g;
86
        $_ =~ s/\s+/ /g;
87

  
88
        # Map names
89
        $_ = map_username($_);
90

  
91
        $_;
92
      } split(m/,/, $1);
93

  
94
      foreach (sort @names) {
95
        print "Reviewed-by: $_\n";
96
      }
97
    } else {
98
      print;
99
    }
100
  }
101
  ' "$msgfile"
102

  
103
  if ! grep -q '^Reviewed-by: ' "$msgfile"
104
  then
105
    echo 'Missing Reviewed-by: line' >&2
106
    sleep 1
107
    return 1
108
  fi
109

  
110
  return 0
111
}
112

  
113
run_editor() {
114
  local filename="$1"
115
  local editor=${EDITOR:-vi}
116
  local args
117

  
118
  case "$(basename "$editor")" in
119
    vi* | *vim)
120
      # Start edit mode at Reviewed-by: line
121
      args='+/^Reviewed-by: +nohlsearch +startinsert!'
122
    ;;
123
    *)
124
      args=
125
    ;;
126
  esac
127

  
128
  $editor $args "$filename"
129
}
130

  
131
commit_editor() {
132
  local msgfile="$1"
133

  
134
  local tmpf=$(mktemp)
135
  trap "rm -f $tmpf" EXIT
136

  
137
  cp "$msgfile" "$tmpf"
138

  
139
  while :
140
  do
141
    add_reviewed_by "$tmpf"
142

  
143
    run_editor "$tmpf"
144

  
145
    replace_users "$tmpf" && break
146
  done
147

  
148
  cp "$tmpf" "$msgfile"
149
}
150

  
151
copy_commit() {
152
  local rev="$1" target_branch="$2"
153

  
154
  echo "Copying commit $rev ..."
155

  
156
  git cherry-pick -n "$rev"
157
  GIT_EDITOR="$me --commit-editor \"\$@\"" git commit -c "$rev" -s
158
}
159

  
160
main() {
161
  local range="$1" target_branch="$2"
162

  
163
  if [[ -z "$target_branch" || "$range" != *..* ]]
164
  then
165
    echo "Usage: $me_plain <from..to> <target-branch>" >&2
166
    exit 1
167
  fi
168

  
169
  git checkout "$target_branch"
170
  local old_head=$(git rev-parse HEAD)
171

  
172
  for rev in $(git rev-list --reverse "$range")
173
  do
174
    copy_commit "$rev"
175
  done
176

  
177
  git log "$old_head..$target_branch"
178
}
179

  
180
if [[ "$1" == --commit-editor ]]
181
then
182
  shift
183
  commit_editor "$@"
184
else
185
  main "$@"
186
fi

Also available in: Unified diff