diff options
Diffstat (limited to 'third_party/git/contrib/contacts/git-contacts')
-rwxr-xr-x | third_party/git/contrib/contacts/git-contacts | 203 |
1 files changed, 0 insertions, 203 deletions
diff --git a/third_party/git/contrib/contacts/git-contacts b/third_party/git/contrib/contacts/git-contacts deleted file mode 100755 index 85ad732fc063..000000000000 --- a/third_party/git/contrib/contacts/git-contacts +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/perl - -# List people who might be interested in a patch. Useful as the argument to -# git-send-email --cc-cmd option, and in other situations. -# -# Usage: git contacts <file | rev-list option> ... - -use strict; -use warnings; -use IPC::Open2; - -my $since = '5-years-ago'; -my $min_percent = 10; -my $labels_rx = qr/Signed-off-by|Reviewed-by|Acked-by|Cc|Reported-by/i; -my %seen; - -sub format_contact { - my ($name, $email) = @_; - return "$name <$email>"; -} - -sub parse_commit { - my ($commit, $data) = @_; - my $contacts = $commit->{contacts}; - my $inbody = 0; - for (split(/^/m, $data)) { - if (not $inbody) { - if (/^author ([^<>]+) <(\S+)> .+$/) { - $contacts->{format_contact($1, $2)} = 1; - } elsif (/^$/) { - $inbody = 1; - } - } elsif (/^$labels_rx:\s+([^<>]+)\s+<(\S+?)>$/o) { - $contacts->{format_contact($1, $2)} = 1; - } - } -} - -sub import_commits { - my ($commits) = @_; - return unless %$commits; - my $pid = open2 my $reader, my $writer, qw(git cat-file --batch); - for my $id (keys(%$commits)) { - print $writer "$id\n"; - my $line = <$reader>; - if ($line =~ /^([0-9a-f]{40}) commit (\d+)/) { - my ($cid, $len) = ($1, $2); - die "expected $id but got $cid\n" unless $id eq $cid; - my $data; - # cat-file emits newline after data, so read len+1 - read $reader, $data, $len + 1; - parse_commit($commits->{$id}, $data); - } - } - close $reader; - close $writer; - waitpid($pid, 0); - die "git-cat-file error: $?\n" if $?; -} - -sub get_blame { - my ($commits, $source, $from, $ranges) = @_; - return unless @$ranges; - open my $f, '-|', - qw(git blame --porcelain -C), - map({"-L$_->[0],+$_->[1]"} @$ranges), - '--since', $since, "$from^", '--', $source or die; - while (<$f>) { - if (/^([0-9a-f]{40}) \d+ \d+ \d+$/) { - my $id = $1; - $commits->{$id} = { id => $id, contacts => {} } - unless $seen{$id}; - $seen{$id} = 1; - } - } - close $f; -} - -sub blame_sources { - my ($sources, $commits) = @_; - for my $s (keys %$sources) { - for my $id (keys %{$sources->{$s}}) { - get_blame($commits, $s, $id, $sources->{$s}{$id}); - } - } -} - -sub scan_patches { - my ($sources, $id, $f) = @_; - my $source; - while (<$f>) { - if (/^From ([0-9a-f]{40}) Mon Sep 17 00:00:00 2001$/) { - $id = $1; - $seen{$id} = 1; - } - next unless $id; - if (m{^--- (?:a/(.+)|/dev/null)$}) { - $source = $1; - } elsif (/^@@ -(\d+)(?:,(\d+))?/ && $source) { - my $len = defined($2) ? $2 : 1; - push @{$sources->{$source}{$id}}, [$1, $len] if $len; - } - } -} - -sub scan_patch_file { - my ($commits, $file) = @_; - open my $f, '<', $file or die "read failure: $file: $!\n"; - scan_patches($commits, undef, $f); - close $f; -} - -sub parse_rev_args { - my @args = @_; - open my $f, '-|', - qw(git rev-parse --revs-only --default HEAD --symbolic), @args - or die; - my @revs; - while (<$f>) { - chomp; - push @revs, $_; - } - close $f; - return @revs if scalar(@revs) != 1; - return "^$revs[0]", 'HEAD' unless $revs[0] =~ /^-/; - return $revs[0], 'HEAD'; -} - -sub scan_rev_args { - my ($commits, $args) = @_; - my @revs = parse_rev_args(@$args); - open my $f, '-|', qw(git rev-list --reverse), @revs or die; - while (<$f>) { - chomp; - my $id = $_; - $seen{$id} = 1; - open my $g, '-|', qw(git show -C --oneline), $id or die; - scan_patches($commits, $id, $g); - close $g; - } - close $f; -} - -sub mailmap_contacts { - my ($contacts) = @_; - my %mapped; - my $pid = open2 my $reader, my $writer, qw(git check-mailmap --stdin); - for my $contact (keys(%$contacts)) { - print $writer "$contact\n"; - my $canonical = <$reader>; - chomp $canonical; - $mapped{$canonical} += $contacts->{$contact}; - } - close $reader; - close $writer; - waitpid($pid, 0); - die "git-check-mailmap error: $?\n" if $?; - return \%mapped; -} - -if (!@ARGV) { - die "No input revisions or patch files\n"; -} - -my (@files, @rev_args); -for (@ARGV) { - if (-e) { - push @files, $_; - } else { - push @rev_args, $_; - } -} - -my %sources; -for (@files) { - scan_patch_file(\%sources, $_); -} -if (@rev_args) { - scan_rev_args(\%sources, \@rev_args) -} - -my $toplevel = `git rev-parse --show-toplevel`; -chomp $toplevel; -chdir($toplevel) or die "chdir failure: $toplevel: $!\n"; - -my %commits; -blame_sources(\%sources, \%commits); -import_commits(\%commits); - -my $contacts = {}; -for my $commit (values %commits) { - for my $contact (keys %{$commit->{contacts}}) { - $contacts->{$contact}++; - } -} -$contacts = mailmap_contacts($contacts); - -my $ncommits = scalar(keys %commits); -for my $contact (keys %$contacts) { - my $percent = $contacts->{$contact} * 100 / $ncommits; - next if $percent < $min_percent; - print "$contact\n"; -} |