aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/get_maintainer.pl
diff options
context:
space:
mode:
authorJoe Perches <joe@perches.com>2009-12-14 21:00:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:28 -0500
commita8af2430f3fb997951eff3d0d51cb166b399782b (patch)
treee7a82410bd26354ee5888ed54de563d514f85f51 /scripts/get_maintainer.pl
parent3c7385b81f721f0e7648d5134afb2088b28f8c69 (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/get_maintainer.pl')
-rwxr-xr-xscripts/get_maintainer.pl198
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
511sub format_email { 509sub 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
786sub mailmap { 784sub 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
812sub recent_git_signoffs { 810my $printed_nogit = 0;
813 my ($file) = @_; 811my $printed_nogitdir = 0;
814 812sub 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
834sub 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
866sub 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
909sub 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
881sub save_commits { 922sub 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 {
897sub git_assign_blame { 940sub 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
974sub uniq { 984sub 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
982sub sort_and_uniq { 992sub 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
1010sub output { 1020sub 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) {