The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Version::Dotted - TODO

VERSION

Version v0.0.0_05, released on 2016-12-28 19:36 UTC. This is a trial release.

WHAT?

Version::Dotted and its subclasses complement standard version class with version modification operations, which can be useful in distribution release tools.

This is Version::Dotted module/class documentation. Read it first, but use one of its subclasses.

General topics like getting source, building, installing, bug reporting and some others are covered in the README.

SYNOPSIS

    use Version::Dotted;        # import nothing
    use Version::Dotted 'qv';   # import qv

    # Construct:
    $v = Version::Dotted->new( v1.2.3 );    # same as qv( v1.2.3 )
    $v = qv( v1.2.3 );      # v1.2.3
    $v = qv( '1.2.0' );     # v1.2 (trailing zero parts ignored)
    $v = qv( 'v1' );        # v1

    # Access individual parts:
    $p = $v->part( $i );    # Get i-th part.

    # Stringify:
    $v->stringify;          # "v1.2.3" (always with 'v' prefix)
    "$v";                   # ditto

    # Bump the version:
    $v->bump( $i );         # Bump i-th part
                            # and drop all parts behind i-th.

    # Compare:
    $v > v1.2.3;
    $v == '1.2.3';

DESCRIPTION

version is an official Perl module for comparing versions. For example, (starting from Perl 5.12.0) package with a specified version:

    package Assa v1.2.3;

automatically assigns $VERSION variable to a version object (i. e. an object of version class).

Version::Dotted is not a replacement or alternative for version. Modules should continue to use version implicitly (as shown in the example above) or explicitly:

    package Assa;
    use version 0.77; our $VERSION = version->declare( 'v1.2.3' );

Version::Dotted (or better its more specialized descendants: Version::Dotted::Semantic and Version::Dotted::Odd) is intended for cases where you need to modify version object. For example, in Dist::Zilla AfterRelease plugin:

    sub after_release {
        my ( $self ) = @_;
        my $v = qv( $self->zilla->version );
        $v->bump( 'trial' );    # Version of the next release.
        ...
    };

or in ReleaseStatusProvider plugin:

    sub provide_release_status {
        my ( $self ) = @_;
        my $v = qv( $self->zilla->version );
        return $v->is_trial ? "testing" : "stable";
    };

Version::Dotted is very similar to Perl::Version, but tries to avoid mess and confusing created by supporting both decimal versions (1.003005) and dotted versions (v1.3.5). Version::Dotted does not support decimal versions intentionally to be simpler, cleaner and less confusing.

For the same purpose Version::Dotted does not use underscore (_) to denote trial versions: trial version v0.10.1_01 interpretation depends on version version, it could be either v0.10.1.1 or v0.10.101.

Dotted Version

Dotted (aka dotted-decimal) version is a series of parts joined with dots, each part is a cardinal (non-negative) integer. Every part (except the first) should be in range [0..999], the first part can be bigger than 999.

See also "Dotted-Decimal Versions" in version::Internals.

Parent(s)

Version::Dotted is heavily influenced by Perl::Version, but Version::Dotted is not a subclass of Perl::Version, Version::Dotted is a subclass of version.

The class narrows versionVersion::Dotted creates only dotted (aka dotted-decimal) version objects, support for creating decimal versions is not provided. Support for "alpha" versions is dropped too (subclasses provide support for "trial" versions instead).

The class extends versionVersion::Dotted objects are modifiable.

Warnings

The class reports error by warnings::warnif. It gives the caller flexibility: warning may be either suppressed

    no warnings 'Version::Dotted';

or made fatal:

    use warnings FATAL => 'Version::Dotted';

Release Status

Unfortunately, Perl terminology in this area in not well-defined and not consistently used:

  • The version module names a version containing underscore "alpha version" and refers to CPAN.

  • CPAN::Meta::Spec defines status as one of: stable, testing, and unstable. Word "alpha" is used in the description of unstable release, while testing release is described as "beta". There is also requirement that stable release version should not contain underscore.

  • pause.perl.org site has section named "Developer Releases" which is about releasing "code for testing". Such releases should either have underscore in version or "-TRIAL" suffix.

  • meta::cpan site in the list of module releases shows "DEV" after versions containing underscore.

  • dzil tool has --trial command line option to build a "release that PAUSE will not index".

I think using word "alpha" by version module is a confusing, because version does not provide any support for "beta" and "release candidate". Thus, "alpha" term is dropped in favor of more generic term "trial": trial could be any of "alpha", "beta", "release candidate", "unstable", or "testing".

However, Version::Dotted does not define is_trial method but leaves this for subclasses.

EXPORT

The module exports nothing by default. The module installs qv function (not a method) into caller namespace by explicit request:

    use Version::Dotted 'qv';

If caller module already has qv function, warning is issued and function is redefined.

Note: version exports qv by default, if caller package does not have qv function yet.

The module (unlike to version) does not play any tricks with importer's VERSION and/or UNIVERSAL::VERSION.

CLASS METHODS

new

Constructs a new version object.

    $version = Version::Dotted->new( $arg );

The constructor accepts one argument and creates dotted version object. An argument can be either integer number (1), floating point number (1.2), v-string (v1.2), or string (with or without leading v: '1.2', 'v1.2'), or version object. Trailing zero parts are stripped, leading zeros in parts are insignificant:

    Version::Dotted->new( 1.2.0 ) == Version::Dotted->new( v1.2 )
    Version::Dotted->new( 1.002 ) == Version::Dotted->new( v1.2 )

