diff options
author | Florian Mickler <florian@mickler.org> | 2010-10-26 17:22:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 19:52:17 -0400 |
commit | dace8e300d6820c2842de750d12b498a743bcfe5 (patch) | |
tree | 2c98305bee3da1914c00768c5ac65a0dedda83d5 /scripts | |
parent | bcde44ed7d2a58733efdf04b5392c027d1348bac (diff) |
scripts/get_maintainer.pl: add interactive mode
This is a first version of an interactive mode for
scripts/get_maintainer.pl.
It allows the user to interact with the script. Each cc candidate can be
selected and deselected and a shortlog of authored commits can be
displayed for each candidate.
The menu is displayed via STDERR, the end result is outputted to STDOUT.
This unusual mechanism allows using get_maintainer.pl in interactive mode
via git send-email --cc-cmd.
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/get_maintainer.pl | 146 |
1 files changed, 141 insertions, 5 deletions
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index e5a400c53bf0..1ae8c50f1908 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -33,6 +33,7 @@ my $email_git_max_maintainers = 5; | |||
33 | my $email_git_min_percent = 5; | 33 | my $email_git_min_percent = 5; |
34 | my $email_git_since = "1-year-ago"; | 34 | my $email_git_since = "1-year-ago"; |
35 | my $email_hg_since = "-365"; | 35 | my $email_hg_since = "-365"; |
36 | my $interactive = 0; | ||
36 | my $email_remove_duplicates = 1; | 37 | my $email_remove_duplicates = 1; |
37 | my $output_multiline = 1; | 38 | my $output_multiline = 1; |
38 | my $output_separator = ", "; | 39 | my $output_separator = ", "; |
@@ -52,6 +53,8 @@ my $help = 0; | |||
52 | 53 | ||
53 | my $exit = 0; | 54 | my $exit = 0; |
54 | 55 | ||
56 | my %shortlog_buffer; | ||
57 | |||
55 | my @penguin_chief = (); | 58 | my @penguin_chief = (); |
56 | push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); | 59 | push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); |
57 | #Andrew wants in on most everything - 2009/01/14 | 60 | #Andrew wants in on most everything - 2009/01/14 |
@@ -93,7 +96,8 @@ my %VCS_cmds_git = ( | |||
93 | "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", | 96 | "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", |
94 | "blame_file_cmd" => "git blame -l \$file", | 97 | "blame_file_cmd" => "git blame -l \$file", |
95 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | 98 | "commit_pattern" => "^commit [0-9a-f]{40,40}", |
96 | "blame_commit_pattern" => "^([0-9a-f]+) " | 99 | "blame_commit_pattern" => "^([0-9a-f]+) ", |
100 | "shortlog_cmd" => "git log --no-color --oneline --since=\$email_git_since --author=\"\$email\" -- \$file" | ||
97 | ); | 101 | ); |
98 | 102 | ||
99 | my %VCS_cmds_hg = ( | 103 | my %VCS_cmds_hg = ( |
@@ -107,7 +111,8 @@ my %VCS_cmds_hg = ( | |||
107 | "blame_range_cmd" => "", # not supported | 111 | "blame_range_cmd" => "", # not supported |
108 | "blame_file_cmd" => "hg blame -c \$file", | 112 | "blame_file_cmd" => "hg blame -c \$file", |
109 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | 113 | "commit_pattern" => "^commit [0-9a-f]{40,40}", |
110 | "blame_commit_pattern" => "^([0-9a-f]+):" | 114 | "blame_commit_pattern" => "^([0-9a-f]+):", |
115 | "shortlog_cmd" => "ht log --date=\$email_hg_since" | ||
111 | ); | 116 | ); |
112 | 117 | ||
113 | my $conf = which_conf(".get_maintainer.conf"); | 118 | my $conf = which_conf(".get_maintainer.conf"); |
@@ -148,6 +153,7 @@ if (!GetOptions( | |||
148 | 'git-min-percent=i' => \$email_git_min_percent, | 153 | 'git-min-percent=i' => \$email_git_min_percent, |
149 | 'git-since=s' => \$email_git_since, | 154 | 'git-since=s' => \$email_git_since, |
150 | 'hg-since=s' => \$email_hg_since, | 155 | 'hg-since=s' => \$email_hg_since, |
156 | 'i|interactive!' => \$interactive, | ||
151 | 'remove-duplicates!' => \$email_remove_duplicates, | 157 | 'remove-duplicates!' => \$email_remove_duplicates, |
152 | 'm!' => \$email_maintainer, | 158 | 'm!' => \$email_maintainer, |
153 | 'n!' => \$email_usename, | 159 | 'n!' => \$email_usename, |
@@ -225,6 +231,8 @@ if ($email_git_all_signature_types) { | |||
225 | $signaturePattern = "(.+?)[Bb][Yy]:"; | 231 | $signaturePattern = "(.+?)[Bb][Yy]:"; |
226 | } | 232 | } |
227 | 233 | ||
234 | |||
235 | |||
228 | ## Read MAINTAINERS for type/value pairs | 236 | ## Read MAINTAINERS for type/value pairs |
229 | 237 | ||
230 | my @typevalue = (); | 238 | my @typevalue = (); |
@@ -450,10 +458,13 @@ foreach my $file (@files) { | |||
450 | ($email_git || ($email_git_fallback && !$exact_pattern_match))) { | 458 | ($email_git || ($email_git_fallback && !$exact_pattern_match))) { |
451 | vcs_file_signoffs($file); | 459 | vcs_file_signoffs($file); |
452 | } | 460 | } |
453 | |||
454 | if ($email && $email_git_blame) { | 461 | if ($email && $email_git_blame) { |
455 | vcs_file_blame($file); | 462 | vcs_file_blame($file); |
456 | } | 463 | } |
464 | if ($email && $interactive){ | ||
465 | vcs_file_shortlogs($file); | ||
466 | |||
467 | } | ||
457 | } | 468 | } |
458 | 469 | ||
459 | if ($keywords) { | 470 | if ($keywords) { |
@@ -486,9 +497,13 @@ if ($email) { | |||
486 | } | 497 | } |
487 | } | 498 | } |
488 | 499 | ||
500 | |||
489 | if ($email || $email_list) { | 501 | if ($email || $email_list) { |
490 | my @to = (); | 502 | my @to = (); |
491 | if ($email) { | 503 | if ($email) { |
504 | if ($interactive) { | ||
505 | @email_to = @{vcs_interactive_menu(\@email_to)}; | ||
506 | } | ||
492 | @to = (@to, @email_to); | 507 | @to = (@to, @email_to); |
493 | } | 508 | } |
494 | if ($email_list) { | 509 | if ($email_list) { |
@@ -501,7 +516,6 @@ if ($scm) { | |||
501 | @scm = uniq(@scm); | 516 | @scm = uniq(@scm); |
502 | output(@scm); | 517 | output(@scm); |
503 | } | 518 | } |
504 | |||
505 | if ($status) { | 519 | if ($status) { |
506 | @status = uniq(@status); | 520 | @status = uniq(@status); |
507 | output(@status); | 521 | output(@status); |
@@ -556,6 +570,7 @@ MAINTAINER field selection options: | |||
556 | --git-blame => use git blame to find modified commits for patch or file | 570 | --git-blame => use git blame to find modified commits for patch or file |
557 | --git-since => git history to use (default: $email_git_since) | 571 | --git-since => git history to use (default: $email_git_since) |
558 | --hg-since => hg history to use (default: $email_hg_since) | 572 | --hg-since => hg history to use (default: $email_hg_since) |
573 | --interactive => display a menu (mostly useful if used with the --git option) | ||
559 | --m => include maintainer(s) if any | 574 | --m => include maintainer(s) if any |
560 | --n => include name 'Full Name <addr\@domain.tld>' | 575 | --n => include name 'Full Name <addr\@domain.tld>' |
561 | --l => include list(s) if any | 576 | --l => include list(s) if any |
@@ -1156,6 +1171,127 @@ sub vcs_exists { | |||
1156 | return 0; | 1171 | return 0; |
1157 | } | 1172 | } |
1158 | 1173 | ||
1174 | sub vcs_interactive_menu { | ||
1175 | my $list_ref = shift; | ||
1176 | my @list = @$list_ref; | ||
1177 | |||
1178 | return if (!vcs_exists()); | ||
1179 | |||
1180 | my %selected; | ||
1181 | my %shortlog; | ||
1182 | my $input; | ||
1183 | my $count = 0; | ||
1184 | |||
1185 | #select maintainers by default | ||
1186 | foreach my $entry (@list){ | ||
1187 | my $role = $entry->[1]; | ||
1188 | $selected{$count} = ($role =~ /maintainer:|supporter:/); | ||
1189 | $count++; | ||
1190 | } | ||
1191 | |||
1192 | #menu loop | ||
1193 | do { | ||
1194 | my $count = 0; | ||
1195 | foreach my $entry (@list){ | ||
1196 | my $email = $entry->[0]; | ||
1197 | my $role = $entry->[1]; | ||
1198 | if ($selected{$count}){ | ||
1199 | print STDERR "* "; | ||
1200 | } else { | ||
1201 | print STDERR " "; | ||
1202 | } | ||
1203 | print STDERR "$count: $email,\t\t $role"; | ||
1204 | print STDERR "\n"; | ||
1205 | if ($shortlog{$count}){ | ||
1206 | my $entries_ref = vcs_get_shortlog($email); | ||
1207 | foreach my $entry_ref (@{$entries_ref}){ | ||
1208 | my $filename = @{$entry_ref}[0]; | ||
1209 | my @shortlog = @{@{$entry_ref}[1]}; | ||
1210 | print STDERR "\tshortlog for $filename (authored commits: " . @shortlog . ").\n"; | ||
1211 | foreach my $commit (@shortlog){ | ||
1212 | print STDERR "\t $commit\n"; | ||
1213 | } | ||
1214 | print STDERR "\n"; | ||
1215 | } | ||
1216 | } | ||
1217 | $count++; | ||
1218 | } | ||
1219 | print STDERR "\n"; | ||
1220 | print STDERR "Choose whom to cc by entering a commaseperated list of numbers and hitting enter.\n"; | ||
1221 | print STDERR "To show a short list of commits, precede the number by a '?',\n"; | ||
1222 | print STDERR "A blank line indicates that you are satisfied with your choice.\n"; | ||
1223 | $input = <STDIN>; | ||
1224 | chomp($input); | ||
1225 | |||
1226 | my @wish = split(/[, ]+/,$input); | ||
1227 | foreach my $nr (@wish){ | ||
1228 | my $logtoggle = 0; | ||
1229 | if ($nr =~ /\?/){ | ||
1230 | $nr =~ s/\?//; | ||
1231 | $logtoggle = 1; | ||
1232 | } | ||
1233 | |||
1234 | #skip out of bounds numbers | ||
1235 | next unless ($nr <= $count && $nr >= 0); | ||
1236 | |||
1237 | if ($logtoggle){ | ||
1238 | $shortlog{$nr} = !$shortlog{$nr}; | ||
1239 | } else { | ||
1240 | $selected{$nr} = !$selected{$nr}; | ||
1241 | |||
1242 | #switch shortlog on if an entry get's selected | ||
1243 | if ($selected{$nr}){ | ||
1244 | $shortlog{$nr}=1; | ||
1245 | } | ||
1246 | } | ||
1247 | }; | ||
1248 | } while(length($input) > 0); | ||
1249 | |||
1250 | #drop not selected entries | ||
1251 | $count = 0; | ||
1252 | my @new_emailto; | ||
1253 | foreach my $entry (@list){ | ||
1254 | if ($selected{$count}){ | ||
1255 | push(@new_emailto,$list[$count]); | ||
1256 | print STDERR "$count: "; | ||
1257 | print STDERR $email_to[$count]->[0]; | ||
1258 | print STDERR ",\t\t "; | ||
1259 | print STDERR $email_to[$count]->[1]; | ||
1260 | print STDERR "\n"; | ||
1261 | } | ||
1262 | $count++; | ||
1263 | } | ||
1264 | return \@new_emailto; | ||
1265 | } | ||
1266 | |||
1267 | sub vcs_get_shortlog { | ||
1268 | my $arg = shift; | ||
1269 | my ($name, $address) = parse_email($arg); | ||
1270 | return $shortlog_buffer{$address}; | ||
1271 | } | ||
1272 | |||
1273 | sub vcs_file_shortlogs { | ||
1274 | my ($file) = @_; | ||
1275 | print STDERR "shortlog processing $file:"; | ||
1276 | foreach my $entry (@email_to){ | ||
1277 | my ($name, $address) = parse_email($entry->[0]); | ||
1278 | print STDERR "."; | ||
1279 | my $commits_ref = vcs_email_shortlog($address, $file); | ||
1280 | push(@{$shortlog_buffer{$address}}, [ $file, $commits_ref ]); | ||
1281 | } | ||
1282 | print STDERR "\n"; | ||
1283 | } | ||
1284 | |||
1285 | sub vcs_email_shortlog { | ||
1286 | my $email = shift; | ||
1287 | my ($file) = @_; | ||
1288 | |||
1289 | my $cmd = $VCS_cmds{"shortlog_cmd"}; | ||
1290 | $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables | ||
1291 | my @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); | ||
1292 | return \@lines; | ||
1293 | } | ||
1294 | |||
1159 | sub vcs_assign { | 1295 | sub vcs_assign { |
1160 | my ($role, $divisor, @lines) = @_; | 1296 | my ($role, $divisor, @lines) = @_; |
1161 | 1297 | ||
@@ -1236,7 +1372,7 @@ sub vcs_file_blame { | |||
1236 | my @commit_signers = (); | 1372 | my @commit_signers = (); |
1237 | 1373 | ||
1238 | my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; | 1374 | my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; |
1239 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | 1375 | $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd |
1240 | 1376 | ||
1241 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); | 1377 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); |
1242 | 1378 | ||