File Coverage

blib/lib/inc.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


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