191f110e0Safresh1use strict; 291f110e0Safresh1use warnings; 391f110e0Safresh1package CPAN::Meta::Requirements; 4*6fb12b70Safresh1our $VERSION = '2.125'; # VERSION 591f110e0Safresh1# ABSTRACT: a set of version requirements for a CPAN dist 691f110e0Safresh1 791f110e0Safresh1 891f110e0Safresh1use Carp (); 991f110e0Safresh1use Scalar::Util (); 1091f110e0Safresh1use version 0.77 (); # the ->parse method 1191f110e0Safresh1 1291f110e0Safresh1 1391f110e0Safresh1my @valid_options = qw( bad_version_hook ); 1491f110e0Safresh1 1591f110e0Safresh1sub new { 1691f110e0Safresh1 my ($class, $options) = @_; 1791f110e0Safresh1 $options ||= {}; 1891f110e0Safresh1 Carp::croak "Argument to $class\->new() must be a hash reference" 1991f110e0Safresh1 unless ref $options eq 'HASH'; 2091f110e0Safresh1 my %self = map {; $_ => $options->{$_}} @valid_options; 2191f110e0Safresh1 2291f110e0Safresh1 return bless \%self => $class; 2391f110e0Safresh1} 2491f110e0Safresh1 2591f110e0Safresh1sub _version_object { 2691f110e0Safresh1 my ($self, $version) = @_; 2791f110e0Safresh1 2891f110e0Safresh1 my $vobj; 2991f110e0Safresh1 3091f110e0Safresh1 eval { 3191f110e0Safresh1 $vobj = (! defined $version) ? version->parse(0) 3291f110e0Safresh1 : (! Scalar::Util::blessed($version)) ? version->parse($version) 3391f110e0Safresh1 : $version; 3491f110e0Safresh1 }; 3591f110e0Safresh1 3691f110e0Safresh1 if ( my $err = $@ ) { 3791f110e0Safresh1 my $hook = $self->{bad_version_hook}; 3891f110e0Safresh1 $vobj = eval { $hook->($version) } 3991f110e0Safresh1 if ref $hook eq 'CODE'; 4091f110e0Safresh1 unless (Scalar::Util::blessed($vobj) && $vobj->isa("version")) { 4191f110e0Safresh1 $err =~ s{ at .* line \d+.*$}{}; 4291f110e0Safresh1 die "Can't convert '$version': $err"; 4391f110e0Safresh1 } 4491f110e0Safresh1 } 4591f110e0Safresh1 4691f110e0Safresh1 # ensure no leading '.' 4791f110e0Safresh1 if ( $vobj =~ m{\A\.} ) { 4891f110e0Safresh1 $vobj = version->parse("0$vobj"); 4991f110e0Safresh1 } 5091f110e0Safresh1 5191f110e0Safresh1 # ensure normal v-string form 5291f110e0Safresh1 if ( $vobj->is_qv ) { 5391f110e0Safresh1 $vobj = version->parse($vobj->normal); 5491f110e0Safresh1 } 5591f110e0Safresh1 5691f110e0Safresh1 return $vobj; 5791f110e0Safresh1} 5891f110e0Safresh1 5991f110e0Safresh1 6091f110e0Safresh1BEGIN { 6191f110e0Safresh1 for my $type (qw(minimum maximum exclusion exact_version)) { 6291f110e0Safresh1 my $method = "with_$type"; 6391f110e0Safresh1 my $to_add = $type eq 'exact_version' ? $type : "add_$type"; 6491f110e0Safresh1 6591f110e0Safresh1 my $code = sub { 6691f110e0Safresh1 my ($self, $name, $version) = @_; 6791f110e0Safresh1 6891f110e0Safresh1 $version = $self->_version_object( $version ); 6991f110e0Safresh1 7091f110e0Safresh1 $self->__modify_entry_for($name, $method, $version); 7191f110e0Safresh1 7291f110e0Safresh1 return $self; 7391f110e0Safresh1 }; 7491f110e0Safresh1 7591f110e0Safresh1 no strict 'refs'; 7691f110e0Safresh1 *$to_add = $code; 7791f110e0Safresh1 } 7891f110e0Safresh1} 7991f110e0Safresh1 8091f110e0Safresh1 8191f110e0Safresh1sub add_requirements { 8291f110e0Safresh1 my ($self, $req) = @_; 8391f110e0Safresh1 8491f110e0Safresh1 for my $module ($req->required_modules) { 8591f110e0Safresh1 my $modifiers = $req->__entry_for($module)->as_modifiers; 8691f110e0Safresh1 for my $modifier (@$modifiers) { 8791f110e0Safresh1 my ($method, @args) = @$modifier; 8891f110e0Safresh1 $self->$method($module => @args); 8991f110e0Safresh1 }; 9091f110e0Safresh1 } 9191f110e0Safresh1 9291f110e0Safresh1 return $self; 9391f110e0Safresh1} 9491f110e0Safresh1 9591f110e0Safresh1 9691f110e0Safresh1sub accepts_module { 9791f110e0Safresh1 my ($self, $module, $version) = @_; 9891f110e0Safresh1 9991f110e0Safresh1 $version = $self->_version_object( $version ); 10091f110e0Safresh1 10191f110e0Safresh1 return 1 unless my $range = $self->__entry_for($module); 10291f110e0Safresh1 return $range->_accepts($version); 10391f110e0Safresh1} 10491f110e0Safresh1 10591f110e0Safresh1 10691f110e0Safresh1sub clear_requirement { 10791f110e0Safresh1 my ($self, $module) = @_; 10891f110e0Safresh1 10991f110e0Safresh1 return $self unless $self->__entry_for($module); 11091f110e0Safresh1 11191f110e0Safresh1 Carp::confess("can't clear requirements on finalized requirements") 11291f110e0Safresh1 if $self->is_finalized; 11391f110e0Safresh1 11491f110e0Safresh1 delete $self->{requirements}{ $module }; 11591f110e0Safresh1 11691f110e0Safresh1 return $self; 11791f110e0Safresh1} 11891f110e0Safresh1 11991f110e0Safresh1 12091f110e0Safresh1sub requirements_for_module { 12191f110e0Safresh1 my ($self, $module) = @_; 12291f110e0Safresh1 my $entry = $self->__entry_for($module); 12391f110e0Safresh1 return unless $entry; 12491f110e0Safresh1 return $entry->as_string; 12591f110e0Safresh1} 12691f110e0Safresh1 12791f110e0Safresh1 12891f110e0Safresh1sub required_modules { keys %{ $_[0]{requirements} } } 12991f110e0Safresh1 13091f110e0Safresh1 13191f110e0Safresh1sub clone { 13291f110e0Safresh1 my ($self) = @_; 13391f110e0Safresh1 my $new = (ref $self)->new; 13491f110e0Safresh1 13591f110e0Safresh1 return $new->add_requirements($self); 13691f110e0Safresh1} 13791f110e0Safresh1 13891f110e0Safresh1sub __entry_for { $_[0]{requirements}{ $_[1] } } 13991f110e0Safresh1 14091f110e0Safresh1sub __modify_entry_for { 14191f110e0Safresh1 my ($self, $name, $method, $version) = @_; 14291f110e0Safresh1 14391f110e0Safresh1 my $fin = $self->is_finalized; 14491f110e0Safresh1 my $old = $self->__entry_for($name); 14591f110e0Safresh1 14691f110e0Safresh1 Carp::confess("can't add new requirements to finalized requirements") 14791f110e0Safresh1 if $fin and not $old; 14891f110e0Safresh1 14991f110e0Safresh1 my $new = ($old || 'CPAN::Meta::Requirements::_Range::Range') 15091f110e0Safresh1 ->$method($version); 15191f110e0Safresh1 15291f110e0Safresh1 Carp::confess("can't modify finalized requirements") 15391f110e0Safresh1 if $fin and $old->as_string ne $new->as_string; 15491f110e0Safresh1 15591f110e0Safresh1 $self->{requirements}{ $name } = $new; 15691f110e0Safresh1} 15791f110e0Safresh1 15891f110e0Safresh1 15991f110e0Safresh1sub is_simple { 16091f110e0Safresh1 my ($self) = @_; 16191f110e0Safresh1 for my $module ($self->required_modules) { 16291f110e0Safresh1 # XXX: This is a complete hack, but also entirely correct. 16391f110e0Safresh1 return if $self->__entry_for($module)->as_string =~ /\s/; 16491f110e0Safresh1 } 16591f110e0Safresh1 16691f110e0Safresh1 return 1; 16791f110e0Safresh1} 16891f110e0Safresh1 16991f110e0Safresh1 17091f110e0Safresh1sub is_finalized { $_[0]{finalized} } 17191f110e0Safresh1 17291f110e0Safresh1 17391f110e0Safresh1sub finalize { $_[0]{finalized} = 1 } 17491f110e0Safresh1 17591f110e0Safresh1 17691f110e0Safresh1sub as_string_hash { 17791f110e0Safresh1 my ($self) = @_; 17891f110e0Safresh1 17991f110e0Safresh1 my %hash = map {; $_ => $self->{requirements}{$_}->as_string } 18091f110e0Safresh1 $self->required_modules; 18191f110e0Safresh1 18291f110e0Safresh1 return \%hash; 18391f110e0Safresh1} 18491f110e0Safresh1 18591f110e0Safresh1 18691f110e0Safresh1my %methods_for_op = ( 18791f110e0Safresh1 '==' => [ qw(exact_version) ], 18891f110e0Safresh1 '!=' => [ qw(add_exclusion) ], 18991f110e0Safresh1 '>=' => [ qw(add_minimum) ], 19091f110e0Safresh1 '<=' => [ qw(add_maximum) ], 19191f110e0Safresh1 '>' => [ qw(add_minimum add_exclusion) ], 19291f110e0Safresh1 '<' => [ qw(add_maximum add_exclusion) ], 19391f110e0Safresh1); 19491f110e0Safresh1 19591f110e0Safresh1sub add_string_requirement { 19691f110e0Safresh1 my ($self, $module, $req) = @_; 19791f110e0Safresh1 19891f110e0Safresh1 Carp::confess("No requirement string provided for $module") 19991f110e0Safresh1 unless defined $req && length $req; 20091f110e0Safresh1 20191f110e0Safresh1 my @parts = split qr{\s*,\s*}, $req; 20291f110e0Safresh1 20391f110e0Safresh1 20491f110e0Safresh1 for my $part (@parts) { 20591f110e0Safresh1 my ($op, $ver) = $part =~ m{\A\s*(==|>=|>|<=|<|!=)\s*(.*)\z}; 20691f110e0Safresh1 20791f110e0Safresh1 if (! defined $op) { 20891f110e0Safresh1 $self->add_minimum($module => $part); 20991f110e0Safresh1 } else { 21091f110e0Safresh1 Carp::confess("illegal requirement string: $req") 21191f110e0Safresh1 unless my $methods = $methods_for_op{ $op }; 21291f110e0Safresh1 21391f110e0Safresh1 $self->$_($module => $ver) for @$methods; 21491f110e0Safresh1 } 21591f110e0Safresh1 } 21691f110e0Safresh1} 21791f110e0Safresh1 21891f110e0Safresh1 21991f110e0Safresh1sub from_string_hash { 22091f110e0Safresh1 my ($class, $hash) = @_; 22191f110e0Safresh1 22291f110e0Safresh1 my $self = $class->new; 22391f110e0Safresh1 22491f110e0Safresh1 for my $module (keys %$hash) { 22591f110e0Safresh1 my $req = $hash->{$module}; 22691f110e0Safresh1 unless ( defined $req && length $req ) { 22791f110e0Safresh1 $req = 0; 22891f110e0Safresh1 Carp::carp("Undefined requirement for $module treated as '0'"); 22991f110e0Safresh1 } 23091f110e0Safresh1 $self->add_string_requirement($module, $req); 23191f110e0Safresh1 } 23291f110e0Safresh1 23391f110e0Safresh1 return $self; 23491f110e0Safresh1} 23591f110e0Safresh1 23691f110e0Safresh1############################################################## 23791f110e0Safresh1 23891f110e0Safresh1{ 23991f110e0Safresh1 package 24091f110e0Safresh1 CPAN::Meta::Requirements::_Range::Exact; 24191f110e0Safresh1 sub _new { bless { version => $_[1] } => $_[0] } 24291f110e0Safresh1 24391f110e0Safresh1 sub _accepts { return $_[0]{version} == $_[1] } 24491f110e0Safresh1 24591f110e0Safresh1 sub as_string { return "== $_[0]{version}" } 24691f110e0Safresh1 24791f110e0Safresh1 sub as_modifiers { return [ [ exact_version => $_[0]{version} ] ] } 24891f110e0Safresh1 24991f110e0Safresh1 sub _clone { 25091f110e0Safresh1 (ref $_[0])->_new( version->new( $_[0]{version} ) ) 25191f110e0Safresh1 } 25291f110e0Safresh1 25391f110e0Safresh1 sub with_exact_version { 25491f110e0Safresh1 my ($self, $version) = @_; 25591f110e0Safresh1 25691f110e0Safresh1 return $self->_clone if $self->_accepts($version); 25791f110e0Safresh1 25891f110e0Safresh1 Carp::confess("illegal requirements: unequal exact version specified"); 25991f110e0Safresh1 } 26091f110e0Safresh1 26191f110e0Safresh1 sub with_minimum { 26291f110e0Safresh1 my ($self, $minimum) = @_; 26391f110e0Safresh1 return $self->_clone if $self->{version} >= $minimum; 26491f110e0Safresh1 Carp::confess("illegal requirements: minimum above exact specification"); 26591f110e0Safresh1 } 26691f110e0Safresh1 26791f110e0Safresh1 sub with_maximum { 26891f110e0Safresh1 my ($self, $maximum) = @_; 26991f110e0Safresh1 return $self->_clone if $self->{version} <= $maximum; 27091f110e0Safresh1 Carp::confess("illegal requirements: maximum below exact specification"); 27191f110e0Safresh1 } 27291f110e0Safresh1 27391f110e0Safresh1 sub with_exclusion { 27491f110e0Safresh1 my ($self, $exclusion) = @_; 27591f110e0Safresh1 return $self->_clone unless $exclusion == $self->{version}; 27691f110e0Safresh1 Carp::confess("illegal requirements: excluded exact specification"); 27791f110e0Safresh1 } 27891f110e0Safresh1} 27991f110e0Safresh1 28091f110e0Safresh1############################################################## 28191f110e0Safresh1 28291f110e0Safresh1{ 28391f110e0Safresh1 package 28491f110e0Safresh1 CPAN::Meta::Requirements::_Range::Range; 28591f110e0Safresh1 28691f110e0Safresh1 sub _self { ref($_[0]) ? $_[0] : (bless { } => $_[0]) } 28791f110e0Safresh1 28891f110e0Safresh1 sub _clone { 28991f110e0Safresh1 return (bless { } => $_[0]) unless ref $_[0]; 29091f110e0Safresh1 29191f110e0Safresh1 my ($s) = @_; 29291f110e0Safresh1 my %guts = ( 29391f110e0Safresh1 (exists $s->{minimum} ? (minimum => version->new($s->{minimum})) : ()), 29491f110e0Safresh1 (exists $s->{maximum} ? (maximum => version->new($s->{maximum})) : ()), 29591f110e0Safresh1 29691f110e0Safresh1 (exists $s->{exclusions} 29791f110e0Safresh1 ? (exclusions => [ map { version->new($_) } @{ $s->{exclusions} } ]) 29891f110e0Safresh1 : ()), 29991f110e0Safresh1 ); 30091f110e0Safresh1 30191f110e0Safresh1 bless \%guts => ref($s); 30291f110e0Safresh1 } 30391f110e0Safresh1 30491f110e0Safresh1 sub as_modifiers { 30591f110e0Safresh1 my ($self) = @_; 30691f110e0Safresh1 my @mods; 30791f110e0Safresh1 push @mods, [ add_minimum => $self->{minimum} ] if exists $self->{minimum}; 30891f110e0Safresh1 push @mods, [ add_maximum => $self->{maximum} ] if exists $self->{maximum}; 30991f110e0Safresh1 push @mods, map {; [ add_exclusion => $_ ] } @{$self->{exclusions} || []}; 31091f110e0Safresh1 return \@mods; 31191f110e0Safresh1 } 31291f110e0Safresh1 31391f110e0Safresh1 sub as_string { 31491f110e0Safresh1 my ($self) = @_; 31591f110e0Safresh1 31691f110e0Safresh1 return 0 if ! keys %$self; 31791f110e0Safresh1 31891f110e0Safresh1 return "$self->{minimum}" if (keys %$self) == 1 and exists $self->{minimum}; 31991f110e0Safresh1 32091f110e0Safresh1 my @exclusions = @{ $self->{exclusions} || [] }; 32191f110e0Safresh1 32291f110e0Safresh1 my @parts; 32391f110e0Safresh1 32491f110e0Safresh1 for my $pair ( 32591f110e0Safresh1 [ qw( >= > minimum ) ], 32691f110e0Safresh1 [ qw( <= < maximum ) ], 32791f110e0Safresh1 ) { 32891f110e0Safresh1 my ($op, $e_op, $k) = @$pair; 32991f110e0Safresh1 if (exists $self->{$k}) { 33091f110e0Safresh1 my @new_exclusions = grep { $_ != $self->{ $k } } @exclusions; 33191f110e0Safresh1 if (@new_exclusions == @exclusions) { 33291f110e0Safresh1 push @parts, "$op $self->{ $k }"; 33391f110e0Safresh1 } else { 33491f110e0Safresh1 push @parts, "$e_op $self->{ $k }"; 33591f110e0Safresh1 @exclusions = @new_exclusions; 33691f110e0Safresh1 } 33791f110e0Safresh1 } 33891f110e0Safresh1 } 33991f110e0Safresh1 34091f110e0Safresh1 push @parts, map {; "!= $_" } @exclusions; 34191f110e0Safresh1 34291f110e0Safresh1 return join q{, }, @parts; 34391f110e0Safresh1 } 34491f110e0Safresh1 34591f110e0Safresh1 sub with_exact_version { 34691f110e0Safresh1 my ($self, $version) = @_; 34791f110e0Safresh1 $self = $self->_clone; 34891f110e0Safresh1 34991f110e0Safresh1 Carp::confess("illegal requirements: exact specification outside of range") 35091f110e0Safresh1 unless $self->_accepts($version); 35191f110e0Safresh1 35291f110e0Safresh1 return CPAN::Meta::Requirements::_Range::Exact->_new($version); 35391f110e0Safresh1 } 35491f110e0Safresh1 35591f110e0Safresh1 sub _simplify { 35691f110e0Safresh1 my ($self) = @_; 35791f110e0Safresh1 35891f110e0Safresh1 if (defined $self->{minimum} and defined $self->{maximum}) { 35991f110e0Safresh1 if ($self->{minimum} == $self->{maximum}) { 36091f110e0Safresh1 Carp::confess("illegal requirements: excluded all values") 36191f110e0Safresh1 if grep { $_ == $self->{minimum} } @{ $self->{exclusions} || [] }; 36291f110e0Safresh1 36391f110e0Safresh1 return CPAN::Meta::Requirements::_Range::Exact->_new($self->{minimum}) 36491f110e0Safresh1 } 36591f110e0Safresh1 36691f110e0Safresh1 Carp::confess("illegal requirements: minimum exceeds maximum") 36791f110e0Safresh1 if $self->{minimum} > $self->{maximum}; 36891f110e0Safresh1 } 36991f110e0Safresh1 37091f110e0Safresh1 # eliminate irrelevant exclusions 37191f110e0Safresh1 if ($self->{exclusions}) { 37291f110e0Safresh1 my %seen; 37391f110e0Safresh1 @{ $self->{exclusions} } = grep { 37491f110e0Safresh1 (! defined $self->{minimum} or $_ >= $self->{minimum}) 37591f110e0Safresh1 and 37691f110e0Safresh1 (! defined $self->{maximum} or $_ <= $self->{maximum}) 37791f110e0Safresh1 and 37891f110e0Safresh1 ! $seen{$_}++ 37991f110e0Safresh1 } @{ $self->{exclusions} }; 38091f110e0Safresh1 } 38191f110e0Safresh1 38291f110e0Safresh1 return $self; 38391f110e0Safresh1 } 38491f110e0Safresh1 38591f110e0Safresh1 sub with_minimum { 38691f110e0Safresh1 my ($self, $minimum) = @_; 38791f110e0Safresh1 $self = $self->_clone; 38891f110e0Safresh1 38991f110e0Safresh1 if (defined (my $old_min = $self->{minimum})) { 39091f110e0Safresh1 $self->{minimum} = (sort { $b cmp $a } ($minimum, $old_min))[0]; 39191f110e0Safresh1 } else { 39291f110e0Safresh1 $self->{minimum} = $minimum; 39391f110e0Safresh1 } 39491f110e0Safresh1 39591f110e0Safresh1 return $self->_simplify; 39691f110e0Safresh1 } 39791f110e0Safresh1 39891f110e0Safresh1 sub with_maximum { 39991f110e0Safresh1 my ($self, $maximum) = @_; 40091f110e0Safresh1 $self = $self->_clone; 40191f110e0Safresh1 40291f110e0Safresh1 if (defined (my $old_max = $self->{maximum})) { 40391f110e0Safresh1 $self->{maximum} = (sort { $a cmp $b } ($maximum, $old_max))[0]; 40491f110e0Safresh1 } else { 40591f110e0Safresh1 $self->{maximum} = $maximum; 40691f110e0Safresh1 } 40791f110e0Safresh1 40891f110e0Safresh1 return $self->_simplify; 40991f110e0Safresh1 } 41091f110e0Safresh1 41191f110e0Safresh1 sub with_exclusion { 41291f110e0Safresh1 my ($self, $exclusion) = @_; 41391f110e0Safresh1 $self = $self->_clone; 41491f110e0Safresh1 41591f110e0Safresh1 push @{ $self->{exclusions} ||= [] }, $exclusion; 41691f110e0Safresh1 41791f110e0Safresh1 return $self->_simplify; 41891f110e0Safresh1 } 41991f110e0Safresh1 42091f110e0Safresh1 sub _accepts { 42191f110e0Safresh1 my ($self, $version) = @_; 42291f110e0Safresh1 42391f110e0Safresh1 return if defined $self->{minimum} and $version < $self->{minimum}; 42491f110e0Safresh1 return if defined $self->{maximum} and $version > $self->{maximum}; 42591f110e0Safresh1 return if defined $self->{exclusions} 42691f110e0Safresh1 and grep { $version == $_ } @{ $self->{exclusions} }; 42791f110e0Safresh1 42891f110e0Safresh1 return 1; 42991f110e0Safresh1 } 43091f110e0Safresh1} 43191f110e0Safresh1 43291f110e0Safresh11; 43391f110e0Safresh1# vim: ts=2 sts=2 sw=2 et: 43491f110e0Safresh1 43591f110e0Safresh1__END__ 436*6fb12b70Safresh1 43791f110e0Safresh1=pod 43891f110e0Safresh1 439*6fb12b70Safresh1=encoding utf-8 440*6fb12b70Safresh1 44191f110e0Safresh1=head1 NAME 44291f110e0Safresh1 44391f110e0Safresh1CPAN::Meta::Requirements - a set of version requirements for a CPAN dist 44491f110e0Safresh1 44591f110e0Safresh1=head1 VERSION 44691f110e0Safresh1 447*6fb12b70Safresh1version 2.125 44891f110e0Safresh1 44991f110e0Safresh1=head1 SYNOPSIS 45091f110e0Safresh1 45191f110e0Safresh1 use CPAN::Meta::Requirements; 45291f110e0Safresh1 45391f110e0Safresh1 my $build_requires = CPAN::Meta::Requirements->new; 45491f110e0Safresh1 45591f110e0Safresh1 $build_requires->add_minimum('Library::Foo' => 1.208); 45691f110e0Safresh1 45791f110e0Safresh1 $build_requires->add_minimum('Library::Foo' => 2.602); 45891f110e0Safresh1 45991f110e0Safresh1 $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); 46091f110e0Safresh1 46191f110e0Safresh1 $METAyml->{build_requires} = $build_requires->as_string_hash; 46291f110e0Safresh1 46391f110e0Safresh1=head1 DESCRIPTION 46491f110e0Safresh1 46591f110e0Safresh1A CPAN::Meta::Requirements object models a set of version constraints like 46691f110e0Safresh1those specified in the F<META.yml> or F<META.json> files in CPAN distributions. 46791f110e0Safresh1It can be built up by adding more and more constraints, and it will reduce them 46891f110e0Safresh1to the simplest representation. 46991f110e0Safresh1 47091f110e0Safresh1Logically impossible constraints will be identified immediately by thrown 47191f110e0Safresh1exceptions. 47291f110e0Safresh1 47391f110e0Safresh1=head1 METHODS 47491f110e0Safresh1 47591f110e0Safresh1=head2 new 47691f110e0Safresh1 47791f110e0Safresh1 my $req = CPAN::Meta::Requirements->new; 47891f110e0Safresh1 47991f110e0Safresh1This returns a new CPAN::Meta::Requirements object. It takes an optional 48091f110e0Safresh1hash reference argument. The following keys are supported: 48191f110e0Safresh1 48291f110e0Safresh1=over 4 48391f110e0Safresh1 48491f110e0Safresh1=item * 48591f110e0Safresh1 48691f110e0Safresh1<bad_version_hook> -- if provided, when a version cannot be parsed into 48791f110e0Safresh1 48891f110e0Safresh1a version object, this code reference will be called with the invalid version 48991f110e0Safresh1string as an argument. It must return a valid version object. 49091f110e0Safresh1 49191f110e0Safresh1=back 49291f110e0Safresh1 49391f110e0Safresh1All other keys are ignored. 49491f110e0Safresh1 49591f110e0Safresh1=head2 add_minimum 49691f110e0Safresh1 49791f110e0Safresh1 $req->add_minimum( $module => $version ); 49891f110e0Safresh1 49991f110e0Safresh1This adds a new minimum version requirement. If the new requirement is 50091f110e0Safresh1redundant to the existing specification, this has no effect. 50191f110e0Safresh1 50291f110e0Safresh1Minimum requirements are inclusive. C<$version> is required, along with any 50391f110e0Safresh1greater version number. 50491f110e0Safresh1 50591f110e0Safresh1This method returns the requirements object. 50691f110e0Safresh1 50791f110e0Safresh1=head2 add_maximum 50891f110e0Safresh1 50991f110e0Safresh1 $req->add_maximum( $module => $version ); 51091f110e0Safresh1 51191f110e0Safresh1This adds a new maximum version requirement. If the new requirement is 51291f110e0Safresh1redundant to the existing specification, this has no effect. 51391f110e0Safresh1 51491f110e0Safresh1Maximum requirements are inclusive. No version strictly greater than the given 51591f110e0Safresh1version is allowed. 51691f110e0Safresh1 51791f110e0Safresh1This method returns the requirements object. 51891f110e0Safresh1 51991f110e0Safresh1=head2 add_exclusion 52091f110e0Safresh1 52191f110e0Safresh1 $req->add_exclusion( $module => $version ); 52291f110e0Safresh1 52391f110e0Safresh1This adds a new excluded version. For example, you might use these three 52491f110e0Safresh1method calls: 52591f110e0Safresh1 52691f110e0Safresh1 $req->add_minimum( $module => '1.00' ); 52791f110e0Safresh1 $req->add_maximum( $module => '1.82' ); 52891f110e0Safresh1 52991f110e0Safresh1 $req->add_exclusion( $module => '1.75' ); 53091f110e0Safresh1 53191f110e0Safresh1Any version between 1.00 and 1.82 inclusive would be acceptable, except for 53291f110e0Safresh11.75. 53391f110e0Safresh1 53491f110e0Safresh1This method returns the requirements object. 53591f110e0Safresh1 53691f110e0Safresh1=head2 exact_version 53791f110e0Safresh1 53891f110e0Safresh1 $req->exact_version( $module => $version ); 53991f110e0Safresh1 54091f110e0Safresh1This sets the version required for the given module to I<exactly> the given 54191f110e0Safresh1version. No other version would be considered acceptable. 54291f110e0Safresh1 54391f110e0Safresh1This method returns the requirements object. 54491f110e0Safresh1 54591f110e0Safresh1=head2 add_requirements 54691f110e0Safresh1 54791f110e0Safresh1 $req->add_requirements( $another_req_object ); 54891f110e0Safresh1 54991f110e0Safresh1This method adds all the requirements in the given CPAN::Meta::Requirements object 55091f110e0Safresh1to the requirements object on which it was called. If there are any conflicts, 55191f110e0Safresh1an exception is thrown. 55291f110e0Safresh1 55391f110e0Safresh1This method returns the requirements object. 55491f110e0Safresh1 55591f110e0Safresh1=head2 accepts_module 55691f110e0Safresh1 55791f110e0Safresh1 my $bool = $req->accepts_modules($module => $version); 55891f110e0Safresh1 55991f110e0Safresh1Given an module and version, this method returns true if the version 56091f110e0Safresh1specification for the module accepts the provided version. In other words, 56191f110e0Safresh1given: 56291f110e0Safresh1 56391f110e0Safresh1 Module => '>= 1.00, < 2.00' 56491f110e0Safresh1 56591f110e0Safresh1We will accept 1.00 and 1.75 but not 0.50 or 2.00. 56691f110e0Safresh1 56791f110e0Safresh1For modules that do not appear in the requirements, this method will return 56891f110e0Safresh1true. 56991f110e0Safresh1 57091f110e0Safresh1=head2 clear_requirement 57191f110e0Safresh1 57291f110e0Safresh1 $req->clear_requirement( $module ); 57391f110e0Safresh1 57491f110e0Safresh1This removes the requirement for a given module from the object. 57591f110e0Safresh1 57691f110e0Safresh1This method returns the requirements object. 57791f110e0Safresh1 57891f110e0Safresh1=head2 requirements_for_module 57991f110e0Safresh1 58091f110e0Safresh1 $req->requirements_for_module( $module ); 58191f110e0Safresh1 58291f110e0Safresh1This returns a string containing the version requirements for a given module in 58391f110e0Safresh1the format described in L<CPAN::Meta::Spec> or undef if the given module has no 58491f110e0Safresh1requirements. This should only be used for informational purposes such as error 58591f110e0Safresh1messages and should not be interpreted or used for comparison (see 58691f110e0Safresh1L</accepts_module> instead.) 58791f110e0Safresh1 58891f110e0Safresh1=head2 required_modules 58991f110e0Safresh1 59091f110e0Safresh1This method returns a list of all the modules for which requirements have been 59191f110e0Safresh1specified. 59291f110e0Safresh1 59391f110e0Safresh1=head2 clone 59491f110e0Safresh1 59591f110e0Safresh1 $req->clone; 59691f110e0Safresh1 59791f110e0Safresh1This method returns a clone of the invocant. The clone and the original object 59891f110e0Safresh1can then be changed independent of one another. 59991f110e0Safresh1 60091f110e0Safresh1=head2 is_simple 60191f110e0Safresh1 60291f110e0Safresh1This method returns true if and only if all requirements are inclusive minimums 60391f110e0Safresh1-- that is, if their string expression is just the version number. 60491f110e0Safresh1 60591f110e0Safresh1=head2 is_finalized 60691f110e0Safresh1 60791f110e0Safresh1This method returns true if the requirements have been finalized by having the 60891f110e0Safresh1C<finalize> method called on them. 60991f110e0Safresh1 61091f110e0Safresh1=head2 finalize 61191f110e0Safresh1 61291f110e0Safresh1This method marks the requirements finalized. Subsequent attempts to change 61391f110e0Safresh1the requirements will be fatal, I<if> they would result in a change. If they 61491f110e0Safresh1would not alter the requirements, they have no effect. 61591f110e0Safresh1 61691f110e0Safresh1If a finalized set of requirements is cloned, the cloned requirements are not 61791f110e0Safresh1also finalized. 61891f110e0Safresh1 61991f110e0Safresh1=head2 as_string_hash 62091f110e0Safresh1 62191f110e0Safresh1This returns a reference to a hash describing the requirements using the 62291f110e0Safresh1strings in the F<META.yml> specification. 62391f110e0Safresh1 62491f110e0Safresh1For example after the following program: 62591f110e0Safresh1 62691f110e0Safresh1 my $req = CPAN::Meta::Requirements->new; 62791f110e0Safresh1 62891f110e0Safresh1 $req->add_minimum('CPAN::Meta::Requirements' => 0.102); 62991f110e0Safresh1 63091f110e0Safresh1 $req->add_minimum('Library::Foo' => 1.208); 63191f110e0Safresh1 63291f110e0Safresh1 $req->add_maximum('Library::Foo' => 2.602); 63391f110e0Safresh1 63491f110e0Safresh1 $req->add_minimum('Module::Bar' => 'v1.2.3'); 63591f110e0Safresh1 63691f110e0Safresh1 $req->add_exclusion('Module::Bar' => 'v1.2.8'); 63791f110e0Safresh1 63891f110e0Safresh1 $req->exact_version('Xyzzy' => '6.01'); 63991f110e0Safresh1 64091f110e0Safresh1 my $hashref = $req->as_string_hash; 64191f110e0Safresh1 64291f110e0Safresh1C<$hashref> would contain: 64391f110e0Safresh1 64491f110e0Safresh1 { 64591f110e0Safresh1 'CPAN::Meta::Requirements' => '0.102', 64691f110e0Safresh1 'Library::Foo' => '>= 1.208, <= 2.206', 64791f110e0Safresh1 'Module::Bar' => '>= v1.2.3, != v1.2.8', 64891f110e0Safresh1 'Xyzzy' => '== 6.01', 64991f110e0Safresh1 } 65091f110e0Safresh1 65191f110e0Safresh1=head2 add_string_requirement 65291f110e0Safresh1 65391f110e0Safresh1 $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); 65491f110e0Safresh1 65591f110e0Safresh1This method parses the passed in string and adds the appropriate requirement 65691f110e0Safresh1for the given module. It understands version ranges as described in the 65791f110e0Safresh1L<CPAN::Meta::Spec/Version Ranges>. For example: 65891f110e0Safresh1 65991f110e0Safresh1=over 4 66091f110e0Safresh1 66191f110e0Safresh1=item 1.3 66291f110e0Safresh1 66391f110e0Safresh1=item >= 1.3 66491f110e0Safresh1 66591f110e0Safresh1=item <= 1.3 66691f110e0Safresh1 66791f110e0Safresh1=item == 1.3 66891f110e0Safresh1 66991f110e0Safresh1=item != 1.3 67091f110e0Safresh1 67191f110e0Safresh1=item > 1.3 67291f110e0Safresh1 67391f110e0Safresh1=item < 1.3 67491f110e0Safresh1 67591f110e0Safresh1=item >= 1.3, != 1.5, <= 2.0 67691f110e0Safresh1 67791f110e0Safresh1A version number without an operator is equivalent to specifying a minimum 67891f110e0Safresh1(C<E<gt>=>). Extra whitespace is allowed. 67991f110e0Safresh1 68091f110e0Safresh1=back 68191f110e0Safresh1 68291f110e0Safresh1=head2 from_string_hash 68391f110e0Safresh1 68491f110e0Safresh1 my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); 68591f110e0Safresh1 68691f110e0Safresh1This is an alternate constructor for a CPAN::Meta::Requirements object. It takes 68791f110e0Safresh1a hash of module names and version requirement strings and returns a new 68891f110e0Safresh1CPAN::Meta::Requirements object. 68991f110e0Safresh1 69091f110e0Safresh1=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan 69191f110e0Safresh1 69291f110e0Safresh1=head1 SUPPORT 69391f110e0Safresh1 69491f110e0Safresh1=head2 Bugs / Feature Requests 69591f110e0Safresh1 69691f110e0Safresh1Please report any bugs or feature requests through the issue tracker 697*6fb12b70Safresh1at L<https://github.com/dagolden/CPAN-Meta-Requirements/issues>. 69891f110e0Safresh1You will be notified automatically of any progress on your issue. 69991f110e0Safresh1 70091f110e0Safresh1=head2 Source Code 70191f110e0Safresh1 70291f110e0Safresh1This is open source software. The code repository is available for 70391f110e0Safresh1public review and contribution under the terms of the license. 70491f110e0Safresh1 705*6fb12b70Safresh1L<https://github.com/dagolden/CPAN-Meta-Requirements> 70691f110e0Safresh1 707*6fb12b70Safresh1 git clone https://github.com/dagolden/CPAN-Meta-Requirements.git 70891f110e0Safresh1 70991f110e0Safresh1=head1 AUTHORS 71091f110e0Safresh1 71191f110e0Safresh1=over 4 71291f110e0Safresh1 71391f110e0Safresh1=item * 71491f110e0Safresh1 71591f110e0Safresh1David Golden <dagolden@cpan.org> 71691f110e0Safresh1 71791f110e0Safresh1=item * 71891f110e0Safresh1 71991f110e0Safresh1Ricardo Signes <rjbs@cpan.org> 72091f110e0Safresh1 72191f110e0Safresh1=back 72291f110e0Safresh1 72391f110e0Safresh1=head1 COPYRIGHT AND LICENSE 72491f110e0Safresh1 72591f110e0Safresh1This software is copyright (c) 2010 by David Golden and Ricardo Signes. 72691f110e0Safresh1 72791f110e0Safresh1This is free software; you can redistribute it and/or modify it under 72891f110e0Safresh1the same terms as the Perl 5 programming language system itself. 72991f110e0Safresh1 73091f110e0Safresh1=cut 731