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