File Coverage

blib/lib/Dist/Zilla/PluginBundle/Git/VersionManager.pm
Criterion Covered Total %
statement 34 34 100.0
branch n/a
condition 1 2 50.0
subroutine 9 9 100.0
pod 0 1 0.0
total 44 46 95.6


line stmt bran cond sub pod time code
1 1     1   2718049 use strict;
  1         2  
  1         29  
2 1     1   6 use warnings;
  1         2  
  1         74  
3             package Dist::Zilla::PluginBundle::Git::VersionManager; # git description: 69fbd84
4             # vim: set ts=8 sts=4 sw=4 tw=115 et :
5             # ABSTRACT: A plugin bundle that manages your version in git
6             # KEYWORDS: bundle distribution git version Changes increment
7              
8             our $VERSION = '0.001';
9              
10 1     1   10 use Moose;
  1         3  
  1         9  
11             with
12             'Dist::Zilla::Role::PluginBundle::Easy',
13             'Dist::Zilla::Role::PluginBundle::PluginRemover' => { -version => '0.103' },
14             'Dist::Zilla::Role::PluginBundle::Config::Slicer';
15              
16 1     1   6257 use List::Util 1.45 qw(any uniq);
  1         26  
  1         96  
17 1     1   9 use Dist::Zilla::Util;
  1         2  
  1         41  
18 1     1   10 use Moose::Util::TypeConstraints qw(subtype where class_type);
  1         3  
  1         12  
19 1     1   624 use CPAN::Meta::Requirements;
  1         2  
  1         27  
20 1     1   5 use namespace::autoclean;
  1         1  
  1         9  
