File Coverage

blib/lib/Module/AutoLoad.pm
Criterion Covered Total %
statement 105 113 92.9
branch 41 68 60.2
condition 5 10 50.0
subroutine 10 10 100.0
pod 0 5 0.0
total 161 206 78.1


line stmt bran cond sub pod time code
1             package Module::AutoLoad;
2              
3 2     2   1725480 use strict;
  2         5  
  2         77  
4 2     2   10 use warnings;
  2         5  
  2         58  
5 2     2   8 use base qw(Exporter);
  2         8  
  2         4296  
6              
7             our $VERSION = '0.04';
8              
9             our $last_fetched = "";
10             our $lib = "lib";
11              
12             sub import {
13 2 50   2   77 warn "Congratulations! Module::AutoLoad has been loaded.\n" if $ENV{AUTOLOAD_DEBUG};
14 2 50       9 $lib = $ENV{AUTOLOAD_LIB} if $ENV{AUTOLOAD_LIB};
15 2 50       11 if ($lib =~ m{^[^/]}) {
16 2         4 eval {
17 2         11 require Cwd;
18 2         67 $lib = Cwd::abs_path($lib);
19             };
20             }
21 2         53 push @INC, $lib, \&inc;
22             }
23              
24             sub mkbase {
25 16     16 0 37 my $path = shift;
26 16 50       161 if ($path =~ s{/+[^/]*$ }{}x) {
27 16 100       332 return 1 if -d $path;
28             }
29 4 50       46 die "$path: Not a directory\n" if lstat $path;
30 4 50       11 if (mkbase($path)) {
31 4 50       15 warn "DEBUG: mkbase: Creating [$path] ...\n" if $ENV{AUTOLOAD_DEBUG};
32 4         617 return mkdir $path, 0755;
33             }
34 0         0 return 0;
35             }
36              
37             sub fetch {
38 16     16 0 36 my $url = shift;
39 16   100     78 my $recurse = shift || {};
40 16 50       103 $url = full($url) unless $url =~ m{^\w+://};
41 16         612 my $contents = get url $url;
42 15         5532752 $last_fetched = $url;
43 15 100       277 if ($contents =~ m{The document has moved }) {
44 4         28 my $bounce = $1;
45 4 50 33     26 if ($recurse->{$bounce} && $recurse->{$bounce} > 2) {
46 0         0 return $contents;
47             }
48 4         25 $recurse->{$bounce}++;
49 4 50       59 return fetch($bounce, $recurse) if $recurse->{total}++<20;
50             }
51 11         98 return $contents;
52             }
53              
54             # full
55             # Turn a relative URL into a full URL
56             sub full {
57 11     11 0 38 my $rel = shift;
58 11 50 33     157 if ($rel =~ m{http://} || $last_fetched !~ m{^(http://[^/]+)(/?.*)}) {
59 0         0 return $rel;
60             }
61 11         29 my $h = $1;
62 11         29 my $p = $2;
63 11 100       35 if ($rel =~ m{^/}) {
64 4         24 return "$h$rel";
65             }
66 7         81 $p =~ s{[^/]*$ }{}x;
67 7         29 return "$h$p$rel";
68             }
69              
70             # fly
71             # Create a stub module to load the real file on-the-fly if needed.
72             sub fly {
73 7     7 0 12 my $inc = shift;
74 7         10 my $url = shift;
75 7         11 my $write = shift;
76 7 50       23 warn "DEBUG: Creating stub for [$inc] in order to download [$url] later if needed.\n" if $ENV{AUTOLOAD_DEBUG};
77 7         16 my $contents = q{
78             my $url = q{$URL};
79             my $myself = $INC{"$inc"} || __FILE__;
80             warn "DEBUG: Downloading [$url] right now ...\n" if $ENV{AUTOLOAD_DEBUG};
81             my $m = Module::AutoLoad::fetch($url);
82             if ($m =~ /package/) {
83             warn "DEBUG: Contents appear fine. Commencing BRICK OVER ...\n" if $ENV{AUTOLOAD_DEBUG};
84             if (open my $fh, ">", $myself) {
85             print $fh $m;
86             close $fh;
87             }
88             else {
89             warn "$myself: WARNING: Unable to repair! $!\n";
90             }
91             warn "DEBUG: Forcing re-evaluation of fresh module contents ...\n" if $ENV{AUTOLOAD_DEBUG};
92             my $e = eval $m;
93             if ($e) {
94             $INC{"$inc"} = $url;
95             $e;
96             }
97             else {
98             die "$url: $@\n";
99             }
100             }
101             else {
102             die "$url: STANKY! $m\n";
103             }
104             };
105 7         537 $contents =~ s/\s+/ /g;
106 7         277 $contents =~ s/([\;\{]+)\s+/$1\n/g;
107 7         33 $contents =~ s/^\s+//;
108 7         777 $contents =~ s/\s*$/\n/;
109             # Fake interpolation
110 7         54 $contents =~ s/\$URL/$url/g;
111 7         53 $contents =~ s/\$inc/$inc/g;
112 7 50       29 if ($write) {
113 7         40 mkbase($write);
114 7         110 $contents =~ s/(\$myself)\s*=.*?;/$1 = "$write";/;
115 7 50       788 open my $fh, ">", $write or die "$write: open: OUCH! $!";
116 7         47 print $fh $contents;
117 7         350 close $fh;
118             }
119 7         82 return $contents;
120             }
121              
122             sub inc {
123 5     5 0 430 my $i = shift;
124 5         11 my $f = shift;
125 5         22 my $cache_file = "$lib/$f";
126 5 50       68 if (-f $cache_file) {
127 0         0 warn "$cache_file: Broken module. Can't continue.\n";
128 0         0 return ();
129             }
130 5 50       17 mkbase($cache_file) or die "$cache_file: Unable to create! $!\n";
131 5 100       35 pop @INC if $INC[-1] eq \&botstrap::inc;
132              
133 5 50       36 if ($f =~ m{^([\w/]+)\.pm}) {
134 5         14 my $dist = $1;
135 5         9 my $mod = $1;
136 5         11 $f = "$1.pm";
137 5         16 $dist =~ s{/+}{-}g;
138 5         13 $mod =~ s{/+}{::}g;
139              
140 5   50     33 my $mapper = $ENV{AUTOLOAD_SRC} || "http://search.cpan.org/dist";
141 5         24 my $search = fetch("$mapper/$dist/");
142 4 50       120 if ($search =~ m{href="([^<>]+)">Browse<}) {
143 4         28 my $src = full($1);
144 4 50       19 if (my $MANIFEST = fetch "$src/MANIFEST") {
145 4 50       89 $src = $1 if $last_fetched =~ m{^(.*?)/+MANIFEST};
146 4 100       23 if ($MANIFEST =~ m{^lib/}m) {
147 2 50       21 warn "DEBUG: YEY! Found a lib/ somewhere!\n" if $ENV{AUTOLOAD_DEBUG};
148 2         25 while ($MANIFEST =~ s{^lib/(\S+\.pm)}{ }m) {
149 6         21 my $remote = $1;
150 6 50       22 warn "DEBUG: MATCH [lib/$remote] RIPPED OUT\n" if $ENV{AUTOLOAD_DEBUG};
151 6         15 $last_fetched = "$src/MANIFEST";
152 6         15 my $cache = "$lib/$remote";
153 6 50       242 if (!-f $cache) {
154 6         34 my $full = full("lib/$remote");
155 6         23 fly($remote,$full,$cache);
156             }
157             }
158             }
159             else {
160 2 50       18 warn "DEBUG: Oh, too bad there is no magic lib folder in the MANIFEST [$MANIFEST]\n" if $ENV{AUTOLOAD_DEBUG};
161             }
162 4 100       161 if (!-f $cache_file) {
163             # Old versions of h2xs used to toss the end module right into the base folder?
164 2 50       17 if ($f =~ m{(\w+\.pm)}) {
165 2         7 my $stub = $1;
166 2 100       99 if ($MANIFEST =~ /^(.*$stub)$/m) {
167 1         3 my $stab = $1;
168 1         5 $last_fetched = "$src/MANIFEST";
169 1         5 $stab = full($stab);
170 1         6 fly($f, $stab, $cache_file);
171             }
172             else {
173 1 50       7 warn "WARNING: No [$stub] in $src/MANIFEST? [$MANIFEST]" if $ENV{AUTOLOAD_DEBUG};
174 1         45 die "No [$stub] in $src/MANIFEST";
175             }
176             }
177             else {
178 0         0 warn "WARNING: Unable to extract stub from file [$f] ??\n";
179             }
180             }
181             }
182             else {
183 0         0 warn "$src: Incomplete distribution! Broken MANIFEST file?\n";
184             }
185             }
186             }
187              
188 3 50       108 if (open my $fh, "<", $cache_file) {
189 3         16 $INC{$f} = $cache_file;
190 3         1949 return $fh;
191             }
192              
193 0           return ();
194             }
195              
196             $INC{"Module/AutoLoad.pm"} ||= __FILE__;
197             # Dummy AutoLoad wrapper module for RCX Framework.
198             package AutoLoad;
199 2     2   13 use base qw(Module::AutoLoad);
  2         4  
  2         201  
200              
201             $INC{"AutoLoad.pm"} ||= __FILE__;
202              
203             1;
204             __END__