TODO: Issue a warning if argument is not v-string or string?

Actually, Version::Dotted has a notion of "minimum number of parts": version object is maintained to have at least minimum number of parts. In Version::Dotted minimum number of parts is 1, but subclasses may raise the bar.

parse

This method issues warning "Operation 'parse' is not supported" and always returns undef.

(The parent's method creates decimal version object. However, this class is intended to create only dotted-decimal version objects.)

OBJECT METHODS

part

Returns i-th part of the version.

    $int = $v->part( $i );  # Get i-th part.

If index is larger than actual number of version parts minus one, undef is returned.

Negative part index causes warning but works like index to regular Perl array: -1 is index of the last version part, -2 — second last, etc.

bump

Bumps i-th version part and drops all the parts behind i-th.

    $v->bump( $i );

If index is larger than actual number of version parts (minus one), missed parts are autovivified with zero values. If result of bumping is bigger than allowed upper boundary for the part (999 for all the parts except the first), warning is printed.

Negative part index causes warning but works.

The method returns reference to version object.

    $v = qv( v1.2.3 );  # v1.2.3
    $v->bump( 3 );      # v1.2.3.1
    $v->bump( 2 );      # v1.2.4
    $v->bump( 1 );      # v1.3
    $v->bump( 0 );      # v2

is_alpha

The method prints a warning and always returns undef.

numify

The method prints a warning and always returns undef.

stringify

    $str = $v->stringify;

The method is inherited from the parent class.

Since the Version::Dotted class constructs only dotted version objects, result of stringification is always a dotted version string with leading 'v', e. g.:

    Version::Dotted->new( 1.2 )->stringify eq 'v1.2';

FUNCTIONS

qv

Shortcut for Version::Dotted->new.

    $v = Version::Dotted->new( $arg );
    $v = qv( $arv );    # ditto

Note: There is no function Version::Dotted::qv, qv function is installed into importer package by explicit request, see "EXPORT".

OPERATORS

<=>

Compares two versions.

    $v <=> $other;

The operator is inherited from parent's class (see "How to compare version objects" in version). However, there is a difference: if $other is not a version object, it converted to a version object using new (not parse).

Other comparison operators (e. g. <, >, <=, etc) are created by Perl.

cmp

The same as <=>.

""

The same as stringify.

    $v->stringify eq "$v";

CAVEATS

Leading Zeros

Leading zeros in parts are insignificant:

    Version::Dotted->new( v01.02.03 ) == Version::Dotted->new( v1.2.3 );
    Version::Dotted->new( 1.002 ) == Version::Dotted->new( v1.2 );

However, Perl interprets numbers with leading zero as octal, so aware of:

    Version::Dotted->new( 010 ) == v8;
    Version::Dotted->new( 010.011 ) == v89;         # oops
    Version::Dotted->new( 010.011.012 ) == v8910;   # ooops

To avoid surprises stick to using v-strings or strings:

    Version::Dotted->new( v010 ) == Version::Dotted->new( v10 );
    Version::Dotted->new( v010.011 ) == Version::Dotted->new( v10.10 );
    Version::Dotted->new( '010.011' ) == Version::Dotted->new( v10.10 );

WHY?

I always used version (a module recommended by Task::Kensho) to compare versions:

    if ( version->parse( $Module::VERSION ) < '0.10.1' ) {
        plan skip_all => "Module $Module::VERSION too old";
    };

When I had a need to manipulate versions, I started to use Perl::Version (another module recommended by Task::Kensho) because version does not provide any method to modify version object. I wanted to bump version of a distribution automatically after release, and Perl::Version did the job for me:

    my $v = Perl::Version->new( $self->zilla->version );
    $v->inc_alpha();

(The idea is: If I just released v0.10.1, the version of the next release would be automatically set to v0.10.1_01. If I released v0.10.1_01, the next version would be v0.10.1_02, and so on. If I decided it is time to release non-trial version, I would manually set version to v0.10.2 or whatever else, e. g. v0.11.0 or v1.0.0.)

Everything was ok. However, I accidentally found that

    version->parse( 'v0.10.1_01' ) > 'v0.10.2'  # is true

Oops. That's was quite surprising, because some time ago this expression had opposite result:

    version->parse( 'v0.10.1_01' ) < 'v0.10.2'  # was true

Little investigation shown the breaking change is in version 0.9913: earlier versions interpret underscore as version part delimiter ('v0.10.1_01' is the same as 'v0.10.1.1'+trial), but 0.9913 and later versions do not ('v0.10.1_01' is the same as 'v.10.101'+trial).

Ignoring underscore is probably a right thing to do, because it is the way how Perl itself interprets v-strings:

    v0.10.1_01 eq v0.10.101     # is true

but it is definitely a change which makes Perl::Version useless (to me).

SEE ALSO

version

Parent class. It provides most of functionality, can work with decimal versions, but does not provide any modifiers. Release status depends on presence of underscore character in version.

Perl::Version

An alternative to version. It works with both decimal and dotted versions, provides modification operations. Release status depends on presence of underscore character in version.

SemVer

TODO

Version::Dotted::Semantic

Subclass implementing Perlish approach to Semantic Versioning.

Version::Dotted::Odd

Subclass implementing odd/even versioning scheme.

AUTHOR

Van de Bugger <van.de.bugger@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2016 Van de Bugger

License GPLv3+: The GNU General Public License version 3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>.

This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.