release.sh: make the types of tarballs optional
[xorg-util-modular.git] / changelog-consolidator.pl
blob03c71d535a1e295029dac0d356206bccc0d93825
1 #! /usr/bin/perl -w
4 # Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
6 # Permission is hereby granted, free of charge, to any person obtaining a
7 # copy of this software and associated documentation files (the "Software"),
8 # to deal in the Software without restriction, including without limitation
9 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 # and/or sell copies of the Software, and to permit persons to whom the
11 # Software is furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice (including the next
14 # paragraph) shall be included in all copies or substantial portions of the
15 # Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 # DEALINGS IN THE SOFTWARE.
27 use strict;
28 use warnings;
29 use diagnostics;
30 use CGI;
31 use Getopt::Long;
33 # Currently available output formats:
34 # short - short log (default)
35 # long - full logs
36 # html - short log with cgit links
37 # stat - diff stats
39 # Input is provided as a list of modules with a from and to version, or
40 # "-" if no version is included, such as:
42 # MODULE 7.5 7.6
43 # ------ ----- ------
44 # applewmproto 1.4.1 1.4.1
45 # bdftopcf 1.0.2 1.0.3
46 # [...]
49 my $output_type = 'short';
51 my $result = GetOptions ("type=s" => \$output_type);
53 my $usage = "Usage: [--type=short|long|html|stat] <filename>\n";
55 if ((!$result) ||
56 (($output_type ne 'short') && ($output_type ne 'long') &&
57 ($output_type ne 'html')&& ($output_type ne 'stat') )) {
58 print STDERR $usage;
59 exit 1;
62 my @modtypes=qw(app data doc driver font lib proto util xcb .);
64 my %modmap = (
65 'libXres' => 'libXRes',
66 'libpthread-stubs' => 'pthread-stubs',
67 'util-macros' => 'macros',
68 'xbitmaps' => 'bitmaps',
69 'xcb-proto' => 'proto',
70 'xcursor-themes' => 'cursors',
71 'xorg-server' => 'xserver',
72 'xproto' => 'x11proto',
73 'xtrans' => 'libxtrans',
76 my %module_info = ();
78 while ($_= <>) {
79 chomp($_);
80 if ($_ =~ m/(\S+)\s+([\-\.\d]+)\s+([\.\d\-\*]+)/) {
81 my ($module, $old, $new) = ($1, $2, $3);
82 my $modtype = "?";
83 my $moddir = $module;
85 next if $new eq '-';
87 if (exists($modmap{$module})) {
88 $moddir = $modmap{$module};
91 if ($module =~ m/font-(.*)/) {
92 $moddir = $1;
93 $modtype = 'font';
94 } else {
95 foreach my $m (@modtypes) {
96 if (-d "$m/$moddir") {
97 $modtype = $m;
98 last;
103 if (($modtype ne '?') && (($old ne $new) || ($output_type eq 'html'))) {
104 if ($output_type ne 'html') {
105 print "======= $modtype/$module ($old..$new)\n\n";
107 my $oldtag = find_tag($modtype, $moddir, $module, $old);
108 my $newtag = find_tag($modtype, $moddir, $module, $new);
109 # print "$modtype/$module: $oldtag -> $newtag\n";
110 # system('git', "--git-dir=$modtype/$moddir/.git", 'log',
111 # '--pretty=short', "$oldtag..$newtag");
113 # special cases for X11R7.7
114 if ($module eq 'xkeyboard-config') {
115 $oldtag = 'xkeyboard-config-2.0';
118 my $tagrange = ($oldtag ne '') ? "$oldtag..$newtag" : "$newtag";
120 my $output_flags = ($output_type eq 'long') ? '' : '--pretty=short';
122 my $git_subcmd = ($output_type eq 'stat') ? 'diff --shortstat' : 'log';
124 my $git_log_cmd = "git --git-dir=$modtype/$moddir/.git" .
125 " $git_subcmd $output_flags $tagrange";
127 if ($output_type eq 'short') {
128 system("$git_log_cmd | git shortlog");
129 } elsif (($output_type eq 'long') || ($output_type eq 'stat')) {
130 system("$git_log_cmd");
131 } else {
132 my %changes = ();
133 open my $gsl, '-|', $git_log_cmd or die;
134 while (my $ll = <$gsl>) {
135 chomp($ll);
136 my $commit = {};
137 my $author;
139 if ($ll =~ m{^commit (\w+)$}) {
140 $commit->{id} = $1;
142 while ($ll = <$gsl>) {
143 chomp($ll);
144 last if $ll =~ m{^\s*$};
145 if ($ll =~ m{^Author:\s*(.*)\s+\<.*\>}) {
146 $author = $1;
147 } elsif ($ll !~ m{^Merge:}) {
148 die "Author match failed: $modtype/$module/$commit->{id}\n$ll\n";
152 my $desc = "";
153 while ($ll = <$gsl>) {
154 last if $ll =~ m{^\s*$};
155 $ll =~ s{^ }{};
156 $desc .= $ll;
158 chomp($desc);
159 $commit->{desc} = $desc;
161 if (!exists $changes{$author}) {
162 $changes{$author} = [ ];
164 unshift @{$changes{$author}}, $commit;
167 close $gsl;
168 my $newtagdate = `git --git-dir=$modtype/$moddir/.git log -1 --tags --simplify-by-decoration --pretty="format:%ad" --date=short $newtag`;
169 $module_info{"$modtype/$module"} =
171 changes => \%changes,
172 oldtag => $oldtag,
173 newtag => $newtag,
174 newtagdate => $newtagdate,
175 modtype => $modtype,
176 moddir => $moddir,
177 module => $module,
178 oldvers => $old,
179 newvers => $new
183 } else {
184 # print $_, "\n";
188 if ($output_type eq 'html') {
189 my $q = new CGI;
191 my $title = 'Consolidated ChangeLog for X11R7.7';
192 print $q->start_html(-title => $title,
193 -style=>{-src =>'http://cgit.freedesktop.org/cgit.css',
194 -code => '.modules { float: left; }' .
195 '.modules > td { padding-left: 3px; }'
197 -encoding => 'utf-8',
198 -head => [
199 $q->Link({-rel => 'home',
200 -href => 'http://www.x.org/'}),
201 $q->Link({-rel => 'SHORTCUT ICON',
202 -href => 'favicon.ico'}),
203 $q->Link({-rel => 'up',
204 -href => 'index.html'}),
206 -itemscope => undef,
207 -itemtype => 'http://schema.org/WebPage'
208 ), "\n";
209 print
210 $q->div({ -style => 'text-align: center;',
211 -itemprop => 'publisher', -content => 'X.Org Foundation' },
212 $q->a({ -href => 'http://www.x.org/', -rel => 'home'},
213 $q->img({ -src => 'logo.png', -border => '0',
214 -alt => 'X.Org Foundation' }))), "\n",
215 $q->h1($title), "\n";
217 print $q->start_table({ -class => 'modules', -cols => '4' }), "\n",
218 $q->Tr($q->th({-colspan=>"2"}, 'Module'),
219 $q->th([' X11R7.6 ', ' X11R7.7 '])), "\n";
221 my $midpoint = scalar(keys %module_info) / 2;
223 foreach my $m (sort keys %module_info) {
224 my $modname = $module_info{$m}->{module};
225 my $moddisplay = $m;
226 print $q->Tr($q->td( [
227 $module_info{$m}->{modtype},
228 $q->a({href=>"#$modname"},
229 $module_info{$m}->{moddir}),
230 $module_info{$m}->{oldvers},
231 $module_info{$m}->{newvers}
232 ])), "\n";
233 if (--$midpoint == 0) {
234 print $q->end_table();
235 print $q->start_table({ -class => 'modules', -cols => '4' }).
236 $q->Tr($q->th({-colspan=>"2"}, 'Module'),
237 $q->th([' X11R7.6 ', ' X11R7.7 '])), "\n";
240 print $q->end_table();
241 print $q->br({-clear => "all"}), "\n";
243 foreach my $m (sort keys %module_info) {
244 my $modname = $module_info{$m}->{module};
245 my $modtype = $module_info{$m}->{modtype};
246 my $moddir = $module_info{$m}->{moddir};
247 my $modvers = $module_info{$m}->{newvers};
248 my $modtar = "$modname-$modvers.tar.bz2";
249 my $moddisplay = $m;
250 $moddisplay =~ s{^\./}{};
251 print
252 $q->start_div({-class => "content", -itemscope => undef,
253 -itemtype=>'http://schema.org/SoftwareApplication'}),
254 $q->h2($q->span({-itemprop => "name"},
255 cgit_link($q, $modtype, $moddir, 'top', $modname, $moddisplay)),
256 $q->span({ -itemprop => 'version' }, $modvers)),
257 "\n";
258 print
259 $q->a({ -href => "src/everything/$modtar",
260 -itemprop => 'downloadURL' }, $modtar),
261 ' &mdash; ', $q->span({ -itemprop => 'datePublished' },
262 $module_info{$m}->{newtagdate}), "\n";
263 print $q->h3('Commits from',
264 ($module_info{$m}->{oldtag} eq '') ?
265 'the beginning' :
266 cgit_link($q, $modtype, $moddir, 'tag',
267 $module_info{$m}->{oldtag},
268 $module_info{$m}->{oldtag}
270 'to',
271 cgit_link($q, $modtype, $moddir, 'tag',
272 $module_info{$m}->{newtag},
273 $module_info{$m}->{newtag}
275 ), "\n";
277 print $q->start_ul({ -class => 'authors', -itemprop => 'versionChanges' });
278 my $changes = $module_info{$m}->{changes};
279 foreach my $a (sort keys %{$changes}) {
280 my @au_changes = @{$changes->{$a}};
281 my $count = scalar @au_changes;
282 print $q->li("$a ($count):",
283 $q->ul({ -class => 'commits' },
284 $q->li([map {
285 cgit_link($q, $modtype, $moddir, 'commit',
286 $_->{id}, $_->{desc}) } @au_changes]))
287 ), "\n";
289 print $q->end_ul();
290 print $q->end_div(), "\n";
292 print $q->end_html(), "\n";
295 sub cgit_link {
296 my ($q, $modtype, $moddir, $type, $id, $body) = @_;
297 # http://cgit.freedesktop.org/xorg/xserver/tag/?id=xorg-server-1.7.1
298 # http://cgit.freedesktop.org/xorg/xserver/commit/?id=9a2f6135bfb0f12ec28f304c97917d2f7c64db05
299 if ($modtype ne 'xcb') {
300 if ($modtype eq '.') {
301 $modtype = "xorg";
302 # special cases for X11R7.6
303 # if ($id eq '9edb9e9b4dde6f73dc5241d078425a7a70699ec9') {
304 # $type = 'commit';
306 } else {
307 $modtype = "xorg/$modtype";
310 my $modpath = "$modtype/$moddir";
311 if ($moddir eq "xkeyboard-config") {
312 $modpath = "xkeyboard-config";
315 my %link_attrs = (-href => "http://cgit.freedesktop.org/$modpath/");
316 if ($type eq 'top') {
317 $link_attrs{-name} = $id;
318 } else {
319 $link_attrs{-href} .= "$type/?id=$id";
321 my $link = $q->a(\%link_attrs, $q->escapeHTML($body));
322 return $link;
325 sub find_tag {
326 my ($modtype, $moddir, $module, $vers) = @_;
328 if ($vers eq '*') {
329 return 'HEAD';
332 if ($vers eq '-') {
333 return '';
336 my $oldvers = $vers;
337 $oldvers =~ s/\./_/g;
339 if (-f "$modtype/$moddir/.git/refs/tags/$module-$vers") {
340 return "$module-$vers";
341 } elsif (-f "$modtype/$moddir/.git/refs/tags/$vers") {
342 return "$vers";
343 } else {
344 if (-f "$modtype/$moddir/.git/refs/tags/$module-$oldvers") {
345 return "$module-$oldvers";
349 $vers =~ s/\./\\./g;
351 open(my $tag_fh, '-|', "git --git-dir=$modtype/$moddir/.git tag -l")
352 or die "Failed to run git --git-dir=$modtype/$moddir/.git tag -l";
354 my $found;
355 while (my $t = <$tag_fh>) {
356 chomp($t);
357 if (($t =~ m/$vers$/) || ($t =~ m/$oldvers$/)) {
358 $found = $t;
361 close($tag_fh);
362 if ($found) {
363 return $found;
366 if (-f "$modtype/$moddir/.git/refs/tags/XORG-7_1") {
367 return 'XORG-7_1';
370 return '';
373 # if [[ -d "$TOP/$d/.git" && ! -f "$TOP/$d/NO-PULL" ]] ; then
374 # cd $TOP/$d
375 # LAST_TAG="$(git describe --abbrev=0)"
376 # if [[ -z "${LAST_TAG}" ]] ; then
377 # LAST_TAG="$(git describe --abbrev=0 --all HEAD^)"
378 # fi
379 # git log "${LAST_TAG}"..