1# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- 2package CPAN; 3$VERSION = '1.76_01'; 4$VERSION = eval $VERSION; 5# $Id: CPAN.pm,v 1.412 2003/07/31 14:53:04 k Exp $ 6 7# only used during development: 8$Revision = ""; 9# $Revision = "[".substr(q$Revision: 1.412 $, 10)."]"; 10 11use Carp (); 12use Config (); 13use Cwd (); 14use DirHandle; 15use Exporter (); 16use ExtUtils::MakeMaker (); # $SelfLoader::DEBUG=1; 17use File::Basename (); 18use File::Copy (); 19use File::Find; 20use File::Path (); 21use FileHandle (); 22use Safe (); 23use Text::ParseWords (); 24use Text::Wrap; 25use File::Spec; 26use Sys::Hostname; 27no lib "."; # we need to run chdir all over and we would get at wrong 28 # libraries there 29 30require Mac::BuildTools if $^O eq 'MacOS'; 31 32END { $End++; &cleanup; } 33 34%CPAN::DEBUG = qw[ 35 CPAN 1 36 Index 2 37 InfoObj 4 38 Author 8 39 Distribution 16 40 Bundle 32 41 Module 64 42 CacheMgr 128 43 Complete 256 44 FTP 512 45 Shell 1024 46 Eval 2048 47 Config 4096 48 Tarzip 8192 49 Version 16384 50 Queue 32768 51]; 52 53$CPAN::DEBUG ||= 0; 54$CPAN::Signal ||= 0; 55$CPAN::Frontend ||= "CPAN::Shell"; 56$CPAN::Defaultsite ||= "ftp://ftp.perl.org/pub/CPAN"; 57 58package CPAN; 59use strict qw(vars); 60 61use vars qw($VERSION @EXPORT $AUTOLOAD $DEBUG $META $HAS_USABLE $term 62 $Revision $Signal $End $Suppress_readline $Frontend 63 $Defaultsite $Have_warned); 64 65@CPAN::ISA = qw(CPAN::Debug Exporter); 66 67@EXPORT = qw( 68 autobundle bundle expand force get cvs_import 69 install make readme recompile shell test clean 70 ); 71 72#-> sub CPAN::AUTOLOAD ; 73sub AUTOLOAD { 74 my($l) = $AUTOLOAD; 75 $l =~ s/.*:://; 76 my(%EXPORT); 77 @EXPORT{@EXPORT} = ''; 78 CPAN::Config->load unless $CPAN::Config_loaded++; 79 if (exists $EXPORT{$l}){ 80 CPAN::Shell->$l(@_); 81 } else { 82 $CPAN::Frontend->mywarn(qq{Unknown command "$AUTOLOAD". }. 83 qq{Type ? for help. 84}); 85 } 86} 87 88#-> sub CPAN::shell ; 89sub shell { 90 my($self) = @_; 91 $Suppress_readline = ! -t STDIN unless defined $Suppress_readline; 92 CPAN::Config->load unless $CPAN::Config_loaded++; 93 94 my $oprompt = shift || "cpan> "; 95 my $prompt = $oprompt; 96 my $commandline = shift || ""; 97 98 local($^W) = 1; 99 unless ($Suppress_readline) { 100 require Term::ReadLine; 101 if (! $term 102 or 103 $term->ReadLine eq "Term::ReadLine::Stub" 104 ) { 105 $term = Term::ReadLine->new('CPAN Monitor'); 106 } 107 if ($term->ReadLine eq "Term::ReadLine::Gnu") { 108 my $attribs = $term->Attribs; 109 $attribs->{attempted_completion_function} = sub { 110 &CPAN::Complete::gnu_cpl; 111 } 112 } else { 113 $readline::rl_completion_function = 114 $readline::rl_completion_function = 'CPAN::Complete::cpl'; 115 } 116 if (my $histfile = $CPAN::Config->{'histfile'}) {{ 117 unless ($term->can("AddHistory")) { 118 $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n"); 119 last; 120 } 121 my($fh) = FileHandle->new; 122 open $fh, "<$histfile" or last; 123 local $/ = "\n"; 124 while (<$fh>) { 125 chomp; 126 $term->AddHistory($_); 127 } 128 close $fh; 129 }} 130 # $term->OUT is autoflushed anyway 131 my $odef = select STDERR; 132 $| = 1; 133 select STDOUT; 134 $| = 1; 135 select $odef; 136 } 137 138 # no strict; # I do not recall why no strict was here (2000-09-03) 139 $META->checklock(); 140 my $cwd = CPAN::anycwd(); 141 my $try_detect_readline; 142 $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term; 143 my $rl_avail = $Suppress_readline ? "suppressed" : 144 ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" : 145 "available (try 'install Bundle::CPAN')"; 146 147 $CPAN::Frontend->myprint( 148 sprintf qq{ 149cpan shell -- CPAN exploration and modules installation (v%s%s) 150ReadLine support %s 151 152}, 153 $CPAN::VERSION, 154 $CPAN::Revision, 155 $rl_avail 156 ) 157 unless $CPAN::Config->{'inhibit_startup_message'} ; 158 my($continuation) = ""; 159 SHELLCOMMAND: while () { 160 if ($Suppress_readline) { 161 print $prompt; 162 last SHELLCOMMAND unless defined ($_ = <> ); 163 chomp; 164 } else { 165 last SHELLCOMMAND unless 166 defined ($_ = $term->readline($prompt, $commandline)); 167 } 168 $_ = "$continuation$_" if $continuation; 169 s/^\s+//; 170 next SHELLCOMMAND if /^$/; 171 $_ = 'h' if /^\s*\?/; 172 if (/^(?:q(?:uit)?|bye|exit)$/i) { 173 last SHELLCOMMAND; 174 } elsif (s/\\$//s) { 175 chomp; 176 $continuation = $_; 177 $prompt = " > "; 178 } elsif (/^\!/) { 179 s/^\!//; 180 my($eval) = $_; 181 package CPAN::Eval; 182 use vars qw($import_done); 183 CPAN->import(':DEFAULT') unless $import_done++; 184 CPAN->debug("eval[$eval]") if $CPAN::DEBUG; 185 eval($eval); 186 warn $@ if $@; 187 $continuation = ""; 188 $prompt = $oprompt; 189 } elsif (/./) { 190 my(@line); 191 if ($] < 5.00322) { # parsewords had a bug until recently 192 @line = split; 193 } else { 194 eval { @line = Text::ParseWords::shellwords($_) }; 195 warn($@), next SHELLCOMMAND if $@; 196 warn("Text::Parsewords could not parse the line [$_]"), 197 next SHELLCOMMAND unless @line; 198 } 199 $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG; 200 my $command = shift @line; 201 eval { CPAN::Shell->$command(@line) }; 202 warn $@ if $@; 203 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!}); 204 $CPAN::Frontend->myprint("\n"); 205 $continuation = ""; 206 $prompt = $oprompt; 207 } 208 } continue { 209 $commandline = ""; # I do want to be able to pass a default to 210 # shell, but on the second command I see no 211 # use in that 212 $Signal=0; 213 CPAN::Queue->nullify_queue; 214 if ($try_detect_readline) { 215 if ($CPAN::META->has_inst("Term::ReadLine::Gnu") 216 || 217 $CPAN::META->has_inst("Term::ReadLine::Perl") 218 ) { 219 delete $INC{"Term/ReadLine.pm"}; 220 my $redef = 0; 221 local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef); 222 require Term::ReadLine; 223 $CPAN::Frontend->myprint("\n$redef subroutines in ". 224 "Term::ReadLine redefined\n"); 225 @_ = ($oprompt,""); 226 goto &shell; 227 } 228 } 229 } 230 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!}); 231} 232 233package CPAN::CacheMgr; 234@CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN); 235use File::Find; 236 237package CPAN::Config; 238use vars qw(%can $dot_cpan); 239 240%can = ( 241 'commit' => "Commit changes to disk", 242 'defaults' => "Reload defaults from disk", 243 'init' => "Interactive setting of all options", 244); 245 246package CPAN::FTP; 247use vars qw($Ua $Thesite $Themethod); 248@CPAN::FTP::ISA = qw(CPAN::Debug); 249 250package CPAN::LWP::UserAgent; 251use vars qw(@ISA $USER $PASSWD $SETUPDONE); 252# we delay requiring LWP::UserAgent and setting up inheritence until we need it 253 254package CPAN::Complete; 255@CPAN::Complete::ISA = qw(CPAN::Debug); 256@CPAN::Complete::COMMANDS = sort qw( 257 ! a b d h i m o q r u autobundle clean dump 258 make test install force readme reload look 259 cvs_import ls 260) unless @CPAN::Complete::COMMANDS; 261 262package CPAN::Index; 263use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03); 264@CPAN::Index::ISA = qw(CPAN::Debug); 265$LAST_TIME ||= 0; 266$DATE_OF_03 ||= 0; 267# use constant PROTOCOL => "2.0"; # outcommented to avoid warning on upgrade from 1.57 268sub PROTOCOL { 2.0 } 269 270package CPAN::InfoObj; 271@CPAN::InfoObj::ISA = qw(CPAN::Debug); 272 273package CPAN::Author; 274@CPAN::Author::ISA = qw(CPAN::InfoObj); 275 276package CPAN::Distribution; 277@CPAN::Distribution::ISA = qw(CPAN::InfoObj); 278 279package CPAN::Bundle; 280@CPAN::Bundle::ISA = qw(CPAN::Module); 281 282package CPAN::Module; 283@CPAN::Module::ISA = qw(CPAN::InfoObj); 284 285package CPAN::Exception::RecursiveDependency; 286use overload '""' => "as_string"; 287 288sub new { 289 my($class) = shift; 290 my($deps) = shift; 291 my @deps; 292 my %seen; 293 for my $dep (@$deps) { 294 push @deps, $dep; 295 last if $seen{$dep}++; 296 } 297 bless { deps => \@deps }, $class; 298} 299 300sub as_string { 301 my($self) = shift; 302 "\nRecursive dependency detected:\n " . 303 join("\n => ", @{$self->{deps}}) . 304 ".\nCannot continue.\n"; 305} 306 307package CPAN::Shell; 308use vars qw($AUTOLOAD @ISA $COLOR_REGISTERED $ADVANCED_QUERY $PRINT_ORNAMENTING); 309@CPAN::Shell::ISA = qw(CPAN::Debug); 310$COLOR_REGISTERED ||= 0; 311$PRINT_ORNAMENTING ||= 0; 312 313#-> sub CPAN::Shell::AUTOLOAD ; 314sub AUTOLOAD { 315 my($autoload) = $AUTOLOAD; 316 my $class = shift(@_); 317 # warn "autoload[$autoload] class[$class]"; 318 $autoload =~ s/.*:://; 319 if ($autoload =~ /^w/) { 320 if ($CPAN::META->has_inst('CPAN::WAIT')) { 321 CPAN::WAIT->$autoload(@_); 322 } else { 323 $CPAN::Frontend->mywarn(qq{ 324Commands starting with "w" require CPAN::WAIT to be installed. 325Please consider installing CPAN::WAIT to use the fulltext index. 326For this you just need to type 327 install CPAN::WAIT 328}); 329 } 330 } else { 331 $CPAN::Frontend->mywarn(qq{Unknown command '$autoload'. }. 332 qq{Type ? for help. 333}); 334 } 335} 336 337package CPAN::Tarzip; 338use vars qw($AUTOLOAD @ISA $BUGHUNTING); 339@CPAN::Tarzip::ISA = qw(CPAN::Debug); 340$BUGHUNTING = 0; # released code must have turned off 341 342package CPAN::Queue; 343 344# One use of the queue is to determine if we should or shouldn't 345# announce the availability of a new CPAN module 346 347# Now we try to use it for dependency tracking. For that to happen 348# we need to draw a dependency tree and do the leaves first. This can 349# easily be reached by running CPAN.pm recursively, but we don't want 350# to waste memory and run into deep recursion. So what we can do is 351# this: 352 353# CPAN::Queue is the package where the queue is maintained. Dependencies 354# often have high priority and must be brought to the head of the queue, 355# possibly by jumping the queue if they are already there. My first code 356# attempt tried to be extremely correct. Whenever a module needed 357# immediate treatment, I either unshifted it to the front of the queue, 358# or, if it was already in the queue, I spliced and let it bypass the 359# others. This became a too correct model that made it impossible to put 360# an item more than once into the queue. Why would you need that? Well, 361# you need temporary duplicates as the manager of the queue is a loop 362# that 363# 364# (1) looks at the first item in the queue without shifting it off 365# 366# (2) cares for the item 367# 368# (3) removes the item from the queue, *even if its agenda failed and 369# even if the item isn't the first in the queue anymore* (that way 370# protecting against never ending queues) 371# 372# So if an item has prerequisites, the installation fails now, but we 373# want to retry later. That's easy if we have it twice in the queue. 374# 375# I also expect insane dependency situations where an item gets more 376# than two lives in the queue. Simplest example is triggered by 'install 377# Foo Foo Foo'. People make this kind of mistakes and I don't want to 378# get in the way. I wanted the queue manager to be a dumb servant, not 379# one that knows everything. 380# 381# Who would I tell in this model that the user wants to be asked before 382# processing? I can't attach that information to the module object, 383# because not modules are installed but distributions. So I'd have to 384# tell the distribution object that it should ask the user before 385# processing. Where would the question be triggered then? Most probably 386# in CPAN::Distribution::rematein. 387# Hope that makes sense, my head is a bit off:-) -- AK 388 389use vars qw{ @All }; 390 391# CPAN::Queue::new ; 392sub new { 393 my($class,$s) = @_; 394 my $self = bless { qmod => $s }, $class; 395 push @All, $self; 396 return $self; 397} 398 399# CPAN::Queue::first ; 400sub first { 401 my $obj = $All[0]; 402 $obj->{qmod}; 403} 404 405# CPAN::Queue::delete_first ; 406sub delete_first { 407 my($class,$what) = @_; 408 my $i; 409 for my $i (0..$#All) { 410 if ( $All[$i]->{qmod} eq $what ) { 411 splice @All, $i, 1; 412 return; 413 } 414 } 415} 416 417# CPAN::Queue::jumpqueue ; 418sub jumpqueue { 419 my $class = shift; 420 my @what = @_; 421 CPAN->debug(sprintf("before jumpqueue All[%s] what[%s]", 422 join(",",map {$_->{qmod}} @All), 423 join(",",@what) 424 )) if $CPAN::DEBUG; 425 WHAT: for my $what (reverse @what) { 426 my $jumped = 0; 427 for (my $i=0; $i<$#All;$i++) { #prevent deep recursion 428 CPAN->debug("i[$All[$i]]what[$what]") if $CPAN::DEBUG; 429 if ($All[$i]->{qmod} eq $what){ 430 $jumped++; 431 if ($jumped > 100) { # one's OK if e.g. just 432 # processing now; more are OK if 433 # user typed it several times 434 $CPAN::Frontend->mywarn( 435qq{Object [$what] queued more than 100 times, ignoring} 436 ); 437 next WHAT; 438 } 439 } 440 } 441 my $obj = bless { qmod => $what }, $class; 442 unshift @All, $obj; 443 } 444 CPAN->debug(sprintf("after jumpqueue All[%s] what[%s]", 445 join(",",map {$_->{qmod}} @All), 446 join(",",@what) 447 )) if $CPAN::DEBUG; 448} 449 450# CPAN::Queue::exists ; 451sub exists { 452 my($self,$what) = @_; 453 my @all = map { $_->{qmod} } @All; 454 my $exists = grep { $_->{qmod} eq $what } @All; 455 # warn "in exists what[$what] all[@all] exists[$exists]"; 456 $exists; 457} 458 459# CPAN::Queue::delete ; 460sub delete { 461 my($self,$mod) = @_; 462 @All = grep { $_->{qmod} ne $mod } @All; 463} 464 465# CPAN::Queue::nullify_queue ; 466sub nullify_queue { 467 @All = (); 468} 469 470 471 472package CPAN; 473 474$META ||= CPAN->new; # In case we re-eval ourselves we need the || 475 476# from here on only subs. 477################################################################################ 478 479#-> sub CPAN::all_objects ; 480sub all_objects { 481 my($mgr,$class) = @_; 482 CPAN::Config->load unless $CPAN::Config_loaded++; 483 CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG; 484 CPAN::Index->reload; 485 values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok 486} 487*all = \&all_objects; 488 489# Called by shell, not in batch mode. In batch mode I see no risk in 490# having many processes updating something as installations are 491# continually checked at runtime. In shell mode I suspect it is 492# unintentional to open more than one shell at a time 493 494#-> sub CPAN::checklock ; 495sub checklock { 496 my($self) = @_; 497 my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock"); 498 if (-f $lockfile && -M _ > 0) { 499 my $fh = FileHandle->new($lockfile) or 500 $CPAN::Frontend->mydie("Could not open $lockfile: $!"); 501 my $otherpid = <$fh>; 502 my $otherhost = <$fh>; 503 $fh->close; 504 if (defined $otherpid && $otherpid) { 505 chomp $otherpid; 506 } 507 if (defined $otherhost && $otherhost) { 508 chomp $otherhost; 509 } 510 my $thishost = hostname(); 511 if (defined $otherhost && defined $thishost && 512 $otherhost ne '' && $thishost ne '' && 513 $otherhost ne $thishost) { 514 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile $lockfile\n". 515 "reports other host $otherhost and other process $otherpid.\n". 516 "Cannot proceed.\n")); 517 } 518 elsif (defined $otherpid && $otherpid) { 519 return if $$ == $otherpid; # should never happen 520 $CPAN::Frontend->mywarn( 521 qq{ 522There seems to be running another CPAN process (pid $otherpid). Contacting... 523}); 524 if (kill 0, $otherpid) { 525 $CPAN::Frontend->mydie(qq{Other job is running. 526You may want to kill it and delete the lockfile, maybe. On UNIX try: 527 kill $otherpid 528 rm $lockfile 529}); 530 } elsif (-w $lockfile) { 531 my($ans) = 532 ExtUtils::MakeMaker::prompt 533 (qq{Other job not responding. Shall I overwrite }. 534 qq{the lockfile? (Y/N)},"y"); 535 $CPAN::Frontend->myexit("Ok, bye\n") 536 unless $ans =~ /^y/i; 537 } else { 538 Carp::croak( 539 qq{Lockfile $lockfile not writeable by you. }. 540 qq{Cannot proceed.\n}. 541 qq{ On UNIX try:\n}. 542 qq{ rm $lockfile\n}. 543 qq{ and then rerun us.\n} 544 ); 545 } 546 } else { 547 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile $lockfile\n". 548 "reports other process with ID ". 549 "$otherpid. Cannot proceed.\n")); 550 } 551 } 552 my $dotcpan = $CPAN::Config->{cpan_home}; 553 eval { File::Path::mkpath($dotcpan);}; 554 if ($@) { 555 # A special case at least for Jarkko. 556 my $firsterror = $@; 557 my $seconderror; 558 my $symlinkcpan; 559 if (-l $dotcpan) { 560 $symlinkcpan = readlink $dotcpan; 561 die "readlink $dotcpan failed: $!" unless defined $symlinkcpan; 562 eval { File::Path::mkpath($symlinkcpan); }; 563 if ($@) { 564 $seconderror = $@; 565 } else { 566 $CPAN::Frontend->mywarn(qq{ 567Working directory $symlinkcpan created. 568}); 569 } 570 } 571 unless (-d $dotcpan) { 572 my $diemess = qq{ 573Your configuration suggests "$dotcpan" as your 574CPAN.pm working directory. I could not create this directory due 575to this error: $firsterror\n}; 576 $diemess .= qq{ 577As "$dotcpan" is a symlink to "$symlinkcpan", 578I tried to create that, but I failed with this error: $seconderror 579} if $seconderror; 580 $diemess .= qq{ 581Please make sure the directory exists and is writable. 582}; 583 $CPAN::Frontend->mydie($diemess); 584 } 585 } 586 my $fh; 587 unless ($fh = FileHandle->new(">$lockfile")) { 588 if ($! =~ /Permission/) { 589 my $incc = $INC{'CPAN/Config.pm'}; 590 my $myincc = File::Spec->catfile($ENV{HOME},'.cpan','CPAN','MyConfig.pm'); 591 $CPAN::Frontend->myprint(qq{ 592 593Your configuration suggests that CPAN.pm should use a working 594directory of 595 $CPAN::Config->{cpan_home} 596Unfortunately we could not create the lock file 597 $lockfile 598due to permission problems. 599 600Please make sure that the configuration variable 601 \$CPAN::Config->{cpan_home} 602points to a directory where you can write a .lock file. You can set 603this variable in either 604 $incc 605or 606 $myincc 607 608}); 609 } 610 $CPAN::Frontend->mydie("Could not open >$lockfile: $!"); 611 } 612 $fh->print($$, "\n"); 613 $fh->print(hostname(), "\n"); 614 $self->{LOCK} = $lockfile; 615 $fh->close; 616 $SIG{TERM} = sub { 617 &cleanup; 618 $CPAN::Frontend->mydie("Got SIGTERM, leaving"); 619 }; 620 $SIG{INT} = sub { 621 # no blocks!!! 622 &cleanup if $Signal; 623 $CPAN::Frontend->mydie("Got another SIGINT") if $Signal; 624 print "Caught SIGINT\n"; 625 $Signal++; 626 }; 627 628# From: Larry Wall <larry@wall.org> 629# Subject: Re: deprecating SIGDIE 630# To: perl5-porters@perl.org 631# Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT) 632# 633# The original intent of __DIE__ was only to allow you to substitute one 634# kind of death for another on an application-wide basis without respect 635# to whether you were in an eval or not. As a global backstop, it should 636# not be used any more lightly (or any more heavily :-) than class 637# UNIVERSAL. Any attempt to build a general exception model on it should 638# be politely squashed. Any bug that causes every eval {} to have to be 639# modified should be not so politely squashed. 640# 641# Those are my current opinions. It is also my optinion that polite 642# arguments degenerate to personal arguments far too frequently, and that 643# when they do, it's because both people wanted it to, or at least didn't 644# sufficiently want it not to. 645# 646# Larry 647 648 # global backstop to cleanup if we should really die 649 $SIG{__DIE__} = \&cleanup; 650 $self->debug("Signal handler set.") if $CPAN::DEBUG; 651} 652 653#-> sub CPAN::DESTROY ; 654sub DESTROY { 655 &cleanup; # need an eval? 656} 657 658#-> sub CPAN::anycwd ; 659sub anycwd () { 660 my $getcwd; 661 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd'; 662 CPAN->$getcwd(); 663} 664 665#-> sub CPAN::cwd ; 666sub cwd {Cwd::cwd();} 667 668#-> sub CPAN::getcwd ; 669sub getcwd {Cwd::getcwd();} 670 671#-> sub CPAN::exists ; 672sub exists { 673 my($mgr,$class,$id) = @_; 674 CPAN::Config->load unless $CPAN::Config_loaded++; 675 CPAN::Index->reload; 676 ### Carp::croak "exists called without class argument" unless $class; 677 $id ||= ""; 678 exists $META->{readonly}{$class}{$id} or 679 exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok 680} 681 682#-> sub CPAN::delete ; 683sub delete { 684 my($mgr,$class,$id) = @_; 685 delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok 686 delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok 687} 688 689#-> sub CPAN::has_usable 690# has_inst is sometimes too optimistic, we should replace it with this 691# has_usable whenever a case is given 692sub has_usable { 693 my($self,$mod,$message) = @_; 694 return 1 if $HAS_USABLE->{$mod}; 695 my $has_inst = $self->has_inst($mod,$message); 696 return unless $has_inst; 697 my $usable; 698 $usable = { 699 LWP => [ # we frequently had "Can't locate object 700 # method "new" via package "LWP::UserAgent" at 701 # (eval 69) line 2006 702 sub {require LWP}, 703 sub {require LWP::UserAgent}, 704 sub {require HTTP::Request}, 705 sub {require URI::URL}, 706 ], 707 Net::FTP => [ 708 sub {require Net::FTP}, 709 sub {require Net::Config}, 710 ] 711 }; 712 if ($usable->{$mod}) { 713 for my $c (0..$#{$usable->{$mod}}) { 714 my $code = $usable->{$mod}[$c]; 715 my $ret = eval { &$code() }; 716 if ($@) { 717 warn "DEBUG: c[$c]\$\@[$@]ret[$ret]"; 718 return; 719 } 720 } 721 } 722 return $HAS_USABLE->{$mod} = 1; 723} 724 725#-> sub CPAN::has_inst 726sub has_inst { 727 my($self,$mod,$message) = @_; 728 Carp::croak("CPAN->has_inst() called without an argument") 729 unless defined $mod; 730 if (defined $message && $message eq "no" 731 || 732 exists $CPAN::META->{dontload_hash}{$mod} # unsafe meta access, ok 733 || 734 exists $CPAN::Config->{dontload_hash}{$mod} 735 ) { 736 $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok 737 return 0; 738 } 739 my $file = $mod; 740 my $obj; 741 $file =~ s|::|/|g; 742 $file =~ s|/|\\|g if $^O eq 'MSWin32'; 743 $file .= ".pm"; 744 if ($INC{$file}) { 745 # checking %INC is wrong, because $INC{LWP} may be true 746 # although $INC{"URI/URL.pm"} may have failed. But as 747 # I really want to say "bla loaded OK", I have to somehow 748 # cache results. 749 ### warn "$file in %INC"; #debug 750 return 1; 751 } elsif (eval { require $file }) { 752 # eval is good: if we haven't yet read the database it's 753 # perfect and if we have installed the module in the meantime, 754 # it tries again. The second require is only a NOOP returning 755 # 1 if we had success, otherwise it's retrying 756 757 $CPAN::Frontend->myprint("CPAN: $mod loaded ok\n"); 758 if ($mod eq "CPAN::WAIT") { 759 push @CPAN::Shell::ISA, CPAN::WAIT; 760 } 761 return 1; 762 } elsif ($mod eq "Net::FTP") { 763 $CPAN::Frontend->mywarn(qq{ 764 Please, install Net::FTP as soon as possible. CPAN.pm installs it for you 765 if you just type 766 install Bundle::libnet 767 768}) unless $Have_warned->{"Net::FTP"}++; 769 sleep 3; 770 } elsif ($mod eq "Digest::MD5"){ 771 $CPAN::Frontend->myprint(qq{ 772 CPAN: MD5 security checks disabled because Digest::MD5 not installed. 773 Please consider installing the Digest::MD5 module. 774 775}); 776 sleep 2; 777 } else { 778 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI 779 } 780 return 0; 781} 782 783#-> sub CPAN::instance ; 784sub instance { 785 my($mgr,$class,$id) = @_; 786 CPAN::Index->reload; 787 $id ||= ""; 788 # unsafe meta access, ok? 789 return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id}; 790 $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id); 791} 792 793#-> sub CPAN::new ; 794sub new { 795 bless {}, shift; 796} 797 798#-> sub CPAN::cleanup ; 799sub cleanup { 800 # warn "cleanup called with arg[@_] End[$End] Signal[$Signal]"; 801 local $SIG{__DIE__} = ''; 802 my($message) = @_; 803 my $i = 0; 804 my $ineval = 0; 805 my($subroutine); 806 while ((undef,undef,undef,$subroutine) = caller(++$i)) { 807 $ineval = 1, last if 808 $subroutine eq '(eval)'; 809 } 810 return if $ineval && !$End; 811 return unless defined $META->{LOCK}; 812 return unless -f $META->{LOCK}; 813 $META->savehist; 814 unlink $META->{LOCK}; 815 # require Carp; 816 # Carp::cluck("DEBUGGING"); 817 $CPAN::Frontend->mywarn("Lockfile removed.\n"); 818} 819 820#-> sub CPAN::savehist 821sub savehist { 822 my($self) = @_; 823 my($histfile,$histsize); 824 unless ($histfile = $CPAN::Config->{'histfile'}){ 825 $CPAN::Frontend->mywarn("No history written (no histfile specified).\n"); 826 return; 827 } 828 $histsize = $CPAN::Config->{'histsize'} || 100; 829 if ($CPAN::term){ 830 unless ($CPAN::term->can("GetHistory")) { 831 $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n"); 832 return; 833 } 834 } else { 835 return; 836 } 837 my @h = $CPAN::term->GetHistory; 838 splice @h, 0, @h-$histsize if @h>$histsize; 839 my($fh) = FileHandle->new; 840 open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!"); 841 local $\ = local $, = "\n"; 842 print $fh @h; 843 close $fh; 844} 845 846sub is_tested { 847 my($self,$what) = @_; 848 $self->{is_tested}{$what} = 1; 849} 850 851sub is_installed { 852 my($self,$what) = @_; 853 delete $self->{is_tested}{$what}; 854} 855 856sub set_perl5lib { 857 my($self) = @_; 858 $self->{is_tested} ||= {}; 859 return unless %{$self->{is_tested}}; 860 my $env = $ENV{PERL5LIB}; 861 $env = $ENV{PERLLIB} unless defined $env; 862 my @env; 863 push @env, $env if defined $env and length $env; 864 my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}}; 865 $CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n"); 866 $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; 867} 868 869package CPAN::CacheMgr; 870 871#-> sub CPAN::CacheMgr::as_string ; 872sub as_string { 873 eval { require Data::Dumper }; 874 if ($@) { 875 return shift->SUPER::as_string; 876 } else { 877 return Data::Dumper::Dumper(shift); 878 } 879} 880 881#-> sub CPAN::CacheMgr::cachesize ; 882sub cachesize { 883 shift->{DU}; 884} 885 886#-> sub CPAN::CacheMgr::tidyup ; 887sub tidyup { 888 my($self) = @_; 889 return unless -d $self->{ID}; 890 while ($self->{DU} > $self->{'MAX'} ) { 891 my($toremove) = shift @{$self->{FIFO}}; 892 $CPAN::Frontend->myprint(sprintf( 893 "Deleting from cache". 894 ": $toremove (%.1f>%.1f MB)\n", 895 $self->{DU}, $self->{'MAX'}) 896 ); 897 return if $CPAN::Signal; 898 $self->force_clean_cache($toremove); 899 return if $CPAN::Signal; 900 } 901} 902 903#-> sub CPAN::CacheMgr::dir ; 904sub dir { 905 shift->{ID}; 906} 907 908#-> sub CPAN::CacheMgr::entries ; 909sub entries { 910 my($self,$dir) = @_; 911 return unless defined $dir; 912 $self->debug("reading dir[$dir]") if $CPAN::DEBUG; 913 $dir ||= $self->{ID}; 914 my($cwd) = CPAN::anycwd(); 915 chdir $dir or Carp::croak("Can't chdir to $dir: $!"); 916 my $dh = DirHandle->new(File::Spec->curdir) 917 or Carp::croak("Couldn't opendir $dir: $!"); 918 my(@entries); 919 for ($dh->read) { 920 next if $_ eq "." || $_ eq ".."; 921 if (-f $_) { 922 push @entries, File::Spec->catfile($dir,$_); 923 } elsif (-d _) { 924 push @entries, File::Spec->catdir($dir,$_); 925 } else { 926 $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n"); 927 } 928 } 929 chdir $cwd or Carp::croak("Can't chdir to $cwd: $!"); 930 sort { -M $b <=> -M $a} @entries; 931} 932 933#-> sub CPAN::CacheMgr::disk_usage ; 934sub disk_usage { 935 my($self,$dir) = @_; 936 return if exists $self->{SIZE}{$dir}; 937 return if $CPAN::Signal; 938 my($Du) = 0; 939 find( 940 sub { 941 $File::Find::prune++ if $CPAN::Signal; 942 return if -l $_; 943 if ($^O eq 'MacOS') { 944 require Mac::Files; 945 my $cat = Mac::Files::FSpGetCatInfo($_); 946 $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen() if $cat; 947 } else { 948 $Du += (-s _); 949 } 950 }, 951 $dir 952 ); 953 return if $CPAN::Signal; 954 $self->{SIZE}{$dir} = $Du/1024/1024; 955 push @{$self->{FIFO}}, $dir; 956 $self->debug("measured $dir is $Du") if $CPAN::DEBUG; 957 $self->{DU} += $Du/1024/1024; 958 $self->{DU}; 959} 960 961#-> sub CPAN::CacheMgr::force_clean_cache ; 962sub force_clean_cache { 963 my($self,$dir) = @_; 964 return unless -e $dir; 965 $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}") 966 if $CPAN::DEBUG; 967 File::Path::rmtree($dir); 968 $self->{DU} -= $self->{SIZE}{$dir}; 969 delete $self->{SIZE}{$dir}; 970} 971 972#-> sub CPAN::CacheMgr::new ; 973sub new { 974 my $class = shift; 975 my $time = time; 976 my($debug,$t2); 977 $debug = ""; 978 my $self = { 979 ID => $CPAN::Config->{'build_dir'}, 980 MAX => $CPAN::Config->{'build_cache'}, 981 SCAN => $CPAN::Config->{'scan_cache'} || 'atstart', 982 DU => 0 983 }; 984 File::Path::mkpath($self->{ID}); 985 my $dh = DirHandle->new($self->{ID}); 986 bless $self, $class; 987 $self->scan_cache; 988 $t2 = time; 989 $debug .= "timing of CacheMgr->new: ".($t2 - $time); 990 $time = $t2; 991 CPAN->debug($debug) if $CPAN::DEBUG; 992 $self; 993} 994 995#-> sub CPAN::CacheMgr::scan_cache ; 996sub scan_cache { 997 my $self = shift; 998 return if $self->{SCAN} eq 'never'; 999 $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}") 1000 unless $self->{SCAN} eq 'atstart'; 1001 $CPAN::Frontend->myprint( 1002 sprintf("Scanning cache %s for sizes\n", 1003 $self->{ID})); 1004 my $e; 1005 for $e ($self->entries($self->{ID})) { 1006 next if $e eq ".." || $e eq "."; 1007 $self->disk_usage($e); 1008 return if $CPAN::Signal; 1009 } 1010 $self->tidyup; 1011} 1012 1013package CPAN::Debug; 1014 1015#-> sub CPAN::Debug::debug ; 1016sub debug { 1017 my($self,$arg) = @_; 1018 my($caller,$func,$line,@rest) = caller(1); # caller(0) eg 1019 # Complete, caller(1) 1020 # eg readline 1021 ($caller) = caller(0); 1022 $caller =~ s/.*:://; 1023 $arg = "" unless defined $arg; 1024 my $rest = join "|", map { defined $_ ? $_ : "UNDEF" } @rest; 1025 if ($CPAN::DEBUG{$caller} & $CPAN::DEBUG){ 1026 if ($arg and ref $arg) { 1027 eval { require Data::Dumper }; 1028 if ($@) { 1029 $CPAN::Frontend->myprint($arg->as_string); 1030 } else { 1031 $CPAN::Frontend->myprint(Data::Dumper::Dumper($arg)); 1032 } 1033 } else { 1034 $CPAN::Frontend->myprint("Debug($caller:$func,$line,[$rest]): $arg\n"); 1035 } 1036 } 1037} 1038 1039package CPAN::Config; 1040 1041#-> sub CPAN::Config::edit ; 1042# returns true on successful action 1043sub edit { 1044 my($self,@args) = @_; 1045 return unless @args; 1046 CPAN->debug("self[$self]args[".join(" | ",@args)."]"); 1047 my($o,$str,$func,$args,$key_exists); 1048 $o = shift @args; 1049 if($can{$o}) { 1050 $self->$o(@args); 1051 return 1; 1052 } else { 1053 CPAN->debug("o[$o]") if $CPAN::DEBUG; 1054 if ($o =~ /list$/) { 1055 $func = shift @args; 1056 $func ||= ""; 1057 CPAN->debug("func[$func]") if $CPAN::DEBUG; 1058 my $changed; 1059 # Let's avoid eval, it's easier to comprehend without. 1060 if ($func eq "push") { 1061 push @{$CPAN::Config->{$o}}, @args; 1062 $changed = 1; 1063 } elsif ($func eq "pop") { 1064 pop @{$CPAN::Config->{$o}}; 1065 $changed = 1; 1066 } elsif ($func eq "shift") { 1067 shift @{$CPAN::Config->{$o}}; 1068 $changed = 1; 1069 } elsif ($func eq "unshift") { 1070 unshift @{$CPAN::Config->{$o}}, @args; 1071 $changed = 1; 1072 } elsif ($func eq "splice") { 1073 splice @{$CPAN::Config->{$o}}, @args; 1074 $changed = 1; 1075 } elsif (@args) { 1076 $CPAN::Config->{$o} = [@args]; 1077 $changed = 1; 1078 } else { 1079 $self->prettyprint($o); 1080 } 1081 if ($o eq "urllist" && $changed) { 1082 # reset the cached values 1083 undef $CPAN::FTP::Thesite; 1084 undef $CPAN::FTP::Themethod; 1085 } 1086 return $changed; 1087 } else { 1088 $CPAN::Config->{$o} = $args[0] if defined $args[0]; 1089 $self->prettyprint($o); 1090 } 1091 } 1092} 1093 1094sub prettyprint { 1095 my($self,$k) = @_; 1096 my $v = $CPAN::Config->{$k}; 1097 if (ref $v) { 1098 my(@report) = ref $v eq "ARRAY" ? 1099 @$v : 1100 map { sprintf(" %-18s => %s\n", 1101 $_, 1102 defined $v->{$_} ? $v->{$_} : "UNDEFINED" 1103 )} keys %$v; 1104 $CPAN::Frontend->myprint( 1105 join( 1106 "", 1107 sprintf( 1108 " %-18s\n", 1109 $k 1110 ), 1111 map {"\t$_\n"} @report 1112 ) 1113 ); 1114 } elsif (defined $v) { 1115 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v); 1116 } else { 1117 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, "UNDEFINED"); 1118 } 1119} 1120 1121#-> sub CPAN::Config::commit ; 1122sub commit { 1123 my($self,$configpm) = @_; 1124 unless (defined $configpm){ 1125 $configpm ||= $INC{"CPAN/MyConfig.pm"}; 1126 $configpm ||= $INC{"CPAN/Config.pm"}; 1127 $configpm || Carp::confess(q{ 1128CPAN::Config::commit called without an argument. 1129Please specify a filename where to save the configuration or try 1130"o conf init" to have an interactive course through configing. 1131}); 1132 } 1133 my($mode); 1134 if (-f $configpm) { 1135 $mode = (stat $configpm)[2]; 1136 if ($mode && ! -w _) { 1137 Carp::confess("$configpm is not writable"); 1138 } 1139 } 1140 1141 my $msg; 1142 $msg = <<EOF unless $configpm =~ /MyConfig/; 1143 1144# This is CPAN.pm's systemwide configuration file. This file provides 1145# defaults for users, and the values can be changed in a per-user 1146# configuration file. The user-config file is being looked for as 1147# ~/.cpan/CPAN/MyConfig.pm. 1148 1149EOF 1150 $msg ||= "\n"; 1151 my($fh) = FileHandle->new; 1152 rename $configpm, "$configpm~" if -f $configpm; 1153 open $fh, ">$configpm" or 1154 $CPAN::Frontend->mydie("Couldn't open >$configpm: $!"); 1155 $fh->print(qq[$msg\$CPAN::Config = \{\n]); 1156 foreach (sort keys %$CPAN::Config) { 1157 $fh->print( 1158 " '$_' => ", 1159 ExtUtils::MakeMaker::neatvalue($CPAN::Config->{$_}), 1160 ",\n" 1161 ); 1162 } 1163 1164 $fh->print("};\n1;\n__END__\n"); 1165 close $fh; 1166 1167 #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 ); 1168 #chmod $mode, $configpm; 1169###why was that so? $self->defaults; 1170 $CPAN::Frontend->myprint("commit: wrote $configpm\n"); 1171 1; 1172} 1173 1174*default = \&defaults; 1175#-> sub CPAN::Config::defaults ; 1176sub defaults { 1177 my($self) = @_; 1178 $self->unload; 1179 $self->load; 1180 1; 1181} 1182 1183sub init { 1184 my($self) = @_; 1185 undef $CPAN::Config->{'inhibit_startup_message'}; # lazy trick to 1186 # have the least 1187 # important 1188 # variable 1189 # undefined 1190 $self->load; 1191 1; 1192} 1193 1194# This is a piece of repeated code that is abstracted here for 1195# maintainability. RMB 1196# 1197sub _configpmtest { 1198 my($configpmdir, $configpmtest) = @_; 1199 if (-w $configpmtest) { 1200 return $configpmtest; 1201 } elsif (-w $configpmdir) { 1202 #_#_# following code dumped core on me with 5.003_11, a.k. 1203 my $configpm_bak = "$configpmtest.bak"; 1204 unlink $configpm_bak if -f $configpm_bak; 1205 if( -f $configpmtest ) { 1206 if( rename $configpmtest, $configpm_bak ) { 1207 $CPAN::Frontend->mywarn(<<END) 1208Old configuration file $configpmtest 1209 moved to $configpm_bak 1210END 1211 } 1212 } 1213 my $fh = FileHandle->new; 1214 if ($fh->open(">$configpmtest")) { 1215 $fh->print("1;\n"); 1216 return $configpmtest; 1217 } else { 1218 # Should never happen 1219 Carp::confess("Cannot open >$configpmtest"); 1220 } 1221 } else { return } 1222} 1223 1224#-> sub CPAN::Config::load ; 1225sub load { 1226 my($self) = shift; 1227 my(@miss); 1228 use Carp; 1229 eval {require CPAN::Config;}; # We eval because of some 1230 # MakeMaker problems 1231 unless ($dot_cpan++){ 1232 unshift @INC, File::Spec->catdir($ENV{HOME},".cpan"); 1233 eval {require CPAN::MyConfig;}; # where you can override 1234 # system wide settings 1235 shift @INC; 1236 } 1237 return unless @miss = $self->missing_config_data; 1238 1239 require CPAN::FirstTime; 1240 my($configpm,$fh,$redo,$theycalled); 1241 $redo ||= ""; 1242 $theycalled++ if @miss==1 && $miss[0] eq 'inhibit_startup_message'; 1243 if (defined $INC{"CPAN/Config.pm"} && -w $INC{"CPAN/Config.pm"}) { 1244 $configpm = $INC{"CPAN/Config.pm"}; 1245 $redo++; 1246 } elsif (defined $INC{"CPAN/MyConfig.pm"} && -w $INC{"CPAN/MyConfig.pm"}) { 1247 $configpm = $INC{"CPAN/MyConfig.pm"}; 1248 $redo++; 1249 } else { 1250 my($path_to_cpan) = File::Basename::dirname($INC{"CPAN.pm"}); 1251 my($configpmdir) = File::Spec->catdir($path_to_cpan,"CPAN"); 1252 my($configpmtest) = File::Spec->catfile($configpmdir,"Config.pm"); 1253 if (-d $configpmdir or File::Path::mkpath($configpmdir)) { 1254 $configpm = _configpmtest($configpmdir,$configpmtest); 1255 } 1256 unless ($configpm) { 1257 $configpmdir = File::Spec->catdir($ENV{HOME},".cpan","CPAN"); 1258 File::Path::mkpath($configpmdir); 1259 $configpmtest = File::Spec->catfile($configpmdir,"MyConfig.pm"); 1260 $configpm = _configpmtest($configpmdir,$configpmtest); 1261 unless ($configpm) { 1262 Carp::confess(qq{WARNING: CPAN.pm is unable to }. 1263 qq{create a configuration file.}); 1264 } 1265 } 1266 } 1267 local($") = ", "; 1268 $CPAN::Frontend->myprint(<<END) if $redo && ! $theycalled; 1269We have to reconfigure CPAN.pm due to following uninitialized parameters: 1270 1271@miss 1272END 1273 $CPAN::Frontend->myprint(qq{ 1274$configpm initialized. 1275}); 1276 sleep 2; 1277 CPAN::FirstTime::init($configpm); 1278} 1279 1280#-> sub CPAN::Config::missing_config_data ; 1281sub missing_config_data { 1282 my(@miss); 1283 for ( 1284 "cpan_home", "keep_source_where", "build_dir", "build_cache", 1285 "scan_cache", "index_expire", "gzip", "tar", "unzip", "make", 1286 "pager", 1287 "makepl_arg", "make_arg", "make_install_arg", "urllist", 1288 "inhibit_startup_message", "ftp_proxy", "http_proxy", "no_proxy", 1289 "prerequisites_policy", 1290 "cache_metadata", 1291 ) { 1292 push @miss, $_ unless defined $CPAN::Config->{$_}; 1293 } 1294 return @miss; 1295} 1296 1297#-> sub CPAN::Config::unload ; 1298sub unload { 1299 delete $INC{'CPAN/MyConfig.pm'}; 1300 delete $INC{'CPAN/Config.pm'}; 1301} 1302 1303#-> sub CPAN::Config::help ; 1304sub help { 1305 $CPAN::Frontend->myprint(q[ 1306Known options: 1307 defaults reload default config values from disk 1308 commit commit session changes to disk 1309 init go through a dialog to set all parameters 1310 1311You may edit key values in the follow fashion (the "o" is a literal 1312letter o): 1313 1314 o conf build_cache 15 1315 1316 o conf build_dir "/foo/bar" 1317 1318 o conf urllist shift 1319 1320 o conf urllist unshift ftp://ftp.foo.bar/ 1321 1322]); 1323 undef; #don't reprint CPAN::Config 1324} 1325 1326#-> sub CPAN::Config::cpl ; 1327sub cpl { 1328 my($word,$line,$pos) = @_; 1329 $word ||= ""; 1330 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 1331 my(@words) = split " ", substr($line,0,$pos+1); 1332 if ( 1333 defined($words[2]) 1334 and 1335 ( 1336 $words[2] =~ /list$/ && @words == 3 1337 || 1338 $words[2] =~ /list$/ && @words == 4 && length($word) 1339 ) 1340 ) { 1341 return grep /^\Q$word\E/, qw(splice shift unshift pop push); 1342 } elsif (@words >= 4) { 1343 return (); 1344 } 1345 my(@o_conf) = (keys %CPAN::Config::can, keys %$CPAN::Config); 1346 return grep /^\Q$word\E/, @o_conf; 1347} 1348 1349package CPAN::Shell; 1350 1351#-> sub CPAN::Shell::h ; 1352sub h { 1353 my($class,$about) = @_; 1354 if (defined $about) { 1355 $CPAN::Frontend->myprint("Detailed help not yet implemented\n"); 1356 } else { 1357 $CPAN::Frontend->myprint(q{ 1358Display Information 1359 command argument description 1360 a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules 1361 i WORD or /REGEXP/ about anything of above 1362 r NONE reinstall recommendations 1363 ls AUTHOR about files in the author's directory 1364 1365Download, Test, Make, Install... 1366 get download 1367 make make (implies get) 1368 test MODULES, make test (implies make) 1369 install DISTS, BUNDLES make install (implies test) 1370 clean make clean 1371 look open subshell in these dists' directories 1372 readme display these dists' README files 1373 1374Other 1375 h,? display this menu ! perl-code eval a perl command 1376 o conf [opt] set and query options q quit the cpan shell 1377 reload cpan load CPAN.pm again reload index load newer indices 1378 autobundle Snapshot force cmd unconditionally do cmd}); 1379 } 1380} 1381 1382*help = \&h; 1383 1384#-> sub CPAN::Shell::a ; 1385sub a { 1386 my($self,@arg) = @_; 1387 # authors are always UPPERCASE 1388 for (@arg) { 1389 $_ = uc $_ unless /=/; 1390 } 1391 $CPAN::Frontend->myprint($self->format_result('Author',@arg)); 1392} 1393 1394#-> sub CPAN::Shell::ls ; 1395sub ls { 1396 my($self,@arg) = @_; 1397 my @accept; 1398 for (@arg) { 1399 unless (/^[A-Z\-]+$/i) { 1400 $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n"); 1401 next; 1402 } 1403 push @accept, uc $_; 1404 } 1405 for my $a (@accept){ 1406 my $author = $self->expand('Author',$a) or die "No author found for $a"; 1407 $author->ls; 1408 } 1409} 1410 1411#-> sub CPAN::Shell::local_bundles ; 1412sub local_bundles { 1413 my($self,@which) = @_; 1414 my($incdir,$bdir,$dh); 1415 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { 1416 my @bbase = "Bundle"; 1417 while (my $bbase = shift @bbase) { 1418 $bdir = File::Spec->catdir($incdir,split /::/, $bbase); 1419 CPAN->debug("bdir[$bdir]\@bbase[@bbase]") if $CPAN::DEBUG; 1420 if ($dh = DirHandle->new($bdir)) { # may fail 1421 my($entry); 1422 for $entry ($dh->read) { 1423 next if $entry =~ /^\./; 1424 if (-d File::Spec->catdir($bdir,$entry)){ 1425 push @bbase, "$bbase\::$entry"; 1426 } else { 1427 next unless $entry =~ s/\.pm(?!\n)\Z//; 1428 $CPAN::META->instance('CPAN::Bundle',"$bbase\::$entry"); 1429 } 1430 } 1431 } 1432 } 1433 } 1434} 1435 1436#-> sub CPAN::Shell::b ; 1437sub b { 1438 my($self,@which) = @_; 1439 CPAN->debug("which[@which]") if $CPAN::DEBUG; 1440 $self->local_bundles; 1441 $CPAN::Frontend->myprint($self->format_result('Bundle',@which)); 1442} 1443 1444#-> sub CPAN::Shell::d ; 1445sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));} 1446 1447#-> sub CPAN::Shell::m ; 1448sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here 1449 my $self = shift; 1450 $CPAN::Frontend->myprint($self->format_result('Module',@_)); 1451} 1452 1453#-> sub CPAN::Shell::i ; 1454sub i { 1455 my($self) = shift; 1456 my(@args) = @_; 1457 my(@type,$type,@m); 1458 @type = qw/Author Bundle Distribution Module/; 1459 @args = '/./' unless @args; 1460 my(@result); 1461 for $type (@type) { 1462 push @result, $self->expand($type,@args); 1463 } 1464 my $result = @result == 1 ? 1465 $result[0]->as_string : 1466 @result == 0 ? 1467 "No objects found of any type for argument @args\n" : 1468 join("", 1469 (map {$_->as_glimpse} @result), 1470 scalar @result, " items found\n", 1471 ); 1472 $CPAN::Frontend->myprint($result); 1473} 1474 1475#-> sub CPAN::Shell::o ; 1476 1477# CPAN::Shell::o and CPAN::Config::edit are closely related. 'o conf' 1478# should have been called set and 'o debug' maybe 'set debug' 1479sub o { 1480 my($self,$o_type,@o_what) = @_; 1481 $o_type ||= ""; 1482 CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n"); 1483 if ($o_type eq 'conf') { 1484 shift @o_what if @o_what && $o_what[0] eq 'help'; 1485 if (!@o_what) { # print all things, "o conf" 1486 my($k,$v); 1487 $CPAN::Frontend->myprint("CPAN::Config options"); 1488 if (exists $INC{'CPAN/Config.pm'}) { 1489 $CPAN::Frontend->myprint(" from $INC{'CPAN/Config.pm'}"); 1490 } 1491 if (exists $INC{'CPAN/MyConfig.pm'}) { 1492 $CPAN::Frontend->myprint(" and $INC{'CPAN/MyConfig.pm'}"); 1493 } 1494 $CPAN::Frontend->myprint(":\n"); 1495 for $k (sort keys %CPAN::Config::can) { 1496 $v = $CPAN::Config::can{$k}; 1497 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v); 1498 } 1499 $CPAN::Frontend->myprint("\n"); 1500 for $k (sort keys %$CPAN::Config) { 1501 CPAN::Config->prettyprint($k); 1502 } 1503 $CPAN::Frontend->myprint("\n"); 1504 } elsif (!CPAN::Config->edit(@o_what)) { 1505 $CPAN::Frontend->myprint(qq{Type 'o conf' to view configuration }. 1506 qq{edit options\n\n}); 1507 } 1508 } elsif ($o_type eq 'debug') { 1509 my(%valid); 1510 @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i; 1511 if (@o_what) { 1512 while (@o_what) { 1513 my($what) = shift @o_what; 1514 if ($what =~ s/^-// && exists $CPAN::DEBUG{$what}) { 1515 $CPAN::DEBUG &= $CPAN::DEBUG ^ $CPAN::DEBUG{$what}; 1516 next; 1517 } 1518 if ( exists $CPAN::DEBUG{$what} ) { 1519 $CPAN::DEBUG |= $CPAN::DEBUG{$what}; 1520 } elsif ($what =~ /^\d/) { 1521 $CPAN::DEBUG = $what; 1522 } elsif (lc $what eq 'all') { 1523 my($max) = 0; 1524 for (values %CPAN::DEBUG) { 1525 $max += $_; 1526 } 1527 $CPAN::DEBUG = $max; 1528 } else { 1529 my($known) = 0; 1530 for (keys %CPAN::DEBUG) { 1531 next unless lc($_) eq lc($what); 1532 $CPAN::DEBUG |= $CPAN::DEBUG{$_}; 1533 $known = 1; 1534 } 1535 $CPAN::Frontend->myprint("unknown argument [$what]\n") 1536 unless $known; 1537 } 1538 } 1539 } else { 1540 my $raw = "Valid options for debug are ". 1541 join(", ",sort(keys %CPAN::DEBUG), 'all'). 1542 qq{ or a number. Completion works on the options. }. 1543 qq{Case is ignored.}; 1544 require Text::Wrap; 1545 $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw)); 1546 $CPAN::Frontend->myprint("\n\n"); 1547 } 1548 if ($CPAN::DEBUG) { 1549 $CPAN::Frontend->myprint("Options set for debugging:\n"); 1550 my($k,$v); 1551 for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) { 1552 $v = $CPAN::DEBUG{$k}; 1553 $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v) 1554 if $v & $CPAN::DEBUG; 1555 } 1556 } else { 1557 $CPAN::Frontend->myprint("Debugging turned off completely.\n"); 1558 } 1559 } else { 1560 $CPAN::Frontend->myprint(qq{ 1561Known options: 1562 conf set or get configuration variables 1563 debug set or get debugging options 1564}); 1565 } 1566} 1567 1568sub paintdots_onreload { 1569 my($ref) = shift; 1570 sub { 1571 if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) { 1572 my($subr) = $1; 1573 ++$$ref; 1574 local($|) = 1; 1575 # $CPAN::Frontend->myprint(".($subr)"); 1576 $CPAN::Frontend->myprint("."); 1577 return; 1578 } 1579 warn @_; 1580 }; 1581} 1582 1583#-> sub CPAN::Shell::reload ; 1584sub reload { 1585 my($self,$command,@arg) = @_; 1586 $command ||= ""; 1587 $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG; 1588 if ($command =~ /cpan/i) { 1589 for my $f (qw(CPAN.pm CPAN/FirstTime.pm)) { 1590 next unless $INC{$f}; 1591 CPAN->debug("reloading the whole $f") if $CPAN::DEBUG; 1592 my $fh = FileHandle->new($INC{$f}); 1593 local($/); 1594 my $redef = 0; 1595 local($SIG{__WARN__}) = paintdots_onreload(\$redef); 1596 eval <$fh>; 1597 warn $@ if $@; 1598 $CPAN::Frontend->myprint("\n$redef subroutines redefined\n"); 1599 } 1600 } elsif ($command =~ /index/) { 1601 CPAN::Index->force_reload; 1602 } else { 1603 $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN.pm file 1604index re-reads the index files\n}); 1605 } 1606} 1607 1608#-> sub CPAN::Shell::_binary_extensions ; 1609sub _binary_extensions { 1610 my($self) = shift @_; 1611 my(@result,$module,%seen,%need,$headerdone); 1612 for $module ($self->expand('Module','/./')) { 1613 my $file = $module->cpan_file; 1614 next if $file eq "N/A"; 1615 next if $file =~ /^Contact Author/; 1616 my $dist = $CPAN::META->instance('CPAN::Distribution',$file); 1617 next if $dist->isa_perl; 1618 next unless $module->xs_file; 1619 local($|) = 1; 1620 $CPAN::Frontend->myprint("."); 1621 push @result, $module; 1622 } 1623# print join " | ", @result; 1624 $CPAN::Frontend->myprint("\n"); 1625 return @result; 1626} 1627 1628#-> sub CPAN::Shell::recompile ; 1629sub recompile { 1630 my($self) = shift @_; 1631 my($module,@module,$cpan_file,%dist); 1632 @module = $self->_binary_extensions(); 1633 for $module (@module){ # we force now and compile later, so we 1634 # don't do it twice 1635 $cpan_file = $module->cpan_file; 1636 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 1637 $pack->force; 1638 $dist{$cpan_file}++; 1639 } 1640 for $cpan_file (sort keys %dist) { 1641 $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n"); 1642 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 1643 $pack->install; 1644 $CPAN::Signal = 0; # it's tempting to reset Signal, so we can 1645 # stop a package from recompiling, 1646 # e.g. IO-1.12 when we have perl5.003_10 1647 } 1648} 1649 1650#-> sub CPAN::Shell::_u_r_common ; 1651sub _u_r_common { 1652 my($self) = shift @_; 1653 my($what) = shift @_; 1654 CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG; 1655 Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless 1656 $what && $what =~ /^[aru]$/; 1657 my(@args) = @_; 1658 @args = '/./' unless @args; 1659 my(@result,$module,%seen,%need,$headerdone, 1660 $version_undefs,$version_zeroes); 1661 $version_undefs = $version_zeroes = 0; 1662 my $sprintf = "%s%-25s%s %9s %9s %s\n"; 1663 my @expand = $self->expand('Module',@args); 1664 my $expand = scalar @expand; 1665 if (0) { # Looks like noise to me, was very useful for debugging 1666 # for metadata cache 1667 $CPAN::Frontend->myprint(sprintf "%d matches in the database\n", $expand); 1668 } 1669 for $module (@expand) { 1670 my $file = $module->cpan_file; 1671 next unless defined $file; # ?? 1672 my($latest) = $module->cpan_version; 1673 my($inst_file) = $module->inst_file; 1674 my($have); 1675 return if $CPAN::Signal; 1676 if ($inst_file){ 1677 if ($what eq "a") { 1678 $have = $module->inst_version; 1679 } elsif ($what eq "r") { 1680 $have = $module->inst_version; 1681 local($^W) = 0; 1682 if ($have eq "undef"){ 1683 $version_undefs++; 1684 } elsif ($have == 0){ 1685 $version_zeroes++; 1686 } 1687 next unless CPAN::Version->vgt($latest, $have); 1688# to be pedantic we should probably say: 1689# && !($have eq "undef" && $latest ne "undef" && $latest gt ""); 1690# to catch the case where CPAN has a version 0 and we have a version undef 1691 } elsif ($what eq "u") { 1692 next; 1693 } 1694 } else { 1695 if ($what eq "a") { 1696 next; 1697 } elsif ($what eq "r") { 1698 next; 1699 } elsif ($what eq "u") { 1700 $have = "-"; 1701 } 1702 } 1703 return if $CPAN::Signal; # this is sometimes lengthy 1704 $seen{$file} ||= 0; 1705 if ($what eq "a") { 1706 push @result, sprintf "%s %s\n", $module->id, $have; 1707 } elsif ($what eq "r") { 1708 push @result, $module->id; 1709 next if $seen{$file}++; 1710 } elsif ($what eq "u") { 1711 push @result, $module->id; 1712 next if $seen{$file}++; 1713 next if $file =~ /^Contact/; 1714 } 1715 unless ($headerdone++){ 1716 $CPAN::Frontend->myprint("\n"); 1717 $CPAN::Frontend->myprint(sprintf( 1718 $sprintf, 1719 "", 1720 "Package namespace", 1721 "", 1722 "installed", 1723 "latest", 1724 "in CPAN file" 1725 )); 1726 } 1727 my $color_on = ""; 1728 my $color_off = ""; 1729 if ( 1730 $COLOR_REGISTERED 1731 && 1732 $CPAN::META->has_inst("Term::ANSIColor") 1733 && 1734 $module->{RO}{description} 1735 ) { 1736 $color_on = Term::ANSIColor::color("green"); 1737 $color_off = Term::ANSIColor::color("reset"); 1738 } 1739 $CPAN::Frontend->myprint(sprintf $sprintf, 1740 $color_on, 1741 $module->id, 1742 $color_off, 1743 $have, 1744 $latest, 1745 $file); 1746 $need{$module->id}++; 1747 } 1748 unless (%need) { 1749 if ($what eq "u") { 1750 $CPAN::Frontend->myprint("No modules found for @args\n"); 1751 } elsif ($what eq "r") { 1752 $CPAN::Frontend->myprint("All modules are up to date for @args\n"); 1753 } 1754 } 1755 if ($what eq "r") { 1756 if ($version_zeroes) { 1757 my $s_has = $version_zeroes > 1 ? "s have" : " has"; 1758 $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }. 1759 qq{a version number of 0\n}); 1760 } 1761 if ($version_undefs) { 1762 my $s_has = $version_undefs > 1 ? "s have" : " has"; 1763 $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }. 1764 qq{parseable version number\n}); 1765 } 1766 } 1767 @result; 1768} 1769 1770#-> sub CPAN::Shell::r ; 1771sub r { 1772 shift->_u_r_common("r",@_); 1773} 1774 1775#-> sub CPAN::Shell::u ; 1776sub u { 1777 shift->_u_r_common("u",@_); 1778} 1779 1780#-> sub CPAN::Shell::autobundle ; 1781sub autobundle { 1782 my($self) = shift; 1783 CPAN::Config->load unless $CPAN::Config_loaded++; 1784 my(@bundle) = $self->_u_r_common("a",@_); 1785 my($todir) = File::Spec->catdir($CPAN::Config->{'cpan_home'},"Bundle"); 1786 File::Path::mkpath($todir); 1787 unless (-d $todir) { 1788 $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n"); 1789 return; 1790 } 1791 my($y,$m,$d) = (localtime)[5,4,3]; 1792 $y+=1900; 1793 $m++; 1794 my($c) = 0; 1795 my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c; 1796 my($to) = File::Spec->catfile($todir,"$me.pm"); 1797 while (-f $to) { 1798 $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c; 1799 $to = File::Spec->catfile($todir,"$me.pm"); 1800 } 1801 my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!"; 1802 $fh->print( 1803 "package Bundle::$me;\n\n", 1804 "\$VERSION = '0.01';\n\n", 1805 "1;\n\n", 1806 "__END__\n\n", 1807 "=head1 NAME\n\n", 1808 "Bundle::$me - Snapshot of installation on ", 1809 $Config::Config{'myhostname'}, 1810 " on ", 1811 scalar(localtime), 1812 "\n\n=head1 SYNOPSIS\n\n", 1813 "perl -MCPAN -e 'install Bundle::$me'\n\n", 1814 "=head1 CONTENTS\n\n", 1815 join("\n", @bundle), 1816 "\n\n=head1 CONFIGURATION\n\n", 1817 Config->myconfig, 1818 "\n\n=head1 AUTHOR\n\n", 1819 "This Bundle has been generated automatically ", 1820 "by the autobundle routine in CPAN.pm.\n", 1821 ); 1822 $fh->close; 1823 $CPAN::Frontend->myprint("\nWrote bundle file 1824 $to\n\n"); 1825} 1826 1827#-> sub CPAN::Shell::expandany ; 1828sub expandany { 1829 my($self,$s) = @_; 1830 CPAN->debug("s[$s]") if $CPAN::DEBUG; 1831 if ($s =~ m|/|) { # looks like a file 1832 $s = CPAN::Distribution->normalize($s); 1833 return $CPAN::META->instance('CPAN::Distribution',$s); 1834 # Distributions spring into existence, not expand 1835 } elsif ($s =~ m|^Bundle::|) { 1836 $self->local_bundles; # scanning so late for bundles seems 1837 # both attractive and crumpy: always 1838 # current state but easy to forget 1839 # somewhere 1840 return $self->expand('Bundle',$s); 1841 } else { 1842 return $self->expand('Module',$s) 1843 if $CPAN::META->exists('CPAN::Module',$s); 1844 } 1845 return; 1846} 1847 1848#-> sub CPAN::Shell::expand ; 1849sub expand { 1850 shift; 1851 my($type,@args) = @_; 1852 my($arg,@m); 1853 CPAN->debug("type[$type]args[@args]") if $CPAN::DEBUG; 1854 for $arg (@args) { 1855 my($regex,$command); 1856 if ($arg =~ m|^/(.*)/$|) { 1857 $regex = $1; 1858 } elsif ($arg =~ m/=/) { 1859 $command = 1; 1860 } 1861 my $class = "CPAN::$type"; 1862 my $obj; 1863 CPAN->debug(sprintf "class[%s]regex[%s]command[%s]", 1864 $class, 1865 defined $regex ? $regex : "UNDEFINED", 1866 $command || "UNDEFINED", 1867 ) if $CPAN::DEBUG; 1868 if (defined $regex) { 1869 for $obj ( 1870 sort 1871 {$a->id cmp $b->id} 1872 $CPAN::META->all_objects($class) 1873 ) { 1874 unless ($obj->id){ 1875 # BUG, we got an empty object somewhere 1876 require Data::Dumper; 1877 CPAN->debug(sprintf( 1878 "Bug in CPAN: Empty id on obj[%s][%s]", 1879 $obj, 1880 Data::Dumper::Dumper($obj) 1881 )) if $CPAN::DEBUG; 1882 next; 1883 } 1884 push @m, $obj 1885 if $obj->id =~ /$regex/i 1886 or 1887 ( 1888 ( 1889 $] < 5.00303 ### provide sort of 1890 ### compatibility with 5.003 1891 || 1892 $obj->can('name') 1893 ) 1894 && 1895 $obj->name =~ /$regex/i 1896 ); 1897 } 1898 } elsif ($command) { 1899 die "equal sign in command disabled (immature interface), ". 1900 "you can set 1901 ! \$CPAN::Shell::ADVANCED_QUERY=1 1902to enable it. But please note, this is HIGHLY EXPERIMENTAL code 1903that may go away anytime.\n" 1904 unless $ADVANCED_QUERY; 1905 my($method,$criterion) = $arg =~ /(.+?)=(.+)/; 1906 my($matchcrit) = $criterion =~ m/^~(.+)/; 1907 for my $self ( 1908 sort 1909 {$a->id cmp $b->id} 1910 $CPAN::META->all_objects($class) 1911 ) { 1912 my $lhs = $self->$method() or next; # () for 5.00503 1913 if ($matchcrit) { 1914 push @m, $self if $lhs =~ m/$matchcrit/; 1915 } else { 1916 push @m, $self if $lhs eq $criterion; 1917 } 1918 } 1919 } else { 1920 my($xarg) = $arg; 1921 if ( $type eq 'Bundle' ) { 1922 $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/; 1923 } elsif ($type eq "Distribution") { 1924 $xarg = CPAN::Distribution->normalize($arg); 1925 } 1926 if ($CPAN::META->exists($class,$xarg)) { 1927 $obj = $CPAN::META->instance($class,$xarg); 1928 } elsif ($CPAN::META->exists($class,$arg)) { 1929 $obj = $CPAN::META->instance($class,$arg); 1930 } else { 1931 next; 1932 } 1933 push @m, $obj; 1934 } 1935 } 1936 return wantarray ? @m : $m[0]; 1937} 1938 1939#-> sub CPAN::Shell::format_result ; 1940sub format_result { 1941 my($self) = shift; 1942 my($type,@args) = @_; 1943 @args = '/./' unless @args; 1944 my(@result) = $self->expand($type,@args); 1945 my $result = @result == 1 ? 1946 $result[0]->as_string : 1947 @result == 0 ? 1948 "No objects of type $type found for argument @args\n" : 1949 join("", 1950 (map {$_->as_glimpse} @result), 1951 scalar @result, " items found\n", 1952 ); 1953 $result; 1954} 1955 1956# The only reason for this method is currently to have a reliable 1957# debugging utility that reveals which output is going through which 1958# channel. No, I don't like the colors ;-) 1959 1960#-> sub CPAN::Shell::print_ornameted ; 1961sub print_ornamented { 1962 my($self,$what,$ornament) = @_; 1963 my $longest = 0; 1964 return unless defined $what; 1965 1966 if ($CPAN::Config->{term_is_latin}){ 1967 # courtesy jhi: 1968 $what 1969 =~ s{([\xC0-\xDF])([\x80-\xBF])}{chr(ord($1)<<6&0xC0|ord($2)&0x3F)}eg; #}; 1970 } 1971 if ($PRINT_ORNAMENTING) { 1972 unless (defined &color) { 1973 if ($CPAN::META->has_inst("Term::ANSIColor")) { 1974 import Term::ANSIColor "color"; 1975 } else { 1976 *color = sub { return "" }; 1977 } 1978 } 1979 my $line; 1980 for $line (split /\n/, $what) { 1981 $longest = length($line) if length($line) > $longest; 1982 } 1983 my $sprintf = "%-" . $longest . "s"; 1984 while ($what){ 1985 $what =~ s/(.*\n?)//m; 1986 my $line = $1; 1987 last unless $line; 1988 my($nl) = chomp $line ? "\n" : ""; 1989 # print "line[$line]ornament[$ornament]sprintf[$sprintf]\n"; 1990 print color($ornament), sprintf($sprintf,$line), color("reset"), $nl; 1991 } 1992 } else { 1993 # chomp $what; 1994 # $what .= "\n"; # newlines unless $PRINT_ORNAMENTING 1995 print $what; 1996 } 1997} 1998 1999sub myprint { 2000 my($self,$what) = @_; 2001 2002 $self->print_ornamented($what, 'bold blue on_yellow'); 2003} 2004 2005sub myexit { 2006 my($self,$what) = @_; 2007 $self->myprint($what); 2008 exit; 2009} 2010 2011sub mywarn { 2012 my($self,$what) = @_; 2013 $self->print_ornamented($what, 'bold red on_yellow'); 2014} 2015 2016sub myconfess { 2017 my($self,$what) = @_; 2018 $self->print_ornamented($what, 'bold red on_white'); 2019 Carp::confess "died"; 2020} 2021 2022sub mydie { 2023 my($self,$what) = @_; 2024 $self->print_ornamented($what, 'bold red on_white'); 2025 die "\n"; 2026} 2027 2028sub setup_output { 2029 return if -t STDOUT; 2030 my $odef = select STDERR; 2031 $| = 1; 2032 select STDOUT; 2033 $| = 1; 2034 select $odef; 2035} 2036 2037#-> sub CPAN::Shell::rematein ; 2038# RE-adme||MA-ke||TE-st||IN-stall 2039sub rematein { 2040 shift; 2041 my($meth,@some) = @_; 2042 my $pragma = ""; 2043 if ($meth eq 'force') { 2044 $pragma = $meth; 2045 $meth = shift @some; 2046 } 2047 setup_output(); 2048 CPAN->debug("pragma[$pragma]meth[$meth] some[@some]") if $CPAN::DEBUG; 2049 2050 # Here is the place to set "test_count" on all involved parties to 2051 # 0. We then can pass this counter on to the involved 2052 # distributions and those can refuse to test if test_count > X. In 2053 # the first stab at it we could use a 1 for "X". 2054 2055 # But when do I reset the distributions to start with 0 again? 2056 # Jost suggested to have a random or cycling interaction ID that 2057 # we pass through. But the ID is something that is just left lying 2058 # around in addition to the counter, so I'd prefer to set the 2059 # counter to 0 now, and repeat at the end of the loop. But what 2060 # about dependencies? They appear later and are not reset, they 2061 # enter the queue but not its copy. How do they get a sensible 2062 # test_count? 2063 2064 # construct the queue 2065 my($s,@s,@qcopy); 2066 foreach $s (@some) { 2067 my $obj; 2068 if (ref $s) { 2069 CPAN->debug("s is an object[$s]") if $CPAN::DEBUG; 2070 $obj = $s; 2071 } elsif ($s =~ m|^/|) { # looks like a regexp 2072 $CPAN::Frontend->mywarn("Sorry, $meth with a regular expression is ". 2073 "not supported\n"); 2074 sleep 2; 2075 next; 2076 } else { 2077 CPAN->debug("calling expandany [$s]") if $CPAN::DEBUG; 2078 $obj = CPAN::Shell->expandany($s); 2079 } 2080 if (ref $obj) { 2081 $obj->color_cmd_tmps(0,1); 2082 CPAN::Queue->new($obj->id); 2083 push @qcopy, $obj; 2084 } elsif ($CPAN::META->exists('CPAN::Author',$s)) { 2085 $obj = $CPAN::META->instance('CPAN::Author',$s); 2086 if ($meth =~ /^(dump|ls)$/) { 2087 $obj->$meth(); 2088 } else { 2089 $CPAN::Frontend->myprint( 2090 join "", 2091 "Don't be silly, you can't $meth ", 2092 $obj->fullname, 2093 " ;-)\n" 2094 ); 2095 sleep 2; 2096 } 2097 } else { 2098 $CPAN::Frontend 2099 ->myprint(qq{Warning: Cannot $meth $s, }. 2100 qq{don\'t know what it is. 2101Try the command 2102 2103 i /$s/ 2104 2105to find objects with matching identifiers. 2106}); 2107 sleep 2; 2108 } 2109 } 2110 2111 # queuerunner (please be warned: when I started to change the 2112 # queue to hold objects instead of names, I made one or two 2113 # mistakes and never found which. I reverted back instead) 2114 while ($s = CPAN::Queue->first) { 2115 my $obj; 2116 if (ref $s) { 2117 $obj = $s; # I do not believe, we would survive if this happened 2118 } else { 2119 $obj = CPAN::Shell->expandany($s); 2120 } 2121 if ($pragma 2122 && 2123 ($] < 5.00303 || $obj->can($pragma))){ 2124 ### compatibility with 5.003 2125 $obj->$pragma($meth); # the pragma "force" in 2126 # "CPAN::Distribution" must know 2127 # what we are intending 2128 } 2129 if ($]>=5.00303 && $obj->can('called_for')) { 2130 $obj->called_for($s); 2131 } 2132 CPAN->debug( 2133 qq{pragma[$pragma]meth[$meth]obj[$obj]as_string\[}. 2134 $obj->as_string. 2135 qq{\]} 2136 ) if $CPAN::DEBUG; 2137 2138 if ($obj->$meth()){ 2139 CPAN::Queue->delete($s); 2140 } else { 2141 CPAN->debug("failed"); 2142 } 2143 2144 $obj->undelay; 2145 CPAN::Queue->delete_first($s); 2146 } 2147 for my $obj (@qcopy) { 2148 $obj->color_cmd_tmps(0,0); 2149 } 2150} 2151 2152#-> sub CPAN::Shell::dump ; 2153sub dump { shift->rematein('dump',@_); } 2154#-> sub CPAN::Shell::force ; 2155sub force { shift->rematein('force',@_); } 2156#-> sub CPAN::Shell::get ; 2157sub get { shift->rematein('get',@_); } 2158#-> sub CPAN::Shell::readme ; 2159sub readme { shift->rematein('readme',@_); } 2160#-> sub CPAN::Shell::make ; 2161sub make { shift->rematein('make',@_); } 2162#-> sub CPAN::Shell::test ; 2163sub test { shift->rematein('test',@_); } 2164#-> sub CPAN::Shell::install ; 2165sub install { shift->rematein('install',@_); } 2166#-> sub CPAN::Shell::clean ; 2167sub clean { shift->rematein('clean',@_); } 2168#-> sub CPAN::Shell::look ; 2169sub look { shift->rematein('look',@_); } 2170#-> sub CPAN::Shell::cvs_import ; 2171sub cvs_import { shift->rematein('cvs_import',@_); } 2172 2173package CPAN::LWP::UserAgent; 2174 2175sub config { 2176 return if $SETUPDONE; 2177 if ($CPAN::META->has_usable('LWP::UserAgent')) { 2178 require LWP::UserAgent; 2179 @ISA = qw(Exporter LWP::UserAgent); 2180 $SETUPDONE++; 2181 } else { 2182 $CPAN::Frontend->mywarn("LWP::UserAgent not available\n"); 2183 } 2184} 2185 2186sub get_basic_credentials { 2187 my($self, $realm, $uri, $proxy) = @_; 2188 return unless $proxy; 2189 if ($USER && $PASSWD) { 2190 } elsif (defined $CPAN::Config->{proxy_user} && 2191 defined $CPAN::Config->{proxy_pass}) { 2192 $USER = $CPAN::Config->{proxy_user}; 2193 $PASSWD = $CPAN::Config->{proxy_pass}; 2194 } else { 2195 require ExtUtils::MakeMaker; 2196 ExtUtils::MakeMaker->import(qw(prompt)); 2197 $USER = prompt("Proxy authentication needed! 2198 (Note: to permanently configure username and password run 2199 o conf proxy_user your_username 2200 o conf proxy_pass your_password 2201 )\nUsername:"); 2202 if ($CPAN::META->has_inst("Term::ReadKey")) { 2203 Term::ReadKey::ReadMode("noecho"); 2204 } else { 2205 $CPAN::Frontend->mywarn("Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal!\n"); 2206 } 2207 $PASSWD = prompt("Password:"); 2208 if ($CPAN::META->has_inst("Term::ReadKey")) { 2209 Term::ReadKey::ReadMode("restore"); 2210 } 2211 $CPAN::Frontend->myprint("\n\n"); 2212 } 2213 return($USER,$PASSWD); 2214} 2215 2216# mirror(): Its purpose is to deal with proxy authentication. When we 2217# call SUPER::mirror, we relly call the mirror method in 2218# LWP::UserAgent. LWP::UserAgent will then call 2219# $self->get_basic_credentials or some equivalent and this will be 2220# $self->dispatched to our own get_basic_credentials method. 2221 2222# Our own get_basic_credentials sets $USER and $PASSWD, two globals. 2223 2224# 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means 2225# although we have gone through our get_basic_credentials, the proxy 2226# server refuses to connect. This could be a case where the username or 2227# password has changed in the meantime, so I'm trying once again without 2228# $USER and $PASSWD to give the get_basic_credentials routine another 2229# chance to set $USER and $PASSWD. 2230 2231sub mirror { 2232 my($self,$url,$aslocal) = @_; 2233 my $result = $self->SUPER::mirror($url,$aslocal); 2234 if ($result->code == 407) { 2235 undef $USER; 2236 undef $PASSWD; 2237 $result = $self->SUPER::mirror($url,$aslocal); 2238 } 2239 $result; 2240} 2241 2242package CPAN::FTP; 2243 2244#-> sub CPAN::FTP::ftp_get ; 2245sub ftp_get { 2246 my($class,$host,$dir,$file,$target) = @_; 2247 $class->debug( 2248 qq[Going to fetch file [$file] from dir [$dir] 2249 on host [$host] as local [$target]\n] 2250 ) if $CPAN::DEBUG; 2251 my $ftp = Net::FTP->new($host); 2252 return 0 unless defined $ftp; 2253 $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG; 2254 $class->debug(qq[Going to login("anonymous","$Config::Config{cf_email}")]); 2255 unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ){ 2256 warn "Couldn't login on $host"; 2257 return; 2258 } 2259 unless ( $ftp->cwd($dir) ){ 2260 warn "Couldn't cwd $dir"; 2261 return; 2262 } 2263 $ftp->binary; 2264 $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG; 2265 unless ( $ftp->get($file,$target) ){ 2266 warn "Couldn't fetch $file from $host\n"; 2267 return; 2268 } 2269 $ftp->quit; # it's ok if this fails 2270 return 1; 2271} 2272 2273# If more accuracy is wanted/needed, Chris Leach sent me this patch... 2274 2275 # > *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997 2276 # > --- /tmp/cp Wed Sep 24 13:26:40 1997 2277 # > *************** 2278 # > *** 1562,1567 **** 2279 # > --- 1562,1580 ---- 2280 # > return 1 if substr($url,0,4) eq "file"; 2281 # > return 1 unless $url =~ m|://([^/]+)|; 2282 # > my $host = $1; 2283 # > + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'}; 2284 # > + if ($proxy) { 2285 # > + $proxy =~ m|://([^/:]+)|; 2286 # > + $proxy = $1; 2287 # > + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'}; 2288 # > + if ($noproxy) { 2289 # > + if ($host !~ /$noproxy$/) { 2290 # > + $host = $proxy; 2291 # > + } 2292 # > + } else { 2293 # > + $host = $proxy; 2294 # > + } 2295 # > + } 2296 # > require Net::Ping; 2297 # > return 1 unless $Net::Ping::VERSION >= 2; 2298 # > my $p; 2299 2300 2301#-> sub CPAN::FTP::localize ; 2302sub localize { 2303 my($self,$file,$aslocal,$force) = @_; 2304 $force ||= 0; 2305 Carp::croak "Usage: ->localize(cpan_file,as_local_file[,$force])" 2306 unless defined $aslocal; 2307 $self->debug("file[$file] aslocal[$aslocal] force[$force]") 2308 if $CPAN::DEBUG; 2309 2310 if ($^O eq 'MacOS') { 2311 # Comment by AK on 2000-09-03: Uniq short filenames would be 2312 # available in CHECKSUMS file 2313 my($name, $path) = File::Basename::fileparse($aslocal, ''); 2314 if (length($name) > 31) { 2315 $name =~ s/( 2316 \.( 2317 readme(\.(gz|Z))? | 2318 (tar\.)?(gz|Z) | 2319 tgz | 2320 zip | 2321 pm\.(gz|Z) 2322 ) 2323 )$//x; 2324 my $suf = $1; 2325 my $size = 31 - length($suf); 2326 while (length($name) > $size) { 2327 chop $name; 2328 } 2329 $name .= $suf; 2330 $aslocal = File::Spec->catfile($path, $name); 2331 } 2332 } 2333 2334 return $aslocal if -f $aslocal && -r _ && !($force & 1); 2335 my($restore) = 0; 2336 if (-f $aslocal){ 2337 rename $aslocal, "$aslocal.bak"; 2338 $restore++; 2339 } 2340 2341 my($aslocal_dir) = File::Basename::dirname($aslocal); 2342 File::Path::mkpath($aslocal_dir); 2343 $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }. 2344 qq{directory "$aslocal_dir". 2345 I\'ll continue, but if you encounter problems, they may be due 2346 to insufficient permissions.\n}) unless -w $aslocal_dir; 2347 2348 # Inheritance is not easier to manage than a few if/else branches 2349 if ($CPAN::META->has_usable('LWP::UserAgent')) { 2350 unless ($Ua) { 2351 CPAN::LWP::UserAgent->config; 2352 eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough? 2353 if ($@) { 2354 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n") 2355 if $CPAN::DEBUG; 2356 } else { 2357 my($var); 2358 $Ua->proxy('ftp', $var) 2359 if $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy}; 2360 $Ua->proxy('http', $var) 2361 if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy}; 2362 2363 2364# >>>>> On Wed, 13 Dec 2000 09:21:34 -0500, "Robison, Jonathon (J.M.)" <jrobiso2@visteon.com> said: 2365# 2366# > I note that although CPAN.pm can use proxies, it doesn't seem equipped to 2367# > use ones that require basic autorization. 2368# 2369# > Example of when I use it manually in my own stuff: 2370# 2371# > $ua->proxy(['http','ftp'], http://my.proxy.server:83'); 2372# > $req->proxy_authorization_basic("username","password"); 2373# > $res = $ua->request($req); 2374# 2375 2376 $Ua->no_proxy($var) 2377 if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy}; 2378 } 2379 } 2380 } 2381 for my $prx (qw(ftp_proxy http_proxy no_proxy)) { 2382 $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx}; 2383 } 2384 2385 # Try the list of urls for each single object. We keep a record 2386 # where we did get a file from 2387 my(@reordered,$last); 2388 $CPAN::Config->{urllist} ||= []; 2389 unless (ref $CPAN::Config->{urllist} eq 'ARRAY') { 2390 warn "Malformed urllist; ignoring. Configuration file corrupt?\n"; 2391 } 2392 $last = $#{$CPAN::Config->{urllist}}; 2393 if ($force & 2) { # local cpans probably out of date, don't reorder 2394 @reordered = (0..$last); 2395 } else { 2396 @reordered = 2397 sort { 2398 (substr($CPAN::Config->{urllist}[$b],0,4) eq "file") 2399 <=> 2400 (substr($CPAN::Config->{urllist}[$a],0,4) eq "file") 2401 or 2402 defined($Thesite) 2403 and 2404 ($b == $Thesite) 2405 <=> 2406 ($a == $Thesite) 2407 } 0..$last; 2408 } 2409 my(@levels); 2410 if ($Themethod) { 2411 @levels = ($Themethod, grep {$_ ne $Themethod} qw/easy hard hardest/); 2412 } else { 2413 @levels = qw/easy hard hardest/; 2414 } 2415 @levels = qw/easy/ if $^O eq 'MacOS'; 2416 my($levelno); 2417 for $levelno (0..$#levels) { 2418 my $level = $levels[$levelno]; 2419 my $method = "host$level"; 2420 my @host_seq = $level eq "easy" ? 2421 @reordered : 0..$last; # reordered has CDROM up front 2422 @host_seq = (0) unless @host_seq; 2423 my $ret = $self->$method(\@host_seq,$file,$aslocal); 2424 if ($ret) { 2425 $Themethod = $level; 2426 my $now = time; 2427 # utime $now, $now, $aslocal; # too bad, if we do that, we 2428 # might alter a local mirror 2429 $self->debug("level[$level]") if $CPAN::DEBUG; 2430 return $ret; 2431 } else { 2432 unlink $aslocal; 2433 last if $CPAN::Signal; # need to cleanup 2434 } 2435 } 2436 unless ($CPAN::Signal) { 2437 my(@mess); 2438 push @mess, 2439 qq{Please check, if the URLs I found in your configuration file \(}. 2440 join(", ", @{$CPAN::Config->{urllist}}). 2441 qq{\) are valid. The urllist can be edited.}, 2442 qq{E.g. with 'o conf urllist push ftp://myurl/'}; 2443 $CPAN::Frontend->myprint(Text::Wrap::wrap("","",@mess). "\n\n"); 2444 sleep 2; 2445 $CPAN::Frontend->myprint("Could not fetch $file\n"); 2446 } 2447 if ($restore) { 2448 rename "$aslocal.bak", $aslocal; 2449 $CPAN::Frontend->myprint("Trying to get away with old file:\n" . 2450 $self->ls($aslocal)); 2451 return $aslocal; 2452 } 2453 return; 2454} 2455 2456sub hosteasy { 2457 my($self,$host_seq,$file,$aslocal) = @_; 2458 my($i); 2459 HOSTEASY: for $i (@$host_seq) { 2460 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite; 2461 $url .= "/" unless substr($url,-1) eq "/"; 2462 $url .= $file; 2463 $self->debug("localizing perlish[$url]") if $CPAN::DEBUG; 2464 if ($url =~ /^file:/) { 2465 my $l; 2466 if ($CPAN::META->has_inst('URI::URL')) { 2467 my $u = URI::URL->new($url); 2468 $l = $u->path; 2469 } else { # works only on Unix, is poorly constructed, but 2470 # hopefully better than nothing. 2471 # RFC 1738 says fileurl BNF is 2472 # fileurl = "file://" [ host | "localhost" ] "/" fpath 2473 # Thanks to "Mark D. Baushke" <mdb@cisco.com> for 2474 # the code 2475 ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part 2476 $l =~ s|^file:||; # assume they 2477 # meant 2478 # file://localhost 2479 $l =~ s|^/||s unless -f $l; # e.g. /P: 2480 $self->debug("without URI::URL we try local file $l") if $CPAN::DEBUG; 2481 } 2482 if ( -f $l && -r _) { 2483 $Thesite = $i; 2484 return $l; 2485 } 2486 # Maybe mirror has compressed it? 2487 if (-f "$l.gz") { 2488 $self->debug("found compressed $l.gz") if $CPAN::DEBUG; 2489 CPAN::Tarzip->gunzip("$l.gz", $aslocal); 2490 if ( -f $aslocal) { 2491 $Thesite = $i; 2492 return $aslocal; 2493 } 2494 } 2495 } 2496 if ($CPAN::META->has_usable('LWP')) { 2497 $CPAN::Frontend->myprint("Fetching with LWP: 2498 $url 2499"); 2500 unless ($Ua) { 2501 CPAN::LWP::UserAgent->config; 2502 eval { $Ua = CPAN::LWP::UserAgent->new; }; 2503 if ($@) { 2504 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n"); 2505 } 2506 } 2507 my $res = $Ua->mirror($url, $aslocal); 2508 if ($res->is_success) { 2509 $Thesite = $i; 2510 my $now = time; 2511 utime $now, $now, $aslocal; # download time is more 2512 # important than upload time 2513 return $aslocal; 2514 } elsif ($url !~ /\.gz(?!\n)\Z/) { 2515 my $gzurl = "$url.gz"; 2516 $CPAN::Frontend->myprint("Fetching with LWP: 2517 $gzurl 2518"); 2519 $res = $Ua->mirror($gzurl, "$aslocal.gz"); 2520 if ($res->is_success && 2521 CPAN::Tarzip->gunzip("$aslocal.gz",$aslocal) 2522 ) { 2523 $Thesite = $i; 2524 return $aslocal; 2525 } 2526 } else { 2527 $CPAN::Frontend->myprint(sprintf( 2528 "LWP failed with code[%s] message[%s]\n", 2529 $res->code, 2530 $res->message, 2531 )); 2532 # Alan Burlison informed me that in firewall environments 2533 # Net::FTP can still succeed where LWP fails. So we do not 2534 # skip Net::FTP anymore when LWP is available. 2535 } 2536 } else { 2537 $CPAN::Frontend->myprint("LWP not available\n"); 2538 } 2539 return if $CPAN::Signal; 2540 if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 2541 # that's the nice and easy way thanks to Graham 2542 my($host,$dir,$getfile) = ($1,$2,$3); 2543 if ($CPAN::META->has_usable('Net::FTP')) { 2544 $dir =~ s|/+|/|g; 2545 $CPAN::Frontend->myprint("Fetching with Net::FTP: 2546 $url 2547"); 2548 $self->debug("getfile[$getfile]dir[$dir]host[$host]" . 2549 "aslocal[$aslocal]") if $CPAN::DEBUG; 2550 if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) { 2551 $Thesite = $i; 2552 return $aslocal; 2553 } 2554 if ($aslocal !~ /\.gz(?!\n)\Z/) { 2555 my $gz = "$aslocal.gz"; 2556 $CPAN::Frontend->myprint("Fetching with Net::FTP 2557 $url.gz 2558"); 2559 if (CPAN::FTP->ftp_get($host, 2560 $dir, 2561 "$getfile.gz", 2562 $gz) && 2563 CPAN::Tarzip->gunzip($gz,$aslocal) 2564 ){ 2565 $Thesite = $i; 2566 return $aslocal; 2567 } 2568 } 2569 # next HOSTEASY; 2570 } 2571 } 2572 return if $CPAN::Signal; 2573 } 2574} 2575 2576sub hosthard { 2577 my($self,$host_seq,$file,$aslocal) = @_; 2578 2579 # Came back if Net::FTP couldn't establish connection (or 2580 # failed otherwise) Maybe they are behind a firewall, but they 2581 # gave us a socksified (or other) ftp program... 2582 2583 my($i); 2584 my($devnull) = $CPAN::Config->{devnull} || ""; 2585 # < /dev/null "; 2586 my($aslocal_dir) = File::Basename::dirname($aslocal); 2587 File::Path::mkpath($aslocal_dir); 2588 HOSTHARD: for $i (@$host_seq) { 2589 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite; 2590 $url .= "/" unless substr($url,-1) eq "/"; 2591 $url .= $file; 2592 my($proto,$host,$dir,$getfile); 2593 2594 # Courtesy Mark Conty mark_conty@cargill.com change from 2595 # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 2596 # to 2597 if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) { 2598 # proto not yet used 2599 ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4); 2600 } else { 2601 next HOSTHARD; # who said, we could ftp anything except ftp? 2602 } 2603 next HOSTHARD if $proto eq "file"; # file URLs would have had 2604 # success above. Likely a bogus URL 2605 2606 $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG; 2607 my($f,$funkyftp); 2608 for $f ('lynx','ncftpget','ncftp','wget') { 2609 next unless exists $CPAN::Config->{$f}; 2610 $funkyftp = $CPAN::Config->{$f}; 2611 next unless defined $funkyftp; 2612 next if $funkyftp =~ /^\s*$/; 2613 my($asl_ungz, $asl_gz); 2614 ($asl_ungz = $aslocal) =~ s/\.gz//; 2615 $asl_gz = "$asl_ungz.gz"; 2616 my($src_switch) = ""; 2617 if ($f eq "lynx"){ 2618 $src_switch = " -source"; 2619 } elsif ($f eq "ncftp"){ 2620 $src_switch = " -c"; 2621 } elsif ($f eq "wget"){ 2622 $src_switch = " -O -"; 2623 } 2624 my($chdir) = ""; 2625 my($stdout_redir) = " > $asl_ungz"; 2626 if ($f eq "ncftpget"){ 2627 $chdir = "cd $aslocal_dir && "; 2628 $stdout_redir = ""; 2629 } 2630 $CPAN::Frontend->myprint( 2631 qq[ 2632Trying with "$funkyftp$src_switch" to get 2633 $url 2634]); 2635 my($system) = 2636 "$chdir$funkyftp$src_switch \"$url\" $devnull$stdout_redir"; 2637 $self->debug("system[$system]") if $CPAN::DEBUG; 2638 my($wstatus); 2639 if (($wstatus = system($system)) == 0 2640 && 2641 ($f eq "lynx" ? 2642 -s $asl_ungz # lynx returns 0 when it fails somewhere 2643 : 1 2644 ) 2645 ) { 2646 if (-s $aslocal) { 2647 # Looks good 2648 } elsif ($asl_ungz ne $aslocal) { 2649 # test gzip integrity 2650 if (CPAN::Tarzip->gtest($asl_ungz)) { 2651 # e.g. foo.tar is gzipped --> foo.tar.gz 2652 rename $asl_ungz, $aslocal; 2653 } else { 2654 CPAN::Tarzip->gzip($asl_ungz,$asl_gz); 2655 } 2656 } 2657 $Thesite = $i; 2658 return $aslocal; 2659 } elsif ($url !~ /\.gz(?!\n)\Z/) { 2660 unlink $asl_ungz if 2661 -f $asl_ungz && -s _ == 0; 2662 my $gz = "$aslocal.gz"; 2663 my $gzurl = "$url.gz"; 2664 $CPAN::Frontend->myprint( 2665 qq[ 2666Trying with "$funkyftp$src_switch" to get 2667 $url.gz 2668]); 2669 my($system) = "$funkyftp$src_switch \"$url.gz\" $devnull > $asl_gz"; 2670 $self->debug("system[$system]") if $CPAN::DEBUG; 2671 my($wstatus); 2672 if (($wstatus = system($system)) == 0 2673 && 2674 -s $asl_gz 2675 ) { 2676 # test gzip integrity 2677 if (CPAN::Tarzip->gtest($asl_gz)) { 2678 CPAN::Tarzip->gunzip($asl_gz,$aslocal); 2679 } else { 2680 # somebody uncompressed file for us? 2681 rename $asl_ungz, $aslocal; 2682 } 2683 $Thesite = $i; 2684 return $aslocal; 2685 } else { 2686 unlink $asl_gz if -f $asl_gz; 2687 } 2688 } else { 2689 my $estatus = $wstatus >> 8; 2690 my $size = -f $aslocal ? 2691 ", left\n$aslocal with size ".-s _ : 2692 "\nWarning: expected file [$aslocal] doesn't exist"; 2693 $CPAN::Frontend->myprint(qq{ 2694System call "$system" 2695returned status $estatus (wstat $wstatus)$size 2696}); 2697 } 2698 return if $CPAN::Signal; 2699 } # lynx,ncftpget,ncftp 2700 } # host 2701} 2702 2703sub hosthardest { 2704 my($self,$host_seq,$file,$aslocal) = @_; 2705 2706 my($i); 2707 my($aslocal_dir) = File::Basename::dirname($aslocal); 2708 File::Path::mkpath($aslocal_dir); 2709 my $ftpbin = $CPAN::Config->{ftp}; 2710 HOSTHARDEST: for $i (@$host_seq) { 2711 unless (length $ftpbin && MM->maybe_command($ftpbin)) { 2712 $CPAN::Frontend->myprint("No external ftp command available\n\n"); 2713 last HOSTHARDEST; 2714 } 2715 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite; 2716 $url .= "/" unless substr($url,-1) eq "/"; 2717 $url .= $file; 2718 $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG; 2719 unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 2720 next; 2721 } 2722 my($host,$dir,$getfile) = ($1,$2,$3); 2723 my $timestamp = 0; 2724 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime, 2725 $ctime,$blksize,$blocks) = stat($aslocal); 2726 $timestamp = $mtime ||= 0; 2727 my($netrc) = CPAN::FTP::netrc->new; 2728 my($netrcfile) = $netrc->netrc; 2729 my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : ""; 2730 my $targetfile = File::Basename::basename($aslocal); 2731 my(@dialog); 2732 push( 2733 @dialog, 2734 "lcd $aslocal_dir", 2735 "cd /", 2736 map("cd $_", split /\//, $dir), # RFC 1738 2737 "bin", 2738 "get $getfile $targetfile", 2739 "quit" 2740 ); 2741 if (! $netrcfile) { 2742 CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG; 2743 } elsif ($netrc->hasdefault || $netrc->contains($host)) { 2744 CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]", 2745 $netrc->hasdefault, 2746 $netrc->contains($host))) if $CPAN::DEBUG; 2747 if ($netrc->protected) { 2748 $CPAN::Frontend->myprint(qq{ 2749 Trying with external ftp to get 2750 $url 2751 As this requires some features that are not thoroughly tested, we\'re 2752 not sure, that we get it right.... 2753 2754} 2755 ); 2756 $self->talk_ftp("$ftpbin$verbose $host", 2757 @dialog); 2758 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 2759 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); 2760 $mtime ||= 0; 2761 if ($mtime > $timestamp) { 2762 $CPAN::Frontend->myprint("GOT $aslocal\n"); 2763 $Thesite = $i; 2764 return $aslocal; 2765 } else { 2766 $CPAN::Frontend->myprint("Hmm... Still failed!\n"); 2767 } 2768 return if $CPAN::Signal; 2769 } else { 2770 $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }. 2771 qq{correctly protected.\n}); 2772 } 2773 } else { 2774 $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host 2775 nor does it have a default entry\n"); 2776 } 2777 2778 # OK, they don't have a valid ~/.netrc. Use 'ftp -n' 2779 # then and login manually to host, using e-mail as 2780 # password. 2781 $CPAN::Frontend->myprint(qq{Issuing "$ftpbin$verbose -n"\n}); 2782 unshift( 2783 @dialog, 2784 "open $host", 2785 "user anonymous $Config::Config{'cf_email'}" 2786 ); 2787 $self->talk_ftp("$ftpbin$verbose -n", @dialog); 2788 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 2789 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); 2790 $mtime ||= 0; 2791 if ($mtime > $timestamp) { 2792 $CPAN::Frontend->myprint("GOT $aslocal\n"); 2793 $Thesite = $i; 2794 return $aslocal; 2795 } else { 2796 $CPAN::Frontend->myprint("Bad luck... Still failed!\n"); 2797 } 2798 return if $CPAN::Signal; 2799 $CPAN::Frontend->myprint("Can't access URL $url.\n\n"); 2800 sleep 2; 2801 } # host 2802} 2803 2804sub talk_ftp { 2805 my($self,$command,@dialog) = @_; 2806 my $fh = FileHandle->new; 2807 $fh->open("|$command") or die "Couldn't open ftp: $!"; 2808 foreach (@dialog) { $fh->print("$_\n") } 2809 $fh->close; # Wait for process to complete 2810 my $wstatus = $?; 2811 my $estatus = $wstatus >> 8; 2812 $CPAN::Frontend->myprint(qq{ 2813Subprocess "|$command" 2814 returned status $estatus (wstat $wstatus) 2815}) if $wstatus; 2816} 2817 2818# find2perl needs modularization, too, all the following is stolen 2819# from there 2820# CPAN::FTP::ls 2821sub ls { 2822 my($self,$name) = @_; 2823 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm, 2824 $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name); 2825 2826 my($perms,%user,%group); 2827 my $pname = $name; 2828 2829 if ($blocks) { 2830 $blocks = int(($blocks + 1) / 2); 2831 } 2832 else { 2833 $blocks = int(($sizemm + 1023) / 1024); 2834 } 2835 2836 if (-f _) { $perms = '-'; } 2837 elsif (-d _) { $perms = 'd'; } 2838 elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; } 2839 elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; } 2840 elsif (-p _) { $perms = 'p'; } 2841 elsif (-S _) { $perms = 's'; } 2842 else { $perms = 'l'; $pname .= ' -> ' . readlink($_); } 2843 2844 my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx'); 2845 my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); 2846 my $tmpmode = $mode; 2847 my $tmp = $rwx[$tmpmode & 7]; 2848 $tmpmode >>= 3; 2849 $tmp = $rwx[$tmpmode & 7] . $tmp; 2850 $tmpmode >>= 3; 2851 $tmp = $rwx[$tmpmode & 7] . $tmp; 2852 substr($tmp,2,1) =~ tr/-x/Ss/ if -u _; 2853 substr($tmp,5,1) =~ tr/-x/Ss/ if -g _; 2854 substr($tmp,8,1) =~ tr/-x/Tt/ if -k _; 2855 $perms .= $tmp; 2856 2857 my $user = $user{$uid} || $uid; # too lazy to implement lookup 2858 my $group = $group{$gid} || $gid; 2859 2860 my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime); 2861 my($timeyear); 2862 my($moname) = $moname[$mon]; 2863 if (-M _ > 365.25 / 2) { 2864 $timeyear = $year + 1900; 2865 } 2866 else { 2867 $timeyear = sprintf("%02d:%02d", $hour, $min); 2868 } 2869 2870 sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n", 2871 $ino, 2872 $blocks, 2873 $perms, 2874 $nlink, 2875 $user, 2876 $group, 2877 $sizemm, 2878 $moname, 2879 $mday, 2880 $timeyear, 2881 $pname; 2882} 2883 2884package CPAN::FTP::netrc; 2885 2886sub new { 2887 my($class) = @_; 2888 my $file = File::Spec->catfile($ENV{HOME},".netrc"); 2889 2890 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 2891 $atime,$mtime,$ctime,$blksize,$blocks) 2892 = stat($file); 2893 $mode ||= 0; 2894 my $protected = 0; 2895 2896 my($fh,@machines,$hasdefault); 2897 $hasdefault = 0; 2898 $fh = FileHandle->new or die "Could not create a filehandle"; 2899 2900 if($fh->open($file)){ 2901 $protected = ($mode & 077) == 0; 2902 local($/) = ""; 2903 NETRC: while (<$fh>) { 2904 my(@tokens) = split " ", $_; 2905 TOKEN: while (@tokens) { 2906 my($t) = shift @tokens; 2907 if ($t eq "default"){ 2908 $hasdefault++; 2909 last NETRC; 2910 } 2911 last TOKEN if $t eq "macdef"; 2912 if ($t eq "machine") { 2913 push @machines, shift @tokens; 2914 } 2915 } 2916 } 2917 } else { 2918 $file = $hasdefault = $protected = ""; 2919 } 2920 2921 bless { 2922 'mach' => [@machines], 2923 'netrc' => $file, 2924 'hasdefault' => $hasdefault, 2925 'protected' => $protected, 2926 }, $class; 2927} 2928 2929# CPAN::FTP::hasdefault; 2930sub hasdefault { shift->{'hasdefault'} } 2931sub netrc { shift->{'netrc'} } 2932sub protected { shift->{'protected'} } 2933sub contains { 2934 my($self,$mach) = @_; 2935 for ( @{$self->{'mach'}} ) { 2936 return 1 if $_ eq $mach; 2937 } 2938 return 0; 2939} 2940 2941package CPAN::Complete; 2942 2943sub gnu_cpl { 2944 my($text, $line, $start, $end) = @_; 2945 my(@perlret) = cpl($text, $line, $start); 2946 # find longest common match. Can anybody show me how to peruse 2947 # T::R::Gnu to have this done automatically? Seems expensive. 2948 return () unless @perlret; 2949 my($newtext) = $text; 2950 for (my $i = length($text)+1;;$i++) { 2951 last unless length($perlret[0]) && length($perlret[0]) >= $i; 2952 my $try = substr($perlret[0],0,$i); 2953 my @tries = grep {substr($_,0,$i) eq $try} @perlret; 2954 # warn "try[$try]tries[@tries]"; 2955 if (@tries == @perlret) { 2956 $newtext = $try; 2957 } else { 2958 last; 2959 } 2960 } 2961 ($newtext,@perlret); 2962} 2963 2964#-> sub CPAN::Complete::cpl ; 2965sub cpl { 2966 my($word,$line,$pos) = @_; 2967 $word ||= ""; 2968 $line ||= ""; 2969 $pos ||= 0; 2970 CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 2971 $line =~ s/^\s*//; 2972 if ($line =~ s/^(force\s*)//) { 2973 $pos -= length($1); 2974 } 2975 my @return; 2976 if ($pos == 0) { 2977 @return = grep /^$word/, @CPAN::Complete::COMMANDS; 2978 } elsif ( $line !~ /^[\!abcdghimorutl]/ ) { 2979 @return = (); 2980 } elsif ($line =~ /^(a|ls)\s/) { 2981 @return = cplx('CPAN::Author',uc($word)); 2982 } elsif ($line =~ /^b\s/) { 2983 CPAN::Shell->local_bundles; 2984 @return = cplx('CPAN::Bundle',$word); 2985 } elsif ($line =~ /^d\s/) { 2986 @return = cplx('CPAN::Distribution',$word); 2987 } elsif ($line =~ m/^( 2988 [mru]|make|clean|dump|get|test|install|readme|look|cvs_import 2989 )\s/x ) { 2990 if ($word =~ /^Bundle::/) { 2991 CPAN::Shell->local_bundles; 2992 } 2993 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); 2994 } elsif ($line =~ /^i\s/) { 2995 @return = cpl_any($word); 2996 } elsif ($line =~ /^reload\s/) { 2997 @return = cpl_reload($word,$line,$pos); 2998 } elsif ($line =~ /^o\s/) { 2999 @return = cpl_option($word,$line,$pos); 3000 } elsif ($line =~ m/^\S+\s/ ) { 3001 # fallback for future commands and what we have forgotten above 3002 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); 3003 } else { 3004 @return = (); 3005 } 3006 return @return; 3007} 3008 3009#-> sub CPAN::Complete::cplx ; 3010sub cplx { 3011 my($class, $word) = @_; 3012 # I believed for many years that this was sorted, today I 3013 # realized, it wasn't sorted anymore. Now (rev 1.301 / v 1.55) I 3014 # make it sorted again. Maybe sort was dropped when GNU-readline 3015 # support came in? The RCS file is difficult to read on that:-( 3016 sort grep /^\Q$word\E/, map { $_->id } $CPAN::META->all_objects($class); 3017} 3018 3019#-> sub CPAN::Complete::cpl_any ; 3020sub cpl_any { 3021 my($word) = shift; 3022 return ( 3023 cplx('CPAN::Author',$word), 3024 cplx('CPAN::Bundle',$word), 3025 cplx('CPAN::Distribution',$word), 3026 cplx('CPAN::Module',$word), 3027 ); 3028} 3029 3030#-> sub CPAN::Complete::cpl_reload ; 3031sub cpl_reload { 3032 my($word,$line,$pos) = @_; 3033 $word ||= ""; 3034 my(@words) = split " ", $line; 3035 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 3036 my(@ok) = qw(cpan index); 3037 return @ok if @words == 1; 3038 return grep /^\Q$word\E/, @ok if @words == 2 && $word; 3039} 3040 3041#-> sub CPAN::Complete::cpl_option ; 3042sub cpl_option { 3043 my($word,$line,$pos) = @_; 3044 $word ||= ""; 3045 my(@words) = split " ", $line; 3046 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 3047 my(@ok) = qw(conf debug); 3048 return @ok if @words == 1; 3049 return grep /^\Q$word\E/, @ok if @words == 2 && length($word); 3050 if (0) { 3051 } elsif ($words[1] eq 'index') { 3052 return (); 3053 } elsif ($words[1] eq 'conf') { 3054 return CPAN::Config::cpl(@_); 3055 } elsif ($words[1] eq 'debug') { 3056 return sort grep /^\Q$word\E/, sort keys %CPAN::DEBUG, 'all'; 3057 } 3058} 3059 3060package CPAN::Index; 3061 3062#-> sub CPAN::Index::force_reload ; 3063sub force_reload { 3064 my($class) = @_; 3065 $CPAN::Index::LAST_TIME = 0; 3066 $class->reload(1); 3067} 3068 3069#-> sub CPAN::Index::reload ; 3070sub reload { 3071 my($cl,$force) = @_; 3072 my $time = time; 3073 3074 # XXX check if a newer one is available. (We currently read it 3075 # from time to time) 3076 for ($CPAN::Config->{index_expire}) { 3077 $_ = 0.001 unless $_ && $_ > 0.001; 3078 } 3079 unless (1 || $CPAN::Have_warned->{readmetadatacache}++) { 3080 # debug here when CPAN doesn't seem to read the Metadata 3081 require Carp; 3082 Carp::cluck("META-PROTOCOL[$CPAN::META->{PROTOCOL}]"); 3083 } 3084 unless ($CPAN::META->{PROTOCOL}) { 3085 $cl->read_metadata_cache; 3086 $CPAN::META->{PROTOCOL} ||= "1.0"; 3087 } 3088 if ( $CPAN::META->{PROTOCOL} < PROTOCOL ) { 3089 # warn "Setting last_time to 0"; 3090 $LAST_TIME = 0; # No warning necessary 3091 } 3092 return if $LAST_TIME + $CPAN::Config->{index_expire}*86400 > $time 3093 and ! $force; 3094 if (0) { 3095 # IFF we are developing, it helps to wipe out the memory 3096 # between reloads, otherwise it is not what a user expects. 3097 undef $CPAN::META; # Neue Gruendlichkeit since v1.52(r1.274) 3098 $CPAN::META = CPAN->new; 3099 } 3100 { 3101 my($debug,$t2); 3102 local $LAST_TIME = $time; 3103 local $CPAN::META->{PROTOCOL} = PROTOCOL; 3104 3105 my $needshort = $^O eq "dos"; 3106 3107 $cl->rd_authindex($cl 3108 ->reload_x( 3109 "authors/01mailrc.txt.gz", 3110 $needshort ? 3111 File::Spec->catfile('authors', '01mailrc.gz') : 3112 File::Spec->catfile('authors', '01mailrc.txt.gz'), 3113 $force)); 3114 $t2 = time; 3115 $debug = "timing reading 01[".($t2 - $time)."]"; 3116 $time = $t2; 3117 return if $CPAN::Signal; # this is sometimes lengthy 3118 $cl->rd_modpacks($cl 3119 ->reload_x( 3120 "modules/02packages.details.txt.gz", 3121 $needshort ? 3122 File::Spec->catfile('modules', '02packag.gz') : 3123 File::Spec->catfile('modules', '02packages.details.txt.gz'), 3124 $force)); 3125 $t2 = time; 3126 $debug .= "02[".($t2 - $time)."]"; 3127 $time = $t2; 3128 return if $CPAN::Signal; # this is sometimes lengthy 3129 $cl->rd_modlist($cl 3130 ->reload_x( 3131 "modules/03modlist.data.gz", 3132 $needshort ? 3133 File::Spec->catfile('modules', '03mlist.gz') : 3134 File::Spec->catfile('modules', '03modlist.data.gz'), 3135 $force)); 3136 $cl->write_metadata_cache; 3137 $t2 = time; 3138 $debug .= "03[".($t2 - $time)."]"; 3139 $time = $t2; 3140 CPAN->debug($debug) if $CPAN::DEBUG; 3141 } 3142 $LAST_TIME = $time; 3143 $CPAN::META->{PROTOCOL} = PROTOCOL; 3144} 3145 3146#-> sub CPAN::Index::reload_x ; 3147sub reload_x { 3148 my($cl,$wanted,$localname,$force) = @_; 3149 $force |= 2; # means we're dealing with an index here 3150 CPAN::Config->load; # we should guarantee loading wherever we rely 3151 # on Config XXX 3152 $localname ||= $wanted; 3153 my $abs_wanted = File::Spec->catfile($CPAN::Config->{'keep_source_where'}, 3154 $localname); 3155 if ( 3156 -f $abs_wanted && 3157 -M $abs_wanted < $CPAN::Config->{'index_expire'} && 3158 !($force & 1) 3159 ) { 3160 my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s"; 3161 $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }. 3162 qq{day$s. I\'ll use that.}); 3163 return $abs_wanted; 3164 } else { 3165 $force |= 1; # means we're quite serious about it. 3166 } 3167 return CPAN::FTP->localize($wanted,$abs_wanted,$force); 3168} 3169 3170#-> sub CPAN::Index::rd_authindex ; 3171sub rd_authindex { 3172 my($cl, $index_target) = @_; 3173 my @lines; 3174 return unless defined $index_target; 3175 $CPAN::Frontend->myprint("Going to read $index_target\n"); 3176 local(*FH); 3177 tie *FH, CPAN::Tarzip, $index_target; 3178 local($/) = "\n"; 3179 push @lines, split /\012/ while <FH>; 3180 foreach (@lines) { 3181 my($userid,$fullname,$email) = 3182 m/alias\s+(\S+)\s+\"([^\"\<]+)\s+\<([^\>]+)\>\"/; 3183 next unless $userid && $fullname && $email; 3184 3185 # instantiate an author object 3186 my $userobj = $CPAN::META->instance('CPAN::Author',$userid); 3187 $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email); 3188 return if $CPAN::Signal; 3189 } 3190} 3191 3192sub userid { 3193 my($self,$dist) = @_; 3194 $dist = $self->{'id'} unless defined $dist; 3195 my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|; 3196 $ret; 3197} 3198 3199#-> sub CPAN::Index::rd_modpacks ; 3200sub rd_modpacks { 3201 my($self, $index_target) = @_; 3202 my @lines; 3203 return unless defined $index_target; 3204 $CPAN::Frontend->myprint("Going to read $index_target\n"); 3205 my $fh = CPAN::Tarzip->TIEHANDLE($index_target); 3206 local($/) = "\n"; 3207 while ($_ = $fh->READLINE) { 3208 s/\012/\n/g; 3209 my @ls = map {"$_\n"} split /\n/, $_; 3210 unshift @ls, "\n" x length($1) if /^(\n+)/; 3211 push @lines, @ls; 3212 } 3213 # read header 3214 my($line_count,$last_updated); 3215 while (@lines) { 3216 my $shift = shift(@lines); 3217 last if $shift =~ /^\s*$/; 3218 $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1; 3219 $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1; 3220 } 3221 if (not defined $line_count) { 3222 3223 warn qq{Warning: Your $index_target does not contain a Line-Count header. 3224Please check the validity of the index file by comparing it to more 3225than one CPAN mirror. I'll continue but problems seem likely to 3226happen.\a 3227}; 3228 3229 sleep 5; 3230 } elsif ($line_count != scalar @lines) { 3231 3232 warn sprintf qq{Warning: Your %s 3233contains a Line-Count header of %d but I see %d lines there. Please 3234check the validity of the index file by comparing it to more than one 3235CPAN mirror. I'll continue but problems seem likely to happen.\a\n}, 3236$index_target, $line_count, scalar(@lines); 3237 3238 } 3239 if (not defined $last_updated) { 3240 3241 warn qq{Warning: Your $index_target does not contain a Last-Updated header. 3242Please check the validity of the index file by comparing it to more 3243than one CPAN mirror. I'll continue but problems seem likely to 3244happen.\a 3245}; 3246 3247 sleep 5; 3248 } else { 3249 3250 $CPAN::Frontend 3251 ->myprint(sprintf qq{ Database was generated on %s\n}, 3252 $last_updated); 3253 $DATE_OF_02 = $last_updated; 3254 3255 if ($CPAN::META->has_inst(HTTP::Date)) { 3256 require HTTP::Date; 3257 my($age) = (time - HTTP::Date::str2time($last_updated))/3600/24; 3258 if ($age > 30) { 3259 3260 $CPAN::Frontend 3261 ->mywarn(sprintf 3262 qq{Warning: This index file is %d days old. 3263 Please check the host you chose as your CPAN mirror for staleness. 3264 I'll continue but problems seem likely to happen.\a\n}, 3265 $age); 3266 3267 } 3268 } else { 3269 $CPAN::Frontend->myprint(" HTTP::Date not available\n"); 3270 } 3271 } 3272 3273 3274 # A necessity since we have metadata_cache: delete what isn't 3275 # there anymore 3276 my $secondtime = $CPAN::META->exists("CPAN::Module","CPAN"); 3277 CPAN->debug("secondtime[$secondtime]") if $CPAN::DEBUG; 3278 my(%exists); 3279 foreach (@lines) { 3280 chomp; 3281 # before 1.56 we split into 3 and discarded the rest. From 3282 # 1.57 we assign remaining text to $comment thus allowing to 3283 # influence isa_perl 3284 my($mod,$version,$dist,$comment) = split " ", $_, 4; 3285 my($bundle,$id,$userid); 3286 3287 if ($mod eq 'CPAN' && 3288 ! ( 3289 CPAN::Queue->exists('Bundle::CPAN') || 3290 CPAN::Queue->exists('CPAN') 3291 ) 3292 ) { 3293 local($^W)= 0; 3294 if ($version > $CPAN::VERSION){ 3295 $CPAN::Frontend->myprint(qq{ 3296 There's a new CPAN.pm version (v$version) available! 3297 [Current version is v$CPAN::VERSION] 3298 You might want to try 3299 install Bundle::CPAN 3300 reload cpan 3301 without quitting the current session. It should be a seamless upgrade 3302 while we are running... 3303}); #}); 3304 sleep 2; 3305 $CPAN::Frontend->myprint(qq{\n}); 3306 } 3307 last if $CPAN::Signal; 3308 } elsif ($mod =~ /^Bundle::(.*)/) { 3309 $bundle = $1; 3310 } 3311 3312 if ($bundle){ 3313 $id = $CPAN::META->instance('CPAN::Bundle',$mod); 3314 # Let's make it a module too, because bundles have so much 3315 # in common with modules. 3316 3317 # Changed in 1.57_63: seems like memory bloat now without 3318 # any value, so commented out 3319 3320 # $CPAN::META->instance('CPAN::Module',$mod); 3321 3322 } else { 3323 3324 # instantiate a module object 3325 $id = $CPAN::META->instance('CPAN::Module',$mod); 3326 3327 } 3328 3329 if ($id->cpan_file ne $dist){ # update only if file is 3330 # different. CPAN prohibits same 3331 # name with different version 3332 $userid = $id->userid || $self->userid($dist); 3333 $id->set( 3334 'CPAN_USERID' => $userid, 3335 'CPAN_VERSION' => $version, 3336 'CPAN_FILE' => $dist, 3337 ); 3338 } 3339 3340 # instantiate a distribution object 3341 if ($CPAN::META->exists('CPAN::Distribution',$dist)) { 3342 # we do not need CONTAINSMODS unless we do something with 3343 # this dist, so we better produce it on demand. 3344 3345 ## my $obj = $CPAN::META->instance( 3346 ## 'CPAN::Distribution' => $dist 3347 ## ); 3348 ## $obj->{CONTAINSMODS}{$mod} = undef; # experimental 3349 } else { 3350 $CPAN::META->instance( 3351 'CPAN::Distribution' => $dist 3352 )->set( 3353 'CPAN_USERID' => $userid, 3354 'CPAN_COMMENT' => $comment, 3355 ); 3356 } 3357 if ($secondtime) { 3358 for my $name ($mod,$dist) { 3359 CPAN->debug("exists name[$name]") if $CPAN::DEBUG; 3360 $exists{$name} = undef; 3361 } 3362 } 3363 return if $CPAN::Signal; 3364 } 3365 undef $fh; 3366 if ($secondtime) { 3367 for my $class (qw(CPAN::Module CPAN::Bundle CPAN::Distribution)) { 3368 for my $o ($CPAN::META->all_objects($class)) { 3369 next if exists $exists{$o->{ID}}; 3370 $CPAN::META->delete($class,$o->{ID}); 3371 CPAN->debug("deleting ID[$o->{ID}] in class[$class]") 3372 if $CPAN::DEBUG; 3373 } 3374 } 3375 } 3376} 3377 3378#-> sub CPAN::Index::rd_modlist ; 3379sub rd_modlist { 3380 my($cl,$index_target) = @_; 3381 return unless defined $index_target; 3382 $CPAN::Frontend->myprint("Going to read $index_target\n"); 3383 my $fh = CPAN::Tarzip->TIEHANDLE($index_target); 3384 my @eval; 3385 local($/) = "\n"; 3386 while ($_ = $fh->READLINE) { 3387 s/\012/\n/g; 3388 my @ls = map {"$_\n"} split /\n/, $_; 3389 unshift @ls, "\n" x length($1) if /^(\n+)/; 3390 push @eval, @ls; 3391 } 3392 while (@eval) { 3393 my $shift = shift(@eval); 3394 if ($shift =~ /^Date:\s+(.*)/){ 3395 return if $DATE_OF_03 eq $1; 3396 ($DATE_OF_03) = $1; 3397 } 3398 last if $shift =~ /^\s*$/; 3399 } 3400 undef $fh; 3401 push @eval, q{CPAN::Modulelist->data;}; 3402 local($^W) = 0; 3403 my($comp) = Safe->new("CPAN::Safe1"); 3404 my($eval) = join("", @eval); 3405 my $ret = $comp->reval($eval); 3406 Carp::confess($@) if $@; 3407 return if $CPAN::Signal; 3408 for (keys %$ret) { 3409 my $obj = $CPAN::META->instance("CPAN::Module",$_); 3410 delete $ret->{$_}{modid}; # not needed here, maybe elsewhere 3411 $obj->set(%{$ret->{$_}}); 3412 return if $CPAN::Signal; 3413 } 3414} 3415 3416#-> sub CPAN::Index::write_metadata_cache ; 3417sub write_metadata_cache { 3418 my($self) = @_; 3419 return unless $CPAN::Config->{'cache_metadata'}; 3420 return unless $CPAN::META->has_usable("Storable"); 3421 my $cache; 3422 foreach my $k (qw(CPAN::Bundle CPAN::Author CPAN::Module 3423 CPAN::Distribution)) { 3424 $cache->{$k} = $CPAN::META->{readonly}{$k}; # unsafe meta access, ok 3425 } 3426 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); 3427 $cache->{last_time} = $LAST_TIME; 3428 $cache->{DATE_OF_02} = $DATE_OF_02; 3429 $cache->{PROTOCOL} = PROTOCOL; 3430 $CPAN::Frontend->myprint("Going to write $metadata_file\n"); 3431 eval { Storable::nstore($cache, $metadata_file) }; 3432 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? 3433} 3434 3435#-> sub CPAN::Index::read_metadata_cache ; 3436sub read_metadata_cache { 3437 my($self) = @_; 3438 return unless $CPAN::Config->{'cache_metadata'}; 3439 return unless $CPAN::META->has_usable("Storable"); 3440 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); 3441 return unless -r $metadata_file and -f $metadata_file; 3442 $CPAN::Frontend->myprint("Going to read $metadata_file\n"); 3443 my $cache; 3444 eval { $cache = Storable::retrieve($metadata_file) }; 3445 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? 3446 if (!$cache || ref $cache ne 'HASH'){ 3447 $LAST_TIME = 0; 3448 return; 3449 } 3450 if (exists $cache->{PROTOCOL}) { 3451 if (PROTOCOL > $cache->{PROTOCOL}) { 3452 $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ". 3453 "with protocol v%s, requiring v%s\n", 3454 $cache->{PROTOCOL}, 3455 PROTOCOL) 3456 ); 3457 return; 3458 } 3459 } else { 3460 $CPAN::Frontend->mywarn("Ignoring Metadata cache written ". 3461 "with protocol v1.0\n"); 3462 return; 3463 } 3464 my $clcnt = 0; 3465 my $idcnt = 0; 3466 while(my($class,$v) = each %$cache) { 3467 next unless $class =~ /^CPAN::/; 3468 $CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok 3469 while (my($id,$ro) = each %$v) { 3470 $CPAN::META->{readwrite}{$class}{$id} ||= 3471 $class->new(ID=>$id, RO=>$ro); 3472 $idcnt++; 3473 } 3474 $clcnt++; 3475 } 3476 unless ($clcnt) { # sanity check 3477 $CPAN::Frontend->myprint("Warning: Found no data in $metadata_file\n"); 3478 return; 3479 } 3480 if ($idcnt < 1000) { 3481 $CPAN::Frontend->myprint("Warning: Found only $idcnt objects ". 3482 "in $metadata_file\n"); 3483 return; 3484 } 3485 $CPAN::META->{PROTOCOL} ||= 3486 $cache->{PROTOCOL}; # reading does not up or downgrade, but it 3487 # does initialize to some protocol 3488 $LAST_TIME = $cache->{last_time}; 3489 $DATE_OF_02 = $cache->{DATE_OF_02}; 3490 $CPAN::Frontend->myprint(" Database was generated on $DATE_OF_02\n") 3491 if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02 3492 return; 3493} 3494 3495package CPAN::InfoObj; 3496 3497# Accessors 3498sub cpan_userid { 3499 my $self = shift; 3500 $self->{RO}{CPAN_USERID} 3501} 3502 3503sub id { shift->{ID}; } 3504 3505#-> sub CPAN::InfoObj::new ; 3506sub new { 3507 my $this = bless {}, shift; 3508 %$this = @_; 3509 $this 3510} 3511 3512# The set method may only be used by code that reads index data or 3513# otherwise "objective" data from the outside world. All session 3514# related material may do anything else with instance variables but 3515# must not touch the hash under the RO attribute. The reason is that 3516# the RO hash gets written to Metadata file and is thus persistent. 3517 3518#-> sub CPAN::InfoObj::set ; 3519sub set { 3520 my($self,%att) = @_; 3521 my $class = ref $self; 3522 3523 # This must be ||=, not ||, because only if we write an empty 3524 # reference, only then the set method will write into the readonly 3525 # area. But for Distributions that spring into existence, maybe 3526 # because of a typo, we do not like it that they are written into 3527 # the readonly area and made permanent (at least for a while) and 3528 # that is why we do not "allow" other places to call ->set. 3529 unless ($self->id) { 3530 CPAN->debug("Bug? Empty ID, rejecting"); 3531 return; 3532 } 3533 my $ro = $self->{RO} = 3534 $CPAN::META->{readonly}{$class}{$self->id} ||= {}; 3535 3536 while (my($k,$v) = each %att) { 3537 $ro->{$k} = $v; 3538 } 3539} 3540 3541#-> sub CPAN::InfoObj::as_glimpse ; 3542sub as_glimpse { 3543 my($self) = @_; 3544 my(@m); 3545 my $class = ref($self); 3546 $class =~ s/^CPAN:://; 3547 push @m, sprintf "%-15s %s\n", $class, $self->{ID}; 3548 join "", @m; 3549} 3550 3551#-> sub CPAN::InfoObj::as_string ; 3552sub as_string { 3553 my($self) = @_; 3554 my(@m); 3555 my $class = ref($self); 3556 $class =~ s/^CPAN:://; 3557 push @m, $class, " id = $self->{ID}\n"; 3558 for (sort keys %{$self->{RO}}) { 3559 # next if m/^(ID|RO)$/; 3560 my $extra = ""; 3561 if ($_ eq "CPAN_USERID") { 3562 $extra .= " (".$self->author; 3563 my $email; # old perls! 3564 if ($email = $CPAN::META->instance("CPAN::Author", 3565 $self->cpan_userid 3566 )->email) { 3567 $extra .= " <$email>"; 3568 } else { 3569 $extra .= " <no email>"; 3570 } 3571 $extra .= ")"; 3572 } elsif ($_ eq "FULLNAME") { # potential UTF-8 conversion 3573 push @m, sprintf " %-12s %s\n", $_, $self->fullname; 3574 next; 3575 } 3576 next unless defined $self->{RO}{$_}; 3577 push @m, sprintf " %-12s %s%s\n", $_, $self->{RO}{$_}, $extra; 3578 } 3579 for (sort keys %$self) { 3580 next if m/^(ID|RO)$/; 3581 if (ref($self->{$_}) eq "ARRAY") { 3582 push @m, sprintf " %-12s %s\n", $_, "@{$self->{$_}}"; 3583 } elsif (ref($self->{$_}) eq "HASH") { 3584 push @m, sprintf( 3585 " %-12s %s\n", 3586 $_, 3587 join(" ",keys %{$self->{$_}}), 3588 ); 3589 } else { 3590 push @m, sprintf " %-12s %s\n", $_, $self->{$_}; 3591 } 3592 } 3593 join "", @m, "\n"; 3594} 3595 3596#-> sub CPAN::InfoObj::author ; 3597sub author { 3598 my($self) = @_; 3599 $CPAN::META->instance("CPAN::Author",$self->cpan_userid)->fullname; 3600} 3601 3602#-> sub CPAN::InfoObj::dump ; 3603sub dump { 3604 my($self) = @_; 3605 require Data::Dumper; 3606 print Data::Dumper::Dumper($self); 3607} 3608 3609package CPAN::Author; 3610 3611#-> sub CPAN::Author::id 3612sub id { 3613 my $self = shift; 3614 my $id = $self->{ID}; 3615 $CPAN::Frontend->mydie("Illegal author id[$id]") unless $id =~ /^[A-Z]/; 3616 $id; 3617} 3618 3619#-> sub CPAN::Author::as_glimpse ; 3620sub as_glimpse { 3621 my($self) = @_; 3622 my(@m); 3623 my $class = ref($self); 3624 $class =~ s/^CPAN:://; 3625 push @m, sprintf(qq{%-15s %s ("%s" <%s>)\n}, 3626 $class, 3627 $self->{ID}, 3628 $self->fullname, 3629 $self->email); 3630 join "", @m; 3631} 3632 3633#-> sub CPAN::Author::fullname ; 3634sub fullname { 3635 shift->{RO}{FULLNAME}; 3636} 3637*name = \&fullname; 3638 3639#-> sub CPAN::Author::email ; 3640sub email { shift->{RO}{EMAIL}; } 3641 3642#-> sub CPAN::Author::ls ; 3643sub ls { 3644 my $self = shift; 3645 my $id = $self->id; 3646 3647 # adapted from CPAN::Distribution::verifyMD5 ; 3648 my(@csf); # chksumfile 3649 @csf = $self->id =~ /(.)(.)(.*)/; 3650 $csf[1] = join "", @csf[0,1]; 3651 $csf[2] = join "", @csf[1,2]; 3652 my(@dl); 3653 @dl = $self->dir_listing([$csf[0],"CHECKSUMS"], 0); 3654 unless (grep {$_->[2] eq $csf[1]} @dl) { 3655 $CPAN::Frontend->myprint("No files in the directory of $id\n"); 3656 return; 3657 } 3658 @dl = $self->dir_listing([@csf[0,1],"CHECKSUMS"], 0); 3659 unless (grep {$_->[2] eq $csf[2]} @dl) { 3660 $CPAN::Frontend->myprint("No files in the directory of $id\n"); 3661 return; 3662 } 3663 @dl = $self->dir_listing([@csf,"CHECKSUMS"], 1); 3664 $CPAN::Frontend->myprint(join "", map { 3665 sprintf("%8d %10s %s/%s\n", $_->[0], $_->[1], $id, $_->[2]) 3666 } sort { $a->[2] cmp $b->[2] } @dl); 3667} 3668 3669# returns an array of arrays, the latter contain (size,mtime,filename) 3670#-> sub CPAN::Author::dir_listing ; 3671sub dir_listing { 3672 my $self = shift; 3673 my $chksumfile = shift; 3674 my $recursive = shift; 3675 my $lc_want = 3676 File::Spec->catfile($CPAN::Config->{keep_source_where}, 3677 "authors", "id", @$chksumfile); 3678 local($") = "/"; 3679 # connect "force" argument with "index_expire". 3680 my $force = 0; 3681 if (my @stat = stat $lc_want) { 3682 $force = $stat[9] + $CPAN::Config->{index_expire}*86400 <= time; 3683 } 3684 my $lc_file = CPAN::FTP->localize("authors/id/@$chksumfile", 3685 $lc_want,$force); 3686 unless ($lc_file) { 3687 $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); 3688 $chksumfile->[-1] .= ".gz"; 3689 $lc_file = CPAN::FTP->localize("authors/id/@$chksumfile", 3690 "$lc_want.gz",1); 3691 if ($lc_file) { 3692 $lc_file =~ s{\.gz(?!\n)\Z}{}; #}; 3693 CPAN::Tarzip->gunzip("$lc_file.gz",$lc_file); 3694 } else { 3695 return; 3696 } 3697 } 3698 3699 # adapted from CPAN::Distribution::MD5_check_file ; 3700 my $fh = FileHandle->new; 3701 my($cksum); 3702 if (open $fh, $lc_file){ 3703 local($/); 3704 my $eval = <$fh>; 3705 $eval =~ s/\015?\012/\n/g; 3706 close $fh; 3707 my($comp) = Safe->new(); 3708 $cksum = $comp->reval($eval); 3709 if ($@) { 3710 rename $lc_file, "$lc_file.bad"; 3711 Carp::confess($@) if $@; 3712 } 3713 } else { 3714 Carp::carp "Could not open $lc_file for reading"; 3715 } 3716 my(@result,$f); 3717 for $f (sort keys %$cksum) { 3718 if (exists $cksum->{$f}{isdir}) { 3719 if ($recursive) { 3720 my(@dir) = @$chksumfile; 3721 pop @dir; 3722 push @dir, $f, "CHECKSUMS"; 3723 push @result, map { 3724 [$_->[0], $_->[1], "$f/$_->[2]"] 3725 } $self->dir_listing(\@dir,1); 3726 } else { 3727 push @result, [ 0, "-", $f ]; 3728 } 3729 } else { 3730 push @result, [ 3731 ($cksum->{$f}{"size"}||0), 3732 $cksum->{$f}{"mtime"}||"---", 3733 $f 3734 ]; 3735 } 3736 } 3737 @result; 3738} 3739 3740package CPAN::Distribution; 3741 3742# Accessors 3743sub cpan_comment { shift->{RO}{CPAN_COMMENT} } 3744 3745sub undelay { 3746 my $self = shift; 3747 delete $self->{later}; 3748} 3749 3750# CPAN::Distribution::normalize 3751sub normalize { 3752 my($self,$s) = @_; 3753 $s = $self->id unless defined $s; 3754 if ( 3755 $s =~ tr|/|| == 1 3756 or 3757 $s !~ m|[A-Z]/[A-Z-]{2}/[A-Z-]{2,}/| 3758 ) { 3759 return $s if $s =~ m:^N/A|^Contact Author: ; 3760 $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4| or 3761 $CPAN::Frontend->mywarn("Strange distribution name [$s]\n"); 3762 CPAN->debug("s[$s]") if $CPAN::DEBUG; 3763 } 3764 $s; 3765} 3766 3767#-> sub CPAN::Distribution::color_cmd_tmps ; 3768sub color_cmd_tmps { 3769 my($self) = shift; 3770 my($depth) = shift || 0; 3771 my($color) = shift || 0; 3772 my($ancestors) = shift || []; 3773 # a distribution needs to recurse into its prereq_pms 3774 3775 return if exists $self->{incommandcolor} 3776 && $self->{incommandcolor}==$color; 3777 if ($depth>=100){ 3778 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); 3779 } 3780 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 3781 my $prereq_pm = $self->prereq_pm; 3782 if (defined $prereq_pm) { 3783 for my $pre (keys %$prereq_pm) { 3784 my $premo = CPAN::Shell->expand("Module",$pre); 3785 $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 3786 } 3787 } 3788 if ($color==0) { 3789 delete $self->{sponsored_mods}; 3790 delete $self->{badtestcnt}; 3791 } 3792 $self->{incommandcolor} = $color; 3793} 3794 3795#-> sub CPAN::Distribution::as_string ; 3796sub as_string { 3797 my $self = shift; 3798 $self->containsmods; 3799 $self->SUPER::as_string(@_); 3800} 3801 3802#-> sub CPAN::Distribution::containsmods ; 3803sub containsmods { 3804 my $self = shift; 3805 return keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS}; 3806 my $dist_id = $self->{ID}; 3807 for my $mod ($CPAN::META->all_objects("CPAN::Module")) { 3808 my $mod_file = $mod->cpan_file or next; 3809 my $mod_id = $mod->{ID} or next; 3810 # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]"; 3811 # sleep 1; 3812 $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id; 3813 } 3814 keys %{$self->{CONTAINSMODS}}; 3815} 3816 3817#-> sub CPAN::Distribution::uptodate ; 3818sub uptodate { 3819 my($self) = @_; 3820 my $c; 3821 foreach $c ($self->containsmods) { 3822 my $obj = CPAN::Shell->expandany($c); 3823 return 0 unless $obj->uptodate; 3824 } 3825 return 1; 3826} 3827 3828#-> sub CPAN::Distribution::called_for ; 3829sub called_for { 3830 my($self,$id) = @_; 3831 $self->{CALLED_FOR} = $id if defined $id; 3832 return $self->{CALLED_FOR}; 3833} 3834 3835#-> sub CPAN::Distribution::safe_chdir ; 3836sub safe_chdir { 3837 my($self,$todir) = @_; 3838 # we die if we cannot chdir and we are debuggable 3839 Carp::confess("safe_chdir called without todir argument") 3840 unless defined $todir and length $todir; 3841 if (chdir $todir) { 3842 $self->debug(sprintf "changed directory to %s", CPAN::anycwd()) 3843 if $CPAN::DEBUG; 3844 } else { 3845 my $cwd = CPAN::anycwd(); 3846 $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }. 3847 qq{to todir[$todir]: $!}); 3848 } 3849} 3850 3851#-> sub CPAN::Distribution::get ; 3852sub get { 3853 my($self) = @_; 3854 EXCUSE: { 3855 my @e; 3856 exists $self->{'build_dir'} and push @e, 3857 "Is already unwrapped into directory $self->{'build_dir'}"; 3858 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 3859 } 3860 my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible 3861 3862 # 3863 # Get the file on local disk 3864 # 3865 3866 my($local_file); 3867 my($local_wanted) = 3868 File::Spec->catfile( 3869 $CPAN::Config->{keep_source_where}, 3870 "authors", 3871 "id", 3872 split(/\//,$self->id) 3873 ); 3874 3875 $self->debug("Doing localize") if $CPAN::DEBUG; 3876 unless ($local_file = 3877 CPAN::FTP->localize("authors/id/$self->{ID}", 3878 $local_wanted)) { 3879 my $note = ""; 3880 if ($CPAN::Index::DATE_OF_02) { 3881 $note = "Note: Current database in memory was generated ". 3882 "on $CPAN::Index::DATE_OF_02\n"; 3883 } 3884 $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note"); 3885 } 3886 $self->debug("local_file[$local_file]") if $CPAN::DEBUG; 3887 $self->{localfile} = $local_file; 3888 return if $CPAN::Signal; 3889 3890 # 3891 # Check integrity 3892 # 3893 if ($CPAN::META->has_inst("Digest::MD5")) { 3894 $self->debug("Digest::MD5 is installed, verifying"); 3895 $self->verifyMD5; 3896 } else { 3897 $self->debug("Digest::MD5 is NOT installed"); 3898 } 3899 return if $CPAN::Signal; 3900 3901 # 3902 # Create a clean room and go there 3903 # 3904 $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok 3905 my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok 3906 $self->safe_chdir($builddir); 3907 $self->debug("Removing tmp") if $CPAN::DEBUG; 3908 File::Path::rmtree("tmp"); 3909 mkdir "tmp", 0755 or Carp::croak "Couldn't mkdir tmp: $!"; 3910 if ($CPAN::Signal){ 3911 $self->safe_chdir($sub_wd); 3912 return; 3913 } 3914 $self->safe_chdir("tmp"); 3915 3916 # 3917 # Unpack the goods 3918 # 3919 if ($local_file =~ /(\.tar\.(gz|Z)|\.tgz)(?!\n)\Z/i){ 3920 $self->{was_uncompressed}++ unless CPAN::Tarzip->gtest($local_file); 3921 $self->untar_me($local_file); 3922 } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) { 3923 $self->unzip_me($local_file); 3924 } elsif ( $local_file =~ /\.pm\.(gz|Z)(?!\n)\Z/) { 3925 $self->{was_uncompressed}++ unless CPAN::Tarzip->gtest($local_file); 3926 $self->pm2dir_me($local_file); 3927 } else { 3928 $self->{archived} = "NO"; 3929 $self->safe_chdir($sub_wd); 3930 return; 3931 } 3932 3933 # we are still in the tmp directory! 3934 # Let's check if the package has its own directory. 3935 my $dh = DirHandle->new(File::Spec->curdir) 3936 or Carp::croak("Couldn't opendir .: $!"); 3937 my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC?? 3938 $dh->close; 3939 my ($distdir,$packagedir); 3940 if (@readdir == 1 && -d $readdir[0]) { 3941 $distdir = $readdir[0]; 3942 $packagedir = File::Spec->catdir($builddir,$distdir); 3943 $self->debug("packagedir[$packagedir]builddir[$builddir]distdir[$distdir]") 3944 if $CPAN::DEBUG; 3945 -d $packagedir and $CPAN::Frontend->myprint("Removing previously used ". 3946 "$packagedir\n"); 3947 File::Path::rmtree($packagedir); 3948 rename($distdir,$packagedir) or 3949 Carp::confess("Couldn't rename $distdir to $packagedir: $!"); 3950 $self->debug(sprintf("renamed distdir[%s] to packagedir[%s] -e[%s]-d[%s]", 3951 $distdir, 3952 $packagedir, 3953 -e $packagedir, 3954 -d $packagedir, 3955 )) if $CPAN::DEBUG; 3956 } else { 3957 my $userid = $self->cpan_userid; 3958 unless ($userid) { 3959 CPAN->debug("no userid? self[$self]"); 3960 $userid = "anon"; 3961 } 3962 my $pragmatic_dir = $userid . '000'; 3963 $pragmatic_dir =~ s/\W_//g; 3964 $pragmatic_dir++ while -d "../$pragmatic_dir"; 3965 $packagedir = File::Spec->catdir($builddir,$pragmatic_dir); 3966 $self->debug("packagedir[$packagedir]") if $CPAN::DEBUG; 3967 File::Path::mkpath($packagedir); 3968 my($f); 3969 for $f (@readdir) { # is already without "." and ".." 3970 my $to = File::Spec->catdir($packagedir,$f); 3971 rename($f,$to) or Carp::confess("Couldn't rename $f to $to: $!"); 3972 } 3973 } 3974 if ($CPAN::Signal){ 3975 $self->safe_chdir($sub_wd); 3976 return; 3977 } 3978 3979 $self->{'build_dir'} = $packagedir; 3980 $self->safe_chdir($builddir); 3981 File::Path::rmtree("tmp"); 3982 3983 my($mpl) = File::Spec->catfile($packagedir,"Makefile.PL"); 3984 my($mpl_exists) = -f $mpl; 3985 unless ($mpl_exists) { 3986 # NFS has been reported to have racing problems after the 3987 # renaming of a directory in some environments. 3988 # This trick helps. 3989 sleep 1; 3990 my $mpldh = DirHandle->new($packagedir) 3991 or Carp::croak("Couldn't opendir $packagedir: $!"); 3992 $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read; 3993 $mpldh->close; 3994 } 3995 unless ($mpl_exists) { 3996 $self->debug(sprintf("makefilepl[%s]anycwd[%s]", 3997 $mpl, 3998 CPAN::anycwd(), 3999 )) if $CPAN::DEBUG; 4000 my($configure) = File::Spec->catfile($packagedir,"Configure"); 4001 if (-f $configure) { 4002 # do we have anything to do? 4003 $self->{'configure'} = $configure; 4004 } elsif (-f File::Spec->catfile($packagedir,"Makefile")) { 4005 $CPAN::Frontend->myprint(qq{ 4006Package comes with a Makefile and without a Makefile.PL. 4007We\'ll try to build it with that Makefile then. 4008}); 4009 $self->{writemakefile} = "YES"; 4010 sleep 2; 4011 } else { 4012 my $cf = $self->called_for || "unknown"; 4013 if ($cf =~ m|/|) { 4014 $cf =~ s|.*/||; 4015 $cf =~ s|\W.*||; 4016 } 4017 $cf =~ s|[/\\:]||g; # risk of filesystem damage 4018 $cf = "unknown" unless length($cf); 4019 $CPAN::Frontend->myprint(qq{Package seems to come without Makefile.PL. 4020 (The test -f "$mpl" returned false.) 4021 Writing one on our own (setting NAME to $cf)\a\n}); 4022 $self->{had_no_makefile_pl}++; 4023 sleep 3; 4024 4025 # Writing our own Makefile.PL 4026 4027 my $fh = FileHandle->new; 4028 $fh->open(">$mpl") 4029 or Carp::croak("Could not open >$mpl: $!"); 4030 $fh->print( 4031qq{# This Makefile.PL has been autogenerated by the module CPAN.pm 4032# because there was no Makefile.PL supplied. 4033# Autogenerated on: }.scalar localtime().qq{ 4034 4035use ExtUtils::MakeMaker; 4036WriteMakefile(NAME => q[$cf]); 4037 4038}); 4039 $fh->close; 4040 } 4041 } 4042 4043 return $self; 4044} 4045 4046# CPAN::Distribution::untar_me ; 4047sub untar_me { 4048 my($self,$local_file) = @_; 4049 $self->{archived} = "tar"; 4050 if (CPAN::Tarzip->untar($local_file)) { 4051 $self->{unwrapped} = "YES"; 4052 } else { 4053 $self->{unwrapped} = "NO"; 4054 } 4055} 4056 4057# CPAN::Distribution::unzip_me ; 4058sub unzip_me { 4059 my($self,$local_file) = @_; 4060 $self->{archived} = "zip"; 4061 if (CPAN::Tarzip->unzip($local_file)) { 4062 $self->{unwrapped} = "YES"; 4063 } else { 4064 $self->{unwrapped} = "NO"; 4065 } 4066 return; 4067} 4068 4069sub pm2dir_me { 4070 my($self,$local_file) = @_; 4071 $self->{archived} = "pm"; 4072 my $to = File::Basename::basename($local_file); 4073 $to =~ s/\.(gz|Z)(?!\n)\Z//; 4074 if (CPAN::Tarzip->gunzip($local_file,$to)) { 4075 $self->{unwrapped} = "YES"; 4076 } else { 4077 $self->{unwrapped} = "NO"; 4078 } 4079} 4080 4081#-> sub CPAN::Distribution::new ; 4082sub new { 4083 my($class,%att) = @_; 4084 4085 # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); 4086 4087 my $this = { %att }; 4088 return bless $this, $class; 4089} 4090 4091#-> sub CPAN::Distribution::look ; 4092sub look { 4093 my($self) = @_; 4094 4095 if ($^O eq 'MacOS') { 4096 $self->Mac::BuildTools::look; 4097 return; 4098 } 4099 4100 if ( $CPAN::Config->{'shell'} ) { 4101 $CPAN::Frontend->myprint(qq{ 4102Trying to open a subshell in the build directory... 4103}); 4104 } else { 4105 $CPAN::Frontend->myprint(qq{ 4106Your configuration does not define a value for subshells. 4107Please define it with "o conf shell <your shell>" 4108}); 4109 return; 4110 } 4111 my $dist = $self->id; 4112 my $dir; 4113 unless ($dir = $self->dir) { 4114 $self->get; 4115 } 4116 unless ($dir ||= $self->dir) { 4117 $CPAN::Frontend->mywarn(qq{ 4118Could not determine which directory to use for looking at $dist. 4119}); 4120 return; 4121 } 4122 my $pwd = CPAN::anycwd(); 4123 $self->safe_chdir($dir); 4124 $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); 4125 unless (system($CPAN::Config->{'shell'}) == 0) { 4126 my $code = $? >> 8; 4127 $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n"); 4128 } 4129 $self->safe_chdir($pwd); 4130} 4131 4132# CPAN::Distribution::cvs_import ; 4133sub cvs_import { 4134 my($self) = @_; 4135 $self->get; 4136 my $dir = $self->dir; 4137 4138 my $package = $self->called_for; 4139 my $module = $CPAN::META->instance('CPAN::Module', $package); 4140 my $version = $module->cpan_version; 4141 4142 my $userid = $self->cpan_userid; 4143 4144 my $cvs_dir = (split /\//, $dir)[-1]; 4145 $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//; 4146 my $cvs_root = 4147 $CPAN::Config->{cvsroot} || $ENV{CVSROOT}; 4148 my $cvs_site_perl = 4149 $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL}; 4150 if ($cvs_site_perl) { 4151 $cvs_dir = "$cvs_site_perl/$cvs_dir"; 4152 } 4153 my $cvs_log = qq{"imported $package $version sources"}; 4154 $version =~ s/\./_/g; 4155 my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log, 4156 "$cvs_dir", $userid, "v$version"); 4157 4158 my $pwd = CPAN::anycwd(); 4159 chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!}); 4160 4161 $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); 4162 4163 $CPAN::Frontend->myprint(qq{@cmd\n}); 4164 system(@cmd) == 0 or 4165 $CPAN::Frontend->mydie("cvs import failed"); 4166 chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!}); 4167} 4168 4169#-> sub CPAN::Distribution::readme ; 4170sub readme { 4171 my($self) = @_; 4172 my($dist) = $self->id; 4173 my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/; 4174 $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG; 4175 my($local_file); 4176 my($local_wanted) = 4177 File::Spec->catfile( 4178 $CPAN::Config->{keep_source_where}, 4179 "authors", 4180 "id", 4181 split(/\//,"$sans.readme"), 4182 ); 4183 $self->debug("Doing localize") if $CPAN::DEBUG; 4184 $local_file = CPAN::FTP->localize("authors/id/$sans.readme", 4185 $local_wanted) 4186 or $CPAN::Frontend->mydie(qq{No $sans.readme found});; 4187 4188 if ($^O eq 'MacOS') { 4189 Mac::BuildTools::launch_file($local_file); 4190 return; 4191 } 4192 4193 my $fh_pager = FileHandle->new; 4194 local($SIG{PIPE}) = "IGNORE"; 4195 $fh_pager->open("|$CPAN::Config->{'pager'}") 4196 or die "Could not open pager $CPAN::Config->{'pager'}: $!"; 4197 my $fh_readme = FileHandle->new; 4198 $fh_readme->open($local_file) 4199 or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!}); 4200 $CPAN::Frontend->myprint(qq{ 4201Displaying file 4202 $local_file 4203with pager "$CPAN::Config->{'pager'}" 4204}); 4205 sleep 2; 4206 $fh_pager->print(<$fh_readme>); 4207} 4208 4209#-> sub CPAN::Distribution::verifyMD5 ; 4210sub verifyMD5 { 4211 my($self) = @_; 4212 EXCUSE: { 4213 my @e; 4214 $self->{MD5_STATUS} ||= ""; 4215 $self->{MD5_STATUS} eq "OK" and push @e, "MD5 Checksum was ok"; 4216 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 4217 } 4218 my($lc_want,$lc_file,@local,$basename); 4219 @local = split(/\//,$self->id); 4220 pop @local; 4221 push @local, "CHECKSUMS"; 4222 $lc_want = 4223 File::Spec->catfile($CPAN::Config->{keep_source_where}, 4224 "authors", "id", @local); 4225 local($") = "/"; 4226 if ( 4227 -s $lc_want 4228 && 4229 $self->MD5_check_file($lc_want) 4230 ) { 4231 return $self->{MD5_STATUS} = "OK"; 4232 } 4233 $lc_file = CPAN::FTP->localize("authors/id/@local", 4234 $lc_want,1); 4235 unless ($lc_file) { 4236 $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); 4237 $local[-1] .= ".gz"; 4238 $lc_file = CPAN::FTP->localize("authors/id/@local", 4239 "$lc_want.gz",1); 4240 if ($lc_file) { 4241 $lc_file =~ s/\.gz(?!\n)\Z//; 4242 CPAN::Tarzip->gunzip("$lc_file.gz",$lc_file); 4243 } else { 4244 return; 4245 } 4246 } 4247 $self->MD5_check_file($lc_file); 4248} 4249 4250#-> sub CPAN::Distribution::MD5_check_file ; 4251sub MD5_check_file { 4252 my($self,$chk_file) = @_; 4253 my($cksum,$file,$basename); 4254 $file = $self->{localfile}; 4255 $basename = File::Basename::basename($file); 4256 my $fh = FileHandle->new; 4257 if (open $fh, $chk_file){ 4258 local($/); 4259 my $eval = <$fh>; 4260 $eval =~ s/\015?\012/\n/g; 4261 close $fh; 4262 my($comp) = Safe->new(); 4263 $cksum = $comp->reval($eval); 4264 if ($@) { 4265 rename $chk_file, "$chk_file.bad"; 4266 Carp::confess($@) if $@; 4267 } 4268 } else { 4269 Carp::carp "Could not open $chk_file for reading"; 4270 } 4271 4272 if (exists $cksum->{$basename}{md5}) { 4273 $self->debug("Found checksum for $basename:" . 4274 "$cksum->{$basename}{md5}\n") if $CPAN::DEBUG; 4275 4276 open($fh, $file); 4277 binmode $fh; 4278 my $eq = $self->eq_MD5($fh,$cksum->{$basename}{'md5'}); 4279 $fh->close; 4280 $fh = CPAN::Tarzip->TIEHANDLE($file); 4281 4282 unless ($eq) { 4283 # had to inline it, when I tied it, the tiedness got lost on 4284 # the call to eq_MD5. (Jan 1998) 4285 my $md5 = Digest::MD5->new; 4286 my($data,$ref); 4287 $ref = \$data; 4288 while ($fh->READ($ref, 4096) > 0){ 4289 $md5->add($data); 4290 } 4291 my $hexdigest = $md5->hexdigest; 4292 $eq += $hexdigest eq $cksum->{$basename}{'md5-ungz'}; 4293 } 4294 4295 if ($eq) { 4296 $CPAN::Frontend->myprint("Checksum for $file ok\n"); 4297 return $self->{MD5_STATUS} = "OK"; 4298 } else { 4299 $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }. 4300 qq{distribution file. }. 4301 qq{Please investigate.\n\n}. 4302 $self->as_string, 4303 $CPAN::META->instance( 4304 'CPAN::Author', 4305 $self->cpan_userid 4306 )->as_string); 4307 4308 my $wrap = qq{I\'d recommend removing $file. Its MD5 4309checksum is incorrect. Maybe you have configured your 'urllist' with 4310a bad URL. Please check this array with 'o conf urllist', and 4311retry.}; 4312 4313 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); 4314 4315 # former versions just returned here but this seems a 4316 # serious threat that deserves a die 4317 4318 # $CPAN::Frontend->myprint("\n\n"); 4319 # sleep 3; 4320 # return; 4321 } 4322 # close $fh if fileno($fh); 4323 } else { 4324 $self->{MD5_STATUS} ||= ""; 4325 if ($self->{MD5_STATUS} eq "NIL") { 4326 $CPAN::Frontend->mywarn(qq{ 4327Warning: No md5 checksum for $basename in $chk_file. 4328 4329The cause for this may be that the file is very new and the checksum 4330has not yet been calculated, but it may also be that something is 4331going awry right now. 4332}); 4333 my $answer = ExtUtils::MakeMaker::prompt("Proceed?", "yes"); 4334 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted."); 4335 } 4336 $self->{MD5_STATUS} = "NIL"; 4337 return; 4338 } 4339} 4340 4341#-> sub CPAN::Distribution::eq_MD5 ; 4342sub eq_MD5 { 4343 my($self,$fh,$expectMD5) = @_; 4344 my $md5 = Digest::MD5->new; 4345 my($data); 4346 while (read($fh, $data, 4096)){ 4347 $md5->add($data); 4348 } 4349 # $md5->addfile($fh); 4350 my $hexdigest = $md5->hexdigest; 4351 # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]"; 4352 $hexdigest eq $expectMD5; 4353} 4354 4355#-> sub CPAN::Distribution::force ; 4356 4357# Both modules and distributions know if "force" is in effect by 4358# autoinspection, not by inspecting a global variable. One of the 4359# reason why this was chosen to work that way was the treatment of 4360# dependencies. They should not autpomatically inherit the force 4361# status. But this has the downside that ^C and die() will return to 4362# the prompt but will not be able to reset the force_update 4363# attributes. We try to correct for it currently in the read_metadata 4364# routine, and immediately before we check for a Signal. I hope this 4365# works out in one of v1.57_53ff 4366 4367sub force { 4368 my($self, $method) = @_; 4369 for my $att (qw( 4370 MD5_STATUS archived build_dir localfile make install unwrapped 4371 writemakefile 4372 )) { 4373 delete $self->{$att}; 4374 } 4375 if ($method && $method eq "install") { 4376 $self->{"force_update"}++; # name should probably have been force_install 4377 } 4378} 4379 4380#-> sub CPAN::Distribution::unforce ; 4381sub unforce { 4382 my($self) = @_; 4383 delete $self->{'force_update'}; 4384} 4385 4386#-> sub CPAN::Distribution::isa_perl ; 4387sub isa_perl { 4388 my($self) = @_; 4389 my $file = File::Basename::basename($self->id); 4390 if ($file =~ m{ ^ perl 4391 -? 4392 (5) 4393 ([._-]) 4394 ( 4395 \d{3}(_[0-4][0-9])? 4396 | 4397 \d*[24680]\.\d+ 4398 ) 4399 \.tar[._-]gz 4400 (?!\n)\Z 4401 }xs){ 4402 return "$1.$3"; 4403 } elsif ($self->cpan_comment 4404 && 4405 $self->cpan_comment =~ /isa_perl\(.+?\)/){ 4406 return $1; 4407 } 4408} 4409 4410#-> sub CPAN::Distribution::perl ; 4411sub perl { 4412 my($self) = @_; 4413 my($perl) = File::Spec->file_name_is_absolute($^X) ? $^X : ""; 4414 my $pwd = CPAN::anycwd(); 4415 my $candidate = File::Spec->catfile($pwd,$^X); 4416 $perl ||= $candidate if MM->maybe_command($candidate); 4417 unless ($perl) { 4418 my ($component,$perl_name); 4419 DIST_PERLNAME: foreach $perl_name ($^X, 'perl', 'perl5', "perl$]") { 4420 PATH_COMPONENT: foreach $component (File::Spec->path(), 4421 $Config::Config{'binexp'}) { 4422 next unless defined($component) && $component; 4423 my($abs) = File::Spec->catfile($component,$perl_name); 4424 if (MM->maybe_command($abs)) { 4425 $perl = $abs; 4426 last DIST_PERLNAME; 4427 } 4428 } 4429 } 4430 } 4431 $perl; 4432} 4433 4434#-> sub CPAN::Distribution::make ; 4435sub make { 4436 my($self) = @_; 4437 $CPAN::Frontend->myprint(sprintf "Running make for %s\n", $self->id); 4438 # Emergency brake if they said install Pippi and get newest perl 4439 if ($self->isa_perl) { 4440 if ( 4441 $self->called_for ne $self->id && 4442 ! $self->{force_update} 4443 ) { 4444 # if we die here, we break bundles 4445 $CPAN::Frontend->mywarn(sprintf qq{ 4446The most recent version "%s" of the module "%s" 4447comes with the current version of perl (%s). 4448I\'ll build that only if you ask for something like 4449 force install %s 4450or 4451 install %s 4452}, 4453 $CPAN::META->instance( 4454 'CPAN::Module', 4455 $self->called_for 4456 )->cpan_version, 4457 $self->called_for, 4458 $self->isa_perl, 4459 $self->called_for, 4460 $self->id); 4461 sleep 5; return; 4462 } 4463 } 4464 $self->get; 4465 EXCUSE: { 4466 my @e; 4467 $self->{archived} eq "NO" and push @e, 4468 "Is neither a tar nor a zip archive."; 4469 4470 $self->{unwrapped} eq "NO" and push @e, 4471 "had problems unarchiving. Please build manually"; 4472 4473 exists $self->{writemakefile} && 4474 $self->{writemakefile} =~ m/ ^ NO\s* ( .* ) /sx and push @e, 4475 $1 || "Had some problem writing Makefile"; 4476 4477 defined $self->{'make'} and push @e, 4478 "Has already been processed within this session"; 4479 4480 exists $self->{later} and length($self->{later}) and 4481 push @e, $self->{later}; 4482 4483 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 4484 } 4485 $CPAN::Frontend->myprint("\n CPAN.pm: Going to build ".$self->id."\n\n"); 4486 my $builddir = $self->dir; 4487 chdir $builddir or Carp::croak("Couldn't chdir $builddir: $!"); 4488 $self->debug("Changed directory to $builddir") if $CPAN::DEBUG; 4489 4490 if ($^O eq 'MacOS') { 4491 Mac::BuildTools::make($self); 4492 return; 4493 } 4494 4495 my $system; 4496 if ($self->{'configure'}) { 4497 $system = $self->{'configure'}; 4498 } else { 4499 my($perl) = $self->perl or die "Couldn\'t find executable perl\n"; 4500 my $switch = ""; 4501# This needs a handler that can be turned on or off: 4502# $switch = "-MExtUtils::MakeMaker ". 4503# "-Mops=:default,:filesys_read,:filesys_open,require,chdir" 4504# if $] > 5.00310; 4505 $system = "$perl $switch Makefile.PL $CPAN::Config->{makepl_arg}"; 4506 } 4507 unless (exists $self->{writemakefile}) { 4508 local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" }; 4509 my($ret,$pid); 4510 $@ = ""; 4511 if ($CPAN::Config->{inactivity_timeout}) { 4512 eval { 4513 alarm $CPAN::Config->{inactivity_timeout}; 4514 local $SIG{CHLD}; # = sub { wait }; 4515 if (defined($pid = fork)) { 4516 if ($pid) { #parent 4517 # wait; 4518 waitpid $pid, 0; 4519 } else { #child 4520 # note, this exec isn't necessary if 4521 # inactivity_timeout is 0. On the Mac I'd 4522 # suggest, we set it always to 0. 4523 exec $system; 4524 } 4525 } else { 4526 $CPAN::Frontend->myprint("Cannot fork: $!"); 4527 return; 4528 } 4529 }; 4530 alarm 0; 4531 if ($@){ 4532 kill 9, $pid; 4533 waitpid $pid, 0; 4534 $CPAN::Frontend->myprint($@); 4535 $self->{writemakefile} = "NO $@"; 4536 $@ = ""; 4537 return; 4538 } 4539 } else { 4540 $ret = system($system); 4541 if ($ret != 0) { 4542 $self->{writemakefile} = "NO Makefile.PL returned status $ret"; 4543 return; 4544 } 4545 } 4546 if (-f "Makefile") { 4547 $self->{writemakefile} = "YES"; 4548 delete $self->{make_clean}; # if cleaned before, enable next 4549 } else { 4550 $self->{writemakefile} = 4551 qq{NO Makefile.PL refused to write a Makefile.}; 4552 # It's probably worth it to record the reason, so let's retry 4553 # local $/; 4554 # my $fh = IO::File->new("$system |"); # STDERR? STDIN? 4555 # $self->{writemakefile} .= <$fh>; 4556 } 4557 } 4558 if ($CPAN::Signal){ 4559 delete $self->{force_update}; 4560 return; 4561 } 4562 if (my @prereq = $self->unsat_prereq){ 4563 return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner 4564 } 4565 $system = join " ", $CPAN::Config->{'make'}, $CPAN::Config->{make_arg}; 4566 if (system($system) == 0) { 4567 $CPAN::Frontend->myprint(" $system -- OK\n"); 4568 $self->{'make'} = "YES"; 4569 } else { 4570 $self->{writemakefile} ||= "YES"; 4571 $self->{'make'} = "NO"; 4572 $CPAN::Frontend->myprint(" $system -- NOT OK\n"); 4573 } 4574} 4575 4576sub follow_prereqs { 4577 my($self) = shift; 4578 my(@prereq) = @_; 4579 my $id = $self->id; 4580 $CPAN::Frontend->myprint("---- Unsatisfied dependencies detected ". 4581 "during [$id] -----\n"); 4582 4583 for my $p (@prereq) { 4584 $CPAN::Frontend->myprint(" $p\n"); 4585 } 4586 my $follow = 0; 4587 if ($CPAN::Config->{prerequisites_policy} eq "follow") { 4588 $follow = 1; 4589 } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") { 4590 require ExtUtils::MakeMaker; 4591 my $answer = ExtUtils::MakeMaker::prompt( 4592"Shall I follow them and prepend them to the queue 4593of modules we are processing right now?", "yes"); 4594 $follow = $answer =~ /^\s*y/i; 4595 } else { 4596 local($") = ", "; 4597 $CPAN::Frontend-> 4598 myprint(" Ignoring dependencies on modules @prereq\n"); 4599 } 4600 if ($follow) { 4601 # color them as dirty 4602 for my $p (@prereq) { 4603 # warn "calling color_cmd_tmps(0,1)"; 4604 CPAN::Shell->expandany($p)->color_cmd_tmps(0,1); 4605 } 4606 CPAN::Queue->jumpqueue(@prereq,$id); # queue them and requeue yourself 4607 $self->{later} = "Delayed until after prerequisites"; 4608 return 1; # signal success to the queuerunner 4609 } 4610} 4611 4612#-> sub CPAN::Distribution::unsat_prereq ; 4613sub unsat_prereq { 4614 my($self) = @_; 4615 my $prereq_pm = $self->prereq_pm or return; 4616 my(@need); 4617 NEED: while (my($need_module, $need_version) = each %$prereq_pm) { 4618 my $nmo = $CPAN::META->instance("CPAN::Module",$need_module); 4619 # we were too demanding: 4620 next if $nmo->uptodate; 4621 4622 # if they have not specified a version, we accept any installed one 4623 if (not defined $need_version or 4624 $need_version == 0 or 4625 $need_version eq "undef") { 4626 next if defined $nmo->inst_file; 4627 } 4628 4629 # We only want to install prereqs if either they're not installed 4630 # or if the installed version is too old. We cannot omit this 4631 # check, because if 'force' is in effect, nobody else will check. 4632 { 4633 local($^W) = 0; 4634 if ( 4635 defined $nmo->inst_file && 4636 ! CPAN::Version->vgt($need_version, $nmo->inst_version) 4637 ){ 4638 CPAN->debug(sprintf "id[%s]inst_file[%s]inst_version[%s]need_version[%s]", 4639 $nmo->id, 4640 $nmo->inst_file, 4641 $nmo->inst_version, 4642 CPAN::Version->readable($need_version) 4643 ); 4644 next NEED; 4645 } 4646 } 4647 4648 if ($self->{sponsored_mods}{$need_module}++){ 4649 # We have already sponsored it and for some reason it's still 4650 # not available. So we do nothing. Or what should we do? 4651 # if we push it again, we have a potential infinite loop 4652 next; 4653 } 4654 push @need, $need_module; 4655 } 4656 @need; 4657} 4658 4659#-> sub CPAN::Distribution::prereq_pm ; 4660sub prereq_pm { 4661 my($self) = @_; 4662 return $self->{prereq_pm} if 4663 exists $self->{prereq_pm_detected} && $self->{prereq_pm_detected}; 4664 return unless $self->{writemakefile}; # no need to have succeeded 4665 # but we must have run it 4666 my $build_dir = $self->{build_dir} or die "Panic: no build_dir?"; 4667 my $makefile = File::Spec->catfile($build_dir,"Makefile"); 4668 my(%p) = (); 4669 my $fh; 4670 if (-f $makefile 4671 and 4672 $fh = FileHandle->new("<$makefile\0")) { 4673 4674 local($/) = "\n"; 4675 4676 # A.Speer @p -> %p, where %p is $p{Module::Name}=Required_Version 4677 while (<$fh>) { 4678 last if /MakeMaker post_initialize section/; 4679 my($p) = m{^[\#] 4680 \s+PREREQ_PM\s+=>\s+(.+) 4681 }x; 4682 next unless $p; 4683 # warn "Found prereq expr[$p]"; 4684 4685 # Regexp modified by A.Speer to remember actual version of file 4686 # PREREQ_PM hash key wants, then add to 4687 while ( $p =~ m/(?:\s)([\w\:]+)=>q\[(.*?)\],?/g ){ 4688 # In case a prereq is mentioned twice, complain. 4689 if ( defined $p{$1} ) { 4690 warn "Warning: PREREQ_PM mentions $1 more than once, last mention wins"; 4691 } 4692 $p{$1} = $2; 4693 } 4694 last; 4695 } 4696 } 4697 $self->{prereq_pm_detected}++; 4698 return $self->{prereq_pm} = \%p; 4699} 4700 4701#-> sub CPAN::Distribution::test ; 4702sub test { 4703 my($self) = @_; 4704 $self->make; 4705 if ($CPAN::Signal){ 4706 delete $self->{force_update}; 4707 return; 4708 } 4709 $CPAN::Frontend->myprint("Running make test\n"); 4710 if (my @prereq = $self->unsat_prereq){ 4711 return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner 4712 } 4713 EXCUSE: { 4714 my @e; 4715 exists $self->{make} or exists $self->{later} or push @e, 4716 "Make had some problems, maybe interrupted? Won't test"; 4717 4718 exists $self->{'make'} and 4719 $self->{'make'} eq 'NO' and 4720 push @e, "Can't test without successful make"; 4721 4722 exists $self->{build_dir} or push @e, "Has no own directory"; 4723 $self->{badtestcnt} ||= 0; 4724 $self->{badtestcnt} > 0 and 4725 push @e, "Won't repeat unsuccessful test during this command"; 4726 4727 exists $self->{later} and length($self->{later}) and 4728 push @e, $self->{later}; 4729 4730 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 4731 } 4732 chdir $self->{'build_dir'} or 4733 Carp::croak("Couldn't chdir to $self->{'build_dir'}"); 4734 $self->debug("Changed directory to $self->{'build_dir'}") 4735 if $CPAN::DEBUG; 4736 4737 if ($^O eq 'MacOS') { 4738 Mac::BuildTools::make_test($self); 4739 return; 4740 } 4741 4742 local $ENV{PERL5LIB} = $ENV{PERL5LIB} || ""; 4743 $CPAN::META->set_perl5lib; 4744 my $system = join " ", $CPAN::Config->{'make'}, "test"; 4745 if (system($system) == 0) { 4746 $CPAN::Frontend->myprint(" $system -- OK\n"); 4747 $CPAN::META->is_tested($self->{'build_dir'}); 4748 $self->{make_test} = "YES"; 4749 } else { 4750 $self->{make_test} = "NO"; 4751 $self->{badtestcnt}++; 4752 $CPAN::Frontend->myprint(" $system -- NOT OK\n"); 4753 } 4754} 4755 4756#-> sub CPAN::Distribution::clean ; 4757sub clean { 4758 my($self) = @_; 4759 $CPAN::Frontend->myprint("Running make clean\n"); 4760 EXCUSE: { 4761 my @e; 4762 exists $self->{make_clean} and $self->{make_clean} eq "YES" and 4763 push @e, "make clean already called once"; 4764 exists $self->{build_dir} or push @e, "Has no own directory"; 4765 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 4766 } 4767 chdir $self->{'build_dir'} or 4768 Carp::croak("Couldn't chdir to $self->{'build_dir'}"); 4769 $self->debug("Changed directory to $self->{'build_dir'}") if $CPAN::DEBUG; 4770 4771 if ($^O eq 'MacOS') { 4772 Mac::BuildTools::make_clean($self); 4773 return; 4774 } 4775 4776 my $system = join " ", $CPAN::Config->{'make'}, "clean"; 4777 if (system($system) == 0) { 4778 $CPAN::Frontend->myprint(" $system -- OK\n"); 4779 4780 # $self->force; 4781 4782 # Jost Krieger pointed out that this "force" was wrong because 4783 # it has the effect that the next "install" on this distribution 4784 # will untar everything again. Instead we should bring the 4785 # object's state back to where it is after untarring. 4786 4787 delete $self->{force_update}; 4788 delete $self->{install}; 4789 delete $self->{writemakefile}; 4790 delete $self->{make}; 4791 delete $self->{make_test}; # no matter if yes or no, tests must be redone 4792 $self->{make_clean} = "YES"; 4793 4794 } else { 4795 # Hmmm, what to do if make clean failed? 4796 4797 $CPAN::Frontend->myprint(qq{ $system -- NOT OK 4798 4799make clean did not succeed, marking directory as unusable for further work. 4800}); 4801 $self->force("make"); # so that this directory won't be used again 4802 4803 } 4804} 4805 4806#-> sub CPAN::Distribution::install ; 4807sub install { 4808 my($self) = @_; 4809 $self->test; 4810 if ($CPAN::Signal){ 4811 delete $self->{force_update}; 4812 return; 4813 } 4814 $CPAN::Frontend->myprint("Running make install\n"); 4815 EXCUSE: { 4816 my @e; 4817 exists $self->{build_dir} or push @e, "Has no own directory"; 4818 4819 exists $self->{make} or exists $self->{later} or push @e, 4820 "Make had some problems, maybe interrupted? Won't install"; 4821 4822 exists $self->{'make'} and 4823 $self->{'make'} eq 'NO' and 4824 push @e, "make had returned bad status, install seems impossible"; 4825 4826 push @e, "make test had returned bad status, ". 4827 "won't install without force" 4828 if exists $self->{'make_test'} and 4829 $self->{'make_test'} eq 'NO' and 4830 ! $self->{'force_update'}; 4831 4832 exists $self->{'install'} and push @e, 4833 $self->{'install'} eq "YES" ? 4834 "Already done" : "Already tried without success"; 4835 4836 exists $self->{later} and length($self->{later}) and 4837 push @e, $self->{later}; 4838 4839 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 4840 } 4841 chdir $self->{'build_dir'} or 4842 Carp::croak("Couldn't chdir to $self->{'build_dir'}"); 4843 $self->debug("Changed directory to $self->{'build_dir'}") 4844 if $CPAN::DEBUG; 4845 4846 if ($^O eq 'MacOS') { 4847 Mac::BuildTools::make_install($self); 4848 return; 4849 } 4850 4851 my $system = join(" ", $CPAN::Config->{'make'}, 4852 "install", $CPAN::Config->{make_install_arg}); 4853 my($stderr) = $^O =~ /Win/i ? "" : " 2>&1 "; 4854 my($pipe) = FileHandle->new("$system $stderr |"); 4855 my($makeout) = ""; 4856 while (<$pipe>){ 4857 $CPAN::Frontend->myprint($_); 4858 $makeout .= $_; 4859 } 4860 $pipe->close; 4861 if ($?==0) { 4862 $CPAN::Frontend->myprint(" $system -- OK\n"); 4863 $CPAN::META->is_installed($self->{'build_dir'}); 4864 return $self->{'install'} = "YES"; 4865 } else { 4866 $self->{'install'} = "NO"; 4867 $CPAN::Frontend->myprint(" $system -- NOT OK\n"); 4868 if ($makeout =~ /permission/s && $> > 0) { 4869 $CPAN::Frontend->myprint(qq{ You may have to su }. 4870 qq{to root to install the package\n}); 4871 } 4872 } 4873 delete $self->{force_update}; 4874} 4875 4876#-> sub CPAN::Distribution::dir ; 4877sub dir { 4878 shift->{'build_dir'}; 4879} 4880 4881package CPAN::Bundle; 4882 4883sub look { 4884 my $self = shift; 4885 $CPAN::Frontend->myprint($self->as_string); 4886} 4887 4888sub undelay { 4889 my $self = shift; 4890 delete $self->{later}; 4891 for my $c ( $self->contains ) { 4892 my $obj = CPAN::Shell->expandany($c) or next; 4893 $obj->undelay; 4894 } 4895} 4896 4897#-> sub CPAN::Bundle::color_cmd_tmps ; 4898sub color_cmd_tmps { 4899 my($self) = shift; 4900 my($depth) = shift || 0; 4901 my($color) = shift || 0; 4902 my($ancestors) = shift || []; 4903 # a module needs to recurse to its cpan_file, a distribution needs 4904 # to recurse into its prereq_pms, a bundle needs to recurse into its modules 4905 4906 return if exists $self->{incommandcolor} 4907 && $self->{incommandcolor}==$color; 4908 if ($depth>=100){ 4909 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); 4910 } 4911 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 4912 4913 for my $c ( $self->contains ) { 4914 my $obj = CPAN::Shell->expandany($c) or next; 4915 CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG; 4916 $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 4917 } 4918 if ($color==0) { 4919 delete $self->{badtestcnt}; 4920 } 4921 $self->{incommandcolor} = $color; 4922} 4923 4924#-> sub CPAN::Bundle::as_string ; 4925sub as_string { 4926 my($self) = @_; 4927 $self->contains; 4928 # following line must be "=", not "||=" because we have a moving target 4929 $self->{INST_VERSION} = $self->inst_version; 4930 return $self->SUPER::as_string; 4931} 4932 4933#-> sub CPAN::Bundle::contains ; 4934sub contains { 4935 my($self) = @_; 4936 my($inst_file) = $self->inst_file || ""; 4937 my($id) = $self->id; 4938 $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG; 4939 unless ($inst_file) { 4940 # Try to get at it in the cpan directory 4941 $self->debug("no inst_file") if $CPAN::DEBUG; 4942 my $cpan_file; 4943 $CPAN::Frontend->mydie("I don't know a bundle with ID $id\n") unless 4944 $cpan_file = $self->cpan_file; 4945 if ($cpan_file eq "N/A") { 4946 $CPAN::Frontend->mydie("Bundle $id not found on disk and not on CPAN. 4947 Maybe stale symlink? Maybe removed during session? Giving up.\n"); 4948 } 4949 my $dist = $CPAN::META->instance('CPAN::Distribution', 4950 $self->cpan_file); 4951 $dist->get; 4952 $self->debug($dist->as_string) if $CPAN::DEBUG; 4953 my($todir) = $CPAN::Config->{'cpan_home'}; 4954 my(@me,$from,$to,$me); 4955 @me = split /::/, $self->id; 4956 $me[-1] .= ".pm"; 4957 $me = File::Spec->catfile(@me); 4958 $from = $self->find_bundle_file($dist->{'build_dir'},$me); 4959 $to = File::Spec->catfile($todir,$me); 4960 File::Path::mkpath(File::Basename::dirname($to)); 4961 File::Copy::copy($from, $to) 4962 or Carp::confess("Couldn't copy $from to $to: $!"); 4963 $inst_file = $to; 4964 } 4965 my @result; 4966 my $fh = FileHandle->new; 4967 local $/ = "\n"; 4968 open($fh,$inst_file) or die "Could not open '$inst_file': $!"; 4969 my $in_cont = 0; 4970 $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG; 4971 while (<$fh>) { 4972 $in_cont = m/^=(?!head1\s+CONTENTS)/ ? 0 : 4973 m/^=head1\s+CONTENTS/ ? 1 : $in_cont; 4974 next unless $in_cont; 4975 next if /^=/; 4976 s/\#.*//; 4977 next if /^\s+$/; 4978 chomp; 4979 push @result, (split " ", $_, 2)[0]; 4980 } 4981 close $fh; 4982 delete $self->{STATUS}; 4983 $self->{CONTAINS} = \@result; 4984 $self->debug("CONTAINS[@result]") if $CPAN::DEBUG; 4985 unless (@result) { 4986 $CPAN::Frontend->mywarn(qq{ 4987The bundle file "$inst_file" may be a broken 4988bundlefile. It seems not to contain any bundle definition. 4989Please check the file and if it is bogus, please delete it. 4990Sorry for the inconvenience. 4991}); 4992 } 4993 @result; 4994} 4995 4996#-> sub CPAN::Bundle::find_bundle_file 4997sub find_bundle_file { 4998 my($self,$where,$what) = @_; 4999 $self->debug("where[$where]what[$what]") if $CPAN::DEBUG; 5000### The following two lines let CPAN.pm become Bundle/CPAN.pm :-( 5001### my $bu = File::Spec->catfile($where,$what); 5002### return $bu if -f $bu; 5003 my $manifest = File::Spec->catfile($where,"MANIFEST"); 5004 unless (-f $manifest) { 5005 require ExtUtils::Manifest; 5006 my $cwd = CPAN::anycwd(); 5007 chdir $where or $CPAN::Frontend->mydie(qq{Could not chdir to "$where": $!}); 5008 ExtUtils::Manifest::mkmanifest(); 5009 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!}); 5010 } 5011 my $fh = FileHandle->new($manifest) 5012 or Carp::croak("Couldn't open $manifest: $!"); 5013 local($/) = "\n"; 5014 my $what2 = $what; 5015 if ($^O eq 'MacOS') { 5016 $what =~ s/^://; 5017 $what =~ tr|:|/|; 5018 $what2 =~ s/:Bundle://; 5019 $what2 =~ tr|:|/|; 5020 } else { 5021 $what2 =~ s|Bundle[/\\]||; 5022 } 5023 my $bu; 5024 while (<$fh>) { 5025 next if /^\s*\#/; 5026 my($file) = /(\S+)/; 5027 if ($file =~ m|\Q$what\E$|) { 5028 $bu = $file; 5029 # return File::Spec->catfile($where,$bu); # bad 5030 last; 5031 } 5032 # retry if she managed to 5033 # have no Bundle directory 5034 $bu = $file if $file =~ m|\Q$what2\E$|; 5035 } 5036 $bu =~ tr|/|:| if $^O eq 'MacOS'; 5037 return File::Spec->catfile($where, $bu) if $bu; 5038 Carp::croak("Couldn't find a Bundle file in $where"); 5039} 5040 5041# needs to work quite differently from Module::inst_file because of 5042# cpan_home/Bundle/ directory and the possibility that we have 5043# shadowing effect. As it makes no sense to take the first in @INC for 5044# Bundles, we parse them all for $VERSION and take the newest. 5045 5046#-> sub CPAN::Bundle::inst_file ; 5047sub inst_file { 5048 my($self) = @_; 5049 my($inst_file); 5050 my(@me); 5051 @me = split /::/, $self->id; 5052 $me[-1] .= ".pm"; 5053 my($incdir,$bestv); 5054 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { 5055 my $bfile = File::Spec->catfile($incdir, @me); 5056 CPAN->debug("bfile[$bfile]") if $CPAN::DEBUG; 5057 next unless -f $bfile; 5058 my $foundv = MM->parse_version($bfile); 5059 if (!$bestv || CPAN::Version->vgt($foundv,$bestv)) { 5060 $self->{INST_FILE} = $bfile; 5061 $self->{INST_VERSION} = $bestv = $foundv; 5062 } 5063 } 5064 $self->{INST_FILE}; 5065} 5066 5067#-> sub CPAN::Bundle::inst_version ; 5068sub inst_version { 5069 my($self) = @_; 5070 $self->inst_file; # finds INST_VERSION as side effect 5071 $self->{INST_VERSION}; 5072} 5073 5074#-> sub CPAN::Bundle::rematein ; 5075sub rematein { 5076 my($self,$meth) = @_; 5077 $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG; 5078 my($id) = $self->id; 5079 Carp::croak "Can't $meth $id, don't have an associated bundle file. :-(\n" 5080 unless $self->inst_file || $self->cpan_file; 5081 my($s,%fail); 5082 for $s ($self->contains) { 5083 my($type) = $s =~ m|/| ? 'CPAN::Distribution' : 5084 $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module'; 5085 if ($type eq 'CPAN::Distribution') { 5086 $CPAN::Frontend->mywarn(qq{ 5087The Bundle }.$self->id.qq{ contains 5088explicitly a file $s. 5089}); 5090 sleep 3; 5091 } 5092 # possibly noisy action: 5093 $self->debug("type[$type] s[$s]") if $CPAN::DEBUG; 5094 my $obj = $CPAN::META->instance($type,$s); 5095 $obj->$meth(); 5096 if ($obj->isa(CPAN::Bundle) 5097 && 5098 exists $obj->{install_failed} 5099 && 5100 ref($obj->{install_failed}) eq "HASH" 5101 ) { 5102 for (keys %{$obj->{install_failed}}) { 5103 $self->{install_failed}{$_} = undef; # propagate faiure up 5104 # to me in a 5105 # recursive call 5106 $fail{$s} = 1; # the bundle itself may have succeeded but 5107 # not all children 5108 } 5109 } else { 5110 my $success; 5111 $success = $obj->can("uptodate") ? $obj->uptodate : 0; 5112 $success ||= $obj->{'install'} && $obj->{'install'} eq "YES"; 5113 if ($success) { 5114 delete $self->{install_failed}{$s}; 5115 } else { 5116 $fail{$s} = 1; 5117 } 5118 } 5119 } 5120 5121 # recap with less noise 5122 if ( $meth eq "install" ) { 5123 if (%fail) { 5124 require Text::Wrap; 5125 my $raw = sprintf(qq{Bundle summary: 5126The following items in bundle %s had installation problems:}, 5127 $self->id 5128 ); 5129 $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw)); 5130 $CPAN::Frontend->myprint("\n"); 5131 my $paragraph = ""; 5132 my %reported; 5133 for $s ($self->contains) { 5134 if ($fail{$s}){ 5135 $paragraph .= "$s "; 5136 $self->{install_failed}{$s} = undef; 5137 $reported{$s} = undef; 5138 } 5139 } 5140 my $report_propagated; 5141 for $s (sort keys %{$self->{install_failed}}) { 5142 next if exists $reported{$s}; 5143 $paragraph .= "and the following items had problems 5144during recursive bundle calls: " unless $report_propagated++; 5145 $paragraph .= "$s "; 5146 } 5147 $CPAN::Frontend->myprint(Text::Wrap::fill(" "," ",$paragraph)); 5148 $CPAN::Frontend->myprint("\n"); 5149 } else { 5150 $self->{'install'} = 'YES'; 5151 } 5152 } 5153} 5154 5155#sub CPAN::Bundle::xs_file 5156sub xs_file { 5157 # If a bundle contains another that contains an xs_file we have 5158 # here, we just don't bother I suppose 5159 return 0; 5160} 5161 5162#-> sub CPAN::Bundle::force ; 5163sub force { shift->rematein('force',@_); } 5164#-> sub CPAN::Bundle::get ; 5165sub get { shift->rematein('get',@_); } 5166#-> sub CPAN::Bundle::make ; 5167sub make { shift->rematein('make',@_); } 5168#-> sub CPAN::Bundle::test ; 5169sub test { 5170 my $self = shift; 5171 $self->{badtestcnt} ||= 0; 5172 $self->rematein('test',@_); 5173} 5174#-> sub CPAN::Bundle::install ; 5175sub install { 5176 my $self = shift; 5177 $self->rematein('install',@_); 5178} 5179#-> sub CPAN::Bundle::clean ; 5180sub clean { shift->rematein('clean',@_); } 5181 5182#-> sub CPAN::Bundle::uptodate ; 5183sub uptodate { 5184 my($self) = @_; 5185 return 0 unless $self->SUPER::uptodate; # we mut have the current Bundle def 5186 my $c; 5187 foreach $c ($self->contains) { 5188 my $obj = CPAN::Shell->expandany($c); 5189 return 0 unless $obj->uptodate; 5190 } 5191 return 1; 5192} 5193 5194#-> sub CPAN::Bundle::readme ; 5195sub readme { 5196 my($self) = @_; 5197 my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{ 5198No File found for bundle } . $self->id . qq{\n}), return; 5199 $self->debug("self[$self] file[$file]") if $CPAN::DEBUG; 5200 $CPAN::META->instance('CPAN::Distribution',$file)->readme; 5201} 5202 5203package CPAN::Module; 5204 5205# Accessors 5206# sub CPAN::Module::userid 5207sub userid { 5208 my $self = shift; 5209 return unless exists $self->{RO}; # should never happen 5210 return $self->{RO}{userid} || $self->{RO}{CPAN_USERID}; 5211} 5212# sub CPAN::Module::description 5213sub description { shift->{RO}{description} } 5214 5215sub undelay { 5216 my $self = shift; 5217 delete $self->{later}; 5218 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { 5219 $dist->undelay; 5220 } 5221} 5222 5223#-> sub CPAN::Module::color_cmd_tmps ; 5224sub color_cmd_tmps { 5225 my($self) = shift; 5226 my($depth) = shift || 0; 5227 my($color) = shift || 0; 5228 my($ancestors) = shift || []; 5229 # a module needs to recurse to its cpan_file 5230 5231 return if exists $self->{incommandcolor} 5232 && $self->{incommandcolor}==$color; 5233 if ($depth>=100){ 5234 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); 5235 } 5236 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 5237 5238 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { 5239 $dist->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 5240 } 5241 if ($color==0) { 5242 delete $self->{badtestcnt}; 5243 } 5244 $self->{incommandcolor} = $color; 5245} 5246 5247#-> sub CPAN::Module::as_glimpse ; 5248sub as_glimpse { 5249 my($self) = @_; 5250 my(@m); 5251 my $class = ref($self); 5252 $class =~ s/^CPAN:://; 5253 my $color_on = ""; 5254 my $color_off = ""; 5255 if ( 5256 $CPAN::Shell::COLOR_REGISTERED 5257 && 5258 $CPAN::META->has_inst("Term::ANSIColor") 5259 && 5260 $self->{RO}{description} 5261 ) { 5262 $color_on = Term::ANSIColor::color("green"); 5263 $color_off = Term::ANSIColor::color("reset"); 5264 } 5265 push @m, sprintf("%-15s %s%-15s%s (%s)\n", 5266 $class, 5267 $color_on, 5268 $self->id, 5269 $color_off, 5270 $self->cpan_file); 5271 join "", @m; 5272} 5273 5274#-> sub CPAN::Module::as_string ; 5275sub as_string { 5276 my($self) = @_; 5277 my(@m); 5278 CPAN->debug("$self entering as_string") if $CPAN::DEBUG; 5279 my $class = ref($self); 5280 $class =~ s/^CPAN:://; 5281 local($^W) = 0; 5282 push @m, $class, " id = $self->{ID}\n"; 5283 my $sprintf = " %-12s %s\n"; 5284 push @m, sprintf($sprintf, 'DESCRIPTION', $self->description) 5285 if $self->description; 5286 my $sprintf2 = " %-12s %s (%s)\n"; 5287 my($userid); 5288 $userid = $self->userid; 5289 if ( $userid ){ 5290 my $author; 5291 if ($author = CPAN::Shell->expand('Author',$userid)) { 5292 my $email = ""; 5293 my $m; # old perls 5294 if ($m = $author->email) { 5295 $email = " <$m>"; 5296 } 5297 push @m, sprintf( 5298 $sprintf2, 5299 'CPAN_USERID', 5300 $userid, 5301 $author->fullname . $email 5302 ); 5303 } 5304 } 5305 push @m, sprintf($sprintf, 'CPAN_VERSION', $self->cpan_version) 5306 if $self->cpan_version; 5307 push @m, sprintf($sprintf, 'CPAN_FILE', $self->cpan_file) 5308 if $self->cpan_file; 5309 my $sprintf3 = " %-12s %1s%1s%1s%1s (%s,%s,%s,%s)\n"; 5310 my(%statd,%stats,%statl,%stati); 5311 @statd{qw,? i c a b R M S,} = qw,unknown idea 5312 pre-alpha alpha beta released mature standard,; 5313 @stats{qw,? m d u n a,} = qw,unknown mailing-list 5314 developer comp.lang.perl.* none abandoned,; 5315 @statl{qw,? p c + o h,} = qw,unknown perl C C++ other hybrid,; 5316 @stati{qw,? f r O h,} = qw,unknown functions 5317 references+ties object-oriented hybrid,; 5318 $statd{' '} = 'unknown'; 5319 $stats{' '} = 'unknown'; 5320 $statl{' '} = 'unknown'; 5321 $stati{' '} = 'unknown'; 5322 push @m, sprintf( 5323 $sprintf3, 5324 'DSLI_STATUS', 5325 $self->{RO}{statd}, 5326 $self->{RO}{stats}, 5327 $self->{RO}{statl}, 5328 $self->{RO}{stati}, 5329 $statd{$self->{RO}{statd}}, 5330 $stats{$self->{RO}{stats}}, 5331 $statl{$self->{RO}{statl}}, 5332 $stati{$self->{RO}{stati}} 5333 ) if $self->{RO}{statd}; 5334 my $local_file = $self->inst_file; 5335 unless ($self->{MANPAGE}) { 5336 if ($local_file) { 5337 $self->{MANPAGE} = $self->manpage_headline($local_file); 5338 } else { 5339 # If we have already untarred it, we should look there 5340 my $dist = $CPAN::META->instance('CPAN::Distribution', 5341 $self->cpan_file); 5342 # warn "dist[$dist]"; 5343 # mff=manifest file; mfh=manifest handle 5344 my($mff,$mfh); 5345 if ( 5346 $dist->{build_dir} 5347 and 5348 (-f ($mff = File::Spec->catfile($dist->{build_dir}, "MANIFEST"))) 5349 and 5350 $mfh = FileHandle->new($mff) 5351 ) { 5352 CPAN->debug("mff[$mff]") if $CPAN::DEBUG; 5353 my $lfre = $self->id; # local file RE 5354 $lfre =~ s/::/./g; 5355 $lfre .= "\\.pm\$"; 5356 my($lfl); # local file file 5357 local $/ = "\n"; 5358 my(@mflines) = <$mfh>; 5359 for (@mflines) { 5360 s/^\s+//; 5361 s/\s.*//s; 5362 } 5363 while (length($lfre)>5 and !$lfl) { 5364 ($lfl) = grep /$lfre/, @mflines; 5365 CPAN->debug("lfl[$lfl]lfre[$lfre]") if $CPAN::DEBUG; 5366 $lfre =~ s/.+?\.//; 5367 } 5368 $lfl =~ s/\s.*//; # remove comments 5369 $lfl =~ s/\s+//g; # chomp would maybe be too system-specific 5370 my $lfl_abs = File::Spec->catfile($dist->{build_dir},$lfl); 5371 # warn "lfl_abs[$lfl_abs]"; 5372 if (-f $lfl_abs) { 5373 $self->{MANPAGE} = $self->manpage_headline($lfl_abs); 5374 } 5375 } 5376 } 5377 } 5378 my($item); 5379 for $item (qw/MANPAGE/) { 5380 push @m, sprintf($sprintf, $item, $self->{$item}) 5381 if exists $self->{$item}; 5382 } 5383 for $item (qw/CONTAINS/) { 5384 push @m, sprintf($sprintf, $item, join(" ",@{$self->{$item}})) 5385 if exists $self->{$item} && @{$self->{$item}}; 5386 } 5387 push @m, sprintf($sprintf, 'INST_FILE', 5388 $local_file || "(not installed)"); 5389 push @m, sprintf($sprintf, 'INST_VERSION', 5390 $self->inst_version) if $local_file; 5391 join "", @m, "\n"; 5392} 5393 5394sub manpage_headline { 5395 my($self,$local_file) = @_; 5396 my(@local_file) = $local_file; 5397 $local_file =~ s/\.pm(?!\n)\Z/.pod/; 5398 push @local_file, $local_file; 5399 my(@result,$locf); 5400 for $locf (@local_file) { 5401 next unless -f $locf; 5402 my $fh = FileHandle->new($locf) 5403 or $Carp::Frontend->mydie("Couldn't open $locf: $!"); 5404 my $inpod = 0; 5405 local $/ = "\n"; 5406 while (<$fh>) { 5407 $inpod = m/^=(?!head1\s+NAME\s*$)/ ? 0 : 5408 m/^=head1\s+NAME\s*$/ ? 1 : $inpod; 5409 next unless $inpod; 5410 next if /^=/; 5411 next if /^\s+$/; 5412 chomp; 5413 push @result, $_; 5414 } 5415 close $fh; 5416 last if @result; 5417 } 5418 join " ", @result; 5419} 5420 5421#-> sub CPAN::Module::cpan_file ; 5422# Note: also inherited by CPAN::Bundle 5423sub cpan_file { 5424 my $self = shift; 5425 CPAN->debug(sprintf "id[%s]", $self->id) if $CPAN::DEBUG; 5426 unless (defined $self->{RO}{CPAN_FILE}) { 5427 CPAN::Index->reload; 5428 } 5429 if (exists $self->{RO}{CPAN_FILE} && defined $self->{RO}{CPAN_FILE}){ 5430 return $self->{RO}{CPAN_FILE}; 5431 } else { 5432 my $userid = $self->userid; 5433 if ( $userid ) { 5434 if ($CPAN::META->exists("CPAN::Author",$userid)) { 5435 my $author = $CPAN::META->instance("CPAN::Author", 5436 $userid); 5437 my $fullname = $author->fullname; 5438 my $email = $author->email; 5439 unless (defined $fullname && defined $email) { 5440 return sprintf("Contact Author %s", 5441 $userid, 5442 ); 5443 } 5444 return "Contact Author $fullname <$email>"; 5445 } else { 5446 return "Contact Author $userid (Email address not available)"; 5447 } 5448 } else { 5449 return "N/A"; 5450 } 5451 } 5452} 5453 5454#-> sub CPAN::Module::cpan_version ; 5455sub cpan_version { 5456 my $self = shift; 5457 5458 $self->{RO}{CPAN_VERSION} = 'undef' 5459 unless defined $self->{RO}{CPAN_VERSION}; 5460 # I believe this is always a bug in the index and should be reported 5461 # as such, but usually I find out such an error and do not want to 5462 # provoke too many bugreports 5463 5464 $self->{RO}{CPAN_VERSION}; 5465} 5466 5467#-> sub CPAN::Module::force ; 5468sub force { 5469 my($self) = @_; 5470 $self->{'force_update'}++; 5471} 5472 5473#-> sub CPAN::Module::rematein ; 5474sub rematein { 5475 my($self,$meth) = @_; 5476 $CPAN::Frontend->myprint(sprintf("Running %s for module %s\n", 5477 $meth, 5478 $self->id)); 5479 my $cpan_file = $self->cpan_file; 5480 if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/){ 5481 $CPAN::Frontend->mywarn(sprintf qq{ 5482 The module %s isn\'t available on CPAN. 5483 5484 Either the module has not yet been uploaded to CPAN, or it is 5485 temporary unavailable. Please contact the author to find out 5486 more about the status. Try 'i %s'. 5487}, 5488 $self->id, 5489 $self->id, 5490 ); 5491 return; 5492 } 5493 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 5494 $pack->called_for($self->id); 5495 $pack->force($meth) if exists $self->{'force_update'}; 5496 $pack->$meth(); 5497 $pack->unforce if $pack->can("unforce") && exists $self->{'force_update'}; 5498 delete $self->{'force_update'}; 5499} 5500 5501#-> sub CPAN::Module::readme ; 5502sub readme { shift->rematein('readme') } 5503#-> sub CPAN::Module::look ; 5504sub look { shift->rematein('look') } 5505#-> sub CPAN::Module::cvs_import ; 5506sub cvs_import { shift->rematein('cvs_import') } 5507#-> sub CPAN::Module::get ; 5508sub get { shift->rematein('get',@_); } 5509#-> sub CPAN::Module::make ; 5510sub make { 5511 my $self = shift; 5512 $self->rematein('make'); 5513} 5514#-> sub CPAN::Module::test ; 5515sub test { 5516 my $self = shift; 5517 $self->{badtestcnt} ||= 0; 5518 $self->rematein('test',@_); 5519} 5520#-> sub CPAN::Module::uptodate ; 5521sub uptodate { 5522 my($self) = @_; 5523 my($latest) = $self->cpan_version; 5524 $latest ||= 0; 5525 my($inst_file) = $self->inst_file; 5526 my($have) = 0; 5527 if (defined $inst_file) { 5528 $have = $self->inst_version; 5529 } 5530 local($^W)=0; 5531 if ($inst_file 5532 && 5533 ! CPAN::Version->vgt($latest, $have) 5534 ) { 5535 CPAN->debug("returning uptodate. inst_file[$inst_file] ". 5536 "latest[$latest] have[$have]") if $CPAN::DEBUG; 5537 return 1; 5538 } 5539 return; 5540} 5541#-> sub CPAN::Module::install ; 5542sub install { 5543 my($self) = @_; 5544 my($doit) = 0; 5545 if ($self->uptodate 5546 && 5547 not exists $self->{'force_update'} 5548 ) { 5549 $CPAN::Frontend->myprint( $self->id. " is up to date.\n"); 5550 } else { 5551 $doit = 1; 5552 } 5553 if ($self->{RO}{stats} && $self->{RO}{stats} eq "a") { 5554 $CPAN::Frontend->mywarn(qq{ 5555\n\n\n ***WARNING*** 5556 The module $self->{ID} has no active maintainer.\n\n\n 5557}); 5558 sleep 5; 5559 } 5560 $self->rematein('install') if $doit; 5561} 5562#-> sub CPAN::Module::clean ; 5563sub clean { shift->rematein('clean') } 5564 5565#-> sub CPAN::Module::inst_file ; 5566sub inst_file { 5567 my($self) = @_; 5568 my($dir,@packpath); 5569 @packpath = split /::/, $self->{ID}; 5570 $packpath[-1] .= ".pm"; 5571 foreach $dir (@INC) { 5572 my $pmfile = File::Spec->catfile($dir,@packpath); 5573 if (-f $pmfile){ 5574 return $pmfile; 5575 } 5576 } 5577 return; 5578} 5579 5580#-> sub CPAN::Module::xs_file ; 5581sub xs_file { 5582 my($self) = @_; 5583 my($dir,@packpath); 5584 @packpath = split /::/, $self->{ID}; 5585 push @packpath, $packpath[-1]; 5586 $packpath[-1] .= "." . $Config::Config{'dlext'}; 5587 foreach $dir (@INC) { 5588 my $xsfile = File::Spec->catfile($dir,'auto',@packpath); 5589 if (-f $xsfile){ 5590 return $xsfile; 5591 } 5592 } 5593 return; 5594} 5595 5596#-> sub CPAN::Module::inst_version ; 5597sub inst_version { 5598 my($self) = @_; 5599 my $parsefile = $self->inst_file or return; 5600 local($^W) = 0 if $] < 5.00303 && $ExtUtils::MakeMaker::VERSION < 5.38; 5601 my $have; 5602 5603 # there was a bug in 5.6.0 that let lots of unini warnings out of 5604 # parse_version. Fixed shortly after 5.6.0 by PMQS. We can remove 5605 # the following workaround after 5.6.1 is out. 5606 local($SIG{__WARN__}) = sub { my $w = shift; 5607 return if $w =~ /uninitialized/i; 5608 warn $w; 5609 }; 5610 5611 $have = MM->parse_version($parsefile) || "undef"; 5612 $have =~ s/^ //; # since the %vd hack these two lines here are needed 5613 $have =~ s/ $//; # trailing whitespace happens all the time 5614 5615 # My thoughts about why %vd processing should happen here 5616 5617 # Alt1 maintain it as string with leading v: 5618 # read index files do nothing 5619 # compare it use utility for compare 5620 # print it do nothing 5621 5622 # Alt2 maintain it as what it is 5623 # read index files convert 5624 # compare it use utility because there's still a ">" vs "gt" issue 5625 # print it use CPAN::Version for print 5626 5627 # Seems cleaner to hold it in memory as a string starting with a "v" 5628 5629 # If the author of this module made a mistake and wrote a quoted 5630 # "v1.13" instead of v1.13, we simply leave it at that with the 5631 # effect that *we* will treat it like a v-tring while the rest of 5632 # perl won't. Seems sensible when we consider that any action we 5633 # could take now would just add complexity. 5634 5635 $have = CPAN::Version->readable($have); 5636 5637 $have =~ s/\s*//g; # stringify to float around floating point issues 5638 $have; # no stringify needed, \s* above matches always 5639} 5640 5641package CPAN::Tarzip; 5642 5643# CPAN::Tarzip::gzip 5644sub gzip { 5645 my($class,$read,$write) = @_; 5646 if ($CPAN::META->has_inst("Compress::Zlib")) { 5647 my($buffer,$fhw); 5648 $fhw = FileHandle->new($read) 5649 or $CPAN::Frontend->mydie("Could not open $read: $!"); 5650 my $gz = Compress::Zlib::gzopen($write, "wb") 5651 or $CPAN::Frontend->mydie("Cannot gzopen $write: $!\n"); 5652 $gz->gzwrite($buffer) 5653 while read($fhw,$buffer,4096) > 0 ; 5654 $gz->gzclose() ; 5655 $fhw->close; 5656 return 1; 5657 } else { 5658 system("$CPAN::Config->{gzip} -c $read > $write")==0; 5659 } 5660} 5661 5662 5663# CPAN::Tarzip::gunzip 5664sub gunzip { 5665 my($class,$read,$write) = @_; 5666 if ($CPAN::META->has_inst("Compress::Zlib")) { 5667 my($buffer,$fhw); 5668 $fhw = FileHandle->new(">$write") 5669 or $CPAN::Frontend->mydie("Could not open >$write: $!"); 5670 my $gz = Compress::Zlib::gzopen($read, "rb") 5671 or $CPAN::Frontend->mydie("Cannot gzopen $read: $!\n"); 5672 $fhw->print($buffer) 5673 while $gz->gzread($buffer) > 0 ; 5674 $CPAN::Frontend->mydie("Error reading from $read: $!\n") 5675 if $gz->gzerror != Compress::Zlib::Z_STREAM_END(); 5676 $gz->gzclose() ; 5677 $fhw->close; 5678 return 1; 5679 } else { 5680 system("$CPAN::Config->{gzip} -dc $read > $write")==0; 5681 } 5682} 5683 5684 5685# CPAN::Tarzip::gtest 5686sub gtest { 5687 my($class,$read) = @_; 5688 # After I had reread the documentation in zlib.h, I discovered that 5689 # uncompressed files do not lead to an gzerror (anymore?). 5690 if ( $CPAN::META->has_inst("Compress::Zlib") ) { 5691 my($buffer,$len); 5692 $len = 0; 5693 my $gz = Compress::Zlib::gzopen($read, "rb") 5694 or $CPAN::Frontend->mydie(sprintf("Cannot gzopen %s: %s\n", 5695 $read, 5696 $Compress::Zlib::gzerrno)); 5697 while ($gz->gzread($buffer) > 0 ){ 5698 $len += length($buffer); 5699 $buffer = ""; 5700 } 5701 my $err = $gz->gzerror; 5702 my $success = ! $err || $err == Compress::Zlib::Z_STREAM_END(); 5703 if ($len == -s $read){ 5704 $success = 0; 5705 CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG; 5706 } 5707 $gz->gzclose(); 5708 CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG; 5709 return $success; 5710 } else { 5711 return system("$CPAN::Config->{gzip} -dt $read")==0; 5712 } 5713} 5714 5715 5716# CPAN::Tarzip::TIEHANDLE 5717sub TIEHANDLE { 5718 my($class,$file) = @_; 5719 my $ret; 5720 $class->debug("file[$file]"); 5721 if ($CPAN::META->has_inst("Compress::Zlib")) { 5722 my $gz = Compress::Zlib::gzopen($file,"rb") or 5723 die "Could not gzopen $file"; 5724 $ret = bless {GZ => $gz}, $class; 5725 } else { 5726 my $pipe = "$CPAN::Config->{gzip} --decompress --stdout $file |"; 5727 my $fh = FileHandle->new($pipe) or die "Could not pipe[$pipe]: $!"; 5728 binmode $fh; 5729 $ret = bless {FH => $fh}, $class; 5730 } 5731 $ret; 5732} 5733 5734 5735# CPAN::Tarzip::READLINE 5736sub READLINE { 5737 my($self) = @_; 5738 if (exists $self->{GZ}) { 5739 my $gz = $self->{GZ}; 5740 my($line,$bytesread); 5741 $bytesread = $gz->gzreadline($line); 5742 return undef if $bytesread <= 0; 5743 return $line; 5744 } else { 5745 my $fh = $self->{FH}; 5746 return scalar <$fh>; 5747 } 5748} 5749 5750 5751# CPAN::Tarzip::READ 5752sub READ { 5753 my($self,$ref,$length,$offset) = @_; 5754 die "read with offset not implemented" if defined $offset; 5755 if (exists $self->{GZ}) { 5756 my $gz = $self->{GZ}; 5757 my $byteread = $gz->gzread($$ref,$length);# 30eaf79e8b446ef52464b5422da328a8 5758 return $byteread; 5759 } else { 5760 my $fh = $self->{FH}; 5761 return read($fh,$$ref,$length); 5762 } 5763} 5764 5765 5766# CPAN::Tarzip::DESTROY 5767sub DESTROY { 5768 my($self) = @_; 5769 if (exists $self->{GZ}) { 5770 my $gz = $self->{GZ}; 5771 $gz->gzclose() if defined $gz; # hard to say if it is allowed 5772 # to be undef ever. AK, 2000-09 5773 } else { 5774 my $fh = $self->{FH}; 5775 $fh->close if defined $fh; 5776 } 5777 undef $self; 5778} 5779 5780 5781# CPAN::Tarzip::untar 5782sub untar { 5783 my($class,$file) = @_; 5784 my($prefer) = 0; 5785 5786 if (0) { # makes changing order easier 5787 } elsif ($BUGHUNTING){ 5788 $prefer=2; 5789 } elsif (MM->maybe_command($CPAN::Config->{gzip}) 5790 && 5791 MM->maybe_command($CPAN::Config->{'tar'})) { 5792 # should be default until Archive::Tar is fixed 5793 $prefer = 1; 5794 } elsif ( 5795 $CPAN::META->has_inst("Archive::Tar") 5796 && 5797 $CPAN::META->has_inst("Compress::Zlib") ) { 5798 $prefer = 2; 5799 } else { 5800 $CPAN::Frontend->mydie(qq{ 5801CPAN.pm needs either both external programs tar and gzip installed or 5802both the modules Archive::Tar and Compress::Zlib. Neither prerequisite 5803is available. Can\'t continue. 5804}); 5805 } 5806 if ($prefer==1) { # 1 => external gzip+tar 5807 my($system); 5808 my $is_compressed = $class->gtest($file); 5809 if ($is_compressed) { 5810 $system = "$CPAN::Config->{gzip} --decompress --stdout " . 5811 "< $file | $CPAN::Config->{tar} xvf -"; 5812 } else { 5813 $system = "$CPAN::Config->{tar} xvf $file"; 5814 } 5815 if (system($system) != 0) { 5816 # people find the most curious tar binaries that cannot handle 5817 # pipes 5818 if ($is_compressed) { 5819 (my $ungzf = $file) =~ s/\.gz(?!\n)\Z//; 5820 if (CPAN::Tarzip->gunzip($file, $ungzf)) { 5821 $CPAN::Frontend->myprint(qq{Uncompressed $file successfully\n}); 5822 } else { 5823 $CPAN::Frontend->mydie(qq{Couldn\'t uncompress $file\n}); 5824 } 5825 $file = $ungzf; 5826 } 5827 $system = "$CPAN::Config->{tar} xvf $file"; 5828 $CPAN::Frontend->myprint(qq{Using Tar:$system:\n}); 5829 if (system($system)==0) { 5830 $CPAN::Frontend->myprint(qq{Untarred $file successfully\n}); 5831 } else { 5832 $CPAN::Frontend->mydie(qq{Couldn\'t untar $file\n}); 5833 } 5834 return 1; 5835 } else { 5836 return 1; 5837 } 5838 } elsif ($prefer==2) { # 2 => modules 5839 my $tar = Archive::Tar->new($file,1); 5840 my $af; # archive file 5841 my @af; 5842 if ($BUGHUNTING) { 5843 # RCS 1.337 had this code, it turned out unacceptable slow but 5844 # it revealed a bug in Archive::Tar. Code is only here to hunt 5845 # the bug again. It should never be enabled in published code. 5846 # GDGraph3d-0.53 was an interesting case according to Larry 5847 # Virden. 5848 warn(">>>Bughunting code enabled<<< " x 20); 5849 for $af ($tar->list_files) { 5850 if ($af =~ m!^(/|\.\./)!) { 5851 $CPAN::Frontend->mydie("ALERT: Archive contains ". 5852 "illegal member [$af]"); 5853 } 5854 $CPAN::Frontend->myprint("$af\n"); 5855 $tar->extract($af); # slow but effective for finding the bug 5856 return if $CPAN::Signal; 5857 } 5858 } else { 5859 for $af ($tar->list_files) { 5860 if ($af =~ m!^(/|\.\./)!) { 5861 $CPAN::Frontend->mydie("ALERT: Archive contains ". 5862 "illegal member [$af]"); 5863 } 5864 $CPAN::Frontend->myprint("$af\n"); 5865 push @af, $af; 5866 return if $CPAN::Signal; 5867 } 5868 $tar->extract(@af); 5869 } 5870 5871 Mac::BuildTools::convert_files([$tar->list_files], 1) 5872 if ($^O eq 'MacOS'); 5873 5874 return 1; 5875 } 5876} 5877 5878sub unzip { 5879 my($class,$file) = @_; 5880 if ($CPAN::META->has_inst("Archive::Zip")) { 5881 # blueprint of the code from Archive::Zip::Tree::extractTree(); 5882 my $zip = Archive::Zip->new(); 5883 my $status; 5884 $status = $zip->read($file); 5885 die "Read of file[$file] failed\n" if $status != Archive::Zip::AZ_OK(); 5886 $CPAN::META->debug("Successfully read file[$file]") if $CPAN::DEBUG; 5887 my @members = $zip->members(); 5888 for my $member ( @members ) { 5889 my $af = $member->fileName(); 5890 if ($af =~ m!^(/|\.\./)!) { 5891 $CPAN::Frontend->mydie("ALERT: Archive contains ". 5892 "illegal member [$af]"); 5893 } 5894 my $status = $member->extractToFileNamed( $af ); 5895 $CPAN::META->debug("af[$af]status[$status]") if $CPAN::DEBUG; 5896 die "Extracting of file[$af] from zipfile[$file] failed\n" if 5897 $status != Archive::Zip::AZ_OK(); 5898 return if $CPAN::Signal; 5899 } 5900 return 1; 5901 } else { 5902 my $unzip = $CPAN::Config->{unzip} or 5903 $CPAN::Frontend->mydie("Cannot unzip, no unzip program available"); 5904 my @system = ($unzip, $file); 5905 return system(@system) == 0; 5906 } 5907} 5908 5909 5910package CPAN::Version; 5911# CPAN::Version::vcmp courtesy Jost Krieger 5912sub vcmp { 5913 my($self,$l,$r) = @_; 5914 local($^W) = 0; 5915 CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG; 5916 5917 return 0 if $l eq $r; # short circuit for quicker success 5918 5919 if ($l=~/^v/ <=> $r=~/^v/) { 5920 for ($l,$r) { 5921 next if /^v/; 5922 $_ = $self->float2vv($_); 5923 } 5924 } 5925 5926 return 5927 ($l ne "undef") <=> ($r ne "undef") || 5928 ($] >= 5.006 && 5929 $l =~ /^v/ && 5930 $r =~ /^v/ && 5931 $self->vstring($l) cmp $self->vstring($r)) || 5932 $l <=> $r || 5933 $l cmp $r; 5934} 5935 5936sub vgt { 5937 my($self,$l,$r) = @_; 5938 $self->vcmp($l,$r) > 0; 5939} 5940 5941sub vstring { 5942 my($self,$n) = @_; 5943 $n =~ s/^v// or die "CPAN::Version::vstring() called with invalid arg [$n]"; 5944 pack "U*", split /\./, $n; 5945} 5946 5947# vv => visible vstring 5948sub float2vv { 5949 my($self,$n) = @_; 5950 my($rev) = int($n); 5951 $rev ||= 0; 5952 my($mantissa) = $n =~ /\.(\d{1,12})/; # limit to 12 digits to limit 5953 # architecture influence 5954 $mantissa ||= 0; 5955 $mantissa .= "0" while length($mantissa)%3; 5956 my $ret = "v" . $rev; 5957 while ($mantissa) { 5958 $mantissa =~ s/(\d{1,3})// or 5959 die "Panic: length>0 but not a digit? mantissa[$mantissa]"; 5960 $ret .= ".".int($1); 5961 } 5962 # warn "n[$n]ret[$ret]"; 5963 $ret; 5964} 5965 5966sub readable { 5967 my($self,$n) = @_; 5968 $n =~ /^([\w\-\+\.]+)/; 5969 5970 return $1 if defined $1 && length($1)>0; 5971 # if the first user reaches version v43, he will be treated as "+". 5972 # We'll have to decide about a new rule here then, depending on what 5973 # will be the prevailing versioning behavior then. 5974 5975 if ($] < 5.006) { # or whenever v-strings were introduced 5976 # we get them wrong anyway, whatever we do, because 5.005 will 5977 # have already interpreted 0.2.4 to be "0.24". So even if he 5978 # indexer sends us something like "v0.2.4" we compare wrongly. 5979 5980 # And if they say v1.2, then the old perl takes it as "v12" 5981 5982 $CPAN::Frontend->mywarn("Suspicious version string seen [$n]\n"); 5983 return $n; 5984 } 5985 my $better = sprintf "v%vd", $n; 5986 CPAN->debug("n[$n] better[$better]") if $CPAN::DEBUG; 5987 return $better; 5988} 5989 5990package CPAN; 5991 59921; 5993 5994__END__ 5995 5996=head1 NAME 5997 5998CPAN - query, download and build perl modules from CPAN sites 5999 6000=head1 SYNOPSIS 6001 6002Interactive mode: 6003 6004 perl -MCPAN -e shell; 6005 6006Batch mode: 6007 6008 use CPAN; 6009 6010 autobundle, clean, install, make, recompile, test 6011 6012=head1 STATUS 6013 6014This module will eventually be replaced by CPANPLUS. CPANPLUS is kind 6015of a modern rewrite from ground up with greater extensibility and more 6016features but no full compatibility. If you're new to CPAN.pm, you 6017probably should investigate if CPANPLUS is the better choice for you. 6018If you're already used to CPAN.pm you're welcome to continue using it, 6019if you accept that its development is mostly (though not completely) 6020stalled. 6021 6022=head1 DESCRIPTION 6023 6024The CPAN module is designed to automate the make and install of perl 6025modules and extensions. It includes some primitive searching capabilities and 6026knows how to use Net::FTP or LWP (or lynx or an external ftp client) 6027to fetch the raw data from the net. 6028 6029Modules are fetched from one or more of the mirrored CPAN 6030(Comprehensive Perl Archive Network) sites and unpacked in a dedicated 6031directory. 6032 6033The CPAN module also supports the concept of named and versioned 6034I<bundles> of modules. Bundles simplify the handling of sets of 6035related modules. See Bundles below. 6036 6037The package contains a session manager and a cache manager. There is 6038no status retained between sessions. The session manager keeps track 6039of what has been fetched, built and installed in the current 6040session. The cache manager keeps track of the disk space occupied by 6041the make processes and deletes excess space according to a simple FIFO 6042mechanism. 6043 6044For extended searching capabilities there's a plugin for CPAN available, 6045L<C<CPAN::WAIT>|CPAN::WAIT>. C<CPAN::WAIT> is a full-text search engine 6046that indexes all documents available in CPAN authors directories. If 6047C<CPAN::WAIT> is installed on your system, the interactive shell of 6048CPAN.pm will enable the C<wq>, C<wr>, C<wd>, C<wl>, and C<wh> commands 6049which send queries to the WAIT server that has been configured for your 6050installation. 6051 6052All other methods provided are accessible in a programmer style and in an 6053interactive shell style. 6054 6055=head2 Interactive Mode 6056 6057The interactive mode is entered by running 6058 6059 perl -MCPAN -e shell 6060 6061which puts you into a readline interface. You will have the most fun if 6062you install Term::ReadKey and Term::ReadLine to enjoy both history and 6063command completion. 6064 6065Once you are on the command line, type 'h' and the rest should be 6066self-explanatory. 6067 6068The function call C<shell> takes two optional arguments, one is the 6069prompt, the second is the default initial command line (the latter 6070only works if a real ReadLine interface module is installed). 6071 6072The most common uses of the interactive modes are 6073 6074=over 2 6075 6076=item Searching for authors, bundles, distribution files and modules 6077 6078There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m> 6079for each of the four categories and another, C<i> for any of the 6080mentioned four. Each of the four entities is implemented as a class 6081with slightly differing methods for displaying an object. 6082 6083Arguments you pass to these commands are either strings exactly matching 6084the identification string of an object or regular expressions that are 6085then matched case-insensitively against various attributes of the 6086objects. The parser recognizes a regular expression only if you 6087enclose it between two slashes. 6088 6089The principle is that the number of found objects influences how an 6090item is displayed. If the search finds one item, the result is 6091displayed with the rather verbose method C<as_string>, but if we find 6092more than one, we display each object with the terse method 6093<as_glimpse>. 6094 6095=item make, test, install, clean modules or distributions 6096 6097These commands take any number of arguments and investigate what is 6098necessary to perform the action. If the argument is a distribution 6099file name (recognized by embedded slashes), it is processed. If it is 6100a module, CPAN determines the distribution file in which this module 6101is included and processes that, following any dependencies named in 6102the module's Makefile.PL (this behavior is controlled by 6103I<prerequisites_policy>.) 6104 6105Any C<make> or C<test> are run unconditionally. An 6106 6107 install <distribution_file> 6108 6109also is run unconditionally. But for 6110 6111 install <module> 6112 6113CPAN checks if an install is actually needed for it and prints 6114I<module up to date> in the case that the distribution file containing 6115the module doesn't need to be updated. 6116 6117CPAN also keeps track of what it has done within the current session 6118and doesn't try to build a package a second time regardless if it 6119succeeded or not. The C<force> command takes as a first argument the 6120method to invoke (currently: C<make>, C<test>, or C<install>) and executes the 6121command from scratch. 6122 6123Example: 6124 6125 cpan> install OpenGL 6126 OpenGL is up to date. 6127 cpan> force install OpenGL 6128 Running make 6129 OpenGL-0.4/ 6130 OpenGL-0.4/COPYRIGHT 6131 [...] 6132 6133A C<clean> command results in a 6134 6135 make clean 6136 6137being executed within the distribution file's working directory. 6138 6139=item get, readme, look module or distribution 6140 6141C<get> downloads a distribution file without further action. C<readme> 6142displays the README file of the associated distribution. C<Look> gets 6143and untars (if not yet done) the distribution file, changes to the 6144appropriate directory and opens a subshell process in that directory. 6145 6146=item ls author 6147 6148C<ls> lists all distribution files in and below an author's CPAN 6149directory. Only those files that contain modules are listed and if 6150there is more than one for any given module, only the most recent one 6151is listed. 6152 6153=item Signals 6154 6155CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are 6156in the cpan-shell it is intended that you can press C<^C> anytime and 6157return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell 6158to clean up and leave the shell loop. You can emulate the effect of a 6159SIGTERM by sending two consecutive SIGINTs, which usually means by 6160pressing C<^C> twice. 6161 6162CPAN.pm ignores a SIGPIPE. If the user sets inactivity_timeout, a 6163SIGALRM is used during the run of the C<perl Makefile.PL> subprocess. 6164 6165=back 6166 6167=head2 CPAN::Shell 6168 6169The commands that are available in the shell interface are methods in 6170the package CPAN::Shell. If you enter the shell command, all your 6171input is split by the Text::ParseWords::shellwords() routine which 6172acts like most shells do. The first word is being interpreted as the 6173method to be called and the rest of the words are treated as arguments 6174to this method. Continuation lines are supported if a line ends with a 6175literal backslash. 6176 6177=head2 autobundle 6178 6179C<autobundle> writes a bundle file into the 6180C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains 6181a list of all modules that are both available from CPAN and currently 6182installed within @INC. The name of the bundle file is based on the 6183current date and a counter. 6184 6185=head2 recompile 6186 6187recompile() is a very special command in that it takes no argument and 6188runs the make/test/install cycle with brute force over all installed 6189dynamically loadable extensions (aka XS modules) with 'force' in 6190effect. The primary purpose of this command is to finish a network 6191installation. Imagine, you have a common source tree for two different 6192architectures. You decide to do a completely independent fresh 6193installation. You start on one architecture with the help of a Bundle 6194file produced earlier. CPAN installs the whole Bundle for you, but 6195when you try to repeat the job on the second architecture, CPAN 6196responds with a C<"Foo up to date"> message for all modules. So you 6197invoke CPAN's recompile on the second architecture and you're done. 6198 6199Another popular use for C<recompile> is to act as a rescue in case your 6200perl breaks binary compatibility. If one of the modules that CPAN uses 6201is in turn depending on binary compatibility (so you cannot run CPAN 6202commands), then you should try the CPAN::Nox module for recovery. 6203 6204=head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution 6205 6206Although it may be considered internal, the class hierarchy does matter 6207for both users and programmer. CPAN.pm deals with above mentioned four 6208classes, and all those classes share a set of methods. A classical 6209single polymorphism is in effect. A metaclass object registers all 6210objects of all kinds and indexes them with a string. The strings 6211referencing objects have a separated namespace (well, not completely 6212separated): 6213 6214 Namespace Class 6215 6216 words containing a "/" (slash) Distribution 6217 words starting with Bundle:: Bundle 6218 everything else Module or Author 6219 6220Modules know their associated Distribution objects. They always refer 6221to the most recent official release. Developers may mark their releases 6222as unstable development versions (by inserting an underbar into the 6223module version number which will also be reflected in the distribution 6224name when you run 'make dist'), so the really hottest and newest 6225distribution is not always the default. If a module Foo circulates 6226on CPAN in both version 1.23 and 1.23_90, CPAN.pm offers a convenient 6227way to install version 1.23 by saying 6228 6229 install Foo 6230 6231This would install the complete distribution file (say 6232BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would 6233like to install version 1.23_90, you need to know where the 6234distribution file resides on CPAN relative to the authors/id/ 6235directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz; 6236so you would have to say 6237 6238 install BAR/Foo-1.23_90.tar.gz 6239 6240The first example will be driven by an object of the class 6241CPAN::Module, the second by an object of class CPAN::Distribution. 6242 6243=head2 Programmer's interface 6244 6245If you do not enter the shell, the available shell commands are both 6246available as methods (C<CPAN::Shell-E<gt>install(...)>) and as 6247functions in the calling package (C<install(...)>). 6248 6249There's currently only one class that has a stable interface - 6250CPAN::Shell. All commands that are available in the CPAN shell are 6251methods of the class CPAN::Shell. Each of the commands that produce 6252listings of modules (C<r>, C<autobundle>, C<u>) also return a list of 6253the IDs of all modules within the list. 6254 6255=over 2 6256 6257=item expand($type,@things) 6258 6259The IDs of all objects available within a program are strings that can 6260be expanded to the corresponding real objects with the 6261C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a 6262list of CPAN::Module objects according to the C<@things> arguments 6263given. In scalar context it only returns the first element of the 6264list. 6265 6266=item expandany(@things) 6267 6268Like expand, but returns objects of the appropriate type, i.e. 6269CPAN::Bundle objects for bundles, CPAN::Module objects for modules and 6270CPAN::Distribution objects fro distributions. 6271 6272=item Programming Examples 6273 6274This enables the programmer to do operations that combine 6275functionalities that are available in the shell. 6276 6277 # install everything that is outdated on my disk: 6278 perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)' 6279 6280 # install my favorite programs if necessary: 6281 for $mod (qw(Net::FTP Digest::MD5 Data::Dumper)){ 6282 my $obj = CPAN::Shell->expand('Module',$mod); 6283 $obj->install; 6284 } 6285 6286 # list all modules on my disk that have no VERSION number 6287 for $mod (CPAN::Shell->expand("Module","/./")){ 6288 next unless $mod->inst_file; 6289 # MakeMaker convention for undefined $VERSION: 6290 next unless $mod->inst_version eq "undef"; 6291 print "No VERSION in ", $mod->id, "\n"; 6292 } 6293 6294 # find out which distribution on CPAN contains a module: 6295 print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file 6296 6297Or if you want to write a cronjob to watch The CPAN, you could list 6298all modules that need updating. First a quick and dirty way: 6299 6300 perl -e 'use CPAN; CPAN::Shell->r;' 6301 6302If you don't want to get any output in the case that all modules are 6303up to date, you can parse the output of above command for the regular 6304expression //modules are up to date// and decide to mail the output 6305only if it doesn't match. Ick? 6306 6307If you prefer to do it more in a programmer style in one single 6308process, maybe something like this suits you better: 6309 6310 # list all modules on my disk that have newer versions on CPAN 6311 for $mod (CPAN::Shell->expand("Module","/./")){ 6312 next unless $mod->inst_file; 6313 next if $mod->uptodate; 6314 printf "Module %s is installed as %s, could be updated to %s from CPAN\n", 6315 $mod->id, $mod->inst_version, $mod->cpan_version; 6316 } 6317 6318If that gives you too much output every day, you maybe only want to 6319watch for three modules. You can write 6320 6321 for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){ 6322 6323as the first line instead. Or you can combine some of the above 6324tricks: 6325 6326 # watch only for a new mod_perl module 6327 $mod = CPAN::Shell->expand("Module","mod_perl"); 6328 exit if $mod->uptodate; 6329 # new mod_perl arrived, let me know all update recommendations 6330 CPAN::Shell->r; 6331 6332=back 6333 6334=head2 Methods in the other Classes 6335 6336The programming interface for the classes CPAN::Module, 6337CPAN::Distribution, CPAN::Bundle, and CPAN::Author is still considered 6338beta and partially even alpha. In the following paragraphs only those 6339methods are documented that have proven useful over a longer time and 6340thus are unlikely to change. 6341 6342=over 4 6343 6344=item CPAN::Author::as_glimpse() 6345 6346Returns a one-line description of the author 6347 6348=item CPAN::Author::as_string() 6349 6350Returns a multi-line description of the author 6351 6352=item CPAN::Author::email() 6353 6354Returns the author's email address 6355 6356=item CPAN::Author::fullname() 6357 6358Returns the author's name 6359 6360=item CPAN::Author::name() 6361 6362An alias for fullname 6363 6364=item CPAN::Bundle::as_glimpse() 6365 6366Returns a one-line description of the bundle 6367 6368=item CPAN::Bundle::as_string() 6369 6370Returns a multi-line description of the bundle 6371 6372=item CPAN::Bundle::clean() 6373 6374Recursively runs the C<clean> method on all items contained in the bundle. 6375 6376=item CPAN::Bundle::contains() 6377 6378Returns a list of objects' IDs contained in a bundle. The associated 6379objects may be bundles, modules or distributions. 6380 6381=item CPAN::Bundle::force($method,@args) 6382 6383Forces CPAN to perform a task that normally would have failed. Force 6384takes as arguments a method name to be called and any number of 6385additional arguments that should be passed to the called method. The 6386internals of the object get the needed changes so that CPAN.pm does 6387not refuse to take the action. The C<force> is passed recursively to 6388all contained objects. 6389 6390=item CPAN::Bundle::get() 6391 6392Recursively runs the C<get> method on all items contained in the bundle 6393 6394=item CPAN::Bundle::inst_file() 6395 6396Returns the highest installed version of the bundle in either @INC or 6397C<$CPAN::Config->{cpan_home}>. Note that this is different from 6398CPAN::Module::inst_file. 6399 6400=item CPAN::Bundle::inst_version() 6401 6402Like CPAN::Bundle::inst_file, but returns the $VERSION 6403 6404=item CPAN::Bundle::uptodate() 6405 6406Returns 1 if the bundle itself and all its members are uptodate. 6407 6408=item CPAN::Bundle::install() 6409 6410Recursively runs the C<install> method on all items contained in the bundle 6411 6412=item CPAN::Bundle::make() 6413 6414Recursively runs the C<make> method on all items contained in the bundle 6415 6416=item CPAN::Bundle::readme() 6417 6418Recursively runs the C<readme> method on all items contained in the bundle 6419 6420=item CPAN::Bundle::test() 6421 6422Recursively runs the C<test> method on all items contained in the bundle 6423 6424=item CPAN::Distribution::as_glimpse() 6425 6426Returns a one-line description of the distribution 6427 6428=item CPAN::Distribution::as_string() 6429 6430Returns a multi-line description of the distribution 6431 6432=item CPAN::Distribution::clean() 6433 6434Changes to the directory where the distribution has been unpacked and 6435runs C<make clean> there. 6436 6437=item CPAN::Distribution::containsmods() 6438 6439Returns a list of IDs of modules contained in a distribution file. 6440Only works for distributions listed in the 02packages.details.txt.gz 6441file. This typically means that only the most recent version of a 6442distribution is covered. 6443 6444=item CPAN::Distribution::cvs_import() 6445 6446Changes to the directory where the distribution has been unpacked and 6447runs something like 6448 6449 cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version 6450 6451there. 6452 6453=item CPAN::Distribution::dir() 6454 6455Returns the directory into which this distribution has been unpacked. 6456 6457=item CPAN::Distribution::force($method,@args) 6458 6459Forces CPAN to perform a task that normally would have failed. Force 6460takes as arguments a method name to be called and any number of 6461additional arguments that should be passed to the called method. The 6462internals of the object get the needed changes so that CPAN.pm does 6463not refuse to take the action. 6464 6465=item CPAN::Distribution::get() 6466 6467Downloads the distribution from CPAN and unpacks it. Does nothing if 6468the distribution has already been downloaded and unpacked within the 6469current session. 6470 6471=item CPAN::Distribution::install() 6472 6473Changes to the directory where the distribution has been unpacked and 6474runs the external command C<make install> there. If C<make> has not 6475yet been run, it will be run first. A C<make test> will be issued in 6476any case and if this fails, the install will be canceled. The 6477cancellation can be avoided by letting C<force> run the C<install> for 6478you. 6479 6480=item CPAN::Distribution::isa_perl() 6481 6482Returns 1 if this distribution file seems to be a perl distribution. 6483Normally this is derived from the file name only, but the index from 6484CPAN can contain a hint to achieve a return value of true for other 6485filenames too. 6486 6487=item CPAN::Distribution::look() 6488 6489Changes to the directory where the distribution has been unpacked and 6490opens a subshell there. Exiting the subshell returns. 6491 6492=item CPAN::Distribution::make() 6493 6494First runs the C<get> method to make sure the distribution is 6495downloaded and unpacked. Changes to the directory where the 6496distribution has been unpacked and runs the external commands C<perl 6497Makefile.PL> and C<make> there. 6498 6499=item CPAN::Distribution::prereq_pm() 6500 6501Returns the hash reference that has been announced by a distribution 6502as the PREREQ_PM hash in the Makefile.PL. Note: works only after an 6503attempt has been made to C<make> the distribution. Returns undef 6504otherwise. 6505 6506=item CPAN::Distribution::readme() 6507 6508Downloads the README file associated with a distribution and runs it 6509through the pager specified in C<$CPAN::Config->{pager}>. 6510 6511=item CPAN::Distribution::test() 6512 6513Changes to the directory where the distribution has been unpacked and 6514runs C<make test> there. 6515 6516=item CPAN::Distribution::uptodate() 6517 6518Returns 1 if all the modules contained in the distribution are 6519uptodate. Relies on containsmods. 6520 6521=item CPAN::Index::force_reload() 6522 6523Forces a reload of all indices. 6524 6525=item CPAN::Index::reload() 6526 6527Reloads all indices if they have been read more than 6528C<$CPAN::Config->{index_expire}> days. 6529 6530=item CPAN::InfoObj::dump() 6531 6532CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution 6533inherit this method. It prints the data structure associated with an 6534object. Useful for debugging. Note: the data structure is considered 6535internal and thus subject to change without notice. 6536 6537=item CPAN::Module::as_glimpse() 6538 6539Returns a one-line description of the module 6540 6541=item CPAN::Module::as_string() 6542 6543Returns a multi-line description of the module 6544 6545=item CPAN::Module::clean() 6546 6547Runs a clean on the distribution associated with this module. 6548 6549=item CPAN::Module::cpan_file() 6550 6551Returns the filename on CPAN that is associated with the module. 6552 6553=item CPAN::Module::cpan_version() 6554 6555Returns the latest version of this module available on CPAN. 6556 6557=item CPAN::Module::cvs_import() 6558 6559Runs a cvs_import on the distribution associated with this module. 6560 6561=item CPAN::Module::description() 6562 6563Returns a 44 character description of this module. Only available for 6564modules listed in The Module List (CPAN/modules/00modlist.long.html 6565or 00modlist.long.txt.gz) 6566 6567=item CPAN::Module::force($method,@args) 6568 6569Forces CPAN to perform a task that normally would have failed. Force 6570takes as arguments a method name to be called and any number of 6571additional arguments that should be passed to the called method. The 6572internals of the object get the needed changes so that CPAN.pm does 6573not refuse to take the action. 6574 6575=item CPAN::Module::get() 6576 6577Runs a get on the distribution associated with this module. 6578 6579=item CPAN::Module::inst_file() 6580 6581Returns the filename of the module found in @INC. The first file found 6582is reported just like perl itself stops searching @INC when it finds a 6583module. 6584 6585=item CPAN::Module::inst_version() 6586 6587Returns the version number of the module in readable format. 6588 6589=item CPAN::Module::install() 6590 6591Runs an C<install> on the distribution associated with this module. 6592 6593=item CPAN::Module::look() 6594 6595Changes to the directory where the distribution associated with this 6596module has been unpacked and opens a subshell there. Exiting the 6597subshell returns. 6598 6599=item CPAN::Module::make() 6600 6601Runs a C<make> on the distribution associated with this module. 6602 6603=item CPAN::Module::manpage_headline() 6604 6605If module is installed, peeks into the module's manpage, reads the 6606headline and returns it. Moreover, if the module has been downloaded 6607within this session, does the equivalent on the downloaded module even 6608if it is not installed. 6609 6610=item CPAN::Module::readme() 6611 6612Runs a C<readme> on the distribution associated with this module. 6613 6614=item CPAN::Module::test() 6615 6616Runs a C<test> on the distribution associated with this module. 6617 6618=item CPAN::Module::uptodate() 6619 6620Returns 1 if the module is installed and up-to-date. 6621 6622=item CPAN::Module::userid() 6623 6624Returns the author's ID of the module. 6625 6626=back 6627 6628=head2 Cache Manager 6629 6630Currently the cache manager only keeps track of the build directory 6631($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that 6632deletes complete directories below C<build_dir> as soon as the size of 6633all directories there gets bigger than $CPAN::Config->{build_cache} 6634(in MB). The contents of this cache may be used for later 6635re-installations that you intend to do manually, but will never be 6636trusted by CPAN itself. This is due to the fact that the user might 6637use these directories for building modules on different architectures. 6638 6639There is another directory ($CPAN::Config->{keep_source_where}) where 6640the original distribution files are kept. This directory is not 6641covered by the cache manager and must be controlled by the user. If 6642you choose to have the same directory as build_dir and as 6643keep_source_where directory, then your sources will be deleted with 6644the same fifo mechanism. 6645 6646=head2 Bundles 6647 6648A bundle is just a perl module in the namespace Bundle:: that does not 6649define any functions or methods. It usually only contains documentation. 6650 6651It starts like a perl module with a package declaration and a $VERSION 6652variable. After that the pod section looks like any other pod with the 6653only difference being that I<one special pod section> exists starting with 6654(verbatim): 6655 6656 =head1 CONTENTS 6657 6658In this pod section each line obeys the format 6659 6660 Module_Name [Version_String] [- optional text] 6661 6662The only required part is the first field, the name of a module 6663(e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest 6664of the line is optional. The comment part is delimited by a dash just 6665as in the man page header. 6666 6667The distribution of a bundle should follow the same convention as 6668other distributions. 6669 6670Bundles are treated specially in the CPAN package. If you say 'install 6671Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all 6672the modules in the CONTENTS section of the pod. You can install your 6673own Bundles locally by placing a conformant Bundle file somewhere into 6674your @INC path. The autobundle() command which is available in the 6675shell interface does that for you by including all currently installed 6676modules in a snapshot bundle file. 6677 6678=head2 Prerequisites 6679 6680If you have a local mirror of CPAN and can access all files with 6681"file:" URLs, then you only need a perl better than perl5.003 to run 6682this module. Otherwise Net::FTP is strongly recommended. LWP may be 6683required for non-UNIX systems or if your nearest CPAN site is 6684associated with a URL that is not C<ftp:>. 6685 6686If you have neither Net::FTP nor LWP, there is a fallback mechanism 6687implemented for an external ftp command or for an external lynx 6688command. 6689 6690=head2 Finding packages and VERSION 6691 6692This module presumes that all packages on CPAN 6693 6694=over 2 6695 6696=item * 6697 6698declare their $VERSION variable in an easy to parse manner. This 6699prerequisite can hardly be relaxed because it consumes far too much 6700memory to load all packages into the running program just to determine 6701the $VERSION variable. Currently all programs that are dealing with 6702version use something like this 6703 6704 perl -MExtUtils::MakeMaker -le \ 6705 'print MM->parse_version(shift)' filename 6706 6707If you are author of a package and wonder if your $VERSION can be 6708parsed, please try the above method. 6709 6710=item * 6711 6712come as compressed or gzipped tarfiles or as zip files and contain a 6713Makefile.PL (well, we try to handle a bit more, but without much 6714enthusiasm). 6715 6716=back 6717 6718=head2 Debugging 6719 6720The debugging of this module is a bit complex, because we have 6721interferences of the software producing the indices on CPAN, of the 6722mirroring process on CPAN, of packaging, of configuration, of 6723synchronicity, and of bugs within CPAN.pm. 6724 6725For code debugging in interactive mode you can try "o debug" which 6726will list options for debugging the various parts of the code. You 6727should know that "o debug" has built-in completion support. 6728 6729For data debugging there is the C<dump> command which takes the same 6730arguments as make/test/install and outputs the object's Data::Dumper 6731dump. 6732 6733=head2 Floppy, Zip, Offline Mode 6734 6735CPAN.pm works nicely without network too. If you maintain machines 6736that are not networked at all, you should consider working with file: 6737URLs. Of course, you have to collect your modules somewhere first. So 6738you might use CPAN.pm to put together all you need on a networked 6739machine. Then copy the $CPAN::Config->{keep_source_where} (but not 6740$CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind 6741of a personal CPAN. CPAN.pm on the non-networked machines works nicely 6742with this floppy. See also below the paragraph about CD-ROM support. 6743 6744=head1 CONFIGURATION 6745 6746When the CPAN module is used for the first time, a configuration 6747dialog tries to determine a couple of site specific options. The 6748result of the dialog is stored in a hash reference C< $CPAN::Config > 6749in a file CPAN/Config.pm. 6750 6751The default values defined in the CPAN/Config.pm file can be 6752overridden in a user specific file: CPAN/MyConfig.pm. Such a file is 6753best placed in $HOME/.cpan/CPAN/MyConfig.pm, because $HOME/.cpan is 6754added to the search path of the CPAN module before the use() or 6755require() statements. 6756 6757The configuration dialog can be started any time later again by 6758issueing the command C< o conf init > in the CPAN shell. 6759 6760Currently the following keys in the hash reference $CPAN::Config are 6761defined: 6762 6763 build_cache size of cache for directories to build modules 6764 build_dir locally accessible directory to build modules 6765 index_expire after this many days refetch index files 6766 cache_metadata use serializer to cache metadata 6767 cpan_home local directory reserved for this package 6768 dontload_hash anonymous hash: modules in the keys will not be 6769 loaded by the CPAN::has_inst() routine 6770 gzip location of external program gzip 6771 histfile file to maintain history between sessions 6772 histsize maximum number of lines to keep in histfile 6773 inactivity_timeout breaks interactive Makefile.PLs after this 6774 many seconds inactivity. Set to 0 to never break. 6775 inhibit_startup_message 6776 if true, does not print the startup message 6777 keep_source_where directory in which to keep the source (if we do) 6778 make location of external make program 6779 make_arg arguments that should always be passed to 'make' 6780 make_install_arg same as make_arg for 'make install' 6781 makepl_arg arguments passed to 'perl Makefile.PL' 6782 pager location of external program more (or any pager) 6783 prerequisites_policy 6784 what to do if you are missing module prerequisites 6785 ('follow' automatically, 'ask' me, or 'ignore') 6786 proxy_user username for accessing an authenticating proxy 6787 proxy_pass password for accessing an authenticating proxy 6788 scan_cache controls scanning of cache ('atstart' or 'never') 6789 tar location of external program tar 6790 term_is_latin if true internal UTF-8 is translated to ISO-8859-1 6791 (and nonsense for characters outside latin range) 6792 unzip location of external program unzip 6793 urllist arrayref to nearby CPAN sites (or equivalent locations) 6794 wait_list arrayref to a wait server to try (See CPAN::WAIT) 6795 ftp_proxy, } the three usual variables for configuring 6796 http_proxy, } proxy requests. Both as CPAN::Config variables 6797 no_proxy } and as environment variables configurable. 6798 6799You can set and query each of these options interactively in the cpan 6800shell with the command set defined within the C<o conf> command: 6801 6802=over 2 6803 6804=item C<o conf E<lt>scalar optionE<gt>> 6805 6806prints the current value of the I<scalar option> 6807 6808=item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>> 6809 6810Sets the value of the I<scalar option> to I<value> 6811 6812=item C<o conf E<lt>list optionE<gt>> 6813 6814prints the current value of the I<list option> in MakeMaker's 6815neatvalue format. 6816 6817=item C<o conf E<lt>list optionE<gt> [shift|pop]> 6818 6819shifts or pops the array in the I<list option> variable 6820 6821=item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>> 6822 6823works like the corresponding perl commands. 6824 6825=back 6826 6827=head2 Note on urllist parameter's format 6828 6829urllist parameters are URLs according to RFC 1738. We do a little 6830guessing if your URL is not compliant, but if you have problems with 6831file URLs, please try the correct format. Either: 6832 6833 file://localhost/whatever/ftp/pub/CPAN/ 6834 6835or 6836 6837 file:///home/ftp/pub/CPAN/ 6838 6839=head2 urllist parameter has CD-ROM support 6840 6841The C<urllist> parameter of the configuration table contains a list of 6842URLs that are to be used for downloading. If the list contains any 6843C<file> URLs, CPAN always tries to get files from there first. This 6844feature is disabled for index files. So the recommendation for the 6845owner of a CD-ROM with CPAN contents is: include your local, possibly 6846outdated CD-ROM as a C<file> URL at the end of urllist, e.g. 6847 6848 o conf urllist push file://localhost/CDROM/CPAN 6849 6850CPAN.pm will then fetch the index files from one of the CPAN sites 6851that come at the beginning of urllist. It will later check for each 6852module if there is a local copy of the most recent version. 6853 6854Another peculiarity of urllist is that the site that we could 6855successfully fetch the last file from automatically gets a preference 6856token and is tried as the first site for the next request. So if you 6857add a new site at runtime it may happen that the previously preferred 6858site will be tried another time. This means that if you want to disallow 6859a site for the next transfer, it must be explicitly removed from 6860urllist. 6861 6862=head1 SECURITY 6863 6864There's no strong security layer in CPAN.pm. CPAN.pm helps you to 6865install foreign, unmasked, unsigned code on your machine. We compare 6866to a checksum that comes from the net just as the distribution file 6867itself. If somebody has managed to tamper with the distribution file, 6868they may have as well tampered with the CHECKSUMS file. Future 6869development will go towards strong authentication. 6870 6871=head1 EXPORT 6872 6873Most functions in package CPAN are exported per default. The reason 6874for this is that the primary use is intended for the cpan shell or for 6875one-liners. 6876 6877=head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES 6878 6879Populating a freshly installed perl with my favorite modules is pretty 6880easy if you maintain a private bundle definition file. To get a useful 6881blueprint of a bundle definition file, the command autobundle can be used 6882on the CPAN shell command line. This command writes a bundle definition 6883file for all modules that are installed for the currently running perl 6884interpreter. It's recommended to run this command only once and from then 6885on maintain the file manually under a private name, say 6886Bundle/my_bundle.pm. With a clever bundle file you can then simply say 6887 6888 cpan> install Bundle::my_bundle 6889 6890then answer a few questions and then go out for a coffee. 6891 6892Maintaining a bundle definition file means keeping track of two 6893things: dependencies and interactivity. CPAN.pm sometimes fails on 6894calculating dependencies because not all modules define all MakeMaker 6895attributes correctly, so a bundle definition file should specify 6896prerequisites as early as possible. On the other hand, it's a bit 6897annoying that many distributions need some interactive configuring. So 6898what I try to accomplish in my private bundle file is to have the 6899packages that need to be configured early in the file and the gentle 6900ones later, so I can go out after a few minutes and leave CPAN.pm 6901untended. 6902 6903=head1 WORKING WITH CPAN.pm BEHIND FIREWALLS 6904 6905Thanks to Graham Barr for contributing the following paragraphs about 6906the interaction between perl, and various firewall configurations. For 6907further informations on firewalls, it is recommended to consult the 6908documentation that comes with the ncftp program. If you are unable to 6909go through the firewall with a simple Perl setup, it is very likely 6910that you can configure ncftp so that it works for your firewall. 6911 6912=head2 Three basic types of firewalls 6913 6914Firewalls can be categorized into three basic types. 6915 6916=over 4 6917 6918=item http firewall 6919 6920This is where the firewall machine runs a web server and to access the 6921outside world you must do it via the web server. If you set environment 6922variables like http_proxy or ftp_proxy to a values beginning with http:// 6923or in your web browser you have to set proxy information then you know 6924you are running an http firewall. 6925 6926To access servers outside these types of firewalls with perl (even for 6927ftp) you will need to use LWP. 6928 6929=item ftp firewall 6930 6931This where the firewall machine runs an ftp server. This kind of 6932firewall will only let you access ftp servers outside the firewall. 6933This is usually done by connecting to the firewall with ftp, then 6934entering a username like "user@outside.host.com" 6935 6936To access servers outside these type of firewalls with perl you 6937will need to use Net::FTP. 6938 6939=item One way visibility 6940 6941I say one way visibility as these firewalls try to make themselves look 6942invisible to the users inside the firewall. An FTP data connection is 6943normally created by sending the remote server your IP address and then 6944listening for the connection. But the remote server will not be able to 6945connect to you because of the firewall. So for these types of firewall 6946FTP connections need to be done in a passive mode. 6947 6948There are two that I can think off. 6949 6950=over 4 6951 6952=item SOCKS 6953 6954If you are using a SOCKS firewall you will need to compile perl and link 6955it with the SOCKS library, this is what is normally called a 'socksified' 6956perl. With this executable you will be able to connect to servers outside 6957the firewall as if it is not there. 6958 6959=item IP Masquerade 6960 6961This is the firewall implemented in the Linux kernel, it allows you to 6962hide a complete network behind one IP address. With this firewall no 6963special compiling is needed as you can access hosts directly. 6964 6965For accessing ftp servers behind such firewalls you may need to set 6966the environment variable C<FTP_PASSIVE> to a true value, e.g. 6967 6968 env FTP_PASSIVE=1 perl -MCPAN -eshell 6969 6970or 6971 6972 perl -MCPAN -e '$ENV{FTP_PASSIVE} = 1; shell' 6973 6974 6975=back 6976 6977=back 6978 6979=head2 Configuring lynx or ncftp for going through a firewall 6980 6981If you can go through your firewall with e.g. lynx, presumably with a 6982command such as 6983 6984 /usr/local/bin/lynx -pscott:tiger 6985 6986then you would configure CPAN.pm with the command 6987 6988 o conf lynx "/usr/local/bin/lynx -pscott:tiger" 6989 6990That's all. Similarly for ncftp or ftp, you would configure something 6991like 6992 6993 o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg" 6994 6995Your mileage may vary... 6996 6997=head1 FAQ 6998 6999=over 4 7000 7001=item 1) 7002 7003I installed a new version of module X but CPAN keeps saying, 7004I have the old version installed 7005 7006Most probably you B<do> have the old version installed. This can 7007happen if a module installs itself into a different directory in the 7008@INC path than it was previously installed. This is not really a 7009CPAN.pm problem, you would have the same problem when installing the 7010module manually. The easiest way to prevent this behaviour is to add 7011the argument C<UNINST=1> to the C<make install> call, and that is why 7012many people add this argument permanently by configuring 7013 7014 o conf make_install_arg UNINST=1 7015 7016=item 2) 7017 7018So why is UNINST=1 not the default? 7019 7020Because there are people who have their precise expectations about who 7021may install where in the @INC path and who uses which @INC array. In 7022fine tuned environments C<UNINST=1> can cause damage. 7023 7024=item 3) 7025 7026I want to clean up my mess, and install a new perl along with 7027all modules I have. How do I go about it? 7028 7029Run the autobundle command for your old perl and optionally rename the 7030resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl 7031with the Configure option prefix, e.g. 7032 7033 ./Configure -Dprefix=/usr/local/perl-5.6.78.9 7034 7035Install the bundle file you produced in the first step with something like 7036 7037 cpan> install Bundle::mybundle 7038 7039and you're done. 7040 7041=item 4) 7042 7043When I install bundles or multiple modules with one command 7044there is too much output to keep track of. 7045 7046You may want to configure something like 7047 7048 o conf make_arg "| tee -ai /root/.cpan/logs/make.out" 7049 o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out" 7050 7051so that STDOUT is captured in a file for later inspection. 7052 7053 7054=item 5) 7055 7056I am not root, how can I install a module in a personal directory? 7057 7058You will most probably like something like this: 7059 7060 o conf makepl_arg "LIB=~/myperl/lib \ 7061 INSTALLMAN1DIR=~/myperl/man/man1 \ 7062 INSTALLMAN3DIR=~/myperl/man/man3" 7063 install Sybase::Sybperl 7064 7065You can make this setting permanent like all C<o conf> settings with 7066C<o conf commit>. 7067 7068You will have to add ~/myperl/man to the MANPATH environment variable 7069and also tell your perl programs to look into ~/myperl/lib, e.g. by 7070including 7071 7072 use lib "$ENV{HOME}/myperl/lib"; 7073 7074or setting the PERL5LIB environment variable. 7075 7076Another thing you should bear in mind is that the UNINST parameter 7077should never be set if you are not root. 7078 7079=item 6) 7080 7081How to get a package, unwrap it, and make a change before building it? 7082 7083 look Sybase::Sybperl 7084 7085=item 7) 7086 7087I installed a Bundle and had a couple of fails. When I 7088retried, everything resolved nicely. Can this be fixed to work 7089on first try? 7090 7091The reason for this is that CPAN does not know the dependencies of all 7092modules when it starts out. To decide about the additional items to 7093install, it just uses data found in the generated Makefile. An 7094undetected missing piece breaks the process. But it may well be that 7095your Bundle installs some prerequisite later than some depending item 7096and thus your second try is able to resolve everything. Please note, 7097CPAN.pm does not know the dependency tree in advance and cannot sort 7098the queue of things to install in a topologically correct order. It 7099resolves perfectly well IFF all modules declare the prerequisites 7100correctly with the PREREQ_PM attribute to MakeMaker. For bundles which 7101fail and you need to install often, it is recommended sort the Bundle 7102definition file manually. It is planned to improve the metadata 7103situation for dependencies on CPAN in general, but this will still 7104take some time. 7105 7106=item 8) 7107 7108In our intranet we have many modules for internal use. How 7109can I integrate these modules with CPAN.pm but without uploading 7110the modules to CPAN? 7111 7112Have a look at the CPAN::Site module. 7113 7114=item 9) 7115 7116When I run CPAN's shell, I get error msg about line 1 to 4, 7117setting meta input/output via the /etc/inputrc file. 7118 7119Some versions of readline are picky about capitalization in the 7120/etc/inputrc file and specifically RedHat 6.2 comes with a 7121/etc/inputrc that contains the word C<on> in lowercase. Change the 7122occurrences of C<on> to C<On> and the bug should disappear. 7123 7124=item 10) 7125 7126Some authors have strange characters in their names. 7127 7128Internally CPAN.pm uses the UTF-8 charset. If your terminal is 7129expecting ISO-8859-1 charset, a converter can be activated by setting 7130term_is_latin to a true value in your config file. One way of doing so 7131would be 7132 7133 cpan> ! $CPAN::Config->{term_is_latin}=1 7134 7135Extended support for converters will be made available as soon as perl 7136becomes stable with regard to charset issues. 7137 7138=back 7139 7140=head1 BUGS 7141 7142We should give coverage for B<all> of the CPAN and not just the PAUSE 7143part, right? In this discussion CPAN and PAUSE have become equal -- 7144but they are not. PAUSE is authors/, modules/ and scripts/. CPAN is 7145PAUSE plus the clpa/, doc/, misc/, ports/, and src/. 7146 7147Future development should be directed towards a better integration of 7148the other parts. 7149 7150If a Makefile.PL requires special customization of libraries, prompts 7151the user for special input, etc. then you may find CPAN is not able to 7152build the distribution. In that case, you should attempt the 7153traditional method of building a Perl module package from a shell. 7154 7155=head1 AUTHOR 7156 7157Andreas Koenig E<lt>andreas.koenig@anima.deE<gt> 7158 7159=head1 TRANSLATIONS 7160 7161Kawai,Takanori provides a Japanese translation of this manpage at 7162http://member.nifty.ne.jp/hippo2000/perltips/CPAN.htm 7163 7164=head1 SEE ALSO 7165 7166perl(1), CPAN::Nox(3) 7167 7168=cut 7169 7170