summaryrefslogtreecommitdiff
path: root/mu-aux/gencl
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-04-03 18:23:32 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-04-03 18:23:32 +0300
commitcaac7dea4cb65a8bed723d705bb6a0b89cf13da1 (patch)
tree154b3222613264c840cb58f93514bdf04755fade /mu-aux/gencl
parentfcdbdbe218624d26166f502da3d918165bf30da8 (diff)
downloadmailutils-caac7dea4cb65a8bed723d705bb6a0b89cf13da1.tar.gz
mailutils-caac7dea4cb65a8bed723d705bb6a0b89cf13da1.tar.bz2
Rewrite gencl as an enhanced replacement of gitlog-to-changelog.
* mu-aux/gencl: Rewritten as a replacement for gitlog-to-changelog. * ChangeLog.amend: More spell fixes. * Makefile.am: Use gencl instead of gitlog-to-changelog. * doc/ChangeLog.CVS: Spell checking * gnulib.modules: Remove gitlog-to-changelog.
Diffstat (limited to 'mu-aux/gencl')
-rwxr-xr-xmu-aux/gencl527
1 files changed, 468 insertions, 59 deletions
diff --git a/mu-aux/gencl b/mu-aux/gencl
index af6056bd5..f124cacde 100755
--- a/mu-aux/gencl
+++ b/mu-aux/gencl
@@ -5,59 +5,265 @@ eval '(exit $?0)' && eval 'exec perl -wS "$0" "$@"'
5use strict; 5use strict;
6use POSIX qw(strftime); 6use POSIX qw(strftime);
7use Getopt::Long qw(:config gnu_getopt no_ignore_case); 7use Getopt::Long qw(:config gnu_getopt no_ignore_case);
8use Text::Wrap;
9use Data::Dumper;
10use threads;
11use Thread::Queue;
12use Time::ParseDate;
13use Safe;
14use Pod::Usage;
15use Pod::Man;
16use Pod::Find qw(pod_where);
8 17
9my @append_files; 18my @append_files;
10my $force; 19my $force;
11my $verbose; 20my $verbose;
12my $changelog_file = 'ChangeLog'; 21my $changelog_file = 'ChangeLog';
22my $since_date;
23my $until_date;
24my $strip_cherry_pick;
25my $amend_file;
26my %amendment;
27my $append_dot;
13 28
14GetOptions('append|a=s@' => \@append_files, 29sub set_date {
15 'file|F=s' => \$changelog_file, 30 my ($time, $err) = parsedate($_[1], PREFER_PAST => 1, UK => 1);
16 'force|f' => \$force, 31 unless (defined($time)) {
17 'verbose|v' => \$verbose) or exit(1); 32 print STDERR "--$_[0]=$_[1]: $err\n";
33 exit(1);
34 }
35 return strftime('%Y-%m-%d', localtime($time));
36}
37
38=head1 NAME
39
40gencl - generate ChangeLog from git log output
41
42=head1 SYNOPSIS
43
44B<gencl>
45[B<-fv>]
46[B<-a> I<FILE>]
47[B<-F> I<FILE>]
48[B<--amend=>I<FILE>]
49[B<--append-dot>]
50[B<--append=>I<FILE>]
51[B<--file=>I<FILE>]
52[B<--force>]
53[B<--since=>I<DATE>]
54[B<--strip-cherry-pick>]
55[B<--until=>I<DATE>]
56[B<--verbose>]
57
58B<gencl> B<-h> | B<--help> | B<--usage>
59
60=head1 DESCRIPTION
61
62Retrieves git log messages and reformats them as a valid ChangeLog
63file. The file begins with an automatically generated entry stating
64the SHA1 hash of the git HEAD commit. This entry is followed by
65the log entries recreated from the git log, in reverse chronological
66order. By default, entire log is converted. This can be changed by
67using B<--since> and/or B<--until> options. Files specified with the
68B<--append> options (if any), are appended after the converted entries.
69The file ends with the B<emacs> B<Local Variables> stanza.
70
71If the B<ChangeLog> file exists, B<gencl> verifies if the source tree
72has changed since the file was created. The file is re-created only if
73there were some changes (whether committed or not). The the B<--force>
74(B<-f>) option instructs B<gencl> to recreate the file unconditionally.
75
76The file supplied with the B<--amend> option is used to correct spelling
77(and other) errors in the log entries. It consists of entries delimited
78with one or more empty lines. Each entry begins with a full SHA1 hash
79of the commit it applies to. The hash is followed by one or more lines
80with a valid Perl code (typically, B<s///> statements). Comments are
81introduced with the B<#> sign. For each git log entry, its hash is looked
82up in that file. If found, the B<$_> variable is set to the commit subject,
83followed by the commit body and the code is evaluated.
84
85=head1 OPTIONS
86
87=over 4
88
89=item B<-a>, B<--append=>I<FILE>
90
91Append I<FILE> to the end of the generated file. Multiple B<--append>
92are processed in the order of their occurrence on the command line.
93The content of I<FILE> is appended verbatim, except that the line beginning
94with the text B<Local Variables:> is taken to mark the end of file.
95
96=item B<-F>, B<--file=>I<FILE>
97
98Create I<FILE> instead of the B<ChangeLog>.
99
100=item B<-f>, B<--force>
101
102Force recreating the ChangeLog, even if no new commits were added to the
103repository since its creation.
104
105=item B<-v>, B<--verbose>
106
107Increase output verbosity.
108
109=item B<--since=>I<DATE>
110
111Convert only the logs since I<DATE>. See B<Time::ParseDate>(3), for
112a list of valid I<DATE> formats.
113
114=item B<--until=>I<DATE>
115
116Convert only the logs until I<DATE>. See B<Time::ParseDate>(3), for
117a list of valid I<DATE> formats.
118
119=item B<--strip-cherry-pick>
120
121Remove data inserted by B<git cherry-pick>. This includes the "cherry picked
122from commit ..." line, and the possible final "Conflicts:" paragraph.
123
124=item B<--amend=>I<FILE>
125
126Read amendment instructions from I<FILE>.
127
128=item B<--append-dot>
129
130Append a dot to the subject line of each commit message if there is no other
131punctuation the end.
132
133=back
134
135=head1 DIFFERENCES FROM GITLOG-TO-CHANGELOG
136
137=over 4
138
139=item 1
140
141B<gencl> writes output to the disk file, whereas B<gitlog-to-changelog>
142prints it to the standard output.
143
144=item 2
145
146The created B<ChangeLog> begins with an automatically generated entry and
147ends with the B<Local Variables> stanza.
148
149=item 3
150
151The B<ChangeLog> file is re-created only if the source tree was changed
152since it was written (whether these changes have been committed or not).
153
154=item 4
155
156Arbitrary number of files can be concatenated to the produced file. This
157is handy for projects that switched to B<git> from other VCS.
158
159=item 5
160
161Each entry is reformatted using B<Text::Wrap>.
162
163=item 6
164
165The following B<gitlab-to-changelog> options are not implemented: B<--cluster>,
166B<--ignore-matching>, B<--ignore_line>.
167
168=back
169
170=cut
171
172sub pod_usage_msg {
173 my ($obj) = @_;
174 open my $fd, '>', \my $msg;
175
176 pod2usage(-verbose => 99,
177 -sections => 'NAME',
178 -output => $fd,
179 -exitval => 'NOEXIT');
180 my @a = split /\n/, $msg;
181 $msg = $a[1];
182 $msg =~ s/^\s+//;
183 $msg =~ s/ - /: /;
184 return $msg;
185}
186
187GetOptions(
188 'h' => sub {
189 pod2usage(-message => pod_usage_msg(),
190 -exitstatus => 0,
191 -input => pod_where({-inc => 1}, $0))
192 },
193 'help' => sub {
194 pod2usage(-exitstatus => 0,
195 -verbose => 2,
196 -input => pod_where({-inc => 1}, $0));
197 },
198 'usage' => sub {
199 pod2usage(-exitstatus => 0,
200 -verbose => 0,
201 -input => pod_where({-inc => 1}, $0));
202 },
203 'append|a=s@' => \@append_files,
204 'file|F=s' => \$changelog_file,
205 'force|f' => \$force,
206 'verbose|v' => \$verbose,
207 'since=s' => sub { $since_date = set_date(@_) },
208 'until=s' => sub { $until_date = set_date(@_) },
209 'strip-cherry-pick' => \$strip_cherry_pick,
210 'amend=s' => \$amend_file,
211 'append-dot' => \$append_dot
212 ) or exit(1);
18 213
19if (! -d '.git') { 214if (! -d '.git') {
20 exit 0; 215 exit 0;
21} 216}
22 217
23my ($hash, $date) = split / /, `git log --max-count=1 --pretty=format:'%H %ad' --date=short HEAD`; 218read_amend_file($amend_file) if $amend_file;
219
220$Text::Wrap::columns = 72;
24 221
25my @modlines; 222create_changelog();
26if (open(my $fd, '-|', 'git diff-index --name-status HEAD 2>/dev/null')) {
27 chomp(@modlines = map {chomp; [split /\s+/, $_, 2]} <$fd>);