Version-Semantic

 view release on metacpan or  search on metacpan

lib/Version/Semantic.pm  view on Meta::CPAN


#<<<
package Version::Core; ## no critic ( RequireFilenameMatchesPackage )
BEGIN {
our $VERSION = 'v2.2.0';
}
#>>>

use overload '<=>' => 'compare_to', '""' => 'to_string';

sub prefix { shift->{ prefix } }
sub major  { shift->{ major } }
sub minor  { shift->{ minor } }
sub patch  { shift->{ patch } }

# Derived attribute
sub version_core { shift->{ version_core } }

sub has_prefix { exists shift->{ prefix } }

sub corever_re { $corever_re }

# Constructor as factory method
sub parse {
  my $options = ( ref $_[ -1 ] eq 'HASH' ) ? pop : {};
  my ( $class, $version ) = @_;
  $version //= '';

  my $ver_re = $class ne __PACKAGE__ ? $semver_re : $corever_re;
  unless ( $version =~ m/\A$ver_re\z/ ) {
    $croak->( "Version '$version' is not a ${ \( $class ne __PACKAGE__ ? 'semantic': 'core' ) } version" )
      if $options->{ fatal };
    return
  }

  $class->new( %+ )
}

sub new {
  my $invocant = shift;
  my $class    = ref $invocant || $invocant;

  my $self = do {

    # Validate @_
    my $length;
    my @tmp = @_;
    while ( ( $length = scalar( my ( $name, $value ) = splice @tmp, 0, 2 ) ) == 2 ) {
      $croak->( "Parameter with undefined name passed to \"$class\" constructor" )
        unless defined $name
    }
    $croak->( "Odd number of arguments passed to \"$class\" constructor" )
      if $length == 1;

    # Remove parameters that have undef values
    my %tmp = @_;
    for ( keys %tmp ) {
      delete $tmp{ $_ } unless defined $tmp{ $_ }
    }

    bless { ref $invocant ? %$invocant : (), %tmp } => $class
  };

  delete $self->{ version_core };

  my %params         = map  { $_ => 1 } $self->_init;
  my @unknown_params = grep { not exists $params{ $_ } } keys %$self;
  # Diagnostic message is copied from 'class' feature
  $croak->( "Unrecognised parameters for \"$class\" constructor: " . join( ', ', @unknown_params ) )
    if @unknown_params;

  $self->{ version_core } = ( $self->{ prefix } // '' ) . join( '.', map { $self->{ $_ } } qw( major minor patch ) );

  $self
}

{
  my %isa = (
    prefix => $prefix_re,
    major  => $num_id_re,
    minor  => $num_id_re,
    patch  => $num_id_re,
  );

  sub _init {
    my $self = shift;

    foreach ( qw( major minor patch ) ) {
      # Diagnostic message is copied from 'class' feature
      $croak->( "Required parameter '$_' is missing for \"${ \ __PACKAGE__ }\" constructor" )
        unless exists $self->{ $_ }
    }

    foreach ( keys %isa ) {
      next unless exists $self->{ $_ };
      $croak->( "Parameter '$_' has invalid value '$self->{ $_ }'" )
        unless $self->{ $_ } =~ m/\A $isa{ $_ } \z/x
    }

    qw( prefix major minor patch )
  }
}

sub increment {
  # Obvious strategies are major, minor, and patch
  my ( $self, $strategy ) = @_;
  $strategy //= 'patch';

  return $self->new( patch => $self->patch + 1 )
    if $strategy eq 'patch';
  return $self->new( minor => $self->minor + 1, patch => 0 )
    if $strategy eq 'minor';
  return $self->new( major => $self->major + 1, minor => 0, patch => 0 )
    if $strategy eq 'major';

  $croak->( "Version incrementation strategy '$strategy' is not implemented" )
}

# https://semver.org/spec/v2.0.0.html#spec-item-11
sub compare_to {
  my ( $self, $other ) = @_;



( run in 1.828 second using v1.01-cache-2.11-cpan-364913b4093 )