diff options
| -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) { |
