| #!/usr/bin/perl |
| |
| use warnings; |
| use strict; |
| use Getopt::Long; |
| |
| sub parsing () { 1; } |
| sub waiting () { 2; } |
| my $state = parsing; |
| |
| my @more; |
| my $append; |
| my $debug; |
| |
| sub find_author { |
| my $map = shift; |
| for my $name (@_) { |
| my $fh; |
| print STDERR "Checking <$name>..." |
| if ($debug); |
| if (!open($fh, "-|", |
| qw(git log -1 --no-merges), |
| '--format=%an <%ae>', |
| "--author=$name", |
| "--all")) { |
| print STDERR "opening pipe to read from git log failed\n" |
| if ($debug); |
| $map->{$name} = $name; |
| next; |
| } |
| my $line = <$fh>; |
| if ($line) { |
| chomp $line; |
| print STDERR "read <$line> from git log\n" |
| if ($debug); |
| $map->{$name} = $line; |
| } else { |
| print STDERR "read false ($line) from git log\n" |
| if ($debug); |
| $map->{$name} = $name; |
| } |
| } |
| } |
| |
| sub accumulate { |
| push @more, [@_]; |
| } |
| |
| my $mine; |
| |
| sub compute_bylines { |
| my %names = map { $_->[1] => 1 } @more; |
| my %map = (); |
| my @append; |
| find_author(\%map, keys (%names)); |
| for (@more) { |
| my ($tag, $name) = @$_; |
| if ($tag eq 'mine') { |
| $mine = $map{$name}; |
| next; |
| } |
| $tag = ucfirst($tag); |
| push @append, "$tag: $map{$name}"; |
| } |
| if (@append) { |
| $append = join("\n", @append) . "\n"; |
| } else { |
| $append = ""; |
| } |
| } |
| |
| sub add_more_bylines { |
| if (!defined $append) { |
| compute_bylines(); |
| } |
| print $append; |
| } |
| |
| my $check_only; |
| |
| exit 1 unless (GetOptions("signed-off-by=s" => \&accumulate, |
| "acked-by=s" => \&accumulate, |
| "reviewed-by=s" => \&accumulate, |
| "tested-by=s" => \&accumulate, |
| "helped-by=s" => \&accumulate, |
| "check-only!" => \$check_only, |
| "mine=s" => \&accumulate, |
| "debug!" => \$debug, |
| )); |
| |
| compute_bylines(); |
| |
| if ($check_only) { |
| add_more_bylines(); |
| exit 0; |
| } |
| |
| my $seen_mine = 0; |
| while (<>) { |
| if ($state == parsing) { |
| if (/^[-A-Za-z]+-by: /i || /^Cc: /i) { |
| $state = waiting; |
| } |
| } elsif ($state == waiting) { |
| if (defined $mine && /^Signed-off-by: \Q$mine\E/) { |
| $seen_mine = 1; |
| next; |
| } elsif (/^[-A-Za-z]+-by: /i || /^Cc: /i) { |
| $state = waiting; |
| } else { |
| add_more_bylines(); |
| if ($seen_mine) { |
| print "Signed-off-by: $mine\n"; |
| } |
| $state = parsing; |
| $seen_mine = 0; |
| } |
| } |
| print; |
| } |