blob: e76d0c0875bf1b7a89742fadfcb6e54d41be3629 [file] [log] [blame]
Petr Mladek3a0ec752011-01-31 19:43:03 +01001#!/usr/bin/perl
2 eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
3 if $running_under_some_shell;
4#!/usr/bin/perl
5
6use strict;
Christian Lohmaier249b6a52017-04-29 19:15:26 +02007use warnings;
Ivan Timofeeva8b77a52012-05-17 18:38:09 +04008use LWP::UserAgent;
Ivan Timofeev521ae232012-05-21 16:54:25 +02009use utf8;
Petr Mladek3e0e88f2012-11-29 11:14:13 +010010use File::Temp;
Christian Lohmaier9c837962017-04-29 18:26:20 +020011use Encode;
12use open ':encoding(utf8)';
13use open ':std' => ':encoding(utf8)';
Petr Mladek3a0ec752011-01-31 19:43:03 +010014
Petr Mladek0746c952012-11-19 17:50:42 +010015my %module_dirname = (
16 "core" => "",
17 "dictionaries" => "dictionaries",
18 "help" => "helpcontent2",
19 "translations" => "translations"
20);
21
Petr Mladek3a0ec752011-01-31 19:43:03 +010022
Ivan Timofeeva8b77a52012-05-17 18:38:09 +040023my %bugzillas = (
Dennis Roczekb990cdf2015-06-09 06:01:37 +020024 fdo => "https://bugs.documentfoundation.org/show_bug.cgi?id=",
25 tdf => "https://bugs.documentfoundation.org/show_bug.cgi?id=",
Thorsten Behrens724b4ea2012-07-12 01:32:55 +020026 bnc => "https://bugzilla.novell.com/show_bug.cgi?id=",
27 rhbz => "https://bugzilla.redhat.com/show_bug.cgi?id=",
Adolfo Jayme Barrientosd02c1592015-05-19 19:48:11 -050028 i => "https://bz.apache.org/ooo/show_bug.cgi?id=",
Thorsten Behrens724b4ea2012-07-12 01:32:55 +020029 fate => "https://features.opensuse.org/",
Ivan Timofeeva8b77a52012-05-17 18:38:09 +040030);
31
Petr Mladek3a0ec752011-01-31 19:43:03 +010032sub search_bugs($$$$)
33{
Petr Mladek0746c952012-11-19 17:50:42 +010034 my ($pdata, $module, $commit_id, $line) = @_;
Petr Mladek3a0ec752011-01-31 19:43:03 +010035
36 my $bug = "";
37 my $bug_orig;
Petr Mladek3a0ec752011-01-31 19:43:03 +010038 while (defined $bug) {
Petr Mladek5c42f5d2011-03-01 21:16:48 +010039
Thorsten Behrens9852f012012-06-12 03:34:33 +020040 # match fdo#123, rhz#123, i#123, #123
Korrawit Pruegsanusak6858c3e2012-06-01 00:24:16 +070041 # but match only bug number with >= 4 digits
Thorsten Behrens9852f012012-06-12 03:34:33 +020042 if ( $line =~ m/(\w+\#+\d{4,})/ ) {
Petr Mladek3a0ec752011-01-31 19:43:03 +010043 $bug_orig = $1;
44 $bug = $1;
Thorsten Behrens9852f012012-06-12 03:34:33 +020045 # default to issuezilla for the #123 variant
46 # but match only bug number with >= 4 digits
47 } elsif ( $line =~ m/(\#)(\d{4,})/ ) {
48 $bug_orig = $1 . $2;
49 $bug = "i#$2";
Petr Mladek9a34f072011-02-02 17:46:51 +010050 # match #i123#
Petr Mladek3a0ec752011-01-31 19:43:03 +010051 } elsif ( $line =~ m/(\#i)(\d+)(\#)/ ) {
52 $bug_orig = $1 . $2 . $3;
Petr Mladekb9e22832011-02-09 12:37:47 +010053 $bug = "i#$2";
Petr Mladek3a0ec752011-01-31 19:43:03 +010054 } else {
55 $bug = undef;
56 next;
57 }
Petr Mladek5c42f5d2011-03-01 21:16:48 +010058
Petr Mladekb9e22832011-02-09 12:37:47 +010059# print " found $bug\n";
Petr Mladek5c42f5d2011-03-01 21:16:48 +010060 # remove bug number from the comment; it will be added later a standardized way
Petr Mladek3a0ec752011-01-31 19:43:03 +010061 $bug_orig =~ s/\#/\\#/;
Dennis Roczek880e3af2015-07-12 04:35:28 +020062 $line =~ s/(,\s)*[Rr](elated|esolve[ds]):?\s*$bug_orig\s?:?\s*//;
Petr Mladek3a0ec752011-01-31 19:43:03 +010063 $line =~ s/\s*-\s*$bug_orig\s*//;
Korrawit Pruegsanusakefecdec2012-06-01 00:24:22 +070064 $line =~ s/\(?$bug_orig\)?\s*[:,-]?\s*//;
Petr Mladek5c42f5d2011-03-01 21:16:48 +010065
Andras Timar382eea62011-04-19 18:42:53 +020066 # bnc# is preferred over n# for novell bugs
Petr Mladek5c42f5d2011-03-01 21:16:48 +010067 $bug =~ s/^n\#/bnc#/;
Thorsten Behrens9852f012012-06-12 03:34:33 +020068 # deb# is preferred over debian# for debian bugs
69 $bug =~ s/^debian\#/deb#/;
70 # easyhack# is sometimes used for fdo# - based easy hacks
71 $bug =~ s/^easyhack\#/fdo#/;
72 # someone mistyped fdo as fd0
73 $bug =~ s/^fd0\#/fdo#/;
Petr Mladek5c42f5d2011-03-01 21:16:48 +010074 # save the bug number
Petr Mladek0746c952012-11-19 17:50:42 +010075 $pdata->{$module}{$commit_id}{'bugs'}{$bug} = 1;
Petr Mladek3a0ec752011-01-31 19:43:03 +010076 }
77
78 return $line;
79}
80
Petr Mladek3a0ec752011-01-31 19:43:03 +010081sub standardize_summary($)
82{
83 my $line = shift;
84
85 $line =~ s/^\s*//;
86 $line =~ s/\s*$//;
87
Korrawit Pruegsanusakf439d762012-06-01 00:24:18 +070088 # lower first letter if the word contains only lowercase letter
89 if ( $line =~ m/(^.[a-z]+\b)/ ) {
90 $line =~ m/(^.)/;
91 my $first_char = lc($1);
92 $line =~ s/^./$first_char/;
93 }
Petr Mladek3a0ec752011-01-31 19:43:03 +010094
95 # FIXME: remove do at the end of line
96 # remove bug numbers
97 return $line;
98}
99
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100100sub generate_git_cherry_ids_log($$$$$)
Petr Mladek3a0ec752011-01-31 19:43:03 +0100101{
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100102 my ($pdata, $repo_dir, $module, $branch_name, $git_args) = @_;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100103
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100104 my $commit_ids_log;
105 my $commit_ids_log_fh;
106 $commit_ids_log_fh = File::Temp->new(TEMPLATE => 'lo-commit-stat-ids-XXXXXX',
107 DIR => '/tmp',
108 UNLINK => 0);
109 $commit_ids_log = $commit_ids_log_fh->filename;
110
111 print STDERR "Filtering cherry-picked commits in the git repo: $module...\n";
112
113 my $cmd = "cd $repo_dir; git cherry $git_args";
114 open (GIT, "$cmd 2>&1|") || die "Can't run $cmd: $!";
115
116 while (my $line = <GIT>) {
117
118 # skip cherry-picked commits
119 next if ( $line =~ m/^\-/ );
120
121 if ( $line =~ m/^\+ / ) {
122 $line =~ s/^\+ //;
123 print $commit_ids_log_fh $line;
124 }
125 }
126
127 close GIT;
128 close $commit_ids_log_fh;
129
130 return $commit_ids_log;
131}
132
133sub load_git_log($$$$$$$)
134{
135 my ($pdata, $repo_dir, $module, $branch_name, $git_command, $git_cherry, $git_args) = @_;
136
137 my $cmd = "cd $repo_dir;";
138 my $commit_ids_log;
139
140 if ($git_cherry) {
141 $commit_ids_log = generate_git_cherry_ids_log($pdata, $repo_dir, $module, $branch_name, $git_args);
142 $cmd .= " cat $commit_ids_log | xargs -n 1 $git_command -1";
143 } else {
144 $cmd .= " $git_command $git_args";
145 }
146
Petr Mladek3a0ec752011-01-31 19:43:03 +0100147 my $commit_id;
148 my $summary;
149
Petr Mladek0746c952012-11-19 17:50:42 +0100150 print STDERR "Analyzing log from the git repo: $module...\n";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100151
Petr Mladek0746c952012-11-19 17:50:42 +0100152# FIXME: ./g pull move submodules in unnamed branches
153# my $repo_branch_name = get_branch_name($repo_dir);
154# if ( $branch_name ne $repo_branch_name ) {
155# die "Error: mismatch of branches:\n" .
156# " main repo is on the branch: $branch_name\n" .
157# " $module repo is on the branch: $repo_branch_name\n";
158# }
Petr Mladek33a84002011-04-26 20:03:01 +0200159
Petr Mladek3a0ec752011-01-31 19:43:03 +0100160 open (GIT, "$cmd 2>&1|") || die "Can't run $cmd: $!";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100161
162 while (my $line = <GIT>) {
163 chomp $line;
164
Petr Mladek9a34f072011-02-02 17:46:51 +0100165 if ( $line =~ m/^commit ([0-9a-z]{20})/ ) {
Christian Lohmaier249b6a52017-04-29 19:15:26 +0200166 $commit_id = $1;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100167 $summary=undef;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100168 next;
169 }
170
Petr Mladek9a34f072011-02-02 17:46:51 +0100171 if ( $line =~ /^Author:\s*([^\<]*)\<([^\>]*)>/ ) {
Petr Mladek3a0ec752011-01-31 19:43:03 +0100172 # get rid of extra empty spaces;
Christian Lohmaier249b6a52017-04-29 19:15:26 +0200173 my $name = $1;
174 my $email = $2;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100175 $name =~ s/\s+$//;
Petr Mladek0746c952012-11-19 17:50:42 +0100176 die "Error: Author already defined for the commit {$commit_id}\n" if defined ($pdata->{$module}{$commit_id}{'author'});
Christian Lohmaier249b6a52017-04-29 19:15:26 +0200177 $pdata->{$module}{$commit_id}{'author'}{'name'} = $name;
178 $pdata->{$module}{$commit_id}{'author'}{'email'} = $email;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100179 next;
180 }
Petr Mladek9a34f072011-02-02 17:46:51 +0100181
182 if ( $line =~ /^Date:\s+/ ) {
Petr Mladek3a0ec752011-01-31 19:43:03 +0100183 # ignore date line
184 next;
185 }
Petr Mladek9a34f072011-02-02 17:46:51 +0100186
Petr Mladek3a0ec752011-01-31 19:43:03 +0100187 if ( $line =~ /^\s*$/ ) {
188 # ignore empty line
189 next;
190 }
191
Petr Mladek0746c952012-11-19 17:50:42 +0100192 $line = search_bugs($pdata, $module, $commit_id, $line);
Andras Timar382eea62011-04-19 18:42:53 +0200193 # FIXME: need to be implemented
Petr Mladek3a0ec752011-01-31 19:43:03 +0100194# search_keywords($pdata, $line);
195
Petr Mladek0746c952012-11-19 17:50:42 +0100196 unless (defined $pdata->{$module}{$commit_id}{'summary'}) {
Petr Mladek3a0ec752011-01-31 19:43:03 +0100197 $summary = standardize_summary($line);
Petr Mladek0746c952012-11-19 17:50:42 +0100198 $pdata->{$module}{$commit_id}{'summary'} = $summary;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100199 }
200 }
201
202 close GIT;
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100203 unlink $commit_ids_log if ($git_cherry);
Petr Mladek3a0ec752011-01-31 19:43:03 +0100204}
205
206sub get_repo_name($)
207{
208 my $repo_dir = shift;
209
210 open (GIT_CONFIG, "$repo_dir/.git/config") ||
211 die "can't open \"$$repo_dir/.git/config\" for reading: $!\n";
212
213 while (my $line = <GIT_CONFIG>) {
214 chomp $line;
215
216 if ( $line =~ /^\s*url\s*=\s*(\S+)$/ ) {
217 my $repo_name = "$1";
218 $repo_name = s/.*\///g;
219 return "$repo_name";
220 }
221 }
222 die "Error: can't find repo name in \"$$repo_dir/.git/config\"\n";
223}
224
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100225sub load_data($$$$$$$)
Petr Mladek3a0ec752011-01-31 19:43:03 +0100226{
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100227 my ($pdata, $top_dir, $p_module_dirname, $branch_name, $git_command, $git_cherry, $git_args) = @_;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100228
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100229 foreach my $module (sort { $a cmp $b } keys %{$p_module_dirname}) {
230 load_git_log($pdata, "$top_dir/$p_module_dirname->{$module}", $module, $branch_name, $git_command, $git_cherry, $git_args);
Petr Mladek3a0ec752011-01-31 19:43:03 +0100231 }
232}
233
Petr Mladekfa4a0612011-03-28 15:51:47 +0200234sub get_branch_name($)
Petr Mladek3a0ec752011-01-31 19:43:03 +0100235{
Petr Mladekfa4a0612011-03-28 15:51:47 +0200236 my ($top_dir) = @_;
237
238 my $branch;
239 my $cmd = "cd $top_dir && git branch";
240
Petr Mladekfa4a0612011-03-28 15:51:47 +0200241 open (GIT, "$cmd 2>&1|") || die "Can't run $cmd: $!";
242
243 while (my $line = <GIT>) {
244 chomp $line;
245
246 if ( $line =~ m/^\*\s*(\S+)/ ) {
247 $branch = "$1";
248 }
249 }
250
251 close GIT;
Petr Mladek33a84002011-04-26 20:03:01 +0200252
253 die "Error: did not detect git branch name in $top_dir\n" unless defined ($branch);
Petr Mladekfa4a0612011-03-28 15:51:47 +0200254
255 return $branch;
256}
257
Petr Mladek7cc7e402013-03-06 15:15:01 +0100258sub get_bug_list($$$)
259{
260 my ($pdata, $pbugs, $check_bugzilla) = @_;
261
262 # associate bugs with their summaries and fixers
263 foreach my $module ( keys %{$pdata}) {
264 foreach my $id ( keys %{$pdata->{$module}}) {
265 foreach my $bug (keys %{$pdata->{$module}{$id}{'bugs'}}) {
Petr Mladek7cc7e402013-03-06 15:15:01 +0100266 my $author = $pdata->{$module}{$id}{'author'}{'name'};
267 my $summary = $pdata->{$module}{$id}{'summary'};
268 $pbugs->{$bug}{'summary'} = $summary;
269 $pbugs->{$bug}{'author'}{$author} = 1;
270 }
271 }
272 }
273
274 # try to replace summaries with bug names from bugzilla
275 if ($check_bugzilla) {
276 print "Getting bug titles:\n";
277 foreach my $bug ( sort { $a cmp $b } keys %{$pbugs}) {
278 $pbugs->{$bug}{'summary'} = get_bug_name($bug, $pbugs->{$bug}{'summary'});
279 }
280 }
281}
282
Petr Mladek93d021a2012-11-20 16:10:58 +0100283sub open_log_file($$$$$$)
Petr Mladekfa4a0612011-03-28 15:51:47 +0200284{
Petr Mladek93d021a2012-11-20 16:10:58 +0100285 my ($log_dir, $log_prefix, $log_suffix, $top_dir, $branch_name, $wiki) = @_;
Petr Mladekfa4a0612011-03-28 15:51:47 +0200286
Petr Mladek93d021a2012-11-20 16:10:58 +0100287 my $logfilename = "$log_prefix-$branch_name-$log_suffix";
Petr Mladeka07a2302011-05-30 17:08:26 +0200288 $logfilename = "$log_dir/$logfilename" if (defined $log_dir);
Petr Mladek93d021a2012-11-20 16:10:58 +0100289 if ($wiki) {
290 $logfilename .= ".wiki";
291 } else {
292 $logfilename .= ".log";
293 }
Petr Mladekfa4a0612011-03-28 15:51:47 +0200294
295 if (-f $logfilename) {
296 print "WARNING: The log file already exists: $logfilename\n";
Andras Timar382eea62011-04-19 18:42:53 +0200297 print "Do you want to overwrite it? (Y/n)?\n";
Petr Mladekfa4a0612011-03-28 15:51:47 +0200298 my $answer = <STDIN>;
299 chomp $answer;
300 $answer = "y" unless ($answer);
301 die "Please, rename the file or choose another log suffix\n" if ( lc($answer) ne "y" );
302 }
303
304 my $log;
305 open($log, '>', $logfilename) || die "Can't open \"$logfilename\" for writing: $!\n";
306
307 return $log;
308}
309
Petr Mladek93d021a2012-11-20 16:10:58 +0100310sub print_commit_summary($$$$$$)
Petr Mladekfa4a0612011-03-28 15:51:47 +0200311{
Petr Mladek0746c952012-11-19 17:50:42 +0100312 my ($summary, $pmodule_title, $pbugs, $pauthors, $prefix, $log) = @_;
Petr Mladek9a34f072011-02-02 17:46:51 +0100313
Petr Mladek3a0ec752011-01-31 19:43:03 +0100314 return if ( $summary eq "" );
Petr Mladek331006b2011-04-28 20:08:11 +0200315
Petr Mladek0746c952012-11-19 17:50:42 +0100316 # print module title if not done yet
317 if ( defined ${$pmodule_title} ) {
318 print $log "${$pmodule_title}\n";
319 ${$pmodule_title} = undef;
Petr Mladek8d8a1892011-02-14 15:26:38 +0100320 }
321
322 # finally print the summary line
Petr Mladek3a0ec752011-01-31 19:43:03 +0100323 my $bugs = "";
324 if ( %{$pbugs} ) {
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400325 $bugs = " (" . join (", ", keys %{$pbugs}) . ")";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100326 }
327
328 my $authors = "";
329 if ( %{$pauthors} ) {
330 $authors = " [" . join (", ", keys %{$pauthors}) . "]";
331 }
332
Thorsten Behrensd5e3a6a2012-06-13 11:20:47 +0200333 print $log $prefix, $summary, $bugs, $authors, "\n";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100334}
335
Petr Mladek93d021a2012-11-20 16:10:58 +0100336sub print_commits($$$)
Petr Mladek3a0ec752011-01-31 19:43:03 +0100337{
Petr Mladek93d021a2012-11-20 16:10:58 +0100338 my ($pdata, $log, $wiki) = @_;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100339
Petr Mladek0746c952012-11-19 17:50:42 +0100340 foreach my $module ( sort { $a cmp $b } keys %{$pdata}) {
341 # check if this module has any entries at all
342 my $module_title = "+ $module";
343 if ( %{$pdata->{$module}} ) {
Petr Mladek3a0ec752011-01-31 19:43:03 +0100344 my $old_summary="";
345 my %authors = ();
346 my %bugs = ();
Petr Mladek0746c952012-11-19 17:50:42 +0100347 foreach my $id ( sort { lc $pdata->{$module}{$a}{'summary'} cmp lc $pdata->{$module}{$b}{'summary'} } keys %{$pdata->{$module}}) {
348 my $summary = $pdata->{$module}{$id}{'summary'};
Petr Mladek3a0ec752011-01-31 19:43:03 +0100349 if ($summary ne $old_summary) {
Petr Mladek93d021a2012-11-20 16:10:58 +0100350 print_commit_summary($old_summary, \$module_title, \%bugs, \%authors, " + ", $log);
Petr Mladek3a0ec752011-01-31 19:43:03 +0100351 $old_summary = $summary;
352 %authors = ();
353 %bugs = ();
354 }
Petr Mladek8d8a1892011-02-14 15:26:38 +0100355 # collect bug numbers
Petr Mladek0746c952012-11-19 17:50:42 +0100356 if (defined $pdata->{$module}{$id}{'bugs'}) {
357 foreach my $bug (keys %{$pdata->{$module}{$id}{'bugs'}}) {
Petr Mladek3a0ec752011-01-31 19:43:03 +0100358 $bugs{$bug} = 1;
359 }
360 }
Petr Mladek8d8a1892011-02-14 15:26:38 +0100361 # collect author names
Petr Mladek0746c952012-11-19 17:50:42 +0100362 my $author = $pdata->{$module}{$id}{'author'}{'name'};
Petr Mladek3a0ec752011-01-31 19:43:03 +0100363 $authors{$author} = 1;
364 }
Petr Mladek93d021a2012-11-20 16:10:58 +0100365 print_commit_summary($old_summary, \$module_title, \%bugs, \%authors, " + ", $log);
Petr Mladek3a0ec752011-01-31 19:43:03 +0100366 }
367 }
368}
369
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400370sub get_bug_name($$)
371{
372 my ($bug, $summary) = @_;
Petr Mladekdd15b51d2012-05-18 18:02:37 +0200373 print "$bug: ";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400374
375 $bug =~ m/(?:(\w*)\#+(\d+))/; # fdo#12345
376 my $bugzilla = $1; # fdo
377 my $bug_number = $2; # 12345
378
379 if ( $bugzillas{$bugzilla} ) {
Thorsten Behrens724b4ea2012-07-12 01:32:55 +0200380 my $url = $bugzillas{$bugzilla} . $bug_number;
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400381 my $ua = LWP::UserAgent->new;
382 $ua->timeout(10);
383 $ua->env_proxy;
384 my $response = $ua->get($url);
385 if ($response->is_success) {
Christian Lohmaier9c837962017-04-29 18:26:20 +0200386 my $title = decode('utf8', $response->title);
387 if ( $title =~ s/^(?:Bug $bug_number \S+|$bug_number –) // ) {
Petr Mladekdd15b51d2012-05-18 18:02:37 +0200388 print "$title\n";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400389 return $title;
Petr Mladekdd15b51d2012-05-18 18:02:37 +0200390 } else {
Christian Lohmaier9c837962017-04-29 18:26:20 +0200391 print "warning: not found; using commit message (only got $title)";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400392 }
393 }
394 }
Christian Lohmaier9c837962017-04-29 18:26:20 +0200395 print "\n";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400396
397 return $summary;
398}
399
Petr Mladek7cc7e402013-03-06 15:15:01 +0100400sub print_bugs($$$$)
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400401{
Petr Mladek7cc7e402013-03-06 15:15:01 +0100402 my ($pbugs, $log, $wiki) = @_;
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400403
Andrea Gelmini64a31242017-08-17 16:41:20 +0200404 # sort alphabetically by bugzilla-type, but within that numerically
Christian Lohmaier0b8cccd2017-04-29 18:54:16 +0200405 foreach my $bug ( sort { ($a =~ /(\D+)/)[0] cmp ($b =~ /(\D+)/)[0] ||
406 ($a =~ /(\d+)/)[0] <=> ($b =~ /(\d+)/)[0] } keys %{$pbugs}) {
Petr Mladek7cc7e402013-03-06 15:15:01 +0100407 my $summary = $pbugs->{$bug}{'summary'};
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400408
409 my $authors = "";
Petr Mladek7cc7e402013-03-06 15:15:01 +0100410 if ( %{$pbugs->{$bug}{'author'}} ) {
411 $authors = " [" . join (", ", keys %{$pbugs->{$bug}{'author'}}) . "]";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400412 }
413
Thorsten Behrens001adf62013-06-27 19:37:53 +0200414 $bug =~ s/(.*)\#(.*)/# {{$1|$2}}/ if ($wiki);
Petr Mladek93d021a2012-11-20 16:10:58 +0100415 print $log $bug, " ", $summary, $authors, "\n";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400416 }
417}
418
Petr Mladek7cc7e402013-03-06 15:15:01 +0100419sub print_bugs_changelog($$$$)
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400420{
Petr Mladek7cc7e402013-03-06 15:15:01 +0100421 my ($pbugs, $log, $wiki) = @_;
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400422
Petr Mladek7cc7e402013-03-06 15:15:01 +0100423 foreach my $bug ( sort { $a cmp $b } keys %{$pbugs}) {
424 my $summary = $pbugs->{$bug}{'summary'};
425
426 my $authors = "";
427 if ( %{$pbugs->{$bug}{'author'}} ) {
428 $authors = " [" . join (", ", keys %{$pbugs->{$bug}{'author'}}) . "]";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400429 }
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400430
Petr Mladek7cc7e402013-03-06 15:15:01 +0100431 print $log " + $summary ($bug)$authors\n";
432 }
433}
434
435sub print_bugnumbers($$$$)
436{
437 my ($pbugs, $log, $wiki) = @_;
438
439 print $log join ("\n", sort { $a cmp $b } keys %{$pbugs}), "\n";
Ivan Timofeeva8b77a52012-05-17 18:38:09 +0400440}
441
Petr Mladek93d021a2012-11-20 16:10:58 +0100442sub generate_log($$$$$$$$)
443{
Petr Mladek7cc7e402013-03-06 15:15:01 +0100444 my ($pused_data, $print_func, $log_dir, $log_prefix, $log_suffix, $top_dir, $branch_name, $wiki) = @_;
Petr Mladek93d021a2012-11-20 16:10:58 +0100445
446 my $log = open_log_file($log_dir, $log_prefix, $log_suffix, $top_dir, $branch_name, $wiki);
Petr Mladek7cc7e402013-03-06 15:15:01 +0100447 & {$print_func} ($pused_data, $log, $wiki);
Petr Mladek93d021a2012-11-20 16:10:58 +0100448 close $log;
449}
450
Petr Mladek3a0ec752011-01-31 19:43:03 +0100451########################################################################
452# help
453
454sub usage()
455{
456 print "This script generates LO git commit summary\n\n" .
457
Petr Mladek0746c952012-11-19 17:50:42 +0100458 "Usage: lo-commit-stat [--help] [--no-submodules] [--module=<module>] --log-dir=<dir> --log-suffix=<string> topdir [git_arg...]\n\n" .
Petr Mladek3a0ec752011-01-31 19:43:03 +0100459
460 "Options:\n" .
Petr Mladek7cc7e402013-03-06 15:15:01 +0100461 " --help print this help\n" .
462 " --no-submodule read changes just from the main repository, ignore submodules\n" .
Petr Mladek0746c952012-11-19 17:50:42 +0100463 " --module=<module> summarize just changes from the given module, use \"core\"\n" .
Petr Mladek7cc7e402013-03-06 15:15:01 +0100464 " for the main module\n" .
465 " --log-dir=<dir> directory where to put the generated log\n" .
Petr Mladekfa4a0612011-03-28 15:51:47 +0200466 " --log-suffix=<string> suffix of the log file name; the result will be\n" .
Petr Mladek7cc7e402013-03-06 15:15:01 +0100467 " commit-log-<branch>-<log-name-suffix>.log; the branch name\n" .
468 " is detected automatically\n" .
469 " --commits generete log with all commits (default)\n" .
470 " --bugs generate log with bugzilla entries\n" .
471 " --bugs-changelog generate log with bugzilla entries, use changelog style\n" .
472 " --bugs-wiki generate log with bugzilla entries, use wiki markup\n" .
473 " --bugs-numbers generate log with bugzilla numbers\n" .
474 " --rev-list use \"git rev-list\" instead of \"git log\"; useful to check\n" .
475 " differences between branches\n" .
476 " --cherry use \"git cherry\" instead of \"git log\"; detects cherry-picked\n" .
477 " commits between branches\n" .
478 " topdir directory with the libreoffice/core clone\n" .
479 " git_arg extra parameters passed to the git command to define\n" .
480 " the area of interest; The default command is \"git log\" and\n" .
481 " parameters might be, for example, --after=\"2010-09-27\" or\n" .
482 " TAG..HEAD; with the option --rev-list, useful might be, for\n" .
483 " example origin/master ^origin/libreoffice-3-3; with the option\n" .
484 " --rev-list, useful might be, for example libreoffice-3.6.3.2\n" .
485 " libreoffice-3.6.4.1\n";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100486}
487
488
489#######################################################################
490#######################################################################
491# MAIN
492#######################################################################
493#######################################################################
494
495
Petr Mladek0746c952012-11-19 17:50:42 +0100496my $module;
Petr Mladek93d021a2012-11-20 16:10:58 +0100497my %generate_log = ();
Petr Mladek3a0ec752011-01-31 19:43:03 +0100498my $top_dir;
Petr Mladeka07a2302011-05-30 17:08:26 +0200499my $log_dir;
Petr Mladekfa4a0612011-03-28 15:51:47 +0200500my $log_suffix;
501my $log;
Petr Mladek7cc7e402013-03-06 15:15:01 +0100502my $list_bugs = 0;
503my $check_bugzilla = 0;
Petr Mladek33a84002011-04-26 20:03:01 +0200504my $branch_name;
Petr Mladek6ad7cdc2011-04-13 16:10:45 +0200505my $git_command = "git log";
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100506my $git_cherry;
507my $git_args = "";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100508my %data;
Petr Mladek7cc7e402013-03-06 15:15:01 +0100509my %bugs = ();
Petr Mladek93d021a2012-11-20 16:10:58 +0100510
511
Petr Mladek3a0ec752011-01-31 19:43:03 +0100512foreach my $arg (@ARGV) {
513 if ($arg eq '--help') {
514 usage();
515 exit;
Petr Mladek0746c952012-11-19 17:50:42 +0100516 } elsif ($arg eq '--no-submodule') {
517 $module = "core";
518 } elsif ($arg =~ m/--module=(.*)/) {
519 $module = $1;
Petr Mladekfa4a0612011-03-28 15:51:47 +0200520 } elsif ($arg =~ m/--log-suffix=(.*)/) {
521 $log_suffix = "$1";
Petr Mladeka07a2302011-05-30 17:08:26 +0200522 } elsif ($arg =~ m/--log-dir=(.*)/) {
523 $log_dir = "$1";
Petr Mladek93d021a2012-11-20 16:10:58 +0100524 } elsif ($arg eq '--commits') {
525 $generate_log{"commits"} = 1;
Petr Mladek8d8a1892011-02-14 15:26:38 +0100526 } elsif ($arg eq '--bugs') {
Petr Mladek93d021a2012-11-20 16:10:58 +0100527 $generate_log{"bugs"} = 1;
Petr Mladek7cc7e402013-03-06 15:15:01 +0100528 $check_bugzilla = 1;
529 $list_bugs = 1;
530 } elsif ($arg eq '--bugs-changelog') {
531 $generate_log{"bugs-changelog"} = 1;
532 $check_bugzilla = 1;
533 $list_bugs = 1;
Petr Mladek93d021a2012-11-20 16:10:58 +0100534 } elsif ($arg eq '--bugs-wiki' || $arg eq '--wikibugs') {
535 $generate_log{"bugs-wiki"} = 1;
Petr Mladek7cc7e402013-03-06 15:15:01 +0100536 $check_bugzilla = 1;
537 $list_bugs = 1;
Petr Mladek93d021a2012-11-20 16:10:58 +0100538 } elsif ($arg eq '--bugs-numbers' || $arg eq '--bug-numbers') {
539 $generate_log{"bugs-numbers"} = 1;
Petr Mladek7cc7e402013-03-06 15:15:01 +0100540 $list_bugs = 1;
Petr Mladek6ad7cdc2011-04-13 16:10:45 +0200541 } elsif ($arg eq '--rev-list') {
542 $git_command = "git rev-list --pretty=medium"
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100543 } elsif ($arg eq '--cherry') {
544 $git_command = "git log";
545 $git_cherry = 1;
Petr Mladek3a0ec752011-01-31 19:43:03 +0100546 } else {
547 if (! defined $top_dir) {
548 $top_dir=$arg;
549 } else {
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100550 $git_args .= " $arg";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100551 }
552 }
553}
554
Petr Mladek93d021a2012-11-20 16:10:58 +0100555# default log
Christian Lohmaier249b6a52017-04-29 19:15:26 +0200556unless (%generate_log) {
Petr Mladek93d021a2012-11-20 16:10:58 +0100557 $generate_log{"commits"} = 1;
558}
559
560# we want only one module
Petr Mladek0746c952012-11-19 17:50:42 +0100561if ($module) {
562 my $name = $module_dirname{$module};
563 %module_dirname = ();
564 $module_dirname{$module} = $name;
565}
566
Andras Timar382eea62011-04-19 18:42:53 +0200567(defined $top_dir) || die "Error: top directory is not defined\n";
Petr Mladek3a0ec752011-01-31 19:43:03 +0100568(-d "$top_dir") || die "Error: not a directory: $top_dir\n";
569(-f "$top_dir/.git/config") || die "Error: can't find $top_dir/.git/config\n";
570
Petr Mladeka07a2302011-05-30 17:08:26 +0200571(!defined $log_dir) || (-d $log_dir) || die "Error: directory does no exist: $log_dir\n";
572
Petr Mladekfa4a0612011-03-28 15:51:47 +0200573(defined $log_suffix) || die "Error: define log suffix using --log-suffix=<string>\n";
574
Petr Mladek33a84002011-04-26 20:03:01 +0200575$branch_name = get_branch_name($top_dir);
Petr Mladekfa4a0612011-03-28 15:51:47 +0200576
Petr Mladek3e0e88f2012-11-29 11:14:13 +0100577load_data(\%data, $top_dir, \%module_dirname, $branch_name, $git_command, $git_cherry, $git_args);
Petr Mladek7cc7e402013-03-06 15:15:01 +0100578get_bug_list(\%data, \%bugs, $check_bugzilla) if ($list_bugs);
Petr Mladek33a84002011-04-26 20:03:01 +0200579
Petr Mladek7cc7e402013-03-06 15:15:01 +0100580generate_log(\%data, \&print_commits, $log_dir, "commits", $log_suffix, $top_dir, $branch_name, 0) if (defined $generate_log{"commits"});
581generate_log(\%bugs, \&print_bugs, $log_dir, "bugs", $log_suffix, $top_dir, $branch_name, 0) if (defined $generate_log{"bugs"});
582generate_log(\%bugs, \&print_bugs, $log_dir, "bugs", $log_suffix, $top_dir, $branch_name, 1) if (defined $generate_log{"bugs-wiki"});
583generate_log(\%bugs, \&print_bugs_changelog, $log_dir, "bugs-changelog", $log_suffix, $top_dir, $branch_name, 0) if (defined $generate_log{"bugs-changelog"});
584generate_log(\%bugs, \&print_bugnumbers, $log_dir, "bug-numbers", $log_suffix, $top_dir, $branch_name, 0) if (defined $generate_log{"bugs-numbers"});