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   3499463 use strict;
  2         3  
  2         69  
4 2     2   7 use warnings;
  2         2  
  2         49  
5 2     2   7 use base qw(Exporter);
  2         6  
  2         4071  
6              
7             our $VERSION = '0.03';
8              
9             our $last_fetched = "";
10             our $lib = "lib";
11              
12             sub import {
13 2 50   2   95 warn "Congratulations! Module::AutoLoad has been loaded.\n" if $ENV{AUTOLOAD_DEBUG};
14 2 50       7 $lib = $ENV{AUTOLOAD_LIB} if $ENV{AUTOLOAD_LIB};
15 2 50       13 if ($lib =~ m{^[^/]}) {
16 2         3 eval {
17 2         10 require Cwd;
18 2         60 $lib = Cwd::abs_path($lib);
19             };
20             }
21 2         36 push @INC, $lib, \&inc;
22             }
23              
24             sub mkbase {
25 16     16 0 25 my $path = shift;
26 16 50       133 if ($path =~ s{/+[^/]*$ }{}x) {
27 16 100       330 return 1 if -d $path;
28             }
29 4 50       39 die "$path: Not a directory\n" if lstat $path;
30 4 50       11 if (mkbase($path)) {
31 4 50       13 warn "DEBUG: mkbase: Creating [$path] ...\n" if $ENV{AUTOLOAD_DEBUG};
32 4         280 return mkdir $path, 0755;
33             }
34 0         0 return 0;
35             }
36              
37             sub fetch {
38 16     16 0 32 my $url = shift;
39 16   100     80 my $recurse = shift || {};
40 16 50       130 $url = full($url) unless $url =~ m{^\w+://};
41 16         734 my $contents = get url $url;
42 15         5732600 $last_fetched = $url;
43 15 100       263 if ($contents =~ m{The document has moved }) {
44 4         41 my $bounce = $1;
45 4 50 33     27 if ($recurse->{$bounce} && $recurse->{$bounce} > 2) {
46 0         0 return $contents;
47             }
48 4         26 $recurse->{$bounce}++;
49 4 50       65 return fetch($bounce, $recurse) if $recurse->{total}++<20;
50             }
51 11         94 return $contents;
52             }
53              
54             # full
55             # Turn a relative URL into a full URL
56             sub full {
57 11     11 0 55 my $rel = shift;
58 11 50 33     140 if ($rel =~ m{http://} || $last_fetched !~ m{^(http://[^/]+)(/?.*)}) {
59 0         0 return $rel;
60             }
61 11         39 my $h = $1;
62 11         26 my $p = $2;
63 11 100       35 if ($rel =~ m{^/}) {
64 4         19 return "$h$rel";
65             }
66 7         59 $p =~ s{[^/]*$ }{}x;
67 7         20 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         7 my $url = shift;
75 7         9 my $write = shift;
76 7 50       18 warn "DEBUG: Creating stub for [$inc] in order to download [$url] later if needed.\n" if $ENV{AUTOLOAD_DEBUG};
77 7         11 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         308 $contents =~ s/\s+/ /g;
106 7         195 $contents =~ s/([\;\{]+)\s+/$1\n/g;
107 7         25 $contents =~ s/^\s+//;
108 7         444 $contents =~ s/\s*$/\n/;
109             # Fake interpolation
110 7         33 $contents =~ s/\$URL/$url/g;
111 7         33 $contents =~ s/\$inc/$inc/g;
112 7 50       17 if ($write) {
113 7         39 mkbase($write);
114 7         72 $contents =~ s/(\$myself)\s*=.*?;/$1 = "$write";/;
115 7 50       652 open my $fh, ">", $write or die "$write: open: OUCH! $!";
116 7         41 print $fh $contents;
117 7         296 close $fh;
118             }
119 7         65 return $contents;
120             }
121              
122             sub inc {
123 5     5 0 430 my $i = shift;
124 5         15 my $f = shift;
125 5         24 my $cache_file = "$lib/$f";
126 5 50       77 if (-f $cache_file) {
127 0         0 warn "$cache_file: Broken module. Can't continue.\n";
128 0         0 return ();
129             }
130 5 50       19 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       41 if ($f =~ m{^([\w/]+)\.pm}) {
134 5         13 my $dist = $1;
135 5         10 my $mod = $1;
136 5         12 $f = "$1.pm";
137 5         17 $dist =~ s{/+}{-}g;
138 5         15 $mod =~ s{/+}{::}g;
139              
140 5   50     37 my $mapper = $ENV{AUTOLOAD_SRC} || "http://search.cpan.org/dist";
141 5         25 my $search = fetch("$mapper/$dist/");
142 4 50       141 if ($search =~ m{href="([^<>]+)">Browse<}) {
143 4         22 my $src = full($1);
144 4 50       19 if (my $MANIFEST = fetch "$src/MANIFEST") {
145 4 50       84 $src = $1 if $last_fetched =~ m{^(.*?)/+MANIFEST};
146 4 100       24 if ($MANIFEST =~ m{^lib/}m) {
147 2 50       24 warn "DEBUG: YEY! Found a lib/ somewhere!\n" if $ENV{AUTOLOAD_DEBUG};
148 2         32 while ($MANIFEST =~ s{^lib/(\S+\.pm)}{ }m) {
149 6         18 my $remote = $1;
150 6 50       18 warn "DEBUG: MATCH [lib/$remote] RIPPED OUT\n" if $ENV{AUTOLOAD_DEBUG};
151 6         16 $last_fetched = "$src/MANIFEST";
152 6         14 my $cache = "$lib/$remote";
153 6 50       204 if (!-f $cache) {
154 6         25 my $full = full("lib/$remote");
155 6         13 fly($remote,$full,$cache);
156             }
157             }
158             }
159             else {
160 2 50       15 warn "DEBUG: Oh, too bad there is no magic lib folder in the MANIFEST [$MANIFEST]\n" if $ENV{AUTOLOAD_DEBUG};
161             }
162 4 100       150 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       107 if ($MANIFEST =~ /^(.*$stub)$/m) {
167 1         2 my $stab = $1;
168 1         4 $last_fetched = "$src/MANIFEST";
169 1         4 $stab = full($stab);
170 1         5 fly($f, $stab, $cache_file);
171             }
172             else {
173 1 50       6 warn "WARNING: No [$stub] in $src/MANIFEST? [$MANIFEST]" if $ENV{AUTOLOAD_DEBUG};
174 1         42 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       91 if (open my $fh, "<", $cache_file) {
189 3         14 $INC{$f} = $cache_file;
190 3         1870 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   16 use base qw(Module::AutoLoad);
  2         2  
  2         304  
200              
201             $INC{"AutoLoad.pm"} ||= __FILE__;
202              
203             1;
204             __END__