diff options
author | Joe Perches <joe@perches.com> | 2009-12-14 21:00:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:53:28 -0500 |
commit | a8af2430f3fb997951eff3d0d51cb166b399782b (patch) | |
tree | e7a82410bd26354ee5888ed54de563d514f85f51 /scripts | |
parent | 3c7385b81f721f0e7648d5134afb2088b28f8c69 (diff) |
scripts/get_maintainer.pl: fix --non with --git-blame and cleanups
Fix email matching without name --n and --git-blame
Using --non and --git-blame caused maintainer signature
matching to fail. Fixed that by adding 3rd argument to
sub format_email to control show/hide name portion of address
Slurp -f file instead of reading line-by-line for K: pattern matching.
Suggested by Wolfram Sang as more efficient
Refactor git command execution
Break into 2 functions, execute/analyze
Share code between --git and --git-blame
Don't warn multiple times when git isn't installed
Improve stats reporting
--git-min-percent and -- rolestats now count the total number of commits
for either the period of --git-since or if using --git-blame the commits
used by the current file and calculate commit % as
# of commits signed / total commits * 100
Code style cleaning
Use consistent sub foo { my (args...) = @_;
Signed-off-by: Joe Perches <joe@perches.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: Greg KH <greg@kroah.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Wolfram Sang <w.sang@pengutronix.de>
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 | 198 |
1 files changed, 104 insertions, 94 deletions
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 4e11c271e613..fe91a984247b 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -182,7 +182,7 @@ if ($email_remove_duplicates) { | |||
182 | next if ($line =~ m/^\s*$/); | 182 | next if ($line =~ m/^\s*$/); |
183 | 183 | ||
184 | my ($name, $address) = parse_email($line); | 184 | my ($name, $address) = parse_email($line); |
185 | $line = format_email($name, $address); | 185 | $line = format_email($name, $address, $email_usename); |
186 | 186 | ||
187 | next if ($line =~ m/^\s*$/); | 187 | next if ($line =~ m/^\s*$/); |
188 | 188 | ||
@@ -214,12 +214,10 @@ foreach my $file (@ARGV) { | |||
214 | push(@files, $file); | 214 | push(@files, $file); |
215 | if (-f $file && $keywords) { | 215 | if (-f $file && $keywords) { |
216 | open(FILE, "<$file") or die "$P: Can't open ${file}\n"; | 216 | open(FILE, "<$file") or die "$P: Can't open ${file}\n"; |
217 | while (<FILE>) { | 217 | my $text = do { local($/) ; <FILE> }; |
218 | my $patch_line = $_; | 218 | foreach my $line (keys %keyword_hash) { |
219 | foreach my $line (keys %keyword_hash) { | 219 | if ($text =~ m/$keyword_hash{$line}/x) { |
220 | if ($patch_line =~ m/^.*$keyword_hash{$line}/x) { | 220 | push(@keyword_tvi, $line); |
221 | push(@keyword_tvi, $line); | ||
222 | } | ||
223 | } | 221 | } |
224 | } | 222 | } |
225 | close(FILE); | 223 | close(FILE); |
@@ -311,7 +309,7 @@ foreach my $file (@files) { | |||
311 | } | 309 | } |
312 | 310 | ||
313 | if ($email && $email_git) { | 311 | if ($email && $email_git) { |
314 | recent_git_signoffs($file); | 312 | git_file_signoffs($file); |
315 | } | 313 | } |
316 | 314 | ||
317 | if ($email && $email_git_blame) { | 315 | if ($email && $email_git_blame) { |
@@ -331,7 +329,7 @@ if ($email) { | |||
331 | if ($chief =~ m/^(.*):(.*)/) { | 329 | if ($chief =~ m/^(.*):(.*)/) { |
332 | my $email_address; | 330 | my $email_address; |
333 | 331 | ||
334 | $email_address = format_email($1, $2); | 332 | $email_address = format_email($1, $2, $email_usename); |
335 | if ($email_git_penguin_chiefs) { | 333 | if ($email_git_penguin_chiefs) { |
336 | push(@email_to, [$email_address, 'chief penguin']); | 334 | push(@email_to, [$email_address, 'chief penguin']); |
337 | } else { | 335 | } else { |
@@ -509,7 +507,7 @@ sub parse_email { | |||
509 | } | 507 | } |
510 | 508 | ||
511 | sub format_email { | 509 | sub format_email { |
512 | my ($name, $address) = @_; | 510 | my ($name, $address, $usename) = @_; |
513 | 511 | ||
514 | my $formatted_email; | 512 | my $formatted_email; |
515 | 513 | ||
@@ -522,11 +520,11 @@ sub format_email { | |||
522 | $name = "\"$name\""; | 520 | $name = "\"$name\""; |
523 | } | 521 | } |
524 | 522 | ||
525 | if ($email_usename) { | 523 | if ($usename) { |
526 | if ("$name" eq "") { | 524 | if ("$name" eq "") { |
527 | $formatted_email = "$address"; | 525 | $formatted_email = "$address"; |
528 | } else { | 526 | } else { |
529 | $formatted_email = "$name <${address}>"; | 527 | $formatted_email = "$name <$address>"; |
530 | } | 528 | } |
531 | } else { | 529 | } else { |
532 | $formatted_email = $address; | 530 | $formatted_email = $address; |
@@ -671,7 +669,7 @@ sub add_categories { | |||
671 | if ($tv =~ m/^(\C):\s*(.*)/) { | 669 | if ($tv =~ m/^(\C):\s*(.*)/) { |
672 | if ($1 eq "P") { | 670 | if ($1 eq "P") { |
673 | $name = $2; | 671 | $name = $2; |
674 | $pvalue = format_email($name, $address); | 672 | $pvalue = format_email($name, $address, $email_usename); |
675 | } | 673 | } |
676 | } | 674 | } |
677 | } | 675 | } |
@@ -714,9 +712,9 @@ sub push_email_address { | |||
714 | } | 712 | } |
715 | 713 | ||
716 | if (!$email_remove_duplicates) { | 714 | if (!$email_remove_duplicates) { |
717 | push(@email_to, [format_email($name, $address), $role]); | 715 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
718 | } elsif (!email_inuse($name, $address)) { | 716 | } elsif (!email_inuse($name, $address)) { |
719 | push(@email_to, [format_email($name, $address), $role]); | 717 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
720 | $email_hash_name{$name}++; | 718 | $email_hash_name{$name}++; |
721 | $email_hash_address{$address}++; | 719 | $email_hash_address{$address}++; |
722 | } | 720 | } |
@@ -747,7 +745,7 @@ sub add_role { | |||
747 | my ($line, $role) = @_; | 745 | my ($line, $role) = @_; |
748 | 746 | ||
749 | my ($name, $address) = parse_email($line); | 747 | my ($name, $address) = parse_email($line); |
750 | my $email = format_email($name, $address); | 748 | my $email = format_email($name, $address, $email_usename); |
751 | 749 | ||
752 | foreach my $entry (@email_to) { | 750 | foreach my $entry (@email_to) { |
753 | if ($email_remove_duplicates) { | 751 | if ($email_remove_duplicates) { |
@@ -784,7 +782,7 @@ sub which { | |||
784 | } | 782 | } |
785 | 783 | ||
786 | sub mailmap { | 784 | sub mailmap { |
787 | my @lines = @_; | 785 | my (@lines) = @_; |
788 | my %hash; | 786 | my %hash; |
789 | 787 | ||
790 | foreach my $line (@lines) { | 788 | foreach my $line (@lines) { |
@@ -793,14 +791,14 @@ sub mailmap { | |||
793 | $hash{$name} = $address; | 791 | $hash{$name} = $address; |
794 | } elsif ($address ne $hash{$name}) { | 792 | } elsif ($address ne $hash{$name}) { |
795 | $address = $hash{$name}; | 793 | $address = $hash{$name}; |
796 | $line = format_email($name, $address); | 794 | $line = format_email($name, $address, $email_usename); |
797 | } | 795 | } |
798 | if (exists($mailmap{$name})) { | 796 | if (exists($mailmap{$name})) { |
799 | my $obj = $mailmap{$name}; | 797 | my $obj = $mailmap{$name}; |
800 | foreach my $map_address (@$obj) { | 798 | foreach my $map_address (@$obj) { |
801 | if (($map_address eq $address) && | 799 | if (($map_address eq $address) && |
802 | ($map_address ne $hash{$name})) { | 800 | ($map_address ne $hash{$name})) { |
803 | $line = format_email($name, $hash{$name}); | 801 | $line = format_email($name, $hash{$name}, $email_usename); |
804 | } | 802 | } |
805 | } | 803 | } |
806 | } | 804 | } |
@@ -809,33 +807,44 @@ sub mailmap { | |||
809 | return @lines; | 807 | return @lines; |
810 | } | 808 | } |
811 | 809 | ||
812 | sub recent_git_signoffs { | 810 | my $printed_nogit = 0; |
813 | my ($file) = @_; | 811 | my $printed_nogitdir = 0; |
814 | 812 | sub has_git { | |
815 | my $sign_offs = ""; | ||
816 | my $cmd = ""; | ||
817 | my $output = ""; | ||
818 | my $count = 0; | ||
819 | my @lines = (); | ||
820 | my %hash; | ||
821 | my $total_sign_offs; | ||
822 | |||
823 | if (which("git") eq "") { | 813 | if (which("git") eq "") { |
824 | warn("$P: git not found. Add --nogit to options?\n"); | 814 | if (!$printed_nogit) { |
825 | return; | 815 | warn("$P: git not found. Add --nogit to options?\n"); |
816 | $printed_nogit = 1; | ||
817 | } | ||
818 | return 0; | ||
826 | } | 819 | } |
827 | if (!(-d ".git")) { | 820 | if (!(-d ".git")) { |
828 | warn("$P: .git directory not found. Use a git repository for better results.\n"); | 821 | if (!$printed_nogitdir) { |
829 | warn("$P: perhaps 'git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git'\n"); | 822 | warn(".git directory not found. " |
830 | return; | 823 | . "Using a git repository produces better results.\n"); |
824 | warn("Try Linus Torvalds' latest git repository using:\n"); | ||
825 | warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n"); | ||
826 | $printed_nogitdir = 1; | ||
827 | } | ||
828 | return 0; | ||
831 | } | 829 | } |
832 | 830 | ||
833 | $cmd = "git log --since=${email_git_since} -- ${file}"; | 831 | return 1; |
832 | } | ||
833 | |||
834 | sub git_find_signers { | ||
835 | my ($cmd) = @_; | ||
836 | |||
837 | my $output; | ||
838 | my @lines = (); | ||
839 | my $commits; | ||
840 | |||
841 | return (0, @lines) if (!has_git()); | ||
834 | 842 | ||
835 | $output = `${cmd}`; | 843 | $output = `${cmd}`; |
836 | $output =~ s/^\s*//gm; | 844 | $output =~ s/^\s*//gm; |
837 | 845 | ||
838 | @lines = split("\n", $output); | 846 | @lines = split("\n", $output); |
847 | $commits = grep(/^commit [0-9a-f]{40,40}/, @lines); # of commits | ||
839 | 848 | ||
840 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); | 849 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); |
841 | if (!$email_git_penguin_chiefs) { | 850 | if (!$email_git_penguin_chiefs) { |
@@ -844,10 +853,28 @@ sub recent_git_signoffs { | |||
844 | # cut -f2- -d":" | 853 | # cut -f2- -d":" |
845 | s/.*:\s*(.+)\s*/$1/ for (@lines); | 854 | s/.*:\s*(.+)\s*/$1/ for (@lines); |
846 | 855 | ||
847 | $total_sign_offs = @lines; | 856 | ## Reformat email addresses (with names) to avoid badly written signatures |
857 | |||
848 | foreach my $line (@lines) { | 858 | foreach my $line (@lines) { |
849 | my ($name, $address) = parse_email($line); | 859 | my ($name, $address) = parse_email($line); |
850 | $line = format_email($name, $address); | 860 | $line = format_email($name, $address, 1); |
861 | } | ||
862 | |||
863 | return ($commits, @lines); | ||
864 | } | ||
865 | |||
866 | sub git_assign_signers { | ||
867 | my ($role, $divisor, @lines) = @_; | ||
868 | |||
869 | my %hash; | ||
870 | my $count = 0; | ||
871 | |||
872 | return if (!has_git()); | ||
873 | return if (@lines <= 0); | ||
874 | |||
875 | if ($divisor <= 0) { | ||
876 | warn("Bad divisor in git_assign_signers: $divisor\n"); | ||
877 | $divisor = 1; | ||
851 | } | 878 | } |
852 | 879 | ||
853 | if ($email_remove_duplicates) { | 880 | if ($email_remove_duplicates) { |
@@ -862,27 +889,43 @@ sub recent_git_signoffs { | |||
862 | # sort -rn | 889 | # sort -rn |
863 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { | 890 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { |
864 | my $sign_offs = $hash{$line}; | 891 | my $sign_offs = $hash{$line}; |
865 | my $role; | 892 | my $percent = $sign_offs * 100 / $divisor; |
866 | 893 | ||
894 | $percent = 100 if ($percent > 100); | ||
867 | $count++; | 895 | $count++; |
868 | last if ($sign_offs < $email_git_min_signatures || | 896 | last if ($sign_offs < $email_git_min_signatures || |
869 | $count > $email_git_max_maintainers || | 897 | $count > $email_git_max_maintainers || |
870 | $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); | 898 | $percent < $email_git_min_percent); |
871 | push_email_address($line, ''); | 899 | push_email_address($line, ''); |
872 | $role = "git-signer"; | ||
873 | if ($output_rolestats) { | 900 | if ($output_rolestats) { |
874 | my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); | 901 | my $fmt_percent = sprintf("%.0f", $percent); |
875 | $role = "$role:$sign_offs/$total_sign_offs=$percent%"; | 902 | add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%"); |
903 | } else { | ||
904 | add_role($line, $role); | ||
876 | } | 905 | } |
877 | add_role($line, $role); | ||
878 | } | 906 | } |
879 | } | 907 | } |
880 | 908 | ||
909 | sub git_file_signoffs { | ||
910 | my ($file) = @_; | ||
911 | |||
912 | my @signers = (); | ||
913 | my $total_signers; | ||
914 | |||
915 | return if (!has_git()); | ||
916 | |||
917 | ($total_signers, @signers) = | ||
918 | git_find_signers("git log --since=$email_git_since -- $file"); | ||
919 | git_assign_signers("git_signer", $total_signers, @signers); | ||
920 | } | ||
921 | |||
881 | sub save_commits { | 922 | sub save_commits { |
882 | my ($cmd, @commits) = @_; | 923 | my ($cmd, @commits) = @_; |
883 | my $output; | 924 | my $output; |
884 | my @lines = (); | 925 | my @lines = (); |
885 | 926 | ||
927 | return (@lines) if (!has_git()); | ||
928 | |||
886 | $output = `${cmd}`; | 929 | $output = `${cmd}`; |
887 | 930 | ||
888 | @lines = split("\n", $output); | 931 | @lines = split("\n", $output); |
@@ -897,13 +940,10 @@ sub save_commits { | |||
897 | sub git_assign_blame { | 940 | sub git_assign_blame { |
898 | my ($file) = @_; | 941 | my ($file) = @_; |
899 | 942 | ||
900 | my @lines = (); | ||
901 | my @commits = (); | ||
902 | my $cmd; | 943 | my $cmd; |
903 | my $output; | 944 | my @commits = (); |
904 | my %hash; | 945 | my @signers = (); |
905 | my $total_sign_offs; | 946 | my $total_commits; |
906 | my $count; | ||
907 | 947 | ||
908 | if (@range) { | 948 | if (@range) { |
909 | foreach my $file_range_diff (@range) { | 949 | foreach my $file_range_diff (@range) { |
@@ -922,57 +962,27 @@ sub git_assign_blame { | |||
922 | } | 962 | } |
923 | } | 963 | } |
924 | 964 | ||
925 | $total_sign_offs = 0; | ||
926 | @commits = uniq(@commits); | 965 | @commits = uniq(@commits); |
927 | foreach my $commit (@commits) { | 966 | $total_commits = @commits; |
928 | $cmd = "git log -1 ${commit}"; | ||
929 | |||
930 | $output = `${cmd}`; | ||
931 | $output =~ s/^\s*//gm; | ||
932 | @lines = split("\n", $output); | ||
933 | |||
934 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); | ||
935 | if (!$email_git_penguin_chiefs) { | ||
936 | @lines = grep(!/${penguin_chiefs}/i, @lines); | ||
937 | } | ||
938 | |||
939 | # cut -f2- -d":" | ||
940 | s/.*:\s*(.+)\s*/$1/ for (@lines); | ||
941 | |||
942 | $total_sign_offs += @lines; | ||
943 | 967 | ||
944 | if ($email_remove_duplicates) { | 968 | foreach my $commit (@commits) { |
945 | @lines = mailmap(@lines); | 969 | my $commit_count; |
946 | } | 970 | my @commit_signers = (); |
947 | 971 | ||
948 | $hash{$_}++ for @lines; | 972 | ($commit_count, @commit_signers) = |
973 | git_find_signers("git log -1 $commit"); | ||
974 | @signers = (@signers, @commit_signers); | ||
949 | } | 975 | } |
950 | 976 | ||
951 | $count = 0; | 977 | if ($from_filename) { |
952 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { | 978 | git_assign_signers("commits", $total_commits, @signers); |
953 | my $sign_offs = $hash{$line}; | 979 | } else { |
954 | my $role; | 980 | git_assign_signers("modified commits", $total_commits, @signers); |
955 | |||
956 | $count++; | ||
957 | last if ($sign_offs < $email_git_min_signatures || | ||
958 | $count > $email_git_max_maintainers || | ||
959 | $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); | ||
960 | push_email_address($line, ''); | ||
961 | if ($from_filename) { | ||
962 | $role = "commits"; | ||
963 | } else { | ||
964 | $role = "modified commits"; | ||
965 | } | ||
966 | if ($output_rolestats) { | ||
967 | my $percent = sprintf("%.0f", $sign_offs * 100 / $total_sign_offs); | ||
968 | $role = "$role:$sign_offs/$total_sign_offs=$percent%"; | ||
969 | } | ||
970 | add_role($line, $role); | ||
971 | } | 981 | } |
972 | } | 982 | } |
973 | 983 | ||
974 | sub uniq { | 984 | sub uniq { |
975 | my @parms = @_; | 985 | my (@parms) = @_; |
976 | 986 | ||
977 | my %saw; | 987 | my %saw; |
978 | @parms = grep(!$saw{$_}++, @parms); | 988 | @parms = grep(!$saw{$_}++, @parms); |
@@ -980,7 +990,7 @@ sub uniq { | |||
980 | } | 990 | } |
981 | 991 | ||
982 | sub sort_and_uniq { | 992 | sub sort_and_uniq { |
983 | my @parms = @_; | 993 | my (@parms) = @_; |
984 | 994 | ||
985 | my %saw; | 995 | my %saw; |
986 | @parms = sort @parms; | 996 | @parms = sort @parms; |
@@ -1008,7 +1018,7 @@ sub merge_email { | |||
1008 | } | 1018 | } |
1009 | 1019 | ||
1010 | sub output { | 1020 | sub output { |
1011 | my @parms = @_; | 1021 | my (@parms) = @_; |
1012 | 1022 | ||
1013 | if ($output_multiline) { | 1023 | if ($output_multiline) { |
1014 | foreach my $line (@parms) { | 1024 | foreach my $line (@parms) { |