1#!@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