git-shortlog.perlon commit Big tool rename. (215a7ad)
   1#!/usr/bin/perl -w
   2
   3use strict;
   4
   5#
   6# Even with git, we don't always have name translations.
   7# So have an email->real name table to translate the
   8# (hopefully few) missing names
   9#
  10my %mailmap = (
  11        'R.Marek@sh.cvut.cz' => 'Rudolf Marek',
  12        'Ralf.Wildenhues@gmx.de' => 'Ralf Wildenhues',
  13        'aherrman@de.ibm.com' => 'Andreas Herrmann',
  14        'akpm@osdl.org' => 'Andrew Morton',
  15        'andrew.vasquez@qlogic.com' => 'Andrew Vasquez',
  16        'aquynh@gmail.com' => 'Nguyen Anh Quynh',
  17        'axboe@suse.de' => 'Jens Axboe',
  18        'blaisorblade@yahoo.it' => 'Paolo \'Blaisorblade\' Giarrusso',
  19        'bunk@stusta.de' => 'Adrian Bunk',
  20        'domen@coderock.org' => 'Domen Puncer',
  21        'dougg@torque.net' => 'Douglas Gilbert',
  22        'dwmw2@shinybook.infradead.org' => 'David Woodhouse',
  23        'ecashin@coraid.com' => 'Ed L Cashin',
  24        'felix@derklecks.de' => 'Felix Moeller',
  25        'fzago@systemfabricworks.com' => 'Frank Zago',
  26        'gregkh@suse.de' => 'Greg Kroah-Hartman',
  27        'hch@lst.de' => 'Christoph Hellwig',
  28        'htejun@gmail.com' => 'Tejun Heo',
  29        'jejb@mulgrave.(none)' => 'James Bottomley',
  30        'jejb@titanic.il.steeleye.com' => 'James Bottomley',
  31        'jgarzik@pretzel.yyz.us' => 'Jeff Garzik',
  32        'johnpol@2ka.mipt.ru' => 'Evgeniy Polyakov',
  33        'kay.sievers@vrfy.org' => 'Kay Sievers',
  34        'minyard@acm.org' => 'Corey Minyard',
  35        'mshah@teja.com' => 'Mitesh shah',
  36        'pj@ludd.ltu.se' => 'Peter A Jonsson',
  37        'rmps@joel.ist.utl.pt' => 'Rui Saraiva',
  38        'santtu.hyrkko@gmail.com' => 'Santtu Hyrkkö',
  39        'simon@thekelleys.org.uk' => 'Simon Kelley',
  40        'ssant@in.ibm.com' => 'Sachin P Sant',
  41        'terra@gnome.org' => 'Morten Welinder',
  42        'tony.luck@intel.com' => 'Tony Luck',
  43        'welinder@anemone.rentec.com' => 'Morten Welinder',
  44        'welinder@darter.rentec.com' => 'Morten Welinder',
  45        'welinder@troll.com' => 'Morten Welinder',
  46);
  47
  48my (%map);
  49my $pstate = 1;
  50my $n_records = 0;
  51my $n_output = 0;
  52
  53
  54sub shortlog_entry($$) {
  55        my ($name, $desc) = @_;
  56        my $key = $name;
  57
  58        $desc =~ s#/pub/scm/linux/kernel/git/#/.../#g;
  59        $desc =~ s#\[PATCH\] ##g;
  60
  61        # store description in array, in email->{desc list} map
  62        if (exists $map{$key}) {
  63                # grab ref
  64                my $obj = $map{$key};
  65
  66                # add desc to array
  67                push(@$obj, $desc);
  68        } else {
  69                # create new array, containing 1 item
  70                my @arr = ($desc);
  71
  72                # store ref to array
  73                $map{$key} = \@arr;
  74        }
  75}
  76
  77# sort comparison function
  78sub by_name($$) {
  79        my ($a, $b) = @_;
  80
  81        uc($a) cmp uc($b);
  82}
  83
  84sub shortlog_output {
  85        my ($obj, $key, $desc);
  86
  87        foreach $key (sort by_name keys %map) {
  88                # output author
  89                printf "%s:\n", $key;
  90
  91                # output author's 1-line summaries
  92                $obj = $map{$key};
  93                foreach $desc (reverse @$obj) {
  94                        print "  $desc\n";
  95                        $n_output++;
  96                }
  97
  98                # blank line separating author from next author
  99                print "\n";
 100        }
 101}
 102
 103sub changelog_input {
 104        my ($author, $desc);
 105
 106        while (<>) {
 107                # get author and email
 108                if ($pstate == 1) {
 109                        my ($email);
 110
 111                        next unless /^Author: (.*)<(.*)>.*$/;
 112        
 113                        $n_records++;
 114        
 115                        $author = $1;
 116                        $email = $2;
 117                        $desc = undef;
 118
 119                        # trim trailing whitespace.
 120                        # why doesn't chomp work?
 121                        while ($author && ($author =~ /\s$/)) {
 122                                chop $author;
 123                        }
 124        
 125                        # cset author fixups
 126                        if (exists $mailmap{$email}) {
 127                                $author = $mailmap{$email};
 128                        } elsif (exists $mailmap{$author}) {
 129                                $author = $mailmap{$author};
 130                        } elsif ((!$author) || ($author eq "")) {
 131                                $author = $email;
 132                        }
 133        
 134                        $pstate++;
 135                }
 136        
 137                # skip to blank line
 138                elsif ($pstate == 2) {
 139                        next unless /^\s*$/;
 140                        $pstate++;
 141                }
 142        
 143                # skip to non-blank line
 144                elsif ($pstate == 3) {
 145                        next unless /^\s*(\S.*)$/;
 146
 147                        # skip lines that are obviously not
 148                        # a 1-line cset description
 149                        next if /^\s*From: /;
 150
 151                        chomp;
 152                        $desc = $1;
 153        
 154                        &shortlog_entry($author, $desc);
 155        
 156                        $pstate = 1;
 157                }
 158        
 159                else {
 160                        die "invalid parse state $pstate";
 161                }
 162        }
 163}
 164
 165sub finalize {
 166        #print "\n$n_records records parsed.\n";
 167
 168        if ($n_records != $n_output) {
 169                die "parse error: input records != output records\n";
 170        }
 171}
 172
 173&changelog_input;
 174&shortlog_output;
 175&finalize;
 176exit(0);
 177