File Coverage

blib/lib/Module/Requires.pm
Criterion Covered Total %
statement 77 78 98.7
branch 52 56 92.8
condition 6 6 100.0
subroutine 5 5 100.0
pod n/a
total 140 145 96.5


line stmt bran cond sub pod time code
1             package Module::Requires;
2 10     10   6735 use strict;
  10         20  
  10         386  
3 10     10   55 use warnings;
  10         16  
  10         459  
4             our $VERSION = '0.03';
5              
6 10     10   49 use Carp;
  10         19  
  10         4392  
7              
8             sub import {
9 37     37   13651 my($class, @args) = @_;
10 37 100 100     1293 my $is_autoload = (@args && $args[0] eq '-autoload') ? shift @args : undef;
11              
12 37         97 my $caller = caller(0);
13 37 100       253 my $target = $is_autoload ? $caller : join '::', __PACKAGE__, '_load_tmp_', $caller;
14              
15 37         54 my @errors;
16 37         49 my $i = 0;
17 37         51 my $len = scalar(@args);
18 37         50 my @imports;
19             LOOP:
20 37         105 while ($len > $i) {
21             # prepare args
22 50         96 my $name = $args[$i++];
23 50         70 my $val = $args[$i++];
24 50         67 my $import;
25             my $version;
26 50 100 100     438 if ($len > $i-1 && $val =~ /^[0-9]+(?:\.[0-9]+)*$/) {
    100          
    100          
    50          
27             # simple version
28 13         23 $version = $val;
29             } elsif (ref($val) eq 'ARRAY') {
30             # detail version
31 8         13 $version = $val;
32             } elsif (ref($val) eq 'HASH') {
33             # autoload
34 18 100       38 unless ($is_autoload) {
35 5         13 push @errors, "$name is unloaded because -autoload an option is lacking.";
36 5         21 next LOOP;
37             }
38 13         27 $import = $val->{import};
39 13         19 $version = $val->{version};
40             } elsif (ref($val)) {
41 0         0 confess 'args format error';
42             } else {
43 11         17 $i--;
44             }
45              
46             # load module
47 45         3025 eval qq{package $target; require $name}; ## no critic.
48 45 100       2095 if ($is_autoload) {
49 20         53 push @imports, [ $name, $import ];
50             }
51 45 100       117 if (my $e = $@) {
52 5         15 push @errors, "Can't load $name\n$e";
53 5         19 next LOOP;
54             }
55              
56             # version check
57 40 100       111 if ($version) {
58 30         31 my $mod_ver = do {
59 10     10   58 no strict 'refs';
  10         17  
  10         5004  
60 30         31 ${"$name\::VERSION"};
  30         95  
61             };
62 30 100       63 if (defined $mod_ver) {
63 29 100       130 if (ref($version) eq 'ARRAY') {
    100          
64             # detail version
65 15 100       12 if (@{ $version } % 2 == 0) {
  15         38  
66 14         16 my @terms;
67             my $is_error;
68 14         17 while (my($k, $v) = splice @{ $version }, 0, 2) {
  36         108  
69 23         132 push @terms, "$k $v";
70 23 100       67 if ($k eq '>') {
    100          
    100          
    100          
    100          
71 12 100       53 $is_error = 1 unless $mod_ver > $v;
72             } elsif ($k eq '>=') {
73 1 50       5 $is_error = 1 unless $mod_ver >= $v;
74             } elsif ($k eq '<') {
75 2 50       11 $is_error = 1 unless $mod_ver < $v;
76             } elsif ($k eq '<=') {
77 1 50       5 $is_error = 1 unless $mod_ver <= $v;
78             } elsif ($k eq '!=') {
79 6 100       21 $is_error = 1 unless $mod_ver != $v;
80             } else {
81 1         3 push @errors, "$name version check syntax error";
82 1         5 next LOOP;
83             }
84             }
85 13 100       32 if ($is_error) {
86 10         19 push @errors, "$name version @{[ join ' AND ', @terms ]} required--this is only version $mod_ver";
  10         37  
87 10         47 next LOOP;
88             }
89             } else {
90 1         2 push @errors, "$name version check syntax error";
91 1         4 next LOOP;
92             }
93             } elsif ($mod_ver < $version) {
94 10         45 push @errors, "$name version $version required--this is only version $mod_ver";
95 10         36 next LOOP;
96             }
97             } else {
98 1         6 push @errors, "$name does not define \$$name\::VERSION--version check failed";
99 1         6 next LOOP;
100             }
101             }
102             }
103              
104             # show the errors
105 37 100       92 if (@errors) {
106 24         4804 confess join "\n", @errors;
107             }
108              
109             # run import method
110 13         74 for my $obj (@imports) {
111 10 100       44 if (defined $obj->[1]) {
112 5 100       7 if (@{ $obj->[1] }) {
  5         23  
113 4         283 eval qq{package $target;\$obj->[0]->import(\@{ \$obj->[1] })}; ## no critic.
114             } else {
115             # same the "use Module ();", it case is do not call import method
116             }
117             } else {
118 5         286 eval qq{package $target;\$obj->[0]->import}; ## no critic.
119             }
120             }
121             }
122              
123             1;
124             __END__