Add the following packages libalgorithm-diff-perl libspiffy-perl libtext-diff-perl...
[pkg-perl] / deb-src / libspiffy-perl / libspiffy-perl-0.30 / inc / Module / Install.pm
1 #line 1 "/Users/ingy/src/ingy/Spiffy/inc/Module/Install.pm - /Users/ingy/local/lib/perl5/site_perl/5.8.6/Module/Install.pm"
2 package Module::Install;
3
4 use 5.004;
5 use strict 'vars';
6 use vars qw{$VERSION};
7 BEGIN {
8     # Don't forget to update Module::Install::Admin too!
9     $VERSION = '0.54';
10 }
11
12 # inc::Module::Install must be loaded first
13 unless ( $INC{join('/', inc => split(/::/, __PACKAGE__)).'.pm'} ) {
14     die <<"END_DIE";
15 Please invoke ${\__PACKAGE__} with:
16
17     use inc::${\__PACKAGE__};
18
19 not:
20
21     use ${\__PACKAGE__};
22
23 END_DIE
24 }
25
26 use Cwd        ();
27 use FindBin;
28 use File::Find ();
29 use File::Path ();
30
31 *inc::Module::Install::VERSION = *VERSION;
32 @inc::Module::Install::ISA     = 'Module::Install';
33
34 sub autoload {
35     my $self   = shift;
36     my $caller = $self->_caller;
37     my $cwd    = Cwd::cwd();
38     my $sym    = "$caller\::AUTOLOAD";
39
40     $sym->{$cwd} = sub {
41         my $pwd = Cwd::cwd();
42         if ( my $code = $sym->{$pwd} ) {
43             # delegate back to parent dirs
44             goto &$code unless $cwd eq $pwd;
45         }
46         $$sym =~ /([^:]+)$/ or die "Cannot autoload $caller - $sym";
47         unshift @_, ($self, $1);
48         goto &{$self->can('call')} unless uc($1) eq $1;
49     };
50 }
51
52 sub import {
53     my $class = shift;
54     my $self  = $class->new(@_);
55
56     unless ( -f $self->{file} ) {
57         require "$self->{path}/$self->{dispatch}.pm";
58         File::Path::mkpath("$self->{prefix}/$self->{author}");
59         $self->{admin} = 
60           "$self->{name}::$self->{dispatch}"->new(_top => $self);
61         $self->{admin}->init;
62         @_ = ($class, _self => $self);
63         goto &{"$self->{name}::import"};
64     }
65
66     *{$self->_caller . "::AUTOLOAD"} = $self->autoload;
67     $self->preload;
68
69     # Unregister loader and worker packages so subdirs can use them again
70     delete $INC{"$self->{file}"};
71     delete $INC{"$self->{path}.pm"};
72 }
73
74 sub preload {
75     my ($self) = @_;
76
77         unless ( $self->{extentions} ) {
78                 $self->load_extensions(
79                         "$self->{prefix}/$self->{path}", $self
80                         );
81         }
82
83     my @exts = @{$self->{extensions}};
84     unless ( @exts ) {
85         my $admin = $self->{admin};
86         @exts = $admin->load_all_extensions;
87     }
88
89     my %seen_method;
90     foreach my $obj ( @exts ) {
91         while (my ($method, $glob) = each %{ref($obj) . '::'}) {
92             next unless defined *{$glob}{CODE};
93             next if $method =~ /^_/;
94             next if $method eq uc($method);
95             $seen_method{$method}++;
96         }
97     }
98
99     my $caller = $self->_caller;
100     foreach my $name (sort keys %seen_method) {
101         *{"${caller}::$name"} = sub {
102             ${"${caller}::AUTOLOAD"} = "${caller}::$name";
103             goto &{"${caller}::AUTOLOAD"};
104         };
105     }
106 }
107
108 sub new {
109     my ($class, %args) = @_;
110
111     # ignore the prefix on extension modules built from top level.
112     my $base_path = Cwd::abs_path($FindBin::Bin);
113     unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
114         delete $args{prefix};
115     }
116
117     return $args{_self} if $args{_self};
118
119     $args{dispatch} ||= 'Admin';
120     $args{prefix}   ||= 'inc';
121     $args{author}   ||= '.author';
122     $args{bundle}   ||= 'inc/BUNDLES';
123     $args{base}     ||= $base_path;
124
125     $class =~ s/^\Q$args{prefix}\E:://;
126     $args{name}     ||= $class;
127     $args{version}  ||= $class->VERSION;
128
129     unless ($args{path}) {
130         $args{path}  = $args{name};
131         $args{path}  =~ s!::!/!g;
132     }
133     $args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
134
135     bless(\%args, $class);
136 }
137
138 sub call {
139     my $self   = shift;
140     my $method = shift;
141     my $obj    = $self->load($method) or return;
142
143     unshift @_, $obj;
144     goto &{$obj->can($method)};
145 }
146
147 sub load {
148     my ($self, $method) = @_;
149
150     $self->load_extensions(
151         "$self->{prefix}/$self->{path}", $self
152     ) unless $self->{extensions};
153
154     foreach my $obj (@{$self->{extensions}}) {
155         return $obj if $obj->can($method);
156     }
157
158     my $admin = $self->{admin} or die <<"END_DIE";
159 The '$method' method does not exist in the '$self->{prefix}' path!
160 Please remove the '$self->{prefix}' directory and run $0 again to load it.
161 END_DIE
162
163     my $obj = $admin->load($method, 1);
164     push @{$self->{extensions}}, $obj;
165
166     $obj;
167 }
168
169 sub load_extensions {
170     my ($self, $path, $top_obj) = @_;
171
172     unshift @INC, $self->{prefix}
173         unless grep { $_ eq $self->{prefix} } @INC;
174
175     local @INC = ($path, @INC);
176     foreach my $rv ($self->find_extensions($path)) {
177         my ($file, $pkg) = @{$rv};
178         next if $self->{pathnames}{$pkg};
179
180         local $@;
181         my $new = eval { require $file; $pkg->can('new') };
182         unless ( $new ) {
183             warn $@ if $@;
184             next;
185         }
186         $self->{pathnames}{$pkg} = delete $INC{$file};
187         push @{$self->{extensions}}, &{$new}($pkg, _top => $top_obj );
188     }
189
190     $self->{extensions} ||= [];
191 }
192
193 sub find_extensions {
194     my ($self, $path) = @_;
195
196     my @found;
197     File::Find::find( sub {
198         my $file = $File::Find::name;
199         return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
200         return if $1 eq $self->{dispatch};
201
202         $file = "$self->{path}/$1.pm";
203         my $pkg = "$self->{name}::$1"; $pkg =~ s!/!::!g;
204         push @found, [ $file, $pkg ];
205     }, $path ) if -d $path;
206
207     @found;
208 }
209
210 sub _caller {
211     my $depth  = 0;
212     my $caller = caller($depth);
213
214     while ($caller eq __PACKAGE__) {
215         $depth++;
216         $caller = caller($depth);
217     }
218
219     $caller;
220 }
221
222 1;