Add some subroutine docs. Must write another test so that I can understand all ins...
[dbsrgits/DBIx-Class-ResultSource-MultipleTableInheritance.git] / inc / Module / Install.pm
CommitLineData
146ec120 1#line 1
2package Module::Install;
3
4# For any maintainers:
5# The load order for Module::Install is a bit magic.
6# It goes something like this...
7#
8# IF ( host has Module::Install installed, creating author mode ) {
9# 1. Makefile.PL calls "use inc::Module::Install"
10# 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
11# 3. The installed version of inc::Module::Install loads
12# 4. inc::Module::Install calls "require Module::Install"
13# 5. The ./inc/ version of Module::Install loads
14# } ELSE {
15# 1. Makefile.PL calls "use inc::Module::Install"
16# 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
17# 3. The ./inc/ version of Module::Install loads
18# }
19
20use 5.005;
21use strict 'vars';
22use Cwd ();
23use File::Find ();
24use File::Path ();
25use FindBin;
26
27use vars qw{$VERSION $MAIN};
28BEGIN {
29 # All Module::Install core packages now require synchronised versions.
30 # This will be used to ensure we don't accidentally load old or
31 # different versions of modules.
32 # This is not enforced yet, but will be some time in the next few
33 # releases once we can make sure it won't clash with custom
34 # Module::Install extensions.
35 $VERSION = '0.95';
36
37 # Storage for the pseudo-singleton
38 $MAIN = undef;
39
40 *inc::Module::Install::VERSION = *VERSION;
41 @inc::Module::Install::ISA = __PACKAGE__;
42
43}
44
45sub import {
46 my $class = shift;
47 my $self = $class->new(@_);
48 my $who = $self->_caller;
49
50 #-------------------------------------------------------------
51 # all of the following checks should be included in import(),
52 # to allow "eval 'require Module::Install; 1' to test
53 # installation of Module::Install. (RT #51267)
54 #-------------------------------------------------------------
55
56 # Whether or not inc::Module::Install is actually loaded, the
57 # $INC{inc/Module/Install.pm} is what will still get set as long as
58 # the caller loaded module this in the documented manner.
59 # If not set, the caller may NOT have loaded the bundled version, and thus
60 # they may not have a MI version that works with the Makefile.PL. This would
61 # result in false errors or unexpected behaviour. And we don't want that.
62 my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
63 unless ( $INC{$file} ) { die <<"END_DIE" }
64
65Please invoke ${\__PACKAGE__} with:
66
67 use inc::${\__PACKAGE__};
68
69not:
70
71 use ${\__PACKAGE__};
72
73END_DIE
74
75 # This reportedly fixes a rare Win32 UTC file time issue, but
76 # as this is a non-cross-platform XS module not in the core,
77 # we shouldn't really depend on it. See RT #24194 for detail.
78 # (Also, this module only supports Perl 5.6 and above).
79 eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006;
80
81 # If the script that is loading Module::Install is from the future,
82 # then make will detect this and cause it to re-run over and over
83 # again. This is bad. Rather than taking action to touch it (which
84 # is unreliable on some platforms and requires write permissions)
85 # for now we should catch this and refuse to run.
86 if ( -f $0 ) {
87 my $s = (stat($0))[9];
88
89 # If the modification time is only slightly in the future,
90 # sleep briefly to remove the problem.
91 my $a = $s - time;
92 if ( $a > 0 and $a < 5 ) { sleep 5 }
93
94 # Too far in the future, throw an error.
95 my $t = time;
96 if ( $s > $t ) { die <<"END_DIE" }
97
98Your installer $0 has a modification time in the future ($s > $t).
99
100This is known to create infinite loops in make.
101
102Please correct this, then run $0 again.
103
104END_DIE
105 }
106
107
108 # Build.PL was formerly supported, but no longer is due to excessive
109 # difficulty in implementing every single feature twice.
110 if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" }
111
112Module::Install no longer supports Build.PL.
113
114It was impossible to maintain duel backends, and has been deprecated.
115
116Please remove all Build.PL files and only use the Makefile.PL installer.
117
118END_DIE
119
120 #-------------------------------------------------------------
121
122 # To save some more typing in Module::Install installers, every...
123 # use inc::Module::Install
124 # ...also acts as an implicit use strict.
125 $^H |= strict::bits(qw(refs subs vars));
126
127 #-------------------------------------------------------------
128
129 unless ( -f $self->{file} ) {
130 require "$self->{path}/$self->{dispatch}.pm";
131 File::Path::mkpath("$self->{prefix}/$self->{author}");
132 $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
133 $self->{admin}->init;
134 @_ = ($class, _self => $self);
135 goto &{"$self->{name}::import"};
136 }
137
138 *{"${who}::AUTOLOAD"} = $self->autoload;
139 $self->preload;
140
141 # Unregister loader and worker packages so subdirs can use them again
142 delete $INC{"$self->{file}"};
143 delete $INC{"$self->{path}.pm"};
144
145 # Save to the singleton
146 $MAIN = $self;
147
148 return 1;
149}
150
151sub autoload {
152 my $self = shift;
153 my $who = $self->_caller;
154 my $cwd = Cwd::cwd();
155 my $sym = "${who}::AUTOLOAD";
156 $sym->{$cwd} = sub {
157 my $pwd = Cwd::cwd();
158 if ( my $code = $sym->{$pwd} ) {
159 # Delegate back to parent dirs
160 goto &$code unless $cwd eq $pwd;
161 }
162 $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
163 my $method = $1;
164 if ( uc($method) eq $method ) {
165 # Do nothing
166 return;
167 } elsif ( $method =~ /^_/ and $self->can($method) ) {
168 # Dispatch to the root M:I class
169 return $self->$method(@_);
170 }
171
172 # Dispatch to the appropriate plugin
173 unshift @_, ( $self, $1 );
174 goto &{$self->can('call')};
175 };
176}
177
178sub preload {
179 my $self = shift;
180 unless ( $self->{extensions} ) {
181 $self->load_extensions(
182 "$self->{prefix}/$self->{path}", $self
183 );
184 }
185
186 my @exts = @{$self->{extensions}};
187 unless ( @exts ) {
188 @exts = $self->{admin}->load_all_extensions;
189 }
190
191 my %seen;
192 foreach my $obj ( @exts ) {
193 while (my ($method, $glob) = each %{ref($obj) . '::'}) {
194 next unless $obj->can($method);
195 next if $method =~ /^_/;
196 next if $method eq uc($method);
197 $seen{$method}++;
198 }
199 }
200
201 my $who = $self->_caller;
202 foreach my $name ( sort keys %seen ) {
203 *{"${who}::$name"} = sub {
204 ${"${who}::AUTOLOAD"} = "${who}::$name";
205 goto &{"${who}::AUTOLOAD"};
206 };
207 }
208}
209
210sub new {
211 my ($class, %args) = @_;
212
213 # ignore the prefix on extension modules built from top level.
214 my $base_path = Cwd::abs_path($FindBin::Bin);
215 unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
216 delete $args{prefix};
217 }
218
219 return $args{_self} if $args{_self};
220
221 $args{dispatch} ||= 'Admin';
222 $args{prefix} ||= 'inc';
223 $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author');
224 $args{bundle} ||= 'inc/BUNDLES';
225 $args{base} ||= $base_path;
226 $class =~ s/^\Q$args{prefix}\E:://;
227 $args{name} ||= $class;
228 $args{version} ||= $class->VERSION;
229 unless ( $args{path} ) {
230 $args{path} = $args{name};
231 $args{path} =~ s!::!/!g;
232 }
233 $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm";
234 $args{wrote} = 0;
235
236 bless( \%args, $class );
237}
238
239sub call {
240 my ($self, $method) = @_;
241 my $obj = $self->load($method) or return;
242 splice(@_, 0, 2, $obj);
243 goto &{$obj->can($method)};
244}
245
246sub load {
247 my ($self, $method) = @_;
248
249 $self->load_extensions(
250 "$self->{prefix}/$self->{path}", $self
251 ) unless $self->{extensions};
252
253 foreach my $obj (@{$self->{extensions}}) {
254 return $obj if $obj->can($method);
255 }
256
257 my $admin = $self->{admin} or die <<"END_DIE";
258The '$method' method does not exist in the '$self->{prefix}' path!
259Please remove the '$self->{prefix}' directory and run $0 again to load it.
260END_DIE
261
262 my $obj = $admin->load($method, 1);
263 push @{$self->{extensions}}, $obj;
264
265 $obj;
266}
267
268sub load_extensions {
269 my ($self, $path, $top) = @_;
270
271 unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) {
272 unshift @INC, $self->{prefix};
273 }
274
275 foreach my $rv ( $self->find_extensions($path) ) {
276 my ($file, $pkg) = @{$rv};
277 next if $self->{pathnames}{$pkg};
278
279 local $@;
280 my $new = eval { require $file; $pkg->can('new') };
281 unless ( $new ) {
282 warn $@ if $@;
283 next;
284 }
285 $self->{pathnames}{$pkg} = delete $INC{$file};
286 push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
287 }
288
289 $self->{extensions} ||= [];
290}
291
292sub find_extensions {
293 my ($self, $path) = @_;
294
295 my @found;
296 File::Find::find( sub {
297 my $file = $File::Find::name;
298 return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
299 my $subpath = $1;
300 return if lc($subpath) eq lc($self->{dispatch});
301
302 $file = "$self->{path}/$subpath.pm";
303 my $pkg = "$self->{name}::$subpath";
304 $pkg =~ s!/!::!g;
305
306 # If we have a mixed-case package name, assume case has been preserved
307 # correctly. Otherwise, root through the file to locate the case-preserved
308 # version of the package name.
309 if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
310 my $content = Module::Install::_read($subpath . '.pm');
311 my $in_pod = 0;
312 foreach ( split //, $content ) {
313 $in_pod = 1 if /^=\w/;
314 $in_pod = 0 if /^=cut/;
315 next if ($in_pod || /^=cut/); # skip pod text
316 next if /^\s*#/; # and comments
317 if ( m/^\s*package\s+($pkg)\s*;/i ) {
318 $pkg = $1;
319 last;
320 }
321 }
322 }
323
324 push @found, [ $file, $pkg ];
325 }, $path ) if -d $path;
326
327 @found;
328}
329
330
331
332
333
334#####################################################################
335# Common Utility Functions
336
337sub _caller {
338 my $depth = 0;
339 my $call = caller($depth);
340 while ( $call eq __PACKAGE__ ) {
341 $depth++;
342 $call = caller($depth);
343 }
344 return $call;
345}
346
347# Done in evals to avoid confusing Perl::MinimumVersion
348eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
349sub _read {
350 local *FH;
351 open( FH, '<', $_[0] ) or die "open($_[0]): $!";
352 my $string = do { local $/; <FH> };
353 close FH or die "close($_[0]): $!";
354 return $string;
355}
356END_NEW
357sub _read {
358 local *FH;
359 open( FH, "< $_[0]" ) or die "open($_[0]): $!";
360 my $string = do { local $/; <FH> };
361 close FH or die "close($_[0]): $!";
362 return $string;
363}
364END_OLD
365
366sub _readperl {
367 my $string = Module::Install::_read($_[0]);
368 $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
369 $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s;
370 $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg;
371 return $string;
372}
373
374sub _readpod {
375 my $string = Module::Install::_read($_[0]);
376 $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
377 return $string if $_[0] =~ /\.pod\z/;
378 $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg;
379 $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg;
380 $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg;
381 $string =~ s/^\n+//s;
382 return $string;
383}
384
385# Done in evals to avoid confusing Perl::MinimumVersion
386eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
387sub _write {
388 local *FH;
389 open( FH, '>', $_[0] ) or die "open($_[0]): $!";
390 foreach ( 1 .. $#_ ) {
391 print FH $_[$_] or die "print($_[0]): $!";
392 }
393 close FH or die "close($_[0]): $!";
394}
395END_NEW
396sub _write {
397 local *FH;
398 open( FH, "> $_[0]" ) or die "open($_[0]): $!";
399 foreach ( 1 .. $#_ ) {
400 print FH $_[$_] or die "print($_[0]): $!";
401 }
402 close FH or die "close($_[0]): $!";
403}
404END_OLD
405
406# _version is for processing module versions (eg, 1.03_05) not
407# Perl versions (eg, 5.8.1).
408sub _version ($) {
409 my $s = shift || 0;
410 my $d =()= $s =~ /(\.)/g;
411 if ( $d >= 2 ) {
412 # Normalise multipart versions
413 $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg;
414 }
415 $s =~ s/^(\d+)\.?//;
416 my $l = $1 || 0;
417 my @v = map {
418 $_ . '0' x (3 - length $_)
419 } $s =~ /(\d{1,3})\D?/g;
420 $l = $l . '.' . join '', @v if @v;
421 return $l + 0;
422}
423
424sub _cmp ($$) {
425 _version($_[0]) <=> _version($_[1]);
426}
427
428# Cloned from Params::Util::_CLASS
429sub _CLASS ($) {
430 (
431 defined $_[0]
432 and
433 ! ref $_[0]
434 and
435 $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s
436 ) ? $_[0] : undef;
437}
438
4391;
440
441# Copyright 2008 - 2010 Adam Kennedy.