diff options
author | Chris 'BinGOs' Williams <chris@bingosnet.co.uk> | 2011-12-30 22:37:19 +0000 |
---|---|---|
committer | Chris 'BinGOs' Williams <chris@bingosnet.co.uk> | 2011-12-30 23:44:10 +0000 |
commit | 2b2835753f61bf52dde32b99603e1546a1c6ee78 (patch) | |
tree | 288dc3f4db3c616983d9bcbf90b6b7feb3b2d219 /cpan | |
parent | 8c9e50e76ac4058a63c63a3d1714aa2556ca9393 (diff) | |
download | perl-2b2835753f61bf52dde32b99603e1546a1c6ee78.tar.gz |
Update CPAN-Meta to CPAN version 2.113640
[DELTA]
2.113640 2011-12-30 15:19:46 America/New_York
- Version::Requirements has now been merged as CPAN::Meta::Requirements,
rendering Version::Requirements itself redundant
Diffstat (limited to 'cpan')
-rw-r--r-- | cpan/CPAN-Meta/Changes | 5 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta.pm | 10 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm | 10 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm | 4 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/History.pm | 4 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm | 22 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Requirements.pm | 598 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm | 4 | ||||
-rw-r--r-- | cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm | 4 | ||||
-rw-r--r-- | cpan/CPAN-Meta/t/accepts.t | 29 | ||||
-rw-r--r-- | cpan/CPAN-Meta/t/basic.t | 224 | ||||
-rw-r--r-- | cpan/CPAN-Meta/t/finalize.t | 91 | ||||
-rw-r--r-- | cpan/CPAN-Meta/t/from-hash.t | 48 | ||||
-rw-r--r-- | cpan/CPAN-Meta/t/merge.t | 136 |
14 files changed, 1160 insertions, 29 deletions
diff --git a/cpan/CPAN-Meta/Changes b/cpan/CPAN-Meta/Changes index 873d41a1e0..eaf4098add 100644 --- a/cpan/CPAN-Meta/Changes +++ b/cpan/CPAN-Meta/Changes @@ -1,5 +1,10 @@ Revision history for CPAN-Meta +2.113640 2011-12-30 15:19:46 America/New_York + + - Version::Requirements has now been merged as CPAN::Meta::Requirements, + rendering Version::Requirements itself redundant + 2.112621 2011-09-19 12:15:16 America/New_York [BUGFIX] diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta.pm b/cpan/CPAN-Meta/lib/CPAN/Meta.pm index cfb1b259a9..eee0e6c04b 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta.pm @@ -2,7 +2,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION use Carp qw(carp croak); @@ -346,7 +346,7 @@ CPAN::Meta - the distribution metadata for a CPAN dist =head1 VERSION -version 2.112621 +version 2.113640 =head1 SYNOPSIS @@ -674,9 +674,9 @@ L<CPAN::Meta::Validator> =head2 Bugs / Feature Requests -Please report any bugs or feature requests by email to C<bug-cpan-meta at rt.cpan.org>, or through -the web interface at L<http://rt.cpan.org/Public/Dist/Display.html?Name=CPAN-Meta>. You will be automatically notified of any -progress on the request by the system. +Please report any bugs or feature requests through the issue tracker +at L<http://rt.cpan.org/Public/Dist/Display.html?Name=CPAN-Meta>. +You will be notified automatically of any progress on your issue. =head2 Source Code diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm index e468720fe6..09fe335fd7 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm @@ -2,7 +2,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta::Converter; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION use CPAN::Meta::Validator; @@ -429,9 +429,9 @@ sub _get_build_requires { my $test_h = _extract_prereqs($_[2]->{prereqs}, qw(test requires)) || {}; my $build_h = _extract_prereqs($_[2]->{prereqs}, qw(build requires)) || {}; - require Version::Requirements; - my $test_req = Version::Requirements->from_string_hash($test_h); - my $build_req = Version::Requirements->from_string_hash($build_h); + require CPAN::Meta::Requirements; + my $test_req = CPAN::Meta::Requirements->from_string_hash($test_h); + my $build_req = CPAN::Meta::Requirements->from_string_hash($build_h); $test_req->add_requirements($build_req)->as_string_hash; } @@ -1260,7 +1260,7 @@ CPAN::Meta::Converter - Convert CPAN distribution metadata structures =head1 VERSION -version 2.112621 +version 2.113640 =head1 SYNOPSIS diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm index 4002b748e2..7914d9a6df 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm @@ -2,7 +2,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta::Feature; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION use CPAN::Meta::Prereqs; @@ -42,7 +42,7 @@ CPAN::Meta::Feature - an optional feature provided by a CPAN distribution =head1 VERSION -version 2.112621 +version 2.113640 =head1 DESCRIPTION diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm index 1f2e9aeb19..cd3b9ddfd8 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm @@ -3,7 +3,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta::History; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION 1; @@ -20,7 +20,7 @@ CPAN::Meta::History - history of CPAN Meta Spec changes =head1 VERSION -version 2.112621 +version 2.113640 =head1 DESCRIPTION diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm index 04c5cf7c9c..1b97804f07 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm @@ -2,12 +2,12 @@ use 5.006; use strict; use warnings; package CPAN::Meta::Prereqs; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION use Carp qw(confess); use Scalar::Util qw(blessed); -use Version::Requirements 0.101020; # finalize +use CPAN::Meta::Requirements; sub __legal_phases { qw(configure build test runtime develop) } @@ -35,7 +35,7 @@ sub new { next TYPE unless keys %$spec; - $guts{prereqs}{$phase}{$type} = Version::Requirements->from_string_hash( + $guts{prereqs}{$phase}{$type} = CPAN::Meta::Requirements->from_string_hash( $spec ); } @@ -59,7 +59,7 @@ sub requirements_for { confess "requested requirements for unknown type: $type"; } - my $req = ($self->{prereqs}{$phase}{$type} ||= Version::Requirements->new); + my $req = ($self->{prereqs}{$phase}{$type} ||= CPAN::Meta::Requirements->new); $req->finalize if $self->is_finalized; @@ -78,7 +78,7 @@ sub with_merged_prereqs { for my $phase ($self->__legal_phases) { for my $type ($self->__legal_types) { - my $req = Version::Requirements->new; + my $req = CPAN::Meta::Requirements->new; for my $prereq (@prereq_objs) { my $this_req = $prereq->requirements_for($phase, $type); @@ -149,7 +149,7 @@ CPAN::Meta::Prereqs - a set of distribution prerequisites by phase and type =head1 VERSION -version 2.112621 +version 2.113640 =head1 DESCRIPTION @@ -189,10 +189,10 @@ dumping the whole set into a structure or string. my $requirements = $prereqs->requirements_for( $phase, $type ); -This method returns a L<Version::Requirements> object for the given phase/type -combination. If no prerequisites are registered for that combination, a new -Version::Requirements object will be returned, and it may be added to as -needed. +This method returns a L<CPAN::Meta::Requirements> object for the given +phase/type combination. If no prerequisites are registered for that +combination, a new CPAN::Meta::Requirements object will be returned, and it may +be added to as needed. If C<$phase> or C<$type> are undefined or otherwise invalid, an exception will be raised. @@ -215,7 +215,7 @@ will not alter them. This method returns a hashref containing structures suitable for dumping into a distmeta data structure. It is made up of hashes and strings, only; there will -be no Prereqs, Version::Requirements, or C<version> objects inside it. +be no Prereqs, CPAN::Meta::Requirements, or C<version> objects inside it. =head2 is_finalized diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Requirements.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Requirements.pm new file mode 100644 index 0000000000..dd2861e5ca --- /dev/null +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Requirements.pm @@ -0,0 +1,598 @@ +use strict; +use warnings; +package CPAN::Meta::Requirements; +our $VERSION = '2.113640'; # VERSION +# ABSTRACT: a set of version requirements for a CPAN dist + + +use Carp (); +use Scalar::Util (); +use version 0.77 (); # the ->parse method + + +sub new { + my ($class) = @_; + return bless {} => $class; +} + +sub _version_object { + my ($self, $version) = @_; + + $version = (! defined $version) ? version->parse(0) + : (! Scalar::Util::blessed($version)) ? version->parse($version) + : $version; + + return $version; +} + + +BEGIN { + for my $type (qw(minimum maximum exclusion exact_version)) { + my $method = "with_$type"; + my $to_add = $type eq 'exact_version' ? $type : "add_$type"; + + my $code = sub { + my ($self, $name, $version) = @_; + + $version = $self->_version_object( $version ); + + $self->__modify_entry_for($name, $method, $version); + + return $self; + }; + + no strict 'refs'; + *$to_add = $code; + } +} + + +sub add_requirements { + my ($self, $req) = @_; + + for my $module ($req->required_modules) { + my $modifiers = $req->__entry_for($module)->as_modifiers; + for my $modifier (@$modifiers) { + my ($method, @args) = @$modifier; + $self->$method($module => @args); + }; + } + + return $self; +} + + +sub accepts_module { + my ($self, $module, $version) = @_; + + $version = $self->_version_object( $version ); + + return 1 unless my $range = $self->__entry_for($module); + return $range->_accepts($version); +} + + +sub clear_requirement { + my ($self, $module) = @_; + + return $self unless $self->__entry_for($module); + + Carp::confess("can't clear requirements on finalized requirements") + if $self->is_finalized; + + delete $self->{requirements}{ $module }; + + return $self; +} + + +sub required_modules { keys %{ $_[0]{requirements} } } + + +sub clone { + my ($self) = @_; + my $new = (ref $self)->new; + + return $new->add_requirements($self); +} + +sub __entry_for { $_[0]{requirements}{ $_[1] } } + +sub __modify_entry_for { + my ($self, $name, $method, $version) = @_; + + my $fin = $self->is_finalized; + my $old = $self->__entry_for($name); + + Carp::confess("can't add new requirements to finalized requirements") + if $fin and not $old; + + my $new = ($old || 'CPAN::Meta::Requirements::_Range::Range') + ->$method($version); + + Carp::confess("can't modify finalized requirements") + if $fin and $old->as_string ne $new->as_string; + + $self->{requirements}{ $name } = $new; +} + + +sub is_simple { + my ($self) = @_; + for my $module ($self->required_modules) { + # XXX: This is a complete hack, but also entirely correct. + return if $self->__entry_for($module)->as_string =~ /\s/; + } + + return 1; +} + + +sub is_finalized { $_[0]{finalized} } + + +sub finalize { $_[0]{finalized} = 1 } + + +sub as_string_hash { + my ($self) = @_; + + my %hash = map {; $_ => $self->{requirements}{$_}->as_string } + $self->required_modules; + + return \%hash; +} + + +my %methods_for_op = ( + '==' => [ qw(exact_version) ], + '!=' => [ qw(add_exclusion) ], + '>=' => [ qw(add_minimum) ], + '<=' => [ qw(add_maximum) ], + '>' => [ qw(add_minimum add_exclusion) ], + '<' => [ qw(add_maximum add_exclusion) ], +); + +sub from_string_hash { + my ($class, $hash) = @_; + + my $self = $class->new; + + for my $module (keys %$hash) { + my @parts = split qr{\s*,\s*}, $hash->{ $module }; + for my $part (@parts) { + my ($op, $ver) = split /\s+/, $part, 2; + + if (! defined $ver) { + $self->add_minimum($module => $op); + } else { + Carp::confess("illegal requirement string: $hash->{ $module }") + unless my $methods = $methods_for_op{ $op }; + + $self->$_($module => $ver) for @$methods; + } + } + } + + return $self; +} + +############################################################## + +{ + package + CPAN::Meta::Requirements::_Range::Exact; + sub _new { bless { version => $_[1] } => $_[0] } + + sub _accepts { return $_[0]{version} == $_[1] } + + sub as_string { return "== $_[0]{version}" } + + sub as_modifiers { return [ [ exact_version => $_[0]{version} ] ] } + + sub _clone { + (ref $_[0])->_new( version->new( $_[0]{version} ) ) + } + + sub with_exact_version { + my ($self, $version) = @_; + + return $self->_clone if $self->_accepts($version); + + Carp::confess("illegal requirements: unequal exact version specified"); + } + + sub with_minimum { + my ($self, $minimum) = @_; + return $self->_clone if $self->{version} >= $minimum; + Carp::confess("illegal requirements: minimum above exact specification"); + } + + sub with_maximum { + my ($self, $maximum) = @_; + return $self->_clone if $self->{version} <= $maximum; + Carp::confess("illegal requirements: maximum below exact specification"); + } + + sub with_exclusion { + my ($self, $exclusion) = @_; + return $self->_clone unless $exclusion == $self->{version}; + Carp::confess("illegal requirements: excluded exact specification"); + } +} + +############################################################## + +{ + package + CPAN::Meta::Requirements::_Range::Range; + + sub _self { ref($_[0]) ? $_[0] : (bless { } => $_[0]) } + + sub _clone { + return (bless { } => $_[0]) unless ref $_[0]; + + my ($s) = @_; + my %guts = ( + (exists $s->{minimum} ? (minimum => version->new($s->{minimum})) : ()), + (exists $s->{maximum} ? (maximum => version->new($s->{maximum})) : ()), + + (exists $s->{exclusions} + ? (exclusions => [ map { version->new($_) } @{ $s->{exclusions} } ]) + : ()), + ); + + bless \%guts => ref($s); + } + + sub as_modifiers { + my ($self) = @_; + my @mods; + push @mods, [ add_minimum => $self->{minimum} ] if exists $self->{minimum}; + push @mods, [ add_maximum => $self->{maximum} ] if exists $self->{maximum}; + push @mods, map {; [ add_exclusion => $_ ] } @{$self->{exclusions} || []}; + return \@mods; + } + + sub as_string { + my ($self) = @_; + + return 0 if ! keys %$self; + + return "$self->{minimum}" if (keys %$self) == 1 and exists $self->{minimum}; + + my @exclusions = @{ $self->{exclusions} || [] }; + + my @parts; + + for my $pair ( + [ qw( >= > minimum ) ], + [ qw( <= < maximum ) ], + ) { + my ($op, $e_op, $k) = @$pair; + if (exists $self->{$k}) { + my @new_exclusions = grep { $_ != $self->{ $k } } @exclusions; + if (@new_exclusions == @exclusions) { + push @parts, "$op $self->{ $k }"; + } else { + push @parts, "$e_op $self->{ $k }"; + @exclusions = @new_exclusions; + } + } + } + + push @parts, map {; "!= $_" } @exclusions; + + return join q{, }, @parts; + } + + sub with_exact_version { + my ($self, $version) = @_; + $self = $self->_clone; + + Carp::confess("illegal requirements: exact specification outside of range") + unless $self->_accepts($version); + + return CPAN::Meta::Requirements::_Range::Exact->_new($version); + } + + sub _simplify { + my ($self) = @_; + + if (defined $self->{minimum} and defined $self->{maximum}) { + if ($self->{minimum} == $self->{maximum}) { + Carp::confess("illegal requirements: excluded all values") + if grep { $_ == $self->{minimum} } @{ $self->{exclusions} || [] }; + + return CPAN::Meta::Requirements::_Range::Exact->_new($self->{minimum}) + } + + Carp::confess("illegal requirements: minimum exceeds maximum") + if $self->{minimum} > $self->{maximum}; + } + + # eliminate irrelevant exclusions + if ($self->{exclusions}) { + my %seen; + @{ $self->{exclusions} } = grep { + (! defined $self->{minimum} or $_ >= $self->{minimum}) + and + (! defined $self->{maximum} or $_ <= $self->{maximum}) + and + ! $seen{$_}++ + } @{ $self->{exclusions} }; + } + + return $self; + } + + sub with_minimum { + my ($self, $minimum) = @_; + $self = $self->_clone; + + if (defined (my $old_min = $self->{minimum})) { + $self->{minimum} = (sort { $b cmp $a } ($minimum, $old_min))[0]; + } else { + $self->{minimum} = $minimum; + } + + return $self->_simplify; + } + + sub with_maximum { + my ($self, $maximum) = @_; + $self = $self->_clone; + + if (defined (my $old_max = $self->{maximum})) { + $self->{maximum} = (sort { $a cmp $b } ($maximum, $old_max))[0]; + } else { + $self->{maximum} = $maximum; + } + + return $self->_simplify; + } + + sub with_exclusion { + my ($self, $exclusion) = @_; + $self = $self->_clone; + + push @{ $self->{exclusions} ||= [] }, $exclusion; + + return $self->_simplify; + } + + sub _accepts { + my ($self, $version) = @_; + + return if defined $self->{minimum} and $version < $self->{minimum}; + return if defined $self->{maximum} and $version > $self->{maximum}; + return if defined $self->{exclusions} + and grep { $version == $_ } @{ $self->{exclusions} }; + + return 1; + } +} + +1; + +__END__ +=pod + +=head1 NAME + +CPAN::Meta::Requirements - a set of version requirements for a CPAN dist + +=head1 VERSION + +version 2.113640 + +=head1 SYNOPSIS + + use CPAN::Meta::Requirements; + + my $build_requires = CPAN::Meta::Requirements->new; + + $build_requires->add_minimum('Library::Foo' => 1.208); + + $build_requires->add_minimum('Library::Foo' => 2.602); + + $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); + + $METAyml->{build_requires} = $build_requires->as_string_hash; + +=head1 DESCRIPTION + +A CPAN::Meta::Requirements object models a set of version constraints like +those specified in the F<META.yml> or F<META.json> files in CPAN distributions. +It can be built up by adding more and more constraints, and it will reduce them +to the simplest representation. + +Logically impossible constraints will be identified immediately by thrown +exceptions. + +=head1 METHODS + +=head2 new + + my $req = CPAN::Meta::Requirements->new; + +This returns a new CPAN::Meta::Requirements object. It ignores any arguments +given. + +=head2 add_minimum + + $req->add_minimum( $module => $version ); + +This adds a new minimum version requirement. If the new requirement is +redundant to the existing specification, this has no effect. + +Minimum requirements are inclusive. C<$version> is required, along with any +greater version number. + +This method returns the requirements object. + +=head2 add_maximum + + $req->add_maximum( $module => $version ); + +This adds a new maximum version requirement. If the new requirement is +redundant to the existing specification, this has no effect. + +Maximum requirements are inclusive. No version strictly greater than the given +version is allowed. + +This method returns the requirements object. + +=head2 add_exclusion + + $req->add_exclusion( $module => $version ); + +This adds a new excluded version. For example, you might use these three +method calls: + + $req->add_minimum( $module => '1.00' ); + $req->add_maximum( $module => '1.82' ); + + $req->add_exclusion( $module => '1.75' ); + +Any version between 1.00 and 1.82 inclusive would be acceptable, except for +1.75. + +This method returns the requirements object. + +=head2 exact_version + + $req->exact_version( $module => $version ); + +This sets the version required for the given module to I<exactly> the given +version. No other version would be considered acceptable. + +This method returns the requirements object. + +=head2 add_requirements + + $req->add_requirements( $another_req_object ); + +This method adds all the requirements in the given CPAN::Meta::Requirements object +to the requirements object on which it was called. If there are any conflicts, +an exception is thrown. + +This method returns the requirements object. + +=head2 accepts_module + + my $bool = $req->accepts_modules($module => $version); + +Given an module and version, this method returns true if the version +specification for the module accepts the provided version. In other words, +given: + + Module => '>= 1.00, < 2.00' + +We will accept 1.00 and 1.75 but not 0.50 or 2.00. + +For modules that do not appear in the requirements, this method will return +true. + +=head2 clear_requirement + + $req->clear_requirement( $module ); + +This removes the requirement for a given module from the object. + +This method returns the requirements object. + +=head2 required_modules + +This method returns a list of all the modules for which requirements have been +specified. + +=head2 clone + + $req->clone; + +This method returns a clone of the invocant. The clone and the original object +can then be changed independent of one another. + +=head2 is_simple + +This method returns true if and only if all requirements are inclusive minimums +-- that is, if their string expression is just the version number. + +=head2 is_finalized + +This method returns true if the requirements have been finalized by having the +C<finalize> method called on them. + +=head2 finalize + +This method marks the requirements finalized. Subsequent attempts to change +the requirements will be fatal, I<if> they would result in a change. If they +would not alter the requirements, they have no effect. + +If a finalized set of requirements is cloned, the cloned requirements are not +also finalized. + +=head2 as_string_hash + +This returns a reference to a hash describing the requirements using the +strings in the F<META.yml> specification. + +For example after the following program: + + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('CPAN::Meta::Requirements' => 0.102); + + $req->add_minimum('Library::Foo' => 1.208); + + $req->add_maximum('Library::Foo' => 2.602); + + $req->add_minimum('Module::Bar' => 'v1.2.3'); + + $req->add_exclusion('Module::Bar' => 'v1.2.8'); + + $req->exact_version('Xyzzy' => '6.01'); + + my $hashref = $req->as_string_hash; + +C<$hashref> would contain: + + { + 'CPAN::Meta::Requirements' => '0.102', + 'Library::Foo' => '>= 1.208, <= 2.206', + 'Module::Bar' => '>= v1.2.3, != v1.2.8', + 'Xyzzy' => '== 6.01', + } + +=head2 from_string_hash + + my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); + +This is an alternate constructor for a CPAN::Meta::Requirements object. It takes +a hash of module names and version requirement strings and returns a new +CPAN::Meta::Requirements object. + +=head1 AUTHORS + +=over 4 + +=item * + +David Golden <dagolden@cpan.org> + +=item * + +Ricardo Signes <rjbs@cpan.org> + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2010 by David Golden and Ricardo Signes. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm index 09bfc23c15..d846c89e44 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm @@ -3,7 +3,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta::Spec; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION 1; @@ -20,7 +20,7 @@ CPAN::Meta::Spec - specification for CPAN distribution metadata =head1 VERSION -version 2.112621 +version 2.113640 =head1 SYNOPSIS diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm b/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm index c3d6906333..4b811e45bf 100644 --- a/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm +++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm @@ -2,7 +2,7 @@ use 5.006; use strict; use warnings; package CPAN::Meta::Validator; -our $VERSION = '2.112621'; # VERSION +our $VERSION = '2.113640'; # VERSION #--------------------------------------------------------------------------# @@ -838,7 +838,7 @@ CPAN::Meta::Validator - validate CPAN distribution metadata structures =head1 VERSION -version 2.112621 +version 2.113640 =head1 SYNOPSIS diff --git a/cpan/CPAN-Meta/t/accepts.t b/cpan/CPAN-Meta/t/accepts.t new file mode 100644 index 0000000000..3456394873 --- /dev/null +++ b/cpan/CPAN-Meta/t/accepts.t @@ -0,0 +1,29 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +{ + my $req = CPAN::Meta::Requirements->new->add_minimum(Foo => 1); + + ok( $req->accepts_module(Foo => 1)); + ok(! $req->accepts_module(Foo => 0)); +} + +{ + my $req = CPAN::Meta::Requirements->new->add_maximum(Foo => 1); + + ok( $req->accepts_module(Foo => 1)); + ok(! $req->accepts_module(Foo => 2)); +} + +{ + my $req = CPAN::Meta::Requirements->new->add_exclusion(Foo => 1); + + ok( $req->accepts_module(Foo => 0)); + ok(! $req->accepts_module(Foo => 1)); +} + +done_testing; diff --git a/cpan/CPAN-Meta/t/basic.t b/cpan/CPAN-Meta/t/basic.t new file mode 100644 index 0000000000..81061b5e0d --- /dev/null +++ b/cpan/CPAN-Meta/t/basic.t @@ -0,0 +1,224 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('Foo::Bar' => 10); + $req->add_minimum('Foo::Bar' => 0); + $req->add_minimum('Foo::Bar' => 2); + + $req->add_minimum('Foo::Baz' => version->declare('v1.2.3')); + + $req->add_minimum('Foo::Undef' => undef); + + is_deeply( + $req->as_string_hash, + { + 'Foo::Bar' => 10, + 'Foo::Baz' => 'v1.2.3', + 'Foo::Undef' => 0, + }, + "some basic minimums", + ); + + ok($req->is_simple, "just minimums? simple"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_maximum(Foo => 1); + is_deeply($req->as_string_hash, { Foo => '<= 1' }, "max only"); + + ok(! $req->is_simple, "maximums? not simple"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_exclusion(Foo => 1); + $req->add_exclusion(Foo => 2); + + # Why would you ever do this?? -- rjbs, 2010-02-20 + is_deeply($req->as_string_hash, { Foo => '!= 1, != 2' }, "excl only"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_maximum(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2', + }, + "min and max", + ); + + $req->add_maximum(Foo => 3); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2', + }, + "exclusions already outside range do not matter", + ); + + $req->add_exclusion(Foo => 1.5); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2, != 1.5', + }, + "exclusions", + ); + + $req->add_minimum(Foo => 1.6); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1.6, <= 2', + }, + "exclusions go away when made irrelevant", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_exclusion(Foo => 1); + $req->add_maximum(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '> 1, <= 2', + }, + "we can exclude an endpoint", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + + $req->add_exclusion(Foo => 1); + + dies_ok { $req->add_maximum(Foo => 1); } + qr/excluded all/, + "can't exclude all values" ; +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + dies_ok {$req->exact_version(Foo => 0.5); } + qr/outside of range/, + "can't add outside-range exact spec to range"; +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + dies_ok { $req->add_maximum(Foo => 0.5); } + qr/minimum exceeds maximum/, + "maximum must exceed (or equal) minimum"; + + $req = CPAN::Meta::Requirements->new; + $req->add_maximum(Foo => 0.5); + dies_ok { $req->add_minimum(Foo => 1); } + qr/minimum exceeds maximum/, + "maximum must exceed (or equal) minimum"; +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_maximum(Foo => 1); + + $req->add_maximum(Foo => 2); # ignored + $req->add_minimum(Foo => 0); # ignored + $req->add_exclusion(Foo => .5); # ignored + + is_deeply( + $req->as_string_hash, + { + 'Foo' => '== 1', + }, + "if min==max, becomes exact requirement", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + $req->add_exclusion(Foo => 0); + $req->add_maximum(Foo => 3); + $req->add_exclusion(Foo => 4); + + $req->add_exclusion(Foo => 2); + $req->add_exclusion(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 3, != 2', + }, + 'test exclusion-skipping', + ); +} + +sub foo_1 { + my $req = CPAN::Meta::Requirements->new; + $req->exact_version(Foo => 1); + return $req; +} + +{ + my $req = foo_1; + + $req->exact_version(Foo => 1); # ignored + + is_deeply($req->as_string_hash, { Foo => '== 1' }, "exact requirement"); + + dies_ok { $req->exact_version(Foo => 2); } + qr/unequal/, + "can't exactly specify differing versions" ; + + $req = foo_1; + $req->add_minimum(Foo => 0); # ignored + $req->add_maximum(Foo => 2); # ignored + + dies_ok { $req->add_maximum(Foo => 0); } qr/maximum below/, "max < fixed"; + + $req = foo_1; + dies_ok { $req->add_minimum(Foo => 2); } qr/minimum above/, "min > fixed"; + + $req = foo_1; + $req->add_exclusion(Foo => 8); # ignored + dies_ok { $req->add_exclusion(Foo => 1); } qr/excluded exact/, "!= && =="; +} + +done_testing; diff --git a/cpan/CPAN-Meta/t/finalize.t b/cpan/CPAN-Meta/t/finalize.t new file mode 100644 index 0000000000..58048b51d5 --- /dev/null +++ b/cpan/CPAN-Meta/t/finalize.t @@ -0,0 +1,91 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('Foo::Bar' => 10); + $req->add_minimum('Foo::Bar' => 0); + $req->add_minimum('Foo::Bar' => 2); + + $req->add_minimum('Foo::Baz' => version->declare('v1.2.3')); + + $req->add_minimum('Foo::Undef' => undef); + + my $want = { + 'Foo::Bar' => 10, + 'Foo::Baz' => 'v1.2.3', + 'Foo::Undef' => 0, + }; + + is_deeply( + $req->as_string_hash, + $want, + "some basic minimums", + ); + + $req->finalize; + + $req->add_minimum('Foo::Bar', 2); + + pass('we can add a Foo::Bar requirement with no effect post finalization'); + + dies_ok { $req->add_minimum('Foo::Bar', 12) } + qr{finalized req}, + "can't add a higher Foo::Bar after finalization"; + + dies_ok { $req->add_minimum('Foo::New', 0) } + qr{finalized req}, + "can't add a new module prereq after finalization"; + + dies_ok { $req->clear_requirement('Foo::Bar') } + qr{finalized req}, + "can't clear an existing prereq after finalization"; + + $req->clear_requirement('Bogus::Req'); + + pass('we can clear a prereq that was not set to begin with'); + + is_deeply( + $req->as_string_hash, + $want, + "none of our attempts to alter the object post-finalization worked", + ); + + my $cloned = $req->clone; + + $cloned->add_minimum('Foo::Bar', 12); + + is_deeply( + $cloned->as_string_hash, + { + %$want, + 'Foo::Bar' => 12, + }, + "we can alter a cloned V:R (finalization does not survive cloning)", + ); + + is_deeply( + $req->as_string_hash, + $want, + "...and original requirements are untouched", + ); +} + +done_testing; diff --git a/cpan/CPAN-Meta/t/from-hash.t b/cpan/CPAN-Meta/t/from-hash.t new file mode 100644 index 0000000000..369c45f694 --- /dev/null +++ b/cpan/CPAN-Meta/t/from-hash.t @@ -0,0 +1,48 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $string_hash = { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + }; + + my $req = CPAN::Meta::Requirements->from_string_hash($string_hash); + + is_deeply( + $req->as_string_hash, + $string_hash, + "we can load from a string hash", + ); +} + +{ + my $string_hash = { + Left => 10, + Shared => '= 2', + Right => 18, + }; + + dies_ok { CPAN::Meta::Requirements->from_string_hash($string_hash) } + qr/illegal/, + "we die when we can't understand a version spec"; +} + +done_testing; diff --git a/cpan/CPAN-Meta/t/merge.t b/cpan/CPAN-Meta/t/merge.t new file mode 100644 index 0000000000..a0513560e4 --- /dev/null +++ b/cpan/CPAN-Meta/t/merge.t @@ -0,0 +1,136 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_minimum(Left => 10); + $req_1->add_minimum(Shared => 2); + $req_1->add_exclusion(Shared => 7); + + my $req_2 = CPAN::Meta::Requirements->new; + $req_2->add_minimum(Shared => 1); + $req_2->add_maximum(Shared => 9); + $req_2->add_minimum(Right => 18); + + $req_1->add_requirements($req_2); + + is_deeply( + $req_1->as_string_hash, + { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + }, + "add requirements to an existing set of requirements", + ); +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_minimum(Left => 10); + $req_1->add_minimum(Shared => 2); + $req_1->add_exclusion(Shared => 7); + $req_1->exact_version(Exact => 8); + + my $req_2 = CPAN::Meta::Requirements->new; + $req_2->add_minimum(Shared => 1); + $req_2->add_maximum(Shared => 9); + $req_2->add_minimum(Right => 18); + $req_2->exact_version(Exact => 8); + + my $clone = $req_1->clone->add_requirements($req_2); + + is_deeply( + $req_1->as_string_hash, + { + Left => 10, + Shared => '>= 2, != 7', + Exact => '== 8', + }, + "clone/add_requirements does not affect lhs", + ); + + is_deeply( + $req_2->as_string_hash, + { + Shared => '>= 1, <= 9', + Right => 18, + Exact => '== 8', + }, + "clone/add_requirements does not affect rhs", + ); + + is_deeply( + $clone->as_string_hash, + { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + Exact => '== 8', + }, + "clone and add_requirements", + ); + + $clone->clear_requirement('Shared'); + + is_deeply( + $clone->as_string_hash, + { + Left => 10, + Right => 18, + Exact => '== 8', + }, + "cleared the shared requirement", + ); +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_maximum(Foo => 1); + + my $req_2 = $req_1->clone; + + is_deeply( + $req_2->as_string_hash, + { + 'Foo' => '<= 1', + }, + 'clone with only max', + ); +} + +{ + my $left = CPAN::Meta::Requirements->new; + $left->add_minimum(Foo => 0); + $left->add_minimum(Bar => 1); + + my $right = CPAN::Meta::Requirements->new; + $right->add_requirements($left); + + is_deeply( + $right->as_string_hash, + { + Foo => 0, + Bar => 1, + }, + "we do not lose 0-min reqs on merge", + ); +} + +done_testing; |