/usr/libexec/git-core
NameSizeModeActions
mergetools/-0755rm
git43973520755editdlrm
git-add43973520755editdlrm
git-am43973520755editdlrm
git-annotate43973520755editdlrm
git-apply43973520755editdlrm
git-archive43973520755editdlrm
git-backfill43973520755editdlrm
git-bisect43973520755editdlrm
git-blame43973520755editdlrm
git-branch43973520755editdlrm
git-bugreport43973520755editdlrm
git-bundle43973520755editdlrm
git-cat-file43973520755editdlrm
git-check-attr43973520755editdlrm
git-check-ignore43973520755editdlrm
git-check-mailmap43973520755editdlrm
git-check-ref-format43973520755editdlrm
git-checkout43973520755editdlrm
git-checkout--worker43973520755editdlrm
git-checkout-index43973520755editdlrm
git-cherry43973520755editdlrm
git-cherry-pick43973520755editdlrm
git-clean43973520755editdlrm
git-clone43973520755editdlrm
git-column43973520755editdlrm
git-commit43973520755editdlrm
git-commit-graph43973520755editdlrm
git-commit-tree43973520755editdlrm
git-config43973520755editdlrm
git-contacts45090755editdlrm
git-count-objects43973520755editdlrm
git-credential43973520755editdlrm
git-credential-cache43973520755editdlrm
git-credential-cache--daemon43973520755editdlrm
git-credential-netrc112460755editdlrm
git-credential-store43973520755editdlrm
git-describe43973520755editdlrm
git-diagnose43973520755editdlrm
git-diff43973520755editdlrm
git-diff-files43973520755editdlrm
git-diff-index43973520755editdlrm
git-diff-pairs43973520755editdlrm
git-diff-tree43973520755editdlrm
git-difftool43973520755editdlrm
git-difftool--helper26640755editdlrm
git-fast-export43973520755editdlrm
git-fast-import43973520755editdlrm
git-fetch43973520755editdlrm
git-fetch-pack43973520755editdlrm
git-filter-branch157950755editdlrm
git-fmt-merge-msg43973520755editdlrm
git-for-each-ref43973520755editdlrm
git-for-each-repo43973520755editdlrm
git-format-patch43973520755editdlrm
git-fsck43973520755editdlrm
git-fsck-objects43973520755editdlrm
git-fsmonitor--daemon43973520755editdlrm
git-gc43973520755editdlrm
git-get-tar-commit-id43973520755editdlrm
git-grep43973520755editdlrm
git-hash-object43973520755editdlrm
git-help43973520755editdlrm
git-hook43973520755editdlrm
git-http-backend8488480755editdlrm
git-http-fetch9332800755editdlrm
git-http-push12950160755editdlrm
git-imap-send9200720755editdlrm
git-index-pack43973520755editdlrm
git-init43973520755editdlrm
git-init-db43973520755editdlrm
git-interpret-trailers43973520755editdlrm
git-last-modified43973520755editdlrm
git-log43973520755editdlrm
git-ls-files43973520755editdlrm
git-ls-remote43973520755editdlrm
git-ls-tree43973520755editdlrm
git-mailinfo43973520755editdlrm
git-mailsplit43973520755editdlrm
git-maintenance43973520755editdlrm
git-merge43973520755editdlrm
git-merge-base43973520755editdlrm
git-merge-file43973520755editdlrm
git-merge-index43973520755editdlrm
git-merge-octopus24810755editdlrm
git-merge-one-file36990755editdlrm
git-merge-ours43973520755editdlrm
git-merge-recursive43973520755editdlrm
git-merge-resolve12300755editdlrm
git-merge-subtree43973520755editdlrm
git-merge-tree43973520755editdlrm
git-mergetool116970755editdlrm
git-mergetool--lib109080644editdlrm
git-mktag43973520755editdlrm
git-mktree43973520755editdlrm
git-multi-pack-index43973520755editdlrm
git-mv43973520755editdlrm
git-name-rev43973520755editdlrm
git-notes43973520755editdlrm
git-pack-objects43973520755editdlrm
git-pack-redundant43973520755editdlrm
git-pack-refs43973520755editdlrm
git-patch-id43973520755editdlrm
git-prune43973520755editdlrm
git-prune-packed43973520755editdlrm
git-pull43973520755editdlrm
git-push43973520755editdlrm
git-quiltimport37000755editdlrm
git-range-diff43973520755editdlrm
git-read-tree43973520755editdlrm
git-rebase43973520755editdlrm
git-receive-pack43973520755editdlrm
git-reflog43973520755editdlrm
git-refs43973520755editdlrm
git-remote43973520755editdlrm
git-remote-ext43973520755editdlrm
git-remote-fd43973520755editdlrm
git-remote-ftp9668400755editdlrm
git-remote-ftps9668400755editdlrm
git-remote-http9668400755editdlrm
git-remote-https9668400755editdlrm
git-repack43973520755editdlrm
git-replace43973520755editdlrm
git-replay43973520755editdlrm
git-repo43973520755editdlrm
git-request-pull39960755editdlrm
git-rerere43973520755editdlrm
git-reset43973520755editdlrm
git-restore43973520755editdlrm
git-rev-list43973520755editdlrm
git-rev-parse43973520755editdlrm
git-revert43973520755editdlrm
git-rm43973520755editdlrm
git-send-pack43973520755editdlrm
git-sh-i18n16830644editdlrm
git-sh-i18n--envsubst8312640755editdlrm
git-sh-setup83980644editdlrm
git-shell8269600755editdlrm
git-shortlog43973520755editdlrm
git-show43973520755editdlrm
git-show-branch43973520755editdlrm
git-show-index43973520755editdlrm
git-show-ref43973520755editdlrm
git-sparse-checkout43973520755editdlrm
git-stage43973520755editdlrm
git-stash43973520755editdlrm
git-status43973520755editdlrm
git-stripspace43973520755editdlrm
git-submodule104970755editdlrm
git-submodule--helper43973520755editdlrm
git-switch43973520755editdlrm
git-symbolic-ref43973520755editdlrm
git-tag43973520755editdlrm
git-unpack-file43973520755editdlrm
git-unpack-objects43973520755editdlrm
git-update-index43973520755editdlrm
git-update-ref43973520755editdlrm
git-update-server-info43973520755editdlrm
git-upload-archive43973520755editdlrm
git-upload-pack43973520755editdlrm
git-var43973520755editdlrm
git-verify-commit43973520755editdlrm
git-verify-pack43973520755editdlrm
git-verify-tag43973520755editdlrm
git-version43973520755editdlrm
git-web--browse44050755editdlrm
git-whatchanged43973520755editdlrm
git-worktree43973520755editdlrm
git-write-tree43973520755editdlrm
scalar8769680755editdlrm
Edit: /usr/libexec/git-core/git-contacts (4509B)
#!/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 ... 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"; }