git-commit-vandalism/git-shortlog.perl
Junio C Hamano 215a7ad1ef Big tool rename.
As promised, this is the "big tool rename" patch.  The primary differences
since 0.99.6 are:

  (1) git-*-script are no more.  The commands installed do not
      have any such suffix so users do not have to remember if
      something is implemented as a shell script or not.

  (2) Many command names with 'cache' in them are renamed with
      'index' if that is what they mean.

There are backward compatibility symblic links so that you and
Porcelains can keep using the old names, but the backward
compatibility support  is expected to be removed in the near
future.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-09-07 17:45:20 -07:00

178 lines
3.8 KiB
Perl
Executable File

#!/usr/bin/perl -w
use strict;
#
# Even with git, we don't always have name translations.
# So have an email->real name table to translate the
# (hopefully few) missing names
#
my %mailmap = (
'R.Marek@sh.cvut.cz' => 'Rudolf Marek',
'Ralf.Wildenhues@gmx.de' => 'Ralf Wildenhues',
'aherrman@de.ibm.com' => 'Andreas Herrmann',
'akpm@osdl.org' => 'Andrew Morton',
'andrew.vasquez@qlogic.com' => 'Andrew Vasquez',
'aquynh@gmail.com' => 'Nguyen Anh Quynh',
'axboe@suse.de' => 'Jens Axboe',
'blaisorblade@yahoo.it' => 'Paolo \'Blaisorblade\' Giarrusso',
'bunk@stusta.de' => 'Adrian Bunk',
'domen@coderock.org' => 'Domen Puncer',
'dougg@torque.net' => 'Douglas Gilbert',
'dwmw2@shinybook.infradead.org' => 'David Woodhouse',
'ecashin@coraid.com' => 'Ed L Cashin',
'felix@derklecks.de' => 'Felix Moeller',
'fzago@systemfabricworks.com' => 'Frank Zago',
'gregkh@suse.de' => 'Greg Kroah-Hartman',
'hch@lst.de' => 'Christoph Hellwig',
'htejun@gmail.com' => 'Tejun Heo',
'jejb@mulgrave.(none)' => 'James Bottomley',
'jejb@titanic.il.steeleye.com' => 'James Bottomley',
'jgarzik@pretzel.yyz.us' => 'Jeff Garzik',
'johnpol@2ka.mipt.ru' => 'Evgeniy Polyakov',
'kay.sievers@vrfy.org' => 'Kay Sievers',
'minyard@acm.org' => 'Corey Minyard',
'mshah@teja.com' => 'Mitesh shah',
'pj@ludd.ltu.se' => 'Peter A Jonsson',
'rmps@joel.ist.utl.pt' => 'Rui Saraiva',
'santtu.hyrkko@gmail.com' => 'Santtu Hyrkkö',
'simon@thekelleys.org.uk' => 'Simon Kelley',
'ssant@in.ibm.com' => 'Sachin P Sant',
'terra@gnome.org' => 'Morten Welinder',
'tony.luck@intel.com' => 'Tony Luck',
'welinder@anemone.rentec.com' => 'Morten Welinder',
'welinder@darter.rentec.com' => 'Morten Welinder',
'welinder@troll.com' => 'Morten Welinder',
);
my (%map);
my $pstate = 1;
my $n_records = 0;
my $n_output = 0;
sub shortlog_entry($$) {
my ($name, $desc) = @_;
my $key = $name;
$desc =~ s#/pub/scm/linux/kernel/git/#/.../#g;
$desc =~ s#\[PATCH\] ##g;
# store description in array, in email->{desc list} map
if (exists $map{$key}) {
# grab ref
my $obj = $map{$key};
# add desc to array
push(@$obj, $desc);
} else {
# create new array, containing 1 item
my @arr = ($desc);
# store ref to array
$map{$key} = \@arr;
}
}
# sort comparison function
sub by_name($$) {
my ($a, $b) = @_;
uc($a) cmp uc($b);
}
sub shortlog_output {
my ($obj, $key, $desc);
foreach $key (sort by_name keys %map) {
# output author
printf "%s:\n", $key;
# output author's 1-line summaries
$obj = $map{$key};
foreach $desc (reverse @$obj) {
print " $desc\n";
$n_output++;
}
# blank line separating author from next author
print "\n";
}
}
sub changelog_input {
my ($author, $desc);
while (<>) {
# get author and email
if ($pstate == 1) {
my ($email);
next unless /^Author: (.*)<(.*)>.*$/;
$n_records++;
$author = $1;
$email = $2;
$desc = undef;
# trim trailing whitespace.
# why doesn't chomp work?
while ($author && ($author =~ /\s$/)) {
chop $author;
}
# cset author fixups
if (exists $mailmap{$email}) {
$author = $mailmap{$email};
} elsif (exists $mailmap{$author}) {
$author = $mailmap{$author};
} elsif ((!$author) || ($author eq "")) {
$author = $email;
}
$pstate++;
}
# skip to blank line
elsif ($pstate == 2) {
next unless /^\s*$/;
$pstate++;
}
# skip to non-blank line
elsif ($pstate == 3) {
next unless /^\s*(\S.*)$/;
# skip lines that are obviously not
# a 1-line cset description
next if /^\s*From: /;
chomp;
$desc = $1;
&shortlog_entry($author, $desc);
$pstate = 1;
}
else {
die "invalid parse state $pstate";
}
}
}
sub finalize {
#print "\n$n_records records parsed.\n";
if ($n_records != $n_output) {
die "parse error: input records != output records\n";
}
}
&changelog_input;
&shortlog_output;
&finalize;
exit(0);