Skip to content

Commit fa375c7

Browse files
author
Linus Torvalds
committed
Add git-shortlog perl script
Somebody finally came through - Jeff Garzik gets a gold star for writing a shortlog script for git, so that I can do nice release announcments again. I added name translations from the current kernel history (and git, for that matter). Hopefully it won't grow at nearly the same rate the BK equivalent did, since 99% of the time git records the full name already. Usage: just do git-rev-list --pretty HEAD ^LAST_HEAD | git-shortlog or, in fact, use any of the other tools (git-diff-tree, git-whatchanged etc) that use the default "pretty" commit format.
1 parent 337cb3f commit fa375c7

File tree

2 files changed

+168
-1
lines changed

2 files changed

+168
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ INSTALL=install
2323
SCRIPTS=git git-apply-patch-script git-merge-one-file-script git-prune-script \
2424
git-pull-script git-tag-script git-resolve-script git-whatchanged \
2525
git-deltafy-script git-fetch-script git-status-script git-commit-script \
26-
git-log-script
26+
git-log-script git-shortlog
2727

2828
PROG= git-update-cache git-diff-files git-init-db git-write-tree \
2929
git-read-tree git-commit-tree git-cat-file git-fsck-cache \

git-shortlog

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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

Comments
 (0)