1use 5.006; # keep at v5.6 for CPAN.pm
2use strict;
3use warnings;
4package CPAN::Meta::Requirements;
5# ABSTRACT: a set of version requirements for a CPAN dist
6
7our $VERSION = '2.140';
8
9#pod =head1 SYNOPSIS
10#pod
11#pod   use CPAN::Meta::Requirements;
12#pod
13#pod   my $build_requires = CPAN::Meta::Requirements->new;
14#pod
15#pod   $build_requires->add_minimum('Library::Foo' => 1.208);
16#pod
17#pod   $build_requires->add_minimum('Library::Foo' => 2.602);
18#pod
19#pod   $build_requires->add_minimum('Module::Bar'  => 'v1.2.3');
20#pod
21#pod   $METAyml->{build_requires} = $build_requires->as_string_hash;
22#pod
23#pod =head1 DESCRIPTION
24#pod
25#pod A CPAN::Meta::Requirements object models a set of version constraints like
26#pod those specified in the F<META.yml> or F<META.json> files in CPAN distributions,
27#pod and as defined by L<CPAN::Meta::Spec>;
28#pod It can be built up by adding more and more constraints, and it will reduce them
29#pod to the simplest representation.
30#pod
31#pod Logically impossible constraints will be identified immediately by thrown
32#pod exceptions.
33#pod
34#pod =cut
35
36use Carp ();
37
38# To help ExtUtils::MakeMaker bootstrap CPAN::Meta::Requirements on perls
39# before 5.10, we fall back to the EUMM bundled compatibility version module if
40# that's the only thing available.  This shouldn't ever happen in a normal CPAN
41# install of CPAN::Meta::Requirements, as version.pm will be picked up from
42# prereqs and be available at runtime.
43
44BEGIN {
45  eval "use version ()"; ## no critic
46  if ( my $err = $@ ) {
47    eval "use ExtUtils::MakeMaker::version" or die $err; ## no critic
48  }
49}
50
51# Perl 5.10.0 didn't have "is_qv" in version.pm
52*_is_qv = version->can('is_qv') ? sub { $_[0]->is_qv } : sub { exists $_[0]->{qv} };
53
54# construct once, reuse many times
55my $V0 = version->new(0);
56
57#pod =method new
58#pod
59#pod   my $req = CPAN::Meta::Requirements->new;
60#pod
61#pod This returns a new CPAN::Meta::Requirements object.  It takes an optional
62#pod hash reference argument.  Currently, only one key is supported:
63#pod
64#pod =for :list
65#pod * C<bad_version_hook> -- if provided, when a version cannot be parsed into
66#pod   a version object, this code reference will be called with the invalid
67#pod   version string as first argument, and the module name as second
68#pod   argument.  It must return a valid version object.
69#pod
70#pod All other keys are ignored.
71#pod
72#pod =cut
73
74my @valid_options = qw( bad_version_hook );
75
76sub new {
77  my ($class, $options) = @_;
78  $options ||= {};
79  Carp::croak "Argument to $class\->new() must be a hash reference"
80    unless ref $options eq 'HASH';
81  my %self = map {; $_ => $options->{$_}} @valid_options;
82
83  return bless \%self => $class;
84}
85
86# from version::vpp
87sub _find_magic_vstring {
88  my $value = shift;
89  my $tvalue = '';
90  require B;
91  my $sv = B::svref_2object(\$value);
92  my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef;
93  while ( $magic ) {
94    if ( $magic->TYPE eq 'V' ) {
95      $tvalue = $magic->PTR;
96      $tvalue =~ s/^v?(.+)$/v$1/;
97      last;
98    }
99    else {
100      $magic = $magic->MOREMAGIC;
101    }
102  }
103  return $tvalue;
104}
105
106# safe if given an unblessed reference
107sub _isa_version {
108  UNIVERSAL::isa( $_[0], 'UNIVERSAL' ) && $_[0]->isa('version')
109}
110
111sub _version_object {
112  my ($self, $module, $version) = @_;
113
114  my ($vobj, $err);
115
116  if (not defined $version or (!ref($version) && $version eq '0')) {
117    return $V0;
118  }
119  elsif ( ref($version) eq 'version' || ( ref($version) && _isa_version($version) ) ) {
120    $vobj = $version;
121  }
122  else {
123    # hack around version::vpp not handling <3 character vstring literals
124    if ( $INC{'version/vpp.pm'} || $INC{'ExtUtils/MakeMaker/version/vpp.pm'} ) {
125      my $magic = _find_magic_vstring( $version );
126      $version = $magic if length $magic;
127    }
128    # pad to 3 characters if before 5.8.1 and appears to be a v-string
129    if ( $] < 5.008001 && $version !~ /\A[0-9]/ && substr($version,0,1) ne 'v' && length($version) < 3 ) {
130      $version .= "\0" x (3 - length($version));
131    }
132    eval {
133      local $SIG{__WARN__} = sub { die "Invalid version: $_[0]" };
134      # avoid specific segfault on some older version.pm versions
135      die "Invalid version: $version" if $version eq 'version';
136      $vobj = version->new($version);
137    };
138    if ( my $err = $@ ) {
139      my $hook = $self->{bad_version_hook};
140      $vobj = eval { $hook->($version, $module) }
141        if ref $hook eq 'CODE';
142      unless (eval { $vobj->isa("version") }) {
143        $err =~ s{ at .* line \d+.*$}{};
144        die "Can't convert '$version': $err";
145      }
146    }
147  }
148
149  # ensure no leading '.'
150  if ( $vobj =~ m{\A\.} ) {
151    $vobj = version->new("0$vobj");
152  }
153
154  # ensure normal v-string form
155  if ( _is_qv($vobj) ) {
156    $vobj = version->new($vobj->normal);
157  }
158
159  return $vobj;
160}
161
162#pod =method add_minimum
163#pod
164#pod   $req->add_minimum( $module => $version );
165#pod
166#pod This adds a new minimum version requirement.  If the new requirement is
167#pod redundant to the existing specification, this has no effect.
168#pod
169#pod Minimum requirements are inclusive.  C<$version> is required, along with any
170#pod greater version number.
171#pod
172#pod This method returns the requirements object.
173#pod
174#pod =method add_maximum
175#pod
176#pod   $req->add_maximum( $module => $version );
177#pod
178#pod This adds a new maximum version requirement.  If the new requirement is
179#pod redundant to the existing specification, this has no effect.
180#pod
181#pod Maximum requirements are inclusive.  No version strictly greater than the given
182#pod version is allowed.
183#pod
184#pod This method returns the requirements object.
185#pod
186#pod =method add_exclusion
187#pod
188#pod   $req->add_exclusion( $module => $version );
189#pod
190#pod This adds a new excluded version.  For example, you might use these three
191#pod method calls:
192#pod
193#pod   $req->add_minimum( $module => '1.00' );
194#pod   $req->add_maximum( $module => '1.82' );
195#pod
196#pod   $req->add_exclusion( $module => '1.75' );
197#pod
198#pod Any version between 1.00 and 1.82 inclusive would be acceptable, except for
199#pod 1.75.
200#pod
201#pod This method returns the requirements object.
202#pod
203#pod =method exact_version
204#pod
205#pod   $req->exact_version( $module => $version );
206#pod
207#pod This sets the version required for the given module to I<exactly> the given
208#pod version.  No other version would be considered acceptable.
209#pod
210#pod This method returns the requirements object.
211#pod
212#pod =cut
213
214BEGIN {
215  for my $type (qw(maximum exclusion exact_version)) {
216    my $method = "with_$type";
217    my $to_add = $type eq 'exact_version' ? $type : "add_$type";
218
219    my $code = sub {
220      my ($self, $name, $version) = @_;
221
222      $version = $self->_version_object( $name, $version );
223
224      $self->__modify_entry_for($name, $method, $version);
225
226      return $self;
227    };
228
229    no strict 'refs';
230    *$to_add = $code;
231  }
232}
233
234# add_minimum is optimized compared to generated subs above because
235# it is called frequently and with "0" or equivalent input
236sub add_minimum {
237  my ($self, $name, $version) = @_;
238
239  # stringify $version so that version->new("0.00")->stringify ne "0"
240  # which preserves the user's choice of "0.00" as the requirement
241  if (not defined $version or "$version" eq '0') {
242    return $self if $self->__entry_for($name);
243    Carp::confess("can't add new requirements to finalized requirements")
244      if $self->is_finalized;
245
246    $self->{requirements}{ $name } =
247      CPAN::Meta::Requirements::_Range::Range->with_minimum($V0, $name);
248  }
249  else {
250    $version = $self->_version_object( $name, $version );
251
252    $self->__modify_entry_for($name, 'with_minimum', $version);
253  }
254  return $self;
255}
256
257#pod =method add_requirements
258#pod
259#pod   $req->add_requirements( $another_req_object );
260#pod
261#pod This method adds all the requirements in the given CPAN::Meta::Requirements
262#pod object to the requirements object on which it was called.  If there are any
263#pod conflicts, an exception is thrown.
264#pod
265#pod This method returns the requirements object.
266#pod
267#pod =cut
268
269sub add_requirements {
270  my ($self, $req) = @_;
271
272  for my $module ($req->required_modules) {
273    my $modifiers = $req->__entry_for($module)->as_modifiers;
274    for my $modifier (@$modifiers) {
275      my ($method, @args) = @$modifier;
276      $self->$method($module => @args);
277    };
278  }
279
280  return $self;
281}
282
283#pod =method accepts_module
284#pod
285#pod   my $bool = $req->accepts_module($module => $version);
286#pod
287#pod Given an module and version, this method returns true if the version
288#pod specification for the module accepts the provided version.  In other words,
289#pod given:
290#pod
291#pod   Module => '>= 1.00, < 2.00'
292#pod
293#pod We will accept 1.00 and 1.75 but not 0.50 or 2.00.
294#pod
295#pod For modules that do not appear in the requirements, this method will return
296#pod true.
297#pod
298#pod =cut
299
300sub accepts_module {
301  my ($self, $module, $version) = @_;
302
303  $version = $self->_version_object( $module, $version );
304
305  return 1 unless my $range = $self->__entry_for($module);
306  return $range->_accepts($version);
307}
308
309#pod =method clear_requirement
310#pod
311#pod   $req->clear_requirement( $module );
312#pod
313#pod This removes the requirement for a given module from the object.
314#pod
315#pod This method returns the requirements object.
316#pod
317#pod =cut
318
319sub clear_requirement {
320  my ($self, $module) = @_;
321
322  return $self unless $self->__entry_for($module);
323
324  Carp::confess("can't clear requirements on finalized requirements")
325    if $self->is_finalized;
326
327  delete $self->{requirements}{ $module };
328
329  return $self;
330}
331
332#pod =method requirements_for_module
333#pod
334#pod   $req->requirements_for_module( $module );
335#pod
336#pod This returns a string containing the version requirements for a given module in
337#pod the format described in L<CPAN::Meta::Spec> or undef if the given module has no
338#pod requirements. This should only be used for informational purposes such as error
339#pod messages and should not be interpreted or used for comparison (see
340#pod L</accepts_module> instead).
341#pod
342#pod =cut
343
344sub requirements_for_module {
345  my ($self, $module) = @_;
346  my $entry = $self->__entry_for($module);
347  return unless $entry;
348  return $entry->as_string;
349}
350
351#pod =method structured_requirements_for_module
352#pod
353#pod   $req->structured_requirements_for_module( $module );
354#pod
355#pod This returns a data structure containing the version requirements for a given
356#pod module or undef if the given module has no requirements.  This should
357#pod not be used for version checks (see L</accepts_module> instead).
358#pod
359#pod Added in version 2.134.
360#pod
361#pod =cut
362
363sub structured_requirements_for_module {
364  my ($self, $module) = @_;
365  my $entry = $self->__entry_for($module);
366  return unless $entry;
367  return $entry->as_struct;
368}
369
370#pod =method required_modules
371#pod
372#pod This method returns a list of all the modules for which requirements have been
373#pod specified.
374#pod
375#pod =cut
376
377sub required_modules { keys %{ $_[0]{requirements} } }
378
379#pod =method clone
380#pod
381#pod   $req->clone;
382#pod
383#pod This method returns a clone of the invocant.  The clone and the original object
384#pod can then be changed independent of one another.
385#pod
386#pod =cut
387
388sub clone {
389  my ($self) = @_;
390  my $new = (ref $self)->new;
391
392  return $new->add_requirements($self);
393}
394
395sub __entry_for     { $_[0]{requirements}{ $_[1] } }
396
397sub __modify_entry_for {
398  my ($self, $name, $method, $version) = @_;
399
400  my $fin = $self->is_finalized;
401  my $old = $self->__entry_for($name);
402
403  Carp::confess("can't add new requirements to finalized requirements")
404    if $fin and not $old;
405
406  my $new = ($old || 'CPAN::Meta::Requirements::_Range::Range')
407          ->$method($version, $name);
408
409  Carp::confess("can't modify finalized requirements")
410    if $fin and $old->as_string ne $new->as_string;
411
412  $self->{requirements}{ $name } = $new;
413}
414
415#pod =method is_simple
416#pod
417#pod This method returns true if and only if all requirements are inclusive minimums
418#pod -- that is, if their string expression is just the version number.
419#pod
420#pod =cut
421
422sub is_simple {
423  my ($self) = @_;
424  for my $module ($self->required_modules) {
425    # XXX: This is a complete hack, but also entirely correct.
426    return if $self->__entry_for($module)->as_string =~ /\s/;
427  }
428
429  return 1;
430}
431
432#pod =method is_finalized
433#pod
434#pod This method returns true if the requirements have been finalized by having the
435#pod C<finalize> method called on them.
436#pod
437#pod =cut
438
439sub is_finalized { $_[0]{finalized} }
440
441#pod =method finalize
442#pod
443#pod This method marks the requirements finalized.  Subsequent attempts to change
444#pod the requirements will be fatal, I<if> they would result in a change.  If they
445#pod would not alter the requirements, they have no effect.
446#pod
447#pod If a finalized set of requirements is cloned, the cloned requirements are not
448#pod also finalized.
449#pod
450#pod =cut
451
452sub finalize { $_[0]{finalized} = 1 }
453
454#pod =method as_string_hash
455#pod
456#pod This returns a reference to a hash describing the requirements using the
457#pod strings in the L<CPAN::Meta::Spec> specification.
458#pod
459#pod For example after the following program:
460#pod
461#pod   my $req = CPAN::Meta::Requirements->new;
462#pod
463#pod   $req->add_minimum('CPAN::Meta::Requirements' => 0.102);
464#pod
465#pod   $req->add_minimum('Library::Foo' => 1.208);
466#pod
467#pod   $req->add_maximum('Library::Foo' => 2.602);
468#pod
469#pod   $req->add_minimum('Module::Bar'  => 'v1.2.3');
470#pod
471#pod   $req->add_exclusion('Module::Bar'  => 'v1.2.8');
472#pod
473#pod   $req->exact_version('Xyzzy'  => '6.01');
474#pod
475#pod   my $hashref = $req->as_string_hash;
476#pod
477#pod C<$hashref> would contain:
478#pod
479#pod   {
480#pod     'CPAN::Meta::Requirements' => '0.102',
481#pod     'Library::Foo' => '>= 1.208, <= 2.206',
482#pod     'Module::Bar'  => '>= v1.2.3, != v1.2.8',
483#pod     'Xyzzy'        => '== 6.01',
484#pod   }
485#pod
486#pod =cut
487
488sub as_string_hash {
489  my ($self) = @_;
490
491  my %hash = map {; $_ => $self->{requirements}{$_}->as_string }
492             $self->required_modules;
493
494  return \%hash;
495}
496
497#pod =method add_string_requirement
498#pod
499#pod   $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206');
500#pod   $req->add_string_requirement('Library::Foo' => v1.208);
501#pod
502#pod This method parses the passed in string and adds the appropriate requirement
503#pod for the given module.  A version can be a Perl "v-string".  It understands
504#pod version ranges as described in the L<CPAN::Meta::Spec/Version Ranges>. For
505#pod example:
506#pod
507#pod =over 4
508#pod
509#pod =item 1.3
510#pod
511#pod =item >= 1.3
512#pod
513#pod =item <= 1.3
514#pod
515#pod =item == 1.3
516#pod
517#pod =item != 1.3
518#pod
519#pod =item > 1.3
520#pod
521#pod =item < 1.3
522#pod
523#pod =item >= 1.3, != 1.5, <= 2.0
524#pod
525#pod A version number without an operator is equivalent to specifying a minimum
526#pod (C<E<gt>=>).  Extra whitespace is allowed.
527#pod
528#pod =back
529#pod
530#pod =cut
531
532my %methods_for_op = (
533  '==' => [ qw(exact_version) ],
534  '!=' => [ qw(add_exclusion) ],
535  '>=' => [ qw(add_minimum)   ],
536  '<=' => [ qw(add_maximum)   ],
537  '>'  => [ qw(add_minimum add_exclusion) ],
538  '<'  => [ qw(add_maximum add_exclusion) ],
539);
540
541sub add_string_requirement {
542  my ($self, $module, $req) = @_;
543
544  unless ( defined $req && length $req ) {
545    $req = 0;
546    $self->_blank_carp($module);
547  }
548
549  my $magic = _find_magic_vstring( $req );
550  if (length $magic) {
551    $self->add_minimum($module => $magic);
552    return;
553  }
554
555  my @parts = split qr{\s*,\s*}, $req;
556
557  for my $part (@parts) {
558    my ($op, $ver) = $part =~ m{\A\s*(==|>=|>|<=|<|!=)\s*(.*)\z};
559
560    if (! defined $op) {
561      $self->add_minimum($module => $part);
562    } else {
563      Carp::confess("illegal requirement string: $req")
564        unless my $methods = $methods_for_op{ $op };
565
566      $self->$_($module => $ver) for @$methods;
567    }
568  }
569}
570
571#pod =method from_string_hash
572#pod
573#pod   my $req = CPAN::Meta::Requirements->from_string_hash( \%hash );
574#pod   my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts );
575#pod
576#pod This is an alternate constructor for a CPAN::Meta::Requirements
577#pod object. It takes a hash of module names and version requirement
578#pod strings and returns a new CPAN::Meta::Requirements object. As with
579#pod add_string_requirement, a version can be a Perl "v-string". Optionally,
580#pod you can supply a hash-reference of options, exactly as with the L</new>
581#pod method.
582#pod
583#pod =cut
584
585sub _blank_carp {
586  my ($self, $module) = @_;
587  Carp::carp("Undefined requirement for $module treated as '0'");
588}
589
590sub from_string_hash {
591  my ($class, $hash, $options) = @_;
592
593  my $self = $class->new($options);
594
595  for my $module (keys %$hash) {
596    my $req = $hash->{$module};
597    unless ( defined $req && length $req ) {
598      $req = 0;
599      $class->_blank_carp($module);
600    }
601    $self->add_string_requirement($module, $req);
602  }
603
604  return $self;
605}
606
607##############################################################
608
609{
610  package
611    CPAN::Meta::Requirements::_Range::Exact;
612  sub _new     { bless { version => $_[1] } => $_[0] }
613
614  sub _accepts { return $_[0]{version} == $_[1] }
615
616  sub as_string { return "== $_[0]{version}" }
617
618  sub as_struct { return [ [ '==', "$_[0]{version}" ] ] }
619
620  sub as_modifiers { return [ [ exact_version => $_[0]{version} ] ] }
621
622  sub _reject_requirements {
623    my ($self, $module, $error) = @_;
624    Carp::confess("illegal requirements for $module: $error")
625  }
626
627  sub _clone {
628    (ref $_[0])->_new( version->new( $_[0]{version} ) )
629  }
630
631  sub with_exact_version {
632    my ($self, $version, $module) = @_;
633    $module = 'module' unless defined $module;
634
635    return $self->_clone if $self->_accepts($version);
636
637    $self->_reject_requirements(
638      $module,
639      "can't be exactly $version when exact requirement is already $self->{version}",
640    );
641  }
642
643  sub with_minimum {
644    my ($self, $minimum, $module) = @_;
645    $module = 'module' unless defined $module;
646
647    return $self->_clone if $self->{version} >= $minimum;
648    $self->_reject_requirements(
649      $module,
650      "minimum $minimum exceeds exact specification $self->{version}",
651    );
652  }
653
654  sub with_maximum {
655    my ($self, $maximum, $module) = @_;
656    $module = 'module' unless defined $module;
657
658    return $self->_clone if $self->{version} <= $maximum;
659    $self->_reject_requirements(
660      $module,
661      "maximum $maximum below exact specification $self->{version}",
662    );
663  }
664
665  sub with_exclusion {
666    my ($self, $exclusion, $module) = @_;
667    $module = 'module' unless defined $module;
668
669    return $self->_clone unless $exclusion == $self->{version};
670    $self->_reject_requirements(
671      $module,
672      "tried to exclude $exclusion, which is already exactly specified",
673    );
674  }
675}
676
677##############################################################
678
679{
680  package
681    CPAN::Meta::Requirements::_Range::Range;
682
683  sub _self { ref($_[0]) ? $_[0] : (bless { } => $_[0]) }
684
685  sub _clone {
686    return (bless { } => $_[0]) unless ref $_[0];
687
688    my ($s) = @_;
689    my %guts = (
690      (exists $s->{minimum} ? (minimum => version->new($s->{minimum})) : ()),
691      (exists $s->{maximum} ? (maximum => version->new($s->{maximum})) : ()),
692
693      (exists $s->{exclusions}
694        ? (exclusions => [ map { version->new($_) } @{ $s->{exclusions} } ])
695        : ()),
696    );
697
698    bless \%guts => ref($s);
699  }
700
701  sub as_modifiers {
702    my ($self) = @_;
703    my @mods;
704    push @mods, [ add_minimum => $self->{minimum} ] if exists $self->{minimum};
705    push @mods, [ add_maximum => $self->{maximum} ] if exists $self->{maximum};
706    push @mods, map {; [ add_exclusion => $_ ] } @{$self->{exclusions} || []};
707    return \@mods;
708  }
709
710  sub as_struct {
711    my ($self) = @_;
712
713    return 0 if ! keys %$self;
714
715    my @exclusions = @{ $self->{exclusions} || [] };
716
717    my @parts;
718
719    for my $tuple (
720      [ qw( >= > minimum ) ],
721      [ qw( <= < maximum ) ],
722    ) {
723      my ($op, $e_op, $k) = @$tuple;
724      if (exists $self->{$k}) {
725        my @new_exclusions = grep { $_ != $self->{ $k } } @exclusions;
726        if (@new_exclusions == @exclusions) {
727          push @parts, [ $op, "$self->{ $k }" ];
728        } else {
729          push @parts, [ $e_op, "$self->{ $k }" ];
730          @exclusions = @new_exclusions;
731        }
732      }
733    }
734
735    push @parts, map {; [ "!=", "$_" ] } @exclusions;
736
737    return \@parts;
738  }
739
740  sub as_string {
741    my ($self) = @_;
742
743    my @parts = @{ $self->as_struct };
744
745    return $parts[0][1] if @parts == 1 and $parts[0][0] eq '>=';
746
747    return join q{, }, map {; join q{ }, @$_ } @parts;
748  }
749
750  sub _reject_requirements {
751    my ($self, $module, $error) = @_;
752    Carp::confess("illegal requirements for $module: $error")
753  }
754
755  sub with_exact_version {
756    my ($self, $version, $module) = @_;
757    $module = 'module' unless defined $module;
758    $self = $self->_clone;
759
760    unless ($self->_accepts($version)) {
761      $self->_reject_requirements(
762        $module,
763        "exact specification $version outside of range " . $self->as_string
764      );
765    }
766
767    return CPAN::Meta::Requirements::_Range::Exact->_new($version);
768  }
769
770  sub _simplify {
771    my ($self, $module) = @_;
772
773    if (defined $self->{minimum} and defined $self->{maximum}) {
774      if ($self->{minimum} == $self->{maximum}) {
775        if (grep { $_ == $self->{minimum} } @{ $self->{exclusions} || [] }) {
776          $self->_reject_requirements(
777            $module,
778            "minimum and maximum are both $self->{minimum}, which is excluded",
779          );
780        }
781
782        return CPAN::Meta::Requirements::_Range::Exact->_new($self->{minimum})
783      }
784
785      if ($self->{minimum} > $self->{maximum}) {
786        $self->_reject_requirements(
787          $module,
788          "minimum $self->{minimum} exceeds maximum $self->{maximum}",
789        );
790      }
791    }
792
793    # eliminate irrelevant exclusions
794    if ($self->{exclusions}) {
795      my %seen;
796      @{ $self->{exclusions} } = grep {
797        (! defined $self->{minimum} or $_ >= $self->{minimum})
798        and
799        (! defined $self->{maximum} or $_ <= $self->{maximum})
800        and
801        ! $seen{$_}++
802      } @{ $self->{exclusions} };
803    }
804
805    return $self;
806  }
807
808  sub with_minimum {
809    my ($self, $minimum, $module) = @_;
810    $module = 'module' unless defined $module;
811    $self = $self->_clone;
812
813    if (defined (my $old_min = $self->{minimum})) {
814      $self->{minimum} = (sort { $b cmp $a } ($minimum, $old_min))[0];
815    } else {
816      $self->{minimum} = $minimum;
817    }
818
819    return $self->_simplify($module);
820  }
821
822  sub with_maximum {
823    my ($self, $maximum, $module) = @_;
824    $module = 'module' unless defined $module;
825    $self = $self->_clone;
826
827    if (defined (my $old_max = $self->{maximum})) {
828      $self->{maximum} = (sort { $a cmp $b } ($maximum, $old_max))[0];
829    } else {
830      $self->{maximum} = $maximum;
831    }
832
833    return $self->_simplify($module);
834  }
835
836  sub with_exclusion {
837    my ($self, $exclusion, $module) = @_;
838    $module = 'module' unless defined $module;
839    $self = $self->_clone;
840
841    push @{ $self->{exclusions} ||= [] }, $exclusion;
842
843    return $self->_simplify($module);
844  }
845
846  sub _accepts {
847    my ($self, $version) = @_;
848
849    return if defined $self->{minimum} and $version < $self->{minimum};
850    return if defined $self->{maximum} and $version > $self->{maximum};
851    return if defined $self->{exclusions}
852          and grep { $version == $_ } @{ $self->{exclusions} };
853
854    return 1;
855  }
856}
857
8581;
859# vim: ts=2 sts=2 sw=2 et:
860
861__END__
862
863=pod
864
865=encoding UTF-8
866
867=head1 NAME
868
869CPAN::Meta::Requirements - a set of version requirements for a CPAN dist
870
871=head1 VERSION
872
873version 2.140
874
875=head1 SYNOPSIS
876
877  use CPAN::Meta::Requirements;
878
879  my $build_requires = CPAN::Meta::Requirements->new;
880
881  $build_requires->add_minimum('Library::Foo' => 1.208);
882
883  $build_requires->add_minimum('Library::Foo' => 2.602);
884
885  $build_requires->add_minimum('Module::Bar'  => 'v1.2.3');
886
887  $METAyml->{build_requires} = $build_requires->as_string_hash;
888
889=head1 DESCRIPTION
890
891A CPAN::Meta::Requirements object models a set of version constraints like
892those specified in the F<META.yml> or F<META.json> files in CPAN distributions,
893and as defined by L<CPAN::Meta::Spec>;
894It can be built up by adding more and more constraints, and it will reduce them
895to the simplest representation.
896
897Logically impossible constraints will be identified immediately by thrown
898exceptions.
899
900=head1 METHODS
901
902=head2 new
903
904  my $req = CPAN::Meta::Requirements->new;
905
906This returns a new CPAN::Meta::Requirements object.  It takes an optional
907hash reference argument.  Currently, only one key is supported:
908
909=over 4
910
911=item *
912
913C<bad_version_hook> -- if provided, when a version cannot be parsed into a version object, this code reference will be called with the invalid version string as first argument, and the module name as second argument.  It must return a valid version object.
914
915=back
916
917All other keys are ignored.
918
919=head2 add_minimum
920
921  $req->add_minimum( $module => $version );
922
923This adds a new minimum version requirement.  If the new requirement is
924redundant to the existing specification, this has no effect.
925
926Minimum requirements are inclusive.  C<$version> is required, along with any
927greater version number.
928
929This method returns the requirements object.
930
931=head2 add_maximum
932
933  $req->add_maximum( $module => $version );
934
935This adds a new maximum version requirement.  If the new requirement is
936redundant to the existing specification, this has no effect.
937
938Maximum requirements are inclusive.  No version strictly greater than the given
939version is allowed.
940
941This method returns the requirements object.
942
943=head2 add_exclusion
944
945  $req->add_exclusion( $module => $version );
946
947This adds a new excluded version.  For example, you might use these three
948method calls:
949
950  $req->add_minimum( $module => '1.00' );
951  $req->add_maximum( $module => '1.82' );
952
953  $req->add_exclusion( $module => '1.75' );
954
955Any version between 1.00 and 1.82 inclusive would be acceptable, except for
9561.75.
957
958This method returns the requirements object.
959
960=head2 exact_version
961
962  $req->exact_version( $module => $version );
963
964This sets the version required for the given module to I<exactly> the given
965version.  No other version would be considered acceptable.
966
967This method returns the requirements object.
968
969=head2 add_requirements
970
971  $req->add_requirements( $another_req_object );
972
973This method adds all the requirements in the given CPAN::Meta::Requirements
974object to the requirements object on which it was called.  If there are any
975conflicts, an exception is thrown.
976
977This method returns the requirements object.
978
979=head2 accepts_module
980
981  my $bool = $req->accepts_module($module => $version);
982
983Given an module and version, this method returns true if the version
984specification for the module accepts the provided version.  In other words,
985given:
986
987  Module => '>= 1.00, < 2.00'
988
989We will accept 1.00 and 1.75 but not 0.50 or 2.00.
990
991For modules that do not appear in the requirements, this method will return
992true.
993
994=head2 clear_requirement
995
996  $req->clear_requirement( $module );
997
998This removes the requirement for a given module from the object.
999
1000This method returns the requirements object.
1001
1002=head2 requirements_for_module
1003
1004  $req->requirements_for_module( $module );
1005
1006This returns a string containing the version requirements for a given module in
1007the format described in L<CPAN::Meta::Spec> or undef if the given module has no
1008requirements. This should only be used for informational purposes such as error
1009messages and should not be interpreted or used for comparison (see
1010L</accepts_module> instead).
1011
1012=head2 structured_requirements_for_module
1013
1014  $req->structured_requirements_for_module( $module );
1015
1016This returns a data structure containing the version requirements for a given
1017module or undef if the given module has no requirements.  This should
1018not be used for version checks (see L</accepts_module> instead).
1019
1020Added in version 2.134.
1021
1022=head2 required_modules
1023
1024This method returns a list of all the modules for which requirements have been
1025specified.
1026
1027=head2 clone
1028
1029  $req->clone;
1030
1031This method returns a clone of the invocant.  The clone and the original object
1032can then be changed independent of one another.
1033
1034=head2 is_simple
1035
1036This method returns true if and only if all requirements are inclusive minimums
1037-- that is, if their string expression is just the version number.
1038
1039=head2 is_finalized
1040
1041This method returns true if the requirements have been finalized by having the
1042C<finalize> method called on them.
1043
1044=head2 finalize
1045
1046This method marks the requirements finalized.  Subsequent attempts to change
1047the requirements will be fatal, I<if> they would result in a change.  If they
1048would not alter the requirements, they have no effect.
1049
1050If a finalized set of requirements is cloned, the cloned requirements are not
1051also finalized.
1052
1053=head2 as_string_hash
1054
1055This returns a reference to a hash describing the requirements using the
1056strings in the L<CPAN::Meta::Spec> specification.
1057
1058For example after the following program:
1059
1060  my $req = CPAN::Meta::Requirements->new;
1061
1062  $req->add_minimum('CPAN::Meta::Requirements' => 0.102);
1063
1064  $req->add_minimum('Library::Foo' => 1.208);
1065
1066  $req->add_maximum('Library::Foo' => 2.602);
1067
1068  $req->add_minimum('Module::Bar'  => 'v1.2.3');
1069
1070  $req->add_exclusion('Module::Bar'  => 'v1.2.8');
1071
1072  $req->exact_version('Xyzzy'  => '6.01');
1073
1074  my $hashref = $req->as_string_hash;
1075
1076C<$hashref> would contain:
1077
1078  {
1079    'CPAN::Meta::Requirements' => '0.102',
1080    'Library::Foo' => '>= 1.208, <= 2.206',
1081    'Module::Bar'  => '>= v1.2.3, != v1.2.8',
1082    'Xyzzy'        => '== 6.01',
1083  }
1084
1085=head2 add_string_requirement
1086
1087  $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206');
1088  $req->add_string_requirement('Library::Foo' => v1.208);
1089
1090This method parses the passed in string and adds the appropriate requirement
1091for the given module.  A version can be a Perl "v-string".  It understands
1092version ranges as described in the L<CPAN::Meta::Spec/Version Ranges>. For
1093example:
1094
1095=over 4
1096
1097=item 1.3
1098
1099=item >= 1.3
1100
1101=item <= 1.3
1102
1103=item == 1.3
1104
1105=item != 1.3
1106
1107=item > 1.3
1108
1109=item < 1.3
1110
1111=item >= 1.3, != 1.5, <= 2.0
1112
1113A version number without an operator is equivalent to specifying a minimum
1114(C<E<gt>=>).  Extra whitespace is allowed.
1115
1116=back
1117
1118=head2 from_string_hash
1119
1120  my $req = CPAN::Meta::Requirements->from_string_hash( \%hash );
1121  my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts );
1122
1123This is an alternate constructor for a CPAN::Meta::Requirements
1124object. It takes a hash of module names and version requirement
1125strings and returns a new CPAN::Meta::Requirements object. As with
1126add_string_requirement, a version can be a Perl "v-string". Optionally,
1127you can supply a hash-reference of options, exactly as with the L</new>
1128method.
1129
1130=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
1131
1132=head1 SUPPORT
1133
1134=head2 Bugs / Feature Requests
1135
1136Please report any bugs or feature requests through the issue tracker
1137at L<https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements/issues>.
1138You will be notified automatically of any progress on your issue.
1139
1140=head2 Source Code
1141
1142This is open source software.  The code repository is available for
1143public review and contribution under the terms of the license.
1144
1145L<https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements>
1146
1147  git clone https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git
1148
1149=head1 AUTHORS
1150
1151=over 4
1152
1153=item *
1154
1155David Golden <dagolden@cpan.org>
1156
1157=item *
1158
1159Ricardo Signes <rjbs@cpan.org>
1160
1161=back
1162
1163=head1 CONTRIBUTORS
1164
1165=for stopwords Ed J Karen Etheridge Leon Timmermans robario
1166
1167=over 4
1168
1169=item *
1170
1171Ed J <mohawk2@users.noreply.github.com>
1172
1173=item *
1174
1175Karen Etheridge <ether@cpan.org>
1176
1177=item *
1178
1179Leon Timmermans <fawaka@gmail.com>
1180
1181=item *
1182
1183robario <webmaster@robario.com>
1184
1185=back
1186
1187=head1 COPYRIGHT AND LICENSE
1188
1189This software is copyright (c) 2010 by David Golden and Ricardo Signes.
1190
1191This is free software; you can redistribute it and/or modify it under
1192the same terms as the Perl 5 programming language system itself.
1193
1194=cut
1195