diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 5e4fb144a04f657ebd43fb0c64145147d522d7d1..9c3986f4140c47c089f96bead3331a5b5d9d6cef 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -98,6 +98,7 @@ my %VCS_cmds_git = ( "available" => '(which("git") ne "") && (-d ".git")', "find_signers_cmd" => "git log --no-color --follow --since=\$email_git_since " . + '--numstat --no-merges ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . @@ -106,6 +107,7 @@ my %VCS_cmds_git = ( " -- \$file", "find_commit_signers_cmd" => "git log --no-color " . + '--numstat ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . @@ -114,6 +116,7 @@ my %VCS_cmds_git = ( " -1 \$commit", "find_commit_author_cmd" => "git log --no-color " . + '--numstat ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . @@ -125,6 +128,7 @@ my %VCS_cmds_git = ( "blame_commit_pattern" => "^([0-9a-f]+) ", "author_pattern" => "^GitAuthor: (.*)", "subject_pattern" => "^GitSubject: (.*)", + "stat_pattern" => "^(\\d+)\\t(\\d+)\\t\$file\$", ); my %VCS_cmds_hg = ( @@ -152,6 +156,7 @@ my %VCS_cmds_hg = ( "blame_commit_pattern" => "^([ 0-9a-f]+):", "author_pattern" => "^HgAuthor: (.*)", "subject_pattern" => "^HgSubject: (.*)", + "stat_pattern" => "^(\\d+)\t(\\d+)\t\$file\$", ); my $conf = which_conf(".get_maintainer.conf"); @@ -1269,20 +1274,30 @@ sub extract_formatted_signatures { } sub vcs_find_signers { - my ($cmd) = @_; + my ($cmd, $file) = @_; my $commits; my @lines = (); my @signatures = (); + my @authors = (); + my @stats = (); @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); my $pattern = $VCS_cmds{"commit_pattern"}; + my $author_pattern = $VCS_cmds{"author_pattern"}; + my $stat_pattern = $VCS_cmds{"stat_pattern"}; + + $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern $commits = grep(/$pattern/, @lines); # of commits + @authors = grep(/$author_pattern/, @lines); @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines); + @stats = grep(/$stat_pattern/, @lines); - return (0, @signatures) if !@signatures; +# print("stats: <@stats>\n"); + + return (0, \@signatures, \@authors, \@stats) if !@signatures; save_commits_by_author(@lines) if ($interactive); save_commits_by_signer(@lines) if ($interactive); @@ -1291,9 +1306,10 @@ sub vcs_find_signers { @signatures = grep(!/${penguin_chiefs}/i, @signatures); } + my ($author_ref, $authors_ref) = extract_formatted_signatures(@authors); my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures); - return ($commits, @$signers_ref); + return ($commits, $signers_ref, $authors_ref, \@stats); } sub vcs_find_author { @@ -1849,7 +1865,12 @@ sub vcs_assign { sub vcs_file_signoffs { my ($file) = @_; + my $authors_ref; + my $signers_ref; + my $stats_ref; + my @authors = (); my @signers = (); + my @stats = (); my $commits; $vcs_used = vcs_exists(); @@ -1858,13 +1879,59 @@ sub vcs_file_signoffs { my $cmd = $VCS_cmds{"find_signers_cmd"}; $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd - ($commits, @signers) = vcs_find_signers($cmd); + ($commits, $signers_ref, $authors_ref, $stats_ref) = vcs_find_signers($cmd, $file); + + @signers = @{$signers_ref} if defined $signers_ref; + @authors = @{$authors_ref} if defined $authors_ref; + @stats = @{$stats_ref} if defined $stats_ref; + +# print("commits: <$commits>\nsigners:<@signers>\nauthors: <@authors>\nstats: <@stats>\n"); foreach my $signer (@signers) { $signer = deduplicate_email($signer); } vcs_assign("commit_signer", $commits, @signers); + vcs_assign("authored", $commits, @authors); + if ($#authors == $#stats) { + my $stat_pattern = $VCS_cmds{"stat_pattern"}; + $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern + + my $added = 0; + my $deleted = 0; + for (my $i = 0; $i <= $#stats; $i++) { + if ($stats[$i] =~ /$stat_pattern/) { + $added += $1; + $deleted += $2; + } + } + my @tmp_authors = uniq(@authors); + foreach my $author (@tmp_authors) { + $author = deduplicate_email($author); + } + @tmp_authors = uniq(@tmp_authors); + my @list_added = (); + my @list_deleted = (); + foreach my $author (@tmp_authors) { + my $auth_added = 0; + my $auth_deleted = 0; + for (my $i = 0; $i <= $#stats; $i++) { + if ($author eq deduplicate_email($authors[$i]) && + $stats[$i] =~ /$stat_pattern/) { + $auth_added += $1; + $auth_deleted += $2; + } + } + for (my $i = 0; $i < $auth_added; $i++) { + push(@list_added, $author); + } + for (my $i = 0; $i < $auth_deleted; $i++) { + push(@list_deleted, $author); + } + } + vcs_assign("added_lines", $added, @list_added); + vcs_assign("removed_lines", $deleted, @list_deleted); + } } sub vcs_file_blame { @@ -1887,6 +1954,10 @@ sub vcs_file_blame { if ($email_git_blame_signatures) { if (vcs_is_hg()) { my $commit_count; + my $commit_authors_ref; + my $commit_signers_ref; + my $stats_ref; + my @commit_authors = (); my @commit_signers = (); my $commit = join(" -r ", @commits); my $cmd; @@ -1894,19 +1965,27 @@ sub vcs_file_blame { $cmd = $VCS_cmds{"find_commit_signers_cmd"}; $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd - ($commit_count, @commit_signers) = vcs_find_signers($cmd); + ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file); + @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref; + @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref; push(@signers, @commit_signers); } else { foreach my $commit (@commits) { my $commit_count; + my $commit_authors_ref; + my $commit_signers_ref; + my $stats_ref; + my @commit_authors = (); my @commit_signers = (); my $cmd; $cmd = $VCS_cmds{"find_commit_signers_cmd"}; $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd - ($commit_count, @commit_signers) = vcs_find_signers($cmd); + ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file); + @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref; + @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref; push(@signers, @commit_signers); }