SemVer-v0.6.0000755000767000024 012460353412 12461 5ustar00davidstaff000000000000SemVer-v0.6.0/Build.PL000444000767000024 146112460353412 14114 0ustar00davidstaff000000000000use strict; use warnings; use Module::Build; Module::Build->new( module_name => 'SemVer', license => 'perl', configure_requires => { 'Module::Build' => '0.30', }, build_requires => { 'Module::Build' => '0.30', 'Test::More' => '0.88', }, requires => { 'version' => 0.82, 'perl' => 5.008001, }, recommends => { 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.06', }, meta_merge => { resources => { homepage => 'http://search.cpan.org/dist/SemVer/', bugtracker => 'http://github.com/theory/semver/issues/', repository => 'http://github.com/theory/semver', } }, )->create_build_script; SemVer-v0.6.0/Changes000444000767000024 315712460353412 14117 0ustar00davidstaff000000000000Revision history for Perl extension SemVer. 0.6.0 2015-01-23T05:07:58Z - Removed tests that fail on version.pm 0.9910 and higher due to trailing decimal sign. Thanks to Andreas Koenig for the report and diagnosis. - Fixed vstring warning on Perl 5.8. - Now skip tests that fail with version::vpp. - Now skip test on version.pm 0.9911 that fails with that version. - Now skip failing tests on Perl 5.8 and version.pm less than 0.9909. - Removed all Pod tests from the distribution. 0.5.0 2013-04-02T06:57:06Z - The `new()` now throws an exception when a version string has a prerelease version with no preceding dash. This is keep its requirement for strictness consistent. - Fixed a bug where a SemVer object passed to `new()` did not properly clone the dash preceding a prerelease version. 0.4.0 2012-11-20T18:59:33Z - Updated the parsers to support an optional dash before the prerelease version, and `normal()` to always emit a dash for the prerelease version. This brings it in line with the final semver 1.0.0 specification. 0.3.0 2011-05-26T04:54:50 - Made leading zeros, such as the "04" in "1.04.3" illegal when parsing via `new()`. - Eliminted "Use of qw(...) as parentheses is deprecated" in the tests when running on Perl 5.14. 0.2.0 2010-09-17T17:59:57 - Require Test::Pod 1.41 for testing POD because it supports `L`. 0.1.0 2010-09-16T19:07:04 - Initial version, created with lots of help and feedback from version.pm author John Peacock SemVer-v0.6.0/MANIFEST000444000767000024 14312460353412 13725 0ustar00davidstaff000000000000Build.PL Changes lib/SemVer.pm MANIFEST This list of files META.json META.yml README.md t/base.t SemVer-v0.6.0/META.json000444000767000024 253212460353412 14241 0ustar00davidstaff000000000000{ "abstract" : "Use semantic version numbers", "author" : [ "David E. Wheeler " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.421", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "SemVer", "prereqs" : { "build" : { "requires" : { "Module::Build" : "0.30", "Test::More" : "0.88" } }, "configure" : { "requires" : { "Module::Build" : "0.30" } }, "runtime" : { "recommends" : { "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.06" }, "requires" : { "perl" : "5.008001", "version" : "0.82" } } }, "provides" : { "SemVer" : { "file" : "lib/SemVer.pm", "version" : "v0.6.0" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "http://github.com/theory/semver/issues/" }, "homepage" : "http://search.cpan.org/dist/SemVer/", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "http://github.com/theory/semver" } }, "version" : "v0.6.0" } SemVer-v0.6.0/META.yml000444000767000024 145512460353412 14074 0ustar00davidstaff000000000000--- abstract: 'Use semantic version numbers' author: - 'David E. Wheeler ' build_requires: Module::Build: '0.30' Test::More: '0.88' configure_requires: Module::Build: '0.30' dynamic_config: 1 generated_by: 'Module::Build version 0.421, CPAN::Meta::Converter version 2.143240' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: SemVer provides: SemVer: file: lib/SemVer.pm version: v0.6.0 recommends: Test::Pod: '1.41' Test::Pod::Coverage: '1.06' requires: perl: '5.008001' version: '0.82' resources: bugtracker: http://github.com/theory/semver/issues/ homepage: http://search.cpan.org/dist/SemVer/ license: http://dev.perl.org/licenses/ repository: http://github.com/theory/semver version: v0.6.0 SemVer-v0.6.0/README.md000444000767000024 300012460353412 14066 0ustar00davidstaff000000000000SemVer version 0.6.0 ==================== This module subclasses [`version`] to create semantic versions, as defined by the [Semantic Versioning 1.0.0 Specification] The two salient points of the specification, for the purposes of version formatting, are: 1. A normal version number MUST take the form X.Y.Z where X, Y, and Z are integers. X is the major version, Y is the minor version, and Z is the patch version. Each element MUST increase numerically by increments of one. For instance: `1.9.0 < 1.10.0 < 1.11.0`. 2. A pre-release version number MAY be denoted by appending an arbitrary string immediately following the patch version and a dash. The string MUST be comprised of only alphanumerics plus dash C<[0-9A-Za-z-]>. Pre-release versions satisfy but have a lower precedence than the associated normal version. Precedence SHOULD be determined by lexicographic ASCII sort order. For instance: `1.0.0-alpha1 < 1.0.0-beta1 < 1.0.0-beta2 < 1.0.0-rc1 < 1.0.0`. [`version`]: http://search.cpan.org/perldoc?version [Semantic Versioning 1.0.0 Specification]: http://semver.org/spec/v1.0.0.html Installation ============ To install this module, type the following: perl Build.PL ./Build ./Build test ./Build install Dependencies ------------ SemVer requires version. Copyright and License --------------------- Copyright (c) 2010-2015 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. SemVer-v0.6.0/lib000755000767000024 012460353412 13227 5ustar00davidstaff000000000000SemVer-v0.6.0/lib/SemVer.pm000444000767000024 2531112460353412 15145 0ustar00davidstaff000000000000package SemVer; use 5.008001; use strict; use version 0.82; use Scalar::Util (); use overload ( '""' => 'stringify', '<=>' => 'vcmp', 'cmp' => 'vcmp', ); our @ISA = qw(version); our $VERSION = '0.6.0'; # For Module::Build sub _die { require Carp; Carp::croak(@_) } # Prevent version.pm from mucking with our internals. sub import {} # Adapted from version.pm. my $STRICT_INTEGER_PART = qr/0|[1-9][0-9]*/; my $STRICT_DOTTED_INTEGER_PART = qr/\.$STRICT_INTEGER_PART/; my $STRICT_DOTTED_INTEGER_VERSION = qr/ $STRICT_INTEGER_PART $STRICT_DOTTED_INTEGER_PART{2,} /x; my $OPTIONAL_EXTRA_PART = qr/[a-zA-Z][-0-9A-Za-z]*/; sub new { my ($class, $ival) = @_; # Handle vstring. return $class->SUPER::new($ival) if Scalar::Util::isvstring($ival); # Let version handle cloning. if (eval { $ival->isa('version') }) { my $self = $class->SUPER::new($ival); $self->{extra} = $ival->{extra}; $self->{dash} = $ival->{dash}; return $self; } my ($val, $dash, $extra) = ( $ival =~ /^v?($STRICT_DOTTED_INTEGER_VERSION)(?:(-)($OPTIONAL_EXTRA_PART))?$/ ); _die qq{Invalid semantic version string format: "$ival"} unless defined $val; my $self = $class->SUPER::new($val); $self->{dash} = $dash; $self->{extra} = $extra; return $self; } $VERSION = __PACKAGE__->new($VERSION); # For ourselves. sub declare { my ($class, $ival) = @_; return $class->new($ival) if Scalar::Util::isvstring($ival) or eval { $ival->isa('version') }; (my $v = $ival) =~ s/(?:(-?)($OPTIONAL_EXTRA_PART))[[:space:]]*$//; my $dash = $1; my $extra = $2; $v += 0 if $v =~ s/_//g; # ignore underscores. my $self = $class->SUPER::declare($v); $self->{dash} = $dash; $self->{extra} = $extra; return $self; } sub parse { my ($class, $ival) = @_; return $class->new($ival) if Scalar::Util::isvstring($ival) or eval { $ival->isa('version') }; (my $v = $ival) =~ s/(?:(-?)($OPTIONAL_EXTRA_PART))[[:space:]]*$//; my $dash = $1; my $extra = $2; $v += 0 if $v =~ s/_//g; # ignore underscores. my $self = $class->SUPER::parse($v); $self->{dash} = $dash; $self->{extra} = $extra; return $self; } sub stringify { my $self = shift; my $str = $self->SUPER::stringify; # This is purely for SemVers constructed from version objects. $str += 0 if $str =~ s/_//g; # ignore underscores. return $str . ($self->{dash} || '') . ($self->{extra} || ''); } sub normal { my $self = shift; (my $norm = $self->SUPER::normal) =~ s/^v//; $norm =~ s/_/./g; return $norm . ($self->{extra} ? "-$self->{extra}" : ''); } sub numify { _die 'Semantic versions cannot be numified'; } sub is_alpha { !!shift->{extra} } sub vcmp { my $left = shift; my $right = ref($left)->declare(shift); # Reverse? ($left, $right) = shift() ? ($right, $left): ($left, $right); # Major and minor win. if (my $ret = $left->SUPER::vcmp($right, 0)) { return $ret; } else { # They're equal. Check the extra text stuff. if (my $l = $left->{extra}) { my $r = $right->{extra} or return -1; return lc $l cmp lc $r; } else { return $right->{extra} ? 1 : 0; } } } 1; __END__ =head1 Name SemVer - Use semantic version numbers =head1 Synopsis use SemVer; our $VERSION = SemVer->new('1.2.0b1'); =head1 Description This module subclasses L to create semantic versions, as defined by the L. The two salient points of the specification, for the purposes of version formatting, are: =over =item 1. A normal version number MUST take the form X.Y.Z where X, Y, and Z are integers. X is the major version, Y is the minor version, and Z is the patch version. Each element MUST increase numerically by increments of one. For instance: C<< 1.9.0 < 1.10.0 < 1.11.0 >>. =item 2. A pre-release version number MAY be denoted by appending an arbitrary string immediately following the patch version and a dash. The string MUST be comprised of only alphanumerics plus dash C<[0-9A-Za-z-]>. Pre-release versions satisfy but have a lower precedence than the associated normal version. Precedence SHOULD be determined by lexicographic ASCII sort order. For instance: C<< 1.0.0-alpha1 < 1.0.0-beta1 < 1.0.0-beta2 < 1.0.0-rc1 < 1.0.0 >>. =back =head2 Usage For strict parsing of semantic version numbers, use the C constructor. If you need something more flexible, use C. And if you need something more comparable with what L expects, try C. Compare how these constructors deal with various version strings (with values shown as returned by C: Argument | new | declare | parse -------------+----------+--------------------------- '1.0.0' | 1.0.0 | 1.0.0 | 1.0.0 '5.5.2-b1' | 5.5.2-b1 | 5.5.2-b1 | 5.5.2-b1 '1.05.0' | | 1.5.0 | 1.5.0 '1.0' | | 1.0.0 | 1.0.0 ' 012.2.2' | | 12.2.2 | 12.2.2 '1.1' | | 1.1.0 | 1.100.0 1.1 | | 1.1.0 | 1.100.0 '1.1.0b1' | | 1.1.0-b1 | 1.1.0-b1 '1.1-b1' | | 1.1.0-b1 | 1.100.0-b1 '1.2.b1' | | 1.2.0-b1 | 1.2.0-b1 '9.0-beta4' | | 9.0.0-beta4 | 9.0.0-beta4 '9' | | 9.0.0 | 9.0.0 '1-b' | | 1.0.0-b | 1.0.0-b 0 | | 0.0.0 | 0.0.0 '0-rc1' | | 0.0.0-rc1 | 0.0.0-rc1 '1.02_30' | | 1.23.0 | 1.23.0 1.02_30 | | 1.23.0 | 1.23.0 Note that, unlike in L, the C and C methods ignore underscores. That is, version strings with underscores are treated as decimal numbers. Hence, the last two examples yield exactly the same semantic versions. As with L objects, the comparison and stringification operators are all overloaded, so that you can compare semantic versions. You can also compare semantic versions with version objects (but not the other way around, alas). Boolean operators are also overloaded, such that all semantic version objects except for those consisting only of zeros are considered true. =head1 Interface =head2 Constructors =head3 C my $semver = SemVer->new('1.2.2'); Performs a validating parse of the version string and returns a new semantic version object. If the version string does not adhere to the semantic version specification an exception will be thrown. See C and C for more forgiving constructors. =head3 C my $semver = SemVer->declare('1.2'); # 1.2.0 This parser strips out any underscores from the version string and passes it to to C's C constructor, which always creates dotted-integer version objects. This is the most flexible way to declare versions. Consider using it to normalize version strings. =head3 C my $semver = SemVer->parse('1.2'); # 1.200.0 This parser dispatches to C's C constructor, which tries to be more flexible in how it converts simple decimal strings and numbers. Not really recommended, since it's treatment of decimals is quite different from the dotted-integer format of semantic version strings, and thus can lead to inconsistencies. Included only for proper compatibility with L. =head2 Instance Methods =head3 C SemVer->declare('v1.2')->normal; # 1.2.0 SemVer->parse('1.2')->normal; # 1.200.0 SemVer->declare('1.02.0-b1')->normal; # 1.2.0-b1 SemVer->parse('1.02_30')->normal # 1.230.0 SemVer->parse(1.02_30)->normal # 1.23.0 Returns a normalized representation of the version. This string will always be a strictly-valid dotted-integer semantic version string suitable for passing to C. Unlike L's C method, there will be no leading "v". =head3 C SemVer->declare('v1.2')->stringify; # v1.2 SemVer->parse('1.200')->stringify; # v1.200 SemVer->declare('1.2-r1')->stringify; # v1.2-r1 SemVer->parse(1.02_30)->stringify; # v1.0230 SemVer->parse(1.02_30)->stringify; # v1.023 Returns a string that is as close to the original representation as possible. If the original representation was a numeric literal, it will be returned the way perl would normally represent it in a string. This method is used whenever a version object is interpolated into a string. =head3 C Throws an exception. Semantic versions cannot be numified. Just don't go there. =head3 C my $is_alpha = $semver->is_alpha; Returns true if an ASCII string is appended to the end of the version string. This also means that the version number is a "special version", in the semantic versioning specification meaning of the phrase. =head3 C Compares the semantic version object to another version object or string and returns 0 if they're the same, -1 if the invocant is smaller than the argument, and 1 if the invocant is greater than the argument. Mostly you don't need to worry about this: Just use the comparison operators instead. They will use this method: if ($semver < $another_semver) { die "Need $another_semver or higher"; } Note that in addition to comparing other semantic version objects, you can also compare regular L objects: if ($semver < $version) { die "Need $version or higher"; } You can also pass in a version string. It will be turned into a semantic version object using C. So if you're using integer versions, you may or may not get what you want: my $semver = version::Semver->new('1.2.0'); my $version = '1.2'; my $bool = $semver == $version; # true If that's not what you want, pass the string to C first: my $semver = version::Semver->new('1.2.0'); my $version = version::Semver->parse('1.2'); # 1.200.0 my $bool = $semver == $version; # false =head1 See Also =over =item * L. =item * L =item * L =back =head1 Support This module is managed in an open L. Feel free to fork and contribute, or to clone L and send patches! Found a bug? Please L or L a report! =head1 Acknowledgements Many thanks to L author John Peacock for his suggestions and debugging help. =head1 Authors David E. Wheeler =head1 Copyright and License Copyright (c) 2010-2015 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SemVer-v0.6.0/t000755000767000024 012460353412 12724 5ustar00davidstaff000000000000SemVer-v0.6.0/t/base.t000444000767000024 2133512460353412 14204 0ustar00davidstaff000000000000#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 568; #use Test::More 'no_plan'; my $CLASS; BEGIN { $CLASS = 'SemVer'; use_ok $CLASS or die; } diag 'Testing with version v', version->VERSION; can_ok $CLASS, qw( new declare parse normal numify is_alpha is_qv vcmp ); # Try the basics. isa_ok my $version = $CLASS->new('0.1.0'), $CLASS, 'An instance'; isa_ok $SemVer::VERSION, $CLASS, q{SemVer's own $VERSION}; my $is_vpp = !!grep { $_ eq 'version::vpp' } @version::ISA; for my $v (qw( 1.2.2 0.2.2 1.2.2 0.0.0 0.1.999 9999.9999999.823823 1.0.0-beta1 1.0.0-beta2 1.0.0 0.0.0-rc1 v1.2.2 999993333.0.0 )) { isa_ok my $semver =$CLASS->new($v), $CLASS, "new($v)"; my $str = $v =~ /^v/ ? substr $v, 1 : $v; is "$semver", $str, qq{$v should stringify to "$str"}; $str =~ s/(\d)([a-z].+)$/$1-$2/; is $semver->normal, $str, qq{$v should normalize to "$str"}; SKIP: { skip 'Boolean comparison broken with version::vpp', 1, $is_vpp; if ($v =~ /0\.0\.0/) { ok !$semver, "$v should be false"; } else { ok !!$semver, "$v should be true"; } } ok $semver->is_qv, "$v should be dotted-decimal"; my $is_alpha = $semver->is_alpha; if ($v =~ /[.]\d+-?[a-z]/) { ok $is_alpha, "$v should be alpha"; } else { ok !$is_alpha, "$v should not be alpha"; } } local $@; eval { $CLASS->new('') }; ok $@, 'Empty string should be an invalid version'; for my $bv (qw( 1.2 0 0.0 1.2b 1.b 1.04.0 1.65.r2 )) { local $@; eval { $CLASS->new($bv) }; like $@, qr{Invalid semantic version string format: "$bv"}, qq{"$bv" should be an invalid semver}; } # Try a vstring. isa_ok $version = $CLASS->new(v2.3.2), $CLASS, 'vstring version'; is $version->stringify, 'v2.3.2', 'vestring should stringify with "v"'; is $version->normal, '2.3.2', 'vstring should normalize without "v"'; # Try a shorter vstring. my $no_2digitvst = $] < 5.10 && version->VERSION < 0.9910; SKIP: { skip 'Two-integer vstrings weak on Perl 5.8', 3 if $no_2digitvst; isa_ok $version = $CLASS->new(v2.3), $CLASS, 'vstring version'; is $version->stringify, 'v2.3', 'short vestring should stringify with "v"'; is $version->normal, '2.3.0', 'short vstring should normalize without required 0'; } # Try another SemVer. isa_ok my $cloned = $CLASS->new($version), $CLASS, 'Cloned SemVer'; is $cloned->stringify, $version->stringify, 'Cloned stringify like original'; is $cloned->normal, $version->normal, 'Cloned should normalize like original'; # Try a SemVer with alpha. isa_ok $version = $CLASS->new('2.3.2-b1'), $CLASS, 'new version'; isa_ok $cloned = $CLASS->new($version), $CLASS, 'Second cloned SemVer'; is $cloned->stringify, $version->stringify, 'Second cloned stringify like original'; is $cloned->normal, $version->normal, 'Second cloned should normalize like original'; # Numify should die local $@; eval { $version->numify }; like $@, qr{Semantic versions cannot be numified}, 'Should get error from numify()'; # Now do some comparisons. Start with equivalents. for my $spec ( [ '1.2.2', '1.2.2' ], [ '1.2.23', '1.2.23' ], [ '0.0.0', '0.0.0' ], [ '999.888.7777', '999.888.7777' ], [ '0.1.2-beta3', '0.1.2-beta3' ], [ '1.0.0-rc-1', '1.0.0-RC-1' ], ) { my $l = $CLASS->new($spec->[0]); my $r = $CLASS->new($spec->[1]); is $l->vcmp($r), 0, "$l->vcmp($r) == 0"; is $l <=> $r, 0, "$l <=> $r == 0"; is $r <=> $l, 0, "$r <=> $l == 0"; cmp_ok $l, '==', $r, "$l == $r"; cmp_ok $l, '==', $r, "$l == $r"; cmp_ok $l, '<=', $r, "$l <= $r"; cmp_ok $l, '>=', $r, "$l >= $r"; is $l cmp $r, 0, "$l cmp $r == 0"; is $r cmp $l, 0, "$r cmp $l == 0"; cmp_ok $l, 'eq', $r, "$l eq $r"; cmp_ok $l, 'eq', $r, "$l eq $r"; cmp_ok $l, 'le', $r, "$l le $r"; cmp_ok $l, 'ge', $r, "$l ge $r"; } # Test not equal. for my $spec ( ['1.2.2', '1.2.3'], ['0.0.1', '1.0.0'], ['1.0.1', '1.1.0'], ['1.1.1', '1.1.0'], ['1.2.3-b', '1.2.3'], ['1.2.3', '1.2.3-b'], ['1.2.3-a', '1.2.3-b'], ['1.2.3-aaaaaaa1', '1.2.3-aaaaaaa2'], ) { my $l = $CLASS->new($spec->[0]); my $r = $CLASS->new($spec->[1]); cmp_ok $l->vcmp($r), '!=', 0, "$l->vcmp($r) != 0"; cmp_ok $l, '!=', $r, "$l != $r"; cmp_ok $l, 'ne', $r, "$l ne $r"; } # Test >, >=, <, and <=. for my $spec ( ['2.2.2', '1.1.1'], ['2.2.2', '2.1.1'], ['2.2.2', '2.2.1'], ['2.2.2-b', '2.2.1'], ['2.2.2', '2.2.2-b'], ['2.2.2-c', '2.2.2-b'], ['2.2.2-rc-2', '2.2.2-RC-1'], ['0.9.10', '0.9.9'], ) { my $l = $CLASS->new($spec->[0]); my $r = $CLASS->new($spec->[1]); cmp_ok $l->vcmp($r), '>', 0, "$l->vcmp($r) > 0"; cmp_ok $r->vcmp($l), '<', 0, "$r->vcmp($l) < 0"; cmp_ok $l, '>', $r, "$l > $r"; cmp_ok $l, '>=', $r, "$l >= $r"; cmp_ok $r, '<', $l, "$r < $l"; cmp_ok $r, '<=', $l, "$r <= $l"; cmp_ok $l, 'gt', $r, "$l gt $r"; cmp_ok $l, 'ge', $r, "$l ge $r"; cmp_ok $r, 'lt', $l, "$r lt $l"; cmp_ok $r, 'le', $l, "$r le $l"; } # Compare to version objects. my $semver = $CLASS->new('1.2.0'); for my $v (qw( 1.002 1.2.0 v1.002 v1.2.0 )) { my $version = version->new($v); ok $semver == $version, "$semver == $version"; } # Compare to strings. for my $v (qw( 1.2.0 v1.2.0 )) { my $semver = $CLASS->new($v); cmp_ok $semver, '==', $v, qq{$semver == "$v"}; cmp_ok $v, '==', $semver, qq{"$v" == $semver}; cmp_ok $semver, 'eq', $v, qq{$semver eq "$v"}; cmp_ok $v, 'eq', $semver, qq{"$v" eq $semver}; } # Test declare() and parse. for my $spec ( ['1.2.2', '1.2.2'], ['01.2.2', '1.2.2'], ['1.02.2', '1.2.2'], ['1.2.02', '1.2.2'], ['1.2.02b', '1.2.2-b'], ['1.2.02beta-3 ', '1.2.2-beta-3'], ['1.02.02rc1', '1.2.2-rc1'], ['1.0', '1.0.0'], ['1.1', '1.1.0', '1.100.0'], [ 1.1, '1.1.0', '1.100.0'], ['1.1b1', '1.1.0-b1', '1.100.0-b1'], ['1b', '1.0.0-b'], ['9.0beta4', '9.0.0-beta4'], [' 012.2.2', '12.2.2'], ['99999998', '99999998.0.0'], ['1.02_30', '1.23.0'], [1.02_30, '1.23.0'], [3.4, '3.4.0', '3.400.0'], [3.04, '3.4.0', '3.40.0' ], ['3.04', '3.4.0', '3.40.0' ], [v3.4, '3.4.0' ], [9, '9.0.0' ], ['9', '9.0.0' ], ['0', '0.0.0' ], [0, '0.0.0' ], ['0rc1', '0.0.0-rc1' ], ) { SKIP: { skip 'Two-integer vstrings weak on Perl 5.8', 12 if $no_2digitvst && Scalar::Util::isvstring($spec->[0]); my $r = $CLASS->new($spec->[1]); isa_ok my $l = SemVer->declare($spec->[0]), $CLASS, "Declared $spec->[0]"; my $string = Scalar::Util::isvstring($spec->[0]) ? join '.', map { ord } split // => $spec->[0] : $spec->[0]; $string =~ s/^\s+//; $string =~ s/\s+$//; $string += 0 if $string =~ s/_//g; my $vstring = $string =~ /^\d+[.][^.]+$/ ? "v$string" : $string; SKIP: { skip 'Stringification broken with version::vpp', 1, $is_vpp; is $l->stringify, $vstring, qq{... And it should stringify to "$vstring"}; } is $l->normal, $spec->[1], qq{... And it should normalize to "$spec->[1]"}; # Compare the non-semantic version string to the semantic one. cmp_ok $spec->[0], '==', $r, qq{$r == "$spec->[0]"}; if ($spec->[0] && $spec->[0] !~ /^[a-z]/ && $spec->[0] !~ /[.]{2}/) { my $exp = $spec->[2] || $spec->[1]; isa_ok $l = SemVer->parse($spec->[0]), $CLASS, "Parsed $spec->[0]"; $string = "v$string" if Scalar::Util::isvstring($spec->[0]); $string =~ s/_//; is $l->stringify, $string, "... And it should stringify to $string"; is $l->normal, $exp, "... And it should normalize to $exp"; # Try with the parsed version. $r = $CLASS->new($spec->[2]) if $spec->[2]; cmp_ok $l, '==', $r, qq{$l == $r} unless $string =~ /_/; } # Try creating as a version object and cloning. if ($spec->[0] !~ /[a-z]/i) { isa_ok my $v = version->parse($spec->[0]), 'version', "base version $spec->[0]"; isa_ok my $sv = SemVer->new($v), 'SemVer', "SemVer from base version $spec->[0]"; is $sv->stringify, $string, qq{... And it should stringify to "$vstring"}; SKIP: { skip 'version 0.9911 broke alpha->normal()', 1, if $spec->[0] =~ /_/ && version->VERSION == 0.9911; is $sv->normal, $l->normal, '... And it should normalize to "' . $l->normal . '"'; } } }}