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