diff options
author | Joe Perches <joe@perches.com> | 2010-10-26 17:22:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 19:52:17 -0400 |
commit | 6ef1c52e122b675acc88a8b016d6477f67988b91 (patch) | |
tree | ae38fb0fa0811356aa95c5bf8246eb0f9826e37c /scripts | |
parent | 683c6f8fcbcb6de8d07545ba70aff49e50d8bcf2 (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')
-rwxr-xr-x | scripts/get_maintainer.pl | 135 |
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 @@ | |||
13 | use strict; | 13 | use strict; |
14 | 14 | ||
15 | my $P = $0; | 15 | my $P = $0; |
16 | my $V = '0.26-beta3'; | 16 | my $V = '0.26-beta4'; |
17 | 17 | ||
18 | use Getopt::Long qw(:config no_auto_abbrev); | 18 | use 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 = (); | |||
407 | my @web = (); | 408 | my @web = (); |
408 | my @subsystem = (); | 409 | my @subsystem = (); |
409 | my @status = (); | 410 | my @status = (); |
411 | my @interactive_to = (); | ||
410 | my $signature_pattern; | 412 | my $signature_pattern; |
411 | 413 | ||
412 | my @to = get_maintainer(); | 414 | my @maintainers = get_maintainers(); |
413 | 415 | ||
414 | @to = merge_email(@to); | 416 | if (@maintainers) { |
415 | 417 | @maintainers = merge_email(@maintainers); | |
416 | output(@to) if (@to); | 418 | output(@maintainers); |
419 | } | ||
417 | 420 | ||
418 | if ($scm) { | 421 | if ($scm) { |
419 | @scm = uniq(@scm); | 422 | @scm = uniq(@scm); |
@@ -437,7 +440,7 @@ if ($web) { | |||
437 | 440 | ||
438 | exit($exit); | 441 | exit($exit); |
439 | 442 | ||
440 | sub get_maintainer { | 443 | sub 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 | ||
1262 | sub interactive_get_maintainer { | 1276 | sub 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 | |||
1480 | Interactive mode allows you to select the various maintainers, submitters, | ||
1481 | commit signers and mailing lists that could be CC'd on a patch. | ||
1482 | |||
1483 | Any *'d entry is selected. | ||
1484 | |||
1485 | If you have git or hg installed, You can choose to summarize the commit | ||
1486 | history of files in the patch. Also, each line of the current file can | ||
1487 | be matched to its commit author and that commits signers with blame. | ||
1488 | |||
1489 | Various knobs exist to control the length of time for active commit | ||
1490 | tracking, the maximum number of commit authors and signers to add, | ||
1491 | and such. | ||
1492 | |||
1493 | Enter selections at the prompt until you are satisfied that the selected | ||
1494 | maintainers are appropriate. You may enter multiple selections separated | ||
1495 | by either commas or spaces. | ||
1496 | |||
1497 | EOT | ||
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 && |