File Coverage

blib/lib/Dist/Zilla/Plugin/NextRelease.pm
Criterion Covered Total %
statement 63 65 96.9
branch 8 12 66.6
condition 5 7 71.4
subroutine 11 11 100.0
pod 0 3 0.0
total 87 98 88.7


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::NextRelease 6.030;
2             # ABSTRACT: update the next release number in your changelog
3              
4 5     5   4571 use Moose;
  5         15  
  5         42  
5             with (
6             'Dist::Zilla::Role::FileMunger',
7             'Dist::Zilla::Role::TextTemplate',
8             'Dist::Zilla::Role::AfterRelease',
9             );
10              
11 5     5   37101 use Dist::Zilla::Pragmas;
  5         17  
  5         52  
12              
13 5     5   47 use namespace::autoclean;
  5         14  
  5         57  
14              
15 5     5   573 use Dist::Zilla::Path;
  5         25  
  5         75  
16 5     5   1694 use Moose::Util::TypeConstraints;
  5         20  
  5         58  
17 5     5   11912 use List::Util 'first';
  5         19  
  5         3278  
18             use String::Formatter 0.100680 stringf => {
19             -as => '_format_version',
20              
21             input_processor => 'require_single_input',
22             string_replacer => 'method_replace',
23             codes => {
24 15         3500 v => sub { $_[0]->zilla->version },
25             d => sub {
26 9         4388 require DateTime;
27 9         1505019 DateTime->VERSION('0.44'); # CLDR fixes
28              
29 9         414 DateTime->from_epoch(epoch => $^T, time_zone => $_[0]->time_zone)
30             ->format_cldr($_[1]),
31             },
32 0         0 t => sub { "\t" },
33 0         0 n => sub { "\n" },
34 2         31 E => sub { $_[0]->_user_info('email') },
35 3         61 U => sub { $_[0]->_user_info('name') },
36 10 100 100     61190 T => sub { $_[0]->zilla->is_trial
37             ? ($_[1] // '-TRIAL') : '' },
38 1 50 50     168 V => sub { $_[0]->zilla->version
39             . ($_[0]->zilla->is_trial
40             ? ($_[1] // '-TRIAL') : '') },
41             P => sub {
42 1         16 my $releaser = first { $_->can('cpanid') } @{ $_[0]->zilla->plugins_with('-Releaser') };
  1         6  
  1         33  
43 1 50       8 $_[0]->log_fatal('releaser doesn\'t provide cpanid, but %P used') unless $releaser;
44 1         7 $releaser->cpanid;
45             },
46             },
47 5     5   4551 };
  5         17235  
  5         134  
48              
49             our $DEFAULT_TIME_ZONE = 'local';
50             has time_zone => (
51             is => 'ro',
52             isa => 'Str', # should be more validated later -- apocal
53             default => $DEFAULT_TIME_ZONE,
54             );
55              
56             has format => (
57             is => 'ro',
58             isa => 'Str', # should be more validated Later -- rjbs, 2008-06-05
59             default => '%-9v %{yyyy-MM-dd HH:mm:ssZZZZZ VVVV}d%{ (TRIAL RELEASE)}T',
60             );
61              
62             has filename => (
63             is => 'ro',
64             isa => 'Str',
65             default => 'Changes',
66             );
67              
68             has update_filename => (
69             is => 'ro',
70             isa => 'Str',
71             lazy => 1,
72             default => sub { $_[0]->filename },
73             );
74              
75             has user_stash => (
76             is => 'ro',
77             isa => 'Str',
78             default => '%User'
79             );
80              
81             has _user_stash_obj => (
82             is => 'ro',
83             isa => maybe_type( class_type('Dist::Zilla::Stash::User') ),
84             lazy => 1,
85             init_arg => undef,
86             default => sub { $_[0]->zilla->stash_named( $_[0]->user_stash ) },
87             );
88              
89             sub _user_info {
90 5     5   24 my ($self, $field) = @_;
91              
92 5         175 my $stash = $self->_user_stash_obj;
93              
94 5 100 66     259 $self->log_fatal([
95             "You must enter your %s in the [%s] section in ~/.dzil/config.ini",
96             $field, $self->user_stash
97             ]) unless $stash and defined(my $value = $stash->$field);
98              
99 4         15 return $value;
100             }
101              
102             sub section_header {
103 16     16 0 50 my ($self) = @_;
104              
105 16         556 return _format_version($self->format, $self);
106             }
107              
108             has _original_changes_content => (
109             is => 'rw',
110             isa => 'Str',
111             init_arg => undef,
112             );
113              
114             sub munge_files {
115 15     15 0 55 my ($self) = @_;
116              
117 15         40 my ($file) = grep { $_->name eq $self->filename } @{ $self->zilla->files };
  86         272  
  15         559  
118 15 50       84 $self->log_fatal([ 'failed to find %s in the distribution', $self->filename ]) if not $file;
119              
120             # save original unmunged content, for replacing back in the repo later
121 15         100 my $content = $self->_original_changes_content($file->content);
122              
123 15         476 $content = $self->fill_in_string(
124             $content,
125             {
126             dist => \($self->zilla),
127             version => \($self->zilla->version),
128             NEXT => \($self->section_header),
129             },
130             );
131              
132 14         132 $self->log_debug([ 'updating contents of %s in memory', $file->name ]);
133 14         553 $file->content($content);
134             }
135              
136             # new release is part of distribution history, let's record that.
137             sub after_release {
138 1     1 0 1220 my ($self) = @_;
139 1         102 my $filename = $self->filename;
140 1         11 my ($gathered_file) = grep { $_->name eq $filename } @{ $self->zilla->files };
  2         46  
  1         66  
141 1 50       20 $self->log_fatal("failed to find $filename in the distribution") if not $gathered_file;
142 1         66 my $iolayer = sprintf(":raw:encoding(%s)", $gathered_file->encoding);
143              
144             # read original changelog
145 1         59 my $content = $self->_original_changes_content;
146              
147             # add the version and date to file content
148 1         47 my $delim = $self->delim;
149 1         22 my $header = $self->section_header;
150 1         151 $content =~ s{ (\Q$delim->[0]\E \s*) \$NEXT (\s* \Q$delim->[1]\E) }
151             {$1\$NEXT$2\n\n$header}xs;
152 1         50  
153 1         22 my $update_fn = $self->update_filename;
154             $self->log_debug([ 'updating contents of %s on disk', $update_fn ]);
155              
156 1         97 # and finally rewrite the changelog on disk
157             path($update_fn)->spew({binmode => $iolayer}, $content);
158             }
159              
160             __PACKAGE__->meta->make_immutable;
161             1;
162              
163             #pod =head1 SYNOPSIS
164             #pod
165             #pod In your F<dist.ini>:
166             #pod
167             #pod [NextRelease]
168             #pod
169             #pod In your F<Changes> file:
170             #pod
171             #pod {{$NEXT}}
172             #pod
173             #pod
174             #pod =head1 DESCRIPTION
175             #pod
176             #pod Tired of having to update your F<Changes> file by hand with the new
177             #pod version and release date / time each time you release your distribution?
178             #pod Well, this plugin is for you.
179             #pod
180             #pod Add this plugin to your F<dist.ini>, and the following to your
181             #pod F<Changes> file:
182             #pod
183             #pod {{$NEXT}}
184             #pod
185             #pod The C<NextRelease> plugin will then do 2 things:
186             #pod
187             #pod =over 4
188             #pod
189             #pod =item * At build time, this special marker will be replaced with the
190             #pod version and the build date, to form a standard changelog header. This
191             #pod will be done to the in-memory file - the original F<Changes> file won't
192             #pod be updated.
193             #pod
194             #pod =item * After release (when running C<dzil release>), since the version
195             #pod and build date are now part of your dist's history, the real F<Changes>
196             #pod file (not the in-memory one) will be updated with this piece of
197             #pod information.
198             #pod
199             #pod =back
200             #pod
201             #pod The module accepts the following options in its F<dist.ini> section:
202             #pod
203             #pod =begin :list
204             #pod
205             #pod = filename
206             #pod the name of your changelog file; defaults to F<Changes>
207             #pod
208             #pod = update_filename
209             #pod the file to which to write an updated changelog to; defaults to the C<filename>
210             #pod
211             #pod = format
212             #pod sprintf-like string used to compute the next value of C<{{$NEXT}}>;
213             #pod defaults to C<%-9v %{yyyy-MM-dd HH:mm:ssZZZZZ VVVV}d%{ (TRIAL RELEASE)}T>
214             #pod
215             #pod = time_zone
216             #pod the timezone to use when generating the date; defaults to I<local>
217             #pod
218             #pod = user_stash
219             #pod the name of the stash where the user's name and email address can be found;
220             #pod defaults to C<%User>
221             #pod
222             #pod =end :list
223             #pod
224             #pod The module allows the following sprintf-like format codes in the C<format>:
225             #pod
226             #pod =begin :list
227             #pod
228             #pod = C<%v>
229             #pod The distribution version
230             #pod
231             #pod = C<%{-TRIAL}T>
232             #pod Expands to -TRIAL (or any other supplied string) if this
233             #pod is a trial release, or the empty string if not. A bare C<%T> means
234             #pod C<%{-TRIAL}T>.
235             #pod
236             #pod = C<%{-TRIAL}V>
237             #pod Equivalent to C<%v%{-TRIAL}T>, to allow for the application of modifiers such
238             #pod as space padding to the entire version string produced.
239             #pod
240             #pod = C<%{CLDR format}d>
241             #pod The date of the release. You can use any CLDR format supported by
242             #pod L<DateTime>. You must specify the format; there is no default.
243             #pod
244             #pod = C<%U>
245             #pod The name of the user making this release (from C<user_stash>).
246             #pod
247             #pod = C<%E>
248             #pod The email address of the user making this release (from C<user_stash>).
249             #pod
250             #pod = C<%P>
251             #pod The CPAN (PAUSE) id of the user making this release (from -Releaser plugins;
252             #pod see L<[UploadToCPAN]|Dist::Zilla::Plugin::UploadToCPAN/username>).
253             #pod
254             #pod = C<%n>
255             #pod A newline
256             #pod
257             #pod = C<%t>
258             #pod A tab
259             #pod
260             #pod =end :list
261             #pod
262             #pod =head1 SEE ALSO
263             #pod
264             #pod Core Dist::Zilla plugins:
265             #pod L<AutoVersion|Dist::Zilla::Plugin::AutoVersion>,
266             #pod L<PkgVersion|Dist::Zilla::Plugin::PkgVersion>,
267             #pod L<PodVersion|Dist::Zilla::Plugin::PodVersion>.
268             #pod
269             #pod Dist::Zilla roles:
270             #pod L<AfterRelease|Dist::Zilla::Plugin::AfterRelease>,
271             #pod L<FileMunger|Dist::Zilla::Role::FileMunger>,
272             #pod L<TextTemplate|Dist::Zilla::Role::TextTemplate>.
273              
274             __END__
275              
276             =pod
277              
278             =encoding UTF-8
279              
280             =head1 NAME
281              
282             Dist::Zilla::Plugin::NextRelease - update the next release number in your changelog
283              
284             =head1 VERSION
285              
286             version 6.030
287              
288             =head1 SYNOPSIS
289              
290             In your F<dist.ini>:
291              
292             [NextRelease]
293              
294             In your F<Changes> file:
295              
296             {{$NEXT}}
297              
298             =head1 DESCRIPTION
299              
300             Tired of having to update your F<Changes> file by hand with the new
301             version and release date / time each time you release your distribution?
302             Well, this plugin is for you.
303              
304             Add this plugin to your F<dist.ini>, and the following to your
305             F<Changes> file:
306              
307             {{$NEXT}}
308              
309             The C<NextRelease> plugin will then do 2 things:
310              
311             =over 4
312              
313             =item * At build time, this special marker will be replaced with the
314             version and the build date, to form a standard changelog header. This
315             will be done to the in-memory file - the original F<Changes> file won't
316             be updated.
317              
318             =item * After release (when running C<dzil release>), since the version
319             and build date are now part of your dist's history, the real F<Changes>
320             file (not the in-memory one) will be updated with this piece of
321             information.
322              
323             =back
324              
325             The module accepts the following options in its F<dist.ini> section:
326              
327             =over 4
328              
329             =item filename
330              
331             the name of your changelog file; defaults to F<Changes>
332              
333             =item update_filename
334              
335             the file to which to write an updated changelog to; defaults to the C<filename>
336              
337             =item format
338              
339             sprintf-like string used to compute the next value of C<{{$NEXT}}>;
340             defaults to C<%-9v %{yyyy-MM-dd HH:mm:ssZZZZZ VVVV}d%{ (TRIAL RELEASE)}T>
341              
342             =item time_zone
343              
344             the timezone to use when generating the date; defaults to I<local>
345              
346             =item user_stash
347              
348             the name of the stash where the user's name and email address can be found;
349             defaults to C<%User>
350              
351             =back
352              
353             The module allows the following sprintf-like format codes in the C<format>:
354              
355             =over 4
356              
357             =item C<%v>
358              
359             The distribution version
360              
361             =item C<%{-TRIAL}T>
362              
363             Expands to -TRIAL (or any other supplied string) if this
364             is a trial release, or the empty string if not. A bare C<%T> means
365             C<%{-TRIAL}T>.
366              
367             =item C<%{-TRIAL}V>
368              
369             Equivalent to C<%v%{-TRIAL}T>, to allow for the application of modifiers such
370             as space padding to the entire version string produced.
371              
372             =item C<%{CLDR format}d>
373              
374             The date of the release. You can use any CLDR format supported by
375             L<DateTime>. You must specify the format; there is no default.
376              
377             =item C<%U>
378              
379             The name of the user making this release (from C<user_stash>).
380              
381             =item C<%E>
382              
383             The email address of the user making this release (from C<user_stash>).
384              
385             =item C<%P>
386              
387             The CPAN (PAUSE) id of the user making this release (from -Releaser plugins;
388             see L<[UploadToCPAN]|Dist::Zilla::Plugin::UploadToCPAN/username>).
389              
390             =item C<%n>
391              
392             A newline
393              
394             =item C<%t>
395              
396             A tab
397              
398             =back
399              
400             =head1 PERL VERSION
401              
402             This module should work on any version of perl still receiving updates from
403             the Perl 5 Porters. This means it should work on any version of perl released
404             in the last two to three years. (That is, if the most recently released
405             version is v5.40, then this module should work on both v5.40 and v5.38.)
406              
407             Although it may work on older versions of perl, no guarantee is made that the
408             minimum required version will not be increased. The version may be increased
409             for any reason, and there is no promise that patches will be accepted to lower
410             the minimum required perl.
411              
412             =head1 SEE ALSO
413              
414             Core Dist::Zilla plugins:
415             L<AutoVersion|Dist::Zilla::Plugin::AutoVersion>,
416             L<PkgVersion|Dist::Zilla::Plugin::PkgVersion>,
417             L<PodVersion|Dist::Zilla::Plugin::PodVersion>.
418              
419             Dist::Zilla roles:
420             L<AfterRelease|Dist::Zilla::Plugin::AfterRelease>,
421             L<FileMunger|Dist::Zilla::Role::FileMunger>,
422             L<TextTemplate|Dist::Zilla::Role::TextTemplate>.
423              
424             =head1 AUTHOR
425              
426             Ricardo SIGNES 😏 <cpan@semiotic.systems>
427              
428             =head1 COPYRIGHT AND LICENSE
429              
430             This software is copyright (c) 2023 by Ricardo SIGNES.
431              
432             This is free software; you can redistribute it and/or modify it under
433             the same terms as the Perl 5 programming language system itself.
434              
435             =cut