File Coverage

lib/Dist/Zilla/Plugin/Git/NextRelease.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1 1     1   575 use 5.008; # utf8
  1         2  
  1         42  
2 1     1   4 use strict;
  1         1  
  1         24  
3 1     1   3 use warnings;
  1         7  
  1         20  
4 1     1   505 use utf8;
  1         8  
  1         3  
5              
6             package Dist::Zilla::Plugin::Git::NextRelease;
7              
8             our $VERSION = '0.004000';
9              
10             # ABSTRACT: Use time-stamp from Git instead of process start time.
11              
12             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
13              
14 1     1   258 use Moose qw( extends has around );
  0            
  0            
15             extends 'Dist::Zilla::Plugin::NextRelease';
16              
17             use Git::Wrapper::Plus 0.003100; # Fixed shallow commits
18             use DateTime;
19             use Dist::Zilla::Util::ConfigDumper qw( config_dumper );
20              
21             use String::Formatter 0.100680 stringf => {
22             -as => '_format_version',
23              
24             input_processor => 'require_single_input',
25             string_replacer => 'method_replace',
26             codes => {
27             v => sub { $_[0]->zilla->version },
28             d => sub {
29             my $t = $_[0]->_git_timestamp;
30             $t = $t->set_time_zone( $_[0]->time_zone );
31             return $t->format_cldr( $_[1] ),;
32             },
33             t => sub { "\t" },
34             n => sub { "\n" },
35             E => sub { $_[0]->_user_info('email') },
36             U => sub { $_[0]->_user_info('name') },
37             T => sub {
38             $_[0]->zilla->is_trial ? ( defined $_[1] ? $_[1] : '-TRIAL' ) : q[];
39             },
40             V => sub {
41             $_[0]->zilla->version . ( $_[0]->zilla->is_trial ? ( defined $_[1] ? $_[1] : '-TRIAL' ) : q[] );
42             },
43             'H' => sub { $_[0]->_git_sha1 },
44             'h' => sub { $_[0]->_git_sha1_abbrev },
45             },
46             };
47              
48              
49              
50              
51              
52              
53              
54              
55              
56             has 'branch' => (
57             is => ro =>,
58             lazy_build => 1,
59             );
60              
61              
62              
63              
64              
65              
66              
67              
68              
69             has 'default_branch' => (
70             is => ro =>,
71             lazy_build => 1,
72             predicate => 'has_default_branch',
73             );
74              
75             sub _build_default_branch {
76             my ($self) = @_;
77             return $self->log_fatal('default_branch was used but not specified');
78             }
79              
80             has _git_timestamp => (
81             init_arg => undef,
82             is => ro =>,
83             lazy_build => 1,
84             );
85             has '_gwp' => (
86             init_arg => undef,
87             is => ro =>,
88             lazy_build => 1,
89             );
90              
91             around dump_config => config_dumper( __PACKAGE__, { attrs => [ 'default_branch', 'branch' ] } );
92              
93             sub _build__gwp {
94             my ($self) = @_;
95             return Git::Wrapper::Plus->new( q[] . $self->zilla->root );
96             }
97              
98             sub _build_branch {
99             my ($self) = @_;
100             my $cb = $self->_gwp->branches->current_branch;
101             if ( not $cb ) {
102             if ( not $self->has_default_branch ) {
103             $self->log_fatal(
104             [
105             q[Cannot determine branch to get timestamp from when not on a branch.]
106             . q[Specify default_branch if you want this to work here.],
107             ],
108             );
109             }
110             return $self->default_branch;
111             }
112             return $cb->name;
113             }
114              
115             has '_branch_object' => ( is => ro =>, init_arg => undef, lazy_build => 1 );
116             has '_branch_commit' => ( is => ro =>, init_arg => undef, lazy_build => 1 );
117             has '_git_sha1' => ( is => ro =>, init_arg => undef, lazy_build => 1 );
118             has '_git_sha1_abbrev' => ( is => ro =>, init_arg => undef, lazy_build => 1 );
119              
120             sub _build__branch_object {
121             my ($self) = @_;
122             my ( $branch, ) = $self->_gwp->branches->get_branch( $self->branch );
123             if ( not $branch ) {
124             $self->log_fatal( [ q[Branch %s does not exist], $self->branch ] );
125             }
126             return $branch;
127             }
128              
129             sub _build__git_sha1 {
130             my ($self) = @_;
131             return $self->_branch_object->sha1;
132             }
133              
134             sub _build__git_sha1_abbrev {
135             my ($self) = @_;
136             return substr $self->_git_sha1, 0, 7;
137             }
138              
139             sub _build__branch_commit {
140             my ($self) = @_;
141             return [ $self->_gwp->git->cat_file( 'commit', $self->_git_sha1 ) ];
142             }
143              
144             sub _build__git_timestamp {
145             my ($self) = @_;
146             my ( $committer, ) = grep { /\Acommitter /msx } @{ $self->_branch_commit };
147             chomp $committer;
148             ## no critic ( Compatibility::PerlMinimumVersionAndWhy )
149             if ( $committer =~ qr/\s+(\d+)\s+(\S+)\z/msx ) {
150             return DateTime->from_epoch( epoch => $1, time_zone => $2 );
151             }
152             return $self->log_fatal( [ q[Could not parse timestamp and timezone from string <%s>], $committer ] );
153             }
154              
155              
156              
157              
158              
159              
160              
161              
162              
163              
164             sub section_header {
165             my ($self) = @_;
166              
167             return _format_version( $self->format, $self );
168             }
169             __PACKAGE__->meta->make_immutable;
170             no Moose;
171              
172             1;
173              
174             __END__
175              
176             =pod
177              
178             =encoding UTF-8
179              
180             =head1 NAME
181              
182             Dist::Zilla::Plugin::Git::NextRelease - Use time-stamp from Git instead of process start time.
183              
184             =head1 VERSION
185              
186             version 0.004000
187              
188             =head1 SYNOPSIS
189              
190             This module acts as a moderately thin wrapper to L<< C<[NextRelease]>|Dist::Zilla::Plugin::NextRelease >>
191             so that the time-stamps produced are generated by asking C<git> for the time-stamp of the current branch.
192              
193             If you always require a specific branch for generating time-stamps, it can be specified as a parameter.
194              
195             -[NextRelease]
196             +[Git::NextRelease]
197              
198             Optionally:
199              
200             +branch = master
201              
202             Or:
203              
204             +default_branch = master
205              
206             ( The latter only having impact in detached-head conditions )
207              
208             This exists mostly because of my extensive use of L<< C<[Git::CommitBuild]>|Dist::Zilla::Plugin::Git::CommitBuild >>, to provide
209             a commit series for both releases, and builds of all changes/commits in order to push them to Travis for testing. ( Mostly,
210             because testing a build branch is substantially faster than testing a master that requires C<Dist::Zilla>, especially if you're
211             doing "Fresh install" testing like I am. )
212              
213             =head1 METHODS
214              
215             =head2 C<section_header>
216              
217             This is the sole method of L<< C<[NextRelease]>|Dist::Zilla::Plugin::NextRelease >> that we override,
218             in order for it to inject the right things.
219              
220             This method basically returns the date string to append to the Changes header.
221              
222             =head1 ATTRIBUTES
223              
224             =head2 C<branch>
225              
226             If set, always use the specified branch to determine time-stamp.
227              
228             Default value is resolved from determining "current" branch.
229              
230             =head2 C<default_branch>
231              
232             If you want being on a branch to always resolve to that branch,
233             but you still want a useful behavior when on a detached head,
234             specifying this value means that on a detached head, the stated branch will be used instead.
235              
236             =head1 FORMATS
237              
238             C<[Git::NextRelease]> enhances and adds a few features of C<[NextRelease]>
239              
240             =over 4
241              
242             =item * C<%d> - A CLDR formatter of the C<branch>'s C<HEAD> timestamp. ( Original uses simply C<now> )
243              
244             =item * C<%H> - The SHA1 of C<branch>'s C<HEAD>
245              
246             =item * C<%h> - The SHA1 of C<branch>'s C<HEAD> shortened to 7 characters.
247              
248             =back
249              
250             =head1 AUTHOR
251              
252             Kent Fredric <kentnl@cpan.org>
253              
254             =head1 COPYRIGHT AND LICENSE
255              
256             This software is copyright (c) 2014 by Kent Fredric <kentfredric@gmail.com>.
257              
258             This is free software; you can redistribute it and/or modify it under
259             the same terms as the Perl 5 programming language system itself.
260              
261             =cut