root/inc/Module/Install.pm

Revision 10751, 4.1 kB (checked in by audreyt, 3 years ago)

* Don't break ActivePerl? 5.8.8 on case-insensitive filesystems.

Aankhen++ for catching this age-old bug in inc/Module/Install.pm.

  • Property svn:mime-type set to text/plain; charset=UTF-8
  • Property svn:eol-style set to native
Line 
1package Module::Install;
2$VERSION = '0.36';
3use FindBin;
4
5die << "." unless $INC{join('/', inc => split(/::/, __PACKAGE__)).'.pm'};
6Please invoke ${\__PACKAGE__} with:
7
8    use inc::${\__PACKAGE__};
9
10not:
11
12    use ${\__PACKAGE__};
13
14.
15
16use strict 'vars';
17use Cwd ();
18use File::Find ();
19use File::Path ();
20
21@inc::Module::Install::ISA = 'Module::Install';
22*inc::Module::Install::VERSION = *VERSION;
23
24sub import {
25    my $class = shift;
26    my $self = $class->new(@_);
27
28    if (not -f $self->{file}) {
29        require Cwd;
30        die << ".";
31*** Error: $self->{file} does not exist!
32    Current directory is @{[Cwd::abs_path(Cwd::cwd())]}
33    Program path is @{[Cwd::abs_path($FindBin::Bin)]}
34*** Please report this issue to <perl6-compiler\@perl.org>.
35.
36        require "$self->{path}/$self->{dispatch}.pm";
37        File::Path::mkpath("$self->{prefix}/$self->{author}");
38        $self->{admin} =
39          "$self->{name}::$self->{dispatch}"->new(_top => $self);
40        $self->{admin}->init;
41        @_ = ($class, _self => $self);
42        goto &{"$self->{name}::import"};
43    }
44
45    *{caller(0) . "::AUTOLOAD"} = $self->autoload;
46
47    # Unregister loader and worker packages so subdirs can use them again
48    delete $INC{"$self->{file}"};
49    delete $INC{"$self->{path}.pm"};
50}
51
52sub autoload {
53    my $self = shift;
54    my $caller = caller;
55
56    my $cwd = Cwd::cwd();
57    my $sym = "$caller\::AUTOLOAD";
58
59    $sym->{$cwd} = sub {
60        my $pwd = Cwd::cwd();
61        if (my $code = $sym->{$pwd}) {
62            goto &$code unless $cwd eq $pwd; # delegate back to parent dirs
63        }
64        $$sym =~ /([^:]+)$/ or die "Cannot autoload $caller";
65        unshift @_, ($self, $1);
66        goto &{$self->can('call')} unless uc($1) eq $1;
67    };
68}
69
70use Cwd qw(cwd abs_path);
71sub new {
72    my ($class, %args) = @_;
73
74    # ignore the prefix on extension modules built from top level.
75    delete $args{prefix}
76      unless Cwd::abs_path(Cwd::cwd()) eq Cwd::abs_path($FindBin::Bin);
77
78    return $args{_self} if $args{_self};
79
80    $args{dispatch} ||= 'Admin';
81    $args{prefix}   ||= 'inc';
82    $args{author}   ||= '.author';
83    $args{bundle}   ||= 'inc/BUNDLES';
84    $args{base}     ||= Cwd::abs_path($FindBin::Bin);
85
86    $class =~ s/^inc:://;
87    $args{name}     ||= $class;
88    $args{version}  ||= $class->VERSION;
89
90    unless ($args{path}) {
91        $args{path}  = $args{name};
92        $args{path}  =~ s!::!/!g;
93    }
94    $args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
95
96    bless(\%args, $class);
97}
98
99sub call {
100    my $self   = shift;
101    my $method = shift;
102    my $obj = $self->load($method) or return;
103
104    unshift @_, $obj;
105    goto &{$obj->can($method)};
106}
107
108sub load {
109    my ($self, $method) = @_;
110
111    my $extensions = $self->{extensions} || [];
112    unless (@$extensions) {
113        $self->load_extensions("$self->{prefix}/$self->{path}", $self);
114    }
115
116    foreach my $obj (@{$self->{extensions}}) {
117        return $obj if $obj->can($method);
118    }
119
120    my $admin = $self->{admin} or die << "END";
121The '$method' method does not exist in the '$self->{prefix}' path!
122Please remove the '$self->{prefix}' directory and run $0 again to load it.
123END
124
125    my $obj = $admin->load($method, 1);
126    push @{$self->{extensions}}, $obj;
127
128    $obj;
129}
130
131sub load_extensions {
132    my ($self, $path, $top_obj) = @_;
133    $path = "$self->{base}/$path";
134
135    unshift @INC, $self->{prefix}
136        unless grep { $_ eq $self->{prefix} } @INC;
137
138    foreach my $rv ($self->find_extensions($path)) {
139        my ($file, $pkg) = @{$rv};
140        next if $self->{pathnames}{$pkg};
141
142        eval { require $file; 1 } or (warn($@), next);
143        $self->{pathnames}{$pkg} = delete $INC{$file};
144        push @{$self->{extensions}}, $pkg->new( _top => $top_obj );
145    }
146}
147
148sub find_extensions {
149    my ($self, $path) = @_;
150    my @found;
151
152    File::Find::find(sub {
153        my $file = $File::Find::name;
154        return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
155        return if $1 eq $self->{dispatch};
156
157        $file = "$self->{path}/$1.pm";
158        my $pkg = "$self->{name}::$1"; $pkg =~ s!/!::!g;
159        push @found, [$file, $pkg];
160    }, $path) if -d $path;
161
162    @found;
163}
164
1651;
166
167__END__
Note: See TracBrowser for help on using the browser.