File Coverage

blib/lib/File/FindLib.pm
Criterion Covered Total %
statement 56 58 96.5
branch 15 20 75.0
condition 8 12 66.6
subroutine 8 8 100.0
pod 0 2 0.0
total 87 100 87.0


line stmt bran cond sub pod time code
1             package File::FindLib;
2 3     3   3129 use strict;
  3         5  
  3         136  
3              
4 3     3   17 use File::Basename qw< dirname >;
  3         5  
  3         209  
5 3     3   2109 use File::Spec::Functions qw< rel2abs catdir splitdir >;
  3         2566  
  3         218  
6              
7 3     3   16 use vars qw< $VERSION >;
  3         6  
  3         158  
8              
9             my $Pkg= __PACKAGE__; # Our class name (convenient to use in messages)
10             BEGIN {
11 3     3   3184 $VERSION= 0.001_004;
12             }
13              
14             return 1; # No run-time code below; just 'sub's and maybe BEGIN blocks
15              
16              
17             sub import {
18 4     4   75 my( $class, @args )= @_;
19 4 50       14 if( 1 == @args ) {
20 4         10 my( $find )= @args;
21 4         29 return LookUp(
22             -from => ( caller )[1],
23             -upto => $find,
24             -add => $find,
25             );
26             } else {
27 0         0 die "Too many arguments to 'use $Pkg'. Not yet supported.\n";
28             }
29             }
30              
31              
32             sub LookUp {
33 4     4 0 18 my %args= @_;
34 4         22 my $from= rel2abs( $args{-from} );
35 4         232 my $upto= $args{-upto};
36 4         10 my $add= $args{-add};
37              
38 4 0 33     225 warn "$Pkg finds no $from; perhaps chdir()ed before 'use $Pkg'?\n"
39             if ! -e $from && $^W;
40 4 50       78 if( -l $from ) {
41 0         0 $from= rel2abs( readlink($from), dirname($from) );
42             }
43 4         9 my $dir= $from;
44 4 50       261 $dir= dirname( $dir )
45             if ! -d _;
46 4         15 while( 1 ) {
47 11         45 my $find= catdir( $dir, $upto );
48 11 100       187 if( -e $find ) {
49 3         18 my $path= catdir( $dir, $add );
50 3 100       60 if( -d $path ) {
51 1         12 require lib;
52 1         11 lib->import( $path );
53 1         155 return $path;
54             }
55 2         1357 my $ret= require $path;
56 2         105 UpdateInc( $path );
57 2         69 return $ret;
58             }
59 8         213 my $up= dirname( $dir );
60 8 100       36 die "$Pkg can't find $find in ancestor directory of $from.\n"
61             if $up eq $dir;
62 7         11 $dir= $up;
63             }
64             }
65              
66              
67             # Set $INC{'My/Mod.pm'} after loading 'lib/My/Mod.pm';
68             # so "use File::FindLib 'lib/Mod.pm'; use Mod;" doesn't load it twice.
69              
70             sub UpdateInc {
71 5     5 0 1479 my( $path )= @_; # Path to module file.
72 5         10 my $base= $path; # Path minus ".pm"; parts that go into package name.
73 5 100       34 return 0 # If no .pm on end, "use Bareword" wouldn't find it.
74             if $base !~ s/[.]pm$//;
75 4         23 my @parts= grep length $_, splitdir( $base ); # Potential pkg name parts.
76 4         112 my @names; # Above minus leading parts that aren't barewords.
77 4   100     103 unshift @names, pop @parts # Include last part until find...
78             while @parts && $parts[-1] =~ /^\w+$/; # ...a non-bareword.
79             EDGE:
80 4         18 for my $o ( 0 .. $#names ) { # Strip shortest prefix that leaves a pkg.
81             next # "use Foo::123" works but "use 123::Foo" wouldn't.
82 9 100       31 if $names[$o] =~ /^[0-9]/;
83 8         14 my $stab= \%main::;
84 8         26 my @pkg= @names[ $o..$#names ];
85 8         17 for my $name ( @pkg ) { # Defined package? No autovivification.
86 14         37 $stab= $stab->{$name.'::'};
87             next EDGE
88 14 100 100     86 if ! $stab || 'GLOB' ne ref \$stab;
89             }
90 3         25 my $mod= join '/', @pkg; # @INC always uses '/'; no catdir()
91 3   33     26 $INC{"$mod.pm"} ||= $INC{$path};
92 3         17 return 1;
93             }
94 1         26 return 0;
95             }
96              
97              
98             __END__