1#!/usr/bin/perl
2
3# Generate Git history.
4#
5# Copyright 2016-2017 Robert Krawitz (rlk@alum.mit.edu)
6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by the Free
9# Software Foundation; either version 2 of the License, or (at your option)
10# any later version.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15# for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20use Getopt::Long;
21
22use strict;
23
24my ($base_file);
25my ($base_revision);
26
27GetOptions("i=s" => \$base_file,
28	   "r=s" => \$base_revision);
29
30my ($autline) = "";
31my ($curmsg) = "";
32my ($curtag) = "";
33my (%addlines);
34my (%removelines);
35my (%filechanges);
36my (%files);
37my (@ignore_files) = (".travis.yml",
38    "scripts/travis/checksums",
39    "scripts/travis/integration",
40    "scripts/travis/smoke");
41
42my ($state) = 0;
43my ($ostate) = 0;
44my ($firsttime) = 1;
45
46sub print_it {
47    my (@files) = sort keys %files;
48    my (%tmp_files);
49    map {$tmp_files{$_} = 1} @files;
50    map {delete $tmp_files{$_}} @ignore_files;
51    if ($curtag ne "") {
52	print "===============================================================================\n";
53	print "Name: $curtag\n\n";
54    }
55    print "$autline\n" if (keys %tmp_files > 0);
56    if ($#files >= 0) {
57	my ($add) = 0;
58	my ($remove) = 0;
59	my $file_detail;
60	my ($fcount) = 0;
61	foreach my $fn (@files) {
62	    next if (($fn =~ /\.po$/ && $filechanges{$fn} ne 'C' &&
63		      $filechanges{$fn} ne 'D' ) ||
64		     $fn =~ /^ChangeLog\.pre/);
65	    if ($fn =~ /\.(po|eps)$/) {
66		$removelines{$fn} = 0;
67		$addlines{$fn} = 0;
68	    }
69	    if ($fcount++ == 0) {
70		$file_detail .=  "	Files:";
71		$file_detail .=  "	$fn (";
72	    } else {
73		$file_detail .=  "		$fn (";
74	    }
75	    if ($filechanges{$fn} eq 'D') {
76		$file_detail .=  "removed -$removelines{$fn}";
77		$remove += $removelines{$fn};
78	    } elsif ($filechanges{$fn} eq 'C') {
79		$file_detail .=  "added +$addlines{$fn}";
80		$add += +$addlines{$fn};
81	    } else {
82		$file_detail .=  "+$addlines{$fn}, -$removelines{$fn}";
83		$remove += $removelines{$fn};
84		$add += +$addlines{$fn};
85	    }
86	    $file_detail .=  ")\n";
87	}
88	print "	Lines: +$add, -$remove\n" if (keys %tmp_files > 0);
89	print "$file_detail\n" if (keys %tmp_files > 0);
90    }
91    print "$curmsg\n" if (keys %tmp_files > 0);
92    $autline = "";
93    $curmsg = "";
94    $curtag = "";
95    %addlines = ();
96    %removelines = ();
97    %filechanges = ();
98    %files = ();
99}
100
101if ($base_revision) {
102    $base_revision = "'$base_revision..HEAD'";
103}
104
105open(GITLOG, "git log -w --diff-algorithm=default --summary --numstat --date=short --pretty=format:'>>>GIT1%n%cd  <%an>	%H%n>>>GIT2%n%B>>>GIT3%n%D%n>>>GIT4' $base_revision -- ':(exclude)po/*.po' ':(exclude)ChangeLog.pre-5.2.11'|") or die "Can't run git log: $!\n";
106
107while (<GITLOG>) {
108    if (/>>>GIT([0-9]+)$/) {
109	$state = $1;
110	if ($state == 1) {
111	    if (! $firsttime) {
112		print_it();
113	    }
114	    $firsttime = 0;
115	}
116    } elsif ($state == 1) {
117	$autline = $_;
118    } elsif ($state == 2) {
119	if ($_ ne "\n") {
120	    $curmsg .= "	";
121	}
122	$curmsg .= $_;
123    } elsif ($state == 3) {
124	if (/tag: ((guten|gimp-)?print-[0-9]+_.*)/) {
125	    $curtag = $1;
126	}
127    } elsif ($state == 4) {
128	if ($_ ne "\n") {
129	    chomp;
130	    $_ =~ s/^[ 	]+//;
131	    if (/^delete/) {
132		my ($junk, $junk, $junk, $fn) = split(/ /, $_, 4);
133		$filechanges{$fn} = 'D';
134	    } elsif (/^create/) {
135		my ($junk, $junk, $junk, $fn) = split(/ /, $_, 4);
136		$filechanges{$fn} = 'C';
137	    } elsif (/^[-0-9]/) {
138		my ($add, $remove, $fn) = split(/	/, $_, 3);
139		$add = 0 if ($add eq '-');
140		$remove = 0 if ($remove eq '-');
141		$files{$fn} = 1;
142		$addlines{$fn} = $add;
143		$removelines{$fn} = $remove;
144	    }
145	}
146    } else {
147	die "Unknown state $state\n";
148    }
149}
150
151print_it();
152
153if ($base_file) {
154    open IN, $base_file or die "Can't open baseline file $base_file: $!";
155    while (<IN>) {
156	print;
157    }
158}
159
160exit 0;
161