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