This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Be sure to find the vmsish pragma for one-liners in exit.t.
[perl5.git] / lib / CPAN / Bundle.pm
CommitLineData
f9916dde
A
1# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2# vim: ts=4 sts=4 sw=4:
3package CPAN::Bundle;
4use strict;
5use CPAN::Module;
6@CPAN::Bundle::ISA = qw(CPAN::Module);
7
8use vars qw(
9 $VERSION
10);
11$VERSION = "5.5";
12
13sub look {
14 my $self = shift;
15 $CPAN::Frontend->myprint($self->as_string);
16}
17
18#-> CPAN::Bundle::undelay
19sub undelay {
20 my $self = shift;
21 delete $self->{later};
22 for my $c ( $self->contains ) {
23 my $obj = CPAN::Shell->expandany($c) or next;
24 $obj->undelay;
25 }
26}
27
28# mark as dirty/clean
29#-> sub CPAN::Bundle::color_cmd_tmps ;
30sub color_cmd_tmps {
31 my($self) = shift;
32 my($depth) = shift || 0;
33 my($color) = shift || 0;
34 my($ancestors) = shift || [];
35 # a module needs to recurse to its cpan_file, a distribution needs
36 # to recurse into its prereq_pms, a bundle needs to recurse into its modules
37
38 return if exists $self->{incommandcolor}
39 && $color==1
40 && $self->{incommandcolor}==$color;
41 if ($depth>=$CPAN::MAX_RECURSION) {
42 die(CPAN::Exception::RecursiveDependency->new($ancestors));
43 }
44 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
45
46 for my $c ( $self->contains ) {
47 my $obj = CPAN::Shell->expandany($c) or next;
48 CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG;
49 $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
50 }
51 # never reached code?
52 #if ($color==0) {
53 #delete $self->{badtestcnt};
54 #}
55 $self->{incommandcolor} = $color;
56}
57
58#-> sub CPAN::Bundle::as_string ;
59sub as_string {
60 my($self) = @_;
61 $self->contains;
62 # following line must be "=", not "||=" because we have a moving target
63 $self->{INST_VERSION} = $self->inst_version;
64 return $self->SUPER::as_string;
65}
66
67#-> sub CPAN::Bundle::contains ;
68sub contains {
69 my($self) = @_;
70 my($inst_file) = $self->inst_file || "";
71 my($id) = $self->id;
72 $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG;
73 if ($inst_file && CPAN::Version->vlt($self->inst_version,$self->cpan_version)) {
74 undef $inst_file;
75 }
76 unless ($inst_file) {
77 # Try to get at it in the cpan directory
78 $self->debug("no inst_file") if $CPAN::DEBUG;
79 my $cpan_file;
80 $CPAN::Frontend->mydie("I don't know a bundle with ID $id\n") unless
81 $cpan_file = $self->cpan_file;
82 if ($cpan_file eq "N/A") {
83 $CPAN::Frontend->mydie("Bundle $id not found on disk and not on CPAN.
84 Maybe stale symlink? Maybe removed during session? Giving up.\n");
85 }
86 my $dist = $CPAN::META->instance('CPAN::Distribution',
87 $self->cpan_file);
88 $self->debug("before get id[$dist->{ID}]") if $CPAN::DEBUG;
89 $dist->get;
90 $self->debug("after get id[$dist->{ID}]") if $CPAN::DEBUG;
91 my($todir) = $CPAN::Config->{'cpan_home'};
92 my(@me,$from,$to,$me);
93 @me = split /::/, $self->id;
94 $me[-1] .= ".pm";
95 $me = File::Spec->catfile(@me);
96 $from = $self->find_bundle_file($dist->{build_dir},join('/',@me));
97 $to = File::Spec->catfile($todir,$me);
98 File::Path::mkpath(File::Basename::dirname($to));
99 File::Copy::copy($from, $to)
100 or Carp::confess("Couldn't copy $from to $to: $!");
101 $inst_file = $to;
102 }
103 my @result;
104 my $fh = FileHandle->new;
105 local $/ = "\n";
106 open($fh,$inst_file) or die "Could not open '$inst_file': $!";
107 my $in_cont = 0;
108 $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG;
109 while (<$fh>) {
110 $in_cont = m/^=(?!head1\s+(?i-xsm:CONTENTS))/ ? 0 :
111 m/^=head1\s+(?i-xsm:CONTENTS)/ ? 1 : $in_cont;
112 next unless $in_cont;
113 next if /^=/;
114 s/\#.*//;
115 next if /^\s+$/;
116 chomp;
117 push @result, (split " ", $_, 2)[0];
118 }
119 close $fh;
120 delete $self->{STATUS};
121 $self->{CONTAINS} = \@result;
122 $self->debug("CONTAINS[@result]") if $CPAN::DEBUG;
123 unless (@result) {
124 $CPAN::Frontend->mywarn(qq{
125The bundle file "$inst_file" may be a broken
126bundlefile. It seems not to contain any bundle definition.
127Please check the file and if it is bogus, please delete it.
128Sorry for the inconvenience.
129});
130 }
131 @result;
132}
133
134#-> sub CPAN::Bundle::find_bundle_file
135# $where is in local format, $what is in unix format
136sub find_bundle_file {
137 my($self,$where,$what) = @_;
138 $self->debug("where[$where]what[$what]") if $CPAN::DEBUG;
139### The following two lines let CPAN.pm become Bundle/CPAN.pm :-(
140### my $bu = File::Spec->catfile($where,$what);
141### return $bu if -f $bu;
142 my $manifest = File::Spec->catfile($where,"MANIFEST");
143 unless (-f $manifest) {
144 require ExtUtils::Manifest;
145 my $cwd = CPAN::anycwd();
146 $self->safe_chdir($where);
147 ExtUtils::Manifest::mkmanifest();
148 $self->safe_chdir($cwd);
149 }
150 my $fh = FileHandle->new($manifest)
151 or Carp::croak("Couldn't open $manifest: $!");
152 local($/) = "\n";
153 my $bundle_filename = $what;
154 $bundle_filename =~ s|Bundle.*/||;
155 my $bundle_unixpath;
156 while (<$fh>) {
157 next if /^\s*\#/;
158 my($file) = /(\S+)/;
159 if ($file =~ m|\Q$what\E$|) {
160 $bundle_unixpath = $file;
161 # return File::Spec->catfile($where,$bundle_unixpath); # bad
162 last;
163 }
164 # retry if she managed to have no Bundle directory
165 $bundle_unixpath = $file if $file =~ m|\Q$bundle_filename\E$|;
166 }
167 return File::Spec->catfile($where, split /\//, $bundle_unixpath)
168 if $bundle_unixpath;
169 Carp::croak("Couldn't find a Bundle file in $where");
170}
171
172# needs to work quite differently from Module::inst_file because of
173# cpan_home/Bundle/ directory and the possibility that we have
174# shadowing effect. As it makes no sense to take the first in @INC for
175# Bundles, we parse them all for $VERSION and take the newest.
176
177#-> sub CPAN::Bundle::inst_file ;
178sub inst_file {
179 my($self) = @_;
180 my($inst_file);
181 my(@me);
182 @me = split /::/, $self->id;
183 $me[-1] .= ".pm";
184 my($incdir,$bestv);
185 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
186 my $parsefile = File::Spec->catfile($incdir, @me);
187 CPAN->debug("parsefile[$parsefile]") if $CPAN::DEBUG;
188 next unless -f $parsefile;
189 my $have = eval { MM->parse_version($parsefile); };
190 if ($@) {
191 $CPAN::Frontend->mywarn("Error while parsing version number in file '$parsefile'\n");
192 }
193 if (!$bestv || CPAN::Version->vgt($have,$bestv)) {
194 $self->{INST_FILE} = $parsefile;
195 $self->{INST_VERSION} = $bestv = $have;
196 }
197 }
198 $self->{INST_FILE};
199}
200
201#-> sub CPAN::Bundle::inst_version ;
202sub inst_version {
203 my($self) = @_;
204 $self->inst_file; # finds INST_VERSION as side effect
205 $self->{INST_VERSION};
206}
207
208#-> sub CPAN::Bundle::rematein ;
209sub rematein {
210 my($self,$meth) = @_;
211 $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG;
212 my($id) = $self->id;
213 Carp::croak( "Can't $meth $id, don't have an associated bundle file. :-(\n" )
214 unless $self->inst_file || $self->cpan_file;
215 my($s,%fail);
216 for $s ($self->contains) {
217 my($type) = $s =~ m|/| ? 'CPAN::Distribution' :
218 $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module';
219 if ($type eq 'CPAN::Distribution') {
220 $CPAN::Frontend->mywarn(qq{
221The Bundle }.$self->id.qq{ contains
222explicitly a file '$s'.
223Going to $meth that.
224});
225 $CPAN::Frontend->mysleep(5);
226 }
227 # possibly noisy action:
228 $self->debug("type[$type] s[$s]") if $CPAN::DEBUG;
229 my $obj = $CPAN::META->instance($type,$s);
230 $obj->{reqtype} = $self->{reqtype};
231 $obj->$meth();
232 }
233}
234
235# If a bundle contains another that contains an xs_file we have here,
236# we just don't bother I suppose
237#-> sub CPAN::Bundle::xs_file
238sub xs_file {
239 return 0;
240}
241
242#-> sub CPAN::Bundle::force ;
243sub fforce { shift->rematein('fforce',@_); }
244#-> sub CPAN::Bundle::force ;
245sub force { shift->rematein('force',@_); }
246#-> sub CPAN::Bundle::notest ;
247sub notest { shift->rematein('notest',@_); }
248#-> sub CPAN::Bundle::get ;
249sub get { shift->rematein('get',@_); }
250#-> sub CPAN::Bundle::make ;
251sub make { shift->rematein('make',@_); }
252#-> sub CPAN::Bundle::test ;
253sub test {
254 my $self = shift;
255 # $self->{badtestcnt} ||= 0;
256 $self->rematein('test',@_);
257}
258#-> sub CPAN::Bundle::install ;
259sub install {
260 my $self = shift;
261 $self->rematein('install',@_);
262}
263#-> sub CPAN::Bundle::clean ;
264sub clean { shift->rematein('clean',@_); }
265
266#-> sub CPAN::Bundle::uptodate ;
267sub uptodate {
268 my($self) = @_;
269 return 0 unless $self->SUPER::uptodate; # we mut have the current Bundle def
270 my $c;
271 foreach $c ($self->contains) {
272 my $obj = CPAN::Shell->expandany($c);
273 return 0 unless $obj->uptodate;
274 }
275 return 1;
276}
277
278#-> sub CPAN::Bundle::readme ;
279sub readme {
280 my($self) = @_;
281 my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{
282No File found for bundle } . $self->id . qq{\n}), return;
283 $self->debug("self[$self] file[$file]") if $CPAN::DEBUG;
284 $CPAN::META->instance('CPAN::Distribution',$file)->readme;
285}
286
2871;