File Coverage

blib/lib/Version/Dotted.pm
Criterion Covered Total %
statement 112 113 99.1
branch 24 26 92.3
condition 5 5 100.0
subroutine 26 26 100.0
pod 10 10 100.0
total 177 180 98.3


line stmt bran cond sub pod time code
1             # ---------------------------------------------------------------------- copyright and license ---
2             #
3             # file: lib/Version/Dotted.pm
4             #
5             # Copyright © 2016 Van de Bugger.
6             #
7             # This file is part of perl-Version-Dotted.
8             #
9             # perl-Version-Dotted is free software: you can redistribute it and/or modify it under the terms
10             # of the GNU General Public License as published by the Free Software Foundation, either version
11             # 3 of the License, or (at your option) any later version.
12             #
13             # perl-Version-Dotted is distributed in the hope that it will be useful, but WITHOUT ANY
14             # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15             # PURPOSE. See the GNU General Public License for more details.
16             #
17             # You should have received a copy of the GNU General Public License along with
18             # perl-Version-Dotted. If not, see .
19             #
20             # ---------------------------------------------------------------------- copyright and license ---
21              
22             #pod =for :this This is C module/class documentation. Read it first because it contains
23             #pod many relevant details, and use one of subclasses.
24             #pod
25             #pod =for :those General topics like getting source, building, installing, bug reporting and some others
26             #pod are covered in the F.
27             #pod
28             #pod =for test_synopsis my ( $v, $i, $int, @int, $str, $bool );
29             #pod
30             #pod =head1 SYNOPSIS
31             #pod
32             #pod use Version::Dotted; # import nothing
33             #pod use Version::Dotted 'qv'; # import qv
34             #pod
35             #pod # Construct:
36             #pod $v = Version::Dotted->new( v1.2.3 ); # same as qv( v1.2.3 )
37             #pod $v = qv( v1.2.3 ); # v1.2.3
38             #pod $v = qv( 'v1.2.0' ); # v1.2 (trailing zero parts ignored)
39             #pod $v = qv( 'v1' ); # v1
40             #pod
41             #pod # Access parts:
42             #pod @int = $v->parts; # Get all parts.
43             #pod $int = $v->part( $i ); # Get i-th part (zero-based).
44             #pod
45             #pod # Bump the version:
46             #pod $v->bump( $i ); # Bump i-th part
47             #pod # and drop all parts behind i-th.
48             #pod
49             #pod # Determine release status:
50             #pod $bool = $v->is_trial;
51             #pod
52             #pod # Stringify:
53             #pod $str = $v->stringify; # "v1.2.3"
54             #pod $str = "$v"; # ditto
55             #pod
56             #pod # Compare:
57             #pod $bool = $v >= v1.2.3;
58             #pod $bool = $v <=> 'v1.2.3';
59             #pod
60             #pod =head1 DESCRIPTION
61             #pod
62             #pod =head2 Purpose
63             #pod
64             #pod C is I a replacement for C, if you are going to declare version of
65             #pod your module or compare versions, just L|/Using version>.
66             #pod
67             #pod C is designed for two purposes:
68             #pod
69             #pod =over
70             #pod
71             #pod =item 1
72             #pod
73             #pod To bump a dotted version.
74             #pod
75             #pod =item 2
76             #pod
77             #pod To implement well-defined approach(es) to trial versions which do(es) not rely on underscore
78             #pod character to be compatible with C module 0.77 or later.
79             #pod
80             #pod =back
81             #pod
82             #pod See also L.
83             #pod
84             #pod =head2 Types of Versions
85             #pod
86             #pod Historically, two types of version numbers are used in Perl: L and
87             #pod L.
88             #pod
89             #pod C handles dotted versions, obviously, and only: no support for decimal versions is
90             #pod provided intentionally.
91             #pod
92             #pod =head2 Bumping
93             #pod
94             #pod "Bumping" means incrementing a version part by one and dropping all the parts behind the
95             #pod incremented. For example, bumping the third part of C gives C, bumping the second
96             #pod part of C gives C (the third part is dropped).
97             #pod
98             #pod =head2 Trial Versions
99             #pod
100             #pod Firstly, C prefers "trial" term to "alpha" (see L).
101             #pod
102             #pod Secondly, trial versions are not denoted by underscore character anymore (see L). Definition
103             #pod of trial version is left for subclasses.
104             #pod
105             #pod =head2 Parent(s)
106             #pod
107             #pod C is heavily influenced by C, but C is not a
108             #pod subclass of C.
109             #pod
110             #pod C it is a subclass of C. The class narrows C
111             #pod C creates only dotted (aka dotted-decimal) version objects. The class extends
112             #pod C — C objects are modifiable.
113             #pod
114             #pod =head2 Error Reporting
115             #pod
116             #pod The class reports error by C. It gives flexibility to the caller: warning may be
117             #pod either suppressed
118             #pod
119             #pod no warnings 'Version::Dotted';
120             #pod
121             #pod or made fatal:
122             #pod
123             #pod use warnings FATAL => 'Version::Dotted';
124             #pod
125             #pod =cut
126              
127             package Version::Dotted;
128              
129 3     3   33778 use strict;
  3         4  
  3         80  
