aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/get_maintainer.pl
diff options
context:
space:
mode:
authorJoe Perches <joe@perches.com>2010-10-26 17:22:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 19:52:17 -0400
commit6ef1c52e122b675acc88a8b016d6477f67988b91 (patch)
treeae38fb0fa0811356aa95c5bf8246eb0f9826e37c /scripts/get_maintainer.pl
parent683c6f8fcbcb6de8d07545ba70aff49e50d8bcf2 (diff)
scripts/get_maintainer.pl: use case insensitive name de-duplication
Case insensitive name and email address matching can help reduce duplication when authors don't always use the exact same signature. o Add a --interactive per-file exact_match hash so git history can be checked on per-file only when there is no direct maintainer o Make @interactive_to list global so save_commits_by_<foo> can check email names & addresses against this list for duplication o Don't allow --interactive and --sections o rename subroutine get_maintainer to get_maintainers o Added help text option to --interactive menu prompt Update version to 0.26-beta4 Signed-off-by: Joe Perches <joe@perches.com> Cc: Florian Mickler <florian@mickler.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/get_maintainer.pl')
-rwxr-xr-xscripts/get_maintainer.pl135
1 files changed, 101 insertions, 34 deletions
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index f51176039ff5..61d3bb51bddf 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -13,7 +13,7 @@
13use strict; 13use strict;
14 14
15my $P = $0; 15my $P = $0;
16my $V = '0.26-beta3'; 16my $V = '0.26-beta4';
17 17
18use Getopt::Long qw(:config no_auto_abbrev); 18use Getopt::Long qw(:config no_auto_abbrev);
19 19
@@ -242,6 +242,7 @@ if ($sections) {
242 $subsystem = 0; 242 $subsystem = 0;
243 $web = 0; 243 $web = 0;
244 $keywords = 0; 244 $keywords = 0;
245 $interactive = 0;
245} else { 246} else {
246 my $selections = $email + $scm + $status + $subsystem + $web; 247 my $selections = $email + $scm + $status + $subsystem + $web;
247 if ($selections == 0) { 248 if ($selections == 0) {
@@ -407,13 +408,15 @@ my @scm = ();
407my @web = (); 408my @web = ();
408my @subsystem = (); 409my @subsystem = ();
409my @status = (); 410my @status = ();
411my @interactive_to = ();
410my $signature_pattern; 412my $signature_pattern;
411 413
412my @to = get_maintainer(); 414my @maintainers = get_maintainers();
413 415
414@to = merge_email(@to); 416if (@maintainers) {
415 417 @maintainers = merge_email(@maintainers);
416output(@to) if (@to); 418 output(@maintainers);
419}
417 420
418if ($scm) { 421if ($scm) {
419 @scm = uniq(@scm); 422 @scm = uniq(@scm);
@@ -437,7 +440,7 @@ if ($web) {
437 440
438exit($exit); 441exit($exit);
439 442
440sub get_maintainer { 443sub get_maintainers {
441 %email_hash_name = (); 444 %email_hash_name = ();
442 %email_hash_address = (); 445 %email_hash_address = ();
443 %commit_author_hash = (); 446 %commit_author_hash = ();
@@ -449,7 +452,7 @@ sub get_maintainer {
449 @web = (); 452 @web = ();
450 @subsystem = (); 453 @subsystem = ();
451 @status = (); 454 @status = ();
452 455 @interactive_to = ();
453 if ($email_git_all_signature_types) { 456 if ($email_git_all_signature_types) {
454 $signature_pattern = "(.+?)[Bb][Yy]:"; 457 $signature_pattern = "(.+?)[Bb][Yy]:";
455 } else { 458 } else {
@@ -458,10 +461,11 @@ sub get_maintainer {
458 461
459 # Find responsible parties 462 # Find responsible parties
460 463
464 my %exact_pattern_match_hash;
465
461 foreach my $file (@files) { 466 foreach my $file (@files) {
462 467
463 my %hash; 468 my %hash;
464 my $exact_pattern_match = 0;
465 my $tvi = find_first_section(); 469 my $tvi = find_first_section();
466 while ($tvi < @typevalue) { 470 while ($tvi < @typevalue) {
467 my $start = find_starting_index($tvi); 471 my $start = find_starting_index($tvi);
@@ -497,7 +501,9 @@ sub get_maintainer {
497 my $file_pd = ($file =~ tr@/@@); 501 my $file_pd = ($file =~ tr@/@@);
498 $value_pd++ if (substr($value,-1,1) ne "/"); 502 $value_pd++ if (substr($value,-1,1) ne "/");
499 $value_pd = -1 if ($value =~ /^\.\*/); 503 $value_pd = -1 if ($value =~ /^\.\*/);
500 $exact_pattern_match = 1 if ($value_pd >= $file_pd); 504 if ($value_pd >= $file_pd) {
505 $exact_pattern_match_hash{$file} = 1;
506 }
501 if ($pattern_depth == 0 || 507 if ($pattern_depth == 0 ||
502 (($file_pd - $value_pd) < $pattern_depth)) { 508 (($file_pd - $value_pd) < $pattern_depth)) {
503 $hash{$tvi} = $value_pd; 509 $hash{$tvi} = $value_pd;
@@ -530,14 +536,6 @@ sub get_maintainer {
530 print("\n"); 536 print("\n");
531 } 537 }
532 } 538 }
533
534 if ($email && ($email_git ||
535 ($email_git_fallback && !$exact_pattern_match))) {
536 vcs_file_signoffs($file);
537 }
538 if ($email && $email_git_blame) {
539 vcs_file_blame($file);
540 }
541 } 539 }
542 540
543 if ($keywords) { 541 if ($keywords) {
@@ -547,6 +545,19 @@ sub get_maintainer {
547 } 545 }
548 } 546 }
549 547
548 @interactive_to = (@email_to, @list_to);
549
550 foreach my $file (@files) {
551 if ($email &&
552 ($email_git || ($email_git_fallback &&
553 !$exact_pattern_match_hash{$file}))) {
554 vcs_file_signoffs($file);
555 }
556 if ($email && $email_git_blame) {
557 vcs_file_blame($file);
558 }
559 }
560
550 if ($email) { 561 if ($email) {
551 foreach my $chief (@penguin_chief) { 562 foreach my $chief (@penguin_chief) {
552 if ($chief =~ m/^(.*):(.*)/) { 563 if ($chief =~ m/^(.*):(.*)/) {
@@ -580,7 +591,10 @@ sub get_maintainer {
580 } 591 }
581 } 592 }
582 593
583 @to = interactive_get_maintainer(\@to) if ($interactive); 594 if ($interactive) {
595 @interactive_to = @to;
596 @to = interactive_get_maintainers(\@interactive_to);
597 }
584 598
585 return @to; 599 return @to;
586} 600}
@@ -899,16 +913,16 @@ sub add_categories {
899 } 913 }
900 if ($list_additional =~ m/subscribers-only/) { 914 if ($list_additional =~ m/subscribers-only/) {
901 if ($email_subscriber_list) { 915 if ($email_subscriber_list) {
902 if (!$hash_list_to{$list_address}) { 916 if (!$hash_list_to{lc($list_address)}) {
903 $hash_list_to{$list_address} = 1; 917 $hash_list_to{lc($list_address)} = 1;
904 push(@list_to, [$list_address, 918 push(@list_to, [$list_address,
905 "subscriber list${list_role}"]); 919 "subscriber list${list_role}"]);
906 } 920 }
907 } 921 }
908 } else { 922 } else {
909 if ($email_list) { 923 if ($email_list) {
910 if (!$hash_list_to{$list_address}) { 924 if (!$hash_list_to{lc($list_address)}) {
911 $hash_list_to{$list_address} = 1; 925 $hash_list_to{lc($list_address)} = 1;
912 push(@list_to, [$list_address, 926 push(@list_to, [$list_address,
913 "open list${list_role}"]); 927 "open list${list_role}"]);
914 } 928 }
@@ -946,8 +960,8 @@ sub email_inuse {
946 my ($name, $address) = @_; 960 my ($name, $address) = @_;
947 961
948 return 1 if (($name eq "") && ($address eq "")); 962 return 1 if (($name eq "") && ($address eq ""));
949 return 1 if (($name ne "") && exists($email_hash_name{$name})); 963 return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
950 return 1 if (($address ne "") && exists($email_hash_address{$address})); 964 return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
951 965
952 return 0; 966 return 0;
953} 967}
@@ -965,8 +979,8 @@ sub push_email_address {
965 push(@email_to, [format_email($name, $address, $email_usename), $role]); 979 push(@email_to, [format_email($name, $address, $email_usename), $role]);
966 } elsif (!email_inuse($name, $address)) { 980 } elsif (!email_inuse($name, $address)) {
967 push(@email_to, [format_email($name, $address, $email_usename), $role]); 981 push(@email_to, [format_email($name, $address, $email_usename), $role]);
968 $email_hash_name{$name}++; 982 $email_hash_name{lc($name)}++;
969 $email_hash_address{$address}++; 983 $email_hash_address{lc($address)}++;
970 } 984 }
971 985
972 return 1; 986 return 1;
@@ -1259,7 +1273,7 @@ sub vcs_is_hg {
1259 return $vcs_used == 2; 1273 return $vcs_used == 2;
1260} 1274}
1261 1275
1262sub interactive_get_maintainer { 1276sub interactive_get_maintainers {
1263 my ($list_ref) = @_; 1277 my ($list_ref) = @_;
1264 my @list = @$list_ref; 1278 my @list = @$list_ref;
1265 1279
@@ -1269,11 +1283,12 @@ sub interactive_get_maintainer {
1269 my %authored; 1283 my %authored;
1270 my %signed; 1284 my %signed;
1271 my $count = 0; 1285 my $count = 0;
1272 1286 my $maintained = 0;
1273 #select maintainers by default 1287 #select maintainers by default
1274 foreach my $entry (@list){ 1288 foreach my $entry (@list) {
1275 my $role = $entry->[1]; 1289 my $role = $entry->[1];
1276 $selected{$count} = ($role =~ /^(maintainer|supporter|open list)/); 1290 $selected{$count} = ($role =~ /^(maintainer|supporter|open list)/i);
1291 $maintained = 1 if ($role =~ /^(maintainer|supporter)/i);
1277 $authored{$count} = 0; 1292 $authored{$count} = 0;
1278 $signed{$count} = 0; 1293 $signed{$count} = 0;
1279 $count++; 1294 $count++;
@@ -1286,8 +1301,14 @@ sub interactive_get_maintainer {
1286 while (!$done) { 1301 while (!$done) {
1287 $count = 0; 1302 $count = 0;
1288 if ($redraw) { 1303 if ($redraw) {
1289 printf STDERR "\n%1s %2s %-65sauth sign\n", 1304 printf STDERR "\n%1s %2s %-65s",
1290 "*", "#", "email/list and role:stats"; 1305 "*", "#", "email/list and role:stats";
1306 if ($email_git ||
1307 ($email_git_fallback && !$maintained) ||
1308 $email_git_blame) {
1309 print STDERR "auth sign";
1310 }
1311 print STDERR "\n";
1291 foreach my $entry (@list) { 1312 foreach my $entry (@list) {
1292 my $email = $entry->[0]; 1313 my $email = $entry->[0];
1293 my $role = $entry->[1]; 1314 my $role = $entry->[1];
@@ -1453,6 +1474,27 @@ sub interactive_get_maintainer {
1453 $pattern_depth = $val; 1474 $pattern_depth = $val;
1454 $rerun = 1; 1475 $rerun = 1;
1455 } 1476 }
1477 } elsif ($sel eq "h" || $sel eq "?") {
1478 print STDERR <<EOT
1479
1480Interactive mode allows you to select the various maintainers, submitters,
1481commit signers and mailing lists that could be CC'd on a patch.
1482
1483Any *'d entry is selected.
1484
1485If you have git or hg installed, You can choose to summarize the commit
1486history of files in the patch. Also, each line of the current file can
1487be matched to its commit author and that commits signers with blame.
1488
1489Various knobs exist to control the length of time for active commit
1490tracking, the maximum number of commit authors and signers to add,
1491and such.
1492
1493Enter selections at the prompt until you are satisfied that the selected
1494maintainers are appropriate. You may enter multiple selections separated
1495by either commas or spaces.
1496
1497EOT
1456 } else { 1498 } else {
1457 print STDERR "invalid option: '$nr'\n"; 1499 print STDERR "invalid option: '$nr'\n";
1458 $redraw = 0; 1500 $redraw = 0;
@@ -1461,7 +1503,7 @@ sub interactive_get_maintainer {
1461 if ($rerun) { 1503 if ($rerun) {
1462 print STDERR "git-blame can be very slow, please have patience..." 1504 print STDERR "git-blame can be very slow, please have patience..."
1463 if ($email_git_blame); 1505 if ($email_git_blame);
1464 goto &get_maintainer; 1506 goto &get_maintainers;
1465 } 1507 }
1466 } 1508 }
1467 1509
@@ -1496,9 +1538,20 @@ sub save_commits_by_author {
1496 1538
1497 foreach my $line (@lines) { 1539 foreach my $line (@lines) {
1498 if ($line =~ m/$VCS_cmds{"author_pattern"}/) { 1540 if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
1541 my $matched = 0;
1499 my $author = $1; 1542 my $author = $1;
1500 my ($name, $address) = parse_email($author); 1543 my ($name, $address) = parse_email($author);
1501 $author = format_email($name, $address, 1); 1544 foreach my $to (@interactive_to) {
1545 my ($to_name, $to_address) = parse_email($to->[0]);
1546 if ($email_remove_duplicates &&
1547 ((lc($name) eq lc($to_name)) ||
1548 (lc($address) eq lc($to_address)))) {
1549 $author = $to->[0];
1550 $matched = 1;
1551 last;
1552 }
1553 }
1554 $author = format_email($name, $address, 1) if (!$matched);
1502 push(@authors, $author); 1555 push(@authors, $author);
1503 } 1556 }
1504 push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/); 1557 push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
@@ -1539,6 +1592,20 @@ sub save_commits_by_signer {
1539 my $type = $types[0]; 1592 my $type = $types[0];
1540 my $signer = $signers[0]; 1593 my $signer = $signers[0];
1541 1594
1595 my $matched = 0;
1596 my ($name, $address) = parse_email($signer);
1597 foreach my $to (@interactive_to) {
1598 my ($to_name, $to_address) = parse_email($to->[0]);
1599 if ($email_remove_duplicates &&
1600 ((lc($name) eq lc($to_name)) ||
1601 (lc($address) eq lc($to_address)))) {
1602 $signer = $to->[0];
1603 $matched = 1;
1604 last;
1605 }
1606 $signer = format_email($name, $address, 1) if (!$matched);
1607 }
1608
1542 my $exists = 0; 1609 my $exists = 0;
1543 foreach my $ref(@{$commit_signer_hash{$signer}}) { 1610 foreach my $ref(@{$commit_signer_hash{$signer}}) {
1544 if (@{$ref}[0] eq $commit && 1611 if (@{$ref}[0] eq $commit &&