File Coverage

blib/lib/CPAN/Requirements/Dynamic.pm
Criterion Covered Total %
statement 51 57 89.4
branch 14 18 77.7
condition 6 15 40.0
subroutine 11 12 91.6
pod 3 3 100.0
total 85 105 80.9


line stmt bran cond sub pod time code
1             package CPAN::Requirements::Dynamic;
2             $CPAN::Requirements::Dynamic::VERSION = '0.002';
3 1     1   92575 use strict;
  1         2  
  1         50  
4 1     1   6 use warnings;
  1         2  
  1         60  
5              
6 1     1   8 use Carp 'croak';
  1         2  
  1         87  
7 1     1   534 use Parse::CPAN::Meta;
  1         1487  
  1         899  
8              
9             sub _version_satisfies {
10 3     3   6 my ($version, $range) = @_;
11 3         19 require CPAN::Meta::Requirements::Range;
12 3         18 return CPAN::Meta::Requirements::Range->with_string_requirement($range)->accepts($version);
13             }
14              
15             my %default_commands = (
16             can_run => sub {
17             my ($self, $command) = @_;
18             require IPC::Cmd;
19             return IPC::Cmd::can_run($command);
20             },
21             config_defined => sub {
22             my ($self, $entry) = @_;
23             return $self->{config}->get($entry) eq 'define';
24             },
25             has_env => sub {
26             my ($self, $entry) = @_;
27             return !!$ENV{$entry};
28             },
29             has_perl => sub {
30             my ($self, $range) = @_;
31             return _version_satisfies($], $range);
32             },
33             is_extended => sub {
34             return !!$ENV{EXTENDED_TESTING};
35             },
36             is_os => sub {
37             my ($self, @wanted) = @_;
38             return !!grep { $_ eq $^O } @wanted
39             },
40             is_os_type => sub {
41             my ($self, $wanted) = @_;
42             require Perl::OSType;
43             return Perl::OSType::is_os_type($wanted);
44             },
45             is_smoker => sub {
46             return !!$ENV{AUTOMATED_TESTING};
47             },
48             want_xs => sub {
49             my ($self) = @_;
50             return !!0 if $self->{pureperl_only};
51             require ExtUtils::HasCompiler;
52             return ExtUtils::HasCompiler::can_compile_extension(config => $self->{config});
53             },
54             );
55              
56             sub new {
57 1     1 1 175221 my ($class, %args) = @_;
58             return bless {
59             config => $args{config} || do { require ExtUtils::Config; ExtUtils::Config->new },
60             prereqs => $args{prereqs} || do { require CPAN::Meta::Prereqs; CPAN::Meta::Prereqs->new },
61             commands => $args{commands} || \%default_commands,
62             pureperl_only => $args{pureperl_only},
63 1   33     7 }, $class;
      33        
      50        
64             }
65              
66             sub _get_command {
67 8     8   15 my ($self, $name) = @_;
68 8 100       22 if ($name eq 'or') {
    100          
69             return sub {
70 1     1   18 my ($self, @each) = @_;
71 1         2 for my $elem (@each) {
72 1 50       5 return !!1 if $self->_run_condition($elem);
73             }
74 0         0 return !!0;
75 1         6 };
76             } elsif ($name eq 'and') {
77             return sub {
78 1     1   3 my ($self, @each) = @_;
79 1         2 for my $elem (@each) {
80 2 100       8 return !!0 if not $self->_run_condition($elem);
81             }
82 0         0 return !!1;
83 1         5 };
84             } else {
85 6   33     25 return $self->{commands}{$name} || croak "No such command $name";
86             }
87             }
88              
89             sub _run_condition {
90 8     8   17 my ($self, $condition) = @_;
91              
92 8         13 my $negate = !!0;
93 8         12 my ($function, @arguments) = @{ $condition };
  8         22  
94 8         20 while ($function eq 'not') {
95 1         3 $function = shift @arguments;
96 1         3 $negate = !$negate;
97             }
98              
99 8         19 my $method = $self->_get_command($function);
100 8         19 my $primary = $self->$method(@arguments);
101 8 100       575 return $negate ? !$primary : $primary;
102             }
103              
104             sub evaluate {
105 1     1 1 122 my ($self, $argument) = @_;
106 1         7 my $version = $argument->{version};
107 1 50       5 croak "Dynamic prereqs spec version $version is not supported" if int $version > 1;
108 1         2 my @prereqs;
109              
110 1         2 for my $entry (@{ $argument->{expressions} }) {
  1         4  
111 5 100       670 if ($self->_run_condition($entry->{condition})) {
112 3 50       14 if ($entry->{error}) {
    50          
113 0         0 die "$entry->{error}\n";
114             } elsif (my $prereqs = $entry->{prereqs}) {
115 3   50     30 my $phase = $entry->{phase} || 'runtime';
116 3   50     12 my $relation = $entry->{relation} || 'requires';
117 3         27 my $prereqs = { $phase => { $relation => $entry->{prereqs} } };
118 3         22 push @prereqs, CPAN::Meta::Prereqs->new($prereqs);
119             }
120             }
121             }
122              
123 1         6 return $self->{prereqs}->with_merged_prereqs(\@prereqs);
124             }
125              
126             sub evaluate_file {
127 0     0 1   my ($self, $filename) = @_;
128 0           my $structure = Parse::CPAN::Meta->load_file($filename);
129 0           return $self->evaluate($structure);
130             }
131              
132             1;
133              
134             # ABSTRACT: Dynamic prerequisites in meta files
135              
136             __END__