21              
22             has changes_version_columns => (
23             is => 'ro', isa => subtype('Int', where { $_ > 0 && $_ < 20 }),
24             init_arg => undef,
25             lazy => 1,
26             default => sub { $_[0]->payload->{changes_version_columns} // 10 },
27             );
28              
29             has commit_files_after_release => (
30             isa => 'ArrayRef[Str]',
31             init_arg => undef,
32             lazy => 1,
33             default => sub { $_[0]->payload->{commit_files_after_release} // [] },
34             traits => ['Array'],
35             handles => { commit_files_after_release => 'elements' },
36             );
37              
38             around commit_files_after_release => sub {
39             my $orig = shift; my $self = shift;
40             sort(uniq($self->$orig(@_), 'Changes'));
41             };
42              
43             sub mvp_multivalue_args { qw(commit_files_after_release) }
44              
45             has _develop_requires => (
46             isa => class_type('CPAN::Meta::Requirements'),
47             lazy => 1,
48             default => sub { CPAN::Meta::Requirements->new },
49             handles => {
50             _add_minimum_develop_requires => 'add_minimum',
51             _develop_requires_as_string_hash => 'as_string_hash',
52             },
53             );
54              
55             sub configure
56             {
57 1     1 0 5 my $self = shift;
58              
59             my $fallback_version_provider =
60 1   50     28 $self->payload->{'RewriteVersion::Transitional.fallback_version_provider'}
61             // 'Git::NextVersion'; # TODO: move this default to an attribute; be careful of overlays
62              
63             # allow override of any config option for the fallback_version_provider plugin
64             # by specifying it as if it was used directly
65             # i.e. Git::NextVersion.foo = ... in dist.ini is rewritten in the payload as
66             # RewriteVersion::Transitional.foo = ... so it can override defaults passed in by the caller
67             # (a wrapper plugin bundle.)
68 1         10 foreach my $fallback_key (grep { /^$fallback_version_provider\./ } keys %{ $self->payload })
  4         33  
  1         25  
69             {
70 1         15 (my $new_key = $fallback_key) =~ s/^$fallback_version_provider(?=\.)/RewriteVersion::Transitional/;
71 1         27 $self->payload->{$new_key} = delete $self->payload->{$fallback_key};
72             }
73              
74             $self->add_plugins(
75             # VersionProvider (and a file munger, for the transitional usecase)
76 1         21 [ 'RewriteVersion::Transitional' => { ':version' => '0.004' } ],
77              
78             [ 'MetaProvides::Update' ],
79              
80             # After Release
81             [ 'CopyFilesFromRelease' => { filename => [ 'Changes' ] } ],
82             [ 'Git::Commit' => 'release snapshot' => {
83             ':version' => '2.020',
84             allow_dirty => [ $self->commit_files_after_release ],
85             } ],
86             [ 'Git::Tag' => {} ],
87             [ 'BumpVersionAfterRelease::Transitional' => { ':version' => '0.004' } ],
88             [ 'NextRelease' => { ':version' => '5.033', time_zone => 'UTC', format => '%-' . ($self->changes_version_columns - 2) . 'v %{yyyy-MM-dd HH:mm:ss\'Z\'}d%{ (TRIAL RELEASE)}T' } ],
89             [ 'Git::Commit' => 'post-release commit' => {
90             ':version' => '2.020',
91             allow_dirty => [ 'Changes' ],
92             allow_dirty_match => [ '^lib/.*\.pm$' ],
93             commit_msg => 'increment $VERSION after %v release'
94             } ],
95             );
96              
97             # ensure that additional optional plugins are declared in prereqs
98             $self->add_plugins(
99             [ 'Prereqs' => 'prereqs for @Git::VersionManager' =>
100             { '-phase' => 'develop', '-relationship' => 'requires',
101 1         276 %{ $self->_develop_requires_as_string_hash } } ]
  1         5  
102             );
103             }
104              
105             # determine develop prereqs
106             around add_plugins => sub
107             {
108             my ($orig, $self, @plugins) = @_;
109              
110             my $remove = $self->payload->{ $self->plugin_remover_attribute } // [];
111              
112             foreach my $plugin_spec (@plugins = map { ref $_ ? $_ : [ $_ ] } @plugins)
113             {
114             next if any { $_ eq $plugin_spec->[0] } @$remove;
115              
116             # this plugin is provided in the local distribution
117             next if $plugin_spec->[0] eq 'MetaProvides::Update';
118              
119             # record develop prereq
120             my $payload = ref $plugin_spec->[-1] ? $plugin_spec->[-1] : {};
121             my $plugin = Dist::Zilla::Util->expand_config_package_name($plugin_spec->[0]);
122             $self->_add_minimum_develop_requires($plugin => $payload->{':version'} // 0);
123             }
124              
125             return $self->$orig(@plugins);
126             };
127              
128             __PACKAGE__->meta->make_immutable;
129             1;
130              
131             __END__
132              
133             =pod
134              
135             =encoding UTF-8
136              
137             =head1 NAME
138              
139             Dist::Zilla::PluginBundle::Git::VersionManager - A plugin bundle that manages your version in git
140              
141             =head1 VERSION
142              
143             version 0.001
144              
145             =head1 SYNOPSIS
146              
147             In your F<dist.ini>:
148              
149             [@Author::You], or other config entries...
150              
151             [@Git::VersionManager]
152             [Git::Push]
153              
154             Or, in your plugin bundle's C<configure> method:
155              
156             $self->add_plugin(...);
157             $self->add_bundle('@Git::VersionManager' => \%options)
158             $self->add_plugin('Git::Push');
159              
160             =head1 DESCRIPTION
161              
162             This is a L<Dist::Zilla> plugin bundle that manages the version of your distribution, and the C<$VERSION> of the
163             modules within it. The current version (of the release in question) is determined from C<our $VERSION = ...>
164             declarations in the code (or from the C<V> environment variable), the F<Changes> file is updated and committed as a
165             release commit to C<git>, which is then tagged, and then the C<$VERSION> in code is then incremented and then that
166             change is committed. The default options used for the plugins are carefully curated to work together, but all
167             can be customized or overridden (see below).
168              
169             It is equivalent to the following configuration directly in a F<dist.ini>:
170              
171             [RewriteVersion::Transitional]
172             :version = 0.004
173              
174             [CopyFilesFromRelease / copy Changes]
175             filename = Changes
176              
177             [Git::Commit / release snapshot]
178             :version = 2.020
179             allow_dirty = Changes
180             allow_dirty = ... anything else passed in 'commit_files_after_release'
181              
182             [Git::Tag]
183              
184             [BumpVersionAfterRelease::Transitional]
185             :version = 0.004
186              
187             [NextRelease]
188             :version = 5.033
189             time_zone = UTC
190             format = %-8v %{yyyy-MM-dd HH:mm:ss'Z'}d%{ (TRIAL RELEASE)}T
191              
192             [Git::Commit / post-release commit]
193             :version = 2.020
194             allow_dirty = Changes
195             allow_dirty_match = ^lib/.*\.pm$
196             commit_msg = increment $VERSION after %v release
197              
198             [Prereqs / prereqs for @Git::VersionManager]
199             -phase = develop
200             -relationship = requires
201             ...all the plugins this bundle uses...
202              
203             =for Pod::Coverage configure
204              
205             =head1 OPTIONS / OVERRIDES
206              
207             =for stopwords CopyFilesFromRelease
208              
209             =head2 commit_files_after_release
210              
211             File(s), which are expected to exist in the repository directory,
212             to be committed to git as part of the release commit. Can be used more than once.
213             When specified, the default is appended to, rather than overwritten.
214             Defaults to F<Changes>.
215              
216             Note that you are responsible for ensuring these files are in the repository
217             (perhaps by using L<[CopyFilesFromRelease]|Dist::Zilla::Plugin::CopyFilesFromRelease>.
218             Additionally, the file(s) will not be committed if they do not already have git history;
219             for new files, you should add the C<add_files_in = .> configuration (and use
220             L<[Git::Check]|Dist::Zilla::Plugin::Git::Check> to ensure that B<only> these files
221             exist in the repository, not any other files that should not be added.)
222              
223             =head2 changes_version_columns
224              
225             An integer that specifies how many columns (right-padded with whitespace) are
226             allocated in F<Changes> entries to the version string. Defaults to 10.
227             Unused if C<NextRelease.format = anything> is passed into the configuration.
228              
229             =for stopwords customizations
230              
231             =head2 other customizations
232              
233             This bundle makes use of L<Dist::Zilla::Role::PluginBundle::PluginRemover> and
234             L<Dist::Zilla::Role::PluginBundle::Config::Slicer> to allow further customization.
235             (Note that even though some overridden values are inspected in this class,
236             they are still overlaid on top of whatever this bundle eventually decides to
237             pass -- so what is in the F<dist.ini> or in the C<add_bundle> arguments always
238             trumps everything else.)
239              
240             Plugins are not loaded until they are actually needed, so it is possible to
241             C<--force>-install this plugin bundle and C<-remove> some plugins that do not
242             install or are otherwise problematic (although release functionality will
243             likely be broken, you should still be able to build the distribution, more or less).
244              
245             =head1 SUPPORT
246              
247             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-PluginBundle-Git-VersionManager>
248             (or L<bug-Dist-Zilla-PluginBundle-Git-VersionManager@rt.cpan.org|mailto:bug-Dist-Zilla-PluginBundle-Git-VersionManager@rt.cpan.org>).
249              
250             There is also a mailing list available for users of this distribution, at
251             L<http://dzil.org/#mailing-list>.
252              
253             There is also an irc channel available for users of this distribution, at
254             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
255              
256             I am also usually active on irc, as 'ether' at C<irc.perl.org>.
257              
258             =head1 AUTHOR
259              
260             Karen Etheridge <ether@cpan.org>
261              
262             =head1 COPYRIGHT AND LICENCE
263              
264             This software is copyright (c) 2017 by Karen Etheridge.
265              
266             This is free software; you can redistribute it and/or modify it under
267             the same terms as the Perl 5 programming language system itself.
268              
269             =cut