130 3     3   11 use warnings;
  3         3  
  3         60  
131 3     3   11 use warnings::register;
  3         3  
  3         266  
132 3     3   9 use version 0.77 qw{};
  3         41  
  3         90  
133              
134             # ABSTRACT: Bump a dotted version, check if version is trial
135             our $VERSION = 'v0.0.0_07'; # TRIAL VERSION
136              
137 3     3   362 use parent 'version';
  3         223  
  3         14  
138             use overload (
139 3         20 'cmp' => \&_cmp,
140             '<=>' => \&_cmp,
141 3     3   3024 );
  3         2166  
142              
143             # --------------------------------------------------------------------------------------------------
144              
145             #pod =Attribute min_len
146             #pod
147             #pod Minimal number of parts, read-only.
148             #pod
149             #pod $int = Version::Dotted->min_len; # == 1
150             #pod
151             #pod Objects are maintained to have at least minimal number of parts. In C minimal
152             #pod number of parts is 1, subclasses may raise the bar.
153             #pod
154             #pod =cut
155              
156 187     187 1 229 sub min_len { 1 }; ## no critic ( RequireFinalReturn )
157              
158 210     210   380 sub _max_len { 1000 }; ## no critic ( RequireFinalReturn )
159             # TODO: INTMAX?
160              
161             sub _warn {
162 26     26   32 my ( $self, $message ) = @_;
163 26         437 warnings::warnif( 'Version::Dotted', $message );
164 26         11172 return;
165             };
166              
167             # --------------------------------------------------------------------------------------------------
168              
169             #pod =Method C
170             #pod
171             #pod Constructs a new version object.
172             #pod
173             #pod $obj = Version::Dotted->new( $arg );
174             #pod
175             #pod The constructor accepts one argument and creates dotted version object. An argument can be either
176             #pod integer number (C<1>), floating point number (C<1.2>), v-string (C), or string (with or
177             #pod without leading v: C<'1.2'>, C<'v1.2'>), or C object. Trailing zero parts may be stripped
178             #pod (if number of parts exceeds required minimum), leading zeros in parts are insignificant:
179             #pod
180             #pod Version::Dotted->new( 1.2.0 ) == Version::Dotted->new( v1.2 );
181             #pod Version::Dotted->new( 1.002 ) == Version::Dotted->new( v1.2 );
182             #pod
183             #pod However, to avoid surprises (see L and L) it is better to stick to
184             #pod using v-strings or strings, using numbers is not recommended (and may be prohibited in future).
185             #pod
186             #pod =caveat Leading Zeros
187             #pod
188             #pod Leading zeros in parts are insignificant:
189             #pod
190             #pod qv( v01.02.03 ) == v1.2.3;
191             #pod qv( 1.002 ) == v1.2;
192             #pod
193             #pod However, Perl interprets numbers with leading zero as octal, so be aware of:
194             #pod
195             #pod qv( 010 ) == v8; # 010 == 8
196             #pod qv( 010.011 ) == v89; # 010.011 eq 8 . 9 eq "89"
197             #pod
198             #pod To avoid surprises stick to using v-strings or strings:
199             #pod
200             #pod qv( v010 ) == v10;
201             #pod qv( v010.011 ) == v10.10;
202             #pod qv( 'v010.011' ) == v10.10;
203             #pod
204             #pod =caveat Trailing Zeros
205             #pod
206             #pod Perl ignores trailing zeros in floating point numbers:
207             #pod
208             #pod 1.200 == 1.2;
209             #pod
210             #pod so
211             #pod
212             #pod qv( 1.200 ) == v1.2; # not v1.200
213             #pod
214             #pod To avoid such surprises stick to using v-strings or strings:
215             #pod
216             #pod qv( v1.200 ) == v1.200;
217             #pod qv( '1.200' ) == v1.200;
218             #pod
219             #pod =cut
220              
221             sub new {
222 195     195 1 266 my ( $class, $arg ) = @_;
223 195         169 my $v;
224 195 100       175 if ( eval { $arg->isa( 'version' ) } ) {
  195         975  
225 3         21 $v = $class->declare( 0 ); # Create a new version object.
226 3         4 $v->{ version } = [ @{ $arg->{ version } } ]; # Copy version parts.
  3         18  
227             } else {
228 192 100       355 if ( not defined $arg ) {
229 1         7 $class->_warn( "Use of undefined value to construct version" );
230 1         2 $arg = 'v0';
231             };
232             # `declare` can die if `$arg` is not valid. It will complain on Version/Dotted.pm, which
233             # is not good — we have to translate errors to caller code. Unfortunately, tricks with
234             # @version::CARP_NOT does not work. @version::vpp:CARP_NOT does work, but only if vpp
235             # module is used (which is not normal case). @version::vxs::CARP_NOT is not respected at
236             # all. So we have to catch and rethrow exception in order to edit source location.
237             eval {
238 192         1301 $v = $class->declare( $arg );
239 191         491 1;
240 192 100       169 } or do {
241 1 50       14 if ( $@ =~ s{ \h at \h .*?/Version/Dotted\.pm \h line \h \d+ \.? \n? \z }{}x ) {
242 1         5 $class->_warn( $@ );
243 1         6 $v = $class->declare( 0 );
244             } else {
245 0         0 die $@; ## no critic ( RequireCarping )
246             };
247             };
248             };
249 195         423 return $v->_norm();
250             };
251              
252             # --------------------------------------------------------------------------------------------------
253              
254             #pod =Method C
255             #pod
256             #pod Prints warning "Method 'parse' is not supported" and returns C.
257             #pod
258             #pod =cut
259              
260             sub parse {
261 2     2 1 224 my ( $class ) = @_;
262 2         3 $class->_warn( "Method 'parse' is not supported" );
263 2         5 return;
264             };
265              
266             # --------------------------------------------------------------------------------------------------
267              
268             # If $arg is a version object, return it as-is. Otherwise create a version object and return it.
269             sub _obj {
270 132     132   131 my ( $self, $arg ) = @_;
271 132 100       173 if ( not eval { $arg->isa( 'version' ) } ) {
  132         914  
272 125         259 $arg = $self->new( $arg );
273             };
274 132         200 return $arg;
275             };
276              
277             # --------------------------------------------------------------------------------------------------
278              
279             #pod =method C
280             #pod
281             #pod Returns all parts of the version.
282             #pod
283             #pod @int = $v->parts; # Get all parts.
284             #pod
285             #pod In scalar context it gives number of parts in the version object:
286             #pod
287             #pod $int = $v->parts; # Get number of parts.
288             #pod
289             #pod =cut
290              
291             sub parts {
292 2     2 1 9 my ( $self ) = @_;
293 2         3 return @{ $self->{ version } };
  2         39  
294             };
295              
296             # --------------------------------------------------------------------------------------------------
297              
298             #pod =method C
299             #pod
300             #pod Returns i-th part of the version.
301             #pod
302             #pod $int = $v->part( $i ); # Get i-th part.
303             #pod
304             #pod If index is larger than actual number of version parts minus one, C is returned.
305             #pod
306             #pod Negative part index causes warning but works like index to regular Perl array: C<-1> is index
307             #pod of the last version part, C<-2> — second last, etc.
308             #pod
309             #pod =cut
310              
311             sub part {
312 25     25 1 88 my ( $self, $idx ) = @_;
313 25 100       65 $idx >= 0 or $self->_warn( "Negative version part index '$idx'" );
314 25         110 return $self->{ version }->[ $idx ];
315             };
316              
317             # --------------------------------------------------------------------------------------------------
318              
319             #pod =method C
320             #pod
321             #pod Bumps i-th version part.
322             #pod
323             #pod $v->bump( $i );
324             #pod
325             #pod "Bumping" means incrementing i-th version part by one I dropping all the parts behind i-th:
326             #pod
327             #pod $v = qv( v1.2.3 ); # $v == v1.2.3
328             #pod $v->bump( 3 ); # $v == v1.2.3.1
329             #pod $v->bump( 2 ); # $v == v1.2.4
330             #pod $v->bump( 1 ); # $v == v1.3
331             #pod $v->bump( 0 ); # $v == v2
332             #pod
333             #pod If index is larger than actual number of version parts (minus one), missed parts are autovivified:
334             #pod
335             #pod $v->bump( 5 ); # $v == v2.0.0.0.0.1
336             #pod
337             #pod Negative part index causes warning but works.
338             #pod
339             #pod The method returns reference to version object:
340             #pod
341             #pod $v->bump( 2 )->stringify;
342             #pod
343             #pod =cut
344              
345             sub bump {
346 16     16 1 673 my ( $self, $idx ) = @_;
347 16         23 my $v = $self->{ version };
348 16 100       44 if ( $idx < - abs( @$v ) ) {
349 1         3 $self->_warn( "Invalid version part index '$idx'" );
350 1         4 return;
351             };
352 15 100       34 $idx >= 0 or $self->_warn( "Negative version part index '$idx'" );
353 15         24 ++ $v->[ $idx ];
354 15 100       28 if ( $idx == -1 ) {
355             # -1 denotes the last part, nothing to delete behind it.
356             } else {
357             # Ok, it is not the last part, let us delete everything behind it:
358 14         26 splice( @$v, $idx + 1 );
359             };
360 15         32 return $self->_norm();
361             };
362              
363             # --------------------------------------------------------------------------------------------------
364              
365             #pod =method C
366             #pod
367             #pod Returns true in case of trial version, and false otherwise.
368             #pod
369             #pod $bool = $v->is_trial;
370             #pod
371             #pod This method always returns false, but descendants will likely redefine the method.
372             #pod
373             #pod See also L.
374             #pod
375             #pod =cut
376              
377             sub is_trial {
378 9     9 1 17 my ( $self ) = @_;
379 9         21 return '';
380             };
381              
382             # --------------------------------------------------------------------------------------------------
383              
384             #pod =method C
385             #pod
386             #pod The method does the same as C but prints a warning.
387             #pod
388             #pod =cut
389              
390             sub is_alpha {
391 5     5 1 930 my ( $self ) = @_;
392 5         9 $self->_warn( "Method 'is_alpha' is not recommended, use 'is_trial' instead" );
393 5         9 return $self->is_trial;
394             };
395              
396             # --------------------------------------------------------------------------------------------------
397              
398             #pod =operator C=E>
399             #pod
400             #pod Compares two versions.
401             #pod
402             #pod $v <=> $other;
403             #pod
404             #pod The operator is inherited from parent's class (see L).
405             #pod However, there is a subtle difference: if C<$other> is not a version object, it converted to a
406             #pod version object using C (I parent's C).
407             #pod
408             #pod Other comparison operators (e. g. C>, C>, C=>, etc) are created by Perl.
409             #pod
410             #pod =operator C
411             #pod
412             #pod The same as C=E>.
413             #pod
414             #pod =cut
415              
416             sub _cmp {
417 132     132   29864 my ( $self, $other, $swap ) = @_;
418 132         251 $other = $self->_obj( $other );
419 3     3   1637 no strict 'refs'; ## no critic ( ProhibitNoStrict )
  3         6  
  3         829  
420 132         129 return &{ 'version::(cmp' }( $self, $other, $swap );
  132         1085  
421             };
422              
423             # --------------------------------------------------------------------------------------------------
424              
425             # Normalize version representation.
426             sub _norm {
427 210     210   200 my ( $self ) = @_;
428 210         466 my $v = $self->{ version };
429 210         369 my $m = $self->min_len;
430             # Make sure there are no undefined elements in the array (which can appear after `bump`):
431 210   100     1059 $_ // ( $_ = 0 ) for @$v;
432             # Make sure we have at least $m parts:
433 210         438 while ( @$v < $m ) {
434 3         6 push( @$v, 0 );
435             };
436             # Drop zero parts from the end (but keep at lest $m parts):
437 210   100     881 while ( @$v > $m and $v->[ -1 ] == 0 ) {
438 157         675 -- $#$v;
439             };
440             # Update version string representation:
441 210         633 my $s = 'v' . join( '.', @$v );
442 210         296 $self->{ original } = $s;
443             # Check number of parts:
444 210 50       364 @$v <= $self->_max_len or $self->_warn( "Bad version '$s': too many parts" );
445 210         548 return $self;
446             };
447              
448             # --------------------------------------------------------------------------------------------------
449              
450             #pod =method C
451             #pod
452             #pod Returns version string with leading 'v' character.
453             #pod
454             #pod $str = $v->stringify;
455             #pod
456             #pod See also L.
457             #pod
458             #pod =operator ""
459             #pod
460             #pod Returns version string.
461             #pod
462             #pod $str = "$v";
463             #pod
464             #pod The same as C.
465             #pod
466             #pod =note Stringification
467             #pod
468             #pod The parent class C works with dotted and decimal versions and has three stringification
469             #pod methods:
470             #pod
471             #pod $v->stringify; # as close to the original representatiion as possible
472             #pod $v->numify; # (convert to) decimal version
473             #pod $v->normal; # (convert to) dotted version with leading 'v'
474             #pod
475             #pod C and C are used to convert a version to specified form, dotted or decimal
476             #pod respectively, regardless of its actual type:
477             #pod
478             #pod version->parse( 1.003010 )->normal; # eq "v1.3.10"
479             #pod version->declare( v1.3.10 )->numify; # eq "1.003010"
480             #pod
481             #pod C works with dotted versions only. C returns dotted version string with
482             #pod leading 'v' character (like parent does), C does exactly the same, C is not
483             #pod supported:
484             #pod
485             #pod $v->normal; # dotted version with leading 'v'
486             #pod $v->stringify; # same as normal
487             #pod $v->numify; # prints warning & returns undef
488             #pod
489             #pod Practically it means C has only one stringification method. Since there is no
490             #pod place for conversion, C is the preferred name for it.
491             #pod
492             #pod =cut
493              
494             sub stringify {
495 2     2 1 5 my ( $self ) = @_;
496 2         8 return $self->{ original };
497             };
498              
499             # --------------------------------------------------------------------------------------------------
500              
501             #pod =method C
502             #pod
503             #pod The same as C.
504             #pod
505             #pod $str = $v->normal;
506             #pod
507             #pod See also L.
508             #pod
509             #pod =cut
510              
511             # Parent method will reconstruct the version string from `version` attribute and ensure it has at
512             # least 3 parts.
513              
514             *normal = \&stringify;
515              
516             # --------------------------------------------------------------------------------------------------
517              
518             #pod =method C
519             #pod
520             #pod Prints warning "Method 'numify' is not supported" and returns C.
521             #pod
522             #pod See also L.
523             #pod
524             #pod =cut
525              
526             sub numify {
527 2     2 1 222 my ( $self ) = @_;
528 2         5 $self->_warn( "Method 'numify' is not supported" );
529 2         5 return;
530             };
531              
532             # --------------------------------------------------------------------------------------------------
533              
534             #pod =head1 EXPORT
535             #pod
536             #pod The module exports nothing by default.
537             #pod
538             #pod The module installs C function (I a method) into caller namespace by explicit request:
539             #pod
540             #pod use Version::Dotted 'qv';
541             #pod
542             #pod If caller module already has C function, warning is issued and function is redefined.
543             #pod
544             #pod Note: C exports C by default, if caller package does not have C function yet.
545             #pod
546             #pod The module (unlike to C) does not play any tricks with importer's C and/or
547             #pod C.
548             #pod
549             #pod =function qv
550             #pod
551             #pod Shortcut for Cnew>.
552             #pod
553             #pod $v = qv( $arg ); # same as $v = Version::Dotted->new( $arg );
554             #pod
555             #pod The function is prototyped. It takes one scalar argument:
556             #pod
557             #pod ( $v, $w ) = qv v1.2.3, v1.2.3;
558             #pod
559             #pod C<$v> will be a C object, C<$w> will be a v-string. (C's C grabs
560             #pod entire list but uses only the first argument, C<$w> would be undefined.)
561             #pod
562             #pod Note: There is no function C in C package, the function is installed into
563             #pod importer package by explicit request, see L.
564             #pod
565             #pod =cut
566              
567             # We have to redefine parents' import. Otherwise we will export `qv` into importer namespace by
568             # default. Explicit import of `qv` is a good idea, though.
569              
570             sub import { ## no critic ( RequireArgUnpacking )
571 12     12   4376 my ( $class, @list ) = @_;
572 12         29 my $pkg = caller();
573 12         199 my %args = map( { $_ => 1 } @list );
  7         33  
574 12 100       37 if ( delete( $args{ qv } ) ) {
575 4         9 my $qv = $pkg . '::qv';
576 3     3   12 no strict 'refs'; ## no critic ( ProhibitNoStrict )
  3         3  
  3         76  
577 3     3   9 no warnings qw{ redefine prototype }; ## no critic ( ProhibitNoWarnings )
  3         3  
  3         561  
578 4 100       27 $class->_warn( "Subroutine '$qv' redefined" ) if defined &$qv;
579             *$qv = sub ($) {
580 69     69   13693 return $class->new( @_ );
581 4         26 };
582             };
583 12 100       36 if ( %args ) {
584 3         13 $class->_warn( "Bad $class import: " . join( ', ', map( { "'$_'" } keys( %args ) ) ) );
  3         22  
585             };
586 12         752 return;
587             };
588              
589             1;
590              
591             #pod =for comment ---------------------------------------------------------------------------------------
592             #pod
593             #pod =note Using C
594             #pod
595             #pod C is an Perl core module. It serves for two purposes:
596             #pod
597             #pod =over
598             #pod
599             #pod =item 1
600             #pod
601             #pod Declare package version. C module can be used either explicitly (works for any Perl
602             #pod version):
603             #pod
604             #pod package Assa;
605             #pod use version 0.77; our $VERSION = version->declare( 'v1.2.3' );
606             #pod
607             #pod or implicitly (works for Perl 5.12.0 or later):
608             #pod
609             #pod package Assa v1.2.3;
610             #pod
611             #pod In the second case Perl automatically assigns C<$VERSION> variable an object of C class.
612             #pod
613             #pod =item 2
614             #pod
615             #pod Compare package versions:
616             #pod
617             #pod version->parse( $Assa::VERSION ) >= 'v1.2.3';
618             #pod
619             #pod =back
620             #pod
621             #pod =for comment ---------------------------------------------------------------------------------------
622             #pod
623             #pod =note Decimal Versions
624             #pod
625             #pod Decimal version is just a floating-point number. In Perl decimal version can be represented by
626             #pod floating-point number, string, or C object:
627             #pod
628             #pod 0.003010 # floating-point number
629             #pod '0.003010' # string
630             #pod version->parse( '0.003010' ) # version object
631             #pod
632             #pod Floating-point numbers can be compared, but lose trailing zeros. Strings do not lose trailing
633             #pod zeros, but cannot be compared (string comparison operators are not suitable for comparing
634             #pod versions). C objects does not lose trailing zeros, can be easily compared, but cannot be
635             #pod modified.
636             #pod
637             #pod See also: L.
638             #pod
639             #pod =for comment ---------------------------------------------------------------------------------------
640             #pod
641             #pod =note Dotted Versions
642             #pod
643             #pod Dotted (aka dotted-decimal) version is a series of parts joined with dots, each part is a cardinal
644             #pod (non-negative) integer. In Perl dotted versions can be represented by v-strings, strings, or
645             #pod C objects:
646             #pod
647             #pod v0.10.3 # v-string
648             #pod 'v0.10.3' # string
649             #pod version->declare( 'v0.10.3' ) # version object
650             #pod
651             #pod V-strings can be easily compared (by C, C and other string comparison operators), but are
652             #pod not suitable for printing. Strings can be easily printed but string comparison operators are not
653             #pod suitable for comparing versions. C objects can be easily compared and printed, but cannot
654             #pod be modified. (C objects can be.)
655             #pod
656             #pod Leading 'v' character is optional: in strings — always, in v-strings — if there are two or more
657             #pod dots. However, using 'v' character is recommended for clarity and readability.
658             #pod
659             #pod See also: L.
660             #pod
661             #pod =for comment ---------------------------------------------------------------------------------------
662             #pod
663             #pod =note Conversion Rules
664             #pod
665             #pod To convert a decimal version to dotted one: (1) insert dot after each third digit in fractional
666             #pod part, and then (2) strip leading zeros in every part:
667             #pod
668             #pod 1.003010 -(1)-> 1.003.010 -(2)-> 1.3.10
669             #pod
670             #pod Obviously any possible decimal version can be conversed to corresponding dotted version.
671             #pod
672             #pod To convert a dotted version to decimal one: (1) prepend each part (except the first) with leading
673             #pod zeros to have exactly 3 digits in each part, and then (2) strip all the dots except the first:
674             #pod
675             #pod 1.3.10 -(1)-> 1.003.010 -(2)-> 1.003010
676             #pod
677             #pod Not all dotted version can be converted to corresponding decimal one. First, all parts (except the
678             #pod first) of a dotted version must comprise not more than 3 digits. Second, dotted version should not
679             #pod contain too many parts due to limited precision of floating-point numbers.
680             #pod
681             #pod =for comment ---------------------------------------------------------------------------------------
682             #pod
683             #pod =note Non-Stable Releases
684             #pod
685             #pod Perl terminology in this area in not well-defined and not consistently used:
686             #pod
687             #pod =over
688             #pod
689             #pod =item *
690             #pod
691             #pod The C module declares any version with underscore character (e. g. 'v1.2.3_4') to be an
692             #pod "alpha" version. C refers to CPAN convention "to note unstable releases with an
693             #pod underscore in the version string".
694             #pod
695             #pod =item *
696             #pod
697             #pod In turn, C defines release status as one of: C, C, and
698             #pod C. Word "alpha" is used in the description of C release, while C
699             #pod release is described as "beta". There is also requirement that C release version should not
700             #pod contain underscore. (There is no requirement that C and C releases should
701             #pod underscore.)
702             #pod
703             #pod =item *
704             #pod
705             #pod pause.perl.org site has section named "Developer Releases" which is about releasing "code for
706             #pod testing". Such releases should either have version with underscore or "-TRIAL" suffix.
707             #pod
708             #pod =item *
709             #pod
710             #pod meta::cpan site in the list of module releases shows "DEV" (which likely means "developer release")
711             #pod after versions containing underscore.
712             #pod
713             #pod =item *
714             #pod
715             #pod C tool has C<--trial> command line option to build a "release that PAUSE will not index".
716             #pod
717             #pod =back
718             #pod
719             #pod "Alpha" term used by C module (and some others) is a bad choice because it has strong
720             #pod association with "beta" and "release candidate" terms, which do not have any support by C.
721             #pod
722             #pod "Trial" term sounds more neutral and generic: a trial release could be either "alpha", "beta",
723             #pod "release candidate", "unstable", "testing", or "developer release".
724             #pod
725             #pod =for comment ---------------------------------------------------------------------------------------
726             #pod
727             #pod =note Underscores
728             #pod
729             #pod TODO
730             #pod
731             #pod =for comment ---------------------------------------------------------------------------------------
732             #pod
733             #pod =head1 SEE ALSO
734             #pod
735             #pod =begin :list
736             #pod
737             #pod = L
738             #pod
739             #pod Parent class. It provides most of functionality, can work with decimal versions, but does not
740             #pod provide any modifiers. Release status depends on presence of underscore character in version.
741             #pod
742             #pod = L
743             #pod
744             #pod An alternative to C. It works with both decimal and dotted versions, provides modification
745             #pod operations. Release status depends on presence of underscore character in version.
746             #pod
747             #pod = L
748             #pod
749             #pod TODO
750             #pod
751             #pod = L
752             #pod
753             #pod TODO
754             #pod
755             #pod = L
756             #pod
757             #pod Subclass implementing adaptation of Semantic Versioning.
758             #pod
759             #pod = L
760             #pod
761             #pod Subclass implementing odd/even versioning scheme.
762             #pod
763             #pod =end :list
764             #pod
765             #pod =head1 COPYRIGHT AND LICENSE
766             #pod
767             #pod Copyright (C) 2016 Van de Bugger
768             #pod
769             #pod License GPLv3+: The GNU General Public License version 3 or later
770             #pod .
771             #pod
772             #pod This is free software: you are free to change and redistribute it. There is
773             #pod NO WARRANTY, to the extent permitted by law.
774             #pod
775             #pod
776             #pod =cut
777              
778             # ------------------------------------------------------------------------------------------------
779             #
780             # file: doc/what.pod
781             #
782             # This file is part of perl-Version-Dotted.
783             #
784             # ------------------------------------------------------------------------------------------------
785              
786             #pod =encoding UTF-8
787             #pod
788             #pod =head1 WHAT?
789             #pod
790             #pod C and its subclasses complement standard C class with bump operation and
791             #pod (re)define trial versions differently.
792             #pod
793             #pod =cut
794              
795             # end of file #
796             # ------------------------------------------------------------------------------------------------
797             #
798             # file: doc/why.pod
799             #
800             # This file is part of perl-Version-Dotted.
801             #
802             # ------------------------------------------------------------------------------------------------
803              
804             #pod =encoding UTF-8
805             #pod
806             #pod =head1 WHY?
807             #pod
808             #pod C is an official Perl module for declare and compare versions, it is recommended by
809             #pod C and used by Perl itself (C automatically assigns C<$VERSION>
810             #pod variable an object of C class). Unfortunately, the module does not provide any method to
811             #pod bump a version.
812             #pod
813             #pod C is another module recommended by C. This module provides method(s)
814             #pod to bump a version, e. g.:
815             #pod
816             #pod my $v = Perl::Version->new( 'v1.2.3' );
817             #pod $v->inc_alpha;
818             #pod "$v"; # eq 'v1.2.3_01'
819             #pod
820             #pod I used such code with no problem… until C 0.9913. C 0.9913 changed interpretation
821             #pod of underscore character: before C<'v1.2.3_01'> was interpreted as C<'v1.2.3.1'> (+ trial flag,
822             #pod of course), starting from 0.9913 it is interpreted as C<'v1.2.301'> (+ trial flag).
823             #pod
824             #pod I believe there were good reasons for this change (e. g. current C behavior matches Perl
825             #pod behavior and so reduces the mess), but this change breaks C as well as my code
826             #pod because
827             #pod
828             #pod version->parse( 'v1.2.3_01' ) < 'v1.2.4'
829             #pod
830             #pod was true before, is false now.
831             #pod
832             #pod Thus, C is broken and it is not clear when and how it will be fixed. But
833             #pod
834             #pod =over
835             #pod
836             #pod =item 1
837             #pod
838             #pod I want a method to bump a version, and want it now.
839             #pod
840             #pod =item 2
841             #pod
842             #pod I want a method to represent trial versions, and want it is compatible with C either
843             #pod pre-0.9913 or post-0.9912 (i. e. >= 0.77).
844             #pod
845             #pod =item 3
846             #pod
847             #pod I want these methods to work with dotted versions, decimal versions are out of my interest.
848             #pod
849             #pod =back
850             #pod
851             #pod (BTW: Requirement #2 effectively means that new method should not rely on underscores.)
852             #pod
853             #pod C fulfills my requirements.
854             #pod
855             #pod =cut
856              
857             # end of file #
858              
859              
860             # end of file #
861              
862             __END__