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   31111 use strict;
  3         6  
  3         141  
2             package inc;
3             our $VERSION = '0.04';
4              
5 3     3   80 use 5.008001;
  3         6  
  3         83  
6              
7 3     3   1974 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             die "Invalid spec string '$next'"
61             unless $next =~ /^(\-?)(\w+)(?:=(.*))?$/;
62             my $name = $2;
63             $name = "not_$name" if $1;
64             my @args = $3 ? split /,/, $3 : ();
65             return [$name, @args];
66             }
67              
68             sub get_next_spec {
69             my ($self) = @_;
70             while (@{$self->{spec}}) {
71             my $next = shift @{$self->{spec}};
72             next unless length $next;
73             if ($next =~ /:/) {
74             # XXX This parse is flimsy:
75             my @rest;
76             ($next, @rest) = split /:/, $next;
77             unshift @{$self->{spec}}, @rest;
78             next unless $next;
79             }
80             return $next;
81             }
82             return;
83             }
84              
85             sub lookup {
86             my ($modpath, @inc) = @_;
87             for (@inc) {
88             my $path = "$_/$modpath";
89             if (-e $path) {
90             open my $fh, '<', $path
91             or die "Can't open '$path' for input:\n$!";
92             return $fh;
93             }
94             }
95             return;
96             }
97              
98             sub run_perl_eval {
99             my ($perl, @argv) = @_;
100             local $ENV{PERL5OPT};
101              
102             my $out = qx!$^X -e '$perl' @argv!;
103             return eval $out;
104             }
105              
106             sub only_find {
107             my ($self, $hash) = @_;
108             return sub {
109             my ($self, $modpath) = @_;
110             (my $modname = $modpath) =~ s!/!::!g;
111             $modname =~ s!\.pm$!!;
112             return unless $hash->{$modname};
113             return lookup($modpath, @$INC);
114             }
115             }
116              
117             #------------------------------------------------------------------------------
118             # Smart Objects
119             #------------------------------------------------------------------------------
120             sub inc_blib {
121             return 'blib/lib', 'blib/arch';
122             }
123              
124             sub inc_cache {
125             my ($self) = @_;
126             die "inc 'cache' object not yet implemented";
127             return ();
128             }
129              
130             sub inc_core {
131             my ($self, $version) = @_;
132             $version ||= $Config::Config{version};
133             my $hash = $self->{"corelists/$version"} ||=
134             run_perl_eval $perl_core, $version;
135             $self->only_find($hash);
136             }
137              
138             sub inc_cwd {
139             my ($self) = @_;
140             return (
141             $self->{cwd},
142             );
143             }
144              
145             sub inc_deps {
146             my ($self, @module) = @_;
147             die "inc 'deps' object not yet implemented";
148             }
149              
150             sub inc_dot {
151             my ($self) = @_;
152             return (
153             $self->{curdir},
154             );
155             }
156              
157             my $hash_dzil;
158             sub inc_dzil {
159             my ($self) = @_;
160             local $ENV{PERL5OPT};
161             $hash_dzil ||= +{ map { chomp; ($_, 1) } `dzil listdeps` };
162             $self->only_find($hash_dzil);
163             }
164              
165             sub inc_inc {
166             my ($self) = @_;
167             return @{$self->{inc}};
168             }
169              
170             sub inc_INC {
171             my ($self) = @_;
172             return @{$self->{INC}};
173             }
174              
175             sub inc_lib {
176             return Cwd::abs_path('lib');
177             }
178              
179             sub inc_meta {
180             my ($self) = @_;
181             die "inc 'meta' object not yet implemented";
182             }
183              
184             sub inc_none {
185             return ();
186             }
187              
188             sub inc_not {
189             my ($self) = @_;
190             die "inc 'not' object requires one regex"
191             unless @_ == 1;
192             my $regex = qr/$_[0]/;
193             $self->{list} = [grep {ref or not($regex)} @{$self->{list}}];
194             return ();
195             }
196              
197             sub inc_perl5lib {
198             return () unless defined $ENV{PERL5LIB};
199             return split /:/, $ENV{PERL5LIB};
200             }
201              
202             sub inc_priv {
203             my ($self) = @_;
204             return (
205             $self->{archlib},
206             $self->{privlib},
207             );
208             }
209              
210             sub inc_not_priv {
211             my ($self) = @_;
212             $self->{list} = [grep {
213             ref or not(
214             $_ eq $self->{archlib} or
215             $_ eq $self->{priv}
216             )
217             } @{$self->{list}}];
218             return ();
219             }
220              
221             sub inc_site {
222             my ($self) = @_;
223             return (
224             $self->{sitearch},
225             $self->{sitelib},
226             );
227             }
228              
229             sub inc_not_site {
230             my ($self) = @_;
231             $self->{list} = [grep {
232             ref or not(
233             $_ eq $self->{sitearch} or
234             $_ eq $self->{sitelib}
235             )
236             } @{$self->{list}}];
237             return ();
238             }
239              
240             sub inc_show {
241             my ($self) = @_;
242             for (@{$self->{list}}) {
243             print "$_\n";
244             }
245             return ();
246             }
247              
248             sub inc_zild {
249             my ($self) = @_;
250             die "inc 'zild' object not yet implemented";
251             }
252              
253             #------------------------------------------------------------------------------
254             # Perl scripts to run externally, so as not to load unintended modules into the
255             # main process:
256             #------------------------------------------------------------------------------
257             $perl_init = <<'...';
258             use Data::Dumper();
259             use Cwd();
260             use Config();
261             use File::Spec;
262             $Data::Dumper::Terse = 1;
263             print Data::Dumper::Dumper +{
264             INC => \@INC,
265             archlib => $Config::Config{archlib},
266             privlib => $Config::Config{privlib},
267             sitearch => $Config::Config{sitearch},
268             sitelib => $Config::Config{sitelib},
269             curdir => File::Spec->curdir,
270             cwd => Cwd::cwd,
271             };
272             ...
273              
274             $perl_core = <<'...';
275             use Module::CoreList();
276             use version();
277             use Data::Dumper();
278              
279             my $version = shift @ARGV;
280             $version = version->parse($version)->numify;
281             $Data::Dumper::Terse = 1;
282             print Data::Dumper::Dumper $Module::CoreList::version{$version};
283             ...
284              
285             1;