view release on metacpan or search on metacpan
lib/Changes/Version.pm view on Meta::CPAN
use strict;
use warnings;
sub init
{
my $self = shift( @_ );
$self->{alpha} = undef;
# Used for other version types
$self->{beta} = undef;
$self->{compat} = 0;
# What version fragment to increase/decrease by default, such as when we do operations like $v++ or $v--
$self->{default_frag} = 'minor';
$self->{extra} = [];
$self->{major} = undef;
$self->{minor} = undef;
$self->{original} = undef;
$self->{padded} = 1;
$self->{patch} = undef;
$self->{pattern} = undef;
$self->{pretty} = 0;
$self->{qv} = 0;
# Release candidate used by non-perl open source softwares
$self->{rc} = undef;
$self->{target} = 'perl';
$self->{type} = undef;
my $keys = [qw( alpha beta compat default_frag extra major minor original patch qv rc target type _version )];
my $vstr;
# Changes::Version->new( 'v0.1.2_3' ); or
# Changes::Version->new( 'v0.1.2_3', alpha => 4 ); or
# Changes::Version->new( 'v0.1.2_3', { alpha => 4 } ); or
# Changes::Version->new( major => 0, minor => 1, patch => 2, alpha => 3, qv => 1 ); or
# Changes::Version->new({ major => 0, minor => 1, patch => 2, alpha => 3, qv => 1 }); or
if( ( @_ == 1 && ref( $_[0] ) ne 'HASH' ) ||
( @_ > 1 && ref( $_[0] ) ne 'HASH' && ( ( @_ % 2 ) || ref( $_[1] ) eq 'HASH' ) ) )
{
$vstr = shift( @_ );
lib/Changes/Version.pm view on Meta::CPAN
# For non-perl open source softwares
sub dec_beta { return( shift->_inc_dec( 'dec' => 'beta', @_ ) ); }
sub dec_major { return( shift->_inc_dec( 'dec' => 'major', @_ ) ); }
sub dec_minor { return( shift->_inc_dec( 'dec' => 'minor', @_ ) ); }
sub dec_patch { return( shift->_inc_dec( 'dec' => 'patch', @_ ) ); }
sub default_frag { return( shift->_set_get_scalar_as_object( 'default_frag', @_ ) ); }
sub extra { return( shift->_set_get_array_as_object( 'extra', @_ ) ); }
sub format
{
my $self = shift( @_ );
my $fmt = shift( @_ ) ||
return( $self->error( "No pattern was provided to format this version." ) );
# NOTE: numify()
my $numify = sub
lib/Changes/Version.pm view on Meta::CPAN
sub parse
{
my $self = shift( @_ );
my $str = shift( @_ );
return( $self->error( "No version string was provided." ) ) if( !defined( $str ) || !length( "$str" ) );
if( $] >= 5.008_001 && ref( \$str ) eq 'VSTRING' )
{
my $def = { original => $str };
$def->{type} = 'dotted';
$def->{qv} = 1;
my @frags = map{ ord( $_ ) } split( //, $str );
@$def{qw( major minor patch )} = splice( @frags, 0, 3 );
$def->{extra} = \@frags;
$def->{pattern} = '%R%d';
my $new = $self->new( %$def );
$new->{_version} = version->parse( $str );
return( $new );
}
if( $str =~ /^$VERSION_LAX_REGEX$/ )
{
my $re = { %+ };
my $def = { original => $str };
lib/Changes/Version.pm view on Meta::CPAN
my $vstr = $v->normal;
if( $vstr =~ /^$VERSION_LAX_REGEX$/ )
{
my $re2 = { %+ };
if( defined( $re2->{dotted} ) && length( $re2->{dotted} ) )
{
if( defined( $re2->{minor_patch} ) )
{
# delete( $def->{alpha} );
$def->{major} = $re2->{major};
my @frags = split( /\./, $re2->{minor_patch} );
shift( @frags );
$def->{minor} = shift( @frags );
$def->{patch} = shift( @frags );
$def->{extra} = \@frags;
}
}
}
}
else
{
$v = version->parse( $re->{dotted} );
# Same as %M%P%E -> 5.3.4.5.6.7.8
push( @$fmt, '%d' );
push( @$fmt, '%a' ) if( defined( $def->{alpha} ) && length( $def->{alpha} ) );
if( defined( $re->{minor_patch} ) )
{
my @frags = split( /\./, $re->{minor_patch} );
# throw away the empty data because of the leading dot
shift( @frags );
$def->{minor} = shift( @frags );
$def->{patch} = shift( @frags );
$def->{extra} = \@frags;
}
}
$def->{pattern} = join( '', @$fmt );
}
elsif( $def->{type} eq 'decimal' )
{
# $def->{minor} = $re->{minor} if( defined( $re->{minor} ) );
# $re->{release} is the decimal version without the alpha information if it is smaller than 3
# This issue stems from decimal number having an underscore can either mean they have a version like
# 5.006_002 which would be equivalent v5.6.2 and in this case, "_002" is not an alpha information; and
lib/Changes/Version.pm view on Meta::CPAN
# my $vstr = $v->normal;
# if( $vstr =~ /^$VERSION_LAX_REGEX$/ )
# {
# my $re2 = { %+ };
# if( defined( $re2->{dotted} ) && length( $re2->{dotted} ) )
# {
# if( defined( $re2->{minor_patch} ) )
# {
# # delete( $def->{alpha} );
# $def->{major} = $re2->{major};
# my @frags = split( /\./, $re2->{minor_patch} );
# shift( @frags );
# $def->{minor} = shift( @frags );
# $def->{patch} = shift( @frags );
# $def->{extra} = \@frags;
# }
# }
# }
# }
}
my $new = $self->new( %$def );
$new->{_version} = $v if( defined( $v ) );
return( $self->pass_error ) if( !defined( $new ) );
CORE::delete( $new->{_reset} );
return( $new );
lib/Changes/Version.pm view on Meta::CPAN
sub _bool
{
my $self = shift( @_ );
# return( $self->_compare( $self->_version, version->new("0"), 1 ) );
return( $self->_compare( $self, "0", 1 ) );
}
sub _bubble
{
my $self = shift( @_ );
my $frag = shift( @_ );
my $val = shift( @_ );
# We die, because this is an internal method and those cases should not happen unless this were a design bug
if( !defined( $frag ) || !length( $frag ) )
{
die( "No fragment was provided to cascade" );
}
elsif( $frag !~ /^(major|minor|patch|alpha|\d+)$/ )
{
die( "Unsupported version fragment '$frag'. Only use 'major', 'minor', 'patch' or 'alpha' or a number starting from 1 (1 = major, 2 = minor, etc)." );
}
# Not for us. We bubble only when a value is negative resulting from a cascading decrease
# e.g. 3.12.-1 -> 3.11.0, or 3.0.-1 -> 2.9.0, or 2.-1 -> 1.0
elsif( $val >= 0 )
{
return;
}
my $type = $self->type;
my $extra = $self->extra;
my $frag_is_int = ( $frag =~ /^\d+$/ ? 1 : 0 );
my $frag2num =
{
major => 1,
minor => 2,
patch => 3,
};
my $num2frag =
{
1 => 'major',
2 => 'minor',
3 => 'patch',
};
if( $frag eq 'alpha' )
{
$self->alpha( undef );
return;
}
die( "Fragment provided '$frag' cannot be 0." ) if( $frag_is_int && $frag == 0 );
my $level = $frag_is_int ? $frag : $frag2num->{ $frag };
# Should not be happening
if( $type eq 'decimal' && $level > 2 )
{
$self->patch( undef );
$self->alpha( undef );
@$extra = ();
return;
}
for( my $i = $level; $level >= 1; $i-- )
{
if( $val < 0 )
{
my $new_val = 0;
unless( $i == 1 )
{
my $up_val;
my $j = $i - 1;
if( exists( $num2frag->{ $j } ) )
{
my $coderef = $self->can( $num2frag->{ $j } ) ||
die( "Cannot find reference for method ", $num2frag->{ $j } );
$up_val = $coderef->( $self );
}
else
{
$up_val = $extra->[ $j - 4 ];
}
# Set value for next iteration
$val = ( $up_val // 0 ) - 1;
$new_val = ( $up_val > 0 ) ? 9 : 0;
}
if( exists( $num2frag->{ $i } ) )
{
# my $coderef = $self->can( $num2frag->{ $i } ) ||
# die( "Cannot find reference for method ", $num2frag->{ $i } );
# $coderef->( $self, 0 );
$self->{ $num2frag->{ $i } } = $new_val;
}
else
{
$extra->[ $i - 4 ] = $new_val;
}
}
else
{
if( exists( $num2frag->{ $i } ) )
{
# my $coderef = $self->can( $num2frag->{ $i } ) ||
# die( "Cannot find reference for method ", $num2frag->{ $i } );
# $coderef->( $self, 0 );
$self->{ $num2frag->{ $i } } = $val;
}
else
{
$extra->[ $i - 4 ] = $val;
}
last;
}
}
$self->_cascade( $level );
}
sub _cascade
{
my $self = shift( @_ );
my $frag = shift( @_ );
# We die, because this is an internal method and those cases should not happen unless this were a design bug
if( !defined( $frag ) || !length( $frag ) )
{
die( "No fragment was provided to cascade" );
}
elsif( $frag !~ /^(major|minor|patch|alpha|\d+)$/ )
{
die( "Unsupported version fragment '$frag'. Only use 'major', 'minor', 'patch' or 'alpha' or a number starting from 1 (1 = major, 2 = minor, etc)." );
}
my $type = $self->type;
my $extra = $self->extra;
my $frag_is_int = ( $frag =~ /^\d+$/ ? 1 : 0 );
if( $frag eq 'major' || ( $frag_is_int && $frag == 1 ) )
{
$self->alpha( undef );
$self->patch(0);
# $self->patch( $type eq 'decimal' ? undef : 0 );
$self->minor(0);
}
elsif( $frag eq 'minor' || ( $frag_is_int && $frag == 2 ) )
{
$self->alpha( undef );
$self->patch(0);
# $self->patch( $type eq 'decimal' ? undef : 0 );
}
elsif( $frag eq 'patch' || ( $frag_is_int && $frag == 3 ) )
{
$self->alpha( undef );
}
elsif( $frag eq 'alpha' )
{
# Nothing to do
}
elsif( $type eq 'dotted' && $frag_is_int )
{
my $offset = ( $frag - 4 );
my $len = $extra->length;
# Before the fragment offset, we set the value to 0 if it is undefined or empty, and
# after the fragment offset everything else is reset to 0
for( my $i = 0; $i < ( $offset < $len ? $len : $offset ); $i++ )
{
if( (
$i < $offset &&
( !defined( $extra->[$i] ) || !length( $extra->[$i] ) )
) || $i > $offset )
{
$extra->[$i] = 0;
}
}
lib/Changes/Version.pm view on Meta::CPAN
# return( $left->{_version} == $right->{_version} );
# return( $lv == $rv );
return( $lv <=> $rv );
}
sub _compute
{
my $self = shift( @_ );
my $opts = pop( @_ );
my( $other, $swap, $nomethod, $bitwise ) = @_;
my $frag = $self->default_frag // 'minor';
$frag = 'minor' if( $frag !~ /^(major|minor|patch|alpha|\d+)$/ );
if( !defined( $opts ) ||
ref( $opts ) ne 'HASH' ||
!exists( $opts->{op} ) ||
!defined( $opts->{op} ) ||
!length( $opts->{op} ) )
{
die( "No argument 'op' provided" );
}
my $op = $opts->{op};
my $clone = $self->clone;
my $extra = $self->extra;
my $frag_is_int = ( $frag =~ /^\d+$/ ? 1 : 0 );
my $map =
{
1 => 'major',
2 => 'minor',
3 => 'patch',
};
my $coderef;
if( ( $frag_is_int && exists( $map->{ $frag } ) ) || !$frag_is_int )
{
$coderef = $self->can( $map->{ $frag } // $frag ) ||
die( "Cannot find code reference for method ", ( $frag_is_int ? $map->{ $frag } : $frag ) );
}
my $val = defined( $coderef ) ? $coderef->( $self ) : $extra->[ $frag - 4 ];
my $err;
if( !defined( $val ) )
{
$val = $self->new_number(0);
}
elsif( !$self->_is_a( $val => 'Module::Generic::Number' ) )
{
$val = $self->new_number( "$val" );
if( !defined( $val ) )
{
lib/Changes/Version.pm view on Meta::CPAN
$new = $self;
$new_val = $n;
}
else
{
$new_val = int( $rv );
}
if( $new_val < 0 )
{
$new->_bubble( $frag, $new_val );
}
else
{
if( defined( $coderef ) )
{
$coderef->( $new, $new_val );
}
else
{
$extra->[( $frag - 4 )] = $new_val;
}
$new->_cascade( $frag );
}
$new->reset(1);
return( $new );
}
}
sub _inc_dec
{
my $self = shift( @_ );
my $op = shift( @_ ) || return( $self->error( "No op was provided." ) );
return( $self->error( "Op can only be 'inc' or 'dec'" ) ) if( $op !~ /^(inc|dec)$/ );
my $frag = shift( @_ );
my $unit = shift( @_ );
if( !defined( $frag ) || !length( "$frag" ) )
{
return( $self->error( "No version fragment was specified to ", ( $op eq 'inc' ? 'increase' : 'decrease' ), " the version number." ) );
}
elsif( $frag !~ /^(major|minor|patch|alpha|\d+)$/ )
{
return( $self->error( "Unsupported version fragment '$frag' to ", ( $op eq 'inc' ? 'increase' : 'decrease' ), ". Only use 'major', 'minor', 'patch' or 'alpha' or a number starting from 1 (1 = major, 2 = minor, etc)." ) );
}
if( defined( $unit ) && $unit !~ /^\d+$/ )
{
return( $self->error( "Unit to ", ( $op eq 'inc' ? 'increase' : 'decrease' ), " fragment $frag value must be an integer." ) );
}
my $extra = $self->extra;
my $frag_is_int = ( $frag =~ /^\d+$/ ? 1 : 0 );
my $map =
{
1 => 'major',
2 => 'minor',
3 => 'patch',
};
my $coderef;
if( ( $frag_is_int && exists( $map->{ $frag } ) ) || !$frag_is_int )
{
$coderef = $self->can( $map->{ $frag } // $frag ) ||
die( "Cannot find code reference for method ", ( $frag_is_int ? $map->{ $frag } : $frag ) );
}
my $n = defined( $coderef ) ? $coderef->( $self ) : $extra->[ $frag - 4 ];
# The offset specified is out of bound
if( $frag_is_int && ( $frag - 4 ) > $extra->size )
{
$n = (
$op eq 'inc'
? ( defined( $unit ) ? $unit : 1 )
: 0
);
}
elsif( defined( $unit ) && $unit == 1 )
{
$op eq 'inc' ? ( $n += $unit ) : ( $n -= $unit );
lib/Changes/Version.pm view on Meta::CPAN
{
$op eq 'inc' ? $n++ : $n--;
}
if( defined( $coderef ) )
{
$coderef->( $self, $n );
}
else
{
$extra->[( $frag - 4 )] = $n;
}
$self->_cascade( $frag );
$self->reset(1);
return( $self );
}
sub _noop
{
my( $self, $other, $swap, $nomethod, $bitwise ) = @_;
warn( "This operation $nomethod is not supported by Changes::Version\n" ) if( $self->_warnings_is_enabled );
}
lib/Changes/Version.pm view on Meta::CPAN
}
my $ok = 0;
if( !$self->extra->is_empty )
{
$ok++;
$comp->push( $self->extra->list );
}
for( qw( patch minor major ) )
{
next if( !length( $def->{ $_ } ) && !$ok );
# We stop skipping version fragments as soon as one is defined
$ok++;
$comp->unshift( $def->{ $_ } );
}
my $v = ( $self->qv ? 'v' : '' ) . $comp->map(sub{ 0 + $_ })->join( '.' )->scalar;
$v .= '_' . $def->{alpha} if( defined( $def->{alpha} ) && length( $def->{alpha} ) );
return( $v );
}
sub _verify
{
lib/Changes/Version.pm view on Meta::CPAN
die( Changes::Version->error ) if( !defined( $v ) );
my $type = $v->type;
$v->type( 'decimal' );
$v->padded(0);
$v->pretty(1);
$v->type( 'dotted' );
$v++;
# Updating 'minor'
say "$v"; # v1.3.0
$v += 2;
$v->default_frag( 'major' );
$v++;
say "$v"; # v2.0.0
$v->inc_patch;
say $v->is_alpha; # false
say $v->numify; # returns new Changes::Version object
say $v->normal; # returns new Changes::Version object
say $v->as_string; # same as say "$v";
# 5.0.6_2
say $v->format( "%R%d%A" );
lib/Changes/Version.pm view on Meta::CPAN
my $v = Changes::Version->new( ... ) || die( Changes::Version->error );
would be dangerous, because you would be assessing the return version object in a boolean context that could return false if the version was C<0>.
It supports the following options that can also be accessed or changed with their corresponding method.
=over 4
=item * C<alpha>
Specifies the alpha fragment integer of the version. See L</alpha> for more information.
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 4,
);
my $alpha = $v->alpha; # 4
$v->alpha(7);
say "$v"; # v1.2.3_7
=item * C<beta>
Specifies the beta fragment integer of the version. See L</beta> for more information.
Currently unused and reserved for future release.
=item * C<compat>
Boolean. When enabled, this will ensure the version formatting is strictly compliant with the L<version> module. Default to false.
=item * C<default_frag>
Specifies the fragment name or integer value used by overloaded operations.
my $v = Changes::Version->new( 'v1.2.3_4' );
my $default = $v->default_frag; # By default 'minor'
$v->default_frag( 'major' );
$v++; # Version is now v2.2.3_4
=item * C<extra>
Specifies the array reference of version fragments beyond C<patch>
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 12,
extra => [qw( 4 5 6 7 )],
);
say "$v"; # v1.2.3.4.5.6.7_12
my $a = $v->extra; # contains 4, 5, 6, 7
=item * C<major>
Specifies the C<major> fragment of the version string.
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 4,
);
my $major = $v->major; # 1
say "$v"; # v1.2.3_4
$v->major(3);
say "$v"; # v3.0.0
=item * C<minor>
Specifies the C<minor> fragment of the version string.
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 4,
);
my $minor = $v->minor; # 2
say "$v"; # v1.2.3_4
$v->minor(3);
lib/Changes/Version.pm view on Meta::CPAN
minor => 20,
patch => 300,
type => 'decimal',
);
say "$v"; # 1.020300
$v->padded(0);
say "$v"; # 1.0203
=item * C<patch>
Specifies the C<patch> fragment of the version string.
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 4,
);
my $patch = $v->patch; # 3
say "$v"; # v1.2.3_4
$v->patch(7);
lib/Changes/Version.pm view on Meta::CPAN
1.2345_01
are all legitimate version strings.
If an error occurred, this will return an L<error|Module::Generic/error>.
=head1 METHODS
=head2 alpha
Sets or gets the C<alpha> fragment integer of the version.
Setting this to C<undef> effectively removes it.
Returns a L<number object|Module::Generic::Number>
=head2 as_string
Returns a version string properly formatted according to the C<type> set with L</type> and other parameters sets such as L</qv>, L</padded> and L</pretty>
Resulting value is cached, which means the second time this is called, the cached value will be returned for speed.
lib/Changes/Version.pm view on Meta::CPAN
say "$v"; # v1.2.3_4
# Changing the patch level
$v->inc( 'patch' );
# Now forced to re-format
say "$v"; # v1.2.4
# No change, using the cache
say "$v"; # v1.2.4
=head2 beta
The beta fragment integer of the version. This is currently unused and reserved for future release of this class.
=head2 compat
Boolean. When enabled, this will ensure the version formatting is strictly compliant with the L<version> module. Default to false.
=head2 dec
Provided with a version fragment, and an optiona integer, and this will decrease the version fragment value by as much. If no integer is provided, the default decrement is 1.
my $v = Changes::Version->new(
major => 1,
minor => 2,
patch => 3,
alpha => 4,
);
say "$v"; # v1.2.3_4;
$v->dec( 'alpha' );
say "$v"; # v1.2.3_3;
$v->dec( 'patch', 2 );
say "$v"; # v1.2.1
my $v = Changes::Version->new( 'v1.2.3.4.5.6.7_8' );
# Decrease the 5th fragment
$v->dec(5);
say "$v"; # v1.2.3.4.4.0.0
Any change to a fragment value will reset the lower fragment values to zero. Thus:
=over 4
=item * changing the C<major> value will reset C<minor> and C<patch> to 0 and C<alpha> to C<undef>
=item * changing the C<minor> value will reset C<patch> to 0 and C<alpha> to C<undef>
=item * changing the C<patch> value will reset C<alpha> to C<undef>
=item * changing the nth fragment value will reset all fragment value after that to 0
=back
If you pass a fragment that is an integer and it is outside the maximum number of fragments, it will automatically expand the number of version fragments and initialise the intermediary fragments to 0. A fragment as an integer starts at 1.
Using the example above:
$v->dec(10);
say "$v"; # v1.2.3.4.5.6.7.0.0.0
The 10th element is set to 0 because it does not exist, so it cannot be decreased.
=head2 dec_alpha
This is a shortcut for calling L</dec> on fragment C<alpha>
=head2 dec_beta
This is a shortcut for calling L</dec> on fragment C<beta>
=head2 dec_major
This is a shortcut for calling L</dec> on fragment C<major>
=head2 dec_minor
This is a shortcut for calling L</dec> on fragment C<minor>
=head2 dec_patch
This is a shortcut for calling L</dec> on fragment C<patch>
=head2 default_frag
my $v = Changes::Version->new( 'v1.2.3_4' );
my $default = $v->default_frag; # By default 'minor'
$v->default_frag( 'major' );
$v++; # Version is now v2.2.3_4
String. Sets or gets the name or the integer value for the version fragment. Supported value can be C<major>, C<minor>. C<patch>, C<alpha>, or an integer.
Returns a L<scalar object|Module::Generic::Scalar>
=head2 extra
Sets or gets an array reference of version fragments starting from C<1> for C<major>, C<2> for C<minor>, C<3> for C<patch>, etc. For example:
my $v = Changes::Version->new( 'v1.2.3.4.5.6.7_8' );
my $a = $v->extra; # contains 4, 5, 6, 7
Note that C<alpha> is not accessible via digits, but only using L</alpha>
You should not be accessing this directly.
Returns an L<array object|Module::Generic::Array>
lib/Changes/Version.pm view on Meta::CPAN
See also L</pattern> to get or set a pattern used by L</as_string>
See also below the L<possible patterns|/"PATTERNS">
=head2 inc
Same as L</dec>, but increasing instead of decreasing.
=head2 inc_alpha
This is a shortcut for calling L</inc> on fragment C<alpha>
=head2 inc_beta
This is a shortcut for calling L</inc> on fragment C<beta>
=head2 inc_major
This is a shortcut for calling L</inc> on fragment C<major>
=head2 inc_minor
This is a shortcut for calling L</inc> on fragment C<minor>
=head2 inc_patch
This is a shortcut for calling L</inc> on fragment C<patch>
=head2 is_alpha
Returns true if L</alpha> has a value set.
=head2 is_qv
Returns true if L</qv> is set to true, false otherwise.
=head2 major
Sets or gets the C<major> fragment of the version string.
my $v = Changes::Version->new( 'v1.2.3_4' );
my $major = $v->major; # 1
$v->major(3);
say "$v"; # v3.2.3_4
Setting this to C<undef> effectively removes it.
Returns a L<number object|Module::Generic::Number>
=head2 minor
Sets or gets the C<minor> fragment of the version string.
my $v = Changes::Version->new( 'v1.2.3_4' );
my $minor = $v->minor; # 2
$v->minor(3);
say "$v"; # v1.3.3_4
Setting this to C<undef> effectively removes it.
Returns a L<number object|Module::Generic::Number>
lib/Changes/Version.pm view on Meta::CPAN
padded => 1,
);
say "$v"; # 1.002030
$v->padded(0);
say "$v"; # 1.00203
Returns a L<boolean object|Module::Generic::Boolean>
=head2 patch
Sets or gets the C<patch> fragment of the version string.
my $v = Changes::Version->new( 'v1.2.3_4' );
my $patch = $v->patch; # 3
$v->patch(5);
say "$v"; # v1.3.5_4
Returns a L<number object|Module::Generic::Number>
=head2 pattern
lib/Changes/Version.pm view on Meta::CPAN
This is on my bucket list of things to improve.
=item * C<cmp>
Same as above.
=item * C<bool>
=item * C<+>, C<->, C<*>, C</>
When performing those operations, it will use the value of the fragment of the version set with L</default_frag>, which, by default, is C<minor>.
It returns a new L<Changes::Version> object reflecting the new version value. However, if the operation is swapped, with the version object on the right-hand side instead of the left-hand side, this will return a regular number.
my $vers = Changes::Version->new( 'v1.2.3_4' );
my $new_version_object = $vers + 2; # Now v1.4.3_4 (minor has been bumped up by 2)
$vers->default_frag( 'major' );
my $new_version_object = $vers + 2; # Now v3.2.3_4 (this time, 'major' was increased)
But, when swapped:
my $vers = Changes::Version->new( 'v1.2.3_4' );
my $n = 3 + $vers; # yields 5 (using the 'minor' fragment by default)
$vers->default_frag( 'major' );
my $n = 3 + $vers; # yields 4 (this time, using the 'major' fragment)
=item * C<+=>, C<-=>, C<*=>, C</=>
In this operations, it modifies the current object with the operand provided and returns the current object, instead of creating a new one.
my $vers = Changes::Version->new( 'v1.2.3_4' );
# By default, using the 'minor' fragment
$vers += 1; # version is now v2.2.3_4
$vers->default_frag( 'alpha' );
$vers /= 2; # version is now v1.2.3_2
=item * C<++>, C<-->
When using those operations, it updates the current object directly and returns it. For example:
my $vers = Changes::Version->new( 'v1.2.3_4' );
# By default, using the 'minor' fragment
$vers++; # version is now v1.3.3_4
=back
=head1 PATTERNS
The following patterns can be used to format the version string.
=over 4
lib/Changes/Version.pm view on Meta::CPAN
This will return the alpha version, if any, prepended with an underscore.
If there is no alpha version, it returns an empty string.
=item * C<%a>
my $v = Changes::Version->parse( "5.0.6_2" );
say $v->format( '%a' ); # 2
This will return the C<alpha> fragment value, if any.
If there is no C<alpha> fragment value, it returns an empty string.
=item * C<%D>
my $v = Changes::Version->parse( "5.0.6.1.2.3.4_2" );
say $v->format( '%D' ); # 0.6.1.2.3.4
my $v = Changes::Version->parse( "5.0.6" );
say $v->format( '%D' ); # 0.6
This will return the C<minor>, C<patch>, and any extra fragments.
This is designed for dotted-decimal types, and C<minor>, and C<patch> will always return a number, possibly C<0>
=item * C<%d>
my $v = Changes::Version->parse( "5.0.6.1.2.3.4_2" );
say $v->format( '%D' ); # .0.6.1.2.3.4
my $v = Changes::Version->parse( "5.0.6" );
say $v->format( '%D' ); # .0.6
lib/Changes/Version.pm view on Meta::CPAN
my $v = Changes::Version->parse( "5" );
say $v->format( '%R%d%A' ); # 5.0.0
=item * C<%M>
my $v = Changes::Version->parse( "5.2.6_3" );
say $v->format( '%M' ); # 2
This returns the C<minor> part of the version.
If there is no C<minor> fragment value, it returns an empty string.
=item * C<%m>
my $v = Changes::Version->parse( "5.2.6_3" );
say $v->format( '%m' ); # .2
This is similar to C<%M>, but will prepend a dot if the value is not null.
=item * C<%N>
lib/Changes/Version.pm view on Meta::CPAN
=item * C<%n>
my $v = Changes::Version->parse( "5.2.6" ):
say $v->format( '%R%n' ); # 5.002006
say $v->format( '%n' ); # .002006
This is similar to C<%N>, but will prepend a dot if the value is not null.
=item * C<%P>
This returns the C<patch> fragment value of the version, if any.
If there is no C<patch> fragment value, it returns an empty string.
=item * C<%R>
This returns the C<major> fragment value of the version, if any.
If there is no C<major> fragment value, it returns an empty string.
=item * C<%U>
my $v = Changes::Version->parse( "5.2.6" ):
say $v->format( '%R.%U' ); # 5.002_006
say $v->format( '%U' ); # 002_006
This returns the C<minor> and C<patch> value of a dotted-decimal version as numified version using the underscore to separate the C<minor> and the C<patch> fragments.
=item * C<%u>
my $v = Changes::Version->parse( "5.2.6" ):
say $v->format( '%R%u' ); # 5.002_006
say $v->format( '%u' ); # .002_006
This is similar to C<%U>, but will prepend a dot if the value is not null.
=back
t/006_version.t view on Meta::CPAN
can_ok( $v, 'alpha' );
can_ok( $v, 'as_string' );
can_ok( $v, 'beta' );
can_ok( $v, 'compat' );
can_ok( $v, 'dec' );
can_ok( $v, 'dec_alpha' );
can_ok( $v, 'dec_beta' );
can_ok( $v, 'dec_major' );
can_ok( $v, 'dec_minor' );
can_ok( $v, 'dec_patch' );
can_ok( $v, 'default_frag' );
can_ok( $v, 'extra' );
can_ok( $v, 'inc' );
can_ok( $v, 'inc_alpha' );
can_ok( $v, 'inc_beta' );
can_ok( $v, 'inc_major' );
can_ok( $v, 'inc_minor' );
can_ok( $v, 'inc_patch' );
can_ok( $v, 'is_alpha' );
can_ok( $v, 'is_qv' );
can_ok( $v, 'major' );
t/006_version.t view on Meta::CPAN
# Those will not work
# '+=' => { version => $v, operand => 1, expect => [qw( )] },
# '-=' => { version => $v, operand => 1, expect => [qw( )] },
# '*=' => { version => $v, operand => 2, expect => [qw( )] },
# '/=' => { version => $v, operand => 2, expect => [qw( )] },
# '++' => { version => $v, expect => [qw( )] },
# '--' => { version => $v, expect => [qw( )] },
],
};
my $frag2pos =
{
major => 0,
minor => 1,
patch => 2,
alpha => 3,
};
# foreach my $type ( qw( dotted decimal ) )
foreach my $type ( sort( keys( %$tests_dict ) ) )
{
t/006_version.t view on Meta::CPAN
my $vers;
if( ref( $def->{version} ) )
{
$vers = $def->{version}->clone;
}
else
{
$vers = Changes::Version->new( $def->{version}, debug => $DEBUG );
}
my $orig = $vers->clone;
foreach my $frag (qw( major minor patch alpha ))
{
diag( "Using version '$vers' for test of type '$type' with fragment '$frag' and with operator '$op'" ) if( $DEBUG );
my $expect = $def->{expect}->[ $frag2pos->{ $frag } ];
$vers->default_frag( $frag );
my $eval;
if( $def->{swapped} )
{
$eval = "$def->{operand} ${op} \$vers";
}
else
{
$eval = "\$vers" . ( exists( $def->{operand} ) ? " ${op} $def->{operand}" : $op );
}
my $rv = eval( $eval );
t/006_version.t view on Meta::CPAN
}
# ++, --
if( !exists( $def->{operand} ) )
{
is( "$vers" => $expect, "${orig}${op} -> ${expect}" );
}
# Others returns a new object
else
{
is( "$rv" => $expect, ( $def->{swapped} ? "$def->{operand} ${op} ${orig}" : "${orig} ${op} $def->{operand}" ) . " -> ${expect} (using $frag)" );
}
$vers = $orig->clone;
}
}
};
}
subtest "satisfy" => sub
{
ok( Changes::Version->satisfy( '0', '0' ), "'0' satisfies '0'" );