File Coverage

blib/lib/Dist/Zilla/Plugin/ReleaseStatus/FromVersion.pm
Criterion Covered Total %
statement 43 43 100.0
branch 11 16 68.7
condition 1 3 33.3
subroutine 13 13 100.0
pod 0 2 0.0
total 68 77 88.3


line stmt bran cond sub pod time code
1 1     1   1827064 use v5.10;
  1         2  
2 1     1   4 use strict;
  1         1  
  1         17  
3 1     1   4 use warnings;
  1         1  
  1         44  
4              
5             package Dist::Zilla::Plugin::ReleaseStatus::FromVersion;
6             # ABSTRACT: Set release status from version number patterns
7              
8             our $VERSION = '0.001';
9              
10 1     1   3 use Moose;
  1         1  
  1         6  
11 1     1   3784 use Moose::Util::TypeConstraints qw/enum/;
  1         2  
  1         7  
12 1     1   253 use version;
  1         1  
  1         6  
13              
14             use constant {
15 1         475 STABLE => 'stable',
16             TESTING => 'testing',
17             UNSTABLE => 'unstable',
18 1     1   58 };
  1         2  
19              
20             my %RULES = (
21             none => sub { 0 },
22             second_decimal_odd => _odd_digit_checker(2),
23             third_decimal_odd => _odd_digit_checker(3),
24             fourth_decimal_odd => _odd_digit_checker(4),
25             fifth_decimal_odd => _odd_digit_checker(5),
26             sixth_decimal_odd => _odd_digit_checker(6),
27             second_element_odd => _odd_tuple_checker(2),
28             third_element_odd => _odd_tuple_checker(3),
29             fourth_element_odd => _odd_tuple_checker(4),
30             );
31              
32             enum VersionMode => [ keys %RULES ];
33              
34             #pod =attr testing
35             #pod
36             #pod Rule for setting status to 'testing'. Must be one of the L</Status Rules>.
37             #pod
38             #pod The default is C<none>.
39             #pod
40             #pod =cut
41              
42             has testing => (
43             is => 'ro',
44             isa => 'VersionMode',
45             default => 'none',
46             );
47              
48             #pod =attr unstable
49             #pod
50             #pod Rule for setting status to 'unstable'. Must be one of the L</Status rules>.
51             #pod
52             #pod This setting takes precedence over C<testing>.
53             #pod
54             #pod The default is C<none>.
55             #pod
56             #pod =cut
57              
58             has unstable => (
59             is => 'ro',
60             isa => 'VersionMode',
61             default => 'none',
62             );
63              
64             sub BUILD {
65 38     38 0 47 my ($self) = @_;
66 38         64 for my $type ( TESTING, UNSTABLE ) {
67 76         2619 my $rule = $self->$type;
68             $self->logger->log_fatal("Unknown rule for '$type': $rule")
69 76 50       1381 unless $RULES{$rule};
70             }
71             }
72              
73             sub provide_release_status {
74 38     38 0 658082 my $self = shift;
75 38         1118 my $version = version->new( $self->zilla->version );
76              
77 38 100       2160 $self->logger->log_fatal("Versions with underscore ('$version') are not supported")
78             if $version =~ /_/;
79              
80             return
81             $RULES{ $self->unstable }->($version) ? UNSTABLE
82 36 100       1289 : $RULES{ $self->testing }->($version) ? TESTING
    100          
83             : STABLE;
84             }
85              
86             #--------------------------------------------------------------------------#
87             # utility functions
88             #--------------------------------------------------------------------------#
89              
90             sub _odd_digit_checker {
91 5     5   4 my $pos = shift;
92             return sub {
93 21     21   21 my $version = shift;
94 21 50       58 return if $version->is_qv;
95 21         92 my ($fraction) = $version =~ m{\.(\d+)\z};
96 21 50 33     102 return unless defined($fraction) && length($fraction) >= $pos;
97 21         312 return substr( $fraction, $pos - 1, 1 ) % 2;
98 5         11 };
99             }
100              
101             sub _odd_tuple_checker {
102 3     3   4 my $pos = shift;
103             return sub {
104 20     20   30 my $version = shift;
105 20 50       69 return unless $version->is_qv;
106 20         98 my $string = $version->normal;
107 20         58 $string =~ s/^v//;
108 20         58 my @tuples = split /\./, $string;
109 20 50       365 return ( defined( $tuples[ $pos - 1 ] ) ? ( $tuples[ $pos - 1 ] % 2 ) : 0 );
110 3         10 };
111             }
112              
113             with 'Dist::Zilla::Role::ReleaseStatusProvider';
114              
115             __PACKAGE__->meta->make_immutable;
116              
117             1;
118              
119              
120             # vim: ts=4 sts=4 sw=4 et tw=75:
121              
122             __END__
123              
124             =pod
125              
126             =encoding UTF-8
127              
128             =head1 NAME
129              
130             Dist::Zilla::Plugin::ReleaseStatus::FromVersion - Set release status from version number patterns
131              
132             =head1 VERSION
133              
134             version 0.001
135              
136             =head1 SYNOPSIS
137              
138             # in dist.ini
139             [ReleaseStatus::FromVersion]
140             testing = third_decimal_odd
141              
142             =head1 DESCRIPTION
143              
144             This module tells L<Dist::Zilla> to set a distribution's release status based
145             on its version number.
146              
147             There are two attributes: C<testing> and C<unstable>. Each is assigned a
148             string corresponding to a rule to apply to the distribution's version.
149             (See L</Status rules>)
150              
151             If the C<unstable> rule is true, the release status will be 'unstable'.
152             Otherwise, if the C<testing> rule is true, the release status will be
153             'testing'. Otherwise, the release status will be 'stable'.
154              
155             B<NOTE>: Use of this plugin with version numbers with underscores – whether
156             decimal or tuple – will result in a fatal error. This module B<replaces>
157             underscore heuristics to determine release status and is thus incompatible
158             with such versions.
159              
160             =head1 USAGE
161              
162             Add C<[ReleaseStatus::FromVersion]> to your dist.ini and set the
163             C<testing> and/or C<unstable> attributes. Keep in mind that
164             C<unstable> has the highest precedence.
165              
166             =head2 Status rules
167              
168             =head3 Default rule
169              
170             The default rule 'none' is always false.
171              
172             =head3 Decimal version rules
173              
174             This set of rules apply only to "decimal versions" — versions that
175             that look like integers or floating point numbers. They will be
176             false if applied to a version tuple.
177              
178             The only decimal rules so far check a particular digit after the decimal
179             point and return true if the digit is odd:
180              
181             second_decimal_odd
182             third_decimal_odd
183             fourth_decimal_odd
184             fifth_decimal_odd
185             sixth_decimal_odd
186              
187             For example, here is the 'fourth_decimal_odd' rule applied to two
188             version numbers:
189              
190             1.0100 — false
191             1.0101 — true
192              
193             =head3 Tuple version rules
194              
195             This set of rules apply only to "tuple versions", aka "dotted-decimal
196             versions" — versions that that look like "v1", "v1.2", "v1.2.3" and so on.
197             They also apply to versions without the leading-v as long as there are more
198             than two decimal points, e.g. "1.2.3". They will be false if applied to a
199             decimal version.
200              
201             Tuple versions treat each decimal-separated value as an individual number.
202              
203             The only tuple rules so far check a particular element of the tuple and
204             return true if the element is odd:
205              
206             second_element_odd
207             third_element_odd
208             fourth_element_odd
209              
210             For example, here is the 'second_element_odd' rule applied to two
211             version numbers:
212              
213             v1.0.3 — false
214             v1.1.3 — true
215              
216             =head3 New rules
217              
218             If you have an idea for a new rule, please look at how the existing rules
219             are implemented and open a Github issue or send a pull-request with your
220             idea.
221              
222             =head1 ATTRIBUTES
223              
224             =head2 testing
225              
226             Rule for setting status to 'testing'. Must be one of the L</Status Rules>.
227              
228             The default is C<none>.
229              
230             =head2 unstable
231              
232             Rule for setting status to 'unstable'. Must be one of the L</Status rules>.
233              
234             This setting takes precedence over C<testing>.
235              
236             The default is C<none>.
237              
238             =for Pod::Coverage BUILD STABLE TESTING UNSTABLE provide_release_status
239              
240             =head1 EXAMPLE
241              
242             Here is a somewhat contrived example demonstrating precedence:
243              
244             [ReleaseStatus::FromVersion]
245              
246             unstable = second_decimal_odd
247             testing = fourth_decimal_odd
248              
249             # results for different possible version
250              
251             1.0000 — stable
252             1.0100 — unstable
253             1.0101 — unstable
254             1.0200 — stable
255             1.0201 — testing
256             1.0202 — stable
257              
258             =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
259              
260             =head1 SUPPORT
261              
262             =head2 Bugs / Feature Requests
263              
264             Please report any bugs or feature requests through the issue tracker
265             at L<https://github.com/dagolden/Dist-Zilla-Plugin-ReleaseStatus-FromVersion/issues>.
266             You will be notified automatically of any progress on your issue.
267              
268             =head2 Source Code
269              
270             This is open source software. The code repository is available for
271             public review and contribution under the terms of the license.
272              
273             L<https://github.com/dagolden/Dist-Zilla-Plugin-ReleaseStatus-FromVersion>
274              
275             git clone https://github.com/dagolden/Dist-Zilla-Plugin-ReleaseStatus-FromVersion.git
276              
277             =head1 AUTHOR
278              
279             David Golden <dagolden@cpan.org>
280              
281             =head1 CONTRIBUTOR
282              
283             =for stopwords David Golden
284              
285             David Golden <xdg@xdg.me>
286              
287             =head1 COPYRIGHT AND LICENSE
288              
289             This software is Copyright (c) 2015 by David Golden.
290              
291             This is free software, licensed under:
292              
293             The Apache License, Version 2.0, January 2004
294              
295             =cut