File Coverage

blib/lib/inc.pm
Criterion Covered Total %
statement 62 147 42.1
branch 13 46 28.2
condition 3 14 21.4
subroutine 15 36 41.6
pod 0 31 0.0
total 93 274 33.9


line stmt bran cond sub pod time code
1 3     3   49904 use strict;
  3         8  
  3         231  
2             package inc;
3             our $VERSION = '0.06';
4              
5 3     3   92 use 5.008001;
  3         10  
  3         8056  
6              
7             # use XXX;
8              
9             my $perl_init;
10             my $perl_core;
11              
12             sub new {
13 6     6 0 37 my ($class, @spec) = @_;
14 6         44 my $init = run_perl_eval($perl_init);
15 6         108 my $self = bless {
16             spec => \@spec,
17             %$init,
18             }, $class;
19 6         88 return $self;
20             }
21              
22             sub import {
23 1     1   15 my ($class) = shift;
24 1 50       23 return unless @_;
25 0         0 my $self = $class->new(@_);
26 0         0 @INC = $self->create_list;
27 0         0 return;
28             }
29              
30             sub list {
31 6     6 0 14685 my ($class) = shift;
32 6 50       48 die "'inc->list()' requires at least one argument"
33             unless @_;
34 6         40 my $self = $class->new(@_);
35 6         51 return $self->create_list;
36             }
37              
38             sub create_list {
39 6     6 0 16 my ($self) = shift;
40 6         63 my $list = $self->{list} = [];
41 6         125 $self->{inc} = [@INC];
42 6         47 while (my $next = $self->parse_spec) {
43 8         25 my ($name, @args) = @$next;
44 8 50       31 if ($name =~ m!/!) {
45 0         0 push @$list, $name;
46             }
47             else {
48 8         22 my $method = "inc_$name";
49 8 50       87 die "No 'inc' support found for '$name'"
50             unless $self->can($method);
51 8         45 push @$list, $self->$method(@args);
52             }
53             }
54 6         211 return @$list;
55             }
56              
57             sub parse_spec {
58 14     14 0 29 my ($self) = @_;
59 14 100       52 my $next = $self->get_next_spec or return;
60 8 50       34 return [$next] if $next =~ m!/!;
61 8 50       132 die "Invalid spec string '$next'"
62             unless $next =~ /^(\-?)(\w+)(?:=(.*))?$/;
63 8         47 my $name = $2;
64 8 50       30 $name = "not_$name" if $1;
65 8 50       42 my @args = $3 ? split /,/, $3 : ();
66 8         50 return [$name, @args];
67             }
68              
69             sub get_next_spec {
70 14     14 0 25 my ($self) = @_;
71 14         32 while (@{$self->{spec}}) {
  14         89  
72 8         13 my $next = shift @{$self->{spec}};
  8         54  
73 8 50       900 next unless length $next;
74 8 50       42 if ($next =~ /:/) {
75             # XXX This parse is flimsy:
76 0         0 my @rest;
77 0         0 ($next, @rest) = split /:/, $next;
78 0         0 unshift @{$self->{spec}}, @rest;
  0         0  
79 0 0       0 next unless $next;
80             }
81 8         42 return $next;
82             }
83 6         108 return;
84             }
85              
86             sub lookup {
87 0     0 0 0 my ($modpath, @inc) = @_;
88 0         0 for (@inc) {
89 0         0 my $path = "$_/$modpath";
90 0 0       0 if (-e $path) {
91 0 0       0 open my $fh, '<', $path
92             or die "Can't open '$path' for input:\n$!";
93 0         0 return $fh;
94             }
95             }
96 0         0 return;
97             }
98              
99             sub run_perl_eval {
100 10     10 0 35 my ($perl, @argv) = @_;
101 10         66 local $ENV{PERL5OPT};
102              
103 10         848929 my $out = qx!$^X -e '$perl' @argv!;
104 10         6143 my $data = eval $out;
105 10 50       89 die $@ if $@;
106 10         266 return $data;
107             }
108              
109             sub only_find {
110 2     2 0 5 my ($self, $hash) = @_;
111             return sub {
112 0     0   0 my ($this, $modpath) = @_;
113 0         0 (my $modname = $modpath) =~ s!/!::!g;
114 0         0 $modname =~ s!\.pm$!!;
115 0 0       0 return unless $hash->{$modname};
116 0         0 return lookup($modpath, @{$self->{INC}});
  0         0  
117             }
118 2         58 }
119              
120             sub regex_find {
121 0     0 0 0 my ($self, $regex) = @_;
122             return sub {
123 0     0   0 my ($this, $modpath) = @_;
124 0         0 (my $modname = $modpath) =~ s!/!::!g;
125 0         0 $modname =~ s!\.pm$!!;
126 0 0       0 return unless $modname =~ $regex;
127 0         0 return lookup($modpath, @{$self->{INC}});
  0         0  
128             }
129 0         0 }
130              
131             #------------------------------------------------------------------------------
132             # Smart Objects
133             #------------------------------------------------------------------------------
134             sub inc_blib {
135 0     0 0 0 return 'blib/lib', 'blib/arch';
136             }
137              
138             sub inc_cache {
139 0     0 0 0 my ($self) = @_;
140 0         0 die "inc 'cache' object not yet implemented";
141 0         0 return ();
142             }
143              
144             sub inc_core {
145 2     2 0 7 my ($self, $version) = @_;
146 2   66     3464 $version ||= $Config::Config{version};
147 2   33     1348 my $hash = $self->{"corelists/$version"} ||=
148             run_perl_eval $perl_core, $version;
149 2         21 $self->only_find($hash);
150             }
151              
152             sub inc_cwd {
153 2     2 0 8 my ($self) = @_;
154             return (
155 2         14 $self->{cwd},
156             );
157             }
158              
159             sub inc_deps {
160 0     0 0 0 my ($self, @module) = @_;
161 0         0 die "inc 'deps' object not yet implemented";
162             }
163              
164             sub inc_dot {
165 2     2 0 9 my ($self) = @_;
166             return (
167 2         19 $self->{curdir},
168             );
169             }
170              
171             my $hash_dzil;
172             sub inc_dzil {
173 0     0 0 0 my ($self) = @_;
174 0         0 local $ENV{PERL5OPT};
175 0   0     0 $hash_dzil ||= +{ map { chomp; ($_, 1) } `dzil listdeps` };
  0         0  
  0         0  
176 0         0 $self->only_find($hash_dzil);
177             }
178              
179             sub inc_inc {
180 0     0 0 0 my ($self) = @_;
181 0         0 return @{$self->{inc}};
  0         0  
182             }
183              
184             sub inc_INC {
185 0     0 0 0 my ($self) = @_;
186 0         0 return @{$self->{INC}};
  0         0  
187             }
188              
189             sub inc_LC {
190 1     1 0 6 my ($self) = @_;
191 1         187 $self->inc_core('5.8.1');
192             }
193              
194             sub inc_lib {
195 2     2 0 1371 return run_perl_eval <<'...';
196             use Cwd;
197             print q{"} . Cwd::abs_path(q{lib}) . q{"};
198             ...
199             }
200              
201             sub inc_meta {
202 0     0 0   my ($self) = @_;
203 0           die "inc 'meta' object not yet implemented";
204             }
205              
206             sub inc_none {
207 0     0 0   return ();
208             }
209              
210             sub inc_not {
211 0     0 0   my ($self, @args) = @_;
212 0 0         die "inc 'not' object requires one regex"
213             unless @args == 1;
214 0           my $regex = qr/$args[0]/;
215 0 0         $self->{list} = [grep {ref or not($regex)} @{$self->{list}}];
  0            
  0            
216 0           return ();
217             }
218              
219             sub inc_ok {
220 0     0 0   my ($self, @args) = @_;
221 0 0         die "inc 'ok' object requires one regex"
222             unless @args == 1;
223 0           my $regex = qr/$args[0]/;
224 0           $self->regex_find($regex);
225             }
226              
227             sub inc_perl5lib {
228 0 0   0 0   return () unless defined $ENV{PERL5LIB};
229 0           return split /:/, $ENV{PERL5LIB};
230             }
231              
232             sub inc_priv {
233 0     0 0   my ($self) = @_;
234             return (
235 0           $self->{archlib},
236             $self->{privlib},
237             );
238             }
239              
240             sub inc_not_priv {
241 0     0 0   my ($self) = @_;
242 0 0 0       $self->{list} = [grep {
243 0           ref or not(
244             $_ eq $self->{archlib} or
245             $_ eq $self->{priv}
246             )
247 0           } @{$self->{list}}];
248 0           return ();
249             }
250              
251             sub inc_site {
252 0     0 0   my ($self) = @_;
253             return (
254 0           $self->{sitearch},
255             $self->{sitelib},
256             );
257             }
258              
259             sub inc_not_site {
260 0     0 0   my ($self) = @_;
261 0 0 0       $self->{list} = [grep {
262 0           ref or not(
263             $_ eq $self->{sitearch} or
264             $_ eq $self->{sitelib}
265             )
266 0           } @{$self->{list}}];
267 0           return ();
268             }
269              
270             sub inc_show {
271 0     0 0   my ($self) = @_;
272 0           for (@{$self->{list}}) {
  0            
273 0           print "$_\n";
274             }
275 0           return ();
276             }
277              
278             sub inc_zild {
279 0     0 0   my ($self) = @_;
280 0           die "inc 'zild' object not yet implemented";
281             }
282              
283             #------------------------------------------------------------------------------
284             # Perl scripts to run externally, so as not to load unintended modules into the
285             # main process:
286             #------------------------------------------------------------------------------
287             $perl_init = <<'...';
288             use Data::Dumper();
289             use Cwd();
290             use Config();
291             use File::Spec;
292             $Data::Dumper::Terse = 1;
293             print Data::Dumper::Dumper +{
294             INC => \@INC,
295             archlib => $Config::Config{archlib},
296             privlib => $Config::Config{privlib},
297             sitearch => $Config::Config{sitearch},
298             sitelib => $Config::Config{sitelib},
299             curdir => File::Spec->curdir,
300             cwd => Cwd::cwd,
301             };
302             ...
303              
304             $perl_core = <<'...';
305             use Module::CoreList();
306             use version();
307             use Data::Dumper();
308              
309             my $version = shift @ARGV;
310             $version = version->parse($version)->numify;
311             $Data::Dumper::Terse = 1;
312             print Data::Dumper::Dumper $Module::CoreList::version{$version};
313             ...
314              
315             1;