[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- 2 use strict; 3 package CPAN; 4 $CPAN::VERSION = '1.9205'; 5 $CPAN::VERSION = eval $CPAN::VERSION if $CPAN::VERSION =~ /_/; 6 7 use CPAN::HandleConfig; 8 use CPAN::Version; 9 use CPAN::Debug; 10 use CPAN::Queue; 11 use CPAN::Tarzip; 12 use CPAN::DeferedCode; 13 use Carp (); 14 use Config (); 15 use Cwd (); 16 use DirHandle (); 17 use Exporter (); 18 use ExtUtils::MakeMaker qw(prompt); # for some unknown reason, 19 # 5.005_04 does not work without 20 # this 21 use File::Basename (); 22 use File::Copy (); 23 use File::Find; 24 use File::Path (); 25 use File::Spec (); 26 use FileHandle (); 27 use Fcntl qw(:flock); 28 use Safe (); 29 use Sys::Hostname qw(hostname); 30 use Text::ParseWords (); 31 use Text::Wrap (); 32 33 sub find_perl (); 34 35 # we need to run chdir all over and we would get at wrong libraries 36 # there 37 BEGIN { 38 if (File::Spec->can("rel2abs")) { 39 for my $inc (@INC) { 40 $inc = File::Spec->rel2abs($inc) unless ref $inc; 41 } 42 } 43 } 44 no lib "."; 45 46 require Mac::BuildTools if $^O eq 'MacOS'; 47 $ENV{PERL5_CPAN_IS_RUNNING}=$$; 48 $ENV{PERL5_CPANPLUS_IS_RUNNING}=$$; # https://rt.cpan.org/Ticket/Display.html?id=23735 49 50 END { $CPAN::End++; &cleanup; } 51 52 $CPAN::Signal ||= 0; 53 $CPAN::Frontend ||= "CPAN::Shell"; 54 unless (@CPAN::Defaultsites) { 55 @CPAN::Defaultsites = map { 56 CPAN::URL->new(TEXT => $_, FROM => "DEF") 57 } 58 "http://www.perl.org/CPAN/", 59 "ftp://ftp.perl.org/pub/CPAN/"; 60 } 61 # $CPAN::iCwd (i for initial) is going to be initialized during find_perl 62 $CPAN::Perl ||= CPAN::find_perl(); 63 $CPAN::Defaultdocs ||= "http://search.cpan.org/perldoc?"; 64 $CPAN::Defaultrecent ||= "http://search.cpan.org/uploads.rdf"; 65 $CPAN::Defaultrecent ||= "http://cpan.uwinnipeg.ca/htdocs/cpan.xml"; 66 67 # our globals are getting a mess 68 use vars qw( 69 $AUTOLOAD 70 $Be_Silent 71 $CONFIG_DIRTY 72 $Defaultdocs 73 $Echo_readline 74 $Frontend 75 $GOTOSHELL 76 $HAS_USABLE 77 $Have_warned 78 $MAX_RECURSION 79 $META 80 $RUN_DEGRADED 81 $Signal 82 $SQLite 83 $Suppress_readline 84 $VERSION 85 $autoload_recursion 86 $term 87 @Defaultsites 88 @EXPORT 89 ); 90 91 $MAX_RECURSION = 32; 92 93 @CPAN::ISA = qw(CPAN::Debug Exporter); 94 95 # note that these functions live in CPAN::Shell and get executed via 96 # AUTOLOAD when called directly 97 @EXPORT = qw( 98 autobundle 99 bundle 100 clean 101 cvs_import 102 expand 103 force 104 fforce 105 get 106 install 107 install_tested 108 is_tested 109 make 110 mkmyconfig 111 notest 112 perldoc 113 readme 114 recent 115 recompile 116 report 117 shell 118 smoke 119 test 120 upgrade 121 ); 122 123 sub soft_chdir_with_alternatives ($); 124 125 { 126 $autoload_recursion ||= 0; 127 128 #-> sub CPAN::AUTOLOAD ; 129 sub AUTOLOAD { 130 $autoload_recursion++; 131 my($l) = $AUTOLOAD; 132 $l =~ s/.*:://; 133 if ($CPAN::Signal) { 134 warn "Refusing to autoload '$l' while signal pending"; 135 $autoload_recursion--; 136 return; 137 } 138 if ($autoload_recursion > 1) { 139 my $fullcommand = join " ", map { "'$_'" } $l, @_; 140 warn "Refusing to autoload $fullcommand in recursion\n"; 141 $autoload_recursion--; 142 return; 143 } 144 my(%export); 145 @export{@EXPORT} = ''; 146 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 147 if (exists $export{$l}) { 148 CPAN::Shell->$l(@_); 149 } else { 150 die(qq{Unknown CPAN command "$AUTOLOAD". }. 151 qq{Type ? for help.\n}); 152 } 153 $autoload_recursion--; 154 } 155 } 156 157 #-> sub CPAN::shell ; 158 sub shell { 159 my($self) = @_; 160 $Suppress_readline = ! -t STDIN unless defined $Suppress_readline; 161 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 162 163 my $oprompt = shift || CPAN::Prompt->new; 164 my $prompt = $oprompt; 165 my $commandline = shift || ""; 166 $CPAN::CurrentCommandId ||= 1; 167 168 local($^W) = 1; 169 unless ($Suppress_readline) { 170 require Term::ReadLine; 171 if (! $term 172 or 173 $term->ReadLine eq "Term::ReadLine::Stub" 174 ) { 175 $term = Term::ReadLine->new('CPAN Monitor'); 176 } 177 if ($term->ReadLine eq "Term::ReadLine::Gnu") { 178 my $attribs = $term->Attribs; 179 $attribs->{attempted_completion_function} = sub { 180 &CPAN::Complete::gnu_cpl; 181 } 182 } else { 183 $readline::rl_completion_function = 184 $readline::rl_completion_function = 'CPAN::Complete::cpl'; 185 } 186 if (my $histfile = $CPAN::Config->{'histfile'}) {{ 187 unless ($term->can("AddHistory")) { 188 $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n"); 189 last; 190 } 191 $META->readhist($term,$histfile); 192 }} 193 for ($CPAN::Config->{term_ornaments}) { # alias 194 local $Term::ReadLine::termcap_nowarn = 1; 195 $term->ornaments($_) if defined; 196 } 197 # $term->OUT is autoflushed anyway 198 my $odef = select STDERR; 199 $| = 1; 200 select STDOUT; 201 $| = 1; 202 select $odef; 203 } 204 205 $META->checklock(); 206 my @cwd = grep { defined $_ and length $_ } 207 CPAN::anycwd(), 208 File::Spec->can("tmpdir") ? File::Spec->tmpdir() : (), 209 File::Spec->rootdir(); 210 my $try_detect_readline; 211 $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term; 212 unless ($CPAN::Config->{inhibit_startup_message}) { 213 my $rl_avail = $Suppress_readline ? "suppressed" : 214 ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" : 215 "available (maybe install Bundle::CPAN or Bundle::CPANxxl?)"; 216 $CPAN::Frontend->myprint( 217 sprintf qq{ 218 cpan shell -- CPAN exploration and modules installation (v%s) 219 ReadLine support %s 220 221 }, 222 $CPAN::VERSION, 223 $rl_avail 224 ) 225 } 226 my($continuation) = ""; 227 my $last_term_ornaments; 228 SHELLCOMMAND: while () { 229 if ($Suppress_readline) { 230 if ($Echo_readline) { 231 $|=1; 232 } 233 print $prompt; 234 last SHELLCOMMAND unless defined ($_ = <> ); 235 if ($Echo_readline) { 236 # backdoor: I could not find a way to record sessions 237 print $_; 238 } 239 chomp; 240 } else { 241 last SHELLCOMMAND unless 242 defined ($_ = $term->readline($prompt, $commandline)); 243 } 244 $_ = "$continuation$_" if $continuation; 245 s/^\s+//; 246 next SHELLCOMMAND if /^$/; 247 s/^\s*\?\s*/help /; 248 if (/^(?:q(?:uit)?|bye|exit)$/i) { 249 last SHELLCOMMAND; 250 } elsif (s/\\$//s) { 251 chomp; 252 $continuation = $_; 253 $prompt = " > "; 254 } elsif (/^\!/) { 255 s/^\!//; 256 my($eval) = $_; 257 package CPAN::Eval; 258 use strict; 259 use vars qw($import_done); 260 CPAN->import(':DEFAULT') unless $import_done++; 261 CPAN->debug("eval[$eval]") if $CPAN::DEBUG; 262 eval($eval); 263 warn $@ if $@; 264 $continuation = ""; 265 $prompt = $oprompt; 266 } elsif (/./) { 267 my(@line); 268 eval { @line = Text::ParseWords::shellwords($_) }; 269 warn($@), next SHELLCOMMAND if $@; 270 warn("Text::Parsewords could not parse the line [$_]"), 271 next SHELLCOMMAND unless @line; 272 $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG; 273 my $command = shift @line; 274 eval { CPAN::Shell->$command(@line) }; 275 if ($@) { 276 my $err = "$@"; 277 if ($err =~ /\S/) { 278 require Carp; 279 require Dumpvalue; 280 my $dv = Dumpvalue->new(); 281 Carp::cluck(sprintf "Catching error: %s", $dv->stringify($err)); 282 } 283 } 284 if ($command =~ /^( 285 # classic commands 286 make 287 |test 288 |install 289 |clean 290 291 # pragmas for classic commands 292 |ff?orce 293 |notest 294 295 # compounds 296 |report 297 |smoke 298 |upgrade 299 )$/x) { 300 # only commands that tell us something about failed distros 301 CPAN::Shell->failed($CPAN::CurrentCommandId,1); 302 } 303 soft_chdir_with_alternatives(\@cwd); 304 $CPAN::Frontend->myprint("\n"); 305 $continuation = ""; 306 $CPAN::CurrentCommandId++; 307 $prompt = $oprompt; 308 } 309 } continue { 310 $commandline = ""; # I do want to be able to pass a default to 311 # shell, but on the second command I see no 312 # use in that 313 $Signal=0; 314 CPAN::Queue->nullify_queue; 315 if ($try_detect_readline) { 316 if ($CPAN::META->has_inst("Term::ReadLine::Gnu") 317 || 318 $CPAN::META->has_inst("Term::ReadLine::Perl") 319 ) { 320 delete $INC{"Term/ReadLine.pm"}; 321 my $redef = 0; 322 local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef); 323 require Term::ReadLine; 324 $CPAN::Frontend->myprint("\n$redef subroutines in ". 325 "Term::ReadLine redefined\n"); 326 $GOTOSHELL = 1; 327 } 328 } 329 if ($term and $term->can("ornaments")) { 330 for ($CPAN::Config->{term_ornaments}) { # alias 331 if (defined $_) { 332 if (not defined $last_term_ornaments 333 or $_ != $last_term_ornaments 334 ) { 335 local $Term::ReadLine::termcap_nowarn = 1; 336 $term->ornaments($_); 337 $last_term_ornaments = $_; 338 } 339 } else { 340 undef $last_term_ornaments; 341 } 342 } 343 } 344 for my $class (qw(Module Distribution)) { 345 # again unsafe meta access? 346 for my $dm (keys %{$CPAN::META->{readwrite}{"CPAN::$class"}}) { 347 next unless $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; 348 CPAN->debug("BUG: $class '$dm' was in command state, resetting"); 349 delete $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; 350 } 351 } 352 if ($GOTOSHELL) { 353 $GOTOSHELL = 0; # not too often 354 $META->savehist if $CPAN::term && $CPAN::term->can("GetHistory"); 355 @_ = ($oprompt,""); 356 goto &shell; 357 } 358 } 359 soft_chdir_with_alternatives(\@cwd); 360 } 361 362 #-> CPAN::soft_chdir_with_alternatives ; 363 sub soft_chdir_with_alternatives ($) { 364 my($cwd) = @_; 365 unless (@$cwd) { 366 my $root = File::Spec->rootdir(); 367 $CPAN::Frontend->mywarn(qq{Warning: no good directory to chdir to! 368 Trying '$root' as temporary haven. 369 }); 370 push @$cwd, $root; 371 } 372 while () { 373 if (chdir $cwd->[0]) { 374 return; 375 } else { 376 if (@$cwd>1) { 377 $CPAN::Frontend->mywarn(qq{Could not chdir to "$cwd->[0]": $! 378 Trying to chdir to "$cwd->[1]" instead. 379 }); 380 shift @$cwd; 381 } else { 382 $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd->[0]": $!}); 383 } 384 } 385 } 386 } 387 388 sub _flock { 389 my($fh,$mode) = @_; 390 if ($Config::Config{d_flock}) { 391 return flock $fh, $mode; 392 } elsif (!$Have_warned->{"d_flock"}++) { 393 $CPAN::Frontend->mywarn("Your OS does not support locking; continuing and ignoring all locking issues\n"); 394 $CPAN::Frontend->mysleep(5); 395 return 1; 396 } else { 397 return 1; 398 } 399 } 400 401 sub _yaml_module () { 402 my $yaml_module = $CPAN::Config->{yaml_module} || "YAML"; 403 if ( 404 $yaml_module ne "YAML" 405 && 406 !$CPAN::META->has_inst($yaml_module) 407 ) { 408 # $CPAN::Frontend->mywarn("'$yaml_module' not installed, falling back to 'YAML'\n"); 409 $yaml_module = "YAML"; 410 } 411 if ($yaml_module eq "YAML" 412 && 413 $CPAN::META->has_inst($yaml_module) 414 && 415 $YAML::VERSION < 0.60 416 && 417 !$Have_warned->{"YAML"}++ 418 ) { 419 $CPAN::Frontend->mywarn("Warning: YAML version '$YAML::VERSION' is too low, please upgrade!\n". 420 "I'll continue but problems are *very* likely to happen.\n" 421 ); 422 $CPAN::Frontend->mysleep(5); 423 } 424 return $yaml_module; 425 } 426 427 # CPAN::_yaml_loadfile 428 sub _yaml_loadfile { 429 my($self,$local_file) = @_; 430 return +[] unless -s $local_file; 431 my $yaml_module = _yaml_module; 432 if ($CPAN::META->has_inst($yaml_module)) { 433 # temporarly enable yaml code deserialisation 434 no strict 'refs'; 435 # 5.6.2 could not do the local() with the reference 436 local $YAML::LoadCode; 437 local $YAML::Syck::LoadCode; 438 ${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0; 439 440 my $code; 441 if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) { 442 my @yaml; 443 eval { @yaml = $code->($local_file); }; 444 if ($@) { 445 # this shall not be done by the frontend 446 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); 447 } 448 return \@yaml; 449 } elsif ($code = UNIVERSAL::can($yaml_module, "Load")) { 450 local *FH; 451 open FH, $local_file or die "Could not open '$local_file': $!"; 452 local $/; 453 my $ystream = <FH>; 454 my @yaml; 455 eval { @yaml = $code->($ystream); }; 456 if ($@) { 457 # this shall not be done by the frontend 458 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); 459 } 460 return \@yaml; 461 } 462 } else { 463 # this shall not be done by the frontend 464 die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "parse"); 465 } 466 return +[]; 467 } 468 469 # CPAN::_yaml_dumpfile 470 sub _yaml_dumpfile { 471 my($self,$local_file,@what) = @_; 472 my $yaml_module = _yaml_module; 473 if ($CPAN::META->has_inst($yaml_module)) { 474 my $code; 475 if (UNIVERSAL::isa($local_file, "FileHandle")) { 476 $code = UNIVERSAL::can($yaml_module, "Dump"); 477 eval { print $local_file $code->(@what) }; 478 } elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) { 479 eval { $code->($local_file,@what); }; 480 } elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) { 481 local *FH; 482 open FH, ">$local_file" or die "Could not open '$local_file': $!"; 483 print FH $code->(@what); 484 } 485 if ($@) { 486 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"dump",$@); 487 } 488 } else { 489 if (UNIVERSAL::isa($local_file, "FileHandle")) { 490 # I think this case does not justify a warning at all 491 } else { 492 die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "dump"); 493 } 494 } 495 } 496 497 sub _init_sqlite () { 498 unless ($CPAN::META->has_inst("CPAN::SQLite")) { 499 $CPAN::Frontend->mywarn(qq{CPAN::SQLite not installed, trying to work without\n}) 500 unless $Have_warned->{"CPAN::SQLite"}++; 501 return; 502 } 503 require CPAN::SQLite::META; # not needed since CVS version of 2006-12-17 504 $CPAN::SQLite ||= CPAN::SQLite::META->new($CPAN::META); 505 } 506 507 { 508 my $negative_cache = {}; 509 sub _sqlite_running { 510 if ($negative_cache->{time} && time < $negative_cache->{time} + 60) { 511 # need to cache the result, otherwise too slow 512 return $negative_cache->{fact}; 513 } else { 514 $negative_cache = {}; # reset 515 } 516 my $ret = $CPAN::Config->{use_sqlite} && ($CPAN::SQLite || _init_sqlite()); 517 return $ret if $ret; # fast anyway 518 $negative_cache->{time} = time; 519 return $negative_cache->{fact} = $ret; 520 } 521 } 522 523 package CPAN::CacheMgr; 524 use strict; 525 @CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN); 526 use File::Find; 527 528 package CPAN::FTP; 529 use strict; 530 use Fcntl qw(:flock); 531 use vars qw($connect_to_internet_ok $Ua $Thesite $ThesiteURL $Themethod); 532 @CPAN::FTP::ISA = qw(CPAN::Debug); 533 534 package CPAN::LWP::UserAgent; 535 use strict; 536 use vars qw(@ISA $USER $PASSWD $SETUPDONE); 537 # we delay requiring LWP::UserAgent and setting up inheritance until we need it 538 539 package CPAN::Complete; 540 use strict; 541 @CPAN::Complete::ISA = qw(CPAN::Debug); 542 # Q: where is the "How do I add a new command" HOWTO? 543 # A: svn diff -r 1048:1049 where andk added the report command 544 @CPAN::Complete::COMMANDS = sort qw( 545 ? ! a b d h i m o q r u 546 autobundle 547 bye 548 clean 549 cvs_import 550 dump 551 exit 552 failed 553 force 554 fforce 555 hosts 556 install 557 install_tested 558 is_tested 559 look 560 ls 561 make 562 mkmyconfig 563 notest 564 perldoc 565 quit 566 readme 567 recent 568 recompile 569 reload 570 report 571 reports 572 scripts 573 smoke 574 test 575 upgrade 576 ); 577 578 package CPAN::Index; 579 use strict; 580 use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03 $HAVE_REANIMATED); 581 @CPAN::Index::ISA = qw(CPAN::Debug); 582 $LAST_TIME ||= 0; 583 $DATE_OF_03 ||= 0; 584 # use constant PROTOCOL => "2.0"; # outcommented to avoid warning on upgrade from 1.57 585 sub PROTOCOL { 2.0 } 586 587 package CPAN::InfoObj; 588 use strict; 589 @CPAN::InfoObj::ISA = qw(CPAN::Debug); 590 591 package CPAN::Author; 592 use strict; 593 @CPAN::Author::ISA = qw(CPAN::InfoObj); 594 595 package CPAN::Distribution; 596 use strict; 597 @CPAN::Distribution::ISA = qw(CPAN::InfoObj); 598 599 package CPAN::Bundle; 600 use strict; 601 @CPAN::Bundle::ISA = qw(CPAN::Module); 602 603 package CPAN::Module; 604 use strict; 605 @CPAN::Module::ISA = qw(CPAN::InfoObj); 606 607 package CPAN::Exception::RecursiveDependency; 608 use strict; 609 use overload '""' => "as_string"; 610 611 # a module sees its distribution (no version) 612 # a distribution sees its prereqs (which are module names) (usually with versions) 613 # a bundle sees its module names and/or its distributions (no version) 614 615 sub new { 616 my($class) = shift; 617 my($deps) = shift; 618 my (@deps,%seen,$loop_starts_with); 619 DCHAIN: for my $dep (@$deps) { 620 push @deps, {name => $dep, display_as => $dep}; 621 if ($seen{$dep}++) { 622 $loop_starts_with = $dep; 623 last DCHAIN; 624 } 625 } 626 my $in_loop = 0; 627 for my $i (0..$#deps) { 628 my $x = $deps[$i]{name}; 629 $in_loop ||= $x eq $loop_starts_with; 630 my $xo = CPAN::Shell->expandany($x) or next; 631 if ($xo->isa("CPAN::Module")) { 632 my $have = $xo->inst_version || "N/A"; 633 my($want,$d,$want_type); 634 if ($i>0 and $d = $deps[$i-1]{name}) { 635 my $do = CPAN::Shell->expandany($d); 636 $want = $do->{prereq_pm}{requires}{$x}; 637 if (defined $want) { 638 $want_type = "requires: "; 639 } else { 640 $want = $do->{prereq_pm}{build_requires}{$x}; 641 if (defined $want) { 642 $want_type = "build_requires: "; 643 } else { 644 $want_type = "unknown status"; 645 $want = "???"; 646 } 647 } 648 } else { 649 $want = $xo->cpan_version; 650 $want_type = "want: "; 651 } 652 $deps[$i]{have} = $have; 653 $deps[$i]{want_type} = $want_type; 654 $deps[$i]{want} = $want; 655 $deps[$i]{display_as} = "$x (have: $have; $want_type$want)"; 656 } elsif ($xo->isa("CPAN::Distribution")) { 657 $deps[$i]{display_as} = $xo->pretty_id; 658 if ($in_loop) { 659 $xo->{make} = CPAN::Distrostatus->new("NO cannot resolve circular dependency"); 660 } else { 661 $xo->{make} = CPAN::Distrostatus->new("NO one dependency ($loop_starts_with) is a circular dependency"); 662 } 663 $xo->store_persistent_state; # otherwise I will not reach 664 # all involved parties for 665 # the next session 666 } 667 } 668 bless { deps => \@deps }, $class; 669 } 670 671 sub as_string { 672 my($self) = shift; 673 my $ret = "\nRecursive dependency detected:\n "; 674 $ret .= join("\n => ", map {$_->{display_as}} @{$self->{deps}}); 675 $ret .= ".\nCannot resolve.\n"; 676 $ret; 677 } 678 679 package CPAN::Exception::yaml_not_installed; 680 use strict; 681 use overload '""' => "as_string"; 682 683 sub new { 684 my($class,$module,$file,$during) = @_; 685 bless { module => $module, file => $file, during => $during }, $class; 686 } 687 688 sub as_string { 689 my($self) = shift; 690 "'$self->{module}' not installed, cannot $self->{during} '$self->{file}'\n"; 691 } 692 693 package CPAN::Exception::yaml_process_error; 694 use strict; 695 use overload '""' => "as_string"; 696 697 sub new { 698 my($class,$module,$file,$during,$error) = @_; 699 bless { module => $module, 700 file => $file, 701 during => $during, 702 error => $error }, $class; 703 } 704 705 sub as_string { 706 my($self) = shift; 707 if ($self->{during}) { 708 if ($self->{file}) { 709 if ($self->{module}) { 710 if ($self->{error}) { 711 return "Alert: While trying to '$self->{during}' YAML file\n". 712 " '$self->{file}'\n". 713 "with '$self->{module}' the following error was encountered:\n". 714 " $self->{error}\n"; 715 } else { 716 return "Alert: While trying to '$self->{during}' YAML file\n". 717 " '$self->{file}'\n". 718 "with '$self->{module}' some unknown error was encountered\n"; 719 } 720 } else { 721 return "Alert: While trying to '$self->{during}' YAML file\n". 722 " '$self->{file}'\n". 723 "some unknown error was encountered\n"; 724 } 725 } else { 726 return "Alert: While trying to '$self->{during}' some YAML file\n". 727 "some unknown error was encountered\n"; 728 } 729 } else { 730 return "Alert: unknown error encountered\n"; 731 } 732 } 733 734 package CPAN::Prompt; use overload '""' => "as_string"; 735 use vars qw($prompt); 736 $prompt = "cpan> "; 737 $CPAN::CurrentCommandId ||= 0; 738 sub new { 739 bless {}, shift; 740 } 741 sub as_string { 742 my $word = "cpan"; 743 unless ($CPAN::META->{LOCK}) { 744 $word = "nolock_cpan"; 745 } 746 if ($CPAN::Config->{commandnumber_in_prompt}) { 747 sprintf "$word\[%d]> ", $CPAN::CurrentCommandId; 748 } else { 749 "$word> "; 750 } 751 } 752 753 package CPAN::URL; use overload '""' => "as_string", fallback => 1; 754 # accessors: TEXT(the url string), FROM(DEF=>defaultlist,USER=>urllist), 755 # planned are things like age or quality 756 sub new { 757 my($class,%args) = @_; 758 bless { 759 %args 760 }, $class; 761 } 762 sub as_string { 763 my($self) = @_; 764 $self->text; 765 } 766 sub text { 767 my($self,$set) = @_; 768 if (defined $set) { 769 $self->{TEXT} = $set; 770 } 771 $self->{TEXT}; 772 } 773 774 package CPAN::Distrostatus; 775 use overload '""' => "as_string", 776 fallback => 1; 777 sub new { 778 my($class,$arg) = @_; 779 bless { 780 TEXT => $arg, 781 FAILED => substr($arg,0,2) eq "NO", 782 COMMANDID => $CPAN::CurrentCommandId, 783 TIME => time, 784 }, $class; 785 } 786 sub commandid { shift->{COMMANDID} } 787 sub failed { shift->{FAILED} } 788 sub text { 789 my($self,$set) = @_; 790 if (defined $set) { 791 $self->{TEXT} = $set; 792 } 793 $self->{TEXT}; 794 } 795 sub as_string { 796 my($self) = @_; 797 $self->text; 798 } 799 800 package CPAN::Shell; 801 use strict; 802 use vars qw( 803 $ADVANCED_QUERY 804 $AUTOLOAD 805 $COLOR_REGISTERED 806 $Help 807 $autoload_recursion 808 $reload 809 @ISA 810 ); 811 @CPAN::Shell::ISA = qw(CPAN::Debug); 812 $COLOR_REGISTERED ||= 0; 813 $Help = { 814 '?' => \"help", 815 '!' => "eval the rest of the line as perl", 816 a => "whois author", 817 autobundle => "wtite inventory into a bundle file", 818 b => "info about bundle", 819 bye => \"quit", 820 clean => "clean up a distribution's build directory", 821 # cvs_import 822 d => "info about a distribution", 823 # dump 824 exit => \"quit", 825 failed => "list all failed actions within current session", 826 fforce => "redo a command from scratch", 827 force => "redo a command", 828 h => \"help", 829 help => "overview over commands; 'help ...' explains specific commands", 830 hosts => "statistics about recently used hosts", 831 i => "info about authors/bundles/distributions/modules", 832 install => "install a distribution", 833 install_tested => "install all distributions tested OK", 834 is_tested => "list all distributions tested OK", 835 look => "open a subshell in a distribution's directory", 836 ls => "list distributions according to a glob", 837 m => "info about a module", 838 make => "make/build a distribution", 839 mkmyconfig => "write current config into a CPAN/MyConfig.pm file", 840 notest => "run a (usually install) command but leave out the test phase", 841 o => "'o conf ...' for config stuff; 'o debug ...' for debugging", 842 perldoc => "try to get a manpage for a module", 843 q => \"quit", 844 quit => "leave the cpan shell", 845 r => "review over upgradeable modules", 846 readme => "display the README of a distro woth a pager", 847 recent => "show recent uploads to the CPAN", 848 # recompile 849 reload => "'reload cpan' or 'reload index'", 850 report => "test a distribution and send a test report to cpantesters", 851 reports => "info about reported tests from cpantesters", 852 # scripts 853 # smoke 854 test => "test a distribution", 855 u => "display uninstalled modules", 856 upgrade => "combine 'r' command with immediate installation", 857 }; 858 { 859 $autoload_recursion ||= 0; 860 861 #-> sub CPAN::Shell::AUTOLOAD ; 862 sub AUTOLOAD { 863 $autoload_recursion++; 864 my($l) = $AUTOLOAD; 865 my $class = shift(@_); 866 # warn "autoload[$l] class[$class]"; 867 $l =~ s/.*:://; 868 if ($CPAN::Signal) { 869 warn "Refusing to autoload '$l' while signal pending"; 870 $autoload_recursion--; 871 return; 872 } 873 if ($autoload_recursion > 1) { 874 my $fullcommand = join " ", map { "'$_'" } $l, @_; 875 warn "Refusing to autoload $fullcommand in recursion\n"; 876 $autoload_recursion--; 877 return; 878 } 879 if ($l =~ /^w/) { 880 # XXX needs to be reconsidered 881 if ($CPAN::META->has_inst('CPAN::WAIT')) { 882 CPAN::WAIT->$l(@_); 883 } else { 884 $CPAN::Frontend->mywarn(qq{ 885 Commands starting with "w" require CPAN::WAIT to be installed. 886 Please consider installing CPAN::WAIT to use the fulltext index. 887 For this you just need to type 888 install CPAN::WAIT 889 }); 890 } 891 } else { 892 $CPAN::Frontend->mywarn(qq{Unknown shell command '$l'. }. 893 qq{Type ? for help. 894 }); 895 } 896 $autoload_recursion--; 897 } 898 } 899 900 package CPAN; 901 use strict; 902 903 $META ||= CPAN->new; # In case we re-eval ourselves we need the || 904 905 # from here on only subs. 906 ################################################################################ 907 908 sub _perl_fingerprint { 909 my($self,$other_fingerprint) = @_; 910 my $dll = eval {OS2::DLLname()}; 911 my $mtime_dll = 0; 912 if (defined $dll) { 913 $mtime_dll = (-f $dll ? (stat(_))[9] : '-1'); 914 } 915 my $mtime_perl = (-f CPAN::find_perl ? (stat(_))[9] : '-1'); 916 my $this_fingerprint = { 917 '$^X' => CPAN::find_perl, 918 sitearchexp => $Config::Config{sitearchexp}, 919 'mtime_$^X' => $mtime_perl, 920 'mtime_dll' => $mtime_dll, 921 }; 922 if ($other_fingerprint) { 923 if (exists $other_fingerprint->{'stat($^X)'}) { # repair fp from rev. 1.88_57 924 $other_fingerprint->{'mtime_$^X'} = $other_fingerprint->{'stat($^X)'}[9]; 925 } 926 # mandatory keys since 1.88_57 927 for my $key (qw($^X sitearchexp mtime_dll mtime_$^X)) { 928 return unless $other_fingerprint->{$key} eq $this_fingerprint->{$key}; 929 } 930 return 1; 931 } else { 932 return $this_fingerprint; 933 } 934 } 935 936 sub suggest_myconfig () { 937 SUGGEST_MYCONFIG: if(!$INC{'CPAN/MyConfig.pm'}) { 938 $CPAN::Frontend->myprint("You don't seem to have a user ". 939 "configuration (MyConfig.pm) yet.\n"); 940 my $new = CPAN::Shell::colorable_makemaker_prompt("Do you want to create a ". 941 "user configuration now? (Y/n)", 942 "yes"); 943 if($new =~ m{^y}i) { 944 CPAN::Shell->mkmyconfig(); 945 return &checklock; 946 } else { 947 $CPAN::Frontend->mydie("OK, giving up."); 948 } 949 } 950 } 951 952 #-> sub CPAN::all_objects ; 953 sub all_objects { 954 my($mgr,$class) = @_; 955 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 956 CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG; 957 CPAN::Index->reload; 958 values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok 959 } 960 961 # Called by shell, not in batch mode. In batch mode I see no risk in 962 # having many processes updating something as installations are 963 # continually checked at runtime. In shell mode I suspect it is 964 # unintentional to open more than one shell at a time 965 966 #-> sub CPAN::checklock ; 967 sub checklock { 968 my($self) = @_; 969 my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock"); 970 if (-f $lockfile && -M _ > 0) { 971 my $fh = FileHandle->new($lockfile) or 972 $CPAN::Frontend->mydie("Could not open lockfile '$lockfile': $!"); 973 my $otherpid = <$fh>; 974 my $otherhost = <$fh>; 975 $fh->close; 976 if (defined $otherpid && $otherpid) { 977 chomp $otherpid; 978 } 979 if (defined $otherhost && $otherhost) { 980 chomp $otherhost; 981 } 982 my $thishost = hostname(); 983 if (defined $otherhost && defined $thishost && 984 $otherhost ne '' && $thishost ne '' && 985 $otherhost ne $thishost) { 986 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile '$lockfile'\n". 987 "reports other host $otherhost and other ". 988 "process $otherpid.\n". 989 "Cannot proceed.\n")); 990 } elsif ($RUN_DEGRADED) { 991 $CPAN::Frontend->mywarn("Running in degraded mode (experimental)\n"); 992 } elsif (defined $otherpid && $otherpid) { 993 return if $$ == $otherpid; # should never happen 994 $CPAN::Frontend->mywarn( 995 qq{ 996 There seems to be running another CPAN process (pid $otherpid). Contacting... 997 }); 998 if (kill 0, $otherpid) { 999 $CPAN::Frontend->mywarn(qq{Other job is running.\n}); 1000 my($ans) = 1001 CPAN::Shell::colorable_makemaker_prompt 1002 (qq{Shall I try to run in degraded }. 1003 qq{mode? (Y/n)},"y"); 1004 if ($ans =~ /^y/i) { 1005 $CPAN::Frontend->mywarn("Running in degraded mode (experimental). 1006 Please report if something unexpected happens\n"); 1007 $RUN_DEGRADED = 1; 1008 for ($CPAN::Config) { 1009 # XXX 1010 # $_->{build_dir_reuse} = 0; # 2006-11-17 akoenig Why was that? 1011 $_->{commandnumber_in_prompt} = 0; # visibility 1012 $_->{histfile} = ""; # who should win otherwise? 1013 $_->{cache_metadata} = 0; # better would be a lock? 1014 $_->{use_sqlite} = 0; # better would be a write lock! 1015 } 1016 } else { 1017 $CPAN::Frontend->mydie(" 1018 You may want to kill the other job and delete the lockfile. On UNIX try: 1019 kill $otherpid 1020 rm $lockfile 1021 "); 1022 } 1023 } elsif (-w $lockfile) { 1024 my($ans) = 1025 CPAN::Shell::colorable_makemaker_prompt 1026 (qq{Other job not responding. Shall I overwrite }. 1027 qq{the lockfile '$lockfile'? (Y/n)},"y"); 1028 $CPAN::Frontend->myexit("Ok, bye\n") 1029 unless $ans =~ /^y/i; 1030 } else { 1031 Carp::croak( 1032 qq{Lockfile '$lockfile' not writeable by you. }. 1033 qq{Cannot proceed.\n}. 1034 qq{ On UNIX try:\n}. 1035 qq{ rm '$lockfile'\n}. 1036 qq{ and then rerun us.\n} 1037 ); 1038 } 1039 } else { 1040 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Found invalid lockfile ". 1041 "'$lockfile', please remove. Cannot proceed.\n")); 1042 } 1043 } 1044 my $dotcpan = $CPAN::Config->{cpan_home}; 1045 eval { File::Path::mkpath($dotcpan);}; 1046 if ($@) { 1047 # A special case at least for Jarkko. 1048 my $firsterror = $@; 1049 my $seconderror; 1050 my $symlinkcpan; 1051 if (-l $dotcpan) { 1052 $symlinkcpan = readlink $dotcpan; 1053 die "readlink $dotcpan failed: $!" unless defined $symlinkcpan; 1054 eval { File::Path::mkpath($symlinkcpan); }; 1055 if ($@) { 1056 $seconderror = $@; 1057 } else { 1058 $CPAN::Frontend->mywarn(qq{ 1059 Working directory $symlinkcpan created. 1060 }); 1061 } 1062 } 1063 unless (-d $dotcpan) { 1064 my $mess = qq{ 1065 Your configuration suggests "$dotcpan" as your 1066 CPAN.pm working directory. I could not create this directory due 1067 to this error: $firsterror\n}; 1068 $mess .= qq{ 1069 As "$dotcpan" is a symlink to "$symlinkcpan", 1070 I tried to create that, but I failed with this error: $seconderror 1071 } if $seconderror; 1072 $mess .= qq{ 1073 Please make sure the directory exists and is writable. 1074 }; 1075 $CPAN::Frontend->mywarn($mess); 1076 return suggest_myconfig; 1077 } 1078 } # $@ after eval mkpath $dotcpan 1079 if (0) { # to test what happens when a race condition occurs 1080 for (reverse 1..10) { 1081 print $_, "\n"; 1082 sleep 1; 1083 } 1084 } 1085 # locking 1086 if (!$RUN_DEGRADED && !$self->{LOCKFH}) { 1087 my $fh; 1088 unless ($fh = FileHandle->new("+>>$lockfile")) { 1089 if ($! =~ /Permission/) { 1090 $CPAN::Frontend->mywarn(qq{ 1091 1092 Your configuration suggests that CPAN.pm should use a working 1093 directory of 1094 $CPAN::Config->{cpan_home} 1095 Unfortunately we could not create the lock file 1096 $lockfile 1097 due to permission problems. 1098 1099 Please make sure that the configuration variable 1100 \$CPAN::Config->{cpan_home} 1101 points to a directory where you can write a .lock file. You can set 1102 this variable in either a CPAN/MyConfig.pm or a CPAN/Config.pm in your 1103 \@INC path; 1104 }); 1105 return suggest_myconfig; 1106 } 1107 } 1108 my $sleep = 1; 1109 while (!CPAN::_flock($fh, LOCK_EX|LOCK_NB)) { 1110 if ($sleep>10) { 1111 $CPAN::Frontend->mydie("Giving up\n"); 1112 } 1113 $CPAN::Frontend->mysleep($sleep++); 1114 $CPAN::Frontend->mywarn("Could not lock lockfile with flock: $!; retrying\n"); 1115 } 1116 1117 seek $fh, 0, 0; 1118 truncate $fh, 0; 1119 $fh->autoflush(1); 1120 $fh->print($$, "\n"); 1121 $fh->print(hostname(), "\n"); 1122 $self->{LOCK} = $lockfile; 1123 $self->{LOCKFH} = $fh; 1124 } 1125 $SIG{TERM} = sub { 1126 my $sig = shift; 1127 &cleanup; 1128 $CPAN::Frontend->mydie("Got SIG$sig, leaving"); 1129 }; 1130 $SIG{INT} = sub { 1131 # no blocks!!! 1132 my $sig = shift; 1133 &cleanup if $Signal; 1134 die "Got yet another signal" if $Signal > 1; 1135 $CPAN::Frontend->mydie("Got another SIG$sig") if $Signal; 1136 $CPAN::Frontend->mywarn("Caught SIG$sig, trying to continue\n"); 1137 $Signal++; 1138 }; 1139 1140 # From: Larry Wall <larry@wall.org> 1141 # Subject: Re: deprecating SIGDIE 1142 # To: perl5-porters@perl.org 1143 # Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT) 1144 # 1145 # The original intent of __DIE__ was only to allow you to substitute one 1146 # kind of death for another on an application-wide basis without respect 1147 # to whether you were in an eval or not. As a global backstop, it should 1148 # not be used any more lightly (or any more heavily :-) than class 1149 # UNIVERSAL. Any attempt to build a general exception model on it should 1150 # be politely squashed. Any bug that causes every eval {} to have to be 1151 # modified should be not so politely squashed. 1152 # 1153 # Those are my current opinions. It is also my optinion that polite 1154 # arguments degenerate to personal arguments far too frequently, and that 1155 # when they do, it's because both people wanted it to, or at least didn't 1156 # sufficiently want it not to. 1157 # 1158 # Larry 1159 1160 # global backstop to cleanup if we should really die 1161 $SIG{__DIE__} = \&cleanup; 1162 $self->debug("Signal handler set.") if $CPAN::DEBUG; 1163 } 1164 1165 #-> sub CPAN::DESTROY ; 1166 sub DESTROY { 1167 &cleanup; # need an eval? 1168 } 1169 1170 #-> sub CPAN::anycwd ; 1171 sub anycwd () { 1172 my $getcwd; 1173 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd'; 1174 CPAN->$getcwd(); 1175 } 1176 1177 #-> sub CPAN::cwd ; 1178 sub cwd {Cwd::cwd();} 1179 1180 #-> sub CPAN::getcwd ; 1181 sub getcwd {Cwd::getcwd();} 1182 1183 #-> sub CPAN::fastcwd ; 1184 sub fastcwd {Cwd::fastcwd();} 1185 1186 #-> sub CPAN::backtickcwd ; 1187 sub backtickcwd {my $cwd = `cwd`; chomp $cwd; $cwd} 1188 1189 #-> sub CPAN::find_perl ; 1190 sub find_perl () { 1191 my($perl) = File::Spec->file_name_is_absolute($^X) ? $^X : ""; 1192 my $pwd = $CPAN::iCwd = CPAN::anycwd(); 1193 my $candidate = File::Spec->catfile($pwd,$^X); 1194 $perl ||= $candidate if MM->maybe_command($candidate); 1195 1196 unless ($perl) { 1197 my ($component,$perl_name); 1198 DIST_PERLNAME: foreach $perl_name ($^X, 'perl', 'perl5', "perl$]") { 1199 PATH_COMPONENT: foreach $component (File::Spec->path(), 1200 $Config::Config{'binexp'}) { 1201 next unless defined($component) && $component; 1202 my($abs) = File::Spec->catfile($component,$perl_name); 1203 if (MM->maybe_command($abs)) { 1204 $perl = $abs; 1205 last DIST_PERLNAME; 1206 } 1207 } 1208 } 1209 } 1210 1211 return $perl; 1212 } 1213 1214 1215 #-> sub CPAN::exists ; 1216 sub exists { 1217 my($mgr,$class,$id) = @_; 1218 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 1219 CPAN::Index->reload; 1220 ### Carp::croak "exists called without class argument" unless $class; 1221 $id ||= ""; 1222 $id =~ s/:+/::/g if $class eq "CPAN::Module"; 1223 my $exists; 1224 if (CPAN::_sqlite_running) { 1225 $exists = (exists $META->{readonly}{$class}{$id} or 1226 $CPAN::SQLite->set($class, $id)); 1227 } else { 1228 $exists = exists $META->{readonly}{$class}{$id}; 1229 } 1230 $exists ||= exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok 1231 } 1232 1233 #-> sub CPAN::delete ; 1234 sub delete { 1235 my($mgr,$class,$id) = @_; 1236 delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok 1237 delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok 1238 } 1239 1240 #-> sub CPAN::has_usable 1241 # has_inst is sometimes too optimistic, we should replace it with this 1242 # has_usable whenever a case is given 1243 sub has_usable { 1244 my($self,$mod,$message) = @_; 1245 return 1 if $HAS_USABLE->{$mod}; 1246 my $has_inst = $self->has_inst($mod,$message); 1247 return unless $has_inst; 1248 my $usable; 1249 $usable = { 1250 LWP => [ # we frequently had "Can't locate object 1251 # method "new" via package "LWP::UserAgent" at 1252 # (eval 69) line 2006 1253 sub {require LWP}, 1254 sub {require LWP::UserAgent}, 1255 sub {require HTTP::Request}, 1256 sub {require URI::URL}, 1257 ], 1258 'Net::FTP' => [ 1259 sub {require Net::FTP}, 1260 sub {require Net::Config}, 1261 ], 1262 'File::HomeDir' => [ 1263 sub {require File::HomeDir; 1264 unless (CPAN::Version->vge(File::HomeDir::->VERSION, 0.52)) { 1265 for ("Will not use File::HomeDir, need 0.52\n") { 1266 $CPAN::Frontend->mywarn($_); 1267 die $_; 1268 } 1269 } 1270 }, 1271 ], 1272 'Archive::Tar' => [ 1273 sub {require Archive::Tar; 1274 unless (CPAN::Version->vge(Archive::Tar::->VERSION, 1.00)) { 1275 for ("Will not use Archive::Tar, need 1.00\n") { 1276 $CPAN::Frontend->mywarn($_); 1277 die $_; 1278 } 1279 } 1280 }, 1281 ], 1282 'File::Temp' => [ 1283 # XXX we should probably delete from 1284 # %INC too so we can load after we 1285 # installed a new enough version -- 1286 # I'm not sure. 1287 sub {require File::Temp; 1288 unless (CPAN::Version->vge(File::Temp::->VERSION,0.16)) { 1289 for ("Will not use File::Temp, need 0.16\n") { 1290 $CPAN::Frontend->mywarn($_); 1291 die $_; 1292 } 1293 } 1294 }, 1295 ] 1296 }; 1297 if ($usable->{$mod}) { 1298 for my $c (0..$#{$usable->{$mod}}) { 1299 my $code = $usable->{$mod}[$c]; 1300 my $ret = eval { &$code() }; 1301 $ret = "" unless defined $ret; 1302 if ($@) { 1303 # warn "DEBUG: c[$c]\$\@[$@]ret[$ret]"; 1304 return; 1305 } 1306 } 1307 } 1308 return $HAS_USABLE->{$mod} = 1; 1309 } 1310 1311 #-> sub CPAN::has_inst 1312 sub has_inst { 1313 my($self,$mod,$message) = @_; 1314 Carp::croak("CPAN->has_inst() called without an argument") 1315 unless defined $mod; 1316 my %dont = map { $_ => 1 } keys %{$CPAN::META->{dontload_hash}||{}}, 1317 keys %{$CPAN::Config->{dontload_hash}||{}}, 1318 @{$CPAN::Config->{dontload_list}||[]}; 1319 if (defined $message && $message eq "no" # afair only used by Nox 1320 || 1321 $dont{$mod} 1322 ) { 1323 $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok 1324 return 0; 1325 } 1326 my $file = $mod; 1327 my $obj; 1328 $file =~ s|::|/|g; 1329 $file .= ".pm"; 1330 if ($INC{$file}) { 1331 # checking %INC is wrong, because $INC{LWP} may be true 1332 # although $INC{"URI/URL.pm"} may have failed. But as 1333 # I really want to say "bla loaded OK", I have to somehow 1334 # cache results. 1335 ### warn "$file in %INC"; #debug 1336 return 1; 1337 } elsif (eval { require $file }) { 1338 # eval is good: if we haven't yet read the database it's 1339 # perfect and if we have installed the module in the meantime, 1340 # it tries again. The second require is only a NOOP returning 1341 # 1 if we had success, otherwise it's retrying 1342 1343 my $mtime = (stat $INC{$file})[9]; 1344 # privileged files loaded by has_inst; Note: we use $mtime 1345 # as a proxy for a checksum. 1346 $CPAN::Shell::reload->{$file} = $mtime; 1347 my $v = eval "\$$mod\::VERSION"; 1348 $v = $v ? " (v$v)" : ""; 1349 CPAN::Shell->optprint("load_module","CPAN: $mod loaded ok$v\n"); 1350 if ($mod eq "CPAN::WAIT") { 1351 push @CPAN::Shell::ISA, 'CPAN::WAIT'; 1352 } 1353 return 1; 1354 } elsif ($mod eq "Net::FTP") { 1355 $CPAN::Frontend->mywarn(qq{ 1356 Please, install Net::FTP as soon as possible. CPAN.pm installs it for you 1357 if you just type 1358 install Bundle::libnet 1359 1360 }) unless $Have_warned->{"Net::FTP"}++; 1361 $CPAN::Frontend->mysleep(3); 1362 } elsif ($mod eq "Digest::SHA") { 1363 if ($Have_warned->{"Digest::SHA"}++) { 1364 $CPAN::Frontend->mywarn(qq{CPAN: checksum security checks disabled }. 1365 qq{because Digest::SHA not installed.\n}); 1366 } else { 1367 $CPAN::Frontend->mywarn(qq{ 1368 CPAN: checksum security checks disabled because Digest::SHA not installed. 1369 Please consider installing the Digest::SHA module. 1370 1371 }); 1372 $CPAN::Frontend->mysleep(2); 1373 } 1374 } elsif ($mod eq "Module::Signature") { 1375 # NOT prefs_lookup, we are not a distro 1376 my $check_sigs = $CPAN::Config->{check_sigs}; 1377 if (not $check_sigs) { 1378 # they do not want us:-( 1379 } elsif (not $Have_warned->{"Module::Signature"}++) { 1380 # No point in complaining unless the user can 1381 # reasonably install and use it. 1382 if (eval { require Crypt::OpenPGP; 1 } || 1383 ( 1384 defined $CPAN::Config->{'gpg'} 1385 && 1386 $CPAN::Config->{'gpg'} =~ /\S/ 1387 ) 1388 ) { 1389 $CPAN::Frontend->mywarn(qq{ 1390 CPAN: Module::Signature security checks disabled because Module::Signature 1391 not installed. Please consider installing the Module::Signature module. 1392 You may also need to be able to connect over the Internet to the public 1393 keyservers like pgp.mit.edu (port 11371). 1394 1395 }); 1396 $CPAN::Frontend->mysleep(2); 1397 } 1398 } 1399 } else { 1400 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI 1401 } 1402 return 0; 1403 } 1404 1405 #-> sub CPAN::instance ; 1406 sub instance { 1407 my($mgr,$class,$id) = @_; 1408 CPAN::Index->reload; 1409 $id ||= ""; 1410 # unsafe meta access, ok? 1411 return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id}; 1412 $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id); 1413 } 1414 1415 #-> sub CPAN::new ; 1416 sub new { 1417 bless {}, shift; 1418 } 1419 1420 #-> sub CPAN::cleanup ; 1421 sub cleanup { 1422 # warn "cleanup called with arg[@_] End[$CPAN::End] Signal[$Signal]"; 1423 local $SIG{__DIE__} = ''; 1424 my($message) = @_; 1425 my $i = 0; 1426 my $ineval = 0; 1427 my($subroutine); 1428 while ((undef,undef,undef,$subroutine) = caller(++$i)) { 1429 $ineval = 1, last if 1430 $subroutine eq '(eval)'; 1431 } 1432 return if $ineval && !$CPAN::End; 1433 return unless defined $META->{LOCK}; 1434 return unless -f $META->{LOCK}; 1435 $META->savehist; 1436 close $META->{LOCKFH}; 1437 unlink $META->{LOCK}; 1438 # require Carp; 1439 # Carp::cluck("DEBUGGING"); 1440 if ( $CPAN::CONFIG_DIRTY ) { 1441 $CPAN::Frontend->mywarn("Warning: Configuration not saved.\n"); 1442 } 1443 $CPAN::Frontend->myprint("Lockfile removed.\n"); 1444 } 1445 1446 #-> sub CPAN::readhist 1447 sub readhist { 1448 my($self,$term,$histfile) = @_; 1449 my($fh) = FileHandle->new; 1450 open $fh, "<$histfile" or last; 1451 local $/ = "\n"; 1452 while (<$fh>) { 1453 chomp; 1454 $term->AddHistory($_); 1455 } 1456 close $fh; 1457 } 1458 1459 #-> sub CPAN::savehist 1460 sub savehist { 1461 my($self) = @_; 1462 my($histfile,$histsize); 1463 unless ($histfile = $CPAN::Config->{'histfile'}) { 1464 $CPAN::Frontend->mywarn("No history written (no histfile specified).\n"); 1465 return; 1466 } 1467 $histsize = $CPAN::Config->{'histsize'} || 100; 1468 if ($CPAN::term) { 1469 unless ($CPAN::term->can("GetHistory")) { 1470 $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n"); 1471 return; 1472 } 1473 } else { 1474 return; 1475 } 1476 my @h = $CPAN::term->GetHistory; 1477 splice @h, 0, @h-$histsize if @h>$histsize; 1478 my($fh) = FileHandle->new; 1479 open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!"); 1480 local $\ = local $, = "\n"; 1481 print $fh @h; 1482 close $fh; 1483 } 1484 1485 #-> sub CPAN::is_tested 1486 sub is_tested { 1487 my($self,$what,$when) = @_; 1488 unless ($what) { 1489 Carp::cluck("DEBUG: empty what"); 1490 return; 1491 } 1492 $self->{is_tested}{$what} = $when; 1493 } 1494 1495 #-> sub CPAN::is_installed 1496 # unsets the is_tested flag: as soon as the thing is installed, it is 1497 # not needed in set_perl5lib anymore 1498 sub is_installed { 1499 my($self,$what) = @_; 1500 delete $self->{is_tested}{$what}; 1501 } 1502 1503 sub _list_sorted_descending_is_tested { 1504 my($self) = @_; 1505 sort 1506 { ($self->{is_tested}{$b}||0) <=> ($self->{is_tested}{$a}||0) } 1507 keys %{$self->{is_tested}} 1508 } 1509 1510 #-> sub CPAN::set_perl5lib 1511 sub set_perl5lib { 1512 my($self,$for) = @_; 1513 unless ($for) { 1514 (undef,undef,undef,$for) = caller(1); 1515 $for =~ s/.*://; 1516 } 1517 $self->{is_tested} ||= {}; 1518 return unless %{$self->{is_tested}}; 1519 my $env = $ENV{PERL5LIB}; 1520 $env = $ENV{PERLLIB} unless defined $env; 1521 my @env; 1522 push @env, $env if defined $env and length $env; 1523 #my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}}; 1524 #$CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n"); 1525 1526 my @dirs = map {("$_/blib/arch", "$_/blib/lib")} $self->_list_sorted_descending_is_tested; 1527 if (@dirs < 12) { 1528 $CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB for '$for'\n"); 1529 } elsif (@dirs < 24) { 1530 my @d = map {my $cp = $_; 1531 $cp =~ s/^\Q$CPAN::Config->{build_dir}\E/%BUILDDIR%/; 1532 $cp 1533 } @dirs; 1534 $CPAN::Frontend->myprint("Prepending @d to PERL5LIB; ". 1535 "%BUILDDIR%=$CPAN::Config->{build_dir} ". 1536 "for '$for'\n" 1537 ); 1538 } else { 1539 my $cnt = keys %{$self->{is_tested}}; 1540 $CPAN::Frontend->myprint("Prepending blib/arch and blib/lib of ". 1541 "$cnt build dirs to PERL5LIB; ". 1542 "for '$for'\n" 1543 ); 1544 } 1545 1546 $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; 1547 } 1548 1549 package CPAN::CacheMgr; 1550 use strict; 1551 1552 #-> sub CPAN::CacheMgr::as_string ; 1553 sub as_string { 1554 eval { require Data::Dumper }; 1555 if ($@) { 1556 return shift->SUPER::as_string; 1557 } else { 1558 return Data::Dumper::Dumper(shift); 1559 } 1560 } 1561 1562 #-> sub CPAN::CacheMgr::cachesize ; 1563 sub cachesize { 1564 shift->{DU}; 1565 } 1566 1567 #-> sub CPAN::CacheMgr::tidyup ; 1568 sub tidyup { 1569 my($self) = @_; 1570 return unless $CPAN::META->{LOCK}; 1571 return unless -d $self->{ID}; 1572 my @toremove = grep { $self->{SIZE}{$_}==0 } @{$self->{FIFO}}; 1573 for my $current (0..$#toremove) { 1574 my $toremove = $toremove[$current]; 1575 $CPAN::Frontend->myprint(sprintf( 1576 "DEL(%d/%d): %s \n", 1577 $current+1, 1578 scalar @toremove, 1579 $toremove, 1580 ) 1581 ); 1582 return if $CPAN::Signal; 1583 $self->_clean_cache($toremove); 1584 return if $CPAN::Signal; 1585 } 1586 } 1587 1588 #-> sub CPAN::CacheMgr::dir ; 1589 sub dir { 1590 shift->{ID}; 1591 } 1592 1593 #-> sub CPAN::CacheMgr::entries ; 1594 sub entries { 1595 my($self,$dir) = @_; 1596 return unless defined $dir; 1597 $self->debug("reading dir[$dir]") if $CPAN::DEBUG; 1598 $dir ||= $self->{ID}; 1599 my($cwd) = CPAN::anycwd(); 1600 chdir $dir or Carp::croak("Can't chdir to $dir: $!"); 1601 my $dh = DirHandle->new(File::Spec->curdir) 1602 or Carp::croak("Couldn't opendir $dir: $!"); 1603 my(@entries); 1604 for ($dh->read) { 1605 next if $_ eq "." || $_ eq ".."; 1606 if (-f $_) { 1607 push @entries, File::Spec->catfile($dir,$_); 1608 } elsif (-d _) { 1609 push @entries, File::Spec->catdir($dir,$_); 1610 } else { 1611 $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n"); 1612 } 1613 } 1614 chdir $cwd or Carp::croak("Can't chdir to $cwd: $!"); 1615 sort { -M $a <=> -M $b} @entries; 1616 } 1617 1618 #-> sub CPAN::CacheMgr::disk_usage ; 1619 sub disk_usage { 1620 my($self,$dir,$fast) = @_; 1621 return if exists $self->{SIZE}{$dir}; 1622 return if $CPAN::Signal; 1623 my($Du) = 0; 1624 if (-e $dir) { 1625 if (-d $dir) { 1626 unless (-x $dir) { 1627 unless (chmod 0755, $dir) { 1628 $CPAN::Frontend->mywarn("I have neither the -x permission nor the ". 1629 "permission to change the permission; cannot ". 1630 "estimate disk usage of '$dir'\n"); 1631 $CPAN::Frontend->mysleep(5); 1632 return; 1633 } 1634 } 1635 } elsif (-f $dir) { 1636 # nothing to say, no matter what the permissions 1637 } 1638 } else { 1639 $CPAN::Frontend->mywarn("File or directory '$dir' has gone, ignoring\n"); 1640 return; 1641 } 1642 if ($fast) { 1643 $Du = 0; # placeholder 1644 } else { 1645 find( 1646 sub { 1647 $File::Find::prune++ if $CPAN::Signal; 1648 return if -l $_; 1649 if ($^O eq 'MacOS') { 1650 require Mac::Files; 1651 my $cat = Mac::Files::FSpGetCatInfo($_); 1652 $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen() if $cat; 1653 } else { 1654 if (-d _) { 1655 unless (-x _) { 1656 unless (chmod 0755, $_) { 1657 $CPAN::Frontend->mywarn("I have neither the -x permission nor ". 1658 "the permission to change the permission; ". 1659 "can only partially estimate disk usage ". 1660 "of '$_'\n"); 1661 $CPAN::Frontend->mysleep(5); 1662 return; 1663 } 1664 } 1665 } else { 1666 $Du += (-s _); 1667 } 1668 } 1669 }, 1670 $dir 1671 ); 1672 } 1673 return if $CPAN::Signal; 1674 $self->{SIZE}{$dir} = $Du/1024/1024; 1675 unshift @{$self->{FIFO}}, $dir; 1676 $self->debug("measured $dir is $Du") if $CPAN::DEBUG; 1677 $self->{DU} += $Du/1024/1024; 1678 $self->{DU}; 1679 } 1680 1681 #-> sub CPAN::CacheMgr::_clean_cache ; 1682 sub _clean_cache { 1683 my($self,$dir) = @_; 1684 return unless -e $dir; 1685 unless (File::Spec->canonpath(File::Basename::dirname($dir)) 1686 eq File::Spec->canonpath($CPAN::Config->{build_dir})) { 1687 $CPAN::Frontend->mywarn("Directory '$dir' not below $CPAN::Config->{build_dir}, ". 1688 "will not remove\n"); 1689 $CPAN::Frontend->mysleep(5); 1690 return; 1691 } 1692 $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}") 1693 if $CPAN::DEBUG; 1694 File::Path::rmtree($dir); 1695 my $id_deleted = 0; 1696 if ($dir !~ /\.yml$/ && -f "$dir.yml") { 1697 my $yaml_module = CPAN::_yaml_module; 1698 if ($CPAN::META->has_inst($yaml_module)) { 1699 my($peek_yaml) = eval { CPAN->_yaml_loadfile("$dir.yml"); }; 1700 if ($@) { 1701 $CPAN::Frontend->mywarn("(parse error on '$dir.yml' removing anyway)"); 1702 unlink "$dir.yml" or 1703 $CPAN::Frontend->mywarn("(Could not unlink '$dir.yml': $!)"); 1704 return; 1705 } elsif (my $id = $peek_yaml->[0]{distribution}{ID}) { 1706 $CPAN::META->delete("CPAN::Distribution", $id); 1707 1708 # XXX we should restore the state NOW, otherise this 1709 # distro does not exist until we read an index. BUG ALERT(?) 1710 1711 # $CPAN::Frontend->mywarn (" +++\n"); 1712 $id_deleted++; 1713 } 1714 } 1715 unlink "$dir.yml"; # may fail 1716 unless ($id_deleted) { 1717 CPAN->debug("no distro found associated with '$dir'"); 1718 } 1719 } 1720 $self->{DU} -= $self->{SIZE}{$dir}; 1721 delete $self->{SIZE}{$dir}; 1722 } 1723 1724 #-> sub CPAN::CacheMgr::new ; 1725 sub new { 1726 my $class = shift; 1727 my $time = time; 1728 my($debug,$t2); 1729 $debug = ""; 1730 my $self = { 1731 ID => $CPAN::Config->{build_dir}, 1732 MAX => $CPAN::Config->{'build_cache'}, 1733 SCAN => $CPAN::Config->{'scan_cache'} || 'atstart', 1734 DU => 0 1735 }; 1736 File::Path::mkpath($self->{ID}); 1737 my $dh = DirHandle->new($self->{ID}); 1738 bless $self, $class; 1739 $self->scan_cache; 1740 $t2 = time; 1741 $debug .= "timing of CacheMgr->new: ".($t2 - $time); 1742 $time = $t2; 1743 CPAN->debug($debug) if $CPAN::DEBUG; 1744 $self; 1745 } 1746 1747 #-> sub CPAN::CacheMgr::scan_cache ; 1748 sub scan_cache { 1749 my $self = shift; 1750 return if $self->{SCAN} eq 'never'; 1751 $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}") 1752 unless $self->{SCAN} eq 'atstart'; 1753 return unless $CPAN::META->{LOCK}; 1754 $CPAN::Frontend->myprint( 1755 sprintf("Scanning cache %s for sizes\n", 1756 $self->{ID})); 1757 my $e; 1758 my @entries = $self->entries($self->{ID}); 1759 my $i = 0; 1760 my $painted = 0; 1761 for $e (@entries) { 1762 my $symbol = "."; 1763 if ($self->{DU} > $self->{MAX}) { 1764 $symbol = "-"; 1765 $self->disk_usage($e,1); 1766 } else { 1767 $self->disk_usage($e); 1768 } 1769 $i++; 1770 while (($painted/76) < ($i/@entries)) { 1771 $CPAN::Frontend->myprint($symbol); 1772 $painted++; 1773 } 1774 return if $CPAN::Signal; 1775 } 1776 $CPAN::Frontend->myprint("DONE\n"); 1777 $self->tidyup; 1778 } 1779 1780 package CPAN::Shell; 1781 use strict; 1782 1783 #-> sub CPAN::Shell::h ; 1784 sub h { 1785 my($class,$about) = @_; 1786 if (defined $about) { 1787 my $help; 1788 if (exists $Help->{$about}) { 1789 if (ref $Help->{$about}) { # aliases 1790 $about = ${$Help->{$about}}; 1791 } 1792 $help = $Help->{$about}; 1793 } else { 1794 $help = "No help available"; 1795 } 1796 $CPAN::Frontend->myprint("$about\: $help\n"); 1797 } else { 1798 my $filler = " " x (80 - 28 - length($CPAN::VERSION)); 1799 $CPAN::Frontend->myprint(qq{ 1800 Display Information $filler (ver $CPAN::VERSION) 1801 command argument description 1802 a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules 1803 i WORD or /REGEXP/ about any of the above 1804 ls AUTHOR or GLOB about files in the author's directory 1805 (with WORD being a module, bundle or author name or a distribution 1806 name of the form AUTHOR/DISTRIBUTION) 1807 1808 Download, Test, Make, Install... 1809 get download clean make clean 1810 make make (implies get) look open subshell in dist directory 1811 test make test (implies make) readme display these README files 1812 install make install (implies test) perldoc display POD documentation 1813 1814 Upgrade 1815 r WORDs or /REGEXP/ or NONE report updates for some/matching/all modules 1816 upgrade WORDs or /REGEXP/ or NONE upgrade some/matching/all modules 1817 1818 Pragmas 1819 force CMD try hard to do command fforce CMD try harder 1820 notest CMD skip testing 1821 1822 Other 1823 h,? display this menu ! perl-code eval a perl command 1824 o conf [opt] set and query options q quit the cpan shell 1825 reload cpan load CPAN.pm again reload index load newer indices 1826 autobundle Snapshot recent latest CPAN uploads}); 1827 } 1828 } 1829 1830 *help = \&h; 1831 1832 #-> sub CPAN::Shell::a ; 1833 sub a { 1834 my($self,@arg) = @_; 1835 # authors are always UPPERCASE 1836 for (@arg) { 1837 $_ = uc $_ unless /=/; 1838 } 1839 $CPAN::Frontend->myprint($self->format_result('Author',@arg)); 1840 } 1841 1842 #-> sub CPAN::Shell::globls ; 1843 sub globls { 1844 my($self,$s,$pragmas) = @_; 1845 # ls is really very different, but we had it once as an ordinary 1846 # command in the Shell (upto rev. 321) and we could not handle 1847 # force well then 1848 my(@accept,@preexpand); 1849 if ($s =~ /[\*\?\/]/) { 1850 if ($CPAN::META->has_inst("Text::Glob")) { 1851 if (my($au,$pathglob) = $s =~ m|(.*?)/(.*)|) { 1852 my $rau = Text::Glob::glob_to_regex(uc $au); 1853 CPAN::Shell->debug("au[$au]pathglob[$pathglob]rau[$rau]") 1854 if $CPAN::DEBUG; 1855 push @preexpand, map { $_->id . "/" . $pathglob } 1856 CPAN::Shell->expand_by_method('CPAN::Author',['id'],"/$rau/"); 1857 } else { 1858 my $rau = Text::Glob::glob_to_regex(uc $s); 1859 push @preexpand, map { $_->id } 1860 CPAN::Shell->expand_by_method('CPAN::Author', 1861 ['id'], 1862 "/$rau/"); 1863 } 1864 } else { 1865 $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed"); 1866 } 1867 } else { 1868 push @preexpand, uc $s; 1869 } 1870 for (@preexpand) { 1871 unless (/^[A-Z0-9\-]+(\/|$)/i) { 1872 $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n"); 1873 next; 1874 } 1875 push @accept, $_; 1876 } 1877 my $silent = @accept>1; 1878 my $last_alpha = ""; 1879 my @results; 1880 for my $a (@accept) { 1881 my($author,$pathglob); 1882 if ($a =~ m|(.*?)/(.*)|) { 1883 my $a2 = $1; 1884 $pathglob = $2; 1885 $author = CPAN::Shell->expand_by_method('CPAN::Author', 1886 ['id'], 1887 $a2) 1888 or $CPAN::Frontend->mydie("No author found for $a2\n"); 1889 } else { 1890 $author = CPAN::Shell->expand_by_method('CPAN::Author', 1891 ['id'], 1892 $a) 1893 or $CPAN::Frontend->mydie("No author found for $a\n"); 1894 } 1895 if ($silent) { 1896 my $alpha = substr $author->id, 0, 1; 1897 my $ad; 1898 if ($alpha eq $last_alpha) { 1899 $ad = ""; 1900 } else { 1901 $ad = "[$alpha]"; 1902 $last_alpha = $alpha; 1903 } 1904 $CPAN::Frontend->myprint($ad); 1905 } 1906 for my $pragma (@$pragmas) { 1907 if ($author->can($pragma)) { 1908 $author->$pragma(); 1909 } 1910 } 1911 push @results, $author->ls($pathglob,$silent); # silent if 1912 # more than one 1913 # author 1914 for my $pragma (@$pragmas) { 1915 my $unpragma = "un$pragma"; 1916 if ($author->can($unpragma)) { 1917 $author->$unpragma(); 1918 } 1919 } 1920 } 1921 @results; 1922 } 1923 1924 #-> sub CPAN::Shell::local_bundles ; 1925 sub local_bundles { 1926 my($self,@which) = @_; 1927 my($incdir,$bdir,$dh); 1928 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { 1929 my @bbase = "Bundle"; 1930 while (my $bbase = shift @bbase) { 1931 $bdir = File::Spec->catdir($incdir,split /::/, $bbase); 1932 CPAN->debug("bdir[$bdir]\@bbase[@bbase]") if $CPAN::DEBUG; 1933 if ($dh = DirHandle->new($bdir)) { # may fail 1934 my($entry); 1935 for $entry ($dh->read) { 1936 next if $entry =~ /^\./; 1937 next unless $entry =~ /^\w+(\.pm)?(?!\n)\Z/; 1938 if (-d File::Spec->catdir($bdir,$entry)) { 1939 push @bbase, "$bbase\::$entry"; 1940 } else { 1941 next unless $entry =~ s/\.pm(?!\n)\Z//; 1942 $CPAN::META->instance('CPAN::Bundle',"$bbase\::$entry"); 1943 } 1944 } 1945 } 1946 } 1947 } 1948 } 1949 1950 #-> sub CPAN::Shell::b ; 1951 sub b { 1952 my($self,@which) = @_; 1953 CPAN->debug("which[@which]") if $CPAN::DEBUG; 1954 $self->local_bundles; 1955 $CPAN::Frontend->myprint($self->format_result('Bundle',@which)); 1956 } 1957 1958 #-> sub CPAN::Shell::d ; 1959 sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));} 1960 1961 #-> sub CPAN::Shell::m ; 1962 sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here 1963 my $self = shift; 1964 $CPAN::Frontend->myprint($self->format_result('Module',@_)); 1965 } 1966 1967 #-> sub CPAN::Shell::i ; 1968 sub i { 1969 my($self) = shift; 1970 my(@args) = @_; 1971 @args = '/./' unless @args; 1972 my(@result); 1973 for my $type (qw/Bundle Distribution Module/) { 1974 push @result, $self->expand($type,@args); 1975 } 1976 # Authors are always uppercase. 1977 push @result, $self->expand("Author", map { uc $_ } @args); 1978 1979 my $result = @result == 1 ? 1980 $result[0]->as_string : 1981 @result == 0 ? 1982 "No objects found of any type for argument @args\n" : 1983 join("", 1984 (map {$_->as_glimpse} @result), 1985 scalar @result, " items found\n", 1986 ); 1987 $CPAN::Frontend->myprint($result); 1988 } 1989 1990 #-> sub CPAN::Shell::o ; 1991 1992 # CPAN::Shell::o and CPAN::HandleConfig::edit are closely related. 'o 1993 # conf' calls through to CPAN::HandleConfig::edit. 'o conf' should 1994 # probably have been called 'set' and 'o debug' maybe 'set debug' or 1995 # 'debug'; 'o conf ARGS' calls ->edit in CPAN/HandleConfig.pm 1996 sub o { 1997 my($self,$o_type,@o_what) = @_; 1998 $o_type ||= ""; 1999 CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n"); 2000 if ($o_type eq 'conf') { 2001 my($cfilter); 2002 ($cfilter) = $o_what[0] =~ m|^/(.*)/$| if @o_what; 2003 if (!@o_what or $cfilter) { # print all things, "o conf" 2004 $cfilter ||= ""; 2005 my $qrfilter = eval 'qr/$cfilter/'; 2006 my($k,$v); 2007 $CPAN::Frontend->myprint("\$CPAN::Config options from "); 2008 my @from; 2009 if (exists $INC{'CPAN/Config.pm'}) { 2010 push @from, $INC{'CPAN/Config.pm'}; 2011 } 2012 if (exists $INC{'CPAN/MyConfig.pm'}) { 2013 push @from, $INC{'CPAN/MyConfig.pm'}; 2014 } 2015 $CPAN::Frontend->myprint(join " and ", map {"'$_'"} @from); 2016 $CPAN::Frontend->myprint(":\n"); 2017 for $k (sort keys %CPAN::HandleConfig::can) { 2018 next unless $k =~ /$qrfilter/; 2019 $v = $CPAN::HandleConfig::can{$k}; 2020 $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v); 2021 } 2022 $CPAN::Frontend->myprint("\n"); 2023 for $k (sort keys %CPAN::HandleConfig::keys) { 2024 next unless $k =~ /$qrfilter/; 2025 CPAN::HandleConfig->prettyprint($k); 2026 } 2027 $CPAN::Frontend->myprint("\n"); 2028 } else { 2029 if (CPAN::HandleConfig->edit(@o_what)) { 2030 } else { 2031 $CPAN::Frontend->myprint(qq{Type 'o conf' to view all configuration }. 2032 qq{items\n\n}); 2033 } 2034 } 2035 } elsif ($o_type eq 'debug') { 2036 my(%valid); 2037 @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i; 2038 if (@o_what) { 2039 while (@o_what) { 2040 my($what) = shift @o_what; 2041 if ($what =~ s/^-// && exists $CPAN::DEBUG{$what}) { 2042 $CPAN::DEBUG &= $CPAN::DEBUG ^ $CPAN::DEBUG{$what}; 2043 next; 2044 } 2045 if ( exists $CPAN::DEBUG{$what} ) { 2046 $CPAN::DEBUG |= $CPAN::DEBUG{$what}; 2047 } elsif ($what =~ /^\d/) { 2048 $CPAN::DEBUG = $what; 2049 } elsif (lc $what eq 'all') { 2050 my($max) = 0; 2051 for (values %CPAN::DEBUG) { 2052 $max += $_; 2053 } 2054 $CPAN::DEBUG = $max; 2055 } else { 2056 my($known) = 0; 2057 for (keys %CPAN::DEBUG) { 2058 next unless lc($_) eq lc($what); 2059 $CPAN::DEBUG |= $CPAN::DEBUG{$_}; 2060 $known = 1; 2061 } 2062 $CPAN::Frontend->myprint("unknown argument [$what]\n") 2063 unless $known; 2064 } 2065 } 2066 } else { 2067 my $raw = "Valid options for debug are ". 2068 join(", ",sort(keys %CPAN::DEBUG), 'all'). 2069 qq{ or a number. Completion works on the options. }. 2070 qq{Case is ignored.}; 2071 require Text::Wrap; 2072 $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw)); 2073 $CPAN::Frontend->myprint("\n\n"); 2074 } 2075 if ($CPAN::DEBUG) { 2076 $CPAN::Frontend->myprint("Options set for debugging ($CPAN::DEBUG):\n"); 2077 my($k,$v); 2078 for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) { 2079 $v = $CPAN::DEBUG{$k}; 2080 $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v) 2081 if $v & $CPAN::DEBUG; 2082 } 2083 } else { 2084 $CPAN::Frontend->myprint("Debugging turned off completely.\n"); 2085 } 2086 } else { 2087 $CPAN::Frontend->myprint(qq{ 2088 Known options: 2089 conf set or get configuration variables 2090 debug set or get debugging options 2091 }); 2092 } 2093 } 2094 2095 # CPAN::Shell::paintdots_onreload 2096 sub paintdots_onreload { 2097 my($ref) = shift; 2098 sub { 2099 if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) { 2100 my($subr) = $1; 2101 ++$$ref; 2102 local($|) = 1; 2103 # $CPAN::Frontend->myprint(".($subr)"); 2104 $CPAN::Frontend->myprint("."); 2105 if ($subr =~ /\bshell\b/i) { 2106 # warn "debug[$_[0]]"; 2107 2108 # It would be nice if we could detect that a 2109 # subroutine has actually changed, but for now we 2110 # practically always set the GOTOSHELL global 2111 2112 $CPAN::GOTOSHELL=1; 2113 } 2114 return; 2115 } 2116 warn @_; 2117 }; 2118 } 2119 2120 #-> sub CPAN::Shell::hosts ; 2121 sub hosts { 2122 my($self) = @_; 2123 my $fullstats = CPAN::FTP->_ftp_statistics(); 2124 my $history = $fullstats->{history} || []; 2125 my %S; # statistics 2126 while (my $last = pop @$history) { 2127 my $attempts = $last->{attempts} or next; 2128 my $start; 2129 if (@$attempts) { 2130 $start = $attempts->[-1]{start}; 2131 if ($#$attempts > 0) { 2132 for my $i (0..$#$attempts-1) { 2133 my $url = $attempts->[$i]{url} or next; 2134 $S{no}{$url}++; 2135 } 2136 } 2137 } else { 2138 $start = $last->{start}; 2139 } 2140 next unless $last->{thesiteurl}; # C-C? bad filenames? 2141 $S{start} = $start; 2142 $S{end} ||= $last->{end}; 2143 my $dltime = $last->{end} - $start; 2144 my $dlsize = $last->{filesize} || 0; 2145 my $url = ref $last->{thesiteurl} ? $last->{thesiteurl}->text : $last->{thesiteurl}; 2146 my $s = $S{ok}{$url} ||= {}; 2147 $s->{n}++; 2148 $s->{dlsize} ||= 0; 2149 $s->{dlsize} += $dlsize/1024; 2150 $s->{dltime} ||= 0; 2151 $s->{dltime} += $dltime; 2152 } 2153 my $res; 2154 for my $url (keys %{$S{ok}}) { 2155 next if $S{ok}{$url}{dltime} == 0; # div by zero 2156 push @{$res->{ok}}, [@{$S{ok}{$url}}{qw(n dlsize dltime)}, 2157 $S{ok}{$url}{dlsize}/$S{ok}{$url}{dltime}, 2158 $url, 2159 ]; 2160 } 2161 for my $url (keys %{$S{no}}) { 2162 push @{$res->{no}}, [$S{no}{$url}, 2163 $url, 2164 ]; 2165 } 2166 my $R = ""; # report 2167 if ($S{start} && $S{end}) { 2168 $R .= sprintf "Log starts: %s\n", $S{start} ? scalar(localtime $S{start}) : "unknown"; 2169 $R .= sprintf "Log ends : %s\n", $S{end} ? scalar(localtime $S{end}) : "unknown"; 2170 } 2171 if ($res->{ok} && @{$res->{ok}}) { 2172 $R .= sprintf "\nSuccessful downloads: 2173 N kB secs kB/s url\n"; 2174 my $i = 20; 2175 for (sort { $b->[3] <=> $a->[3] } @{$res->{ok}}) { 2176 $R .= sprintf "%4d %8d %5d %9.1f %s\n", @$_; 2177 last if --$i<=0; 2178 } 2179 } 2180 if ($res->{no} && @{$res->{no}}) { 2181 $R .= sprintf "\nUnsuccessful downloads:\n"; 2182 my $i = 20; 2183 for (sort { $b->[0] <=> $a->[0] } @{$res->{no}}) { 2184 $R .= sprintf "%4d %s\n", @$_; 2185 last if --$i<=0; 2186 } 2187 } 2188 $CPAN::Frontend->myprint($R); 2189 } 2190 2191 #-> sub CPAN::Shell::reload ; 2192 sub reload { 2193 my($self,$command,@arg) = @_; 2194 $command ||= ""; 2195 $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG; 2196 if ($command =~ /^cpan$/i) { 2197 my $redef = 0; 2198 chdir $CPAN::iCwd if $CPAN::iCwd; # may fail 2199 my $failed; 2200 my @relo = ( 2201 "CPAN.pm", 2202 "CPAN/Debug.pm", 2203 "CPAN/FirstTime.pm", 2204 "CPAN/HandleConfig.pm", 2205 "CPAN/Kwalify.pm", 2206 "CPAN/Queue.pm", 2207 "CPAN/Reporter/Config.pm", 2208 "CPAN/Reporter/History.pm", 2209 "CPAN/Reporter.pm", 2210 "CPAN/SQLite.pm", 2211 "CPAN/Tarzip.pm", 2212 "CPAN/Version.pm", 2213 ); 2214 MFILE: for my $f (@relo) { 2215 next unless exists $INC{$f}; 2216 my $p = $f; 2217 $p =~ s/\.pm$//; 2218 $p =~ s|/|::|g; 2219 $CPAN::Frontend->myprint("($p"); 2220 local($SIG{__WARN__}) = paintdots_onreload(\$redef); 2221 $self->_reload_this($f) or $failed++; 2222 my $v = eval "$p\::->VERSION"; 2223 $CPAN::Frontend->myprint("v$v)"); 2224 } 2225 $CPAN::Frontend->myprint("\n$redef subroutines redefined\n"); 2226 if ($failed) { 2227 my $errors = $failed == 1 ? "error" : "errors"; 2228 $CPAN::Frontend->mywarn("\n$failed $errors during reload. You better quit ". 2229 "this session.\n"); 2230 } 2231 } elsif ($command =~ /^index$/i) { 2232 CPAN::Index->force_reload; 2233 } else { 2234 $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN modules 2235 index re-reads the index files\n}); 2236 } 2237 } 2238 2239 # reload means only load again what we have loaded before 2240 #-> sub CPAN::Shell::_reload_this ; 2241 sub _reload_this { 2242 my($self,$f,$args) = @_; 2243 CPAN->debug("f[$f]") if $CPAN::DEBUG; 2244 return 1 unless $INC{$f}; # we never loaded this, so we do not 2245 # reload but say OK 2246 my $pwd = CPAN::anycwd(); 2247 CPAN->debug("pwd[$pwd]") if $CPAN::DEBUG; 2248 my($file); 2249 for my $inc (@INC) { 2250 $file = File::Spec->catfile($inc,split /\//, $f); 2251 last if -f $file; 2252 $file = ""; 2253 } 2254 CPAN->debug("file[$file]") if $CPAN::DEBUG; 2255 my @inc = @INC; 2256 unless ($file && -f $file) { 2257 # this thingie is not in the INC path, maybe CPAN/MyConfig.pm? 2258 $file = $INC{$f}; 2259 unless (CPAN->has_inst("File::Basename")) { 2260 @inc = File::Basename::dirname($file); 2261 } else { 2262 # do we ever need this? 2263 @inc = substr($file,0,-length($f)-1); # bring in back to me! 2264 } 2265 } 2266 CPAN->debug("file[$file]inc[@inc]") if $CPAN::DEBUG; 2267 unless (-f $file) { 2268 $CPAN::Frontend->mywarn("Found no file to reload for '$f'\n"); 2269 return; 2270 } 2271 my $mtime = (stat $file)[9]; 2272 if ($reload->{$f}) { 2273 } elsif ($^T < $mtime) { 2274 # since we started the file has changed, force it to be reloaded 2275 $reload->{$f} = -1; 2276 } else { 2277 $reload->{$f} = $mtime; 2278 } 2279 my $must_reload = $mtime != $reload->{$f}; 2280 $args ||= {}; 2281 $must_reload ||= $args->{reloforce}; # o conf defaults needs this 2282 if ($must_reload) { 2283 my $fh = FileHandle->new($file) or 2284 $CPAN::Frontend->mydie("Could not open $file: $!"); 2285 local($/); 2286 local $^W = 1; 2287 my $content = <$fh>; 2288 CPAN->debug(sprintf("reload file[%s] content[%s...]",$file,substr($content,0,128))) 2289 if $CPAN::DEBUG; 2290 delete $INC{$f}; 2291 local @INC = @inc; 2292 eval "require '$f'"; 2293 if ($@) { 2294 warn $@; 2295 return; 2296 } 2297 $reload->{$f} = $mtime; 2298 } else { 2299 $CPAN::Frontend->myprint("__unchanged__"); 2300 } 2301 return 1; 2302 } 2303 2304 #-> sub CPAN::Shell::mkmyconfig ; 2305 sub mkmyconfig { 2306 my($self, $cpanpm, %args) = @_; 2307 require CPAN::FirstTime; 2308 my $home = CPAN::HandleConfig::home; 2309 $cpanpm = $INC{'CPAN/MyConfig.pm'} || 2310 File::Spec->catfile(split /\//, "$home/.cpan/CPAN/MyConfig.pm"); 2311 File::Path::mkpath(File::Basename::dirname($cpanpm)) unless -e $cpanpm; 2312 CPAN::HandleConfig::require_myconfig_or_config; 2313 $CPAN::Config ||= {}; 2314 $CPAN::Config = { 2315 %$CPAN::Config, 2316 build_dir => undef, 2317 cpan_home => undef, 2318 keep_source_where => undef, 2319 histfile => undef, 2320 }; 2321 CPAN::FirstTime::init($cpanpm, %args); 2322 } 2323 2324 #-> sub CPAN::Shell::_binary_extensions ; 2325 sub _binary_extensions { 2326 my($self) = shift @_; 2327 my(@result,$module,%seen,%need,$headerdone); 2328 for $module ($self->expand('Module','/./')) { 2329 my $file = $module->cpan_file; 2330 next if $file eq "N/A"; 2331 next if $file =~ /^Contact Author/; 2332 my $dist = $CPAN::META->instance('CPAN::Distribution',$file); 2333 next if $dist->isa_perl; 2334 next unless $module->xs_file; 2335 local($|) = 1; 2336 $CPAN::Frontend->myprint("."); 2337 push @result, $module; 2338 } 2339 # print join " | ", @result; 2340 $CPAN::Frontend->myprint("\n"); 2341 return @result; 2342 } 2343 2344 #-> sub CPAN::Shell::recompile ; 2345 sub recompile { 2346 my($self) = shift @_; 2347 my($module,@module,$cpan_file,%dist); 2348 @module = $self->_binary_extensions(); 2349 for $module (@module) { # we force now and compile later, so we 2350 # don't do it twice 2351 $cpan_file = $module->cpan_file; 2352 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 2353 $pack->force; 2354 $dist{$cpan_file}++; 2355 } 2356 for $cpan_file (sort keys %dist) { 2357 $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n"); 2358 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 2359 $pack->install; 2360 $CPAN::Signal = 0; # it's tempting to reset Signal, so we can 2361 # stop a package from recompiling, 2362 # e.g. IO-1.12 when we have perl5.003_10 2363 } 2364 } 2365 2366 #-> sub CPAN::Shell::scripts ; 2367 sub scripts { 2368 my($self, $arg) = @_; 2369 $CPAN::Frontend->mywarn(">>>> experimental command, currently unsupported <<<<\n\n"); 2370 2371 for my $req (qw( HTML::LinkExtor Sort::Versions List::Util )) { 2372 unless ($CPAN::META->has_inst($req)) { 2373 $CPAN::Frontend->mywarn(" $req not available\n"); 2374 } 2375 } 2376 my $p = HTML::LinkExtor->new(); 2377 my $indexfile = "/home/ftp/pub/PAUSE/scripts/new/index.html"; 2378 unless (-f $indexfile) { 2379 $CPAN::Frontend->mydie("found no indexfile[$indexfile]\n"); 2380 } 2381 $p->parse_file($indexfile); 2382 my @hrefs; 2383 my $qrarg; 2384 if ($arg =~ s|^/(.+)/$|$1|) { 2385 $qrarg = eval 'qr/$arg/'; # hide construct from 5.004 2386 } 2387 for my $l ($p->links) { 2388 my $tag = shift @$l; 2389 next unless $tag eq "a"; 2390 my %att = @$l; 2391 my $href = $att{href}; 2392 next unless $href =~ s|^\.\./authors/id/./../||; 2393 if ($arg) { 2394 if ($qrarg) { 2395 if ($href =~ $qrarg) { 2396 push @hrefs, $href; 2397 } 2398 } else { 2399 if ($href =~ /\Q$arg\E/) { 2400 push @hrefs, $href; 2401 } 2402 } 2403 } else { 2404 push @hrefs, $href; 2405 } 2406 } 2407 # now filter for the latest version if there is more than one of a name 2408 my %stems; 2409 for (sort @hrefs) { 2410 my $href = $_; 2411 s/-v?\d.*//; 2412 my $stem = $_; 2413 $stems{$stem} ||= []; 2414 push @{$stems{$stem}}, $href; 2415 } 2416 for (sort keys %stems) { 2417 my $highest; 2418 if (@{$stems{$_}} > 1) { 2419 $highest = List::Util::reduce { 2420 Sort::Versions::versioncmp($a,$b) > 0 ? $a : $b 2421 } @{$stems{$_}}; 2422 } else { 2423 $highest = $stems{$_}[0]; 2424 } 2425 $CPAN::Frontend->myprint("$highest\n"); 2426 } 2427 } 2428 2429 #-> sub CPAN::Shell::report ; 2430 sub report { 2431 my($self,@args) = @_; 2432 unless ($CPAN::META->has_inst("CPAN::Reporter")) { 2433 $CPAN::Frontend->mydie("CPAN::Reporter not installed; cannot continue"); 2434 } 2435 local $CPAN::Config->{test_report} = 1; 2436 $self->force("test",@args); # force is there so that the test be 2437 # re-run (as documented) 2438 } 2439 2440 # compare with is_tested 2441 #-> sub CPAN::Shell::install_tested 2442 sub install_tested { 2443 my($self,@some) = @_; 2444 $CPAN::Frontend->mywarn("install_tested() must not be called with arguments.\n"), 2445 return if @some; 2446 CPAN::Index->reload; 2447 2448 for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) { 2449 my $yaml = "$b.yml"; 2450 unless (-f $yaml) { 2451 $CPAN::Frontend->mywarn("No YAML file for $b available, skipping\n"); 2452 next; 2453 } 2454 my $yaml_content = CPAN->_yaml_loadfile($yaml); 2455 my $id = $yaml_content->[0]{distribution}{ID}; 2456 unless ($id) { 2457 $CPAN::Frontend->mywarn("No ID found in '$yaml', skipping\n"); 2458 next; 2459 } 2460 my $do = CPAN::Shell->expandany($id); 2461 unless ($do) { 2462 $CPAN::Frontend->mywarn("Could not expand ID '$id', skipping\n"); 2463 next; 2464 } 2465 unless ($do->{build_dir}) { 2466 $CPAN::Frontend->mywarn("Distro '$id' has no build_dir, skipping\n"); 2467 next; 2468 } 2469 unless ($do->{build_dir} eq $b) { 2470 $CPAN::Frontend->mywarn("Distro '$id' has build_dir '$do->{build_dir}' but expected '$b', skipping\n"); 2471 next; 2472 } 2473 push @some, $do; 2474 } 2475 2476 $CPAN::Frontend->mywarn("No tested distributions found.\n"), 2477 return unless @some; 2478 2479 @some = grep { $_->{make_test} && ! $_->{make_test}->failed } @some; 2480 $CPAN::Frontend->mywarn("No distributions tested with this build of perl found.\n"), 2481 return unless @some; 2482 2483 # @some = grep { not $_->uptodate } @some; 2484 # $CPAN::Frontend->mywarn("No non-uptodate distributions tested with this build of perl found.\n"), 2485 # return unless @some; 2486 2487 CPAN->debug("some[@some]"); 2488 for my $d (@some) { 2489 my $id = $d->can("pretty_id") ? $d->pretty_id : $d->id; 2490 $CPAN::Frontend->myprint("install_tested: Running for $id\n"); 2491 $CPAN::Frontend->mysleep(1); 2492 $self->install($d); 2493 } 2494 } 2495 2496 #-> sub CPAN::Shell::upgrade ; 2497 sub upgrade { 2498 my($self,@args) = @_; 2499 $self->install($self->r(@args)); 2500 } 2501 2502 #-> sub CPAN::Shell::_u_r_common ; 2503 sub _u_r_common { 2504 my($self) = shift @_; 2505 my($what) = shift @_; 2506 CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG; 2507 Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless 2508 $what && $what =~ /^[aru]$/; 2509 my(@args) = @_; 2510 @args = '/./' unless @args; 2511 my(@result,$module,%seen,%need,$headerdone, 2512 $version_undefs,$version_zeroes, 2513 @version_undefs,@version_zeroes); 2514 $version_undefs = $version_zeroes = 0; 2515 my $sprintf = "%s%-25s%s %9s %9s %s\n"; 2516 my @expand = $self->expand('Module',@args); 2517 my $expand = scalar @expand; 2518 if (0) { # Looks like noise to me, was very useful for debugging 2519 # for metadata cache 2520 $CPAN::Frontend->myprint(sprintf "%d matches in the database\n", $expand); 2521 } 2522 MODULE: for $module (@expand) { 2523 my $file = $module->cpan_file; 2524 next MODULE unless defined $file; # ?? 2525 $file =~ s!^./../!!; 2526 my($latest) = $module->cpan_version; 2527 my($inst_file) = $module->inst_file; 2528 my($have); 2529 return if $CPAN::Signal; 2530 if ($inst_file) { 2531 if ($what eq "a") { 2532 $have = $module->inst_version; 2533 } elsif ($what eq "r") { 2534 $have = $module->inst_version; 2535 local($^W) = 0; 2536 if ($have eq "undef") { 2537 $version_undefs++; 2538 push @version_undefs, $module->as_glimpse; 2539 } elsif (CPAN::Version->vcmp($have,0)==0) { 2540 $version_zeroes++; 2541 push @version_zeroes, $module->as_glimpse; 2542 } 2543 next MODULE unless CPAN::Version->vgt($latest, $have); 2544 # to be pedantic we should probably say: 2545 # && !($have eq "undef" && $latest ne "undef" && $latest gt ""); 2546 # to catch the case where CPAN has a version 0 and we have a version undef 2547 } elsif ($what eq "u") { 2548 next MODULE; 2549 } 2550 } else { 2551 if ($what eq "a") { 2552 next MODULE; 2553 } elsif ($what eq "r") { 2554 next MODULE; 2555 } elsif ($what eq "u") { 2556 $have = "-"; 2557 } 2558 } 2559 return if $CPAN::Signal; # this is sometimes lengthy 2560 $seen{$file} ||= 0; 2561 if ($what eq "a") { 2562 push @result, sprintf "%s %s\n", $module->id, $have; 2563 } elsif ($what eq "r") { 2564 push @result, $module->id; 2565 next MODULE if $seen{$file}++; 2566 } elsif ($what eq "u") { 2567 push @result, $module->id; 2568 next MODULE if $seen{$file}++; 2569 next MODULE if $file =~ /^Contact/; 2570 } 2571 unless ($headerdone++) { 2572 $CPAN::Frontend->myprint("\n"); 2573 $CPAN::Frontend->myprint(sprintf( 2574 $sprintf, 2575 "", 2576 "Package namespace", 2577 "", 2578 "installed", 2579 "latest", 2580 "in CPAN file" 2581 )); 2582 } 2583 my $color_on = ""; 2584 my $color_off = ""; 2585 if ( 2586 $COLOR_REGISTERED 2587 && 2588 $CPAN::META->has_inst("Term::ANSIColor") 2589 && 2590 $module->description 2591 ) { 2592 $color_on = Term::ANSIColor::color("green"); 2593 $color_off = Term::ANSIColor::color("reset"); 2594 } 2595 $CPAN::Frontend->myprint(sprintf $sprintf, 2596 $color_on, 2597 $module->id, 2598 $color_off, 2599 $have, 2600 $latest, 2601 $file); 2602 $need{$module->id}++; 2603 } 2604 unless (%need) { 2605 if ($what eq "u") { 2606 $CPAN::Frontend->myprint("No modules found for @args\n"); 2607 } elsif ($what eq "r") { 2608 $CPAN::Frontend->myprint("All modules are up to date for @args\n"); 2609 } 2610 } 2611 if ($what eq "r") { 2612 if ($version_zeroes) { 2613 my $s_has = $version_zeroes > 1 ? "s have" : " has"; 2614 $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }. 2615 qq{a version number of 0\n}); 2616 if ($CPAN::Config->{show_zero_versions}) { 2617 local $" = "\t"; 2618 $CPAN::Frontend->myprint(qq{ they are\n\t@version_zeroes\n}); 2619 $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 0' }. 2620 qq{to hide them)\n}); 2621 } else { 2622 $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 1' }. 2623 qq{to show them)\n}); 2624 } 2625 } 2626 if ($version_undefs) { 2627 my $s_has = $version_undefs > 1 ? "s have" : " has"; 2628 $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }. 2629 qq{parseable version number\n}); 2630 if ($CPAN::Config->{show_unparsable_versions}) { 2631 local $" = "\t"; 2632 $CPAN::Frontend->myprint(qq{ they are\n\t@version_undefs\n}); 2633 $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 0' }. 2634 qq{to hide them)\n}); 2635 } else { 2636 $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 1' }. 2637 qq{to show them)\n}); 2638 } 2639 } 2640 } 2641 @result; 2642 } 2643 2644 #-> sub CPAN::Shell::r ; 2645 sub r { 2646 shift->_u_r_common("r",@_); 2647 } 2648 2649 #-> sub CPAN::Shell::u ; 2650 sub u { 2651 shift->_u_r_common("u",@_); 2652 } 2653 2654 #-> sub CPAN::Shell::failed ; 2655 sub failed { 2656 my($self,$only_id,$silent) = @_; 2657 my @failed; 2658 DIST: for my $d ($CPAN::META->all_objects("CPAN::Distribution")) { 2659 my $failed = ""; 2660 NAY: for my $nosayer ( # order matters! 2661 "unwrapped", 2662 "writemakefile", 2663 "signature_verify", 2664 "make", 2665 "make_test", 2666 "install", 2667 "make_clean", 2668 ) { 2669 next unless exists $d->{$nosayer}; 2670 next unless defined $d->{$nosayer}; 2671 next unless ( 2672 UNIVERSAL::can($d->{$nosayer},"failed") ? 2673 $d->{$nosayer}->failed : 2674 $d->{$nosayer} =~ /^NO/ 2675 ); 2676 next NAY if $only_id && $only_id != ( 2677 UNIVERSAL::can($d->{$nosayer},"commandid") 2678 ? 2679 $d->{$nosayer}->commandid 2680 : 2681 $CPAN::CurrentCommandId 2682 ); 2683 $failed = $nosayer; 2684 last; 2685 } 2686 next DIST unless $failed; 2687 my $id = $d->id; 2688 $id =~ s|^./../||; 2689 #$print .= sprintf( 2690 # " %-45s: %s %s\n", 2691 push @failed, 2692 ( 2693 UNIVERSAL::can($d->{$failed},"failed") ? 2694 [ 2695 $d->{$failed}->commandid, 2696 $id, 2697 $failed, 2698 $d->{$failed}->text, 2699 $d->{$failed}{TIME}||0, 2700 ] : 2701 [ 2702 1, 2703 $id, 2704 $failed, 2705 $d->{$failed}, 2706 0, 2707 ] 2708 ); 2709 } 2710 my $scope; 2711 if ($only_id) { 2712 $scope = "this command"; 2713 } elsif ($CPAN::Index::HAVE_REANIMATED) { 2714 $scope = "this or a previous session"; 2715 # it might be nice to have a section for previous session and 2716 # a second for this 2717 } else { 2718 $scope = "this session"; 2719 } 2720 if (@failed) { 2721 my $print; 2722 my $debug = 0; 2723 if ($debug) { 2724 $print = join "", 2725 map { sprintf "%5d %-45s: %s %s\n", @$_ } 2726 sort { $a->[0] <=> $b->[0] } @failed; 2727 } else { 2728 $print = join "", 2729 map { sprintf " %-45s: %s %s\n", @$_[1..3] } 2730 sort { 2731 $a->[0] <=> $b->[0] 2732 || 2733 $a->[4] <=> $b->[4] 2734 } @failed; 2735 } 2736 $CPAN::Frontend->myprint("Failed during $scope:\n$print"); 2737 } elsif (!$only_id || !$silent) { 2738 $CPAN::Frontend->myprint("Nothing failed in $scope\n"); 2739 } 2740 } 2741 2742 # XXX intentionally undocumented because completely bogus, unportable, 2743 # useless, etc. 2744 2745 #-> sub CPAN::Shell::status ; 2746 sub status { 2747 my($self) = @_; 2748 require Devel::Size; 2749 my $ps = FileHandle->new; 2750 open $ps, "/proc/$$/status"; 2751 my $vm = 0; 2752 while (<$ps>) { 2753 next unless /VmSize:\s+(\d+)/; 2754 $vm = $1; 2755 last; 2756 } 2757 $CPAN::Frontend->mywarn(sprintf( 2758 "%-27s %6d\n%-27s %6d\n", 2759 "vm", 2760 $vm, 2761 "CPAN::META", 2762 Devel::Size::total_size($CPAN::META)/1024, 2763 )); 2764 for my $k (sort keys %$CPAN::META) { 2765 next unless substr($k,0,4) eq "read"; 2766 warn sprintf " %-26s %6d\n", $k, Devel::Size::total_size($CPAN::META->{$k})/1024; 2767 for my $k2 (sort keys %{$CPAN::META->{$k}}) { 2768 warn sprintf " %-25s %6d (keys: %6d)\n", 2769 $k2, 2770 Devel::Size::total_size($CPAN::META->{$k}{$k2})/1024, 2771 scalar keys %{$CPAN::META->{$k}{$k2}}; 2772 } 2773 } 2774 } 2775 2776 # compare with install_tested 2777 #-> sub CPAN::Shell::is_tested 2778 sub is_tested { 2779 my($self) = @_; 2780 CPAN::Index->reload; 2781 for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) { 2782 my $time; 2783 if ($CPAN::META->{is_tested}{$b}) { 2784 $time = scalar(localtime $CPAN::META->{is_tested}{$b}); 2785 } else { 2786 $time = scalar localtime; 2787 $time =~ s/\S/?/g; 2788 } 2789 $CPAN::Frontend->myprint(sprintf "%s %s\n", $time, $b); 2790 } 2791 } 2792 2793 #-> sub CPAN::Shell::autobundle ; 2794 sub autobundle { 2795 my($self) = shift; 2796 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 2797 my(@bundle) = $self->_u_r_common("a",@_); 2798 my($todir) = File::Spec->catdir($CPAN::Config->{'cpan_home'},"Bundle"); 2799 File::Path::mkpath($todir); 2800 unless (-d $todir) { 2801 $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n"); 2802 return; 2803 } 2804 my($y,$m,$d) = (localtime)[5,4,3]; 2805 $y+=1900; 2806 $m++; 2807 my($c) = 0; 2808 my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c; 2809 my($to) = File::Spec->catfile($todir,"$me.pm"); 2810 while (-f $to) { 2811 $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c; 2812 $to = File::Spec->catfile($todir,"$me.pm"); 2813 } 2814 my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!"; 2815 $fh->print( 2816 "package Bundle::$me;\n\n", 2817 "\$VERSION = '0.01';\n\n", 2818 "1;\n\n", 2819 "__END__\n\n", 2820 "=head1 NAME\n\n", 2821 "Bundle::$me - Snapshot of installation on ", 2822 $Config::Config{'myhostname'}, 2823 " on ", 2824 scalar(localtime), 2825 "\n\n=head1 SYNOPSIS\n\n", 2826 "perl -MCPAN -e 'install Bundle::$me'\n\n", 2827 "=head1 CONTENTS\n\n", 2828 join("\n", @bundle), 2829 "\n\n=head1 CONFIGURATION\n\n", 2830 Config->myconfig, 2831 "\n\n=head1 AUTHOR\n\n", 2832 "This Bundle has been generated automatically ", 2833 "by the autobundle routine in CPAN.pm.\n", 2834 ); 2835 $fh->close; 2836 $CPAN::Frontend->myprint("\nWrote bundle file 2837 $to\n\n"); 2838 } 2839 2840 #-> sub CPAN::Shell::expandany ; 2841 sub expandany { 2842 my($self,$s) = @_; 2843 CPAN->debug("s[$s]") if $CPAN::DEBUG; 2844 if ($s =~ m|/| or substr($s,-1,1) eq ".") { # looks like a file or a directory 2845 $s = CPAN::Distribution->normalize($s); 2846 return $CPAN::META->instance('CPAN::Distribution',$s); 2847 # Distributions spring into existence, not expand 2848 } elsif ($s =~ m|^Bundle::|) { 2849 $self->local_bundles; # scanning so late for bundles seems 2850 # both attractive and crumpy: always 2851 # current state but easy to forget 2852 # somewhere 2853 return $self->expand('Bundle',$s); 2854 } else { 2855 return $self->expand('Module',$s) 2856 if $CPAN::META->exists('CPAN::Module',$s); 2857 } 2858 return; 2859 } 2860 2861 #-> sub CPAN::Shell::expand ; 2862 sub expand { 2863 my $self = shift; 2864 my($type,@args) = @_; 2865 CPAN->debug("type[$type]args[@args]") if $CPAN::DEBUG; 2866 my $class = "CPAN::$type"; 2867 my $methods = ['id']; 2868 for my $meth (qw(name)) { 2869 next unless $class->can($meth); 2870 push @$methods, $meth; 2871 } 2872 $self->expand_by_method($class,$methods,@args); 2873 } 2874 2875 #-> sub CPAN::Shell::expand_by_method ; 2876 sub expand_by_method { 2877 my $self = shift; 2878 my($class,$methods,@args) = @_; 2879 my($arg,@m); 2880 for $arg (@args) { 2881 my($regex,$command); 2882 if ($arg =~ m|^/(.*)/$|) { 2883 $regex = $1; 2884 # FIXME: there seem to be some ='s in the author data, which trigger 2885 # a failure here. This needs to be contemplated. 2886 # } elsif ($arg =~ m/=/) { 2887 # $command = 1; 2888 } 2889 my $obj; 2890 CPAN->debug(sprintf "class[%s]regex[%s]command[%s]", 2891 $class, 2892 defined $regex ? $regex : "UNDEFINED", 2893 defined $command ? $command : "UNDEFINED", 2894 ) if $CPAN::DEBUG; 2895 if (defined $regex) { 2896 if (CPAN::_sqlite_running) { 2897 $CPAN::SQLite->search($class, $regex); 2898 } 2899 for $obj ( 2900 $CPAN::META->all_objects($class) 2901 ) { 2902 unless ($obj && UNIVERSAL::can($obj,"id") && $obj->id) { 2903 # BUG, we got an empty object somewhere 2904 require Data::Dumper; 2905 CPAN->debug(sprintf( 2906 "Bug in CPAN: Empty id on obj[%s][%s]", 2907 $obj, 2908 Data::Dumper::Dumper($obj) 2909 )) if $CPAN::DEBUG; 2910 next; 2911 } 2912 for my $method (@$methods) { 2913 my $match = eval {$obj->$method() =~ /$regex/i}; 2914 if ($@) { 2915 my($err) = $@ =~ /^(.+) at .+? line \d+\.$/; 2916 $err ||= $@; # if we were too restrictive above 2917 $CPAN::Frontend->mydie("$err\n"); 2918 } elsif ($match) { 2919 push @m, $obj; 2920 last; 2921 } 2922 } 2923 } 2924 } elsif ($command) { 2925 die "equal sign in command disabled (immature interface), ". 2926 "you can set 2927 ! \$CPAN::Shell::ADVANCED_QUERY=1 2928 to enable it. But please note, this is HIGHLY EXPERIMENTAL code 2929 that may go away anytime.\n" 2930 unless $ADVANCED_QUERY; 2931 my($method,$criterion) = $arg =~ /(.+?)=(.+)/; 2932 my($matchcrit) = $criterion =~ m/^~(.+)/; 2933 for my $self ( 2934 sort 2935 {$a->id cmp $b->id} 2936 $CPAN::META->all_objects($class) 2937 ) { 2938 my $lhs = $self->$method() or next; # () for 5.00503 2939 if ($matchcrit) { 2940 push @m, $self if $lhs =~ m/$matchcrit/; 2941 } else { 2942 push @m, $self if $lhs eq $criterion; 2943 } 2944 } 2945 } else { 2946 my($xarg) = $arg; 2947 if ( $class eq 'CPAN::Bundle' ) { 2948 $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/; 2949 } elsif ($class eq "CPAN::Distribution") { 2950 $xarg = CPAN::Distribution->normalize($arg); 2951 } else { 2952 $xarg =~ s/:+/::/g; 2953 } 2954 if ($CPAN::META->exists($class,$xarg)) { 2955 $obj = $CPAN::META->instance($class,$xarg); 2956 } elsif ($CPAN::META->exists($class,$arg)) { 2957 $obj = $CPAN::META->instance($class,$arg); 2958 } else { 2959 next; 2960 } 2961 push @m, $obj; 2962 } 2963 } 2964 @m = sort {$a->id cmp $b->id} @m; 2965 if ( $CPAN::DEBUG ) { 2966 my $wantarray = wantarray; 2967 my $join_m = join ",", map {$_->id} @m; 2968 $self->debug("wantarray[$wantarray]join_m[$join_m]"); 2969 } 2970 return wantarray ? @m : $m[0]; 2971 } 2972 2973 #-> sub CPAN::Shell::format_result ; 2974 sub format_result { 2975 my($self) = shift; 2976 my($type,@args) = @_; 2977 @args = '/./' unless @args; 2978 my(@result) = $self->expand($type,@args); 2979 my $result = @result == 1 ? 2980 $result[0]->as_string : 2981 @result == 0 ? 2982 "No objects of type $type found for argument @args\n" : 2983 join("", 2984 (map {$_->as_glimpse} @result), 2985 scalar @result, " items found\n", 2986 ); 2987 $result; 2988 } 2989 2990 #-> sub CPAN::Shell::report_fh ; 2991 { 2992 my $installation_report_fh; 2993 my $previously_noticed = 0; 2994 2995 sub report_fh { 2996 return $installation_report_fh if $installation_report_fh; 2997 if ($CPAN::META->has_usable("File::Temp")) { 2998 $installation_report_fh 2999 = File::Temp->new( 3000 dir => File::Spec->tmpdir, 3001 template => 'cpan_install_XXXX', 3002 suffix => '.txt', 3003 unlink => 0, 3004 ); 3005 } 3006 unless ( $installation_report_fh ) { 3007 warn("Couldn't open installation report file; " . 3008 "no report file will be generated." 3009 ) unless $previously_noticed++; 3010 } 3011 } 3012 } 3013 3014 3015 # The only reason for this method is currently to have a reliable 3016 # debugging utility that reveals which output is going through which 3017 # channel. No, I don't like the colors ;-) 3018 3019 # to turn colordebugging on, write 3020 # cpan> o conf colorize_output 1 3021 3022 #-> sub CPAN::Shell::print_ornamented ; 3023 { 3024 my $print_ornamented_have_warned = 0; 3025 sub colorize_output { 3026 my $colorize_output = $CPAN::Config->{colorize_output}; 3027 if ($colorize_output && !$CPAN::META->has_inst("Term::ANSIColor")) { 3028 unless ($print_ornamented_have_warned++) { 3029 # no myprint/mywarn within myprint/mywarn! 3030 warn "Colorize_output is set to true but Term::ANSIColor is not 3031 installed. To activate colorized output, please install Term::ANSIColor.\n\n"; 3032 } 3033 $colorize_output = 0; 3034 } 3035 return $colorize_output; 3036 } 3037 } 3038 3039 3040 #-> sub CPAN::Shell::print_ornamented ; 3041 sub print_ornamented { 3042 my($self,$what,$ornament) = @_; 3043 return unless defined $what; 3044 3045 local $| = 1; # Flush immediately 3046 if ( $CPAN::Be_Silent ) { 3047 print {report_fh()} $what; 3048 return; 3049 } 3050 my $swhat = "$what"; # stringify if it is an object 3051 if ($CPAN::Config->{term_is_latin}) { 3052 # note: deprecated, need to switch to $LANG and $LC_* 3053 # courtesy jhi: 3054 $swhat 3055 =~ s{([\xC0-\xDF])([\x80-\xBF])}{chr(ord($1)<<6&0xC0|ord($2)&0x3F)}eg; #}; 3056 } 3057 if ($self->colorize_output) { 3058 if ( $CPAN::DEBUG && $swhat =~ /^Debug\(/ ) { 3059 # if you want to have this configurable, please file a bugreport 3060 $ornament = $CPAN::Config->{colorize_debug} || "black on_cyan"; 3061 } 3062 my $color_on = eval { Term::ANSIColor::color($ornament) } || ""; 3063 if ($@) { 3064 print "Term::ANSIColor rejects color[$ornament]: $@\n 3065 Please choose a different color (Hint: try 'o conf init /color/')\n"; 3066 } 3067 # GGOLDBACH/Test-GreaterVersion-0.008 broke wthout this 3068 # $trailer construct. We want the newline be the last thing if 3069 # there is a newline at the end ensuring that the next line is 3070 # empty for other players 3071 my $trailer = ""; 3072 $trailer = $1 if $swhat =~ s/([\r\n]+)\z//; 3073 print $color_on, 3074 $swhat, 3075 Term::ANSIColor::color("reset"), 3076 $trailer; 3077 } else { 3078 print $swhat; 3079 } 3080 } 3081 3082 #-> sub CPAN::Shell::myprint ; 3083 3084 # where is myprint/mywarn/Frontend/etc. documented? Where to use what? 3085 # I think, we send everything to STDOUT and use print for normal/good 3086 # news and warn for news that need more attention. Yes, this is our 3087 # working contract for now. 3088 sub myprint { 3089 my($self,$what) = @_; 3090 $self->print_ornamented($what, 3091 $CPAN::Config->{colorize_print}||'bold blue on_white', 3092 ); 3093 } 3094 3095 sub optprint { 3096 my($self,$category,$what) = @_; 3097 my $vname = $category . "_verbosity"; 3098 CPAN::HandleConfig->load unless $CPAN::Config_loaded++; 3099 if (!$CPAN::Config->{$vname} 3100 || $CPAN::Config->{$vname} =~ /^v/ 3101 ) { 3102 $CPAN::Frontend->myprint($what); 3103 } 3104 } 3105 3106 #-> sub CPAN::Shell::myexit ; 3107 sub myexit { 3108 my($self,$what) = @_; 3109 $self->myprint($what); 3110 exit; 3111 } 3112 3113 #-> sub CPAN::Shell::mywarn ; 3114 sub mywarn { 3115 my($self,$what) = @_; 3116 $self->print_ornamented($what, $CPAN::Config->{colorize_warn}||'bold red on_white'); 3117 } 3118 3119 # only to be used for shell commands 3120 #-> sub CPAN::Shell::mydie ; 3121 sub mydie { 3122 my($self,$what) = @_; 3123 $self->mywarn($what); 3124 3125 # If it is the shell, we want the following die to be silent, 3126 # but if it is not the shell, we would need a 'die $what'. We need 3127 # to take care that only shell commands use mydie. Is this 3128 # possible? 3129 3130 die "\n"; 3131 } 3132 3133 # sub CPAN::Shell::colorable_makemaker_prompt ; 3134 sub colorable_makemaker_prompt { 3135 my($foo,$bar) = @_; 3136 if (CPAN::Shell->colorize_output) { 3137 my $ornament = $CPAN::Config->{colorize_print}||'bold blue on_white'; 3138 my $color_on = eval { Term::ANSIColor::color($ornament); } || ""; 3139 print $color_on; 3140 } 3141 my $ans = ExtUtils::MakeMaker::prompt($foo,$bar); 3142 if (CPAN::Shell->colorize_output) { 3143 print Term::ANSIColor::color('reset'); 3144 } 3145 return $ans; 3146 } 3147 3148 # use this only for unrecoverable errors! 3149 #-> sub CPAN::Shell::unrecoverable_error ; 3150 sub unrecoverable_error { 3151 my($self,$what) = @_; 3152 my @lines = split /\n/, $what; 3153 my $longest = 0; 3154 for my $l (@lines) { 3155 $longest = length $l if length $l > $longest; 3156 } 3157 $longest = 62 if $longest > 62; 3158 for my $l (@lines) { 3159 if ($l =~ /^\s*$/) { 3160 $l = "\n"; 3161 next; 3162 } 3163 $l = "==> $l"; 3164 if (length $l < 66) { 3165 $l = pack "A66 A*", $l, "<=="; 3166 } 3167 $l .= "\n"; 3168 } 3169 unshift @lines, "\n"; 3170 $self->mydie(join "", @lines); 3171 } 3172 3173 #-> sub CPAN::Shell::mysleep ; 3174 sub mysleep { 3175 my($self, $sleep) = @_; 3176 if (CPAN->has_inst("Time::HiRes")) { 3177 Time::HiRes::sleep($sleep); 3178 } else { 3179 sleep($sleep < 1 ? 1 : int($sleep + 0.5)); 3180 } 3181 } 3182 3183 #-> sub CPAN::Shell::setup_output ; 3184 sub setup_output { 3185 return if -t STDOUT; 3186 my $odef = select STDERR; 3187 $| = 1; 3188 select STDOUT; 3189 $| = 1; 3190 select $odef; 3191 } 3192 3193 #-> sub CPAN::Shell::rematein ; 3194 # RE-adme||MA-ke||TE-st||IN-stall : nearly everything runs through here 3195 sub rematein { 3196 my $self = shift; 3197 my($meth,@some) = @_; 3198 my @pragma; 3199 while($meth =~ /^(ff?orce|notest)$/) { 3200 push @pragma, $meth; 3201 $meth = shift @some or 3202 $CPAN::Frontend->mydie("Pragma $pragma[-1] used without method: ". 3203 "cannot continue"); 3204 } 3205 setup_output(); 3206 CPAN->debug("pragma[@pragma]meth[$meth]some[@some]") if $CPAN::DEBUG; 3207 3208 # Here is the place to set "test_count" on all involved parties to 3209 # 0. We then can pass this counter on to the involved 3210 # distributions and those can refuse to test if test_count > X. In 3211 # the first stab at it we could use a 1 for "X". 3212 3213 # But when do I reset the distributions to start with 0 again? 3214 # Jost suggested to have a random or cycling interaction ID that 3215 # we pass through. But the ID is something that is just left lying 3216 # around in addition to the counter, so I'd prefer to set the 3217 # counter to 0 now, and repeat at the end of the loop. But what 3218 # about dependencies? They appear later and are not reset, they 3219 # enter the queue but not its copy. How do they get a sensible 3220 # test_count? 3221 3222 # With configure_requires, "get" is vulnerable in recursion. 3223 3224 my $needs_recursion_protection = "get|make|test|install"; 3225 3226 # construct the queue 3227 my($s,@s,@qcopy); 3228 STHING: foreach $s (@some) { 3229 my $obj; 3230 if (ref $s) { 3231 CPAN->debug("s is an object[$s]") if $CPAN::DEBUG; 3232 $obj = $s; 3233 } elsif ($s =~ m|[\$\@\%]|) { # looks like a perl variable 3234 } elsif ($s =~ m|^/|) { # looks like a regexp 3235 if (substr($s,-1,1) eq ".") { 3236 $obj = CPAN::Shell->expandany($s); 3237 } else { 3238 $CPAN::Frontend->mywarn("Sorry, $meth with a regular expression is ". 3239 "not supported.\nRejecting argument '$s'\n"); 3240 $CPAN::Frontend->mysleep(2); 3241 next; 3242 } 3243 } elsif ($meth eq "ls") { 3244 $self->globls($s,\@pragma); 3245 next STHING; 3246 } else { 3247 CPAN->debug("calling expandany [$s]") if $CPAN::DEBUG; 3248 $obj = CPAN::Shell->expandany($s); 3249 } 3250 if (0) { 3251 } elsif (ref $obj) { 3252 if ($meth =~ /^($needs_recursion_protection)$/) { 3253 # it would be silly to check for recursion for look or dump 3254 # (we are in CPAN::Shell::rematein) 3255 CPAN->debug("Going to test against recursion") if $CPAN::DEBUG; 3256 eval { $obj->color_cmd_tmps(0,1); }; 3257 if ($@) { 3258 if (ref $@ 3259 and $@->isa("CPAN::Exception::RecursiveDependency")) { 3260 $CPAN::Frontend->mywarn($@); 3261 } else { 3262 if (0) { 3263 require Carp; 3264 Carp::confess(sprintf "DEBUG: \$\@[%s]ref[%s]", $@, ref $@); 3265 } 3266 die; 3267 } 3268 } 3269 } 3270 CPAN::Queue->queue_item(qmod => $obj->id, reqtype => "c"); 3271 push @qcopy, $obj; 3272 } elsif ($CPAN::META->exists('CPAN::Author',uc($s))) { 3273 $obj = $CPAN::META->instance('CPAN::Author',uc($s)); 3274 if ($meth =~ /^(dump|ls|reports)$/) { 3275 $obj->$meth(); 3276 } else { 3277 $CPAN::Frontend->mywarn( 3278 join "", 3279 "Don't be silly, you can't $meth ", 3280 $obj->fullname, 3281 " ;-)\n" 3282 ); 3283 $CPAN::Frontend->mysleep(2); 3284 } 3285 } elsif ($s =~ m|[\$\@\%]| && $meth eq "dump") { 3286 CPAN::InfoObj->dump($s); 3287 } else { 3288 $CPAN::Frontend 3289 ->mywarn(qq{Warning: Cannot $meth $s, }. 3290 qq{don't know what it is. 3291 Try the command 3292 3293 i /$s/ 3294 3295 to find objects with matching identifiers. 3296 }); 3297 $CPAN::Frontend->mysleep(2); 3298 } 3299 } 3300 3301 # queuerunner (please be warned: when I started to change the 3302 # queue to hold objects instead of names, I made one or two 3303 # mistakes and never found which. I reverted back instead) 3304 while (my $q = CPAN::Queue->first) { 3305 my $obj; 3306 my $s = $q->as_string; 3307 my $reqtype = $q->reqtype || ""; 3308 $obj = CPAN::Shell->expandany($s); 3309 unless ($obj) { 3310 # don't know how this can happen, maybe we should panic, 3311 # but maybe we get a solution from the first user who hits 3312 # this unfortunate exception? 3313 $CPAN::Frontend->mywarn("Warning: Could not expand string '$s' ". 3314 "to an object. Skipping.\n"); 3315 $CPAN::Frontend->mysleep(5); 3316 CPAN::Queue->delete_first($s); 3317 next; 3318 } 3319 $obj->{reqtype} ||= ""; 3320 { 3321 # force debugging because CPAN::SQLite somehow delivers us 3322 # an empty object; 3323 3324 # local $CPAN::DEBUG = 1024; # Shell; probably fixed now 3325 3326 CPAN->debug("s[$s]obj-reqtype[$obj->{reqtype}]". 3327 "q-reqtype[$reqtype]") if $CPAN::DEBUG; 3328 } 3329 if ($obj->{reqtype}) { 3330 if ($obj->{reqtype} eq "b" && $reqtype =~ /^[rc]$/) { 3331 $obj->{reqtype} = $reqtype; 3332 if ( 3333 exists $obj->{install} 3334 && 3335 ( 3336 UNIVERSAL::can($obj->{install},"failed") ? 3337 $obj->{install}->failed : 3338 $obj->{install} =~ /^NO/ 3339 ) 3340 ) { 3341 delete $obj->{install}; 3342 $CPAN::Frontend->mywarn 3343 ("Promoting $obj->{ID} from 'build_requires' to 'requires'"); 3344 } 3345 } 3346 } else { 3347 $obj->{reqtype} = $reqtype; 3348 } 3349 3350 for my $pragma (@pragma) { 3351 if ($pragma 3352 && 3353 $obj->can($pragma)) { 3354 $obj->$pragma($meth); 3355 } 3356 } 3357 if (UNIVERSAL::can($obj, 'called_for')) { 3358 $obj->called_for($s); 3359 } 3360 CPAN->debug(qq{pragma[@pragma]meth[$meth]}. 3361 qq{ID[$obj->{ID}]}) if $CPAN::DEBUG; 3362 3363 push @qcopy, $obj; 3364 if ($meth =~ /^(report)$/) { # they came here with a pragma? 3365 $self->$meth($obj); 3366 } elsif (! UNIVERSAL::can($obj,$meth)) { 3367 # Must never happen 3368 my $serialized = ""; 3369 if (0) { 3370 } elsif ($CPAN::META->has_inst("YAML::Syck")) { 3371 $serialized = YAML::Syck::Dump($obj); 3372 } elsif ($CPAN::META->has_inst("YAML")) { 3373 $serialized = YAML::Dump($obj); 3374 } elsif ($CPAN::META->has_inst("Data::Dumper")) { 3375 $serialized = Data::Dumper::Dumper($obj); 3376 } else { 3377 require overload; 3378 $serialized = overload::StrVal($obj); 3379 } 3380 CPAN->debug("Going to panic. meth[$meth]s[$s]") if $CPAN::DEBUG; 3381 $CPAN::Frontend->mydie("Panic: obj[$serialized] cannot meth[$meth]"); 3382 } elsif ($obj->$meth()) { 3383 CPAN::Queue->delete($s); 3384 CPAN->debug("From queue deleted. meth[$meth]s[$s]") if $CPAN::DEBUG; 3385 } else { 3386 CPAN->debug("Failed. pragma[@pragma]meth[$meth]") if $CPAN::DEBUG; 3387 } 3388 3389 $obj->undelay; 3390 for my $pragma (@pragma) { 3391 my $unpragma = "un$pragma"; 3392 if ($obj->can($unpragma)) { 3393 $obj->$unpragma(); 3394 } 3395 } 3396 CPAN::Queue->delete_first($s); 3397 } 3398 if ($meth =~ /^($needs_recursion_protection)$/) { 3399 for my $obj (@qcopy) { 3400 $obj->color_cmd_tmps(0,0); 3401 } 3402 } 3403 } 3404 3405 #-> sub CPAN::Shell::recent ; 3406 sub recent { 3407 my($self) = @_; 3408 if ($CPAN::META->has_inst("XML::LibXML")) { 3409 my $url = $CPAN::Defaultrecent; 3410 $CPAN::Frontend->myprint("Going to fetch '$url'\n"); 3411 unless ($CPAN::META->has_usable("LWP")) { 3412 $CPAN::Frontend->mydie("LWP not installed; cannot continue"); 3413 } 3414 CPAN::LWP::UserAgent->config; 3415 my $Ua; 3416 eval { $Ua = CPAN::LWP::UserAgent->new; }; 3417 if ($@) { 3418 $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n"); 3419 } 3420 my $resp = $Ua->get($url); 3421 unless ($resp->is_success) { 3422 $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code); 3423 } 3424 $CPAN::Frontend->myprint("DONE\n\n"); 3425 my $xml = XML::LibXML->new->parse_string($resp->content); 3426 if (0) { 3427 my $s = $xml->serialize(2); 3428 $s =~ s/\n\s*\n/\n/g; 3429 $CPAN::Frontend->myprint($s); 3430 return; 3431 } 3432 my @distros; 3433 if ($url =~ /winnipeg/) { 3434 my $pubdate = $xml->findvalue("/rss/channel/pubDate"); 3435 $CPAN::Frontend->myprint(" pubDate: $pubdate\n\n"); 3436 for my $eitem ($xml->findnodes("/rss/channel/item")) { 3437 my $distro = $eitem->findvalue("enclosure/\@url"); 3438 $distro =~ s|.*?/authors/id/./../||; 3439 my $size = $eitem->findvalue("enclosure/\@length"); 3440 my $desc = $eitem->findvalue("description"); 3441 $desc =~ s/.+? - //; 3442 $CPAN::Frontend->myprint("$distro [$size b]\n $desc\n"); 3443 push @distros, $distro; 3444 } 3445 } elsif ($url =~ /search.*uploads.rdf/) { 3446 # xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 3447 # xmlns="http://purl.org/rss/1.0/" 3448 # xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" 3449 # xmlns:dc="http://purl.org/dc/elements/1.1/" 3450 # xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" 3451 # xmlns:admin="http://webns.net/mvcb/" 3452 3453 3454 my $dc_date = $xml->findvalue("//*[local-name(.) = 'RDF']/*[local-name(.) = 'channel']/*[local-name(.) = 'date']"); 3455 $CPAN::Frontend->myprint(" dc:date: $dc_date\n\n"); 3456 my $finish_eitem = 0; 3457 local $SIG{INT} = sub { $finish_eitem = 1 }; 3458 EITEM: for my $eitem ($xml->findnodes("//*[local-name(.) = 'RDF']/*[local-name(.) = 'item']")) { 3459 my $distro = $eitem->findvalue("\@rdf:about"); 3460 $distro =~ s|.*~||; # remove up to the tilde before the name 3461 $distro =~ s|/$||; # remove trailing slash 3462 $distro =~ s|([^/]+)|\U$1\E|; # upcase the name 3463 my $author = uc $1 or die "distro[$distro] without author, cannot continue"; 3464 my $desc = $eitem->findvalue("*[local-name(.) = 'description']"); 3465 my $i = 0; 3466 SUBDIRTEST: while () { 3467 last SUBDIRTEST if ++$i >= 6; # half a dozen must do! 3468 if (my @ret = $self->globls("$distro*")) { 3469 @ret = grep {$_->[2] !~ /meta/} @ret; 3470 @ret = grep {length $_->[2]} @ret; 3471 if (@ret) { 3472 $distro = "$author/$ret[0][2]"; 3473 last SUBDIRTEST; 3474 } 3475 } 3476 $distro =~ s|/|/*/|; # allow it to reside in a subdirectory 3477 } 3478 3479 next EITEM if $distro =~ m|\*|; # did not find the thing 3480 $CPAN::Frontend->myprint("____$desc\n"); 3481 push @distros, $distro; 3482 last EITEM if $finish_eitem; 3483 } 3484 } 3485 return \@distros; 3486 } else { 3487 # deprecated old version 3488 $CPAN::Frontend->mydie("no XML::LibXML installed, cannot continue\n"); 3489 } 3490 } 3491 3492 #-> sub CPAN::Shell::smoke ; 3493 sub smoke { 3494 my($self) = @_; 3495 my $distros = $self->recent; 3496 DISTRO: for my $distro (@$distros) { 3497 $CPAN::Frontend->myprint(sprintf "Going to download and test '$distro'\n"); 3498 { 3499 my $skip = 0; 3500 local $SIG{INT} = sub { $skip = 1 }; 3501 for (0..9) { 3502 $CPAN::Frontend->myprint(sprintf "\r%2d (Hit ^C to skip)", 10-$_); 3503 sleep 1; 3504 if ($skip) { 3505 $CPAN::Frontend->myprint(" skipped\n"); 3506 next DISTRO; 3507 } 3508 } 3509 } 3510 $CPAN::Frontend->myprint("\r \n"); # leave the dirty line with a newline 3511 $self->test($distro); 3512 } 3513 } 3514 3515 { 3516 # set up the dispatching methods 3517 no strict "refs"; 3518 for my $command (qw( 3519 clean 3520 cvs_import 3521 dump 3522 force 3523 fforce 3524 get 3525 install 3526 look 3527 ls 3528 make 3529 notest 3530 perldoc 3531 readme 3532 reports 3533 test 3534 )) { 3535 *$command = sub { shift->rematein($command, @_); }; 3536 } 3537 } 3538 3539 package CPAN::LWP::UserAgent; 3540 use strict; 3541 3542 sub config { 3543 return if $SETUPDONE; 3544 if ($CPAN::META->has_usable('LWP::UserAgent')) { 3545 require LWP::UserAgent; 3546 @ISA = qw(Exporter LWP::UserAgent); 3547 $SETUPDONE++; 3548 } else { 3549 $CPAN::Frontend->mywarn(" LWP::UserAgent not available\n"); 3550 } 3551 } 3552 3553 sub get_basic_credentials { 3554 my($self, $realm, $uri, $proxy) = @_; 3555 if ($USER && $PASSWD) { 3556 return ($USER, $PASSWD); 3557 } 3558 if ( $proxy ) { 3559 ($USER,$PASSWD) = $self->get_proxy_credentials(); 3560 } else { 3561 ($USER,$PASSWD) = $self->get_non_proxy_credentials(); 3562 } 3563 return($USER,$PASSWD); 3564 } 3565 3566 sub get_proxy_credentials { 3567 my $self = shift; 3568 my ($user, $password); 3569 if ( defined $CPAN::Config->{proxy_user} && 3570 defined $CPAN::Config->{proxy_pass}) { 3571 $user = $CPAN::Config->{proxy_user}; 3572 $password = $CPAN::Config->{proxy_pass}; 3573 return ($user, $password); 3574 } 3575 my $username_prompt = "\nProxy authentication needed! 3576 (Note: to permanently configure username and password run 3577 o conf proxy_user your_username 3578 o conf proxy_pass your_password 3579 )\nUsername:"; 3580 ($user, $password) = 3581 _get_username_and_password_from_user($username_prompt); 3582 return ($user,$password); 3583 } 3584 3585 sub get_non_proxy_credentials { 3586 my $self = shift; 3587 my ($user,$password); 3588 if ( defined $CPAN::Config->{username} && 3589 defined $CPAN::Config->{password}) { 3590 $user = $CPAN::Config->{username}; 3591 $password = $CPAN::Config->{password}; 3592 return ($user, $password); 3593 } 3594 my $username_prompt = "\nAuthentication needed! 3595 (Note: to permanently configure username and password run 3596 o conf username your_username 3597 o conf password your_password 3598 )\nUsername:"; 3599 3600 ($user, $password) = 3601 _get_username_and_password_from_user($username_prompt); 3602 return ($user,$password); 3603 } 3604 3605 sub _get_username_and_password_from_user { 3606 my $username_message = shift; 3607 my ($username,$password); 3608 3609 ExtUtils::MakeMaker->import(qw(prompt)); 3610 $username = prompt($username_message); 3611 if ($CPAN::META->has_inst("Term::ReadKey")) { 3612 Term::ReadKey::ReadMode("noecho"); 3613 } 3614 else { 3615 $CPAN::Frontend->mywarn( 3616 "Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal!\n" 3617 ); 3618 } 3619 $password = prompt("Password:"); 3620 3621 if ($CPAN::META->has_inst("Term::ReadKey")) { 3622 Term::ReadKey::ReadMode("restore"); 3623 } 3624 $CPAN::Frontend->myprint("\n\n"); 3625 return ($username,$password); 3626 } 3627 3628 # mirror(): Its purpose is to deal with proxy authentication. When we 3629 # call SUPER::mirror, we relly call the mirror method in 3630 # LWP::UserAgent. LWP::UserAgent will then call 3631 # $self->get_basic_credentials or some equivalent and this will be 3632 # $self->dispatched to our own get_basic_credentials method. 3633 3634 # Our own get_basic_credentials sets $USER and $PASSWD, two globals. 3635 3636 # 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means 3637 # although we have gone through our get_basic_credentials, the proxy 3638 # server refuses to connect. This could be a case where the username or 3639 # password has changed in the meantime, so I'm trying once again without 3640 # $USER and $PASSWD to give the get_basic_credentials routine another 3641 # chance to set $USER and $PASSWD. 3642 3643 # mirror(): Its purpose is to deal with proxy authentication. When we 3644 # call SUPER::mirror, we relly call the mirror method in 3645 # LWP::UserAgent. LWP::UserAgent will then call 3646 # $self->get_basic_credentials or some equivalent and this will be 3647 # $self->dispatched to our own get_basic_credentials method. 3648 3649 # Our own get_basic_credentials sets $USER and $PASSWD, two globals. 3650 3651 # 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means 3652 # although we have gone through our get_basic_credentials, the proxy 3653 # server refuses to connect. This could be a case where the username or 3654 # password has changed in the meantime, so I'm trying once again without 3655 # $USER and $PASSWD to give the get_basic_credentials routine another 3656 # chance to set $USER and $PASSWD. 3657 3658 sub mirror { 3659 my($self,$url,$aslocal) = @_; 3660 my $result = $self->SUPER::mirror($url,$aslocal); 3661 if ($result->code == 407) { 3662 undef $USER; 3663 undef $PASSWD; 3664 $result = $self->SUPER::mirror($url,$aslocal); 3665 } 3666 $result; 3667 } 3668 3669 package CPAN::FTP; 3670 use strict; 3671 3672 #-> sub CPAN::FTP::ftp_statistics 3673 # if they want to rewrite, they need to pass in a filehandle 3674 sub _ftp_statistics { 3675 my($self,$fh) = @_; 3676 my $locktype = $fh ? LOCK_EX : LOCK_SH; 3677 $fh ||= FileHandle->new; 3678 my $file = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml"); 3679 open $fh, "+>>$file" or $CPAN::Frontend->mydie("Could not open '$file': $!"); 3680 my $sleep = 1; 3681 my $waitstart; 3682 while (!CPAN::_flock($fh, $locktype|LOCK_NB)) { 3683 $waitstart ||= localtime(); 3684 if ($sleep>3) { 3685 $CPAN::Frontend->mywarn("Waiting for a read lock on '$file' (since $waitstart)\n"); 3686 } 3687 $CPAN::Frontend->mysleep($sleep); 3688 if ($sleep <= 3) { 3689 $sleep+=0.33; 3690 } elsif ($sleep <=6) { 3691 $sleep+=0.11; 3692 } 3693 } 3694 my $stats = eval { CPAN->_yaml_loadfile($file); }; 3695 if ($@) { 3696 if (ref $@) { 3697 if (ref $@ eq "CPAN::Exception::yaml_not_installed") { 3698 $CPAN::Frontend->myprint("Warning (usually harmless): $@"); 3699 return; 3700 } elsif (ref $@ eq "CPAN::Exception::yaml_process_error") { 3701 $CPAN::Frontend->mydie($@); 3702 } 3703 } else { 3704 $CPAN::Frontend->mydie($@); 3705 } 3706 } 3707 return $stats->[0]; 3708 } 3709 3710 #-> sub CPAN::FTP::_mytime 3711 sub _mytime () { 3712 if (CPAN->has_inst("Time::HiRes")) { 3713 return Time::HiRes::time(); 3714 } else { 3715 return time; 3716 } 3717 } 3718 3719 #-> sub CPAN::FTP::_new_stats 3720 sub _new_stats { 3721 my($self,$file) = @_; 3722 my $ret = { 3723 file => $file, 3724 attempts => [], 3725 start => _mytime, 3726 }; 3727 $ret; 3728 } 3729 3730 #-> sub CPAN::FTP::_add_to_statistics 3731 sub _add_to_statistics { 3732 my($self,$stats) = @_; 3733 my $yaml_module = CPAN::_yaml_module; 3734 $self->debug("yaml_module[$yaml_module]") if $CPAN::DEBUG; 3735 if ($CPAN::META->has_inst($yaml_module)) { 3736 $stats->{thesiteurl} = $ThesiteURL; 3737 if (CPAN->has_inst("Time::HiRes")) { 3738 $stats->{end} = Time::HiRes::time(); 3739 } else { 3740 $stats->{end} = time; 3741 } 3742 my $fh = FileHandle->new; 3743 my $time = time; 3744 my $sdebug = 0; 3745 my @debug; 3746 @debug = $time if $sdebug; 3747 my $fullstats = $self->_ftp_statistics($fh); 3748 close $fh; 3749 $fullstats->{history} ||= []; 3750 push @debug, scalar @{$fullstats->{history}} if $sdebug; 3751 push @debug, time if $sdebug; 3752 push @{$fullstats->{history}}, $stats; 3753 # arbitrary hardcoded constants until somebody demands to have 3754 # them settable; YAML.pm 0.62 is unacceptably slow with 999; 3755 # YAML::Syck 0.82 has no noticable performance problem with 999; 3756 while ( 3757 @{$fullstats->{history}} > 99 3758 || $time - $fullstats->{history}[0]{start} > 14*86400 3759 ) { 3760 shift @{$fullstats->{history}} 3761 } 3762 push @debug, scalar @{$fullstats->{history}} if $sdebug; 3763 push @debug, time if $sdebug; 3764 push @debug, scalar localtime($fullstats->{history}[0]{start}) if $sdebug; 3765 # need no eval because if this fails, it is serious 3766 my $sfile = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml"); 3767 CPAN->_yaml_dumpfile("$sfile.$$",$fullstats); 3768 if ( $sdebug ) { 3769 local $CPAN::DEBUG = 512; # FTP 3770 push @debug, time; 3771 CPAN->debug(sprintf("DEBUG history: before_read[%d]before[%d]at[%d]". 3772 "after[%d]at[%d]oldest[%s]dumped backat[%d]", 3773 @debug, 3774 )); 3775 } 3776 # Win32 cannot rename a file to an existing filename 3777 unlink($sfile) if ($^O eq 'MSWin32'); 3778 rename "$sfile.$$", $sfile 3779 or $CPAN::Frontend->mydie("Could not rename '$sfile.$$' to '$sfile': $!\n"); 3780 } 3781 } 3782 3783 # if file is CHECKSUMS, suggest the place where we got the file to be 3784 # checked from, maybe only for young files? 3785 #-> sub CPAN::FTP::_recommend_url_for 3786 sub _recommend_url_for { 3787 my($self, $file) = @_; 3788 my $urllist = $self->_get_urllist; 3789 if ($file =~ s|/CHECKSUMS(.gz)?$||) { 3790 my $fullstats = $self->_ftp_statistics(); 3791 my $history = $fullstats->{history} || []; 3792 while (my $last = pop @$history) { 3793 last if $last->{end} - time > 3600; # only young results are interesting 3794 next unless $last->{file}; # dirname of nothing dies! 3795 next unless $file eq File::Basename::dirname($last->{file}); 3796 return $last->{thesiteurl}; 3797 } 3798 } 3799 if ($CPAN::Config->{randomize_urllist} 3800 && 3801 rand(1) < $CPAN::Config->{randomize_urllist} 3802 ) { 3803 $urllist->[int rand scalar @$urllist]; 3804 } else { 3805 return (); 3806 } 3807 } 3808 3809 #-> sub CPAN::FTP::_get_urllist 3810 sub _get_urllist { 3811 my($self) = @_; 3812 $CPAN::Config->{urllist} ||= []; 3813 unless (ref $CPAN::Config->{urllist} eq 'ARRAY') { 3814 $CPAN::Frontend->mywarn("Malformed urllist; ignoring. Configuration file corrupt?\n"); 3815 $CPAN::Config->{urllist} = []; 3816 } 3817 my @urllist = grep { defined $_ and length $_ } @{$CPAN::Config->{urllist}}; 3818 for my $u (@urllist) { 3819 CPAN->debug("u[$u]") if $CPAN::DEBUG; 3820 if (UNIVERSAL::can($u,"text")) { 3821 $u->{TEXT} .= "/" unless substr($u->{TEXT},-1) eq "/"; 3822 } else { 3823 $u .= "/" unless substr($u,-1) eq "/"; 3824 $u = CPAN::URL->new(TEXT => $u, FROM => "USER"); 3825 } 3826 } 3827 \@urllist; 3828 } 3829 3830 #-> sub CPAN::FTP::ftp_get ; 3831 sub ftp_get { 3832 my($class,$host,$dir,$file,$target) = @_; 3833 $class->debug( 3834 qq[Going to fetch file [$file] from dir [$dir] 3835 on host [$host] as local [$target]\n] 3836 ) if $CPAN::DEBUG; 3837 my $ftp = Net::FTP->new($host); 3838 unless ($ftp) { 3839 $CPAN::Frontend->mywarn(" Could not connect to host '$host' with Net::FTP\n"); 3840 return; 3841 } 3842 return 0 unless defined $ftp; 3843 $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG; 3844 $class->debug(qq[Going to login("anonymous","$Config::Config{cf_email}")]); 3845 unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ) { 3846 my $msg = $ftp->message; 3847 $CPAN::Frontend->mywarn(" Couldn't login on $host: $msg"); 3848 return; 3849 } 3850 unless ( $ftp->cwd($dir) ) { 3851 my $msg = $ftp->message; 3852 $CPAN::Frontend->mywarn(" Couldn't cwd $dir: $msg"); 3853 return; 3854 } 3855 $ftp->binary; 3856 $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG; 3857 unless ( $ftp->get($file,$target) ) { 3858 my $msg = $ftp->message; 3859 $CPAN::Frontend->mywarn(" Couldn't fetch $file from $host: $msg"); 3860 return; 3861 } 3862 $ftp->quit; # it's ok if this fails 3863 return 1; 3864 } 3865 3866 # If more accuracy is wanted/needed, Chris Leach sent me this patch... 3867 3868 # > *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997 3869 # > --- /tmp/cp Wed Sep 24 13:26:40 1997 3870 # > *************** 3871 # > *** 1562,1567 **** 3872 # > --- 1562,1580 ---- 3873 # > return 1 if substr($url,0,4) eq "file"; 3874 # > return 1 unless $url =~ m|://([^/]+)|; 3875 # > my $host = $1; 3876 # > + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'}; 3877 # > + if ($proxy) { 3878 # > + $proxy =~ m|://([^/:]+)|; 3879 # > + $proxy = $1; 3880 # > + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'}; 3881 # > + if ($noproxy) { 3882 # > + if ($host !~ /$noproxy$/) { 3883 # > + $host = $proxy; 3884 # > + } 3885 # > + } else { 3886 # > + $host = $proxy; 3887 # > + } 3888 # > + } 3889 # > require Net::Ping; 3890 # > return 1 unless $Net::Ping::VERSION >= 2; 3891 # > my $p; 3892 3893 3894 #-> sub CPAN::FTP::localize ; 3895 sub localize { 3896 my($self,$file,$aslocal,$force) = @_; 3897 $force ||= 0; 3898 Carp::croak "Usage: ->localize(cpan_file,as_local_file[,$force])" 3899 unless defined $aslocal; 3900 $self->debug("file[$file] aslocal[$aslocal] force[$force]") 3901 if $CPAN::DEBUG; 3902 3903 if ($^O eq 'MacOS') { 3904 # Comment by AK on 2000-09-03: Uniq short filenames would be 3905 # available in CHECKSUMS file 3906 my($name, $path) = File::Basename::fileparse($aslocal, ''); 3907 if (length($name) > 31) { 3908 $name =~ s/( 3909 \.( 3910 readme(\.(gz|Z))? | 3911 (tar\.)?(gz|Z) | 3912 tgz | 3913 zip | 3914 pm\.(gz|Z) 3915 ) 3916 )$//x; 3917 my $suf = $1; 3918 my $size = 31 - length($suf); 3919 while (length($name) > $size) { 3920 chop $name; 3921 } 3922 $name .= $suf; 3923 $aslocal = File::Spec->catfile($path, $name); 3924 } 3925 } 3926 3927 if (-f $aslocal && -r _ && !($force & 1)) { 3928 my $size; 3929 if ($size = -s $aslocal) { 3930 $self->debug("aslocal[$aslocal]size[$size]") if $CPAN::DEBUG; 3931 return $aslocal; 3932 } else { 3933 # empty file from a previous unsuccessful attempt to download it 3934 unlink $aslocal or 3935 $CPAN::Frontend->mydie("Found a zero-length '$aslocal' that I ". 3936 "could not remove."); 3937 } 3938 } 3939 my($maybe_restore) = 0; 3940 if (-f $aslocal) { 3941 rename $aslocal, "$aslocal.bak$$"; 3942 $maybe_restore++; 3943 } 3944 3945 my($aslocal_dir) = File::Basename::dirname($aslocal); 3946 $self->mymkpath($aslocal_dir); # too early for file URLs / RT #28438 3947 # Inheritance is not easier to manage than a few if/else branches 3948 if ($CPAN::META->has_usable('LWP::UserAgent')) { 3949 unless ($Ua) { 3950 CPAN::LWP::UserAgent->config; 3951 eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough? 3952 if ($@) { 3953 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n") 3954 if $CPAN::DEBUG; 3955 } else { 3956 my($var); 3957 $Ua->proxy('ftp', $var) 3958 if $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy}; 3959 $Ua->proxy('http', $var) 3960 if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy}; 3961 $Ua->no_proxy($var) 3962 if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy}; 3963 } 3964 } 3965 } 3966 for my $prx (qw(ftp_proxy http_proxy no_proxy)) { 3967 $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx}; 3968 } 3969 3970 # Try the list of urls for each single object. We keep a record 3971 # where we did get a file from 3972 my(@reordered,$last); 3973 my $ccurllist = $self->_get_urllist; 3974 $last = $#$ccurllist; 3975 if ($force & 2) { # local cpans probably out of date, don't reorder 3976 @reordered = (0..$last); 3977 } else { 3978 @reordered = 3979 sort { 3980 (substr($ccurllist->[$b],0,4) eq "file") 3981 <=> 3982 (substr($ccurllist->[$a],0,4) eq "file") 3983 or 3984 defined($ThesiteURL) 3985 and 3986 ($ccurllist->[$b] eq $ThesiteURL) 3987 <=> 3988 ($ccurllist->[$a] eq $ThesiteURL) 3989 } 0..$last; 3990 } 3991 my(@levels); 3992 $Themethod ||= ""; 3993 $self->debug("Themethod[$Themethod]reordered[@reordered]") if $CPAN::DEBUG; 3994 my @all_levels = ( 3995 ["dleasy", "file"], 3996 ["dleasy"], 3997 ["dlhard"], 3998 ["dlhardest"], 3999 ["dleasy", "http","defaultsites"], 4000 ["dlhard", "http","defaultsites"], 4001 ["dleasy", "ftp", "defaultsites"], 4002 ["dlhard", "ftp", "defaultsites"], 4003 ["dlhardest","", "defaultsites"], 4004 ); 4005 if ($Themethod) { 4006 @levels = grep {$_->[0] eq $Themethod} @all_levels; 4007 push @levels, grep {$_->[0] ne $Themethod} @all_levels; 4008 } else { 4009 @levels = @all_levels; 4010 } 4011 @levels = qw/dleasy/ if $^O eq 'MacOS'; 4012 my($levelno); 4013 local $ENV{FTP_PASSIVE} = 4014 exists $CPAN::Config->{ftp_passive} ? 4015 $CPAN::Config->{ftp_passive} : 1; 4016 my $ret; 4017 my $stats = $self->_new_stats($file); 4018 LEVEL: for $levelno (0..$#levels) { 4019 my $level_tuple = $levels[$levelno]; 4020 my($level,$scheme,$sitetag) = @$level_tuple; 4021 my $defaultsites = $sitetag && $sitetag eq "defaultsites"; 4022 my @urllist; 4023 if ($defaultsites) { 4024 unless (defined $connect_to_internet_ok) { 4025 $CPAN::Frontend->myprint(sprintf qq{ 4026 I would like to connect to one of the following sites to get '%s': 4027 4028 %s 4029 }, 4030 $file, 4031 join("",map { " ".$_->text."\n" } @CPAN::Defaultsites), 4032 ); 4033 my $answer = CPAN::Shell::colorable_makemaker_prompt("Is it OK to try to connect to the Internet?", "yes"); 4034 if ($answer =~ /^y/i) { 4035 $connect_to_internet_ok = 1; 4036 } else { 4037 $connect_to_internet_ok = 0; 4038 } 4039 } 4040 if ($connect_to_internet_ok) { 4041 @urllist = @CPAN::Defaultsites; 4042 } else { 4043 @urllist = (); 4044 } 4045 } else { 4046 my @host_seq = $level =~ /dleasy/ ? 4047 @reordered : 0..$last; # reordered has file and $Thesiteurl first 4048 @urllist = map { $ccurllist->[$_] } @host_seq; 4049 } 4050 $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG; 4051 my $aslocal_tempfile = $aslocal . ".tmp" . $$; 4052 if (my $recommend = $self->_recommend_url_for($file)) { 4053 @urllist = grep { $_ ne $recommend } @urllist; 4054 unshift @urllist, $recommend; 4055 } 4056 $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG; 4057 $ret = $self->hostdlxxx($level,$scheme,\@urllist,$file,$aslocal_tempfile,$stats); 4058 if ($ret) { 4059 CPAN->debug("ret[$ret]aslocal[$aslocal]") if $CPAN::DEBUG; 4060 if ($ret eq $aslocal_tempfile) { 4061 # if we got it exactly as we asked for, only then we 4062 # want to rename 4063 rename $aslocal_tempfile, $aslocal 4064 or $CPAN::Frontend->mydie("Error while trying to rename ". 4065 "'$ret' to '$aslocal': $!"); 4066 $ret = $aslocal; 4067 } 4068 $Themethod = $level; 4069 my $now = time; 4070 # utime $now, $now, $aslocal; # too bad, if we do that, we 4071 # might alter a local mirror 4072 $self->debug("level[$level]") if $CPAN::DEBUG; 4073 last LEVEL; 4074 } else { 4075 unlink $aslocal_tempfile; 4076 last if $CPAN::Signal; # need to cleanup 4077 } 4078 } 4079 if ($ret) { 4080 $stats->{filesize} = -s $ret; 4081 } 4082 $self->debug("before _add_to_statistics") if $CPAN::DEBUG; 4083 $self->_add_to_statistics($stats); 4084 $self->debug("after _add_to_statistics") if $CPAN::DEBUG; 4085 if ($ret) { 4086 unlink "$aslocal.bak$$"; 4087 return $ret; 4088 } 4089 unless ($CPAN::Signal) { 4090 my(@mess); 4091 local $" = " "; 4092 if (@{$CPAN::Config->{urllist}}) { 4093 push @mess, 4094 qq{Please check, if the URLs I found in your configuration file \(}. 4095 join(", ", @{$CPAN::Config->{urllist}}). 4096 qq{\) are valid.}; 4097 } else { 4098 push @mess, qq{Your urllist is empty!}; 4099 } 4100 push @mess, qq{The urllist can be edited.}, 4101 qq{E.g. with 'o conf urllist push ftp://myurl/'}; 4102 $CPAN::Frontend->mywarn(Text::Wrap::wrap("","","@mess"). "\n\n"); 4103 $CPAN::Frontend->mywarn("Could not fetch $file\n"); 4104 $CPAN::Frontend->mysleep(2); 4105 } 4106 if ($maybe_restore) { 4107 rename "$aslocal.bak$$", $aslocal; 4108 $CPAN::Frontend->myprint("Trying to get away with old file:\n" . 4109 $self->ls($aslocal)); 4110 return $aslocal; 4111 } 4112 return; 4113 } 4114 4115 sub mymkpath { 4116 my($self, $aslocal_dir) = @_; 4117 File::Path::mkpath($aslocal_dir); 4118 $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }. 4119 qq{directory "$aslocal_dir". 4120 I\'ll continue, but if you encounter problems, they may be due 4121 to insufficient permissions.\n}) unless -w $aslocal_dir; 4122 } 4123 4124 sub hostdlxxx { 4125 my $self = shift; 4126 my $level = shift; 4127 my $scheme = shift; 4128 my $h = shift; 4129 $h = [ grep /^\Q$scheme\E:/, @$h ] if $scheme; 4130 my $method = "host$level"; 4131 $self->$method($h, @_); 4132 } 4133 4134 sub _set_attempt { 4135 my($self,$stats,$method,$url) = @_; 4136 push @{$stats->{attempts}}, { 4137 method => $method, 4138 start => _mytime, 4139 url => $url, 4140 }; 4141 } 4142 4143 # package CPAN::FTP; 4144 sub hostdleasy { 4145 my($self,$host_seq,$file,$aslocal,$stats) = @_; 4146 my($ro_url); 4147 HOSTEASY: for $ro_url (@$host_seq) { 4148 $self->_set_attempt($stats,"dleasy",$ro_url); 4149 my $url .= "$ro_url$file"; 4150 $self->debug("localizing perlish[$url]") if $CPAN::DEBUG; 4151 if ($url =~ /^file:/) { 4152 my $l; 4153 if ($CPAN::META->has_inst('URI::URL')) { 4154 my $u = URI::URL->new($url); 4155 $l = $u->path; 4156 } else { # works only on Unix, is poorly constructed, but 4157 # hopefully better than nothing. 4158 # RFC 1738 says fileurl BNF is 4159 # fileurl = "file://" [ host | "localhost" ] "/" fpath 4160 # Thanks to "Mark D. Baushke" <mdb@cisco.com> for 4161 # the code 4162 ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part 4163 $l =~ s|^file:||; # assume they 4164 # meant 4165 # file://localhost 4166 $l =~ s|^/||s 4167 if ! -f $l && $l =~ m|^/\w:|; # e.g. /P: 4168 } 4169 $self->debug("local file[$l]") if $CPAN::DEBUG; 4170 if ( -f $l && -r _) { 4171 $ThesiteURL = $ro_url; 4172 return $l; 4173 } 4174 if ($l =~ /(.+)\.gz$/) { 4175 my $ungz = $1; 4176 if ( -f $ungz && -r _) { 4177 $ThesiteURL = $ro_url; 4178 return $ungz; 4179 } 4180 } 4181 # Maybe mirror has compressed it? 4182 if (-f "$l.gz") { 4183 $self->debug("found compressed $l.gz") if $CPAN::DEBUG; 4184 eval { CPAN::Tarzip->new("$l.gz")->gunzip($aslocal) }; 4185 if ( -f $aslocal) { 4186 $ThesiteURL = $ro_url; 4187 return $aslocal; 4188 } 4189 } 4190 $CPAN::Frontend->mywarn("Could not find '$l'\n"); 4191 } 4192 $self->debug("it was not a file URL") if $CPAN::DEBUG; 4193 if ($CPAN::META->has_usable('LWP')) { 4194 $CPAN::Frontend->myprint("Fetching with LWP: 4195 $url 4196 "); 4197 unless ($Ua) { 4198 CPAN::LWP::UserAgent->config; 4199 eval { $Ua = CPAN::LWP::UserAgent->new; }; 4200 if ($@) { 4201 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n"); 4202 } 4203 } 4204 my $res = $Ua->mirror($url, $aslocal); 4205 if ($res->is_success) { 4206 $ThesiteURL = $ro_url; 4207 my $now = time; 4208 utime $now, $now, $aslocal; # download time is more 4209 # important than upload 4210 # time 4211 return $aslocal; 4212 } elsif ($url !~ /\.gz(?!\n)\Z/) { 4213 my $gzurl = "$url.gz"; 4214 $CPAN::Frontend->myprint("Fetching with LWP: 4215 $gzurl 4216 "); 4217 $res = $Ua->mirror($gzurl, "$aslocal.gz"); 4218 if ($res->is_success) { 4219 if (eval {CPAN::Tarzip->new("$aslocal.gz")->gunzip($aslocal)}) { 4220 $ThesiteURL = $ro_url; 4221 return $aslocal; 4222 } 4223 } 4224 } else { 4225 $CPAN::Frontend->myprint(sprintf( 4226 "LWP failed with code[%s] message[%s]\n", 4227 $res->code, 4228 $res->message, 4229 )); 4230 # Alan Burlison informed me that in firewall environments 4231 # Net::FTP can still succeed where LWP fails. So we do not 4232 # skip Net::FTP anymore when LWP is available. 4233 } 4234 } else { 4235 $CPAN::Frontend->mywarn(" LWP not available\n"); 4236 } 4237 return if $CPAN::Signal; 4238 if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 4239 # that's the nice and easy way thanks to Graham 4240 $self->debug("recognized ftp") if $CPAN::DEBUG; 4241 my($host,$dir,$getfile) = ($1,$2,$3); 4242 if ($CPAN::META->has_usable('Net::FTP')) { 4243 $dir =~ s|/+|/|g; 4244 $CPAN::Frontend->myprint("Fetching with Net::FTP: 4245 $url 4246 "); 4247 $self->debug("getfile[$getfile]dir[$dir]host[$host]" . 4248 "aslocal[$aslocal]") if $CPAN::DEBUG; 4249 if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) { 4250 $ThesiteURL = $ro_url; 4251 return $aslocal; 4252 } 4253 if ($aslocal !~ /\.gz(?!\n)\Z/) { 4254 my $gz = "$aslocal.gz"; 4255 $CPAN::Frontend->myprint("Fetching with Net::FTP 4256 $url.gz 4257 "); 4258 if (CPAN::FTP->ftp_get($host, 4259 $dir, 4260 "$getfile.gz", 4261 $gz) && 4262 eval{CPAN::Tarzip->new($gz)->gunzip($aslocal)} 4263 ) { 4264 $ThesiteURL = $ro_url; 4265 return $aslocal; 4266 } 4267 } 4268 # next HOSTEASY; 4269 } else { 4270 CPAN->debug("Net::FTP does not count as usable atm") if $CPAN::DEBUG; 4271 } 4272 } 4273 if ( 4274 UNIVERSAL::can($ro_url,"text") 4275 and 4276 $ro_url->{FROM} eq "USER" 4277 ) { 4278 ##address #17973: default URLs should not try to override 4279 ##user-defined URLs just because LWP is not available 4280 my $ret = $self->hostdlhard([$ro_url],$file,$aslocal,$stats); 4281 return $ret if $ret; 4282 } 4283 return if $CPAN::Signal; 4284 } 4285 } 4286 4287 # package CPAN::FTP; 4288 sub hostdlhard { 4289 my($self,$host_seq,$file,$aslocal,$stats) = @_; 4290 4291 # Came back if Net::FTP couldn't establish connection (or 4292 # failed otherwise) Maybe they are behind a firewall, but they 4293 # gave us a socksified (or other) ftp program... 4294 4295 my($ro_url); 4296 my($devnull) = $CPAN::Config->{devnull} || ""; 4297 # < /dev/null "; 4298 my($aslocal_dir) = File::Basename::dirname($aslocal); 4299 File::Path::mkpath($aslocal_dir); 4300 HOSTHARD: for $ro_url (@$host_seq) { 4301 $self->_set_attempt($stats,"dlhard",$ro_url); 4302 my $url = "$ro_url$file"; 4303 my($proto,$host,$dir,$getfile); 4304 4305 # Courtesy Mark Conty mark_conty@cargill.com change from 4306 # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 4307 # to 4308 if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) { 4309 # proto not yet used 4310 ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4); 4311 } else { 4312 next HOSTHARD; # who said, we could ftp anything except ftp? 4313 } 4314 next HOSTHARD if $proto eq "file"; # file URLs would have had 4315 # success above. Likely a bogus URL 4316 4317 $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG; 4318 4319 # Try the most capable first and leave ncftp* for last as it only 4320 # does FTP. 4321 DLPRG: for my $f (qw(curl wget lynx ncftpget ncftp)) { 4322 my $funkyftp = CPAN::HandleConfig->safe_quote($CPAN::Config->{$f}); 4323 next unless defined $funkyftp; 4324 next if $funkyftp =~ /^\s*$/; 4325 4326 my($asl_ungz, $asl_gz); 4327 ($asl_ungz = $aslocal) =~ s/\.gz//; 4328 $asl_gz = "$asl_ungz.gz"; 4329 4330 my($src_switch) = ""; 4331 my($chdir) = ""; 4332 my($stdout_redir) = " > $asl_ungz"; 4333 if ($f eq "lynx") { 4334 $src_switch = " -source"; 4335 } elsif ($f eq "ncftp") { 4336 $src_switch = " -c"; 4337 } elsif ($f eq "wget") { 4338 $src_switch = " -O $asl_ungz"; 4339 $stdout_redir = ""; 4340 } elsif ($f eq 'curl') { 4341 $src_switch = ' -L -f -s -S --netrc-optional'; 4342 } 4343 4344 if ($f eq "ncftpget") { 4345 $chdir = "cd $aslocal_dir && "; 4346 $stdout_redir = ""; 4347 } 4348 $CPAN::Frontend->myprint( 4349 qq[ 4350 Trying with "$funkyftp$src_switch" to get 4351 $url 4352 ]); 4353 my($system) = 4354 "$chdir$funkyftp$src_switch \"$url\" $devnull$stdout_redir"; 4355 $self->debug("system[$system]") if $CPAN::DEBUG; 4356 my($wstatus) = system($system); 4357 if ($f eq "lynx") { 4358 # lynx returns 0 when it fails somewhere 4359 if (-s $asl_ungz) { 4360 my $content = do { local *FH; 4361 open FH, $asl_ungz or die; 4362 local $/; 4363 <FH> }; 4364 if ($content =~ /^<.*(<title>[45]|Error [45])/si) { 4365 $CPAN::Frontend->mywarn(qq{ 4366 No success, the file that lynx has downloaded looks like an error message: 4367 $content 4368 }); 4369 $CPAN::Frontend->mysleep(1); 4370 next DLPRG; 4371 } 4372 } else { 4373 $CPAN::Frontend->myprint(qq{ 4374 No success, the file that lynx has downloaded is an empty file. 4375 }); 4376 next DLPRG; 4377 } 4378 } 4379 if ($wstatus == 0) { 4380 if (-s $aslocal) { 4381 # Looks good 4382 } elsif ($asl_ungz ne $aslocal) { 4383 # test gzip integrity 4384 if (eval{CPAN::Tarzip->new($asl_ungz)->gtest}) { 4385 # e.g. foo.tar is gzipped --> foo.tar.gz 4386 rename $asl_ungz, $aslocal; 4387 } else { 4388 eval{CPAN::Tarzip->new($asl_gz)->gzip($asl_ungz)}; 4389 } 4390 } 4391 $ThesiteURL = $ro_url; 4392 return $aslocal; 4393 } elsif ($url !~ /\.gz(?!\n)\Z/) { 4394 unlink $asl_ungz if 4395 -f $asl_ungz && -s _ == 0; 4396 my $gz = "$aslocal.gz"; 4397 my $gzurl = "$url.gz"; 4398 $CPAN::Frontend->myprint( 4399 qq[ 4400 Trying with "$funkyftp$src_switch" to get 4401 $url.gz 4402 ]); 4403 my($system) = "$funkyftp$src_switch \"$url.gz\" $devnull > $asl_gz"; 4404 $self->debug("system[$system]") if $CPAN::DEBUG; 4405 my($wstatus); 4406 if (($wstatus = system($system)) == 0 4407 && 4408 -s $asl_gz 4409 ) { 4410 # test gzip integrity 4411 my $ct = eval{CPAN::Tarzip->new($asl_gz)}; 4412 if ($ct && $ct->gtest) { 4413 $ct->gunzip($aslocal); 4414 } else { 4415 # somebody uncompressed file for us? 4416 rename $asl_ungz, $aslocal; 4417 } 4418 $ThesiteURL = $ro_url; 4419 return $aslocal; 4420 } else { 4421 unlink $asl_gz if -f $asl_gz; 4422 } 4423 } else { 4424 my $estatus = $wstatus >> 8; 4425 my $size = -f $aslocal ? 4426 ", left\n$aslocal with size ".-s _ : 4427 "\nWarning: expected file [$aslocal] doesn't exist"; 4428 $CPAN::Frontend->myprint(qq{ 4429 System call "$system" 4430 returned status $estatus (wstat $wstatus)$size 4431 }); 4432 } 4433 return if $CPAN::Signal; 4434 } # transfer programs 4435 } # host 4436 } 4437 4438 # package CPAN::FTP; 4439 sub hostdlhardest { 4440 my($self,$host_seq,$file,$aslocal,$stats) = @_; 4441 4442 return unless @$host_seq; 4443 my($ro_url); 4444 my($aslocal_dir) = File::Basename::dirname($aslocal); 4445 File::Path::mkpath($aslocal_dir); 4446 my $ftpbin = $CPAN::Config->{ftp}; 4447 unless ($ftpbin && length $ftpbin && MM->maybe_command($ftpbin)) { 4448 $CPAN::Frontend->myprint("No external ftp command available\n\n"); 4449 return; 4450 } 4451 $CPAN::Frontend->mywarn(qq{ 4452 As a last ressort we now switch to the external ftp command '$ftpbin' 4453 to get '$aslocal'. 4454 4455 Doing so often leads to problems that are hard to diagnose. 4456 4457 If you're victim of such problems, please consider unsetting the ftp 4458 config variable with 4459 4460 o conf ftp "" 4461 o conf commit 4462 4463 }); 4464 $CPAN::Frontend->mysleep(2); 4465 HOSTHARDEST: for $ro_url (@$host_seq) { 4466 $self->_set_attempt($stats,"dlhardest",$ro_url); 4467 my $url = "$ro_url$file"; 4468 $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG; 4469 unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { 4470 next; 4471 } 4472 my($host,$dir,$getfile) = ($1,$2,$3); 4473 my $timestamp = 0; 4474 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime, 4475 $ctime,$blksize,$blocks) = stat($aslocal); 4476 $timestamp = $mtime ||= 0; 4477 my($netrc) = CPAN::FTP::netrc->new; 4478 my($netrcfile) = $netrc->netrc; 4479 my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : ""; 4480 my $targetfile = File::Basename::basename($aslocal); 4481 my(@dialog); 4482 push( 4483 @dialog, 4484 "lcd $aslocal_dir", 4485 "cd /", 4486 map("cd $_", split /\//, $dir), # RFC 1738 4487 "bin", 4488 "get $getfile $targetfile", 4489 "quit" 4490 ); 4491 if (! $netrcfile) { 4492 CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG; 4493 } elsif ($netrc->hasdefault || $netrc->contains($host)) { 4494 CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]", 4495 $netrc->hasdefault, 4496 $netrc->contains($host))) if $CPAN::DEBUG; 4497 if ($netrc->protected) { 4498 my $dialog = join "", map { " $_\n" } @dialog; 4499 my $netrc_explain; 4500 if ($netrc->contains($host)) { 4501 $netrc_explain = "Relying that your .netrc entry for '$host' ". 4502 "manages the login"; 4503 } else { 4504 $netrc_explain = "Relying that your default .netrc entry ". 4505 "manages the login"; 4506 } 4507 $CPAN::Frontend->myprint(qq{ 4508 Trying with external ftp to get 4509 $url 4510 $netrc_explain 4511 Going to send the dialog 4512 $dialog 4513 } 4514 ); 4515 $self->talk_ftp("$ftpbin$verbose $host", 4516 @dialog); 4517 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 4518 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); 4519 $mtime ||= 0; 4520 if ($mtime > $timestamp) { 4521 $CPAN::Frontend->myprint("GOT $aslocal\n"); 4522 $ThesiteURL = $ro_url; 4523 return $aslocal; 4524 } else { 4525 $CPAN::Frontend->myprint("Hmm... Still failed!\n"); 4526 } 4527 return if $CPAN::Signal; 4528 } else { 4529 $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }. 4530 qq{correctly protected.\n}); 4531 } 4532 } else { 4533 $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host 4534 nor does it have a default entry\n"); 4535 } 4536 4537 # OK, they don't have a valid ~/.netrc. Use 'ftp -n' 4538 # then and login manually to host, using e-mail as 4539 # password. 4540 $CPAN::Frontend->myprint(qq{Issuing "$ftpbin$verbose -n"\n}); 4541 unshift( 4542 @dialog, 4543 "open $host", 4544 "user anonymous $Config::Config{'cf_email'}" 4545 ); 4546 my $dialog = join "", map { " $_\n" } @dialog; 4547 $CPAN::Frontend->myprint(qq{ 4548 Trying with external ftp to get 4549 $url 4550 Going to send the dialog 4551 $dialog 4552 } 4553 ); 4554 $self->talk_ftp("$ftpbin$verbose -n", @dialog); 4555 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 4556 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); 4557 $mtime ||= 0; 4558 if ($mtime > $timestamp) { 4559 $CPAN::Frontend->myprint("GOT $aslocal\n"); 4560 $ThesiteURL = $ro_url; 4561 return $aslocal; 4562 } else { 4563 $CPAN::Frontend->myprint("Bad luck... Still failed!\n"); 4564 } 4565 return if $CPAN::Signal; 4566 $CPAN::Frontend->mywarn("Can't access URL $url.\n\n"); 4567 $CPAN::Frontend->mysleep(2); 4568 } # host 4569 } 4570 4571 # package CPAN::FTP; 4572 sub talk_ftp { 4573 my($self,$command,@dialog) = @_; 4574 my $fh = FileHandle->new; 4575 $fh->open("|$command") or die "Couldn't open ftp: $!"; 4576 foreach (@dialog) { $fh->print("$_\n") } 4577 $fh->close; # Wait for process to complete 4578 my $wstatus = $?; 4579 my $estatus = $wstatus >> 8; 4580 $CPAN::Frontend->myprint(qq{ 4581 Subprocess "|$command" 4582 returned status $estatus (wstat $wstatus) 4583 }) if $wstatus; 4584 } 4585 4586 # find2perl needs modularization, too, all the following is stolen 4587 # from there 4588 # CPAN::FTP::ls 4589 sub ls { 4590 my($self,$name) = @_; 4591 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm, 4592 $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name); 4593 4594 my($perms,%user,%group); 4595 my $pname = $name; 4596 4597 if ($blocks) { 4598 $blocks = int(($blocks + 1) / 2); 4599 } 4600 else { 4601 $blocks = int(($sizemm + 1023) / 1024); 4602 } 4603 4604 if (-f _) { $perms = '-'; } 4605 elsif (-d _) { $perms = 'd'; } 4606 elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; } 4607 elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; } 4608 elsif (-p _) { $perms = 'p'; } 4609 elsif (-S _) { $perms = 's'; } 4610 else { $perms = 'l'; $pname .= ' -> ' . readlink($_); } 4611 4612 my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx'); 4613 my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); 4614 my $tmpmode = $mode; 4615 my $tmp = $rwx[$tmpmode & 7]; 4616 $tmpmode >>= 3; 4617 $tmp = $rwx[$tmpmode & 7] . $tmp; 4618 $tmpmode >>= 3; 4619 $tmp = $rwx[$tmpmode & 7] . $tmp; 4620 substr($tmp,2,1) =~ tr/-x/Ss/ if -u _; 4621 substr($tmp,5,1) =~ tr/-x/Ss/ if -g _; 4622 substr($tmp,8,1) =~ tr/-x/Tt/ if -k _; 4623 $perms .= $tmp; 4624 4625 my $user = $user{$uid} || $uid; # too lazy to implement lookup 4626 my $group = $group{$gid} || $gid; 4627 4628 my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime); 4629 my($timeyear); 4630 my($moname) = $moname[$mon]; 4631 if (-M _ > 365.25 / 2) { 4632 $timeyear = $year + 1900; 4633 } 4634 else { 4635 $timeyear = sprintf("%02d:%02d", $hour, $min); 4636 } 4637 4638 sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n", 4639 $ino, 4640 $blocks, 4641 $perms, 4642 $nlink, 4643 $user, 4644 $group, 4645 $sizemm, 4646 $moname, 4647 $mday, 4648 $timeyear, 4649 $pname; 4650 } 4651 4652 package CPAN::FTP::netrc; 4653 use strict; 4654 4655 # package CPAN::FTP::netrc; 4656 sub new { 4657 my($class) = @_; 4658 my $home = CPAN::HandleConfig::home; 4659 my $file = File::Spec->catfile($home,".netrc"); 4660 4661 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, 4662 $atime,$mtime,$ctime,$blksize,$blocks) 4663 = stat($file); 4664 $mode ||= 0; 4665 my $protected = 0; 4666 4667 my($fh,@machines,$hasdefault); 4668 $hasdefault = 0; 4669 $fh = FileHandle->new or die "Could not create a filehandle"; 4670 4671 if($fh->open($file)) { 4672 $protected = ($mode & 077) == 0; 4673 local($/) = ""; 4674 NETRC: while (<$fh>) { 4675 my(@tokens) = split " ", $_; 4676 TOKEN: while (@tokens) { 4677 my($t) = shift @tokens; 4678 if ($t eq "default") { 4679 $hasdefault++; 4680 last NETRC; 4681 } 4682 last TOKEN if $t eq "macdef"; 4683 if ($t eq "machine") { 4684 push @machines, shift @tokens; 4685 } 4686 } 4687 } 4688 } else { 4689 $file = $hasdefault = $protected = ""; 4690 } 4691 4692 bless { 4693 'mach' => [@machines], 4694 'netrc' => $file, 4695 'hasdefault' => $hasdefault, 4696 'protected' => $protected, 4697 }, $class; 4698 } 4699 4700 # CPAN::FTP::netrc::hasdefault; 4701 sub hasdefault { shift->{'hasdefault'} } 4702 sub netrc { shift->{'netrc'} } 4703 sub protected { shift->{'protected'} } 4704 sub contains { 4705 my($self,$mach) = @_; 4706 for ( @{$self->{'mach'}} ) { 4707 return 1 if $_ eq $mach; 4708 } 4709 return 0; 4710 } 4711 4712 package CPAN::Complete; 4713 use strict; 4714 4715 sub gnu_cpl { 4716 my($text, $line, $start, $end) = @_; 4717 my(@perlret) = cpl($text, $line, $start); 4718 # find longest common match. Can anybody show me how to peruse 4719 # T::R::Gnu to have this done automatically? Seems expensive. 4720 return () unless @perlret; 4721 my($newtext) = $text; 4722 for (my $i = length($text)+1;;$i++) { 4723 last unless length($perlret[0]) && length($perlret[0]) >= $i; 4724 my $try = substr($perlret[0],0,$i); 4725 my @tries = grep {substr($_,0,$i) eq $try} @perlret; 4726 # warn "try[$try]tries[@tries]"; 4727 if (@tries == @perlret) { 4728 $newtext = $try; 4729 } else { 4730 last; 4731 } 4732 } 4733 ($newtext,@perlret); 4734 } 4735 4736 #-> sub CPAN::Complete::cpl ; 4737 sub cpl { 4738 my($word,$line,$pos) = @_; 4739 $word ||= ""; 4740 $line ||= ""; 4741 $pos ||= 0; 4742 CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 4743 $line =~ s/^\s*//; 4744 if ($line =~ s/^((?:notest|f?force)\s*)//) { 4745 $pos -= length($1); 4746 } 4747 my @return; 4748 if ($pos == 0 || $line =~ /^(?:h(?:elp)?|\?)\s/) { 4749 @return = grep /^\Q$word\E/, @CPAN::Complete::COMMANDS; 4750 } elsif ( $line !~ /^[\!abcdghimorutl]/ ) { 4751 @return = (); 4752 } elsif ($line =~ /^(a|ls)\s/) { 4753 @return = cplx('CPAN::Author',uc($word)); 4754 } elsif ($line =~ /^b\s/) { 4755 CPAN::Shell->local_bundles; 4756 @return = cplx('CPAN::Bundle',$word); 4757 } elsif ($line =~ /^d\s/) { 4758 @return = cplx('CPAN::Distribution',$word); 4759 } elsif ($line =~ m/^( 4760 [mru]|make|clean|dump|get|test|install|readme|look|cvs_import|perldoc|recent 4761 )\s/x ) { 4762 if ($word =~ /^Bundle::/) { 4763 CPAN::Shell->local_bundles; 4764 } 4765 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); 4766 } elsif ($line =~ /^i\s/) { 4767 @return = cpl_any($word); 4768 } elsif ($line =~ /^reload\s/) { 4769 @return = cpl_reload($word,$line,$pos); 4770 } elsif ($line =~ /^o\s/) { 4771 @return = cpl_option($word,$line,$pos); 4772 } elsif ($line =~ m/^\S+\s/ ) { 4773 # fallback for future commands and what we have forgotten above 4774 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); 4775 } else { 4776 @return = (); 4777 } 4778 return @return; 4779 } 4780 4781 #-> sub CPAN::Complete::cplx ; 4782 sub cplx { 4783 my($class, $word) = @_; 4784 if (CPAN::_sqlite_running) { 4785 $CPAN::SQLite->search($class, "^\Q$word\E"); 4786 } 4787 sort grep /^\Q$word\E/, map { $_->id } $CPAN::META->all_objects($class); 4788 } 4789 4790 #-> sub CPAN::Complete::cpl_any ; 4791 sub cpl_any { 4792 my($word) = shift; 4793 return ( 4794 cplx('CPAN::Author',$word), 4795 cplx('CPAN::Bundle',$word), 4796 cplx('CPAN::Distribution',$word), 4797 cplx('CPAN::Module',$word), 4798 ); 4799 } 4800 4801 #-> sub CPAN::Complete::cpl_reload ; 4802 sub cpl_reload { 4803 my($word,$line,$pos) = @_; 4804 $word ||= ""; 4805 my(@words) = split " ", $line; 4806 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 4807 my(@ok) = qw(cpan index); 4808 return @ok if @words == 1; 4809 return grep /^\Q$word\E/, @ok if @words == 2 && $word; 4810 } 4811 4812 #-> sub CPAN::Complete::cpl_option ; 4813 sub cpl_option { 4814 my($word,$line,$pos) = @_; 4815 $word ||= ""; 4816 my(@words) = split " ", $line; 4817 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; 4818 my(@ok) = qw(conf debug); 4819 return @ok if @words == 1; 4820 return grep /^\Q$word\E/, @ok if @words == 2 && length($word); 4821 if (0) { 4822 } elsif ($words[1] eq 'index') { 4823 return (); 4824 } elsif ($words[1] eq 'conf') { 4825 return CPAN::HandleConfig::cpl(@_); 4826 } elsif ($words[1] eq 'debug') { 4827 return sort grep /^\Q$word\E/i, 4828 sort keys %CPAN::DEBUG, 'all'; 4829 } 4830 } 4831 4832 package CPAN::Index; 4833 use strict; 4834 4835 #-> sub CPAN::Index::force_reload ; 4836 sub force_reload { 4837 my($class) = @_; 4838 $CPAN::Index::LAST_TIME = 0; 4839 $class->reload(1); 4840 } 4841 4842 #-> sub CPAN::Index::reload ; 4843 sub reload { 4844 my($self,$force) = @_; 4845 my $time = time; 4846 4847 # XXX check if a newer one is available. (We currently read it 4848 # from time to time) 4849 for ($CPAN::Config->{index_expire}) { 4850 $_ = 0.001 unless $_ && $_ > 0.001; 4851 } 4852 unless (1 || $CPAN::Have_warned->{readmetadatacache}++) { 4853 # debug here when CPAN doesn't seem to read the Metadata 4854 require Carp; 4855 Carp::cluck("META-PROTOCOL[$CPAN::META->{PROTOCOL}]"); 4856 } 4857 unless ($CPAN::META->{PROTOCOL}) { 4858 $self->read_metadata_cache; 4859 $CPAN::META->{PROTOCOL} ||= "1.0"; 4860 } 4861 if ( $CPAN::META->{PROTOCOL} < PROTOCOL ) { 4862 # warn "Setting last_time to 0"; 4863 $LAST_TIME = 0; # No warning necessary 4864 } 4865 if ($LAST_TIME + $CPAN::Config->{index_expire}*86400 > $time 4866 and ! $force) { 4867 # called too often 4868 # CPAN->debug("LAST_TIME[$LAST_TIME]index_expire[$CPAN::Config->{index_expire}]time[$time]"); 4869 } elsif (0) { 4870 # IFF we are developing, it helps to wipe out the memory 4871 # between reloads, otherwise it is not what a user expects. 4872 undef $CPAN::META; # Neue Gruendlichkeit since v1.52(r1.274) 4873 $CPAN::META = CPAN->new; 4874 } else { 4875 my($debug,$t2); 4876 local $LAST_TIME = $time; 4877 local $CPAN::META->{PROTOCOL} = PROTOCOL; 4878 4879 my $needshort = $^O eq "dos"; 4880 4881 $self->rd_authindex($self 4882 ->reload_x( 4883 "authors/01mailrc.txt.gz", 4884 $needshort ? 4885 File::Spec->catfile('authors', '01mailrc.gz') : 4886 File::Spec->catfile('authors', '01mailrc.txt.gz'), 4887 $force)); 4888 $t2 = time; 4889 $debug = "timing reading 01[".($t2 - $time)."]"; 4890 $time = $t2; 4891 return if $CPAN::Signal; # this is sometimes lengthy 4892 $self->rd_modpacks($self 4893 ->reload_x( 4894 "modules/02packages.details.txt.gz", 4895 $needshort ? 4896 File::Spec->catfile('modules', '02packag.gz') : 4897 File::Spec->catfile('modules', '02packages.details.txt.gz'), 4898 $force)); 4899 $t2 = time; 4900 $debug .= "02[".($t2 - $time)."]"; 4901 $time = $t2; 4902 return if $CPAN::Signal; # this is sometimes lengthy 4903 $self->rd_modlist($self 4904 ->reload_x( 4905 "modules/03modlist.data.gz", 4906 $needshort ? 4907 File::Spec->catfile('modules', '03mlist.gz') : 4908 File::Spec->catfile('modules', '03modlist.data.gz'), 4909 $force)); 4910 $self->write_metadata_cache; 4911 $t2 = time; 4912 $debug .= "03[".($t2 - $time)."]"; 4913 $time = $t2; 4914 CPAN->debug($debug) if $CPAN::DEBUG; 4915 } 4916 if ($CPAN::Config->{build_dir_reuse}) { 4917 $self->reanimate_build_dir; 4918 } 4919 if (CPAN::_sqlite_running) { 4920 $CPAN::SQLite->reload(time => $time, force => $force) 4921 if not $LAST_TIME; 4922 } 4923 $LAST_TIME = $time; 4924 $CPAN::META->{PROTOCOL} = PROTOCOL; 4925 } 4926 4927 #-> sub CPAN::Index::reanimate_build_dir ; 4928 sub reanimate_build_dir { 4929 my($self) = @_; 4930 unless ($CPAN::META->has_inst($CPAN::Config->{yaml_module}||"YAML")) { 4931 return; 4932 } 4933 return if $HAVE_REANIMATED++; 4934 my $d = $CPAN::Config->{build_dir}; 4935 my $dh = DirHandle->new; 4936 opendir $dh, $d or return; # does not exist 4937 my $dirent; 4938 my $i = 0; 4939 my $painted = 0; 4940 my $restored = 0; 4941 $CPAN::Frontend->myprint("Going to read $CPAN::Config->{build_dir}/\n"); 4942 my @candidates = map { $_->[0] } 4943 sort { $b->[1] <=> $a->[1] } 4944 map { [ $_, -M File::Spec->catfile($d,$_) ] } 4945 grep {/\.yml$/} readdir $dh; 4946 DISTRO: for $i (0..$#candidates) { 4947 my $dirent = $candidates[$i]; 4948 my $y = eval {CPAN->_yaml_loadfile(File::Spec->catfile($d,$dirent))}; 4949 if ($@) { 4950 warn "Error while parsing file '$dirent'; error: '$@'"; 4951 next DISTRO; 4952 } 4953 my $c = $y->[0]; 4954 if ($c && CPAN->_perl_fingerprint($c->{perl})) { 4955 my $key = $c->{distribution}{ID}; 4956 for my $k (keys %{$c->{distribution}}) { 4957 if ($c->{distribution}{$k} 4958 && ref $c->{distribution}{$k} 4959 && UNIVERSAL::isa($c->{distribution}{$k},"CPAN::Distrostatus")) { 4960 $c->{distribution}{$k}{COMMANDID} = $i - @candidates; 4961 } 4962 } 4963 4964 #we tried to restore only if element already 4965 #exists; but then we do not work with metadata 4966 #turned off. 4967 my $do 4968 = $CPAN::META->{readwrite}{'CPAN::Distribution'}{$key} 4969 = $c->{distribution}; 4970 for my $skipper (qw( 4971 badtestcnt 4972 configure_requires_later 4973 configure_requires_later_for 4974 force_update 4975 later 4976 later_for 4977 notest 4978 should_report 4979 sponsored_mods 4980 )) { 4981 delete $do->{$skipper}; 4982 } 4983 # $DB::single = 1; 4984 if ($do->{make_test} 4985 && $do->{build_dir} 4986 && !(UNIVERSAL::can($do->{make_test},"failed") ? 4987 $do->{make_test}->failed : 4988 $do->{make_test} =~ /^YES/ 4989 ) 4990 && ( 4991 !$do->{install} 4992 || 4993 $do->{install}->failed 4994 ) 4995 ) { 4996 $CPAN::META->is_tested($do->{build_dir},$do->{make_test}{TIME}); 4997 } 4998 $restored++; 4999 } 5000 $i++; 5001 while (($painted/76) < ($i/@candidates)) { 5002 $CPAN::Frontend->myprint("."); 5003 $painted++; 5004 } 5005 } 5006 $CPAN::Frontend->myprint(sprintf( 5007 "DONE\nFound %s old build%s, restored the state of %s\n", 5008 @candidates ? sprintf("%d",scalar @candidates) : "no", 5009 @candidates==1 ? "" : "s", 5010 $restored || "none", 5011 )); 5012 } 5013 5014 5015 #-> sub CPAN::Index::reload_x ; 5016 sub reload_x { 5017 my($cl,$wanted,$localname,$force) = @_; 5018 $force |= 2; # means we're dealing with an index here 5019 CPAN::HandleConfig->load; # we should guarantee loading wherever 5020 # we rely on Config XXX 5021 $localname ||= $wanted; 5022 my $abs_wanted = File::Spec->catfile($CPAN::Config->{'keep_source_where'}, 5023 $localname); 5024 if ( 5025 -f $abs_wanted && 5026 -M $abs_wanted < $CPAN::Config->{'index_expire'} && 5027 !($force & 1) 5028 ) { 5029 my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s"; 5030 $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }. 5031 qq{day$s. I\'ll use that.}); 5032 return $abs_wanted; 5033 } else { 5034 $force |= 1; # means we're quite serious about it. 5035 } 5036 return CPAN::FTP->localize($wanted,$abs_wanted,$force); 5037 } 5038 5039 #-> sub CPAN::Index::rd_authindex ; 5040 sub rd_authindex { 5041 my($cl, $index_target) = @_; 5042 return unless defined $index_target; 5043 return if CPAN::_sqlite_running; 5044 my @lines; 5045 $CPAN::Frontend->myprint("Going to read $index_target\n"); 5046 local(*FH); 5047 tie *FH, 'CPAN::Tarzip', $index_target; 5048 local($/) = "\n"; 5049 local($_); 5050 push @lines, split /\012/ while <FH>; 5051 my $i = 0; 5052 my $painted = 0; 5053 foreach (@lines) { 5054 my($userid,$fullname,$email) = 5055 m/alias\s+(\S+)\s+\"([^\"\<]*)\s+\<(.*)\>\"/; 5056 $fullname ||= $email; 5057 if ($userid && $fullname && $email) { 5058 my $userobj = $CPAN::META->instance('CPAN::Author',$userid); 5059 $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email); 5060 } else { 5061 CPAN->debug(sprintf "line[%s]", $_) if $CPAN::DEBUG; 5062 } 5063 $i++; 5064 while (($painted/76) < ($i/@lines)) { 5065 $CPAN::Frontend->myprint("."); 5066 $painted++; 5067 } 5068 return if $CPAN::Signal; 5069 } 5070 $CPAN::Frontend->myprint("DONE\n"); 5071 } 5072 5073 sub userid { 5074 my($self,$dist) = @_; 5075 $dist = $self->{'id'} unless defined $dist; 5076 my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|; 5077 $ret; 5078 } 5079 5080 #-> sub CPAN::Index::rd_modpacks ; 5081 sub rd_modpacks { 5082 my($self, $index_target) = @_; 5083 return unless defined $index_target; 5084 return if CPAN::_sqlite_running; 5085 $CPAN::Frontend->myprint("Going to read $index_target\n"); 5086 my $fh = CPAN::Tarzip->TIEHANDLE($index_target); 5087 local $_; 5088 CPAN->debug(sprintf "start[%d]", time) if $CPAN::DEBUG; 5089 my $slurp = ""; 5090 my $chunk; 5091 while (my $bytes = $fh->READ(\$chunk,8192)) { 5092 $slurp.=$chunk; 5093 } 5094 my @lines = split /\012/, $slurp; 5095 CPAN->debug(sprintf "end[%d]", time) if $CPAN::DEBUG; 5096 undef $fh; 5097 # read header 5098 my($line_count,$last_updated); 5099 while (@lines) { 5100 my $shift = shift(@lines); 5101 last if $shift =~ /^\s*$/; 5102 $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1; 5103 $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1; 5104 } 5105 CPAN->debug("line_count[$line_count]last_updated[$last_updated]") if $CPAN::DEBUG; 5106 if (not defined $line_count) { 5107 5108 $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Line-Count header. 5109 Please check the validity of the index file by comparing it to more 5110 than one CPAN mirror. I'll continue but problems seem likely to 5111 happen.\a 5112 }); 5113 5114 $CPAN::Frontend->mysleep(5); 5115 } elsif ($line_count != scalar @lines) { 5116 5117 $CPAN::Frontend->mywarn(sprintf qq{Warning: Your %s 5118 contains a Line-Count header of %d but I see %d lines there. Please 5119 check the validity of the index file by comparing it to more than one 5120 CPAN mirror. I'll continue but problems seem likely to happen.\a\n}, 5121 $index_target, $line_count, scalar(@lines)); 5122 5123 } 5124 if (not defined $last_updated) { 5125 5126 $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Last-Updated header. 5127 Please check the validity of the index file by comparing it to more 5128 than one CPAN mirror. I'll continue but problems seem likely to 5129 happen.\a 5130 }); 5131 5132 $CPAN::Frontend->mysleep(5); 5133 } else { 5134 5135 $CPAN::Frontend 5136 ->myprint(sprintf qq{ Database was generated on %s\n}, 5137 $last_updated); 5138 $DATE_OF_02 = $last_updated; 5139 5140 my $age = time; 5141 if ($CPAN::META->has_inst('HTTP::Date')) { 5142 require HTTP::Date; 5143 $age -= HTTP::Date::str2time($last_updated); 5144 } else { 5145 $CPAN::Frontend->mywarn(" HTTP::Date not available\n"); 5146 require Time::Local; 5147 my(@d) = $last_updated =~ / (\d+) (\w+) (\d+) (\d+):(\d+):(\d+) /; 5148 $d[1] = index("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", $d[1])/4; 5149 $age -= $d[1]>=0 ? Time::Local::timegm(@d[5,4,3,0,1,2]) : 0; 5150 } 5151 $age /= 3600*24; 5152 if ($age > 30) { 5153 5154 $CPAN::Frontend 5155 ->mywarn(sprintf 5156 qq{Warning: This index file is %d days old. 5157 Please check the host you chose as your CPAN mirror for staleness. 5158 I'll continue but problems seem likely to happen.\a\n}, 5159 $age); 5160 5161 } elsif ($age < -1) { 5162 5163 $CPAN::Frontend 5164 ->mywarn(sprintf 5165 qq{Warning: Your system date is %d days behind this index file! 5166 System time: %s 5167 Timestamp index file: %s 5168 Please fix your system time, problems with the make command expected.\n}, 5169 -$age, 5170 scalar gmtime, 5171 $DATE_OF_02, 5172 ); 5173 5174 } 5175 } 5176 5177 5178 # A necessity since we have metadata_cache: delete what isn't 5179 # there anymore 5180 my $secondtime = $CPAN::META->exists("CPAN::Module","CPAN"); 5181 CPAN->debug("secondtime[$secondtime]") if $CPAN::DEBUG; 5182 my(%exists); 5183 my $i = 0; 5184 my $painted = 0; 5185 foreach (@lines) { 5186 # before 1.56 we split into 3 and discarded the rest. From 5187 # 1.57 we assign remaining text to $comment thus allowing to 5188 # influence isa_perl 5189 my($mod,$version,$dist,$comment) = split " ", $_, 4; 5190 my($bundle,$id,$userid); 5191 5192 if ($mod eq 'CPAN' && 5193 ! ( 5194 CPAN::Queue->exists('Bundle::CPAN') || 5195 CPAN::Queue->exists('CPAN') 5196 ) 5197 ) { 5198 local($^W)= 0; 5199 if ($version > $CPAN::VERSION) { 5200 $CPAN::Frontend->mywarn(qq{ 5201 New CPAN.pm version (v$version) available. 5202 [Currently running version is v$CPAN::VERSION] 5203 You might want to try 5204 install CPAN 5205 reload cpan 5206 to both upgrade CPAN.pm and run the new version without leaving 5207 the current session. 5208 5209 }); #}); 5210 $CPAN::Frontend->mysleep(2); 5211 $CPAN::Frontend->myprint(qq{\n}); 5212 } 5213 last if $CPAN::Signal; 5214 } elsif ($mod =~ /^Bundle::(.*)/) { 5215 $bundle = $1; 5216 } 5217 5218 if ($bundle) { 5219 $id = $CPAN::META->instance('CPAN::Bundle',$mod); 5220 # Let's make it a module too, because bundles have so much 5221 # in common with modules. 5222 5223 # Changed in 1.57_63: seems like memory bloat now without 5224 # any value, so commented out 5225 5226 # $CPAN::META->instance('CPAN::Module',$mod); 5227 5228 } else { 5229 5230 # instantiate a module object 5231 $id = $CPAN::META->instance('CPAN::Module',$mod); 5232 5233 } 5234 5235 # Although CPAN prohibits same name with different version the 5236 # indexer may have changed the version for the same distro 5237 # since the last time ("Force Reindexing" feature) 5238 if ($id->cpan_file ne $dist 5239 || 5240 $id->cpan_version ne $version 5241 ) { 5242 $userid = $id->userid || $self->userid($dist); 5243 $id->set( 5244 'CPAN_USERID' => $userid, 5245 'CPAN_VERSION' => $version, 5246 'CPAN_FILE' => $dist, 5247 ); 5248 } 5249 5250 # instantiate a distribution object 5251 if ($CPAN::META->exists('CPAN::Distribution',$dist)) { 5252 # we do not need CONTAINSMODS unless we do something with 5253 # this dist, so we better produce it on demand. 5254 5255 ## my $obj = $CPAN::META->instance( 5256 ## 'CPAN::Distribution' => $dist 5257 ## ); 5258 ## $obj->{CONTAINSMODS}{$mod} = undef; # experimental 5259 } else { 5260 $CPAN::META->instance( 5261 'CPAN::Distribution' => $dist 5262 )->set( 5263 'CPAN_USERID' => $userid, 5264 'CPAN_COMMENT' => $comment, 5265 ); 5266 } 5267 if ($secondtime) { 5268 for my $name ($mod,$dist) { 5269 # $self->debug("exists name[$name]") if $CPAN::DEBUG; 5270 $exists{$name} = undef; 5271 } 5272 } 5273 $i++; 5274 while (($painted/76) < ($i/@lines)) { 5275 $CPAN::Frontend->myprint("."); 5276 $painted++; 5277 } 5278 return if $CPAN::Signal; 5279 } 5280 $CPAN::Frontend->myprint("DONE\n"); 5281 if ($secondtime) { 5282 for my $class (qw(CPAN::Module CPAN::Bundle CPAN::Distribution)) { 5283 for my $o ($CPAN::META->all_objects($class)) { 5284 next if exists $exists{$o->{ID}}; 5285 $CPAN::META->delete($class,$o->{ID}); 5286 # CPAN->debug("deleting ID[$o->{ID}] in class[$class]") 5287 # if $CPAN::DEBUG; 5288 } 5289 } 5290 } 5291 } 5292 5293 #-> sub CPAN::Index::rd_modlist ; 5294 sub rd_modlist { 5295 my($cl,$index_target) = @_; 5296 return unless defined $index_target; 5297 return if CPAN::_sqlite_running; 5298 $CPAN::Frontend->myprint("Going to read $index_target\n"); 5299 my $fh = CPAN::Tarzip->TIEHANDLE($index_target); 5300 local $_; 5301 my $slurp = ""; 5302 my $chunk; 5303 while (my $bytes = $fh->READ(\$chunk,8192)) { 5304 $slurp.=$chunk; 5305 } 5306 my @eval2 = split /\012/, $slurp; 5307 5308 while (@eval2) { 5309 my $shift = shift(@eval2); 5310 if ($shift =~ /^Date:\s+(.*)/) { 5311 if ($DATE_OF_03 eq $1) { 5312 $CPAN::Frontend->myprint("Unchanged.\n"); 5313 return; 5314 } 5315 ($DATE_OF_03) = $1; 5316 } 5317 last if $shift =~ /^\s*$/; 5318 } 5319 push @eval2, q{CPAN::Modulelist->data;}; 5320 local($^W) = 0; 5321 my($comp) = Safe->new("CPAN::Safe1"); 5322 my($eval2) = join("\n", @eval2); 5323 CPAN->debug(sprintf "length of eval2[%d]", length $eval2) if $CPAN::DEBUG; 5324 my $ret = $comp->reval($eval2); 5325 Carp::confess($@) if $@; 5326 return if $CPAN::Signal; 5327 my $i = 0; 5328 my $until = keys(%$ret); 5329 my $painted = 0; 5330 CPAN->debug(sprintf "until[%d]", $until) if $CPAN::DEBUG; 5331 for (keys %$ret) { 5332 my $obj = $CPAN::META->instance("CPAN::Module",$_); 5333 delete $ret->{$_}{modid}; # not needed here, maybe elsewhere 5334 $obj->set(%{$ret->{$_}}); 5335 $i++; 5336 while (($painted/76) < ($i/$until)) { 5337 $CPAN::Frontend->myprint("."); 5338 $painted++; 5339 } 5340 return if $CPAN::Signal; 5341 } 5342 $CPAN::Frontend->myprint("DONE\n"); 5343 } 5344 5345 #-> sub CPAN::Index::write_metadata_cache ; 5346 sub write_metadata_cache { 5347 my($self) = @_; 5348 return unless $CPAN::Config->{'cache_metadata'}; 5349 return if CPAN::_sqlite_running; 5350 return unless $CPAN::META->has_usable("Storable"); 5351 my $cache; 5352 foreach my $k (qw(CPAN::Bundle CPAN::Author CPAN::Module 5353 CPAN::Distribution)) { 5354 $cache->{$k} = $CPAN::META->{readonly}{$k}; # unsafe meta access, ok 5355 } 5356 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); 5357 $cache->{last_time} = $LAST_TIME; 5358 $cache->{DATE_OF_02} = $DATE_OF_02; 5359 $cache->{PROTOCOL} = PROTOCOL; 5360 $CPAN::Frontend->myprint("Going to write $metadata_file\n"); 5361 eval { Storable::nstore($cache, $metadata_file) }; 5362 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? 5363 } 5364 5365 #-> sub CPAN::Index::read_metadata_cache ; 5366 sub read_metadata_cache { 5367 my($self) = @_; 5368 return unless $CPAN::Config->{'cache_metadata'}; 5369 return if CPAN::_sqlite_running; 5370 return unless $CPAN::META->has_usable("Storable"); 5371 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); 5372 return unless -r $metadata_file and -f $metadata_file; 5373 $CPAN::Frontend->myprint("Going to read $metadata_file\n"); 5374 my $cache; 5375 eval { $cache = Storable::retrieve($metadata_file) }; 5376 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? 5377 if (!$cache || !UNIVERSAL::isa($cache, 'HASH')) { 5378 $LAST_TIME = 0; 5379 return; 5380 } 5381 if (exists $cache->{PROTOCOL}) { 5382 if (PROTOCOL > $cache->{PROTOCOL}) { 5383 $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ". 5384 "with protocol v%s, requiring v%s\n", 5385 $cache->{PROTOCOL}, 5386 PROTOCOL) 5387 ); 5388 return; 5389 } 5390 } else { 5391 $CPAN::Frontend->mywarn("Ignoring Metadata cache written ". 5392 "with protocol v1.0\n"); 5393 return; 5394 } 5395 my $clcnt = 0; 5396 my $idcnt = 0; 5397 while(my($class,$v) = each %$cache) { 5398 next unless $class =~ /^CPAN::/; 5399 $CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok 5400 while (my($id,$ro) = each %$v) { 5401 $CPAN::META->{readwrite}{$class}{$id} ||= 5402 $class->new(ID=>$id, RO=>$ro); 5403 $idcnt++; 5404 } 5405 $clcnt++; 5406 } 5407 unless ($clcnt) { # sanity check 5408 $CPAN::Frontend->myprint("Warning: Found no data in $metadata_file\n"); 5409 return; 5410 } 5411 if ($idcnt < 1000) { 5412 $CPAN::Frontend->myprint("Warning: Found only $idcnt objects ". 5413 "in $metadata_file\n"); 5414 return; 5415 } 5416 $CPAN::META->{PROTOCOL} ||= 5417 $cache->{PROTOCOL}; # reading does not up or downgrade, but it 5418 # does initialize to some protocol 5419 $LAST_TIME = $cache->{last_time}; 5420 $DATE_OF_02 = $cache->{DATE_OF_02}; 5421 $CPAN::Frontend->myprint(" Database was generated on $DATE_OF_02\n") 5422 if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02 5423 return; 5424 } 5425 5426 package CPAN::InfoObj; 5427 use strict; 5428 5429 sub ro { 5430 my $self = shift; 5431 exists $self->{RO} and return $self->{RO}; 5432 } 5433 5434 #-> sub CPAN::InfoObj::cpan_userid 5435 sub cpan_userid { 5436 my $self = shift; 5437 my $ro = $self->ro; 5438 if ($ro) { 5439 return $ro->{CPAN_USERID} || "N/A"; 5440 } else { 5441 $self->debug("ID[$self->{ID}]"); 5442 # N/A for bundles found locally 5443 return "N/A"; 5444 } 5445 } 5446 5447 sub id { shift->{ID}; } 5448 5449 #-> sub CPAN::InfoObj::new ; 5450 sub new { 5451 my $this = bless {}, shift; 5452 %$this = @_; 5453 $this 5454 } 5455 5456 # The set method may only be used by code that reads index data or 5457 # otherwise "objective" data from the outside world. All session 5458 # related material may do anything else with instance variables but 5459 # must not touch the hash under the RO attribute. The reason is that 5460 # the RO hash gets written to Metadata file and is thus persistent. 5461 5462 #-> sub CPAN::InfoObj::safe_chdir ; 5463 sub safe_chdir { 5464 my($self,$todir) = @_; 5465 # we die if we cannot chdir and we are debuggable 5466 Carp::confess("safe_chdir called without todir argument") 5467 unless defined $todir and length $todir; 5468 if (chdir $todir) { 5469 $self->debug(sprintf "changed directory to %s", CPAN::anycwd()) 5470 if $CPAN::DEBUG; 5471 } else { 5472 if (-e $todir) { 5473 unless (-x $todir) { 5474 unless (chmod 0755, $todir) { 5475 my $cwd = CPAN::anycwd(); 5476 $CPAN::Frontend->mywarn("I have neither the -x permission nor the ". 5477 "permission to change the permission; cannot ". 5478 "chdir to '$todir'\n"); 5479 $CPAN::Frontend->mysleep(5); 5480 $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }. 5481 qq{to todir[$todir]: $!}); 5482 } 5483 } 5484 } else { 5485 $CPAN::Frontend->mydie("Directory '$todir' has gone. Cannot continue.\n"); 5486 } 5487 if (chdir $todir) { 5488 $self->debug(sprintf "changed directory to %s", CPAN::anycwd()) 5489 if $CPAN::DEBUG; 5490 } else { 5491 my $cwd = CPAN::anycwd(); 5492 $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }. 5493 qq{to todir[$todir] (a chmod has been issued): $!}); 5494 } 5495 } 5496 } 5497 5498 #-> sub CPAN::InfoObj::set ; 5499 sub set { 5500 my($self,%att) = @_; 5501 my $class = ref $self; 5502 5503 # This must be ||=, not ||, because only if we write an empty 5504 # reference, only then the set method will write into the readonly 5505 # area. But for Distributions that spring into existence, maybe 5506 # because of a typo, we do not like it that they are written into 5507 # the readonly area and made permanent (at least for a while) and 5508 # that is why we do not "allow" other places to call ->set. 5509 unless ($self->id) { 5510 CPAN->debug("Bug? Empty ID, rejecting"); 5511 return; 5512 } 5513 my $ro = $self->{RO} = 5514 $CPAN::META->{readonly}{$class}{$self->id} ||= {}; 5515 5516 while (my($k,$v) = each %att) { 5517 $ro->{$k} = $v; 5518 } 5519 } 5520 5521 #-> sub CPAN::InfoObj::as_glimpse ; 5522 sub as_glimpse { 5523 my($self) = @_; 5524 my(@m); 5525 my $class = ref($self); 5526 $class =~ s/^CPAN:://; 5527 my $id = $self->can("pretty_id") ? $self->pretty_id : $self->{ID}; 5528 push @m, sprintf "%-15s %s\n", $class, $id; 5529 join "", @m; 5530 } 5531 5532 #-> sub CPAN::InfoObj::as_string ; 5533 sub as_string { 5534 my($self) = @_; 5535 my(@m); 5536 my $class = ref($self); 5537 $class =~ s/^CPAN:://; 5538 push @m, $class, " id = $self->{ID}\n"; 5539 my $ro; 5540 unless ($ro = $self->ro) { 5541 if (substr($self->{ID},-1,1) eq ".") { # directory 5542 $ro = +{}; 5543 } else { 5544 $CPAN::Frontend->mywarn("Unknown object $self->{ID}\n"); 5545 $CPAN::Frontend->mysleep(5); 5546 return; 5547 } 5548 } 5549 for (sort keys %$ro) { 5550 # next if m/^(ID|RO)$/; 5551 my $extra = ""; 5552 if ($_ eq "CPAN_USERID") { 5553 $extra .= " ("; 5554 $extra .= $self->fullname; 5555 my $email; # old perls! 5556 if ($email = $CPAN::META->instance("CPAN::Author", 5557 $self->cpan_userid 5558 )->email) { 5559 $extra .= " <$email>"; 5560 } else { 5561 $extra .= " <no email>"; 5562 } 5563 $extra .= ")"; 5564 } elsif ($_ eq "FULLNAME") { # potential UTF-8 conversion 5565 push @m, sprintf " %-12s %s\n", $_, $self->fullname; 5566 next; 5567 } 5568 next unless defined $ro->{$_}; 5569 push @m, sprintf " %-12s %s%s\n", $_, $ro->{$_}, $extra; 5570 } 5571 KEY: for (sort keys %$self) { 5572 next if m/^(ID|RO)$/; 5573 unless (defined $self->{$_}) { 5574 delete $self->{$_}; 5575 next KEY; 5576 } 5577 if (ref($self->{$_}) eq "ARRAY") { 5578 push @m, sprintf " %-12s %s\n", $_, "@{$self->{$_}}"; 5579 } elsif (ref($self->{$_}) eq "HASH") { 5580 my $value; 5581 if (/^CONTAINSMODS$/) { 5582 $value = join(" ",sort keys %{$self->{$_}}); 5583 } elsif (/^prereq_pm$/) { 5584 my @value; 5585 my $v = $self->{$_}; 5586 for my $x (sort keys %$v) { 5587 my @svalue; 5588 for my $y (sort keys %{$v->{$x}}) { 5589 push @svalue, "$y=>$v->{$x}{$y}"; 5590 } 5591 push @value, "$x\:" . join ",", @svalue if @svalue; 5592 } 5593 $value = join ";", @value; 5594 } else { 5595 $value = $self->{$_}; 5596 } 5597 push @m, sprintf( 5598 " %-12s %s\n", 5599 $_, 5600 $value, 5601 ); 5602 } else { 5603 push @m, sprintf " %-12s %s\n", $_, $self->{$_}; 5604 } 5605 } 5606 join "", @m, "\n"; 5607 } 5608 5609 #-> sub CPAN::InfoObj::fullname ; 5610 sub fullname { 5611 my($self) = @_; 5612 $CPAN::META->instance("CPAN::Author",$self->cpan_userid)->fullname; 5613 } 5614 5615 #-> sub CPAN::InfoObj::dump ; 5616 sub dump { 5617 my($self, $what) = @_; 5618 unless ($CPAN::META->has_inst("Data::Dumper")) { 5619 $CPAN::Frontend->mydie("dump command requires Data::Dumper installed"); 5620 } 5621 local $Data::Dumper::Sortkeys; 5622 $Data::Dumper::Sortkeys = 1; 5623 my $out = Data::Dumper::Dumper($what ? eval $what : $self); 5624 if (length $out > 100000) { 5625 my $fh_pager = FileHandle->new; 5626 local($SIG{PIPE}) = "IGNORE"; 5627 my $pager = $CPAN::Config->{'pager'} || "cat"; 5628 $fh_pager->open("|$pager") 5629 or die "Could not open pager $pager\: $!"; 5630 $fh_pager->print($out); 5631 close $fh_pager; 5632 } else { 5633 $CPAN::Frontend->myprint($out); 5634 } 5635 } 5636 5637 package CPAN::Author; 5638 use strict; 5639 5640 #-> sub CPAN::Author::force 5641 sub force { 5642 my $self = shift; 5643 $self->{force}++; 5644 } 5645 5646 #-> sub CPAN::Author::force 5647 sub unforce { 5648 my $self = shift; 5649 delete $self->{force}; 5650 } 5651 5652 #-> sub CPAN::Author::id 5653 sub id { 5654 my $self = shift; 5655 my $id = $self->{ID}; 5656 $CPAN::Frontend->mydie("Illegal author id[$id]") unless $id =~ /^[A-Z]/; 5657 $id; 5658 } 5659 5660 #-> sub CPAN::Author::as_glimpse ; 5661 sub as_glimpse { 5662 my($self) = @_; 5663 my(@m); 5664 my $class = ref($self); 5665 $class =~ s/^CPAN:://; 5666 push @m, sprintf(qq{%-15s %s ("%s" <%s>)\n}, 5667 $class, 5668 $self->{ID}, 5669 $self->fullname, 5670 $self->email); 5671 join "", @m; 5672 } 5673 5674 #-> sub CPAN::Author::fullname ; 5675 sub fullname { 5676 shift->ro->{FULLNAME}; 5677 } 5678 *name = \&fullname; 5679 5680 #-> sub CPAN::Author::email ; 5681 sub email { shift->ro->{EMAIL}; } 5682 5683 #-> sub CPAN::Author::ls ; 5684 sub ls { 5685 my $self = shift; 5686 my $glob = shift || ""; 5687 my $silent = shift || 0; 5688 my $id = $self->id; 5689 5690 # adapted from CPAN::Distribution::verifyCHECKSUM ; 5691 my(@csf); # chksumfile 5692 @csf = $self->id =~ /(.)(.)(.*)/; 5693 $csf[1] = join "", @csf[0,1]; 5694 $csf[2] = join "", @csf[1,2]; # ("A","AN","ANDK") 5695 my(@dl); 5696 @dl = $self->dir_listing([$csf[0],"CHECKSUMS"], 0, 1); 5697 unless (grep {$_->[2] eq $csf[1]} @dl) { 5698 $CPAN::Frontend->myprint("Directory $csf[1]/ does not exist\n") unless $silent ; 5699 return; 5700 } 5701 @dl = $self->dir_listing([@csf[0,1],"CHECKSUMS"], 0, 1); 5702 unless (grep {$_->[2] eq $csf[2]} @dl) { 5703 $CPAN::Frontend->myprint("Directory $id/ does not exist\n") unless $silent; 5704 return; 5705 } 5706 @dl = $self->dir_listing([@csf,"CHECKSUMS"], 1, 1); 5707 if ($glob) { 5708 if ($CPAN::META->has_inst("Text::Glob")) { 5709 my $rglob = Text::Glob::glob_to_regex($glob); 5710 @dl = grep { $_->[2] =~ /$rglob/ } @dl; 5711 } else { 5712 $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed"); 5713 } 5714 } 5715 unless ($silent >= 2) { 5716 $CPAN::Frontend->myprint(join "", map { 5717 sprintf("%8d %10s %s/%s\n", $_->[0], $_->[1], $id, $_->[2]) 5718 } sort { $a->[2] cmp $b->[2] } @dl); 5719 } 5720 @dl; 5721 } 5722 5723 # returns an array of arrays, the latter contain (size,mtime,filename) 5724 #-> sub CPAN::Author::dir_listing ; 5725 sub dir_listing { 5726 my $self = shift; 5727 my $chksumfile = shift; 5728 my $recursive = shift; 5729 my $may_ftp = shift; 5730 5731 my $lc_want = 5732 File::Spec->catfile($CPAN::Config->{keep_source_where}, 5733 "authors", "id", @$chksumfile); 5734 5735 my $fh; 5736 5737 # Purge and refetch old (pre-PGP) CHECKSUMS; they are a security 5738 # hazard. (Without GPG installed they are not that much better, 5739 # though.) 5740 $fh = FileHandle->new; 5741 if (open($fh, $lc_want)) { 5742 my $line = <$fh>; close $fh; 5743 unlink($lc_want) unless $line =~ /PGP/; 5744 } 5745 5746 local($") = "/"; 5747 # connect "force" argument with "index_expire". 5748 my $force = $self->{force}; 5749 if (my @stat = stat $lc_want) { 5750 $force ||= $stat[9] + $CPAN::Config->{index_expire}*86400 <= time; 5751 } 5752 my $lc_file; 5753 if ($may_ftp) { 5754 $lc_file = CPAN::FTP->localize( 5755 "authors/id/@$chksumfile", 5756 $lc_want, 5757 $force, 5758 ); 5759 unless ($lc_file) { 5760 $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); 5761 $chksumfile->[-1] .= ".gz"; 5762 $lc_file = CPAN::FTP->localize("authors/id/@$chksumfile", 5763 "$lc_want.gz",1); 5764 if ($lc_file) { 5765 $lc_file =~ s{\.gz(?!\n)\Z}{}; #}; 5766 eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)}; 5767 } else { 5768 return; 5769 } 5770 } 5771 } else { 5772 $lc_file = $lc_want; 5773 # we *could* second-guess and if the user has a file: URL, 5774 # then we could look there. But on the other hand, if they do 5775 # have a file: URL, wy did they choose to set 5776 # $CPAN::Config->{show_upload_date} to false? 5777 } 5778 5779 # adapted from CPAN::Distribution::CHECKSUM_check_file ; 5780 $fh = FileHandle->new; 5781 my($cksum); 5782 if (open $fh, $lc_file) { 5783 local($/); 5784 my $eval = <$fh>; 5785 $eval =~ s/\015?\012/\n/g; 5786 close $fh; 5787 my($comp) = Safe->new(); 5788 $cksum = $comp->reval($eval); 5789 if ($@) { 5790 rename $lc_file, "$lc_file.bad"; 5791 Carp::confess($@) if $@; 5792 } 5793 } elsif ($may_ftp) { 5794 Carp::carp "Could not open '$lc_file' for reading."; 5795 } else { 5796 # Maybe should warn: "You may want to set show_upload_date to a true value" 5797 return; 5798 } 5799 my(@result,$f); 5800 for $f (sort keys %$cksum) { 5801 if (exists $cksum->{$f}{isdir}) { 5802 if ($recursive) { 5803 my(@dir) = @$chksumfile; 5804 pop @dir; 5805 push @dir, $f, "CHECKSUMS"; 5806 push @result, map { 5807 [$_->[0], $_->[1], "$f/$_->[2]"] 5808 } $self->dir_listing(\@dir,1,$may_ftp); 5809 } else { 5810 push @result, [ 0, "-", $f ]; 5811 } 5812 } else { 5813 push @result, [ 5814 ($cksum->{$f}{"size"}||0), 5815 $cksum->{$f}{"mtime"}||"---", 5816 $f 5817 ]; 5818 } 5819 } 5820 @result; 5821 } 5822 5823 #-> sub CPAN::Author::reports 5824 sub reports { 5825 $CPAN::Frontend->mywarn("reports on authors not implemented. 5826 Please file a bugreport if you need this.\n"); 5827 } 5828 5829 package CPAN::Distribution; 5830 use strict; 5831 5832 # Accessors 5833 sub cpan_comment { 5834 my $self = shift; 5835 my $ro = $self->ro or return; 5836 $ro->{CPAN_COMMENT} 5837 } 5838 5839 #-> CPAN::Distribution::undelay 5840 sub undelay { 5841 my $self = shift; 5842 for my $delayer ( 5843 "configure_requires_later", 5844 "configure_requires_later_for", 5845 "later", 5846 "later_for", 5847 ) { 5848 delete $self->{$delayer}; 5849 } 5850 } 5851 5852 #-> CPAN::Distribution::is_dot_dist 5853 sub is_dot_dist { 5854 my($self) = @_; 5855 return substr($self->id,-1,1) eq "."; 5856 } 5857 5858 # add the A/AN/ stuff 5859 #-> CPAN::Distribution::normalize 5860 sub normalize { 5861 my($self,$s) = @_; 5862 $s = $self->id unless defined $s; 5863 if (substr($s,-1,1) eq ".") { 5864 # using a global because we are sometimes called as static method 5865 if (!$CPAN::META->{LOCK} 5866 && !$CPAN::Have_warned->{"$s is unlocked"}++ 5867 ) { 5868 $CPAN::Frontend->mywarn("You are visiting the local directory 5869 '$s' 5870 without lock, take care that concurrent processes do not do likewise.\n"); 5871 $CPAN::Frontend->mysleep(1); 5872 } 5873 if ($s eq ".") { 5874 $s = "$CPAN::iCwd/."; 5875 } elsif (File::Spec->file_name_is_absolute($s)) { 5876 } elsif (File::Spec->can("rel2abs")) { 5877 $s = File::Spec->rel2abs($s); 5878 } else { 5879 $CPAN::Frontend->mydie("Your File::Spec is too old, please upgrade File::Spec"); 5880 } 5881 CPAN->debug("s[$s]") if $CPAN::DEBUG; 5882 unless ($CPAN::META->exists("CPAN::Distribution", $s)) { 5883 for ($CPAN::META->instance("CPAN::Distribution", $s)) { 5884 $_->{build_dir} = $s; 5885 $_->{archived} = "local_directory"; 5886 $_->{unwrapped} = CPAN::Distrostatus->new("YES -- local_directory"); 5887 } 5888 } 5889 } elsif ( 5890 $s =~ tr|/|| == 1 5891 or 5892 $s !~ m|[A-Z]/[A-Z-]{2}/[A-Z-]{2,}/| 5893 ) { 5894 return $s if $s =~ m:^N/A|^Contact Author: ; 5895 $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4| or 5896 $CPAN::Frontend->mywarn("Strange distribution name [$s]\n"); 5897 CPAN->debug("s[$s]") if $CPAN::DEBUG; 5898 } 5899 $s; 5900 } 5901 5902 #-> sub CPAN::Distribution::author ; 5903 sub author { 5904 my($self) = @_; 5905 my($authorid); 5906 if (substr($self->id,-1,1) eq ".") { 5907 $authorid = "LOCAL"; 5908 } else { 5909 ($authorid) = $self->pretty_id =~ /^([\w\-]+)/; 5910 } 5911 CPAN::Shell->expand("Author",$authorid); 5912 } 5913 5914 # tries to get the yaml from CPAN instead of the distro itself: 5915 # EXPERIMENTAL, UNDOCUMENTED AND UNTESTED, for Tels 5916 sub fast_yaml { 5917 my($self) = @_; 5918 my $meta = $self->pretty_id; 5919 $meta =~ s/\.(tar.gz|tgz|zip|tar.bz2)/.meta/; 5920 my(@ls) = CPAN::Shell->globls($meta); 5921 my $norm = $self->normalize($meta); 5922 5923 my($local_file); 5924 my($local_wanted) = 5925 File::Spec->catfile( 5926 $CPAN::Config->{keep_source_where}, 5927 "authors", 5928 "id", 5929 split(/\//,$norm) 5930 ); 5931 $self->debug("Doing localize") if $CPAN::DEBUG; 5932 unless ($local_file = 5933 CPAN::FTP->localize("authors/id/$norm", 5934 $local_wanted)) { 5935 $CPAN::Frontend->mydie("Giving up on downloading yaml file '$local_wanted'\n"); 5936 } 5937 my $yaml = CPAN->_yaml_loadfile($local_file)->[0]; 5938 } 5939 5940 #-> sub CPAN::Distribution::cpan_userid 5941 sub cpan_userid { 5942 my $self = shift; 5943 if ($self->{ID} =~ m{[A-Z]/[A-Z\-]{2}/([A-Z\-]+)/}) { 5944 return $1; 5945 } 5946 return $self->SUPER::cpan_userid; 5947 } 5948 5949 #-> sub CPAN::Distribution::pretty_id 5950 sub pretty_id { 5951 my $self = shift; 5952 my $id = $self->id; 5953 return $id unless $id =~ m|^./../|; 5954 substr($id,5); 5955 } 5956 5957 #-> sub CPAN::Distribution::base_id 5958 sub base_id { 5959 my $self = shift; 5960 my $id = $self->pretty_id(); 5961 my $base_id = File::Basename::basename($id); 5962 $base_id =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i; 5963 return $base_id; 5964 } 5965 5966 # mark as dirty/clean for the sake of recursion detection. $color=1 5967 # means "in use", $color=0 means "not in use anymore". $color=2 means 5968 # we have determined prereqs now and thus insist on passing this 5969 # through (at least) once again. 5970 5971 #-> sub CPAN::Distribution::color_cmd_tmps ; 5972 sub color_cmd_tmps { 5973 my($self) = shift; 5974 my($depth) = shift || 0; 5975 my($color) = shift || 0; 5976 my($ancestors) = shift || []; 5977 # a distribution needs to recurse into its prereq_pms 5978 5979 return if exists $self->{incommandcolor} 5980 && $color==1 5981 && $self->{incommandcolor}==$color; 5982 if ($depth>=$CPAN::MAX_RECURSION) { 5983 die(CPAN::Exception::RecursiveDependency->new($ancestors)); 5984 } 5985 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 5986 my $prereq_pm = $self->prereq_pm; 5987 if (defined $prereq_pm) { 5988 PREREQ: for my $pre (keys %{$prereq_pm->{requires}||{}}, 5989 keys %{$prereq_pm->{build_requires}||{}}) { 5990 next PREREQ if $pre eq "perl"; 5991 my $premo; 5992 unless ($premo = CPAN::Shell->expand("Module",$pre)) { 5993 $CPAN::Frontend->mywarn("prerequisite module[$pre] not known\n"); 5994 $CPAN::Frontend->mysleep(2); 5995 next PREREQ; 5996 } 5997 $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 5998 } 5999 } 6000 if ($color==0) { 6001 delete $self->{sponsored_mods}; 6002 6003 # as we are at the end of a command, we'll give up this 6004 # reminder of a broken test. Other commands may test this guy 6005 # again. Maybe 'badtestcnt' should be renamed to 6006 # 'make_test_failed_within_command'? 6007 delete $self->{badtestcnt}; 6008 } 6009 $self->{incommandcolor} = $color; 6010 } 6011 6012 #-> sub CPAN::Distribution::as_string ; 6013 sub as_string { 6014 my $self = shift; 6015 $self->containsmods; 6016 $self->upload_date; 6017 $self->SUPER::as_string(@_); 6018 } 6019 6020 #-> sub CPAN::Distribution::containsmods ; 6021 sub containsmods { 6022 my $self = shift; 6023 return keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS}; 6024 my $dist_id = $self->{ID}; 6025 for my $mod ($CPAN::META->all_objects("CPAN::Module")) { 6026 my $mod_file = $mod->cpan_file or next; 6027 my $mod_id = $mod->{ID} or next; 6028 # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]"; 6029 # sleep 1; 6030 if ($CPAN::Signal) { 6031 delete $self->{CONTAINSMODS}; 6032 return; 6033 } 6034 $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id; 6035 } 6036 keys %{$self->{CONTAINSMODS}||={}}; 6037 } 6038 6039 #-> sub CPAN::Distribution::upload_date ; 6040 sub upload_date { 6041 my $self = shift; 6042 return $self->{UPLOAD_DATE} if exists $self->{UPLOAD_DATE}; 6043 my(@local_wanted) = split(/\//,$self->id); 6044 my $filename = pop @local_wanted; 6045 push @local_wanted, "CHECKSUMS"; 6046 my $author = CPAN::Shell->expand("Author",$self->cpan_userid); 6047 return unless $author; 6048 my @dl = $author->dir_listing(\@local_wanted,0,$CPAN::Config->{show_upload_date}); 6049 return unless @dl; 6050 my($dirent) = grep { $_->[2] eq $filename } @dl; 6051 # warn sprintf "dirent[%s]id[%s]", $dirent, $self->id; 6052 return unless $dirent->[1]; 6053 return $self->{UPLOAD_DATE} = $dirent->[1]; 6054 } 6055 6056 #-> sub CPAN::Distribution::uptodate ; 6057 sub uptodate { 6058 my($self) = @_; 6059 my $c; 6060 foreach $c ($self->containsmods) { 6061 my $obj = CPAN::Shell->expandany($c); 6062 unless ($obj->uptodate) { 6063 my $id = $self->pretty_id; 6064 $self->debug("$id not uptodate due to $c") if $CPAN::DEBUG; 6065 return 0; 6066 } 6067 } 6068 return 1; 6069 } 6070 6071 #-> sub CPAN::Distribution::called_for ; 6072 sub called_for { 6073 my($self,$id) = @_; 6074 $self->{CALLED_FOR} = $id if defined $id; 6075 return $self->{CALLED_FOR}; 6076 } 6077 6078 #-> sub CPAN::Distribution::get ; 6079 sub get { 6080 my($self) = @_; 6081 $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG; 6082 if (my $goto = $self->prefs->{goto}) { 6083 $CPAN::Frontend->mywarn 6084 (sprintf( 6085 "delegating to '%s' as specified in prefs file '%s' doc %d\n", 6086 $goto, 6087 $self->{prefs_file}, 6088 $self->{prefs_file_doc}, 6089 )); 6090 return $self->goto($goto); 6091 } 6092 local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) 6093 ? $ENV{PERL5LIB} 6094 : ($ENV{PERLLIB} || ""); 6095 6096 $CPAN::META->set_perl5lib; 6097 local $ENV{MAKEFLAGS}; # protect us from outer make calls 6098 6099 EXCUSE: { 6100 my @e; 6101 my $goodbye_message; 6102 $self->debug("checking disabled id[$self->{ID}]") if $CPAN::DEBUG; 6103 if ($self->prefs->{disabled}) { 6104 my $why = sprintf( 6105 "Disabled via prefs file '%s' doc %d", 6106 $self->{prefs_file}, 6107 $self->{prefs_file_doc}, 6108 ); 6109 push @e, $why; 6110 $self->{unwrapped} = CPAN::Distrostatus->new("NO $why"); 6111 $goodbye_message = "[disabled] -- NA $why"; 6112 # note: not intended to be persistent but at least visible 6113 # during this session 6114 } else { 6115 if (exists $self->{build_dir} && -d $self->{build_dir} 6116 && ($self->{modulebuild}||$self->{writemakefile}) 6117 ) { 6118 # this deserves print, not warn: 6119 $CPAN::Frontend->myprint(" Has already been unwrapped into directory ". 6120 "$self->{build_dir}\n" 6121 ); 6122 return 1; 6123 } 6124 6125 # although we talk about 'force' we shall not test on 6126 # force directly. New model of force tries to refrain from 6127 # direct checking of force. 6128 exists $self->{unwrapped} and ( 6129 UNIVERSAL::can($self->{unwrapped},"failed") ? 6130 $self->{unwrapped}->failed : 6131 $self->{unwrapped} =~ /^NO/ 6132 ) 6133 and push @e, "Unwrapping had some problem, won't try again without force"; 6134 } 6135 if (@e) { 6136 $CPAN::Frontend->mywarn(join "", map {"$_\n"} @e); 6137 if ($goodbye_message) { 6138 $self->goodbye($goodbye_message); 6139 } 6140 return; 6141 } 6142 } 6143 my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible 6144 6145 my($local_file); 6146 unless ($self->{build_dir} && -d $self->{build_dir}) { 6147 $self->get_file_onto_local_disk; 6148 return if $CPAN::Signal; 6149 $self->check_integrity; 6150 return if $CPAN::Signal; 6151 (my $packagedir,$local_file) = $self->run_preps_on_packagedir; 6152 $packagedir ||= $self->{build_dir}; 6153 $self->{build_dir} = $packagedir; 6154 } 6155 6156 if ($CPAN::Signal) { 6157 $self->safe_chdir($sub_wd); 6158 return; 6159 } 6160 return $self->run_MM_or_MB($local_file); 6161 } 6162 6163 #-> CPAN::Distribution::get_file_onto_local_disk 6164 sub get_file_onto_local_disk { 6165 my($self) = @_; 6166 6167 return if $self->is_dot_dist; 6168 my($local_file); 6169 my($local_wanted) = 6170 File::Spec->catfile( 6171 $CPAN::Config->{keep_source_where}, 6172 "authors", 6173 "id", 6174 split(/\//,$self->id) 6175 ); 6176 6177 $self->debug("Doing localize") if $CPAN::DEBUG; 6178 unless ($local_file = 6179 CPAN::FTP->localize("authors/id/$self->{ID}", 6180 $local_wanted)) { 6181 my $note = ""; 6182 if ($CPAN::Index::DATE_OF_02) { 6183 $note = "Note: Current database in memory was generated ". 6184 "on $CPAN::Index::DATE_OF_02\n"; 6185 } 6186 $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note"); 6187 } 6188 6189 $self->debug("local_wanted[$local_wanted]local_file[$local_file]") if $CPAN::DEBUG; 6190 $self->{localfile} = $local_file; 6191 } 6192 6193 6194 #-> CPAN::Distribution::check_integrity 6195 sub check_integrity { 6196 my($self) = @_; 6197 6198 return if $self->is_dot_dist; 6199 if ($CPAN::META->has_inst("Digest::SHA")) { 6200 $self->debug("Digest::SHA is installed, verifying"); 6201 $self->verifyCHECKSUM; 6202 } else { 6203 $self->debug("Digest::SHA is NOT installed"); 6204 } 6205 } 6206 6207 #-> CPAN::Distribution::run_preps_on_packagedir 6208 sub run_preps_on_packagedir { 6209 my($self) = @_; 6210 return if $self->is_dot_dist; 6211 6212 $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok 6213 my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok 6214 $self->safe_chdir($builddir); 6215 $self->debug("Removing tmp-$$") if $CPAN::DEBUG; 6216 File::Path::rmtree("tmp-$$"); 6217 unless (mkdir "tmp-$$", 0755) { 6218 $CPAN::Frontend->unrecoverable_error(<<EOF); 6219 Couldn't mkdir '$builddir/tmp-$$': $! 6220 6221 Cannot continue: Please find the reason why I cannot make the 6222 directory 6223 $builddir/tmp-$$ 6224 and fix the problem, then retry. 6225 6226 EOF 6227 } 6228 if ($CPAN::Signal) { 6229 return; 6230 } 6231 $self->safe_chdir("tmp-$$"); 6232 6233 # 6234 # Unpack the goods 6235 # 6236 my $local_file = $self->{localfile}; 6237 my $ct = eval{CPAN::Tarzip->new($local_file)}; 6238 unless ($ct) { 6239 $self->{unwrapped} = CPAN::Distrostatus->new("NO"); 6240 delete $self->{build_dir}; 6241 return; 6242 } 6243 if ($local_file =~ /(\.tar\.(bz2|gz|Z)|\.tgz)(?!\n)\Z/i) { 6244 $self->{was_uncompressed}++ unless eval{$ct->gtest()}; 6245 $self->untar_me($ct); 6246 } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) { 6247 $self->unzip_me($ct); 6248 } else { 6249 $self->{was_uncompressed}++ unless $ct->gtest(); 6250 $local_file = $self->handle_singlefile($local_file); 6251 } 6252 6253 # we are still in the tmp directory! 6254 # Let's check if the package has its own directory. 6255 my $dh = DirHandle->new(File::Spec->curdir) 6256 or Carp::croak("Couldn't opendir .: $!"); 6257 my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC?? 6258 $dh->close; 6259 my ($packagedir); 6260 # XXX here we want in each branch File::Temp to protect all build_dir directories 6261 if (CPAN->has_usable("File::Temp")) { 6262 my $tdir_base; 6263 my $from_dir; 6264 my @dirents; 6265 if (@readdir == 1 && -d $readdir[0]) { 6266 $tdir_base = $readdir[0]; 6267 $from_dir = File::Spec->catdir(File::Spec->curdir,$readdir[0]); 6268 my $dh2 = DirHandle->new($from_dir) 6269 or Carp::croak("Couldn't opendir $from_dir: $!"); 6270 @dirents = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh2->read; ### MAC?? 6271 } else { 6272 my $userid = $self->cpan_userid; 6273 CPAN->debug("userid[$userid]"); 6274 if (!$userid or $userid eq "N/A") { 6275 $userid = "anon"; 6276 } 6277 $tdir_base = $userid; 6278 $from_dir = File::Spec->curdir; 6279 @dirents = @readdir; 6280 } 6281 $packagedir = File::Temp::tempdir( 6282 "$tdir_base-XXXXXX", 6283 DIR => $builddir, 6284 CLEANUP => 0, 6285 ); 6286 my $f; 6287 for $f (@dirents) { # is already without "." and ".." 6288 my $from = File::Spec->catdir($from_dir,$f); 6289 my $to = File::Spec->catdir($packagedir,$f); 6290 unless (File::Copy::move($from,$to)) { 6291 my $err = $!; 6292 $from = File::Spec->rel2abs($from); 6293 Carp::confess("Couldn't move $from to $to: $err"); 6294 } 6295 } 6296 } else { # older code below, still better than nothing when there is no File::Temp 6297 my($distdir); 6298 if (@readdir == 1 && -d $readdir[0]) { 6299 $distdir = $readdir[0]; 6300 $packagedir = File::Spec->catdir($builddir,$distdir); 6301 $self->debug("packagedir[$packagedir]builddir[$builddir]distdir[$distdir]") 6302 if $CPAN::DEBUG; 6303 -d $packagedir and $CPAN::Frontend->myprint("Removing previously used ". 6304 "$packagedir\n"); 6305 File::Path::rmtree($packagedir); 6306 unless (File::Copy::move($distdir,$packagedir)) { 6307 $CPAN::Frontend->unrecoverable_error(<<EOF); 6308 Couldn't move '$distdir' to '$packagedir': $! 6309 6310 Cannot continue: Please find the reason why I cannot move 6311 $builddir/tmp-$$/$distdir 6312 to 6313 $packagedir 6314 and fix the problem, then retry 6315 6316 EOF 6317 } 6318 $self->debug(sprintf("moved distdir[%s] to packagedir[%s] -e[%s]-d[%s]", 6319 $distdir, 6320 $packagedir, 6321 -e $packagedir, 6322 -d $packagedir, 6323 )) if $CPAN::DEBUG; 6324 } else { 6325 my $userid = $self->cpan_userid; 6326 CPAN->debug("userid[$userid]") if $CPAN::DEBUG; 6327 if (!$userid or $userid eq "N/A") { 6328 $userid = "anon"; 6329 } 6330 my $pragmatic_dir = $userid . '000'; 6331 $pragmatic_dir =~ s/\W_//g; 6332 $pragmatic_dir++ while -d "../$pragmatic_dir"; 6333 $packagedir = File::Spec->catdir($builddir,$pragmatic_dir); 6334 $self->debug("packagedir[$packagedir]") if $CPAN::DEBUG; 6335 File::Path::mkpath($packagedir); 6336 my($f); 6337 for $f (@readdir) { # is already without "." and ".." 6338 my $to = File::Spec->catdir($packagedir,$f); 6339 File::Copy::move($f,$to) or Carp::confess("Couldn't move $f to $to: $!"); 6340 } 6341 } 6342 } 6343 $self->{build_dir} = $packagedir; 6344 $self->safe_chdir($builddir); 6345 File::Path::rmtree("tmp-$$"); 6346 6347 $self->safe_chdir($packagedir); 6348 $self->_signature_business(); 6349 $self->safe_chdir($builddir); 6350 6351 return($packagedir,$local_file); 6352 } 6353 6354 #-> sub CPAN::Distribution::parse_meta_yml ; 6355 sub parse_meta_yml { 6356 my($self) = @_; 6357 my $build_dir = $self->{build_dir} or die "PANIC: cannot parse yaml without a build_dir"; 6358 my $yaml = File::Spec->catfile($build_dir,"META.yml"); 6359 $self->debug("yaml[$yaml]") if $CPAN::DEBUG; 6360 return unless -f $yaml; 6361 my $early_yaml; 6362 eval { 6363 require Parse::Metayaml; # hypothetical 6364 $early_yaml = Parse::Metayaml::LoadFile($yaml)->[0]; 6365 }; 6366 unless ($early_yaml) { 6367 eval { $early_yaml = CPAN->_yaml_loadfile($yaml)->[0]; }; 6368 } 6369 unless ($early_yaml) { 6370 return; 6371 } 6372 return $early_yaml; 6373 } 6374 6375 #-> sub CPAN::Distribution::satisfy_configure_requires ; 6376 sub satisfy_configure_requires { 6377 my($self) = @_; 6378 my $enable_configure_requires = 1; 6379 if (!$enable_configure_requires) { 6380 return 1; 6381 # if we return 1 here, everything is as before we introduced 6382 # configure_requires that means, things with 6383 # configure_requires simply fail, all others succeed 6384 } 6385 my @prereq = $self->unsat_prereq("configure_requires_later") or return 1; 6386 if ($self->{configure_requires_later}) { 6387 for my $k (keys %{$self->{configure_requires_later_for}||{}}) { 6388 if ($self->{configure_requires_later_for}{$k}>1) { 6389 # we must not come here a second time 6390 $CPAN::Frontend->mywarn("Panic: Some prerequisites is not available, please investigate..."); 6391 require YAML::Syck; 6392 $CPAN::Frontend->mydie 6393 ( 6394 YAML::Syck::Dump 6395 ({self=>$self, prereq=>\@prereq}) 6396 ); 6397 } 6398 } 6399 } 6400 if ($prereq[0][0] eq "perl") { 6401 my $need = "requires perl '$prereq[0][1]'"; 6402 my $id = $self->pretty_id; 6403 $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n"); 6404 $self->{make} = CPAN::Distrostatus->new("NO $need"); 6405 $self->store_persistent_state; 6406 return $self->goodbye("[prereq] -- NOT OK"); 6407 } else { 6408 my $follow = eval { 6409 $self->follow_prereqs("configure_requires_later", @prereq); 6410 }; 6411 if (0) { 6412 } elsif ($follow) { 6413 return; 6414 } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) { 6415 $CPAN::Frontend->mywarn($@); 6416 return $self->goodbye("[depend] -- NOT OK"); 6417 } 6418 } 6419 die "never reached"; 6420 } 6421 6422 #-> sub CPAN::Distribution::run_MM_or_MB ; 6423 sub run_MM_or_MB { 6424 my($self,$local_file) = @_; 6425 $self->satisfy_configure_requires() or return; 6426 my($mpl) = File::Spec->catfile($self->{build_dir},"Makefile.PL"); 6427 my($mpl_exists) = -f $mpl; 6428 unless ($mpl_exists) { 6429 # NFS has been reported to have racing problems after the 6430 # renaming of a directory in some environments. 6431 # This trick helps. 6432 $CPAN::Frontend->mysleep(1); 6433 my $mpldh = DirHandle->new($self->{build_dir}) 6434 or Carp::croak("Couldn't opendir $self->{build_dir}: $!"); 6435 $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read; 6436 $mpldh->close; 6437 } 6438 my $prefer_installer = "eumm"; # eumm|mb 6439 if (-f File::Spec->catfile($self->{build_dir},"Build.PL")) { 6440 if ($mpl_exists) { # they *can* choose 6441 if ($CPAN::META->has_inst("Module::Build")) { 6442 $prefer_installer = CPAN::HandleConfig->prefs_lookup($self, 6443 q{prefer_installer}); 6444 } 6445 } else { 6446 $prefer_installer = "mb"; 6447 } 6448 } 6449 return unless $self->patch; 6450 if (lc($prefer_installer) eq "rand") { 6451 $prefer_installer = rand()<.5 ? "eumm" : "mb"; 6452 } 6453 if (lc($prefer_installer) eq "mb") { 6454 $self->{modulebuild} = 1; 6455 } elsif ($self->{archived} eq "patch") { 6456 # not an edge case, nothing to install for sure 6457 my $why = "A patch file cannot be installed"; 6458 $CPAN::Frontend->mywarn("Refusing to handle this file: $why\n"); 6459 $self->{writemakefile} = CPAN::Distrostatus->new("NO $why"); 6460 } elsif (! $mpl_exists) { 6461 $self->_edge_cases($mpl,$local_file); 6462 } 6463 if ($self->{build_dir} 6464 && 6465 $CPAN::Config->{build_dir_reuse} 6466 ) { 6467 $self->store_persistent_state; 6468 } 6469 return $self; 6470 } 6471 6472 #-> CPAN::Distribution::store_persistent_state 6473 sub store_persistent_state { 6474 my($self) = @_; 6475 my $dir = $self->{build_dir}; 6476 unless (File::Spec->canonpath(File::Basename::dirname($dir)) 6477 eq File::Spec->canonpath($CPAN::Config->{build_dir})) { 6478 $CPAN::Frontend->mywarn("Directory '$dir' not below $CPAN::Config->{build_dir}, ". 6479 "will not store persistent state\n"); 6480 return; 6481 } 6482 my $file = sprintf "%s.yml", $dir; 6483 my $yaml_module = CPAN::_yaml_module; 6484 if ($CPAN::META->has_inst($yaml_module)) { 6485 CPAN->_yaml_dumpfile( 6486 $file, 6487 { 6488 time => time, 6489 perl => CPAN::_perl_fingerprint, 6490 distribution => $self, 6491 } 6492 ); 6493 } else { 6494 $CPAN::Frontend->myprint("Warning (usually harmless): '$yaml_module' not installed, ". 6495 "will not store persistent state\n"); 6496 } 6497 } 6498 6499 #-> CPAN::Distribution::try_download 6500 sub try_download { 6501 my($self,$patch) = @_; 6502 my $norm = $self->normalize($patch); 6503 my($local_wanted) = 6504 File::Spec->catfile( 6505 $CPAN::Config->{keep_source_where}, 6506 "authors", 6507 "id", 6508 split(/\//,$norm), 6509 ); 6510 $self->debug("Doing localize") if $CPAN::DEBUG; 6511 return CPAN::FTP->localize("authors/id/$norm", 6512 $local_wanted); 6513 } 6514 6515 { 6516 my $stdpatchargs = ""; 6517 #-> CPAN::Distribution::patch 6518 sub patch { 6519 my($self) = @_; 6520 $self->debug("checking patches id[$self->{ID}]") if $CPAN::DEBUG; 6521 my $patches = $self->prefs->{patches}; 6522 $patches ||= ""; 6523 $self->debug("patches[$patches]") if $CPAN::DEBUG; 6524 if ($patches) { 6525 return unless @$patches; 6526 $self->safe_chdir($self->{build_dir}); 6527 CPAN->debug("patches[$patches]") if $CPAN::DEBUG; 6528 my $patchbin = $CPAN::Config->{patch}; 6529 unless ($patchbin && length $patchbin) { 6530 $CPAN::Frontend->mydie("No external patch command configured\n\n". 6531 "Please run 'o conf init /patch/'\n\n"); 6532 } 6533 unless (MM->maybe_command($patchbin)) { 6534 $CPAN::Frontend->mydie("No external patch command available\n\n". 6535 "Please run 'o conf init /patch/'\n\n"); 6536 } 6537 $patchbin = CPAN::HandleConfig->safe_quote($patchbin); 6538 local $ENV{PATCH_GET} = 0; # formerly known as -g0 6539 unless ($stdpatchargs) { 6540 my $system = "$patchbin --version |"; 6541 local *FH; 6542 open FH, $system or die "Could not fork '$system': $!"; 6543 local $/ = "\n"; 6544 my $pversion; 6545 PARSEVERSION: while (<FH>) { 6546 if (/^patch\s+([\d\.]+)/) { 6547 $pversion = $1; 6548 last PARSEVERSION; 6549 } 6550 } 6551 if ($pversion) { 6552 $stdpatchargs = "-N --fuzz=3"; 6553 } else { 6554 $stdpatchargs = "-N"; 6555 } 6556 } 6557 my $countedpatches = @$patches == 1 ? "1 patch" : (scalar @$patches . " patches"); 6558 $CPAN::Frontend->myprint("Going to apply $countedpatches:\n"); 6559 for my $patch (@$patches) { 6560 unless (-f $patch) { 6561 if (my $trydl = $self->try_download($patch)) { 6562 $patch = $trydl; 6563 } else { 6564 my $fail = "Could not find patch '$patch'"; 6565 $CPAN::Frontend->mywarn("$fail; cannot continue\n"); 6566 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); 6567 delete $self->{build_dir}; 6568 return; 6569 } 6570 } 6571 $CPAN::Frontend->myprint(" $patch\n"); 6572 my $readfh = CPAN::Tarzip->TIEHANDLE($patch); 6573 6574 my $pcommand; 6575 my $ppp = $self->_patch_p_parameter($readfh); 6576 if ($ppp eq "applypatch") { 6577 $pcommand = "$CPAN::Config->{applypatch} -verbose"; 6578 } else { 6579 my $thispatchargs = join " ", $stdpatchargs, $ppp; 6580 $pcommand = "$patchbin $thispatchargs"; 6581 } 6582 6583 $readfh = CPAN::Tarzip->TIEHANDLE($patch); # open again 6584 my $writefh = FileHandle->new; 6585 $CPAN::Frontend->myprint(" $pcommand\n"); 6586 unless (open $writefh, "|$pcommand") { 6587 my $fail = "Could not fork '$pcommand'"; 6588 $CPAN::Frontend->mywarn("$fail; cannot continue\n"); 6589 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); 6590 delete $self->{build_dir}; 6591 return; 6592 } 6593 while (my $x = $readfh->READLINE) { 6594 print $writefh $x; 6595 } 6596 unless (close $writefh) { 6597 my $fail = "Could not apply patch '$patch'"; 6598 $CPAN::Frontend->mywarn("$fail; cannot continue\n"); 6599 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); 6600 delete $self->{build_dir}; 6601 return; 6602 } 6603 } 6604 $self->{patched}++; 6605 } 6606 return 1; 6607 } 6608 } 6609 6610 sub _patch_p_parameter { 6611 my($self,$fh) = @_; 6612 my $cnt_files = 0; 6613 my $cnt_p0files = 0; 6614 local($_); 6615 while ($_ = $fh->READLINE) { 6616 if ( 6617 $CPAN::Config->{applypatch} 6618 && 6619 /\#\#\#\# ApplyPatch data follows \#\#\#\#/ 6620 ) { 6621 return "applypatch" 6622 } 6623 next unless /^[\*\+]{3}\s(\S+)/; 6624 my $file = $1; 6625 $cnt_files++; 6626 $cnt_p0files++ if -f $file; 6627 CPAN->debug("file[$file]cnt_files[$cnt_files]cnt_p0files[$cnt_p0files]") 6628 if $CPAN::DEBUG; 6629 } 6630 return "-p1" unless $cnt_files; 6631 return $cnt_files==$cnt_p0files ? "-p0" : "-p1"; 6632 } 6633 6634 #-> sub CPAN::Distribution::_edge_cases 6635 # with "configure" or "Makefile" or single file scripts 6636 sub _edge_cases { 6637 my($self,$mpl,$local_file) = @_; 6638 $self->debug(sprintf("makefilepl[%s]anycwd[%s]", 6639 $mpl, 6640 CPAN::anycwd(), 6641 )) if $CPAN::DEBUG; 6642 my $build_dir = $self->{build_dir}; 6643 my($configure) = File::Spec->catfile($build_dir,"Configure"); 6644 if (-f $configure) { 6645 # do we have anything to do? 6646 $self->{configure} = $configure; 6647 } elsif (-f File::Spec->catfile($build_dir,"Makefile")) { 6648 $CPAN::Frontend->mywarn(qq{ 6649 Package comes with a Makefile and without a Makefile.PL. 6650 We\'ll try to build it with that Makefile then. 6651 }); 6652 $self->{writemakefile} = CPAN::Distrostatus->new("YES"); 6653 $CPAN::Frontend->mysleep(2); 6654 } else { 6655 my $cf = $self->called_for || "unknown"; 6656 if ($cf =~ m|/|) { 6657 $cf =~ s|.*/||; 6658 $cf =~ s|\W.*||; 6659 } 6660 $cf =~ s|[/\\:]||g; # risk of filesystem damage 6661 $cf = "unknown" unless length($cf); 6662 $CPAN::Frontend->mywarn(qq{Package seems to come without Makefile.PL. 6663 (The test -f "$mpl" returned false.) 6664 Writing one on our own (setting NAME to $cf)\a\n}); 6665 $self->{had_no_makefile_pl}++; 6666 $CPAN::Frontend->mysleep(3); 6667 6668 # Writing our own Makefile.PL 6669 6670 my $script = ""; 6671 if ($self->{archived} eq "maybe_pl") { 6672 my $fh = FileHandle->new; 6673 my $script_file = File::Spec->catfile($build_dir,$local_file); 6674 $fh->open($script_file) 6675 or Carp::croak("Could not open script '$script_file': $!"); 6676 local $/ = "\n"; 6677 # name parsen und prereq 6678 my($state) = "poddir"; 6679 my($name, $prereq) = ("", ""); 6680 while (<$fh>) { 6681 if ($state eq "poddir" && /^=head\d\s+(\S+)/) { 6682 if ($1 eq 'NAME') { 6683 $state = "name"; 6684 } elsif ($1 eq 'PREREQUISITES') { 6685 $state = "prereq"; 6686 } 6687 } elsif ($state =~ m{^(name|prereq)$}) { 6688 if (/^=/) { 6689 $state = "poddir"; 6690 } elsif (/^\s*$/) { 6691 # nop 6692 } elsif ($state eq "name") { 6693 if ($name eq "") { 6694 ($name) = /^(\S+)/; 6695 $state = "poddir"; 6696 } 6697 } elsif ($state eq "prereq") { 6698 $prereq .= $_; 6699 } 6700 } elsif (/^=cut\b/) { 6701 last; 6702 } 6703 } 6704 $fh->close; 6705 6706 for ($name) { 6707 s{.*<}{}; # strip X<...> 6708 s{>.*}{}; 6709 } 6710 chomp $prereq; 6711 $prereq = join " ", split /\s+/, $prereq; 6712 my($PREREQ_PM) = join("\n", map { 6713 s{.*<}{}; # strip X<...> 6714 s{>.*}{}; 6715 if (/[\s\'\"]/) { # prose? 6716 } else { 6717 s/[^\w:]$//; # period? 6718 " "x28 . "'$_' => 0,"; 6719 } 6720 } split /\s*,\s*/, $prereq); 6721 6722 $script = " 6723 EXE_FILES => ['$name'], 6724 PREREQ_PM => { 6725 $PREREQ_PM 6726 }, 6727 "; 6728 if ($name) { 6729 my $to_file = File::Spec->catfile($build_dir, $name); 6730 rename $script_file, $to_file 6731 or die "Can't rename $script_file to $to_file: $!"; 6732 } 6733 } 6734 6735 my $fh = FileHandle->new; 6736 $fh->open(">$mpl") 6737 or Carp::croak("Could not open >$mpl: $!"); 6738 $fh->print( 6739 qq{# This Makefile.PL has been autogenerated by the module CPAN.pm 6740 # because there was no Makefile.PL supplied. 6741 # Autogenerated on: }.scalar localtime().qq{ 6742 6743 use ExtUtils::MakeMaker; 6744 WriteMakefile( 6745 NAME => q[$cf],$script 6746 ); 6747 }); 6748 $fh->close; 6749 } 6750 } 6751 6752 #-> CPAN::Distribution::_signature_business 6753 sub _signature_business { 6754 my($self) = @_; 6755 my $check_sigs = CPAN::HandleConfig->prefs_lookup($self, 6756 q{check_sigs}); 6757 if ($check_sigs) { 6758 if ($CPAN::META->has_inst("Module::Signature")) { 6759 if (-f "SIGNATURE") { 6760 $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG; 6761 my $rv = Module::Signature::verify(); 6762 if ($rv != Module::Signature::SIGNATURE_OK() and 6763 $rv != Module::Signature::SIGNATURE_MISSING()) { 6764 $CPAN::Frontend->mywarn( 6765 qq{\nSignature invalid for }. 6766 qq{distribution file. }. 6767 qq{Please investigate.\n\n} 6768 ); 6769 6770 my $wrap = 6771 sprintf(qq{I'd recommend removing %s. Some error occured }. 6772 qq{while checking its signature, so it could }. 6773 qq{be invalid. Maybe you have configured }. 6774 qq{your 'urllist' with a bad URL. Please check this }. 6775 qq{array with 'o conf urllist' and retry. Or }. 6776 qq{examine the distribution in a subshell. Try 6777 look %s 6778 and run 6779 cpansign -v 6780 }, 6781 $self->{localfile}, 6782 $self->pretty_id, 6783 ); 6784 $self->{signature_verify} = CPAN::Distrostatus->new("NO"); 6785 $CPAN::Frontend->mywarn(Text::Wrap::wrap("","",$wrap)); 6786 $CPAN::Frontend->mysleep(5) if $CPAN::Frontend->can("mysleep"); 6787 } else { 6788 $self->{signature_verify} = CPAN::Distrostatus->new("YES"); 6789 $self->debug("Module::Signature has verified") if $CPAN::DEBUG; 6790 } 6791 } else { 6792 $CPAN::Frontend->mywarn(qq{Package came without SIGNATURE\n\n}); 6793 } 6794 } else { 6795 $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG; 6796 } 6797 } 6798 } 6799 6800 #-> CPAN::Distribution::untar_me ; 6801 sub untar_me { 6802 my($self,$ct) = @_; 6803 $self->{archived} = "tar"; 6804 if ($ct->untar()) { 6805 $self->{unwrapped} = CPAN::Distrostatus->new("YES"); 6806 } else { 6807 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- untar failed"); 6808 } 6809 } 6810 6811 # CPAN::Distribution::unzip_me ; 6812 sub unzip_me { 6813 my($self,$ct) = @_; 6814 $self->{archived} = "zip"; 6815 if ($ct->unzip()) { 6816 $self->{unwrapped} = CPAN::Distrostatus->new("YES"); 6817 } else { 6818 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- unzip failed"); 6819 } 6820 return; 6821 } 6822 6823 sub handle_singlefile { 6824 my($self,$local_file) = @_; 6825 6826 if ( $local_file =~ /\.pm(\.(gz|Z))?(?!\n)\Z/ ) { 6827 $self->{archived} = "pm"; 6828 } elsif ( $local_file =~ /\.patch(\.(gz|bz2))?(?!\n)\Z/ ) { 6829 $self->{archived} = "patch"; 6830 } else { 6831 $self->{archived} = "maybe_pl"; 6832 } 6833 6834 my $to = File::Basename::basename($local_file); 6835 if ($to =~ s/\.(gz|Z)(?!\n)\Z//) { 6836 if (eval{CPAN::Tarzip->new($local_file)->gunzip($to)}) { 6837 $self->{unwrapped} = CPAN::Distrostatus->new("YES"); 6838 } else { 6839 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- uncompressing failed"); 6840 } 6841 } else { 6842 if (File::Copy::cp($local_file,".")) { 6843 $self->{unwrapped} = CPAN::Distrostatus->new("YES"); 6844 } else { 6845 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- copying failed"); 6846 } 6847 } 6848 return $to; 6849 } 6850 6851 #-> sub CPAN::Distribution::new ; 6852 sub new { 6853 my($class,%att) = @_; 6854 6855 # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); 6856 6857 my $this = { %att }; 6858 return bless $this, $class; 6859 } 6860 6861 #-> sub CPAN::Distribution::look ; 6862 sub look { 6863 my($self) = @_; 6864 6865 if ($^O eq 'MacOS') { 6866 $self->Mac::BuildTools::look; 6867 return; 6868 } 6869 6870 if ( $CPAN::Config->{'shell'} ) { 6871 $CPAN::Frontend->myprint(qq{ 6872 Trying to open a subshell in the build directory... 6873 }); 6874 } else { 6875 $CPAN::Frontend->myprint(qq{ 6876 Your configuration does not define a value for subshells. 6877 Please define it with "o conf shell <your shell>" 6878 }); 6879 return; 6880 } 6881 my $dist = $self->id; 6882 my $dir; 6883 unless ($dir = $self->dir) { 6884 $self->get; 6885 } 6886 unless ($dir ||= $self->dir) { 6887 $CPAN::Frontend->mywarn(qq{ 6888 Could not determine which directory to use for looking at $dist. 6889 }); 6890 return; 6891 } 6892 my $pwd = CPAN::anycwd(); 6893 $self->safe_chdir($dir); 6894 $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); 6895 { 6896 local $ENV{CPAN_SHELL_LEVEL} = $ENV{CPAN_SHELL_LEVEL}||0; 6897 $ENV{CPAN_SHELL_LEVEL} += 1; 6898 my $shell = CPAN::HandleConfig->safe_quote($CPAN::Config->{'shell'}); 6899 unless (system($shell) == 0) { 6900 my $code = $? >> 8; 6901 $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n"); 6902 } 6903 } 6904 $self->safe_chdir($pwd); 6905 } 6906 6907 # CPAN::Distribution::cvs_import ; 6908 sub cvs_import { 6909 my($self) = @_; 6910 $self->get; 6911 my $dir = $self->dir; 6912 6913 my $package = $self->called_for; 6914 my $module = $CPAN::META->instance('CPAN::Module', $package); 6915 my $version = $module->cpan_version; 6916 6917 my $userid = $self->cpan_userid; 6918 6919 my $cvs_dir = (split /\//, $dir)[-1]; 6920 $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//; 6921 my $cvs_root = 6922 $CPAN::Config->{cvsroot} || $ENV{CVSROOT}; 6923 my $cvs_site_perl = 6924 $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL}; 6925 if ($cvs_site_perl) { 6926 $cvs_dir = "$cvs_site_perl/$cvs_dir"; 6927 } 6928 my $cvs_log = qq{"imported $package $version sources"}; 6929 $version =~ s/\./_/g; 6930 # XXX cvs: undocumented and unclear how it was meant to work 6931 my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log, 6932 "$cvs_dir", $userid, "v$version"); 6933 6934 my $pwd = CPAN::anycwd(); 6935 chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!}); 6936 6937 $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); 6938 6939 $CPAN::Frontend->myprint(qq{@cmd\n}); 6940 system(@cmd) == 0 or 6941 # XXX cvs 6942 $CPAN::Frontend->mydie("cvs import failed"); 6943 chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!}); 6944 } 6945 6946 #-> sub CPAN::Distribution::readme ; 6947 sub readme { 6948 my($self) = @_; 6949 my($dist) = $self->id; 6950 my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/; 6951 $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG; 6952 my($local_file); 6953 my($local_wanted) = 6954 File::Spec->catfile( 6955 $CPAN::Config->{keep_source_where}, 6956 "authors", 6957 "id", 6958 split(/\//,"$sans.readme"), 6959 ); 6960 $self->debug("Doing localize") if $CPAN::DEBUG; 6961 $local_file = CPAN::FTP->localize("authors/id/$sans.readme", 6962 $local_wanted) 6963 or $CPAN::Frontend->mydie(qq{No $sans.readme found});; 6964 6965 if ($^O eq 'MacOS') { 6966 Mac::BuildTools::launch_file($local_file); 6967 return; 6968 } 6969 6970 my $fh_pager = FileHandle->new; 6971 local($SIG{PIPE}) = "IGNORE"; 6972 my $pager = $CPAN::Config->{'pager'} || "cat"; 6973 $fh_pager->open("|$pager") 6974 or die "Could not open pager $pager\: $!"; 6975 my $fh_readme = FileHandle->new; 6976 $fh_readme->open($local_file) 6977 or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!}); 6978 $CPAN::Frontend->myprint(qq{ 6979 Displaying file 6980 $local_file 6981 with pager "$pager" 6982 }); 6983 $fh_pager->print(<$fh_readme>); 6984 $fh_pager->close; 6985 } 6986 6987 #-> sub CPAN::Distribution::verifyCHECKSUM ; 6988 sub verifyCHECKSUM { 6989 my($self) = @_; 6990 EXCUSE: { 6991 my @e; 6992 $self->{CHECKSUM_STATUS} ||= ""; 6993 $self->{CHECKSUM_STATUS} eq "OK" and push @e, "Checksum was ok"; 6994 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 6995 } 6996 my($lc_want,$lc_file,@local,$basename); 6997 @local = split(/\//,$self->id); 6998 pop @local; 6999 push @local, "CHECKSUMS"; 7000 $lc_want = 7001 File::Spec->catfile($CPAN::Config->{keep_source_where}, 7002 "authors", "id", @local); 7003 local($") = "/"; 7004 if (my $size = -s $lc_want) { 7005 $self->debug("lc_want[$lc_want]size[$size]") if $CPAN::DEBUG; 7006 if ($self->CHECKSUM_check_file($lc_want,1)) { 7007 return $self->{CHECKSUM_STATUS} = "OK"; 7008 } 7009 } 7010 $lc_file = CPAN::FTP->localize("authors/id/@local", 7011 $lc_want,1); 7012 unless ($lc_file) { 7013 $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); 7014 $local[-1] .= ".gz"; 7015 $lc_file = CPAN::FTP->localize("authors/id/@local", 7016 "$lc_want.gz",1); 7017 if ($lc_file) { 7018 $lc_file =~ s/\.gz(?!\n)\Z//; 7019 eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)}; 7020 } else { 7021 return; 7022 } 7023 } 7024 if ($self->CHECKSUM_check_file($lc_file)) { 7025 return $self->{CHECKSUM_STATUS} = "OK"; 7026 } 7027 } 7028 7029 #-> sub CPAN::Distribution::SIG_check_file ; 7030 sub SIG_check_file { 7031 my($self,$chk_file) = @_; 7032 my $rv = eval { Module::Signature::_verify($chk_file) }; 7033 7034 if ($rv == Module::Signature::SIGNATURE_OK()) { 7035 $CPAN::Frontend->myprint("Signature for $chk_file ok\n"); 7036 return $self->{SIG_STATUS} = "OK"; 7037 } else { 7038 $CPAN::Frontend->myprint(qq{\nSignature invalid for }. 7039 qq{distribution file. }. 7040 qq{Please investigate.\n\n}. 7041 $self->as_string, 7042 $CPAN::META->instance( 7043 'CPAN::Author', 7044 $self->cpan_userid 7045 )->as_string); 7046 7047 my $wrap = qq{I\'d recommend removing $chk_file. Its signature 7048 is invalid. Maybe you have configured your 'urllist' with 7049 a bad URL. Please check this array with 'o conf urllist', and 7050 retry.}; 7051 7052 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); 7053 } 7054 } 7055 7056 #-> sub CPAN::Distribution::CHECKSUM_check_file ; 7057 7058 # sloppy is 1 when we have an old checksums file that maybe is good 7059 # enough 7060 7061 sub CHECKSUM_check_file { 7062 my($self,$chk_file,$sloppy) = @_; 7063 my($cksum,$file,$basename); 7064 7065 $sloppy ||= 0; 7066 $self->debug("chk_file[$chk_file]sloppy[$sloppy]") if $CPAN::DEBUG; 7067 my $check_sigs = CPAN::HandleConfig->prefs_lookup($self, 7068 q{check_sigs}); 7069 if ($check_sigs) { 7070 if ($CPAN::META->has_inst("Module::Signature")) { 7071 $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG; 7072 $self->SIG_check_file($chk_file); 7073 } else { 7074 $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG; 7075 } 7076 } 7077 7078 $file = $self->{localfile}; 7079 $basename = File::Basename::basename($file); 7080 my $fh = FileHandle->new; 7081 if (open $fh, $chk_file) { 7082 local($/); 7083 my $eval = <$fh>; 7084 $eval =~ s/\015?\012/\n/g; 7085 close $fh; 7086 my($comp) = Safe->new(); 7087 $cksum = $comp->reval($eval); 7088 if ($@) { 7089 rename $chk_file, "$chk_file.bad"; 7090 Carp::confess($@) if $@; 7091 } 7092 } else { 7093 Carp::carp "Could not open $chk_file for reading"; 7094 } 7095 7096 if (! ref $cksum or ref $cksum ne "HASH") { 7097 $CPAN::Frontend->mywarn(qq{ 7098 Warning: checksum file '$chk_file' broken. 7099 7100 When trying to read that file I expected to get a hash reference 7101 for further processing, but got garbage instead. 7102 }); 7103 my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no"); 7104 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); 7105 $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS file broken"; 7106 return; 7107 } elsif (exists $cksum->{$basename}{sha256}) { 7108 $self->debug("Found checksum for $basename:" . 7109 "$cksum->{$basename}{sha256}\n") if $CPAN::DEBUG; 7110 7111 open($fh, $file); 7112 binmode $fh; 7113 my $eq = $self->eq_CHECKSUM($fh,$cksum->{$basename}{sha256}); 7114 $fh->close; 7115 $fh = CPAN::Tarzip->TIEHANDLE($file); 7116 7117 unless ($eq) { 7118 my $dg = Digest::SHA->new(256); 7119 my($data,$ref); 7120 $ref = \$data; 7121 while ($fh->READ($ref, 4096) > 0) { 7122 $dg->add($data); 7123 } 7124 my $hexdigest = $dg->hexdigest; 7125 $eq += $hexdigest eq $cksum->{$basename}{'sha256-ungz'}; 7126 } 7127 7128 if ($eq) { 7129 $CPAN::Frontend->myprint("Checksum for $file ok\n"); 7130 return $self->{CHECKSUM_STATUS} = "OK"; 7131 } else { 7132 $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }. 7133 qq{distribution file. }. 7134 qq{Please investigate.\n\n}. 7135 $self->as_string, 7136 $CPAN::META->instance( 7137 'CPAN::Author', 7138 $self->cpan_userid 7139 )->as_string); 7140 7141 my $wrap = qq{I\'d recommend removing $file. Its 7142 checksum is incorrect. Maybe you have configured your 'urllist' with 7143 a bad URL. Please check this array with 'o conf urllist', and 7144 retry.}; 7145 7146 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); 7147 7148 # former versions just returned here but this seems a 7149 # serious threat that deserves a die 7150 7151 # $CPAN::Frontend->myprint("\n\n"); 7152 # sleep 3; 7153 # return; 7154 } 7155 # close $fh if fileno($fh); 7156 } else { 7157 return if $sloppy; 7158 unless ($self->{CHECKSUM_STATUS}) { 7159 $CPAN::Frontend->mywarn(qq{ 7160 Warning: No checksum for $basename in $chk_file. 7161 7162 The cause for this may be that the file is very new and the checksum 7163 has not yet been calculated, but it may also be that something is 7164 going awry right now. 7165 }); 7166 my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed?", "yes"); 7167 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); 7168 } 7169 $self->{CHECKSUM_STATUS} = "NIL -- distro not in CHECKSUMS file"; 7170 return; 7171 } 7172 } 7173 7174 #-> sub CPAN::Distribution::eq_CHECKSUM ; 7175 sub eq_CHECKSUM { 7176 my($self,$fh,$expect) = @_; 7177 if ($CPAN::META->has_inst("Digest::SHA")) { 7178 my $dg = Digest::SHA->new(256); 7179 my($data); 7180 while (read($fh, $data, 4096)) { 7181 $dg->add($data); 7182 } 7183 my $hexdigest = $dg->hexdigest; 7184 # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]"; 7185 return $hexdigest eq $expect; 7186 } 7187 return 1; 7188 } 7189 7190 #-> sub CPAN::Distribution::force ; 7191 7192 # Both CPAN::Modules and CPAN::Distributions know if "force" is in 7193 # effect by autoinspection, not by inspecting a global variable. One 7194 # of the reason why this was chosen to work that way was the treatment 7195 # of dependencies. They should not automatically inherit the force 7196 # status. But this has the downside that ^C and die() will return to 7197 # the prompt but will not be able to reset the force_update 7198 # attributes. We try to correct for it currently in the read_metadata 7199 # routine, and immediately before we check for a Signal. I hope this 7200 # works out in one of v1.57_53ff 7201 7202 # "Force get forgets previous error conditions" 7203 7204 #-> sub CPAN::Distribution::fforce ; 7205 sub fforce { 7206 my($self, $method) = @_; 7207 $self->force($method,1); 7208 } 7209 7210 #-> sub CPAN::Distribution::force ; 7211 sub force { 7212 my($self, $method,$fforce) = @_; 7213 my %phase_map = ( 7214 get => [ 7215 "unwrapped", 7216 "build_dir", 7217 "archived", 7218 "localfile", 7219 "CHECKSUM_STATUS", 7220 "signature_verify", 7221 "prefs", 7222 "prefs_file", 7223 "prefs_file_doc", 7224 ], 7225 make => [ 7226 "writemakefile", 7227 "make", 7228 "modulebuild", 7229 "prereq_pm", 7230 "prereq_pm_detected", 7231 ], 7232 test => [ 7233 "badtestcnt", 7234 "make_test", 7235 ], 7236 install => [ 7237 "install", 7238 ], 7239 unknown => [ 7240 "reqtype", 7241 "yaml_content", 7242 ], 7243 ); 7244 my $methodmatch = 0; 7245 my $ldebug = 0; 7246 PHASE: for my $phase (qw(unknown get make test install)) { # order matters 7247 $methodmatch = 1 if $fforce || $phase eq $method; 7248 next unless $methodmatch; 7249 ATTRIBUTE: for my $att (@{$phase_map{$phase}}) { 7250 if ($phase eq "get") { 7251 if (substr($self->id,-1,1) eq "." 7252 && $att =~ /(unwrapped|build_dir|archived)/ ) { 7253 # cannot be undone for local distros 7254 next ATTRIBUTE; 7255 } 7256 if ($att eq "build_dir" 7257 && $self->{build_dir} 7258 && $CPAN::META->{is_tested} 7259 ) { 7260 delete $CPAN::META->{is_tested}{$self->{build_dir}}; 7261 } 7262 } elsif ($phase eq "test") { 7263 if ($att eq "make_test" 7264 && $self->{make_test} 7265 && $self->{make_test}{COMMANDID} 7266 && $self->{make_test}{COMMANDID} == $CPAN::CurrentCommandId 7267 ) { 7268 # endless loop too likely 7269 next ATTRIBUTE; 7270 } 7271 } 7272 delete $self->{$att}; 7273 if ($ldebug || $CPAN::DEBUG) { 7274 # local $CPAN::DEBUG = 16; # Distribution 7275 CPAN->debug(sprintf "id[%s]phase[%s]att[%s]", $self->id, $phase, $att); 7276 } 7277 } 7278 } 7279 if ($method && $method =~ /make|test|install/) { 7280 $self->{force_update} = 1; # name should probably have been force_install 7281 } 7282 } 7283 7284 #-> sub CPAN::Distribution::notest ; 7285 sub notest { 7286 my($self, $method) = @_; 7287 # $CPAN::Frontend->mywarn("XDEBUG: set notest for $self $method"); 7288 $self->{"notest"}++; # name should probably have been force_install 7289 } 7290 7291 #-> sub CPAN::Distribution::unnotest ; 7292 sub unnotest { 7293 my($self) = @_; 7294 # warn "XDEBUG: deleting notest"; 7295 delete $self->{notest}; 7296 } 7297 7298 #-> sub CPAN::Distribution::unforce ; 7299 sub unforce { 7300 my($self) = @_; 7301 delete $self->{force_update}; 7302 } 7303 7304 #-> sub CPAN::Distribution::isa_perl ; 7305 sub isa_perl { 7306 my($self) = @_; 7307 my $file = File::Basename::basename($self->id); 7308 if ($file =~ m{ ^ perl 7309 -? 7310 (5) 7311 ([._-]) 7312 ( 7313 \d{3}(_[0-4][0-9])? 7314 | 7315 \d+\.\d+ 7316 ) 7317 \.tar[._-](?:gz|bz2) 7318 (?!\n)\Z 7319 }xs) { 7320 return "$1.$3"; 7321 } elsif ($self->cpan_comment 7322 && 7323 $self->cpan_comment =~ /isa_perl\(.+?\)/) { 7324 return $1; 7325 } 7326 } 7327 7328 7329 #-> sub CPAN::Distribution::perl ; 7330 sub perl { 7331 my ($self) = @_; 7332 if (! $self) { 7333 use Carp qw(carp); 7334 carp __PACKAGE__ . "::perl was called without parameters."; 7335 } 7336 return CPAN::HandleConfig->safe_quote($CPAN::Perl); 7337 } 7338 7339 7340 #-> sub CPAN::Distribution::make ; 7341 sub make { 7342 my($self) = @_; 7343 if (my $goto = $self->prefs->{goto}) { 7344 return $self->goto($goto); 7345 } 7346 my $make = $self->{modulebuild} ? "Build" : "make"; 7347 # Emergency brake if they said install Pippi and get newest perl 7348 if ($self->isa_perl) { 7349 if ( 7350 $self->called_for ne $self->id && 7351 ! $self->{force_update} 7352 ) { 7353 # if we die here, we break bundles 7354 $CPAN::Frontend 7355 ->mywarn(sprintf( 7356 qq{The most recent version "%s" of the module "%s" 7357 is part of the perl-%s distribution. To install that, you need to run 7358 force install %s --or-- 7359 install %s 7360 }, 7361 $CPAN::META->instance( 7362 'CPAN::Module', 7363 $self->called_for 7364 )->cpan_version, 7365 $self->called_for, 7366 $self->isa_perl, 7367 $self->called_for, 7368 $self->id, 7369 )); 7370 $self->{make} = CPAN::Distrostatus->new("NO isa perl"); 7371 $CPAN::Frontend->mysleep(1); 7372 return; 7373 } 7374 } 7375 $CPAN::Frontend->myprint(sprintf "Running %s for %s\n", $make, $self->id); 7376 $self->get; 7377 if ($self->{configure_requires_later}) { 7378 return; 7379 } 7380 local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) 7381 ? $ENV{PERL5LIB} 7382 : ($ENV{PERLLIB} || ""); 7383 $CPAN::META->set_perl5lib; 7384 local $ENV{MAKEFLAGS}; # protect us from outer make calls 7385 7386 if ($CPAN::Signal) { 7387 delete $self->{force_update}; 7388 return; 7389 } 7390 7391 my $builddir; 7392 EXCUSE: { 7393 my @e; 7394 if (!$self->{archived} || $self->{archived} eq "NO") { 7395 push @e, "Is neither a tar nor a zip archive."; 7396 } 7397 7398 if (!$self->{unwrapped} 7399 || ( 7400 UNIVERSAL::can($self->{unwrapped},"failed") ? 7401 $self->{unwrapped}->failed : 7402 $self->{unwrapped} =~ /^NO/ 7403 )) { 7404 push @e, "Had problems unarchiving. Please build manually"; 7405 } 7406 7407 unless ($self->{force_update}) { 7408 exists $self->{signature_verify} and 7409 ( 7410 UNIVERSAL::can($self->{signature_verify},"failed") ? 7411 $self->{signature_verify}->failed : 7412 $self->{signature_verify} =~ /^NO/ 7413 ) 7414 and push @e, "Did not pass the signature test."; 7415 } 7416 7417 if (exists $self->{writemakefile} && 7418 ( 7419 UNIVERSAL::can($self->{writemakefile},"failed") ? 7420 $self->{writemakefile}->failed : 7421 $self->{writemakefile} =~ /^NO/ 7422 )) { 7423 # XXX maybe a retry would be in order? 7424 my $err = UNIVERSAL::can($self->{writemakefile},"text") ? 7425 $self->{writemakefile}->text : 7426 $self->{writemakefile}; 7427 $err =~ s/^NO\s*//; 7428 $err ||= "Had some problem writing Makefile"; 7429 $err .= ", won't make"; 7430 push @e, $err; 7431 } 7432 7433 if (defined $self->{make}) { 7434 if (UNIVERSAL::can($self->{make},"failed") ? 7435 $self->{make}->failed : 7436 $self->{make} =~ /^NO/) { 7437 if ($self->{force_update}) { 7438 # Trying an already failed 'make' (unless somebody else blocks) 7439 } else { 7440 # introduced for turning recursion detection into a distrostatus 7441 my $error = length $self->{make}>3 7442 ? substr($self->{make},3) : "Unknown error"; 7443 $CPAN::Frontend->mywarn("Could not make: $error\n"); 7444 $self->store_persistent_state; 7445 return; 7446 } 7447 } else { 7448 push @e, "Has already been made"; 7449 } 7450 } 7451 7452 my $later = $self->{later} || $self->{configure_requires_later}; 7453 if ($later) { # see also undelay 7454 if ($later) { 7455 push @e, $later; 7456 } 7457 } 7458 7459 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 7460 $builddir = $self->dir or 7461 $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n"); 7462 unless (chdir $builddir) { 7463 push @e, "Couldn't chdir to '$builddir': $!"; 7464 } 7465 $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e; 7466 } 7467 if ($CPAN::Signal) { 7468 delete $self->{force_update}; 7469 return; 7470 } 7471 $CPAN::Frontend->myprint("\n CPAN.pm: Going to build ".$self->id."\n\n"); 7472 $self->debug("Changed directory to $builddir") if $CPAN::DEBUG; 7473 7474 if ($^O eq 'MacOS') { 7475 Mac::BuildTools::make($self); 7476 return; 7477 } 7478 7479 my %env; 7480 while (my($k,$v) = each %ENV) { 7481 next unless defined $v; 7482 $env{$k} = $v; 7483 } 7484 local %ENV = %env; 7485 my $system; 7486 if (my $commandline = $self->prefs->{pl}{commandline}) { 7487 $system = $commandline; 7488 $ENV{PERL} = $^X; 7489 } elsif ($self->{'configure'}) { 7490 $system = $self->{'configure'}; 7491 } elsif ($self->{modulebuild}) { 7492 my($perl) = $self->perl or die "Couldn\'t find executable perl\n"; 7493 $system = "$perl Build.PL $CPAN::Config->{mbuildpl_arg}"; 7494 } else { 7495 my($perl) = $self->perl or die "Couldn\'t find executable perl\n"; 7496 my $switch = ""; 7497 # This needs a handler that can be turned on or off: 7498 # $switch = "-MExtUtils::MakeMaker ". 7499 # "-Mops=:default,:filesys_read,:filesys_open,require,chdir" 7500 # if $] > 5.00310; 7501 my $makepl_arg = $self->make_x_arg("pl"); 7502 $ENV{PERL5_CPAN_IS_EXECUTING} = File::Spec->catfile($self->{build_dir}, 7503 "Makefile.PL"); 7504 $system = sprintf("%s%s Makefile.PL%s", 7505 $perl, 7506 $switch ? " $switch" : "", 7507 $makepl_arg ? " $makepl_arg" : "", 7508 ); 7509 } 7510 if (my $env = $self->prefs->{pl}{env}) { 7511 for my $e (keys %$env) { 7512 $ENV{$e} = $env->{$e}; 7513 } 7514 } 7515 if (exists $self->{writemakefile}) { 7516 } else { 7517 local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" }; 7518 my($ret,$pid,$output); 7519 $@ = ""; 7520 my $go_via_alarm; 7521 if ($CPAN::Config->{inactivity_timeout}) { 7522 require Config; 7523 if ($Config::Config{d_alarm} 7524 && 7525 $Config::Config{d_alarm} eq "define" 7526 ) { 7527 $go_via_alarm++ 7528 } else { 7529 $CPAN::Frontend->mywarn("Warning: you have configured the config ". 7530 "variable 'inactivity_timeout' to ". 7531 "'$CPAN::Config->{inactivity_timeout}'. But ". 7532 "on this machine the system call 'alarm' ". 7533 "isn't available. This means that we cannot ". 7534 "provide the feature of intercepting long ". 7535 "waiting code and will turn this feature off.\n" 7536 ); 7537 $CPAN::Config->{inactivity_timeout} = 0; 7538 } 7539 } 7540 if ($go_via_alarm) { 7541 if ( $self->_should_report('pl') ) { 7542 ($output, $ret) = CPAN::Reporter::record_command( 7543 $system, 7544 $CPAN::Config->{inactivity_timeout}, 7545 ); 7546 CPAN::Reporter::grade_PL( $self, $system, $output, $ret ); 7547 } 7548 else { 7549 eval { 7550 alarm $CPAN::Config->{inactivity_timeout}; 7551 local $SIG{CHLD}; # = sub { wait }; 7552 if (defined($pid = fork)) { 7553 if ($pid) { #parent 7554 # wait; 7555 waitpid $pid, 0; 7556 } else { #child 7557 # note, this exec isn't necessary if 7558 # inactivity_timeout is 0. On the Mac I'd 7559 # suggest, we set it always to 0. 7560 exec $system; 7561 } 7562 } else { 7563 $CPAN::Frontend->myprint("Cannot fork: $!"); 7564 return; 7565 } 7566 }; 7567 alarm 0; 7568 if ($@) { 7569 kill 9, $pid; 7570 waitpid $pid, 0; 7571 my $err = "$@"; 7572 $CPAN::Frontend->myprint($err); 7573 $self->{writemakefile} = CPAN::Distrostatus->new("NO $err"); 7574 $@ = ""; 7575 $self->store_persistent_state; 7576 return $self->goodbye("$system -- TIMED OUT"); 7577 } 7578 } 7579 } else { 7580 if (my $expect_model = $self->_prefs_with_expect("pl")) { 7581 # XXX probably want to check _should_report here and warn 7582 # about not being able to use CPAN::Reporter with expect 7583 $ret = $self->_run_via_expect($system,$expect_model); 7584 if (! defined $ret 7585 && $self->{writemakefile} 7586 && $self->{writemakefile}->failed) { 7587 # timeout 7588 return; 7589 } 7590 } 7591 elsif ( $self->_should_report('pl') ) { 7592 ($output, $ret) = CPAN::Reporter::record_command($system); 7593 CPAN::Reporter::grade_PL( $self, $system, $output, $ret ); 7594 } 7595 else { 7596 $ret = system($system); 7597 } 7598 if ($ret != 0) { 7599 $self->{writemakefile} = CPAN::Distrostatus 7600 ->new("NO '$system' returned status $ret"); 7601 $CPAN::Frontend->mywarn("Warning: No success on command[$system]\n"); 7602 $self->store_persistent_state; 7603 return $self->goodbye("$system -- NOT OK"); 7604 } 7605 } 7606 if (-f "Makefile" || -f "Build") { 7607 $self->{writemakefile} = CPAN::Distrostatus->new("YES"); 7608 delete $self->{make_clean}; # if cleaned before, enable next 7609 } else { 7610 my $makefile = $self->{modulebuild} ? "Build" : "Makefile"; 7611 $self->{writemakefile} = CPAN::Distrostatus 7612 ->new(qq{NO -- No $makefile created}); 7613 $self->store_persistent_state; 7614 return $self->goodbye("$system -- NO $makefile created"); 7615 } 7616 } 7617 if ($CPAN::Signal) { 7618 delete $self->{force_update}; 7619 return; 7620 } 7621 if (my @prereq = $self->unsat_prereq("later")) { 7622 if ($prereq[0][0] eq "perl") { 7623 my $need = "requires perl '$prereq[0][1]'"; 7624 my $id = $self->pretty_id; 7625 $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n"); 7626 $self->{make} = CPAN::Distrostatus->new("NO $need"); 7627 $self->store_persistent_state; 7628 return $self->goodbye("[prereq] -- NOT OK"); 7629 } else { 7630 my $follow = eval { $self->follow_prereqs("later",@prereq); }; 7631 if (0) { 7632 } elsif ($follow) { 7633 # signal success to the queuerunner 7634 return 1; 7635 } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) { 7636 $CPAN::Frontend->mywarn($@); 7637 return $self->goodbye("[depend] -- NOT OK"); 7638 } 7639 } 7640 } 7641 if ($CPAN::Signal) { 7642 delete $self->{force_update}; 7643 return; 7644 } 7645 if (my $commandline = $self->prefs->{make}{commandline}) { 7646 $system = $commandline; 7647 $ENV{PERL} = CPAN::find_perl; 7648 } else { 7649 if ($self->{modulebuild}) { 7650 unless (-f "Build") { 7651 my $cwd = CPAN::anycwd(); 7652 $CPAN::Frontend->mywarn("Alert: no Build file available for 'make $self->{id}'". 7653 " in cwd[$cwd]. Danger, Will Robinson!\n"); 7654 $CPAN::Frontend->mysleep(5); 7655 } 7656 $system = join " ", $self->_build_command(), $CPAN::Config->{mbuild_arg}; 7657 } else { 7658 $system = join " ", $self->_make_command(), $CPAN::Config->{make_arg}; 7659 } 7660 $system =~ s/\s+$//; 7661 my $make_arg = $self->make_x_arg("make"); 7662 $system = sprintf("%s%s", 7663 $system, 7664 $make_arg ? " $make_arg" : "", 7665 ); 7666 } 7667 if (my $env = $self->prefs->{make}{env}) { # overriding the local 7668 # ENV of PL, not the 7669 # outer ENV, but 7670 # unlikely to be a risk 7671 for my $e (keys %$env) { 7672 $ENV{$e} = $env->{$e}; 7673 } 7674 } 7675 my $expect_model = $self->_prefs_with_expect("make"); 7676 my $want_expect = 0; 7677 if ( $expect_model && @{$expect_model->{talk}} ) { 7678 my $can_expect = $CPAN::META->has_inst("Expect"); 7679 if ($can_expect) { 7680 $want_expect = 1; 7681 } else { 7682 $CPAN::Frontend->mywarn("Expect not installed, falling back to ". 7683 "system()\n"); 7684 } 7685 } 7686 my $system_ok; 7687 if ($want_expect) { 7688 # XXX probably want to check _should_report here and 7689 # warn about not being able to use CPAN::Reporter with expect 7690 $system_ok = $self->_run_via_expect($system,$expect_model) == 0; 7691 } 7692 elsif ( $self->_should_report('make') ) { 7693 my ($output, $ret) = CPAN::Reporter::record_command($system); 7694 CPAN::Reporter::grade_make( $self, $system, $output, $ret ); 7695 $system_ok = ! $ret; 7696 } 7697 else { 7698 $system_ok = system($system) == 0; 7699 } 7700 $self->introduce_myself; 7701 if ( $system_ok ) { 7702 $CPAN::Frontend->myprint(" $system -- OK\n"); 7703 $self->{make} = CPAN::Distrostatus->new("YES"); 7704 } else { 7705 $self->{writemakefile} ||= CPAN::Distrostatus->new("YES"); 7706 $self->{make} = CPAN::Distrostatus->new("NO"); 7707 $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); 7708 } 7709 $self->store_persistent_state; 7710 } 7711 7712 # CPAN::Distribution::goodbye ; 7713 sub goodbye { 7714 my($self,$goodbye) = @_; 7715 my $id = $self->pretty_id; 7716 $CPAN::Frontend->mywarn(" $id\n $goodbye\n"); 7717 return; 7718 } 7719 7720 # CPAN::Distribution::_run_via_expect ; 7721 sub _run_via_expect { 7722 my($self,$system,$expect_model) = @_; 7723 CPAN->debug("system[$system]expect_model[$expect_model]") if $CPAN::DEBUG; 7724 if ($CPAN::META->has_inst("Expect")) { 7725 my $expo = Expect->new; # expo Expect object; 7726 $expo->spawn($system); 7727 $expect_model->{mode} ||= "deterministic"; 7728 if ($expect_model->{mode} eq "deterministic") { 7729 return $self->_run_via_expect_deterministic($expo,$expect_model); 7730 } elsif ($expect_model->{mode} eq "anyorder") { 7731 return $self->_run_via_expect_anyorder($expo,$expect_model); 7732 } else { 7733 die "Panic: Illegal expect mode: $expect_model->{mode}"; 7734 } 7735 } else { 7736 $CPAN::Frontend->mywarn("Expect not installed, falling back to system()\n"); 7737 return system($system); 7738 } 7739 } 7740 7741 sub _run_via_expect_anyorder { 7742 my($self,$expo,$expect_model) = @_; 7743 my $timeout = $expect_model->{timeout} || 5; 7744 my $reuse = $expect_model->{reuse}; 7745 my @expectacopy = @{$expect_model->{talk}}; # we trash it! 7746 my $but = ""; 7747 EXPECT: while () { 7748 my($eof,$ran_into_timeout); 7749 my @match = $expo->expect($timeout, 7750 [ eof => sub { 7751 $eof++; 7752 } ], 7753 [ timeout => sub { 7754 $ran_into_timeout++; 7755 } ], 7756 -re => eval"qr{.}", 7757 ); 7758 if ($match[2]) { 7759 $but .= $match[2]; 7760 } 7761 $but .= $expo->clear_accum; 7762 if ($eof) { 7763 $expo->soft_close; 7764 return $expo->exitstatus(); 7765 } elsif ($ran_into_timeout) { 7766 # warn "DEBUG: they are asking a question, but[$but]"; 7767 for (my $i = 0; $i <= $#expectacopy; $i+=2) { 7768 my($next,$send) = @expectacopy[$i,$i+1]; 7769 my $regex = eval "qr{$next}"; 7770 # warn "DEBUG: will compare with regex[$regex]."; 7771 if ($but =~ /$regex/) { 7772 # warn "DEBUG: will send send[$send]"; 7773 $expo->send($send); 7774 # never allow reusing an QA pair unless they told us 7775 splice @expectacopy, $i, 2 unless $reuse; 7776 next EXPECT; 7777 } 7778 } 7779 my $why = "could not answer a question during the dialog"; 7780 $CPAN::Frontend->mywarn("Failing: $why\n"); 7781 $self->{writemakefile} = 7782 CPAN::Distrostatus->new("NO $why"); 7783 return; 7784 } 7785 } 7786 } 7787 7788 sub _run_via_expect_deterministic { 7789 my($self,$expo,$expect_model) = @_; 7790 my $ran_into_timeout; 7791 my $timeout = $expect_model->{timeout} || 15; # currently unsettable 7792 my $expecta = $expect_model->{talk}; 7793 EXPECT: for (my $i = 0; $i <= $#$expecta; $i+=2) { 7794 my($re,$send) = @$expecta[$i,$i+1]; 7795 CPAN->debug("timeout[$timeout]re[$re]") if $CPAN::DEBUG; 7796 my $regex = eval "qr{$re}"; 7797 $expo->expect($timeout, 7798 [ eof => sub { 7799 my $but = $expo->clear_accum; 7800 $CPAN::Frontend->mywarn("EOF (maybe harmless) 7801 expected[$regex]\nbut[$but]\n\n"); 7802 last EXPECT; 7803 } ], 7804 [ timeout => sub { 7805 my $but = $expo->clear_accum; 7806 $CPAN::Frontend->mywarn("TIMEOUT 7807 expected[$regex]\nbut[$but]\n\n"); 7808 $ran_into_timeout++; 7809 } ], 7810 -re => $regex); 7811 if ($ran_into_timeout) { 7812 # note that the caller expects 0 for success 7813 $self->{writemakefile} = 7814 CPAN::Distrostatus->new("NO timeout during expect dialog"); 7815 return; 7816 } 7817 $expo->send($send); 7818 } 7819 $expo->soft_close; 7820 return $expo->exitstatus(); 7821 } 7822 7823 #-> CPAN::Distribution::_validate_distropref 7824 sub _validate_distropref { 7825 my($self,@args) = @_; 7826 if ( 7827 $CPAN::META->has_inst("CPAN::Kwalify") 7828 && 7829 $CPAN::META->has_inst("Kwalify") 7830 ) { 7831 eval {CPAN::Kwalify::_validate("distroprefs",@args);}; 7832 if ($@) { 7833 $CPAN::Frontend->mywarn($@); 7834 } 7835 } else { 7836 CPAN->debug("not validating '@args'") if $CPAN::DEBUG; 7837 } 7838 } 7839 7840 #-> CPAN::Distribution::_find_prefs 7841 sub _find_prefs { 7842 my($self) = @_; 7843 my $distroid = $self->pretty_id; 7844 #CPAN->debug("distroid[$distroid]") if $CPAN::DEBUG; 7845 my $prefs_dir = $CPAN::Config->{prefs_dir}; 7846 return if $prefs_dir =~ /^\s*$/; 7847 eval { File::Path::mkpath($prefs_dir); }; 7848 if ($@) { 7849 $CPAN::Frontend->mydie("Cannot create directory $prefs_dir"); 7850 } 7851 my $yaml_module = CPAN::_yaml_module; 7852 my @extensions; 7853 if ($CPAN::META->has_inst($yaml_module)) { 7854 push @extensions, "yml"; 7855 } else { 7856 my @fallbacks; 7857 if ($CPAN::META->has_inst("Data::Dumper")) { 7858 push @extensions, "dd"; 7859 push @fallbacks, "Data::Dumper"; 7860 } 7861 if ($CPAN::META->has_inst("Storable")) { 7862 push @extensions, "st"; 7863 push @fallbacks, "Storable"; 7864 } 7865 if (@fallbacks) { 7866 local $" = " and "; 7867 unless ($self->{have_complained_about_missing_yaml}++) { 7868 $CPAN::Frontend->mywarn("'$yaml_module' not installed, falling back ". 7869 "to @fallbacks to read prefs '$prefs_dir'\n"); 7870 } 7871 } else { 7872 unless ($self->{have_complained_about_missing_yaml}++) { 7873 $CPAN::Frontend->mywarn("'$yaml_module' not installed, cannot ". 7874 "read prefs '$prefs_dir'\n"); 7875 } 7876 } 7877 } 7878 if (@extensions) { 7879 my $dh = DirHandle->new($prefs_dir) 7880 or die Carp::croak("Couldn't open '$prefs_dir': $!"); 7881 DIRENT: for (sort $dh->read) { 7882 next if $_ eq "." || $_ eq ".."; 7883 my $exte = join "|", @extensions; 7884 next unless /\.($exte)$/; 7885 my $thisexte = $1; 7886 my $abs = File::Spec->catfile($prefs_dir, $_); 7887 if (-f $abs) { 7888 #CPAN->debug(sprintf "abs[%s]", $abs) if $CPAN::DEBUG; 7889 my @distropref; 7890 if ($thisexte eq "yml") { 7891 # need no eval because if we have no YAML we do not try to read *.yml 7892 #CPAN->debug(sprintf "before yaml load abs[%s]", $abs) if $CPAN::DEBUG; 7893 @distropref = @{CPAN->_yaml_loadfile($abs)}; 7894 #CPAN->debug(sprintf "after yaml load abs[%s]", $abs) if $CPAN::DEBUG; 7895 } elsif ($thisexte eq "dd") { 7896 package CPAN::Eval; 7897 no strict; 7898 open FH, "<$abs" or $CPAN::Frontend->mydie("Could not open '$abs': $!"); 7899 local $/; 7900 my $eval = <FH>; 7901 close FH; 7902 eval $eval; 7903 if ($@) { 7904 $CPAN::Frontend->mydie("Error in distroprefs file $_\: $@"); 7905 } 7906 my $i = 1; 7907 while (${"VAR".$i}) { 7908 push @distropref, ${"VAR".$i}; 7909 $i++; 7910 } 7911 } elsif ($thisexte eq "st") { 7912 # eval because Storable is never forward compatible 7913 eval { @distropref = @{scalar Storable::retrieve($abs)}; }; 7914 if ($@) { 7915 $CPAN::Frontend->mywarn("Error reading distroprefs file ". 7916 "$_, skipping\: $@"); 7917 $CPAN::Frontend->mysleep(4); 7918 next DIRENT; 7919 } 7920 } 7921 # $DB::single=1; 7922 #CPAN->debug(sprintf "#distropref[%d]", scalar @distropref) if $CPAN::DEBUG; 7923 ELEMENT: for my $y (0..$#distropref) { 7924 my $distropref = $distropref[$y]; 7925 $self->_validate_distropref($distropref,$abs,$y); 7926 my $match = $distropref->{match}; 7927 unless ($match) { 7928 #CPAN->debug("no 'match' in abs[$abs], skipping") if $CPAN::DEBUG; 7929 next ELEMENT; 7930 } 7931 my $ok = 1; 7932 # do not take the order of C<keys %$match> because 7933 # "module" is by far the slowest 7934 my $saw_valid_subkeys = 0; 7935 for my $sub_attribute (qw(distribution perl perlconfig module)) { 7936 next unless exists $match->{$sub_attribute}; 7937 $saw_valid_subkeys++; 7938 my $qr = eval "qr{$distropref->{match}{$sub_attribute}}"; 7939 if ($sub_attribute eq "module") { 7940 my $okm = 0; 7941 #CPAN->debug(sprintf "distropref[%d]", scalar @distropref) if $CPAN::DEBUG; 7942 my @modules = $self->containsmods; 7943 #CPAN->debug(sprintf "modules[%s]", join(",",@modules)) if $CPAN::DEBUG; 7944 MODULE: for my $module (@modules) { 7945 $okm ||= $module =~ /$qr/; 7946 last MODULE if $okm; 7947 } 7948 $ok &&= $okm; 7949 } elsif ($sub_attribute eq "distribution") { 7950 my $okd = $distroid =~ /$qr/; 7951 $ok &&= $okd; 7952 } elsif ($sub_attribute eq "perl") { 7953 my $okp = CPAN::find_perl =~ /$qr/; 7954 $ok &&= $okp; 7955 } elsif ($sub_attribute eq "perlconfig") { 7956 for my $perlconfigkey (keys %{$match->{perlconfig}}) { 7957 my $perlconfigval = $match->{perlconfig}->{$perlconfigkey}; 7958 # XXX should probably warn if Config does not exist 7959 my $okpc = $Config::Config{$perlconfigkey} =~ /$perlconfigval/; 7960 $ok &&= $okpc; 7961 last if $ok == 0; 7962 } 7963 } else { 7964 $CPAN::Frontend->mydie("Nonconforming .$thisexte file '$abs': ". 7965 "unknown sub_attribut '$sub_attribute'. ". 7966 "Please ". 7967 "remove, cannot continue."); 7968 } 7969 last if $ok == 0; # short circuit 7970 } 7971 unless ($saw_valid_subkeys) { 7972 $CPAN::Frontend->mydie("Nonconforming .$thisexte file '$abs': ". 7973 "missing match/* subattribute. ". 7974 "Please ". 7975 "remove, cannot continue."); 7976 } 7977 #CPAN->debug(sprintf "ok[%d]", $ok) if $CPAN::DEBUG; 7978 if ($ok) { 7979 return { 7980 prefs => $distropref, 7981 prefs_file => $abs, 7982 prefs_file_doc => $y, 7983 }; 7984 } 7985 7986 } 7987 } 7988 } 7989 $dh->close; 7990 } 7991 return; 7992 } 7993 7994 # CPAN::Distribution::prefs 7995 sub prefs { 7996 my($self) = @_; 7997 if (exists $self->{negative_prefs_cache} 7998 && 7999 $self->{negative_prefs_cache} != $CPAN::CurrentCommandId 8000 ) { 8001 delete $self->{negative_prefs_cache}; 8002 delete $self->{prefs}; 8003 } 8004 if (exists $self->{prefs}) { 8005 return $self->{prefs}; # XXX comment out during debugging 8006 } 8007 if ($CPAN::Config->{prefs_dir}) { 8008 CPAN->debug("prefs_dir[$CPAN::Config->{prefs_dir}]") if $CPAN::DEBUG; 8009 my $prefs = $self->_find_prefs(); 8010 $prefs ||= ""; # avoid warning next line 8011 CPAN->debug("prefs[$prefs]") if $CPAN::DEBUG; 8012 if ($prefs) { 8013 for my $x (qw(prefs prefs_file prefs_file_doc)) { 8014 $self->{$x} = $prefs->{$x}; 8015 } 8016 my $bs = sprintf( 8017 "%s[%s]", 8018 File::Basename::basename($self->{prefs_file}), 8019 $self->{prefs_file_doc}, 8020 ); 8021 my $filler1 = "_" x 22; 8022 my $filler2 = int(66 - length($bs))/2; 8023 $filler2 = 0 if $filler2 < 0; 8024 $filler2 = " " x $filler2; 8025 $CPAN::Frontend->myprint(" 8026 $filler1 D i s t r o P r e f s $filler1 8027 $filler2 $bs $filler2 8028 "); 8029 $CPAN::Frontend->mysleep(1); 8030 return $self->{prefs}; 8031 } 8032 } 8033 $self->{negative_prefs_cache} = $CPAN::CurrentCommandId; 8034 return $self->{prefs} = +{}; 8035 } 8036 8037 # CPAN::Distribution::make_x_arg 8038 sub make_x_arg { 8039 my($self, $whixh) = @_; 8040 my $make_x_arg; 8041 my $prefs = $self->prefs; 8042 if ( 8043 $prefs 8044 && exists $prefs->{$whixh} 8045 && exists $prefs->{$whixh}{args} 8046 && $prefs->{$whixh}{args} 8047 ) { 8048 $make_x_arg = join(" ", 8049 map {CPAN::HandleConfig 8050 ->safe_quote($_)} @{$prefs->{$whixh}{args}}, 8051 ); 8052 } 8053 my $what = sprintf "make%s_arg", $whixh eq "make" ? "" : $whixh; 8054 $make_x_arg ||= $CPAN::Config->{$what}; 8055 return $make_x_arg; 8056 } 8057 8058 # CPAN::Distribution::_make_command 8059 sub _make_command { 8060 my ($self) = @_; 8061 if ($self) { 8062 return 8063 CPAN::HandleConfig 8064 ->safe_quote( 8065 CPAN::HandleConfig->prefs_lookup($self, 8066 q{make}) 8067 || $Config::Config{make} 8068 || 'make' 8069 ); 8070 } else { 8071 # Old style call, without object. Deprecated 8072 Carp::confess("CPAN::_make_command() used as function. Don't Do That."); 8073 return 8074 safe_quote(undef, 8075 CPAN::HandleConfig->prefs_lookup($self,q{make}) 8076 || $CPAN::Config->{make} 8077 || $Config::Config{make} 8078 || 'make'); 8079 } 8080 } 8081 8082 #-> sub CPAN::Distribution::follow_prereqs ; 8083 sub follow_prereqs { 8084 my($self) = shift; 8085 my($slot) = shift; 8086 my(@prereq_tuples) = grep {$_->[0] ne "perl"} @_; 8087 return unless @prereq_tuples; 8088 my @prereq = map { $_->[0] } @prereq_tuples; 8089 my $pretty_id = $self->pretty_id; 8090 my %map = ( 8091 b => "build_requires", 8092 r => "requires", 8093 c => "commandline", 8094 ); 8095 my($filler1,$filler2,$filler3,$filler4); 8096 # $DB::single=1; 8097 my $unsat = "Unsatisfied dependencies detected during"; 8098 my $w = length($unsat) > length($pretty_id) ? length($unsat) : length($pretty_id); 8099 { 8100 my $r = int(($w - length($unsat))/2); 8101 my $l = $w - length($unsat) - $r; 8102 $filler1 = "-"x4 . " "x$l; 8103 $filler2 = " "x$r . "-"x4 . "\n"; 8104 } 8105 { 8106 my $r = int(($w - length($pretty_id))/2); 8107 my $l = $w - length($pretty_id) - $r; 8108 $filler3 = "-"x4 . " "x$l; 8109 $filler4 = " "x$r . "-"x4 . "\n"; 8110 } 8111 $CPAN::Frontend-> 8112 myprint("$filler1 $unsat $filler2". 8113 "$filler3 $pretty_id $filler4". 8114 join("", map {" $_->[0] \[$map{$_->[1]}]\n"} @prereq_tuples), 8115 ); 8116 my $follow = 0; 8117 if ($CPAN::Config->{prerequisites_policy} eq "follow") { 8118 $follow = 1; 8119 } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") { 8120 my $answer = CPAN::Shell::colorable_makemaker_prompt( 8121 "Shall I follow them and prepend them to the queue 8122 of modules we are processing right now?", "yes"); 8123 $follow = $answer =~ /^\s*y/i; 8124 } else { 8125 local($") = ", "; 8126 $CPAN::Frontend-> 8127 myprint(" Ignoring dependencies on modules @prereq\n"); 8128 } 8129 if ($follow) { 8130 my $id = $self->id; 8131 # color them as dirty 8132 for my $p (@prereq) { 8133 # warn "calling color_cmd_tmps(0,1)"; 8134 my $any = CPAN::Shell->expandany($p); 8135 $self->{$slot . "_for"}{$any->id}++; 8136 if ($any) { 8137 $any->color_cmd_tmps(0,2); 8138 } else { 8139 $CPAN::Frontend->mywarn("Warning (maybe a bug): Cannot expand prereq '$p'\n"); 8140 $CPAN::Frontend->mysleep(2); 8141 } 8142 } 8143 # queue them and re-queue yourself 8144 CPAN::Queue->jumpqueue({qmod => $id, reqtype => $self->{reqtype}}, 8145 map {+{qmod=>$_->[0],reqtype=>$_->[1]}} reverse @prereq_tuples); 8146 $self->{$slot} = "Delayed until after prerequisites"; 8147 return 1; # signal success to the queuerunner 8148 } 8149 return; 8150 } 8151 8152 #-> sub CPAN::Distribution::unsat_prereq ; 8153 # return ([Foo=>1],[Bar=>1.2]) for normal modules 8154 # return ([perl=>5.008]) if we need a newer perl than we are running under 8155 sub unsat_prereq { 8156 my($self,$slot) = @_; 8157 my(%merged,$prereq_pm); 8158 my $prefs_depends = $self->prefs->{depends}||{}; 8159 if ($slot eq "configure_requires_later") { 8160 my $meta_yml = $self->parse_meta_yml(); 8161 %merged = (%{$meta_yml->{configure_requires}||{}}, 8162 %{$prefs_depends->{configure_requires}||{}}); 8163 $prereq_pm = {}; # configure_requires defined as "b" 8164 } elsif ($slot eq "later") { 8165 my $prereq_pm_0 = $self->prereq_pm || {}; 8166 for my $reqtype (qw(requires build_requires)) { 8167 $prereq_pm->{$reqtype} = {%{$prereq_pm_0->{$reqtype}||{}}}; # copy to not pollute it 8168 for my $k (keys %{$prefs_depends->{$reqtype}||{}}) { 8169 $prereq_pm->{$reqtype}{$k} = $prefs_depends->{$reqtype}{$k}; 8170 } 8171 } 8172 %merged = (%{$prereq_pm->{requires}||{}},%{$prereq_pm->{build_requires}||{}}); 8173 } else { 8174 die "Panic: illegal slot '$slot'"; 8175 } 8176 my(@need); 8177 my @merged = %merged; 8178 CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG; 8179 NEED: while (my($need_module, $need_version) = each %merged) { 8180 my($available_version,$available_file,$nmo); 8181 if ($need_module eq "perl") { 8182 $available_version = $]; 8183 $available_file = CPAN::find_perl; 8184 } else { 8185 $nmo = $CPAN::META->instance("CPAN::Module",$need_module); 8186 next if $nmo->uptodate; 8187 $available_file = $nmo->available_file; 8188 8189 # if they have not specified a version, we accept any installed one 8190 if (defined $available_file 8191 and ( # a few quick shortcurcuits 8192 not defined $need_version 8193 or $need_version eq '0' # "==" would trigger warning when not numeric 8194 or $need_version eq "undef" 8195 )) { 8196 next NEED; 8197 } 8198 8199 $available_version = $nmo->available_version; 8200 } 8201 8202 # We only want to install prereqs if either they're not installed 8203 # or if the installed version is too old. We cannot omit this 8204 # check, because if 'force' is in effect, nobody else will check. 8205 if (defined $available_file) { 8206 my(@all_requirements) = split /\s*,\s*/, $need_version; 8207 local($^W) = 0; 8208 my $ok = 0; 8209 RQ: for my $rq (@all_requirements) { 8210 if ($rq =~ s|>=\s*||) { 8211 } elsif ($rq =~ s|>\s*||) { 8212 # 2005-12: one user 8213 if (CPAN::Version->vgt($available_version,$rq)) { 8214 $ok++; 8215 } 8216 next RQ; 8217 } elsif ($rq =~ s|!=\s*||) { 8218 # 2005-12: no user 8219 if (CPAN::Version->vcmp($available_version,$rq)) { 8220 $ok++; 8221 next RQ; 8222 } else { 8223 last RQ; 8224 } 8225 } elsif ($rq =~ m|<=?\s*|) { 8226 # 2005-12: no user 8227 $CPAN::Frontend->mywarn("Downgrading not supported (rq[$rq])\n"); 8228 $ok++; 8229 next RQ; 8230 } 8231 if (! CPAN::Version->vgt($rq, $available_version)) { 8232 $ok++; 8233 } 8234 CPAN->debug(sprintf("need_module[%s]available_file[%s]". 8235 "available_version[%s]rq[%s]ok[%d]", 8236 $need_module, 8237 $available_file, 8238 $available_version, 8239 CPAN::Version->readable($rq), 8240 $ok, 8241 )) if $CPAN::DEBUG; 8242 } 8243 next NEED if $ok == @all_requirements; 8244 } 8245 8246 if ($need_module eq "perl") { 8247 return ["perl", $need_version]; 8248 } 8249 $self->{sponsored_mods}{$need_module} ||= 0; 8250 CPAN->debug("need_module[$need_module]s/s/n[$self->{sponsored_mods}{$need_module}]") if $CPAN::DEBUG; 8251 if ($self->{sponsored_mods}{$need_module}++) { 8252 # We have already sponsored it and for some reason it's still 8253 # not available. So we do ... what?? 8254 8255 # if we push it again, we have a potential infinite loop 8256 8257 # The following "next" was a very problematic construct. 8258 # It helped a lot but broke some day and had to be 8259 # replaced. 8260 8261 # We must be able to deal with modules that come again and 8262 # again as a prereq and have themselves prereqs and the 8263 # queue becomes long but finally we would find the correct 8264 # order. The RecursiveDependency check should trigger a 8265 # die when it's becoming too weird. Unfortunately removing 8266 # this next breaks many other things. 8267 8268 # The bug that brought this up is described in Todo under 8269 # "5.8.9 cannot install Compress::Zlib" 8270 8271 # next; # this is the next that had to go away 8272 8273 # The following "next NEED" are fine and the error message 8274 # explains well what is going on. For example when the DBI 8275 # fails and consequently DBD::SQLite fails and now we are 8276 # processing CPAN::SQLite. Then we must have a "next" for 8277 # DBD::SQLite. How can we get it and how can we identify 8278 # all other cases we must identify? 8279 8280 my $do = $nmo->distribution; 8281 next NEED unless $do; # not on CPAN 8282 if (CPAN::Version->vcmp($need_version, $nmo->ro->{CPAN_VERSION}) > 0){ 8283 $CPAN::Frontend->mywarn("Warning: Prerequisite ". 8284 "'$need_module => $need_version' ". 8285 "for '$self->{ID}' seems ". 8286 "not available according to the indexes\n" 8287 ); 8288 next NEED; 8289 } 8290 NOSAYER: for my $nosayer ( 8291 "unwrapped", 8292 "writemakefile", 8293 "signature_verify", 8294 "make", 8295 "make_test", 8296 "install", 8297 "make_clean", 8298 ) { 8299 if ($do->{$nosayer}) { 8300 if (UNIVERSAL::can($do->{$nosayer},"failed") ? 8301 $do->{$nosayer}->failed : 8302 $do->{$nosayer} =~ /^NO/) { 8303 if ($nosayer eq "make_test" 8304 && 8305 $do->{make_test}{COMMANDID} != $CPAN::CurrentCommandId 8306 ) { 8307 next NOSAYER; 8308 } 8309 $CPAN::Frontend->mywarn("Warning: Prerequisite ". 8310 "'$need_module => $need_version' ". 8311 "for '$self->{ID}' failed when ". 8312 "processing '$do->{ID}' with ". 8313 "'$nosayer => $do->{$nosayer}'. Continuing, ". 8314 "but chances to succeed are limited.\n" 8315 ); 8316 next NEED; 8317 } else { # the other guy succeeded 8318 if ($nosayer eq "install") { 8319 # we had this with 8320 # DMAKI/DateTime-Calendar-Chinese-0.05.tar.gz 8321 # 2007-03 8322 $CPAN::Frontend->mywarn("Warning: Prerequisite ". 8323 "'$need_module => $need_version' ". 8324 "for '$self->{ID}' already installed ". 8325 "but installation looks suspicious. ". 8326 "Skipping another installation attempt, ". 8327 "to prevent looping endlessly.\n" 8328 ); 8329 next NEED; 8330 } 8331 } 8332 } 8333 } 8334 } 8335 my $needed_as = exists $prereq_pm->{requires}{$need_module} ? "r" : "b"; 8336 push @need, [$need_module,$needed_as]; 8337 } 8338 my @unfolded = map { "[".join(",",@$_)."]" } @need; 8339 CPAN->debug("returning from unsat_prereq[@unfolded]") if $CPAN::DEBUG; 8340 @need; 8341 } 8342 8343 #-> sub CPAN::Distribution::read_yaml ; 8344 sub read_yaml { 8345 my($self) = @_; 8346 return $self->{yaml_content} if exists $self->{yaml_content}; 8347 my $build_dir = $self->{build_dir}; 8348 my $yaml = File::Spec->catfile($build_dir,"META.yml"); 8349 $self->debug("yaml[$yaml]") if $CPAN::DEBUG; 8350 return unless -f $yaml; 8351 eval { $self->{yaml_content} = CPAN->_yaml_loadfile($yaml)->[0]; }; 8352 if ($@) { 8353 $CPAN::Frontend->mywarn("Could not read ". 8354 "'$yaml'. Falling back to other ". 8355 "methods to determine prerequisites\n"); 8356 return $self->{yaml_content} = undef; # if we die, then we 8357 # cannot read YAML's own 8358 # META.yml 8359 } 8360 # not "authoritative" 8361 if (not exists $self->{yaml_content}{dynamic_config} 8362 or $self->{yaml_content}{dynamic_config} 8363 ) { 8364 $self->{yaml_content} = undef; 8365 } 8366 $self->debug(sprintf "yaml_content[%s]", $self->{yaml_content} || "UNDEF") 8367 if $CPAN::DEBUG; 8368 return $self->{yaml_content}; 8369 } 8370 8371 #-> sub CPAN::Distribution::prereq_pm ; 8372 sub prereq_pm { 8373 my($self) = @_; 8374 $self->{prereq_pm_detected} ||= 0; 8375 CPAN->debug("ID[$self->{ID}]prereq_pm_detected[$self->{prereq_pm_detected}]") if $CPAN::DEBUG; 8376 return $self->{prereq_pm} if $self->{prereq_pm_detected}; 8377 return unless $self->{writemakefile} # no need to have succeeded 8378 # but we must have run it 8379 || $self->{modulebuild}; 8380 CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]", 8381 $self->{writemakefile}||"", 8382 $self->{modulebuild}||"", 8383 ) if $CPAN::DEBUG; 8384 my($req,$breq); 8385 if (my $yaml = $self->read_yaml) { # often dynamic_config prevents a result here 8386 $req = $yaml->{requires} || {}; 8387 $breq = $yaml->{build_requires} || {}; 8388 undef $req unless ref $req eq "HASH" && %$req; 8389 if ($req) { 8390 if ($yaml->{generated_by} && 8391 $yaml->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) { 8392 my $eummv = do { local $^W = 0; $1+0; }; 8393 if ($eummv < 6.2501) { 8394 # thanks to Slaven for digging that out: MM before 8395 # that could be wrong because it could reflect a 8396 # previous release 8397 undef $req; 8398 } 8399 } 8400 my $areq; 8401 my $do_replace; 8402 while (my($k,$v) = each %{$req||{}}) { 8403 if ($v =~ /\d/) { 8404 $areq->{$k} = $v; 8405 } elsif ($k =~ /[A-Za-z]/ && 8406 $v =~ /[A-Za-z]/ && 8407 $CPAN::META->exists("Module",$v) 8408 ) { 8409 $CPAN::Frontend->mywarn("Suspicious key-value pair in META.yml's ". 8410 "requires hash: $k => $v; I'll take both ". 8411 "key and value as a module name\n"); 8412 $CPAN::Frontend->mysleep(1); 8413 $areq->{$k} = 0; 8414 $areq->{$v} = 0; 8415 $do_replace++; 8416 } 8417 } 8418 $req = $areq if $do_replace; 8419 } 8420 } 8421 unless ($req || $breq) { 8422 my $build_dir = $self->{build_dir} or die "Panic: no build_dir?"; 8423 my $makefile = File::Spec->catfile($build_dir,"Makefile"); 8424 my $fh; 8425 if (-f $makefile 8426 and 8427 $fh = FileHandle->new("<$makefile\0")) { 8428 CPAN->debug("Getting prereq from Makefile") if $CPAN::DEBUG; 8429 local($/) = "\n"; 8430 while (<$fh>) { 8431 last if /MakeMaker post_initialize section/; 8432 my($p) = m{^[\#] 8433 \s+PREREQ_PM\s+=>\s+(.+) 8434 }x; 8435 next unless $p; 8436 # warn "Found prereq expr[$p]"; 8437 8438 # Regexp modified by A.Speer to remember actual version of file 8439 # PREREQ_PM hash key wants, then add to 8440 while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ) { 8441 # In case a prereq is mentioned twice, complain. 8442 if ( defined $req->{$1} ) { 8443 warn "Warning: PREREQ_PM mentions $1 more than once, ". 8444 "last mention wins"; 8445 } 8446 my($m,$n) = ($1,$2); 8447 if ($n =~ /^q\[(.*?)\]$/) { 8448 $n = $1; 8449 } 8450 $req->{$m} = $n; 8451 } 8452 last; 8453 } 8454 } 8455 } 8456 unless ($req || $breq) { 8457 my $build_dir = $self->{build_dir} or die "Panic: no build_dir?"; 8458 my $buildfile = File::Spec->catfile($build_dir,"Build"); 8459 if (-f $buildfile) { 8460 CPAN->debug("Found '$buildfile'") if $CPAN::DEBUG; 8461 my $build_prereqs = File::Spec->catfile($build_dir,"_build","prereqs"); 8462 if (-f $build_prereqs) { 8463 CPAN->debug("Getting prerequisites from '$build_prereqs'") if $CPAN::DEBUG; 8464 my $content = do { local *FH; 8465 open FH, $build_prereqs 8466 or $CPAN::Frontend->mydie("Could not open ". 8467 "'$build_prereqs': $!"); 8468 local $/; 8469 <FH>; 8470 }; 8471 my $bphash = eval $content; 8472 if ($@) { 8473 } else { 8474 $req = $bphash->{requires} || +{}; 8475 $breq = $bphash->{build_requires} || +{}; 8476 } 8477 } 8478 } 8479 } 8480 if (-f "Build.PL" 8481 && ! -f "Makefile.PL" 8482 && ! exists $req->{"Module::Build"} 8483 && ! $CPAN::META->has_inst("Module::Build")) { 8484 $CPAN::Frontend->mywarn(" Warning: CPAN.pm discovered Module::Build as ". 8485 "undeclared prerequisite.\n". 8486 " Adding it now as such.\n" 8487 ); 8488 $CPAN::Frontend->mysleep(5); 8489 $req->{"Module::Build"} = 0; 8490 delete $self->{writemakefile}; 8491 } 8492 if ($req || $breq) { 8493 $self->{prereq_pm_detected}++; 8494 return $self->{prereq_pm} = { requires => $req, build_requires => $breq }; 8495 } 8496 } 8497 8498 #-> sub CPAN::Distribution::test ; 8499 sub test { 8500 my($self) = @_; 8501 if (my $goto = $self->prefs->{goto}) { 8502 return $self->goto($goto); 8503 } 8504 $self->make; 8505 if ($CPAN::Signal) { 8506 delete $self->{force_update}; 8507 return; 8508 } 8509 # warn "XDEBUG: checking for notest: $self->{notest} $self"; 8510 if ($self->{notest}) { 8511 $CPAN::Frontend->myprint("Skipping test because of notest pragma\n"); 8512 return 1; 8513 } 8514 8515 my $make = $self->{modulebuild} ? "Build" : "make"; 8516 8517 local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) 8518 ? $ENV{PERL5LIB} 8519 : ($ENV{PERLLIB} || ""); 8520 8521 $CPAN::META->set_perl5lib; 8522 local $ENV{MAKEFLAGS}; # protect us from outer make calls 8523 8524 $CPAN::Frontend->myprint("Running $make test\n"); 8525 8526 EXCUSE: { 8527 my @e; 8528 if ($self->{make} or $self->{later}) { 8529 # go ahead 8530 } else { 8531 push @e, 8532 "Make had some problems, won't test"; 8533 } 8534 8535 exists $self->{make} and 8536 ( 8537 UNIVERSAL::can($self->{make},"failed") ? 8538 $self->{make}->failed : 8539 $self->{make} =~ /^NO/ 8540 ) and push @e, "Can't test without successful make"; 8541 $self->{badtestcnt} ||= 0; 8542 if ($self->{badtestcnt} > 0) { 8543 require Data::Dumper; 8544 CPAN->debug(sprintf "NOREPEAT[%s]", Data::Dumper::Dumper($self)) if $CPAN::DEBUG; 8545 push @e, "Won't repeat unsuccessful test during this command"; 8546 } 8547 8548 push @e, $self->{later} if $self->{later}; 8549 push @e, $self->{configure_requires_later} if $self->{configure_requires_later}; 8550 8551 if (exists $self->{build_dir}) { 8552 if (exists $self->{make_test}) { 8553 if ( 8554 UNIVERSAL::can($self->{make_test},"failed") ? 8555 $self->{make_test}->failed : 8556 $self->{make_test} =~ /^NO/ 8557 ) { 8558 if ( 8559 UNIVERSAL::can($self->{make_test},"commandid") 8560 && 8561 $self->{make_test}->commandid == $CPAN::CurrentCommandId 8562 ) { 8563 push @e, "Has already been tested within this command"; 8564 } 8565 } else { 8566 push @e, "Has already been tested successfully"; 8567 } 8568 } 8569 } elsif (!@e) { 8570 push @e, "Has no own directory"; 8571 } 8572 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 8573 unless (chdir $self->{build_dir}) { 8574 push @e, "Couldn't chdir to '$self->{build_dir}': $!"; 8575 } 8576 $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e; 8577 } 8578 $self->debug("Changed directory to $self->{build_dir}") 8579 if $CPAN::DEBUG; 8580 8581 if ($^O eq 'MacOS') { 8582 Mac::BuildTools::make_test($self); 8583 return; 8584 } 8585 8586 if ($self->{modulebuild}) { 8587 my $v = CPAN::Shell->expand("Module","Test::Harness")->inst_version; 8588 if (CPAN::Version->vlt($v,2.62)) { 8589 $CPAN::Frontend->mywarn(qq{The version of your Test::Harness is only 8590 '$v', you need at least '2.62'. Please upgrade your Test::Harness.\n}); 8591 $self->{make_test} = CPAN::Distrostatus->new("NO Test::Harness too old"); 8592 return; 8593 } 8594 } 8595 8596 my $system; 8597 my $prefs_test = $self->prefs->{test}; 8598 if (my $commandline 8599 = exists $prefs_test->{commandline} ? $prefs_test->{commandline} : "") { 8600 $system = $commandline; 8601 $ENV{PERL} = CPAN::find_perl; 8602 } elsif ($self->{modulebuild}) { 8603 $system = sprintf "%s test", $self->_build_command(); 8604 } else { 8605 $system = join " ", $self->_make_command(), "test"; 8606 } 8607 my $make_test_arg = $self->make_x_arg("test"); 8608 $system = sprintf("%s%s", 8609 $system, 8610 $make_test_arg ? " $make_test_arg" : "", 8611 ); 8612 my($tests_ok); 8613 my %env; 8614 while (my($k,$v) = each %ENV) { 8615 next unless defined $v; 8616 $env{$k} = $v; 8617 } 8618 local %ENV = %env; 8619 if (my $env = $self->prefs->{test}{env}) { 8620 for my $e (keys %$env) { 8621 $ENV{$e} = $env->{$e}; 8622 } 8623 } 8624 my $expect_model = $self->_prefs_with_expect("test"); 8625 my $want_expect = 0; 8626 if ( $expect_model && @{$expect_model->{talk}} ) { 8627 my $can_expect = $CPAN::META->has_inst("Expect"); 8628 if ($can_expect) { 8629 $want_expect = 1; 8630 } else { 8631 $CPAN::Frontend->mywarn("Expect not installed, falling back to ". 8632 "testing without\n"); 8633 } 8634 } 8635 if ($want_expect) { 8636 if ($self->_should_report('test')) { 8637 $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is currently ". 8638 "not supported when distroprefs specify ". 8639 "an interactive test\n"); 8640 } 8641 $tests_ok = $self->_run_via_expect($system,$expect_model) == 0; 8642 } elsif ( $self->_should_report('test') ) { 8643 $tests_ok = CPAN::Reporter::test($self, $system); 8644 } else { 8645 $tests_ok = system($system) == 0; 8646 } 8647 $self->introduce_myself; 8648 if ( $tests_ok ) { 8649 { 8650 my @prereq; 8651 8652 # local $CPAN::DEBUG = 16; # Distribution 8653 for my $m (keys %{$self->{sponsored_mods}}) { 8654 next unless $self->{sponsored_mods}{$m} > 0; 8655 my $m_obj = CPAN::Shell->expand("Module",$m) or next; 8656 # XXX we need available_version which reflects 8657 # $ENV{PERL5LIB} so that already tested but not yet 8658 # installed modules are counted. 8659 my $available_version = $m_obj->available_version; 8660 my $available_file = $m_obj->available_file; 8661 if ($available_version && 8662 !CPAN::Version->vlt($available_version,$self->{prereq_pm}{$m}) 8663 ) { 8664 CPAN->debug("m[$m] good enough available_version[$available_version]") 8665 if $CPAN::DEBUG; 8666 } elsif ($available_file 8667 && ( 8668 !$self->{prereq_pm}{$m} 8669 || 8670 $self->{prereq_pm}{$m} == 0 8671 ) 8672 ) { 8673 # lex Class::Accessor::Chained::Fast which has no $VERSION 8674 CPAN->debug("m[$m] have available_file[$available_file]") 8675 if $CPAN::DEBUG; 8676 } else { 8677 push @prereq, $m; 8678 } 8679 } 8680 if (@prereq) { 8681 my $cnt = @prereq; 8682 my $which = join ",", @prereq; 8683 my $but = $cnt == 1 ? "one dependency not OK ($which)" : 8684 "$cnt dependencies missing ($which)"; 8685 $CPAN::Frontend->mywarn("Tests succeeded but $but\n"); 8686 $self->{make_test} = CPAN::Distrostatus->new("NO $but"); 8687 $self->store_persistent_state; 8688 return $self->goodbye("[dependencies] -- NA"); 8689 } 8690 } 8691 8692 $CPAN::Frontend->myprint(" $system -- OK\n"); 8693 $self->{make_test} = CPAN::Distrostatus->new("YES"); 8694 $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME}); 8695 # probably impossible to need the next line because badtestcnt 8696 # has a lifespan of one command 8697 delete $self->{badtestcnt}; 8698 } else { 8699 $self->{make_test} = CPAN::Distrostatus->new("NO"); 8700 $self->{badtestcnt}++; 8701 $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); 8702 CPAN::Shell->optprint 8703 ("hint", 8704 sprintf 8705 ("//hint// to see the cpan-testers results for installing this module, try: 8706 reports %s\n", 8707 $self->pretty_id)); 8708 } 8709 $self->store_persistent_state; 8710 } 8711 8712 sub _prefs_with_expect { 8713 my($self,$where) = @_; 8714 return unless my $prefs = $self->prefs; 8715 return unless my $where_prefs = $prefs->{$where}; 8716 if ($where_prefs->{expect}) { 8717 return { 8718 mode => "deterministic", 8719 timeout => 15, 8720 talk => $where_prefs->{expect}, 8721 }; 8722 } elsif ($where_prefs->{"eexpect"}) { 8723 return $where_prefs->{"eexpect"}; 8724 } 8725 return; 8726 } 8727 8728 #-> sub CPAN::Distribution::clean ; 8729 sub clean { 8730 my($self) = @_; 8731 my $make = $self->{modulebuild} ? "Build" : "make"; 8732 $CPAN::Frontend->myprint("Running $make clean\n"); 8733 unless (exists $self->{archived}) { 8734 $CPAN::Frontend->mywarn("Distribution seems to have never been unzipped". 8735 "/untarred, nothing done\n"); 8736 return 1; 8737 } 8738 unless (exists $self->{build_dir}) { 8739 $CPAN::Frontend->mywarn("Distribution has no own directory, nothing to do.\n"); 8740 return 1; 8741 } 8742 if (exists $self->{writemakefile} 8743 and $self->{writemakefile}->failed 8744 ) { 8745 $CPAN::Frontend->mywarn("No Makefile, don't know how to 'make clean'\n"); 8746 return 1; 8747 } 8748 EXCUSE: { 8749 my @e; 8750 exists $self->{make_clean} and $self->{make_clean} eq "YES" and 8751 push @e, "make clean already called once"; 8752 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 8753 } 8754 chdir $self->{build_dir} or 8755 Carp::confess("Couldn't chdir to $self->{build_dir}: $!"); 8756 $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG; 8757 8758 if ($^O eq 'MacOS') { 8759 Mac::BuildTools::make_clean($self); 8760 return; 8761 } 8762 8763 my $system; 8764 if ($self->{modulebuild}) { 8765 unless (-f "Build") { 8766 my $cwd = CPAN::anycwd(); 8767 $CPAN::Frontend->mywarn("Alert: no Build file available for 'clean $self->{id}". 8768 " in cwd[$cwd]. Danger, Will Robinson!"); 8769 $CPAN::Frontend->mysleep(5); 8770 } 8771 $system = sprintf "%s clean", $self->_build_command(); 8772 } else { 8773 $system = join " ", $self->_make_command(), "clean"; 8774 } 8775 my $system_ok = system($system) == 0; 8776 $self->introduce_myself; 8777 if ( $system_ok ) { 8778 $CPAN::Frontend->myprint(" $system -- OK\n"); 8779 8780 # $self->force; 8781 8782 # Jost Krieger pointed out that this "force" was wrong because 8783 # it has the effect that the next "install" on this distribution 8784 # will untar everything again. Instead we should bring the 8785 # object's state back to where it is after untarring. 8786 8787 for my $k (qw( 8788 force_update 8789 install 8790 writemakefile 8791 make 8792 make_test 8793 )) { 8794 delete $self->{$k}; 8795 } 8796 $self->{make_clean} = CPAN::Distrostatus->new("YES"); 8797 8798 } else { 8799 # Hmmm, what to do if make clean failed? 8800 8801 $self->{make_clean} = CPAN::Distrostatus->new("NO"); 8802 $CPAN::Frontend->mywarn(qq{ $system -- NOT OK\n}); 8803 8804 # 2006-02-27: seems silly to me to force a make now 8805 # $self->force("make"); # so that this directory won't be used again 8806 8807 } 8808 $self->store_persistent_state; 8809 } 8810 8811 #-> sub CPAN::Distribution::goto ; 8812 sub goto { 8813 my($self,$goto) = @_; 8814 $goto = $self->normalize($goto); 8815 my $why = sprintf( 8816 "Goto '$goto' via prefs file '%s' doc %d", 8817 $self->{prefs_file}, 8818 $self->{prefs_file_doc}, 8819 ); 8820 $self->{unwrapped} = CPAN::Distrostatus->new("NO $why"); 8821 # 2007-07-16 akoenig : Better than NA would be if we could inherit 8822 # the status of the $goto distro but given the exceptional nature 8823 # of 'goto' I feel reluctant to implement it 8824 my $goodbye_message = "[goto] -- NA $why"; 8825 $self->goodbye($goodbye_message); 8826 8827 # inject into the queue 8828 8829 CPAN::Queue->delete($self->id); 8830 CPAN::Queue->jumpqueue({qmod => $goto, reqtype => $self->{reqtype}}); 8831 8832 # and run where we left off 8833 8834 my($method) = (caller(1))[3]; 8835 CPAN->instance("CPAN::Distribution",$goto)->$method(); 8836 CPAN::Queue->delete_first($goto); 8837 } 8838 8839 #-> sub CPAN::Distribution::install ; 8840 sub install { 8841 my($self) = @_; 8842 if (my $goto = $self->prefs->{goto}) { 8843 return $self->goto($goto); 8844 } 8845 # $DB::single=1; 8846 unless ($self->{badtestcnt}) { 8847 $self->test; 8848 } 8849 if ($CPAN::Signal) { 8850 delete $self->{force_update}; 8851 return; 8852 } 8853 my $make = $self->{modulebuild} ? "Build" : "make"; 8854 $CPAN::Frontend->myprint("Running $make install\n"); 8855 EXCUSE: { 8856 my @e; 8857 if ($self->{make} or $self->{later}) { 8858 # go ahead 8859 } else { 8860 push @e, 8861 "Make had some problems, won't install"; 8862 } 8863 8864 exists $self->{make} and 8865 ( 8866 UNIVERSAL::can($self->{make},"failed") ? 8867 $self->{make}->failed : 8868 $self->{make} =~ /^NO/ 8869 ) and 8870 push @e, "Make had returned bad status, install seems impossible"; 8871 8872 if (exists $self->{build_dir}) { 8873 } elsif (!@e) { 8874 push @e, "Has no own directory"; 8875 } 8876 8877 if (exists $self->{make_test} and 8878 ( 8879 UNIVERSAL::can($self->{make_test},"failed") ? 8880 $self->{make_test}->failed : 8881 $self->{make_test} =~ /^NO/ 8882 )) { 8883 if ($self->{force_update}) { 8884 $self->{make_test}->text("FAILED but failure ignored because ". 8885 "'force' in effect"); 8886 } else { 8887 push @e, "make test had returned bad status, ". 8888 "won't install without force" 8889 } 8890 } 8891 if (exists $self->{install}) { 8892 if (UNIVERSAL::can($self->{install},"text") ? 8893 $self->{install}->text eq "YES" : 8894 $self->{install} =~ /^YES/ 8895 ) { 8896 $CPAN::Frontend->myprint(" Already done\n"); 8897 $CPAN::META->is_installed($self->{build_dir}); 8898 return 1; 8899 } else { 8900 # comment in Todo on 2006-02-11; maybe retry? 8901 push @e, "Already tried without success"; 8902 } 8903 } 8904 8905 push @e, $self->{later} if $self->{later}; 8906 push @e, $self->{configure_requires_later} if $self->{configure_requires_later}; 8907 8908 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; 8909 unless (chdir $self->{build_dir}) { 8910 push @e, "Couldn't chdir to '$self->{build_dir}': $!"; 8911 } 8912 $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e; 8913 } 8914 $self->debug("Changed directory to $self->{build_dir}") 8915 if $CPAN::DEBUG; 8916 8917 if ($^O eq 'MacOS') { 8918 Mac::BuildTools::make_install($self); 8919 return; 8920 } 8921 8922 my $system; 8923 if (my $commandline = $self->prefs->{install}{commandline}) { 8924 $system = $commandline; 8925 $ENV{PERL} = CPAN::find_perl; 8926 } elsif ($self->{modulebuild}) { 8927 my($mbuild_install_build_command) = 8928 exists $CPAN::HandleConfig::keys{mbuild_install_build_command} && 8929 $CPAN::Config->{mbuild_install_build_command} ? 8930 $CPAN::Config->{mbuild_install_build_command} : 8931 $self->_build_command(); 8932 $system = sprintf("%s install %s", 8933 $mbuild_install_build_command, 8934 $CPAN::Config->{mbuild_install_arg}, 8935 ); 8936 } else { 8937 my($make_install_make_command) = 8938 CPAN::HandleConfig->prefs_lookup($self, 8939 q{make_install_make_command}) 8940 || $self->_make_command(); 8941 $system = sprintf("%s install %s", 8942 $make_install_make_command, 8943 $CPAN::Config->{make_install_arg}, 8944 ); 8945 } 8946 8947 my($stderr) = $^O eq "MSWin32" ? "" : " 2>&1 "; 8948 my $brip = CPAN::HandleConfig->prefs_lookup($self, 8949 q{build_requires_install_policy}); 8950 $brip ||="ask/yes"; 8951 my $id = $self->id; 8952 my $reqtype = $self->{reqtype} ||= "c"; # in doubt it was a command 8953 my $want_install = "yes"; 8954 if ($reqtype eq "b") { 8955 if ($brip eq "no") { 8956 $want_install = "no"; 8957 } elsif ($brip =~ m|^ask/(.+)|) { 8958 my $default = $1; 8959 $default = "yes" unless $default =~ /^(y|n)/i; 8960 $want_install = 8961 CPAN::Shell::colorable_makemaker_prompt 8962 ("$id is just needed temporarily during building or testing. ". 8963 "Do you want to install it permanently? (Y/n)", 8964 $default); 8965 } 8966 } 8967 unless ($want_install =~ /^y/i) { 8968 my $is_only = "is only 'build_requires'"; 8969 $CPAN::Frontend->mywarn("Not installing because $is_only\n"); 8970 $self->{install} = CPAN::Distrostatus->new("NO -- $is_only"); 8971 delete $self->{force_update}; 8972 return; 8973 } 8974 local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) 8975 ? $ENV{PERL5LIB} 8976 : ($ENV{PERLLIB} || ""); 8977 8978 $CPAN::META->set_perl5lib; 8979 my($pipe) = FileHandle->new("$system $stderr |"); 8980 my($makeout) = ""; 8981 while (<$pipe>) { 8982 print $_; # intentionally NOT use Frontend->myprint because it 8983 # looks irritating when we markup in color what we 8984 # just pass through from an external program 8985 $makeout .= $_; 8986 } 8987 $pipe->close; 8988 my $close_ok = $? == 0; 8989 $self->introduce_myself; 8990 if ( $close_ok ) { 8991 $CPAN::Frontend->myprint(" $system -- OK\n"); 8992 $CPAN::META->is_installed($self->{build_dir}); 8993 $self->{install} = CPAN::Distrostatus->new("YES"); 8994 } else { 8995 $self->{install} = CPAN::Distrostatus->new("NO"); 8996 $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); 8997 my $mimc = 8998 CPAN::HandleConfig->prefs_lookup($self, 8999 q{make_install_make_command}); 9000 if ( 9001 $makeout =~ /permission/s 9002 && $> > 0 9003 && ( 9004 ! $mimc 9005 || $mimc eq (CPAN::HandleConfig->prefs_lookup($self, 9006 q{make})) 9007 ) 9008 ) { 9009 $CPAN::Frontend->myprint( 9010 qq{----\n}. 9011 qq{ You may have to su }. 9012 qq{to root to install the package\n}. 9013 qq{ (Or you may want to run something like\n}. 9014 qq{ o conf make_install_make_command 'sudo make'\n}. 9015 qq{ to raise your permissions.} 9016 ); 9017 } 9018 } 9019 delete $self->{force_update}; 9020 # $DB::single = 1; 9021 $self->store_persistent_state; 9022 } 9023 9024 sub introduce_myself { 9025 my($self) = @_; 9026 $CPAN::Frontend->myprint(sprintf(" %s\n",$self->pretty_id)); 9027 } 9028 9029 #-> sub CPAN::Distribution::dir ; 9030 sub dir { 9031 shift->{build_dir}; 9032 } 9033 9034 #-> sub CPAN::Distribution::perldoc ; 9035 sub perldoc { 9036 my($self) = @_; 9037 9038 my($dist) = $self->id; 9039 my $package = $self->called_for; 9040 9041 $self->_display_url( $CPAN::Defaultdocs . $package ); 9042 } 9043 9044 #-> sub CPAN::Distribution::_check_binary ; 9045 sub _check_binary { 9046 my ($dist,$shell,$binary) = @_; 9047 my ($pid,$out); 9048 9049 $CPAN::Frontend->myprint(qq{ + _check_binary($binary)\n}) 9050 if $CPAN::DEBUG; 9051 9052 if ($CPAN::META->has_inst("File::Which")) { 9053 return File::Which::which($binary); 9054 } else { 9055 local *README; 9056 $pid = open README, "which $binary|" 9057 or $CPAN::Frontend->mywarn(qq{Could not fork 'which $binary': $!\n}); 9058 return unless $pid; 9059 while (<README>) { 9060 $out .= $_; 9061 } 9062 close README 9063 or $CPAN::Frontend->mywarn("Could not run 'which $binary': $!\n") 9064 and return; 9065 } 9066 9067 $CPAN::Frontend->myprint(qq{ + $out \n}) 9068 if $CPAN::DEBUG && $out; 9069 9070 return $out; 9071 } 9072 9073 #-> sub CPAN::Distribution::_display_url ; 9074 sub _display_url { 9075 my($self,$url) = @_; 9076 my($res,$saved_file,$pid,$out); 9077 9078 $CPAN::Frontend->myprint(qq{ + _display_url($url)\n}) 9079 if $CPAN::DEBUG; 9080 9081 # should we define it in the config instead? 9082 my $html_converter = "html2text.pl"; 9083 9084 my $web_browser = $CPAN::Config->{'lynx'} || undef; 9085 my $web_browser_out = $web_browser 9086 ? CPAN::Distribution->_check_binary($self,$web_browser) 9087 : undef; 9088 9089 if ($web_browser_out) { 9090 # web browser found, run the action 9091 my $browser = CPAN::HandleConfig->safe_quote($CPAN::Config->{'lynx'}); 9092 $CPAN::Frontend->myprint(qq{system[$browser $url]}) 9093 if $CPAN::DEBUG; 9094 $CPAN::Frontend->myprint(qq{ 9095 Displaying URL 9096 $url 9097 with browser $browser 9098 }); 9099 $CPAN::Frontend->mysleep(1); 9100 system("$browser $url"); 9101 if ($saved_file) { 1 while unlink($saved_file) } 9102 } else { 9103 # web browser not found, let's try text only 9104 my $html_converter_out = 9105 CPAN::Distribution->_check_binary($self,$html_converter); 9106 $html_converter_out = CPAN::HandleConfig->safe_quote($html_converter_out); 9107 9108 if ($html_converter_out ) { 9109 # html2text found, run it 9110 $saved_file = CPAN::Distribution->_getsave_url( $self, $url ); 9111 $CPAN::Frontend->mydie(qq{ERROR: problems while getting $url\n}) 9112 unless defined($saved_file); 9113 9114 local *README; 9115 $pid = open README, "$html_converter $saved_file |" 9116 or $CPAN::Frontend->mydie(qq{ 9117 Could not fork '$html_converter $saved_file': $!}); 9118 my($fh,$filename); 9119 if ($CPAN::META->has_usable("File::Temp")) { 9120 $fh = File::Temp->new( 9121 dir => File::Spec->tmpdir, 9122 template => 'cpan_htmlconvert_XXXX', 9123 suffix => '.txt', 9124 unlink => 0, 9125 ); 9126 $filename = $fh->filename; 9127 } else { 9128 $filename = "cpan_htmlconvert_$$.txt"; 9129 $fh = FileHandle->new(); 9130 open $fh, ">$filename" or die; 9131 } 9132 while (<README>) { 9133 $fh->print($_); 9134 } 9135 close README or 9136 $CPAN::Frontend->mydie(qq{Could not run '$html_converter $saved_file': $!}); 9137 my $tmpin = $fh->filename; 9138 $CPAN::Frontend->myprint(sprintf(qq{ 9139 Run '%s %s' and 9140 saved output to %s\n}, 9141 $html_converter, 9142 $saved_file, 9143 $tmpin, 9144 )) if $CPAN::DEBUG; 9145 close $fh; 9146 local *FH; 9147 open FH, $tmpin 9148 or $CPAN::Frontend->mydie(qq{Could not open "$tmpin": $!}); 9149 my $fh_pager = FileHandle->new; 9150 local($SIG{PIPE}) = "IGNORE"; 9151 my $pager = $CPAN::Config->{'pager'} || "cat"; 9152 $fh_pager->open("|$pager") 9153 or $CPAN::Frontend->mydie(qq{ 9154 Could not open pager '$pager': $!}); 9155 $CPAN::Frontend->myprint(qq{ 9156 Displaying URL 9157 $url 9158 with pager "$pager" 9159 }); 9160 $CPAN::Frontend->mysleep(1); 9161 $fh_pager->print(<FH>); 9162 $fh_pager->close; 9163 } else { 9164 # coldn't find the web browser or html converter 9165 $CPAN::Frontend->myprint(qq{ 9166 You need to install lynx or $html_converter to use this feature.}); 9167 } 9168 } 9169 } 9170 9171 #-> sub CPAN::Distribution::_getsave_url ; 9172 sub _getsave_url { 9173 my($dist, $shell, $url) = @_; 9174 9175 $CPAN::Frontend->myprint(qq{ + _getsave_url($url)\n}) 9176 if $CPAN::DEBUG; 9177 9178 my($fh,$filename); 9179 if ($CPAN::META->has_usable("File::Temp")) { 9180 $fh = File::Temp->new( 9181 dir => File::Spec->tmpdir, 9182 template => "cpan_getsave_url_XXXX", 9183 suffix => ".html", 9184 unlink => 0, 9185 ); 9186 $filename = $fh->filename; 9187 } else { 9188 $fh = FileHandle->new; 9189 $filename = "cpan_getsave_url_$$.html"; 9190 } 9191 my $tmpin = $filename; 9192 if ($CPAN::META->has_usable('LWP')) { 9193 $CPAN::Frontend->myprint("Fetching with LWP: 9194 $url 9195 "); 9196 my $Ua; 9197 CPAN::LWP::UserAgent->config; 9198 eval { $Ua = CPAN::LWP::UserAgent->new; }; 9199 if ($@) { 9200 $CPAN::Frontend->mywarn("ERROR: CPAN::LWP::UserAgent->new dies with $@\n"); 9201 return; 9202 } else { 9203 my($var); 9204 $Ua->proxy('http', $var) 9205 if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy}; 9206 $Ua->no_proxy($var) 9207 if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy}; 9208 } 9209 9210 my $req = HTTP::Request->new(GET => $url); 9211 $req->header('Accept' => 'text/html'); 9212 my $res = $Ua->request($req); 9213 if ($res->is_success) { 9214 $CPAN::Frontend->myprint(" + request successful.\n") 9215 if $CPAN::DEBUG; 9216 print $fh $res->content; 9217 close $fh; 9218 $CPAN::Frontend->myprint(qq{ + saved content to $tmpin \n}) 9219 if $CPAN::DEBUG; 9220 return $tmpin; 9221 } else { 9222 $CPAN::Frontend->myprint(sprintf( 9223 "LWP failed with code[%s], message[%s]\n", 9224 $res->code, 9225 $res->message, 9226 )); 9227 return; 9228 } 9229 } else { 9230 $CPAN::Frontend->mywarn(" LWP not available\n"); 9231 return; 9232 } 9233 } 9234 9235 #-> sub CPAN::Distribution::_build_command 9236 sub _build_command { 9237 my($self) = @_; 9238 if ($^O eq "MSWin32") { # special code needed at least up to 9239 # Module::Build 0.2611 and 0.2706; a fix 9240 # in M:B has been promised 2006-01-30 9241 my($perl) = $self->perl or $CPAN::Frontend->mydie("Couldn't find executable perl\n"); 9242 return "$perl ./Build"; 9243 } 9244 return "./Build"; 9245 } 9246 9247 #-> sub CPAN::Distribution::_should_report 9248 sub _should_report { 9249 my($self, $phase) = @_; 9250 die "_should_report() requires a 'phase' argument" 9251 if ! defined $phase; 9252 9253 # configured 9254 my $test_report = CPAN::HandleConfig->prefs_lookup($self, 9255 q{test_report}); 9256 return unless $test_report; 9257 9258 # don't repeat if we cached a result 9259 return $self->{should_report} 9260 if exists $self->{should_report}; 9261 9262 # available 9263 if ( ! $CPAN::META->has_inst("CPAN::Reporter")) { 9264 $CPAN::Frontend->mywarn( 9265 "CPAN::Reporter not installed. No reports will be sent.\n" 9266 ); 9267 return $self->{should_report} = 0; 9268 } 9269 9270 # capable 9271 my $crv = CPAN::Reporter->VERSION; 9272 if ( CPAN::Version->vlt( $crv, 0.99 ) ) { 9273 # don't cache $self->{should_report} -- need to check each phase 9274 if ( $phase eq 'test' ) { 9275 return 1; 9276 } 9277 else { 9278 $CPAN::Frontend->mywarn( 9279 "Reporting on the '$phase' phase requires CPAN::Reporter 0.99, but \n" . 9280 "you only have version $crv\. Only 'test' phase reports will be sent.\n" 9281 ); 9282 return; 9283 } 9284 } 9285 9286 # appropriate 9287 if ($self->is_dot_dist) { 9288 $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ". 9289 "for local directories\n"); 9290 return $self->{should_report} = 0; 9291 } 9292 if ($self->prefs->{patches} 9293 && 9294 @{$self->prefs->{patches}} 9295 && 9296 $self->{patched} 9297 ) { 9298 $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ". 9299 "when the source has been patched\n"); 9300 return $self->{should_report} = 0; 9301 } 9302 9303 # proceed and cache success 9304 return $self->{should_report} = 1; 9305 } 9306 9307 #-> sub CPAN::Distribution::reports 9308 sub reports { 9309 my($self) = @_; 9310 my $pathname = $self->id; 9311 $CPAN::Frontend->myprint("Distribution: $pathname\n"); 9312 9313 unless ($CPAN::META->has_inst("CPAN::DistnameInfo")) { 9314 $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue"); 9315 } 9316 unless ($CPAN::META->has_usable("LWP")) { 9317 $CPAN::Frontend->mydie("LWP not installed; cannot continue"); 9318 } 9319 unless ($CPAN::META->has_usable("File::Temp")) { 9320 $CPAN::Frontend->mydie("File::Temp not installed; cannot continue"); 9321 } 9322 9323 my $d = CPAN::DistnameInfo->new($pathname); 9324 9325 my $dist = $d->dist; # "CPAN-DistnameInfo" 9326 my $version = $d->version; # "0.02" 9327 my $maturity = $d->maturity; # "released" 9328 my $filename = $d->filename; # "CPAN-DistnameInfo-0.02.tar.gz" 9329 my $cpanid = $d->cpanid; # "GBARR" 9330 my $distvname = $d->distvname; # "CPAN-DistnameInfo-0.02" 9331 9332 my $url = sprintf "http://cpantesters.perl.org/show/%s.yaml", $dist; 9333 9334 CPAN::LWP::UserAgent->config; 9335 my $Ua; 9336 eval { $Ua = CPAN::LWP::UserAgent->new; }; 9337 if ($@) { 9338 $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n"); 9339 } 9340 $CPAN::Frontend->myprint("Fetching '$url'..."); 9341 my $resp = $Ua->get($url); 9342 unless ($resp->is_success) { 9343 $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code); 9344 } 9345 $CPAN::Frontend->myprint("DONE\n\n"); 9346 my $yaml = $resp->content; 9347 # was fuer ein Umweg! 9348 my $fh = File::Temp->new( 9349 dir => File::Spec->tmpdir, 9350 template => 'cpan_reports_XXXX', 9351 suffix => '.yaml', 9352 unlink => 0, 9353 ); 9354 my $tfilename = $fh->filename; 9355 print $fh $yaml; 9356 close $fh or $CPAN::Frontend->mydie("Could not close '$tfilename': $!"); 9357 my $unserialized = CPAN->_yaml_loadfile($tfilename)->[0]; 9358 unlink $tfilename or $CPAN::Frontend->mydie("Could not unlink '$tfilename': $!"); 9359 my %other_versions; 9360 my $this_version_seen; 9361 for my $rep (@$unserialized) { 9362 my $rversion = $rep->{version}; 9363 if ($rversion eq $version) { 9364 unless ($this_version_seen++) { 9365 $CPAN::Frontend->myprint ("$rep->{version}:\n"); 9366 } 9367 $CPAN::Frontend->myprint 9368 (sprintf("%1s%1s%-4s %s on %s %s (%s)\n", 9369 $rep->{archname} eq $Config::Config{archname}?"*":"", 9370 $rep->{action}eq"PASS"?"+":$rep->{action}eq"FAIL"?"-":"", 9371 $rep->{action}, 9372 $rep->{perl}, 9373 ucfirst $rep->{osname}, 9374 $rep->{osvers}, 9375 $rep->{archname}, 9376 )); 9377 } else { 9378 $other_versions{$rep->{version}}++; 9379 } 9380 } 9381 unless ($this_version_seen) { 9382 $CPAN::Frontend->myprint("No reports found for version '$version' 9383 Reports for other versions:\n"); 9384 for my $v (sort keys %other_versions) { 9385 $CPAN::Frontend->myprint(" $v\: $other_versions{$v}\n"); 9386 } 9387 } 9388 $url =~ s/\.yaml/.html/; 9389 $CPAN::Frontend->myprint("See $url for details\n"); 9390 } 9391 9392 package CPAN::Bundle; 9393 use strict; 9394 9395 sub look { 9396 my $self = shift; 9397 $CPAN::Frontend->myprint($self->as_string); 9398 } 9399 9400 #-> CPAN::Bundle::undelay 9401 sub undelay { 9402 my $self = shift; 9403 delete $self->{later}; 9404 for my $c ( $self->contains ) { 9405 my $obj = CPAN::Shell->expandany($c) or next; 9406 $obj->undelay; 9407 } 9408 } 9409 9410 # mark as dirty/clean 9411 #-> sub CPAN::Bundle::color_cmd_tmps ; 9412 sub color_cmd_tmps { 9413 my($self) = shift; 9414 my($depth) = shift || 0; 9415 my($color) = shift || 0; 9416 my($ancestors) = shift || []; 9417 # a module needs to recurse to its cpan_file, a distribution needs 9418 # to recurse into its prereq_pms, a bundle needs to recurse into its modules 9419 9420 return if exists $self->{incommandcolor} 9421 && $color==1 9422 && $self->{incommandcolor}==$color; 9423 if ($depth>=$CPAN::MAX_RECURSION) { 9424 die(CPAN::Exception::RecursiveDependency->new($ancestors)); 9425 } 9426 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 9427 9428 for my $c ( $self->contains ) { 9429 my $obj = CPAN::Shell->expandany($c) or next; 9430 CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG; 9431 $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 9432 } 9433 # never reached code? 9434 #if ($color==0) { 9435 #delete $self->{badtestcnt}; 9436 #} 9437 $self->{incommandcolor} = $color; 9438 } 9439 9440 #-> sub CPAN::Bundle::as_string ; 9441 sub as_string { 9442 my($self) = @_; 9443 $self->contains; 9444 # following line must be "=", not "||=" because we have a moving target 9445 $self->{INST_VERSION} = $self->inst_version; 9446 return $self->SUPER::as_string; 9447 } 9448 9449 #-> sub CPAN::Bundle::contains ; 9450 sub contains { 9451 my($self) = @_; 9452 my($inst_file) = $self->inst_file || ""; 9453 my($id) = $self->id; 9454 $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG; 9455 if ($inst_file && CPAN::Version->vlt($self->inst_version,$self->cpan_version)) { 9456 undef $inst_file; 9457 } 9458 unless ($inst_file) { 9459 # Try to get at it in the cpan directory 9460 $self->debug("no inst_file") if $CPAN::DEBUG; 9461 my $cpan_file; 9462 $CPAN::Frontend->mydie("I don't know a bundle with ID $id\n") unless 9463 $cpan_file = $self->cpan_file; 9464 if ($cpan_file eq "N/A") { 9465 $CPAN::Frontend->mydie("Bundle $id not found on disk and not on CPAN. 9466 Maybe stale symlink? Maybe removed during session? Giving up.\n"); 9467 } 9468 my $dist = $CPAN::META->instance('CPAN::Distribution', 9469 $self->cpan_file); 9470 $self->debug("before get id[$dist->{ID}]") if $CPAN::DEBUG; 9471 $dist->get; 9472 $self->debug("after get id[$dist->{ID}]") if $CPAN::DEBUG; 9473 my($todir) = $CPAN::Config->{'cpan_home'}; 9474 my(@me,$from,$to,$me); 9475 @me = split /::/, $self->id; 9476 $me[-1] .= ".pm"; 9477 $me = File::Spec->catfile(@me); 9478 $from = $self->find_bundle_file($dist->{build_dir},join('/',@me)); 9479 $to = File::Spec->catfile($todir,$me); 9480 File::Path::mkpath(File::Basename::dirname($to)); 9481 File::Copy::copy($from, $to) 9482 or Carp::confess("Couldn't copy $from to $to: $!"); 9483 $inst_file = $to; 9484 } 9485 my @result; 9486 my $fh = FileHandle->new; 9487 local $/ = "\n"; 9488 open($fh,$inst_file) or die "Could not open '$inst_file': $!"; 9489 my $in_cont = 0; 9490 $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG; 9491 while (<$fh>) { 9492 $in_cont = m/^=(?!head1\s+CONTENTS)/ ? 0 : 9493 m/^=head1\s+CONTENTS/ ? 1 : $in_cont; 9494 next unless $in_cont; 9495 next if /^=/; 9496 s/\#.*//; 9497 next if /^\s+$/; 9498 chomp; 9499 push @result, (split " ", $_, 2)[0]; 9500 } 9501 close $fh; 9502 delete $self->{STATUS}; 9503 $self->{CONTAINS} = \@result; 9504 $self->debug("CONTAINS[@result]") if $CPAN::DEBUG; 9505 unless (@result) { 9506 $CPAN::Frontend->mywarn(qq{ 9507 The bundle file "$inst_file" may be a broken 9508 bundlefile. It seems not to contain any bundle definition. 9509 Please check the file and if it is bogus, please delete it. 9510 Sorry for the inconvenience. 9511 }); 9512 } 9513 @result; 9514 } 9515 9516 #-> sub CPAN::Bundle::find_bundle_file 9517 # $where is in local format, $what is in unix format 9518 sub find_bundle_file { 9519 my($self,$where,$what) = @_; 9520 $self->debug("where[$where]what[$what]") if $CPAN::DEBUG; 9521 ### The following two lines let CPAN.pm become Bundle/CPAN.pm :-( 9522 ### my $bu = File::Spec->catfile($where,$what); 9523 ### return $bu if -f $bu; 9524 my $manifest = File::Spec->catfile($where,"MANIFEST"); 9525 unless (-f $manifest) { 9526 require ExtUtils::Manifest; 9527 my $cwd = CPAN::anycwd(); 9528 $self->safe_chdir($where); 9529 ExtUtils::Manifest::mkmanifest(); 9530 $self->safe_chdir($cwd); 9531 } 9532 my $fh = FileHandle->new($manifest) 9533 or Carp::croak("Couldn't open $manifest: $!"); 9534 local($/) = "\n"; 9535 my $bundle_filename = $what; 9536 $bundle_filename =~ s|Bundle.*/||; 9537 my $bundle_unixpath; 9538 while (<$fh>) { 9539 next if /^\s*\#/; 9540 my($file) = /(\S+)/; 9541 if ($file =~ m|\Q$what\E$|) { 9542 $bundle_unixpath = $file; 9543 # return File::Spec->catfile($where,$bundle_unixpath); # bad 9544 last; 9545 } 9546 # retry if she managed to have no Bundle directory 9547 $bundle_unixpath = $file if $file =~ m|\Q$bundle_filename\E$|; 9548 } 9549 return File::Spec->catfile($where, split /\//, $bundle_unixpath) 9550 if $bundle_unixpath; 9551 Carp::croak("Couldn't find a Bundle file in $where"); 9552 } 9553 9554 # needs to work quite differently from Module::inst_file because of 9555 # cpan_home/Bundle/ directory and the possibility that we have 9556 # shadowing effect. As it makes no sense to take the first in @INC for 9557 # Bundles, we parse them all for $VERSION and take the newest. 9558 9559 #-> sub CPAN::Bundle::inst_file ; 9560 sub inst_file { 9561 my($self) = @_; 9562 my($inst_file); 9563 my(@me); 9564 @me = split /::/, $self->id; 9565 $me[-1] .= ".pm"; 9566 my($incdir,$bestv); 9567 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { 9568 my $bfile = File::Spec->catfile($incdir, @me); 9569 CPAN->debug("bfile[$bfile]") if $CPAN::DEBUG; 9570 next unless -f $bfile; 9571 my $foundv = MM->parse_version($bfile); 9572 if (!$bestv || CPAN::Version->vgt($foundv,$bestv)) { 9573 $self->{INST_FILE} = $bfile; 9574 $self->{INST_VERSION} = $bestv = $foundv; 9575 } 9576 } 9577 $self->{INST_FILE}; 9578 } 9579 9580 #-> sub CPAN::Bundle::inst_version ; 9581 sub inst_version { 9582 my($self) = @_; 9583 $self->inst_file; # finds INST_VERSION as side effect 9584 $self->{INST_VERSION}; 9585 } 9586 9587 #-> sub CPAN::Bundle::rematein ; 9588 sub rematein { 9589 my($self,$meth) = @_; 9590 $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG; 9591 my($id) = $self->id; 9592 Carp::croak "Can't $meth $id, don't have an associated bundle file. :-(\n" 9593 unless $self->inst_file || $self->cpan_file; 9594 my($s,%fail); 9595 for $s ($self->contains) { 9596 my($type) = $s =~ m|/| ? 'CPAN::Distribution' : 9597 $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module'; 9598 if ($type eq 'CPAN::Distribution') { 9599 $CPAN::Frontend->mywarn(qq{ 9600 The Bundle }.$self->id.qq{ contains 9601 explicitly a file '$s'. 9602 Going to $meth that. 9603 }); 9604 $CPAN::Frontend->mysleep(5); 9605 } 9606 # possibly noisy action: 9607 $self->debug("type[$type] s[$s]") if $CPAN::DEBUG; 9608 my $obj = $CPAN::META->instance($type,$s); 9609 $obj->{reqtype} = $self->{reqtype}; 9610 $obj->$meth(); 9611 } 9612 } 9613 9614 # If a bundle contains another that contains an xs_file we have here, 9615 # we just don't bother I suppose 9616 #-> sub CPAN::Bundle::xs_file 9617 sub xs_file { 9618 return 0; 9619 } 9620 9621 #-> sub CPAN::Bundle::force ; 9622 sub fforce { shift->rematein('fforce',@_); } 9623 #-> sub CPAN::Bundle::force ; 9624 sub force { shift->rematein('force',@_); } 9625 #-> sub CPAN::Bundle::notest ; 9626 sub notest { shift->rematein('notest',@_); } 9627 #-> sub CPAN::Bundle::get ; 9628 sub get { shift->rematein('get',@_); } 9629 #-> sub CPAN::Bundle::make ; 9630 sub make { shift->rematein('make',@_); } 9631 #-> sub CPAN::Bundle::test ; 9632 sub test { 9633 my $self = shift; 9634 # $self->{badtestcnt} ||= 0; 9635 $self->rematein('test',@_); 9636 } 9637 #-> sub CPAN::Bundle::install ; 9638 sub install { 9639 my $self = shift; 9640 $self->rematein('install',@_); 9641 } 9642 #-> sub CPAN::Bundle::clean ; 9643 sub clean { shift->rematein('clean',@_); } 9644 9645 #-> sub CPAN::Bundle::uptodate ; 9646 sub uptodate { 9647 my($self) = @_; 9648 return 0 unless $self->SUPER::uptodate; # we mut have the current Bundle def 9649 my $c; 9650 foreach $c ($self->contains) { 9651 my $obj = CPAN::Shell->expandany($c); 9652 return 0 unless $obj->uptodate; 9653 } 9654 return 1; 9655 } 9656 9657 #-> sub CPAN::Bundle::readme ; 9658 sub readme { 9659 my($self) = @_; 9660 my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{ 9661 No File found for bundle } . $self->id . qq{\n}), return; 9662 $self->debug("self[$self] file[$file]") if $CPAN::DEBUG; 9663 $CPAN::META->instance('CPAN::Distribution',$file)->readme; 9664 } 9665 9666 package CPAN::Module; 9667 use strict; 9668 9669 # Accessors 9670 #-> sub CPAN::Module::userid 9671 sub userid { 9672 my $self = shift; 9673 my $ro = $self->ro; 9674 return unless $ro; 9675 return $ro->{userid} || $ro->{CPAN_USERID}; 9676 } 9677 #-> sub CPAN::Module::description 9678 sub description { 9679 my $self = shift; 9680 my $ro = $self->ro or return ""; 9681 $ro->{description} 9682 } 9683 9684 #-> sub CPAN::Module::distribution 9685 sub distribution { 9686 my($self) = @_; 9687 CPAN::Shell->expand("Distribution",$self->cpan_file); 9688 } 9689 9690 #-> sub CPAN::Module::undelay 9691 sub undelay { 9692 my $self = shift; 9693 delete $self->{later}; 9694 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { 9695 $dist->undelay; 9696 } 9697 } 9698 9699 # mark as dirty/clean 9700 #-> sub CPAN::Module::color_cmd_tmps ; 9701 sub color_cmd_tmps { 9702 my($self) = shift; 9703 my($depth) = shift || 0; 9704 my($color) = shift || 0; 9705 my($ancestors) = shift || []; 9706 # a module needs to recurse to its cpan_file 9707 9708 return if exists $self->{incommandcolor} 9709 && $color==1 9710 && $self->{incommandcolor}==$color; 9711 return if $color==0 && !$self->{incommandcolor}; 9712 if ($color>=1) { 9713 if ( $self->uptodate ) { 9714 $self->{incommandcolor} = $color; 9715 return; 9716 } elsif (my $have_version = $self->available_version) { 9717 # maybe what we have is good enough 9718 if (@$ancestors) { 9719 my $who_asked_for_me = $ancestors->[-1]; 9720 my $obj = CPAN::Shell->expandany($who_asked_for_me); 9721 if (0) { 9722 } elsif ($obj->isa("CPAN::Bundle")) { 9723 # bundles cannot specify a minimum version 9724 return; 9725 } elsif ($obj->isa("CPAN::Distribution")) { 9726 if (my $prereq_pm = $obj->prereq_pm) { 9727 for my $k (keys %$prereq_pm) { 9728 if (my $want_version = $prereq_pm->{$k}{$self->id}) { 9729 if (CPAN::Version->vcmp($have_version,$want_version) >= 0) { 9730 $self->{incommandcolor} = $color; 9731 return; 9732 } 9733 } 9734 } 9735 } 9736 } 9737 } 9738 } 9739 } else { 9740 $self->{incommandcolor} = $color; # set me before recursion, 9741 # so we can break it 9742 } 9743 if ($depth>=$CPAN::MAX_RECURSION) { 9744 die(CPAN::Exception::RecursiveDependency->new($ancestors)); 9745 } 9746 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; 9747 9748 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { 9749 $dist->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); 9750 } 9751 # unreached code? 9752 # if ($color==0) { 9753 # delete $self->{badtestcnt}; 9754 # } 9755 $self->{incommandcolor} = $color; 9756 } 9757 9758 #-> sub CPAN::Module::as_glimpse ; 9759 sub as_glimpse { 9760 my($self) = @_; 9761 my(@m); 9762 my $class = ref($self); 9763 $class =~ s/^CPAN:://; 9764 my $color_on = ""; 9765 my $color_off = ""; 9766 if ( 9767 $CPAN::Shell::COLOR_REGISTERED 9768 && 9769 $CPAN::META->has_inst("Term::ANSIColor") 9770 && 9771 $self->description 9772 ) { 9773 $color_on = Term::ANSIColor::color("green"); 9774 $color_off = Term::ANSIColor::color("reset"); 9775 } 9776 my $uptodateness = " "; 9777 unless ($class eq "Bundle") { 9778 my $u = $self->uptodate; 9779 $uptodateness = $u ? "=" : "<" if defined $u; 9780 }; 9781 my $id = do { 9782 my $d = $self->distribution; 9783 $d ? $d -> pretty_id : $self->cpan_userid; 9784 }; 9785 push @m, sprintf("%-7s %1s %s%-22s%s (%s)\n", 9786 $class, 9787 $uptodateness, 9788 $color_on, 9789 $self->id, 9790 $color_off, 9791 $id, 9792 ); 9793 join "", @m; 9794 } 9795 9796 #-> sub CPAN::Module::dslip_status 9797 sub dslip_status { 9798 my($self) = @_; 9799 my($stat); 9800 # development status 9801 @{$stat->{D}}{qw,i c a b R M S,} = qw,idea 9802 pre-alpha alpha beta released 9803 mature standard,; 9804 # support level 9805 @{$stat->{S}}{qw,m d u n a,} = qw,mailing-list 9806 developer comp.lang.perl.* 9807 none abandoned,; 9808 # language 9809 @{$stat->{L}}{qw,p c + o h,} = qw,perl C C++ other hybrid,; 9810 # interface 9811 @{$stat->{I}}{qw,f r O p h n,} = qw,functions 9812 references+ties 9813 object-oriented pragma 9814 hybrid none,; 9815 # public licence 9816 @{$stat->{P}}{qw,p g l b a 2 o d r n,} = qw,Standard-Perl 9817 GPL LGPL 9818 BSD Artistic Artistic_2 9819 open-source 9820 distribution_allowed 9821 restricted_distribution 9822 no_licence,; 9823 for my $x (qw(d s l i p)) { 9824 $stat->{$x}{' '} = 'unknown'; 9825 $stat->{$x}{'?'} = 'unknown'; 9826 } 9827 my $ro = $self->ro; 9828 return +{} unless $ro && $ro->{statd}; 9829 return { 9830 D => $ro->{statd}, 9831 S => $ro->{stats}, 9832 L => $ro->{statl}, 9833 I => $ro->{stati}, 9834 P => $ro->{statp}, 9835 DV => $stat->{D}{$ro->{statd}}, 9836 SV => $stat->{S}{$ro->{stats}}, 9837 LV => $stat->{L}{$ro->{statl}}, 9838 IV => $stat->{I}{$ro->{stati}}, 9839 PV => $stat->{P}{$ro->{statp}}, 9840 }; 9841 } 9842 9843 #-> sub CPAN::Module::as_string ; 9844 sub as_string { 9845 my($self) = @_; 9846 my(@m); 9847 CPAN->debug("$self entering as_string") if $CPAN::DEBUG; 9848 my $class = ref($self); 9849 $class =~ s/^CPAN:://; 9850 local($^W) = 0; 9851 push @m, $class, " id = $self->{ID}\n"; 9852 my $sprintf = " %-12s %s\n"; 9853 push @m, sprintf($sprintf, 'DESCRIPTION', $self->description) 9854 if $self->description; 9855 my $sprintf2 = " %-12s %s (%s)\n"; 9856 my($userid); 9857 $userid = $self->userid; 9858 if ( $userid ) { 9859 my $author; 9860 if ($author = CPAN::Shell->expand('Author',$userid)) { 9861 my $email = ""; 9862 my $m; # old perls 9863 if ($m = $author->email) { 9864 $email = " <$m>"; 9865 } 9866 push @m, sprintf( 9867 $sprintf2, 9868 'CPAN_USERID', 9869 $userid, 9870 $author->fullname . $email 9871 ); 9872 } 9873 } 9874 push @m, sprintf($sprintf, 'CPAN_VERSION', $self->cpan_version) 9875 if $self->cpan_version; 9876 if (my $cpan_file = $self->cpan_file) { 9877 push @m, sprintf($sprintf, 'CPAN_FILE', $cpan_file); 9878 if (my $dist = CPAN::Shell->expand("Distribution",$cpan_file)) { 9879 my $upload_date = $dist->upload_date; 9880 if ($upload_date) { 9881 push @m, sprintf($sprintf, 'UPLOAD_DATE', $upload_date); 9882 } 9883 } 9884 } 9885 my $sprintf3 = " %-12s %1s%1s%1s%1s%1s (%s,%s,%s,%s,%s)\n"; 9886 my $dslip = $self->dslip_status; 9887 push @m, sprintf( 9888 $sprintf3, 9889 'DSLIP_STATUS', 9890 @{$dslip}{qw(D S L I P DV SV LV IV PV)}, 9891 ) if $dslip->{D}; 9892 my $local_file = $self->inst_file; 9893 unless ($self->{MANPAGE}) { 9894 my $manpage; 9895 if ($local_file) { 9896 $manpage = $self->manpage_headline($local_file); 9897 } else { 9898 # If we have already untarred it, we should look there 9899 my $dist = $CPAN::META->instance('CPAN::Distribution', 9900 $self->cpan_file); 9901 # warn "dist[$dist]"; 9902 # mff=manifest file; mfh=manifest handle 9903 my($mff,$mfh); 9904 if ( 9905 $dist->{build_dir} 9906 and 9907 (-f ($mff = File::Spec->catfile($dist->{build_dir}, "MANIFEST"))) 9908 and 9909 $mfh = FileHandle->new($mff) 9910 ) { 9911 CPAN->debug("mff[$mff]") if $CPAN::DEBUG; 9912 my $lfre = $self->id; # local file RE 9913 $lfre =~ s/::/./g; 9914 $lfre .= "\\.pm\$"; 9915 my($lfl); # local file file 9916 local $/ = "\n"; 9917 my(@mflines) = <$mfh>; 9918 for (@mflines) { 9919 s/^\s+//; 9920 s/\s.*//s; 9921 } 9922 while (length($lfre)>5 and !$lfl) { 9923 ($lfl) = grep /$lfre/, @mflines; 9924 CPAN->debug("lfl[$lfl]lfre[$lfre]") if $CPAN::DEBUG; 9925 $lfre =~ s/.+?\.//; 9926 } 9927 $lfl =~ s/\s.*//; # remove comments 9928 $lfl =~ s/\s+//g; # chomp would maybe be too system-specific 9929 my $lfl_abs = File::Spec->catfile($dist->{build_dir},$lfl); 9930 # warn "lfl_abs[$lfl_abs]"; 9931 if (-f $lfl_abs) { 9932 $manpage = $self->manpage_headline($lfl_abs); 9933 } 9934 } 9935 } 9936 $self->{MANPAGE} = $manpage if $manpage; 9937 } 9938 my($item); 9939 for $item (qw/MANPAGE/) { 9940 push @m, sprintf($sprintf, $item, $self->{$item}) 9941 if exists $self->{$item}; 9942 } 9943 for $item (qw/CONTAINS/) { 9944 push @m, sprintf($sprintf, $item, join(" ",@{$self->{$item}})) 9945 if exists $self->{$item} && @{$self->{$item}}; 9946 } 9947 push @m, sprintf($sprintf, 'INST_FILE', 9948 $local_file || "(not installed)"); 9949 push @m, sprintf($sprintf, 'INST_VERSION', 9950 $self->inst_version) if $local_file; 9951 join "", @m, "\n"; 9952 } 9953 9954 #-> sub CPAN::Module::manpage_headline 9955 sub manpage_headline { 9956 my($self,$local_file) = @_; 9957 my(@local_file) = $local_file; 9958 $local_file =~ s/\.pm(?!\n)\Z/.pod/; 9959 push @local_file, $local_file; 9960 my(@result,$locf); 9961 for $locf (@local_file) { 9962 next unless -f $locf; 9963 my $fh = FileHandle->new($locf) 9964 or $Carp::Frontend->mydie("Couldn't open $locf: $!"); 9965 my $inpod = 0; 9966 local $/ = "\n"; 9967 while (<$fh>) { 9968 $inpod = m/^=(?!head1\s+NAME\s*$)/ ? 0 : 9969 m/^=head1\s+NAME\s*$/ ? 1 : $inpod; 9970 next unless $inpod; 9971 next if /^=/; 9972 next if /^\s+$/; 9973 chomp; 9974 push @result, $_; 9975 } 9976 close $fh; 9977 last if @result; 9978 } 9979 for (@result) { 9980 s/^\s+//; 9981 s/\s+$//; 9982 } 9983 join " ", @result; 9984 } 9985 9986 #-> sub CPAN::Module::cpan_file ; 9987 # Note: also inherited by CPAN::Bundle 9988 sub cpan_file { 9989 my $self = shift; 9990 # CPAN->debug(sprintf "id[%s]", $self->id) if $CPAN::DEBUG; 9991 unless ($self->ro) { 9992 CPAN::Index->reload; 9993 } 9994 my $ro = $self->ro; 9995 if ($ro && defined $ro->{CPAN_FILE}) { 9996 return $ro->{CPAN_FILE}; 9997 } else { 9998 my $userid = $self->userid; 9999 if ( $userid ) { 10000 if ($CPAN::META->exists("CPAN::Author",$userid)) { 10001 my $author = $CPAN::META->instance("CPAN::Author", 10002 $userid); 10003 my $fullname = $author->fullname; 10004 my $email = $author->email; 10005 unless (defined $fullname && defined $email) { 10006 return sprintf("Contact Author %s", 10007 $userid, 10008 ); 10009 } 10010 return "Contact Author $fullname <$email>"; 10011 } else { 10012 return "Contact Author $userid (Email address not available)"; 10013 } 10014 } else { 10015 return "N/A"; 10016 } 10017 } 10018 } 10019 10020 #-> sub CPAN::Module::cpan_version ; 10021 sub cpan_version { 10022 my $self = shift; 10023 10024 my $ro = $self->ro; 10025 unless ($ro) { 10026 # Can happen with modules that are not on CPAN 10027 $ro = {}; 10028 } 10029 $ro->{CPAN_VERSION} = 'undef' 10030 unless defined $ro->{CPAN_VERSION}; 10031 $ro->{CPAN_VERSION}; 10032 } 10033 10034 #-> sub CPAN::Module::force ; 10035 sub force { 10036 my($self) = @_; 10037 $self->{force_update} = 1; 10038 } 10039 10040 #-> sub CPAN::Module::fforce ; 10041 sub fforce { 10042 my($self) = @_; 10043 $self->{force_update} = 2; 10044 } 10045 10046 #-> sub CPAN::Module::notest ; 10047 sub notest { 10048 my($self) = @_; 10049 # $CPAN::Frontend->mywarn("XDEBUG: set notest for Module"); 10050 $self->{notest}++; 10051 } 10052 10053 #-> sub CPAN::Module::rematein ; 10054 sub rematein { 10055 my($self,$meth) = @_; 10056 $CPAN::Frontend->myprint(sprintf("Running %s for module '%s'\n", 10057 $meth, 10058 $self->id)); 10059 my $cpan_file = $self->cpan_file; 10060 if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/) { 10061 $CPAN::Frontend->mywarn(sprintf qq{ 10062 The module %s isn\'t available on CPAN. 10063 10064 Either the module has not yet been uploaded to CPAN, or it is 10065 temporary unavailable. Please contact the author to find out 10066 more about the status. Try 'i %s'. 10067 }, 10068 $self->id, 10069 $self->id, 10070 ); 10071 return; 10072 } 10073 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); 10074 $pack->called_for($self->id); 10075 if (exists $self->{force_update}) { 10076 if ($self->{force_update} == 2) { 10077 $pack->fforce($meth); 10078 } else { 10079 $pack->force($meth); 10080 } 10081 } 10082 $pack->notest($meth) if exists $self->{notest} && $self->{notest}; 10083 10084 $pack->{reqtype} ||= ""; 10085 CPAN->debug("dist-reqtype[$pack->{reqtype}]". 10086 "self-reqtype[$self->{reqtype}]") if $CPAN::DEBUG; 10087 if ($pack->{reqtype}) { 10088 if ($pack->{reqtype} eq "b" && $self->{reqtype} =~ /^[rc]$/) { 10089 $pack->{reqtype} = $self->{reqtype}; 10090 if ( 10091 exists $pack->{install} 10092 && 10093 ( 10094 UNIVERSAL::can($pack->{install},"failed") ? 10095 $pack->{install}->failed : 10096 $pack->{install} =~ /^NO/ 10097 ) 10098 ) { 10099 delete $pack->{install}; 10100 $CPAN::Frontend->mywarn 10101 ("Promoting $pack->{ID} from 'build_requires' to 'requires'"); 10102 } 10103 } 10104 } else { 10105 $pack->{reqtype} = $self->{reqtype}; 10106 } 10107 10108 my $success = eval { 10109 $pack->$meth(); 10110 }; 10111 my $err = $@; 10112 $pack->unforce if $pack->can("unforce") && exists $self->{force_update}; 10113 $pack->unnotest if $pack->can("unnotest") && exists $self->{notest}; 10114 delete $self->{force_update}; 10115 delete $self->{notest}; 10116 if ($err) { 10117 die $err; 10118 } 10119 return $success; 10120 } 10121 10122 #-> sub CPAN::Module::perldoc ; 10123 sub perldoc { shift->rematein('perldoc') } 10124 #-> sub CPAN::Module::readme ; 10125 sub readme { shift->rematein('readme') } 10126 #-> sub CPAN::Module::look ; 10127 sub look { shift->rematein('look') } 10128 #-> sub CPAN::Module::cvs_import ; 10129 sub cvs_import { shift->rematein('cvs_import') } 10130 #-> sub CPAN::Module::get ; 10131 sub get { shift->rematein('get',@_) } 10132 #-> sub CPAN::Module::make ; 10133 sub make { shift->rematein('make') } 10134 #-> sub CPAN::Module::test ; 10135 sub test { 10136 my $self = shift; 10137 # $self->{badtestcnt} ||= 0; 10138 $self->rematein('test',@_); 10139 } 10140 10141 #-> sub CPAN::Module::uptodate ; 10142 sub uptodate { 10143 my ($self) = @_; 10144 local ($_); 10145 my $inst = $self->inst_version or return undef; 10146 my $cpan = $self->cpan_version; 10147 local ($^W) = 0; 10148 CPAN::Version->vgt($cpan,$inst) and return 0; 10149 CPAN->debug(join("", 10150 "returning uptodate. inst_file[", 10151 $self->inst_file, 10152 "cpan[$cpan] inst[$inst]")) if $CPAN::DEBUG; 10153 return 1; 10154 } 10155 10156 #-> sub CPAN::Module::install ; 10157 sub install { 10158 my($self) = @_; 10159 my($doit) = 0; 10160 if ($self->uptodate 10161 && 10162 not exists $self->{force_update} 10163 ) { 10164 $CPAN::Frontend->myprint(sprintf("%s is up to date (%s).\n", 10165 $self->id, 10166 $self->inst_version, 10167 )); 10168 } else { 10169 $doit = 1; 10170 } 10171 my $ro = $self->ro; 10172 if ($ro && $ro->{stats} && $ro->{stats} eq "a") { 10173 $CPAN::Frontend->mywarn(qq{ 10174 \n\n\n ***WARNING*** 10175 The module $self->{ID} has no active maintainer.\n\n\n 10176 }); 10177 $CPAN::Frontend->mysleep(5); 10178 } 10179 $self->rematein('install') if $doit; 10180 } 10181 #-> sub CPAN::Module::clean ; 10182 sub clean { shift->rematein('clean') } 10183 10184 #-> sub CPAN::Module::inst_file ; 10185 sub inst_file { 10186 my($self) = @_; 10187 $self->_file_in_path([@INC]); 10188 } 10189 10190 #-> sub CPAN::Module::available_file ; 10191 sub available_file { 10192 my($self) = @_; 10193 my $sep = $Config::Config{path_sep}; 10194 my $perllib = $ENV{PERL5LIB}; 10195 $perllib = $ENV{PERLLIB} unless defined $perllib; 10196 my @perllib = split(/$sep/,$perllib) if defined $perllib; 10197 $self->_file_in_path([@perllib,@INC]); 10198 } 10199 10200 #-> sub CPAN::Module::file_in_path ; 10201 sub _file_in_path { 10202 my($self,$path) = @_; 10203 my($dir,@packpath); 10204 @packpath = split /::/, $self->{ID}; 10205 $packpath[-1] .= ".pm"; 10206 if (@packpath == 1 && $packpath[0] eq "readline.pm") { 10207 unshift @packpath, "Term", "ReadLine"; # historical reasons 10208 } 10209 foreach $dir (@$path) { 10210 my $pmfile = File::Spec->catfile($dir,@packpath); 10211 if (-f $pmfile) { 10212 return $pmfile; 10213 } 10214 } 10215 return; 10216 } 10217 10218 #-> sub CPAN::Module::xs_file ; 10219 sub xs_file { 10220 my($self) = @_; 10221 my($dir,@packpath); 10222 @packpath = split /::/, $self->{ID}; 10223 push @packpath, $packpath[-1]; 10224 $packpath[-1] .= "." . $Config::Config{'dlext'}; 10225 foreach $dir (@INC) { 10226 my $xsfile = File::Spec->catfile($dir,'auto',@packpath); 10227 if (-f $xsfile) { 10228 return $xsfile; 10229 } 10230 } 10231 return; 10232 } 10233 10234 #-> sub CPAN::Module::inst_version ; 10235 sub inst_version { 10236 my($self) = @_; 10237 my $parsefile = $self->inst_file or return; 10238 my $have = $self->parse_version($parsefile); 10239 $have; 10240 } 10241 10242 #-> sub CPAN::Module::inst_version ; 10243 sub available_version { 10244 my($self) = @_; 10245 my $parsefile = $self->available_file or return; 10246 my $have = $self->parse_version($parsefile); 10247 $have; 10248 } 10249 10250 #-> sub CPAN::Module::parse_version ; 10251 sub parse_version { 10252 my($self,$parsefile) = @_; 10253 my $have = MM->parse_version($parsefile); 10254 $have = "undef" unless defined $have && length $have; 10255 $have =~ s/^ //; # since the %vd hack these two lines here are needed 10256 $have =~ s/ $//; # trailing whitespace happens all the time 10257 10258 $have = CPAN::Version->readable($have); 10259 10260 $have =~ s/\s*//g; # stringify to float around floating point issues 10261 $have; # no stringify needed, \s* above matches always 10262 } 10263 10264 #-> sub CPAN::Module::reports 10265 sub reports { 10266 my($self) = @_; 10267 $self->distribution->reports; 10268 } 10269 10270 package CPAN; 10271 use strict; 10272 10273 1; 10274 10275 10276 __END__ 10277 10278 =head1 NAME 10279 10280 CPAN - query, download and build perl modules from CPAN sites 10281 10282 =head1 SYNOPSIS 10283 10284 Interactive mode: 10285 10286 perl -MCPAN -e shell 10287 10288 --or-- 10289 10290 cpan 10291 10292 Basic commands: 10293 10294 # Modules: 10295 10296 cpan> install Acme::Meta # in the shell 10297 10298 CPAN::Shell->install("Acme::Meta"); # in perl 10299 10300 # Distributions: 10301 10302 cpan> install NWCLARK/Acme-Meta-0.02.tar.gz # in the shell 10303 10304 CPAN::Shell-> 10305 install("NWCLARK/Acme-Meta-0.02.tar.gz"); # in perl 10306 10307 # module objects: 10308 10309 $mo = CPAN::Shell->expandany($mod); 10310 $mo = CPAN::Shell->expand("Module",$mod); # same thing 10311 10312 # distribution objects: 10313 10314 $do = CPAN::Shell->expand("Module",$mod)->distribution; 10315 $do = CPAN::Shell->expandany($distro); # same thing 10316 $do = CPAN::Shell->expand("Distribution", 10317 $distro); # same thing 10318 10319 =head1 DESCRIPTION 10320 10321 The CPAN module automates or at least simplifies the make and install 10322 of perl modules and extensions. It includes some primitive searching 10323 capabilities and knows how to use Net::FTP or LWP or some external 10324 download clients to fetch the distributions from the net. 10325 10326 These are fetched from one or more of the mirrored CPAN (Comprehensive 10327 Perl Archive Network) sites and unpacked in a dedicated directory. 10328 10329 The CPAN module also supports the concept of named and versioned 10330 I<bundles> of modules. Bundles simplify the handling of sets of 10331 related modules. See Bundles below. 10332 10333 The package contains a session manager and a cache manager. The 10334 session manager keeps track of what has been fetched, built and 10335 installed in the current session. The cache manager keeps track of the 10336 disk space occupied by the make processes and deletes excess space 10337 according to a simple FIFO mechanism. 10338 10339 All methods provided are accessible in a programmer style and in an 10340 interactive shell style. 10341 10342 =head2 CPAN::shell([$prompt, $command]) Starting Interactive Mode 10343 10344 The interactive mode is entered by running 10345 10346 perl -MCPAN -e shell 10347 10348 or 10349 10350 cpan 10351 10352 which puts you into a readline interface. If C<Term::ReadKey> and 10353 either C<Term::ReadLine::Perl> or C<Term::ReadLine::Gnu> are installed 10354 it supports both history and command completion. 10355 10356 Once you are on the command line, type C<h> to get a one page help 10357 screen and the rest should be self-explanatory. 10358 10359 The function call C<shell> takes two optional arguments, one is the 10360 prompt, the second is the default initial command line (the latter 10361 only works if a real ReadLine interface module is installed). 10362 10363 The most common uses of the interactive modes are 10364 10365 =over 2 10366 10367 =item Searching for authors, bundles, distribution files and modules 10368 10369 There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m> 10370 for each of the four categories and another, C<i> for any of the 10371 mentioned four. Each of the four entities is implemented as a class 10372 with slightly differing methods for displaying an object. 10373 10374 Arguments you pass to these commands are either strings exactly matching 10375 the identification string of an object or regular expressions that are 10376 then matched case-insensitively against various attributes of the 10377 objects. The parser recognizes a regular expression only if you 10378 enclose it between two slashes. 10379 10380 The principle is that the number of found objects influences how an 10381 item is displayed. If the search finds one item, the result is 10382 displayed with the rather verbose method C<as_string>, but if we find 10383 more than one, we display each object with the terse method 10384 C<as_glimpse>. 10385 10386 =item C<get>, C<make>, C<test>, C<install>, C<clean> modules or distributions 10387 10388 These commands take any number of arguments and investigate what is 10389 necessary to perform the action. If the argument is a distribution 10390 file name (recognized by embedded slashes), it is processed. If it is 10391 a module, CPAN determines the distribution file in which this module 10392 is included and processes that, following any dependencies named in 10393 the module's META.yml or Makefile.PL (this behavior is controlled by 10394 the configuration parameter C<prerequisites_policy>.) 10395 10396 C<get> downloads a distribution file and untars or unzips it, C<make> 10397 builds it, C<test> runs the test suite, and C<install> installs it. 10398 10399 Any C<make> or C<test> are run unconditionally. An 10400 10401 install <distribution_file> 10402 10403 also is run unconditionally. But for 10404 10405 install <module> 10406 10407 CPAN checks if an install is actually needed for it and prints 10408 I<module up to date> in the case that the distribution file containing 10409 the module doesn't need to be updated. 10410 10411 CPAN also keeps track of what it has done within the current session 10412 and doesn't try to build a package a second time regardless if it 10413 succeeded or not. It does not repeat a test run if the test 10414 has been run successfully before. Same for install runs. 10415 10416 The C<force> pragma may precede another command (currently: C<get>, 10417 C<make>, C<test>, or C<install>) and executes the command from scratch 10418 and tries to continue in case of some errors. See the section below on 10419 the C<force> and the C<fforce> pragma. 10420 10421 The C<notest> pragma may be used to skip the test part in the build 10422 process. 10423 10424 Example: 10425 10426 cpan> notest install Tk 10427 10428 A C<clean> command results in a 10429 10430 make clean 10431 10432 being executed within the distribution file's working directory. 10433 10434 =item C<readme>, C<perldoc>, C<look> module or distribution 10435 10436 C<readme> displays the README file of the associated distribution. 10437 C<Look> gets and untars (if not yet done) the distribution file, 10438 changes to the appropriate directory and opens a subshell process in 10439 that directory. C<perldoc> displays the pod documentation of the 10440 module in html or plain text format. 10441 10442 =item C<ls> author 10443 10444 =item C<ls> globbing_expression 10445 10446 The first form lists all distribution files in and below an author's 10447 CPAN directory as they are stored in the CHECKUMS files distributed on 10448 CPAN. The listing goes recursive into all subdirectories. 10449 10450 The second form allows to limit or expand the output with shell 10451 globbing as in the following examples: 10452 10453 ls JV/make* 10454 ls GSAR/*make* 10455 ls */*make* 10456 10457 The last example is very slow and outputs extra progress indicators 10458 that break the alignment of the result. 10459 10460 Note that globbing only lists directories explicitly asked for, for 10461 example FOO/* will not list FOO/bar/Acme-Sthg-n.nn.tar.gz. This may be 10462 regarded as a bug and may be changed in future versions. 10463 10464 =item C<failed> 10465 10466 The C<failed> command reports all distributions that failed on one of 10467 C<make>, C<test> or C<install> for some reason in the currently 10468 running shell session. 10469 10470 =item Persistence between sessions 10471 10472 If the C<YAML> or the C<YAML::Syck> module is installed a record of 10473 the internal state of all modules is written to disk after each step. 10474 The files contain a signature of the currently running perl version 10475 for later perusal. 10476 10477 If the configurations variable C<build_dir_reuse> is set to a true 10478 value, then CPAN.pm reads the collected YAML files. If the stored 10479 signature matches the currently running perl the stored state is 10480 loaded into memory such that effectively persistence between sessions 10481 is established. 10482 10483 =item The C<force> and the C<fforce> pragma 10484 10485 To speed things up in complex installation scenarios, CPAN.pm keeps 10486 track of what it has already done and refuses to do some things a 10487 second time. A C<get>, a C<make>, and an C<install> are not repeated. 10488 A C<test> is only repeated if the previous test was unsuccessful. The 10489 diagnostic message when CPAN.pm refuses to do something a second time 10490 is one of I<Has already been >C<unwrapped|made|tested successfully> or 10491 something similar. Another situation where CPAN refuses to act is an 10492 C<install> if the according C<test> was not successful. 10493 10494 In all these cases, the user can override the goatish behaviour by 10495 prepending the command with the word force, for example: 10496 10497 cpan> force get Foo 10498 cpan> force make AUTHOR/Bar-3.14.tar.gz 10499 cpan> force test Baz 10500 cpan> force install Acme::Meta 10501 10502 Each I<forced> command is executed with the according part of its 10503 memory erased. 10504 10505 The C<fforce> pragma is a variant that emulates a C<force get> which 10506 erases the entire memory followed by the action specified, effectively 10507 restarting the whole get/make/test/install procedure from scratch. 10508 10509 =item Lockfile 10510 10511 Interactive sessions maintain a lockfile, per default C<~/.cpan/.lock>. 10512 Batch jobs can run without a lockfile and do not disturb each other. 10513 10514 The shell offers to run in I<degraded mode> when another process is 10515 holding the lockfile. This is an experimental feature that is not yet 10516 tested very well. This second shell then does not write the history 10517 file, does not use the metadata file and has a different prompt. 10518 10519 =item Signals 10520 10521 CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are 10522 in the cpan-shell it is intended that you can press C<^C> anytime and 10523 return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell 10524 to clean up and leave the shell loop. You can emulate the effect of a 10525 SIGTERM by sending two consecutive SIGINTs, which usually means by 10526 pressing C<^C> twice. 10527 10528 CPAN.pm ignores a SIGPIPE. If the user sets C<inactivity_timeout>, a 10529 SIGALRM is used during the run of the C<perl Makefile.PL> or C<perl 10530 Build.PL> subprocess. 10531 10532 =back 10533 10534 =head2 CPAN::Shell 10535 10536 The commands that are available in the shell interface are methods in 10537 the package CPAN::Shell. If you enter the shell command, all your 10538 input is split by the Text::ParseWords::shellwords() routine which 10539 acts like most shells do. The first word is being interpreted as the 10540 method to be called and the rest of the words are treated as arguments 10541 to this method. Continuation lines are supported if a line ends with a 10542 literal backslash. 10543 10544 =head2 autobundle 10545 10546 C<autobundle> writes a bundle file into the 10547 C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains 10548 a list of all modules that are both available from CPAN and currently 10549 installed within @INC. The name of the bundle file is based on the 10550 current date and a counter. 10551 10552 =head2 hosts 10553 10554 Note: this feature is still in alpha state and may change in future 10555 versions of CPAN.pm 10556 10557 This commands provides a statistical overview over recent download 10558 activities. The data for this is collected in the YAML file 10559 C<FTPstats.yml> in your C<cpan_home> directory. If no YAML module is 10560 configured or YAML not installed, then no stats are provided. 10561 10562 =head2 mkmyconfig 10563 10564 mkmyconfig() writes your own CPAN::MyConfig file into your ~/.cpan/ 10565 directory so that you can save your own preferences instead of the 10566 system wide ones. 10567 10568 =head2 recent ***EXPERIMENTAL COMMAND*** 10569 10570 The C<recent> command downloads a list of recent uploads to CPAN and 10571 displays them I<slowly>. While the command is running $SIG{INT} is 10572 defined to mean that the loop shall be left after having displayed the 10573 current item. 10574 10575 B<Note>: This command requires XML::LibXML installed. 10576 10577 B<Note>: This whole command currently is a bit klunky and will 10578 probably change in future versions of CPAN.pm but the general 10579 approach will likely stay. 10580 10581 B<Note>: See also L<smoke> 10582 10583 =head2 recompile 10584 10585 recompile() is a very special command in that it takes no argument and 10586 runs the make/test/install cycle with brute force over all installed 10587 dynamically loadable extensions (aka XS modules) with 'force' in 10588 effect. The primary purpose of this command is to finish a network 10589 installation. Imagine, you have a common source tree for two different 10590 architectures. You decide to do a completely independent fresh 10591 installation. You start on one architecture with the help of a Bundle 10592 file produced earlier. CPAN installs the whole Bundle for you, but 10593 when you try to repeat the job on the second architecture, CPAN 10594 responds with a C<"Foo up to date"> message for all modules. So you 10595 invoke CPAN's recompile on the second architecture and you're done. 10596 10597 Another popular use for C<recompile> is to act as a rescue in case your 10598 perl breaks binary compatibility. If one of the modules that CPAN uses 10599 is in turn depending on binary compatibility (so you cannot run CPAN 10600 commands), then you should try the CPAN::Nox module for recovery. 10601 10602 =head2 report Bundle|Distribution|Module 10603 10604 The C<report> command temporarily turns on the C<test_report> config 10605 variable, then runs the C<force test> command with the given 10606 arguments. The C<force> pragma is used to re-run the tests and repeat 10607 every step that might have failed before. 10608 10609 =head2 smoke ***EXPERIMENTAL COMMAND*** 10610 10611 B<*** WARNING: this command downloads and executes software from CPAN to 10612 your computer of completely unknown status. You should never do 10613 this with your normal account and better have a dedicated well 10614 separated and secured machine to do this. ***> 10615 10616 The C<smoke> command takes the list of recent uploads to CPAN as 10617 provided by the C<recent> command and tests them all. While the 10618 command is running $SIG{INT} is defined to mean that the current item 10619 shall be skipped. 10620 10621 B<Note>: This whole command currently is a bit klunky and will 10622 probably change in future versions of CPAN.pm but the general 10623 approach will likely stay. 10624 10625 B<Note>: See also L<recent> 10626 10627 =head2 upgrade [Module|/Regex/]... 10628 10629 The C<upgrade> command first runs an C<r> command with the given 10630 arguments and then installs the newest versions of all modules that 10631 were listed by that. 10632 10633 =head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution 10634 10635 Although it may be considered internal, the class hierarchy does matter 10636 for both users and programmer. CPAN.pm deals with above mentioned four 10637 classes, and all those classes share a set of methods. A classical 10638 single polymorphism is in effect. A metaclass object registers all 10639 objects of all kinds and indexes them with a string. The strings 10640 referencing objects have a separated namespace (well, not completely 10641 separated): 10642 10643 Namespace Class 10644 10645 words containing a "/" (slash) Distribution 10646 words starting with Bundle:: Bundle 10647 everything else Module or Author 10648 10649 Modules know their associated Distribution objects. They always refer 10650 to the most recent official release. Developers may mark their releases 10651 as unstable development versions (by inserting an underbar into the 10652 module version number which will also be reflected in the distribution 10653 name when you run 'make dist'), so the really hottest and newest 10654 distribution is not always the default. If a module Foo circulates 10655 on CPAN in both version 1.23 and 1.23_90, CPAN.pm offers a convenient 10656 way to install version 1.23 by saying 10657 10658 install Foo 10659 10660 This would install the complete distribution file (say 10661 BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would 10662 like to install version 1.23_90, you need to know where the 10663 distribution file resides on CPAN relative to the authors/id/ 10664 directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz; 10665 so you would have to say 10666 10667 install BAR/Foo-1.23_90.tar.gz 10668 10669 The first example will be driven by an object of the class 10670 CPAN::Module, the second by an object of class CPAN::Distribution. 10671 10672 =head2 Integrating local directories 10673 10674 Note: this feature is still in alpha state and may change in future 10675 versions of CPAN.pm 10676 10677 Distribution objects are normally distributions from the CPAN, but 10678 there is a slightly degenerate case for Distribution objects, too, of 10679 projects held on the local disk. These distribution objects have the 10680 same name as the local directory and end with a dot. A dot by itself 10681 is also allowed for the current directory at the time CPAN.pm was 10682 used. All actions such as C<make>, C<test>, and C<install> are applied 10683 directly to that directory. This gives the command C<cpan .> an 10684 interesting touch: while the normal mantra of installing a CPAN module 10685 without CPAN.pm is one of 10686 10687 perl Makefile.PL perl Build.PL 10688 ( go and get prerequisites ) 10689 make ./Build 10690 make test ./Build test 10691 make install ./Build install 10692 10693 the command C<cpan .> does all of this at once. It figures out which 10694 of the two mantras is appropriate, fetches and installs all 10695 prerequisites, cares for them recursively and finally finishes the 10696 installation of the module in the current directory, be it a CPAN 10697 module or not. 10698 10699 The typical usage case is for private modules or working copies of 10700 projects from remote repositories on the local disk. 10701 10702 =head1 CONFIGURATION 10703 10704 When the CPAN module is used for the first time, a configuration 10705 dialog tries to determine a couple of site specific options. The 10706 result of the dialog is stored in a hash reference C< $CPAN::Config > 10707 in a file CPAN/Config.pm. 10708 10709 The default values defined in the CPAN/Config.pm file can be 10710 overridden in a user specific file: CPAN/MyConfig.pm. Such a file is 10711 best placed in $HOME/.cpan/CPAN/MyConfig.pm, because $HOME/.cpan is 10712 added to the search path of the CPAN module before the use() or 10713 require() statements. The mkmyconfig command writes this file for you. 10714 10715 The C<o conf> command has various bells and whistles: 10716 10717 =over 10718 10719 =item completion support 10720 10721 If you have a ReadLine module installed, you can hit TAB at any point 10722 of the commandline and C<o conf> will offer you completion for the 10723 built-in subcommands and/or config variable names. 10724 10725 =item displaying some help: o conf help 10726 10727 Displays a short help 10728 10729 =item displaying current values: o conf [KEY] 10730 10731 Displays the current value(s) for this config variable. Without KEY 10732 displays all subcommands and config variables. 10733 10734 Example: 10735 10736 o conf shell 10737 10738 If KEY starts and ends with a slash the string in between is 10739 interpreted as a regular expression and only keys matching this regex 10740 are displayed 10741 10742 Example: 10743 10744 o conf /color/ 10745 10746 =item changing of scalar values: o conf KEY VALUE 10747 10748 Sets the config variable KEY to VALUE. The empty string can be 10749 specified as usual in shells, with C<''> or C<""> 10750 10751 Example: 10752 10753 o conf wget /usr/bin/wget 10754 10755 =item changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST 10756 10757 If a config variable name ends with C<list>, it is a list. C<o conf 10758 KEY shift> removes the first element of the list, C<o conf KEY pop> 10759 removes the last element of the list. C<o conf KEYS unshift LIST> 10760 prepends a list of values to the list, C<o conf KEYS push LIST> 10761 appends a list of valued to the list. 10762 10763 Likewise, C<o conf KEY splice LIST> passes the LIST to the according 10764 splice command. 10765 10766 Finally, any other list of arguments is taken as a new list value for 10767 the KEY variable discarding the previous value. 10768 10769 Examples: 10770 10771 o conf urllist unshift http://cpan.dev.local/CPAN 10772 o conf urllist splice 3 1 10773 o conf urllist http://cpan1.local http://cpan2.local ftp://ftp.perl.org 10774 10775 =item reverting to saved: o conf defaults 10776 10777 Reverts all config variables to the state in the saved config file. 10778 10779 =item saving the config: o conf commit 10780 10781 Saves all config variables to the current config file (CPAN/Config.pm 10782 or CPAN/MyConfig.pm that was loaded at start). 10783 10784 =back 10785 10786 The configuration dialog can be started any time later again by 10787 issuing the command C< o conf init > in the CPAN shell. A subset of 10788 the configuration dialog can be run by issuing C<o conf init WORD> 10789 where WORD is any valid config variable or a regular expression. 10790 10791 =head2 Config Variables 10792 10793 Currently the following keys in the hash reference $CPAN::Config are 10794 defined: 10795 10796 applypatch path to external prg 10797 auto_commit commit all changes to config variables to disk 10798 build_cache size of cache for directories to build modules 10799 build_dir locally accessible directory to build modules 10800 build_dir_reuse boolean if distros in build_dir are persistent 10801 build_requires_install_policy 10802 to install or not to install when a module is 10803 only needed for building. yes|no|ask/yes|ask/no 10804 bzip2 path to external prg 10805 cache_metadata use serializer to cache metadata 10806 commands_quote prefered character to use for quoting external 10807 commands when running them. Defaults to double 10808 quote on Windows, single tick everywhere else; 10809 can be set to space to disable quoting 10810 check_sigs if signatures should be verified 10811 colorize_debug Term::ANSIColor attributes for debugging output 10812 colorize_output boolean if Term::ANSIColor should colorize output 10813 colorize_print Term::ANSIColor attributes for normal output 10814 colorize_warn Term::ANSIColor attributes for warnings 10815 commandnumber_in_prompt 10816 boolean if you want to see current command number 10817 cpan_home local directory reserved for this package 10818 curl path to external prg 10819 dontload_hash DEPRECATED 10820 dontload_list arrayref: modules in the list will not be 10821 loaded by the CPAN::has_inst() routine 10822 ftp path to external prg 10823 ftp_passive if set, the envariable FTP_PASSIVE is set for downloads 10824 ftp_proxy proxy host for ftp requests 10825 getcwd see below 10826 gpg path to external prg 10827 gzip location of external program gzip 10828 histfile file to maintain history between sessions 10829 histsize maximum number of lines to keep in histfile 10830 http_proxy proxy host for http requests 10831 inactivity_timeout breaks interactive Makefile.PLs or Build.PLs 10832 after this many seconds inactivity. Set to 0 to 10833 never break. 10834 index_expire after this many days refetch index files 10835 inhibit_startup_message 10836 if true, does not print the startup message 10837 keep_source_where directory in which to keep the source (if we do) 10838 load_module_verbosity 10839 report loading of optional modules used by CPAN.pm 10840 lynx path to external prg 10841 make location of external make program 10842 make_arg arguments that should always be passed to 'make' 10843 make_install_make_command 10844 the make command for running 'make install', for 10845 example 'sudo make' 10846 make_install_arg same as make_arg for 'make install' 10847 makepl_arg arguments passed to 'perl Makefile.PL' 10848 mbuild_arg arguments passed to './Build' 10849 mbuild_install_arg arguments passed to './Build install' 10850 mbuild_install_build_command 10851 command to use instead of './Build' when we are 10852 in the install stage, for example 'sudo ./Build' 10853 mbuildpl_arg arguments passed to 'perl Build.PL' 10854 ncftp path to external prg 10855 ncftpget path to external prg 10856 no_proxy don't proxy to these hosts/domains (comma separated list) 10857 pager location of external program more (or any pager) 10858 password your password if you CPAN server wants one 10859 patch path to external prg 10860 prefer_installer legal values are MB and EUMM: if a module comes 10861 with both a Makefile.PL and a Build.PL, use the 10862 former (EUMM) or the latter (MB); if the module 10863 comes with only one of the two, that one will be 10864 used in any case 10865 prerequisites_policy 10866 what to do if you are missing module prerequisites 10867 ('follow' automatically, 'ask' me, or 'ignore') 10868 prefs_dir local directory to store per-distro build options 10869 proxy_user username for accessing an authenticating proxy 10870 proxy_pass password for accessing an authenticating proxy 10871 randomize_urllist add some randomness to the sequence of the urllist 10872 scan_cache controls scanning of cache ('atstart' or 'never') 10873 shell your favorite shell 10874 show_unparsable_versions 10875 boolean if r command tells which modules are versionless 10876 show_upload_date boolean if commands should try to determine upload date 10877 show_zero_versions boolean if r command tells for which modules $version==0 10878 tar location of external program tar 10879 tar_verbosity verbosity level for the tar command 10880 term_is_latin deprecated: if true Unicode is translated to ISO-8859-1 10881 (and nonsense for characters outside latin range) 10882 term_ornaments boolean to turn ReadLine ornamenting on/off 10883 test_report email test reports (if CPAN::Reporter is installed) 10884 unzip location of external program unzip 10885 urllist arrayref to nearby CPAN sites (or equivalent locations) 10886 use_sqlite use CPAN::SQLite for metadata storage (fast and lean) 10887 username your username if you CPAN server wants one 10888 wait_list arrayref to a wait server to try (See CPAN::WAIT) 10889 wget path to external prg 10890 yaml_load_code enable YAML code deserialisation 10891 yaml_module which module to use to read/write YAML files 10892 10893 You can set and query each of these options interactively in the cpan 10894 shell with the C<o conf> or the C<o conf init> command as specified below. 10895 10896 =over 2 10897 10898 =item C<o conf E<lt>scalar optionE<gt>> 10899 10900 prints the current value of the I<scalar option> 10901 10902 =item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>> 10903 10904 Sets the value of the I<scalar option> to I<value> 10905 10906 =item C<o conf E<lt>list optionE<gt>> 10907 10908 prints the current value of the I<list option> in MakeMaker's 10909 neatvalue format. 10910 10911 =item C<o conf E<lt>list optionE<gt> [shift|pop]> 10912 10913 shifts or pops the array in the I<list option> variable 10914 10915 =item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>> 10916 10917 works like the corresponding perl commands. 10918 10919 =item interactive editing: o conf init [MATCH|LIST] 10920 10921 Runs an interactive configuration dialog for matching variables. 10922 Without argument runs the dialog over all supported config variables. 10923 To specify a MATCH the argument must be enclosed by slashes. 10924 10925 Examples: 10926 10927 o conf init ftp_passive ftp_proxy 10928 o conf init /color/ 10929 10930 Note: this method of setting config variables often provides more 10931 explanation about the functioning of a variable than the manpage. 10932 10933 =back 10934 10935 =head2 CPAN::anycwd($path): Note on config variable getcwd 10936 10937 CPAN.pm changes the current working directory often and needs to 10938 determine its own current working directory. Per default it uses 10939 Cwd::cwd but if this doesn't work on your system for some reason, 10940 alternatives can be configured according to the following table: 10941 10942 =over 4 10943 10944 =item cwd 10945 10946 Calls Cwd::cwd 10947 10948 =item getcwd 10949 10950 Calls Cwd::getcwd 10951 10952 =item fastcwd 10953 10954 Calls Cwd::fastcwd 10955 10956 =item backtickcwd 10957 10958 Calls the external command cwd. 10959 10960 =back 10961 10962 =head2 Note on the format of the urllist parameter 10963 10964 urllist parameters are URLs according to RFC 1738. We do a little 10965 guessing if your URL is not compliant, but if you have problems with 10966 C<file> URLs, please try the correct format. Either: 10967 10968 file://localhost/whatever/ftp/pub/CPAN/ 10969 10970 or 10971 10972 file:///home/ftp/pub/CPAN/ 10973 10974 =head2 The urllist parameter has CD-ROM support 10975 10976 The C<urllist> parameter of the configuration table contains a list of 10977 URLs that are to be used for downloading. If the list contains any 10978 C<file> URLs, CPAN always tries to get files from there first. This 10979 feature is disabled for index files. So the recommendation for the 10980 owner of a CD-ROM with CPAN contents is: include your local, possibly 10981 outdated CD-ROM as a C<file> URL at the end of urllist, e.g. 10982 10983 o conf urllist push file://localhost/CDROM/CPAN 10984 10985 CPAN.pm will then fetch the index files from one of the CPAN sites 10986 that come at the beginning of urllist. It will later check for each 10987 module if there is a local copy of the most recent version. 10988 10989 Another peculiarity of urllist is that the site that we could 10990 successfully fetch the last file from automatically gets a preference 10991 token and is tried as the first site for the next request. So if you 10992 add a new site at runtime it may happen that the previously preferred 10993 site will be tried another time. This means that if you want to disallow 10994 a site for the next transfer, it must be explicitly removed from 10995 urllist. 10996 10997 =head2 Maintaining the urllist parameter 10998 10999 If you have YAML.pm (or some other YAML module configured in 11000 C<yaml_module>) installed, CPAN.pm collects a few statistical data 11001 about recent downloads. You can view the statistics with the C<hosts> 11002 command or inspect them directly by looking into the C<FTPstats.yml> 11003 file in your C<cpan_home> directory. 11004 11005 To get some interesting statistics it is recommended to set the 11006 C<randomize_urllist> parameter that introduces some amount of 11007 randomness into the URL selection. 11008 11009 =head2 The C<requires> and C<build_requires> dependency declarations 11010 11011 Since CPAN.pm version 1.88_51 modules declared as C<build_requires> by 11012 a distribution are treated differently depending on the config 11013 variable C<build_requires_install_policy>. By setting 11014 C<build_requires_install_policy> to C<no> such a module is not being 11015 installed. It is only built and tested and then kept in the list of 11016 tested but uninstalled modules. As such it is available during the 11017 build of the dependent module by integrating the path to the 11018 C<blib/arch> and C<blib/lib> directories in the environment variable 11019 PERL5LIB. If C<build_requires_install_policy> is set ti C<yes>, then 11020 both modules declared as C<requires> and those declared as 11021 C<build_requires> are treated alike. By setting to C<ask/yes> or 11022 C<ask/no>, CPAN.pm asks the user and sets the default accordingly. 11023 11024 =head2 Configuration for individual distributions (I<Distroprefs>) 11025 11026 (B<Note:> This feature has been introduced in CPAN.pm 1.8854 and is 11027 still considered beta quality) 11028 11029 Distributions on the CPAN usually behave according to what we call the 11030 CPAN mantra. Or since the event of Module::Build we should talk about 11031 two mantras: 11032 11033 perl Makefile.PL perl Build.PL 11034 make ./Build 11035 make test ./Build test 11036 make install ./Build install 11037 11038 But some modules cannot be built with this mantra. They try to get 11039 some extra data from the user via the environment, extra arguments or 11040 interactively thus disturbing the installation of large bundles like 11041 Phalanx100 or modules with many dependencies like Plagger. 11042 11043 The distroprefs system of C<CPAN.pm> addresses this problem by 11044 allowing the user to specify extra informations and recipes in YAML 11045 files to either 11046 11047 =over 11048 11049 =item 11050 11051 pass additional arguments to one of the four commands, 11052 11053 =item 11054 11055 set environment variables 11056 11057 =item 11058 11059 instantiate an Expect object that reads from the console, waits for 11060 some regular expressions and enters some answers 11061 11062 =item 11063 11064 temporarily override assorted C<CPAN.pm> configuration variables 11065 11066 =item 11067 11068 specify dependencies that the original maintainer forgot to specify 11069 11070 =item 11071 11072 disable the installation of an object altogether 11073 11074 =back 11075 11076 See the YAML and Data::Dumper files that come with the C<CPAN.pm> 11077 distribution in the C<distroprefs/> directory for examples. 11078 11079 =head2 Filenames 11080 11081 The YAML files themselves must have the C<.yml> extension, all other 11082 files are ignored (for two exceptions see I<Fallback Data::Dumper and 11083 Storable> below). The containing directory can be specified in 11084 C<CPAN.pm> in the C<prefs_dir> config variable. Try C<o conf init 11085 prefs_dir> in the CPAN shell to set and activate the distroprefs 11086 system. 11087 11088 Every YAML file may contain arbitrary documents according to the YAML 11089 specification and every single document is treated as an entity that 11090 can specify the treatment of a single distribution. 11091 11092 The names of the files can be picked freely, C<CPAN.pm> always reads 11093 all files (in alphabetical order) and takes the key C<match> (see 11094 below in I<Language Specs>) as a hashref containing match criteria 11095 that determine if the current distribution matches the YAML document 11096 or not. 11097 11098 =head2 Fallback Data::Dumper and Storable 11099 11100 If neither your configured C<yaml_module> nor YAML.pm is installed 11101 CPAN.pm falls back to using Data::Dumper and Storable and looks for 11102 files with the extensions C<.dd> or C<.st> in the C<prefs_dir> 11103 directory. These files are expected to contain one or more hashrefs. 11104 For Data::Dumper generated files, this is expected to be done with by 11105 defining C<$VAR1>, C<$VAR2>, etc. The YAML shell would produce these 11106 with the command 11107 11108 ysh < somefile.yml > somefile.dd 11109 11110 For Storable files the rule is that they must be constructed such that 11111 C<Storable::retrieve(file)> returns an array reference and the array 11112 elements represent one distropref object each. The conversion from 11113 YAML would look like so: 11114 11115 perl -MYAML=LoadFile -MStorable=nstore -e ' 11116 @y=LoadFile(shift); 11117 nstore(\@y, shift)' somefile.yml somefile.st 11118 11119 In bootstrapping situations it is usually sufficient to translate only 11120 a few YAML files to Data::Dumper for the crucial modules like 11121 C<YAML::Syck>, C<YAML.pm> and C<Expect.pm>. If you prefer Storable 11122 over Data::Dumper, remember to pull out a Storable version that writes 11123 an older format than all the other Storable versions that will need to 11124 read them. 11125 11126 =head2 Blueprint 11127 11128 The following example contains all supported keywords and structures 11129 with the exception of C<eexpect> which can be used instead of 11130 C<expect>. 11131 11132 --- 11133 comment: "Demo" 11134 match: 11135 module: "Dancing::Queen" 11136 distribution: "^CHACHACHA/Dancing-" 11137 perl: "/usr/local/cariba-perl/bin/perl" 11138 perlconfig: 11139 archname: "freebsd" 11140 disabled: 1 11141 cpanconfig: 11142 make: gmake 11143 pl: 11144 args: 11145 - "--somearg=specialcase" 11146 11147 env: {} 11148 11149 expect: 11150 - "Which is your favorite fruit" 11151 - "apple\n" 11152 11153 make: 11154 args: 11155 - all 11156 - extra-all 11157 11158 env: {} 11159 11160 expect: [] 11161 11162 commendline: "echo SKIPPING make" 11163 11164 test: 11165 args: [] 11166 11167 env: {} 11168 11169 expect: [] 11170 11171 install: 11172 args: [] 11173 11174 env: 11175 WANT_TO_INSTALL: YES 11176 11177 expect: 11178 - "Do you really want to install" 11179 - "y\n" 11180 11181 patches: 11182 - "ABCDE/Fedcba-3.14-ABCDE-01.patch" 11183 11184 depends: 11185 configure_requires: 11186 LWP: 5.8 11187 build_requires: 11188 Test::Exception: 0.25 11189 requires: 11190 Spiffy: 0.30 11191 11192 11193 =head2 Language Specs 11194 11195 Every YAML document represents a single hash reference. The valid keys 11196 in this hash are as follows: 11197 11198 =over 11199 11200 =item comment [scalar] 11201 11202 A comment 11203 11204 =item cpanconfig [hash] 11205 11206 Temporarily override assorted C<CPAN.pm> configuration variables. 11207 11208 Supported are: C<build_requires_install_policy>, C<check_sigs>, 11209 C<make>, C<make_install_make_command>, C<prefer_installer>, 11210 C<test_report>. Please report as a bug when you need another one 11211 supported. 11212 11213 =item depends [hash] *** EXPERIMENTAL FEATURE *** 11214 11215 All three types, namely C<configure_requires>, C<build_requires>, and 11216 C<requires> are supported in the way specified in the META.yml 11217 specification. The current implementation I<merges> the specified 11218 dependencies with those declared by the package maintainer. In a 11219 future implementation this may be changed to override the original 11220 declaration. 11221 11222 =item disabled [boolean] 11223 11224 Specifies that this distribution shall not be processed at all. 11225 11226 =item goto [string] 11227 11228 The canonical name of a delegate distribution that shall be installed 11229 instead. Useful when a new version, although it tests OK itself, 11230 breaks something else or a developer release or a fork is already 11231 uploaded that is better than the last released version. 11232 11233 =item install [hash] 11234 11235 Processing instructions for the C<make install> or C<./Build install> 11236 phase of the CPAN mantra. See below under I<Processiong Instructions>. 11237 11238 =item make [hash] 11239 11240 Processing instructions for the C<make> or C<./Build> phase of the 11241 CPAN mantra. See below under I<Processiong Instructions>. 11242 11243 =item match [hash] 11244 11245 A hashref with one or more of the keys C<distribution>, C<modules>, 11246 C<perl>, and C<perlconfig> that specify if a document is targeted at a 11247 specific CPAN distribution or installation. 11248 11249 The corresponding values are interpreted as regular expressions. The 11250 C<distribution> related one will be matched against the canonical 11251 distribution name, e.g. "AUTHOR/Foo-Bar-3.14.tar.gz". 11252 11253 The C<module> related one will be matched against I<all> modules 11254 contained in the distribution until one module matches. 11255 11256 The C<perl> related one will be matched against C<$^X> (but with the 11257 absolute path). 11258 11259 The value associated with C<perlconfig> is itself a hashref that is 11260 matched against corresponding values in the C<%Config::Config> hash 11261 living in the C< Config.pm > module. 11262 11263 If more than one restriction of C<module>, C<distribution>, and 11264 C<perl> is specified, the results of the separately computed match 11265 values must all match. If this is the case then the hashref 11266 represented by the YAML document is returned as the preference 11267 structure for the current distribution. 11268 11269 =item patches [array] 11270 11271 An array of patches on CPAN or on the local disk to be applied in 11272 order via the external patch program. If the value for the C<-p> 11273 parameter is C<0> or C<1> is determined by reading the patch 11274 beforehand. 11275 11276 Note: if the C<applypatch> program is installed and C<CPAN::Config> 11277 knows about it B<and> a patch is written by the C<makepatch> program, 11278 then C<CPAN.pm> lets C<applypatch> apply the patch. Both C<makepatch> 11279 and C<applypatch> are available from CPAN in the C<JV/makepatch-*> 11280 distribution. 11281 11282 =item pl [hash] 11283 11284 Processing instructions for the C<perl Makefile.PL> or C<perl 11285 Build.PL> phase of the CPAN mantra. See below under I<Processiong 11286 Instructions>. 11287 11288 =item test [hash] 11289 11290 Processing instructions for the C<make test> or C<./Build test> phase 11291 of the CPAN mantra. See below under I<Processiong Instructions>. 11292 11293 =back 11294 11295 =head2 Processing Instructions 11296 11297 =over 11298 11299 =item args [array] 11300 11301 Arguments to be added to the command line 11302 11303 =item commandline 11304 11305 A full commandline that will be executed as it stands by a system 11306 call. During the execution the environment variable PERL will is set 11307 to $^X (but with an absolute path). If C<commandline> is specified, 11308 the content of C<args> is not used. 11309 11310 =item eexpect [hash] 11311 11312 Extended C<expect>. This is a hash reference with four allowed keys, 11313 C<mode>, C<timeout>, C<reuse>, and C<talk>. 11314 11315 C<mode> may have the values C<deterministic> for the case where all 11316 questions come in the order written down and C<anyorder> for the case 11317 where the questions may come in any order. The default mode is 11318 C<deterministic>. 11319 11320 C<timeout> denotes a timeout in seconds. Floating point timeouts are 11321 OK. In the case of a C<mode=deterministic> the timeout denotes the 11322 timeout per question, in the case of C<mode=anyorder> it denotes the 11323 timeout per byte received from the stream or questions. 11324 11325 C<talk> is a reference to an array that contains alternating questions 11326 and answers. Questions are regular expressions and answers are literal 11327 strings. The Expect module will then watch the stream coming from the 11328 execution of the external program (C<perl Makefile.PL>, C<perl 11329 Build.PL>, C<make>, etc.). 11330 11331 In the case of C<mode=deterministic> the CPAN.pm will inject the 11332 according answer as soon as the stream matches the regular expression. 11333 11334 In the case of C<mode=anyorder> CPAN.pm will answer a question as soon 11335 as the timeout is reached for the next byte in the input stream. In 11336 this mode you can use the C<reuse> parameter to decide what shall 11337 happen with a question-answer pair after it has been used. In the 11338 default case (reuse=0) it is removed from the array, so it cannot be 11339 used again accidentally. In this case, if you want to answer the 11340 question C<Do you really want to do that> several times, then it must 11341 be included in the array at least as often as you want this answer to 11342 be given. Setting the parameter C<reuse> to 1 makes this repetition 11343 unnecessary. 11344 11345 =item env [hash] 11346 11347 Environment variables to be set during the command 11348 11349 =item expect [array] 11350 11351 C<< expect: <array> >> is a short notation for 11352 11353 eexpect: 11354 mode: deterministic 11355 timeout: 15 11356 talk: <array> 11357 11358 =back 11359 11360 =head2 Schema verification with C<Kwalify> 11361 11362 If you have the C<Kwalify> module installed (which is part of the 11363 Bundle::CPANxxl), then all your distroprefs files are checked for 11364 syntactical correctness. 11365 11366 =head2 Example Distroprefs Files 11367 11368 C<CPAN.pm> comes with a collection of example YAML files. Note that these 11369 are really just examples and should not be used without care because 11370 they cannot fit everybody's purpose. After all the authors of the 11371 packages that ask questions had a need to ask, so you should watch 11372 their questions and adjust the examples to your environment and your 11373 needs. You have beend warned:-) 11374 11375 =head1 PROGRAMMER'S INTERFACE 11376 11377 If you do not enter the shell, the available shell commands are both 11378 available as methods (C<CPAN::Shell-E<gt>install(...)>) and as 11379 functions in the calling package (C<install(...)>). Before calling low-level 11380 commands it makes sense to initialize components of CPAN you need, e.g.: 11381 11382 CPAN::HandleConfig->load; 11383 CPAN::Shell::setup_output; 11384 CPAN::Index->reload; 11385 11386 High-level commands do such initializations automatically. 11387 11388 There's currently only one class that has a stable interface - 11389 CPAN::Shell. All commands that are available in the CPAN shell are 11390 methods of the class CPAN::Shell. Each of the commands that produce 11391 listings of modules (C<r>, C<autobundle>, C<u>) also return a list of 11392 the IDs of all modules within the list. 11393 11394 =over 2 11395 11396 =item expand($type,@things) 11397 11398 The IDs of all objects available within a program are strings that can 11399 be expanded to the corresponding real objects with the 11400 C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a 11401 list of CPAN::Module objects according to the C<@things> arguments 11402 given. In scalar context it only returns the first element of the 11403 list. 11404 11405 =item expandany(@things) 11406 11407 Like expand, but returns objects of the appropriate type, i.e. 11408 CPAN::Bundle objects for bundles, CPAN::Module objects for modules and 11409 CPAN::Distribution objects for distributions. Note: it does not expand 11410 to CPAN::Author objects. 11411 11412 =item Programming Examples 11413 11414 This enables the programmer to do operations that combine 11415 functionalities that are available in the shell. 11416 11417 # install everything that is outdated on my disk: 11418 perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)' 11419 11420 # install my favorite programs if necessary: 11421 for $mod (qw(Net::FTP Digest::SHA Data::Dumper)) { 11422 CPAN::Shell->install($mod); 11423 } 11424 11425 # list all modules on my disk that have no VERSION number 11426 for $mod (CPAN::Shell->expand("Module","/./")) { 11427 next unless $mod->inst_file; 11428 # MakeMaker convention for undefined $VERSION: 11429 next unless $mod->inst_version eq "undef"; 11430 print "No VERSION in ", $mod->id, "\n"; 11431 } 11432 11433 # find out which distribution on CPAN contains a module: 11434 print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file 11435 11436 Or if you want to write a cronjob to watch The CPAN, you could list 11437 all modules that need updating. First a quick and dirty way: 11438 11439 perl -e 'use CPAN; CPAN::Shell->r;' 11440 11441 If you don't want to get any output in the case that all modules are 11442 up to date, you can parse the output of above command for the regular 11443 expression //modules are up to date// and decide to mail the output 11444 only if it doesn't match. Ick? 11445 11446 If you prefer to do it more in a programmer style in one single 11447 process, maybe something like this suits you better: 11448 11449 # list all modules on my disk that have newer versions on CPAN 11450 for $mod (CPAN::Shell->expand("Module","/./")) { 11451 next unless $mod->inst_file; 11452 next if $mod->uptodate; 11453 printf "Module %s is installed as %s, could be updated to %s from CPAN\n", 11454 $mod->id, $mod->inst_version, $mod->cpan_version; 11455 } 11456 11457 If that gives you too much output every day, you maybe only want to 11458 watch for three modules. You can write 11459 11460 for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")) { 11461 11462 as the first line instead. Or you can combine some of the above 11463 tricks: 11464 11465 # watch only for a new mod_perl module 11466 $mod = CPAN::Shell->expand("Module","mod_perl"); 11467 exit if $mod->uptodate; 11468 # new mod_perl arrived, let me know all update recommendations 11469 CPAN::Shell->r; 11470 11471 =back 11472 11473 =head2 Methods in the other Classes 11474 11475 =over 4 11476 11477 =item CPAN::Author::as_glimpse() 11478 11479 Returns a one-line description of the author 11480 11481 =item CPAN::Author::as_string() 11482 11483 Returns a multi-line description of the author 11484 11485 =item CPAN::Author::email() 11486 11487 Returns the author's email address 11488 11489 =item CPAN::Author::fullname() 11490 11491 Returns the author's name 11492 11493 =item CPAN::Author::name() 11494 11495 An alias for fullname 11496 11497 =item CPAN::Bundle::as_glimpse() 11498 11499 Returns a one-line description of the bundle 11500 11501 =item CPAN::Bundle::as_string() 11502 11503 Returns a multi-line description of the bundle 11504 11505 =item CPAN::Bundle::clean() 11506 11507 Recursively runs the C<clean> method on all items contained in the bundle. 11508 11509 =item CPAN::Bundle::contains() 11510 11511 Returns a list of objects' IDs contained in a bundle. The associated 11512 objects may be bundles, modules or distributions. 11513 11514 =item CPAN::Bundle::force($method,@args) 11515 11516 Forces CPAN to perform a task that it normally would have refused to 11517 do. Force takes as arguments a method name to be called and any number 11518 of additional arguments that should be passed to the called method. 11519 The internals of the object get the needed changes so that CPAN.pm 11520 does not refuse to take the action. The C<force> is passed recursively 11521 to all contained objects. See also the section above on the C<force> 11522 and the C<fforce> pragma. 11523 11524 =item CPAN::Bundle::get() 11525 11526 Recursively runs the C<get> method on all items contained in the bundle 11527 11528 =item CPAN::Bundle::inst_file() 11529 11530 Returns the highest installed version of the bundle in either @INC or 11531 C<$CPAN::Config->{cpan_home}>. Note that this is different from 11532 CPAN::Module::inst_file. 11533 11534 =item CPAN::Bundle::inst_version() 11535 11536 Like CPAN::Bundle::inst_file, but returns the $VERSION 11537 11538 =item CPAN::Bundle::uptodate() 11539 11540 Returns 1 if the bundle itself and all its members are uptodate. 11541 11542 =item CPAN::Bundle::install() 11543 11544 Recursively runs the C<install> method on all items contained in the bundle 11545 11546 =item CPAN::Bundle::make() 11547 11548 Recursively runs the C<make> method on all items contained in the bundle 11549 11550 =item CPAN::Bundle::readme() 11551 11552 Recursively runs the C<readme> method on all items contained in the bundle 11553 11554 =item CPAN::Bundle::test() 11555 11556 Recursively runs the C<test> method on all items contained in the bundle 11557 11558 =item CPAN::Distribution::as_glimpse() 11559 11560 Returns a one-line description of the distribution 11561 11562 =item CPAN::Distribution::as_string() 11563 11564 Returns a multi-line description of the distribution 11565 11566 =item CPAN::Distribution::author 11567 11568 Returns the CPAN::Author object of the maintainer who uploaded this 11569 distribution 11570 11571 =item CPAN::Distribution::pretty_id() 11572 11573 Returns a string of the form "AUTHORID/TARBALL", where AUTHORID is the 11574 author's PAUSE ID and TARBALL is the distribution filename. 11575 11576 =item CPAN::Distribution::base_id() 11577 11578 Returns the distribution filename without any archive suffix. E.g 11579 "Foo-Bar-0.01" 11580 11581 =item CPAN::Distribution::clean() 11582 11583 Changes to the directory where the distribution has been unpacked and 11584 runs C<make clean> there. 11585 11586 =item CPAN::Distribution::containsmods() 11587 11588 Returns a list of IDs of modules contained in a distribution file. 11589 Only works for distributions listed in the 02packages.details.txt.gz 11590 file. This typically means that only the most recent version of a 11591 distribution is covered. 11592 11593 =item CPAN::Distribution::cvs_import() 11594 11595 Changes to the directory where the distribution has been unpacked and 11596 runs something like 11597 11598 cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version 11599 11600 there. 11601 11602 =item CPAN::Distribution::dir() 11603 11604 Returns the directory into which this distribution has been unpacked. 11605 11606 =item CPAN::Distribution::force($method,@args) 11607 11608 Forces CPAN to perform a task that it normally would have refused to 11609 do. Force takes as arguments a method name to be called and any number 11610 of additional arguments that should be passed to the called method. 11611 The internals of the object get the needed changes so that CPAN.pm 11612 does not refuse to take the action. See also the section above on the 11613 C<force> and the C<fforce> pragma. 11614 11615 =item CPAN::Distribution::get() 11616 11617 Downloads the distribution from CPAN and unpacks it. Does nothing if 11618 the distribution has already been downloaded and unpacked within the 11619 current session. 11620 11621 =item CPAN::Distribution::install() 11622 11623 Changes to the directory where the distribution has been unpacked and 11624 runs the external command C<make install> there. If C<make> has not 11625 yet been run, it will be run first. A C<make test> will be issued in 11626 any case and if this fails, the install will be canceled. The 11627 cancellation can be avoided by letting C<force> run the C<install> for 11628 you. 11629 11630 This install method has only the power to install the distribution if 11631 there are no dependencies in the way. To install an object and all of 11632 its dependencies, use CPAN::Shell->install. 11633 11634 Note that install() gives no meaningful return value. See uptodate(). 11635 11636 =item CPAN::Distribution::install_tested() 11637 11638 Install all the distributions that have been tested sucessfully but 11639 not yet installed. See also C<is_tested>. 11640 11641 =item CPAN::Distribution::isa_perl() 11642 11643 Returns 1 if this distribution file seems to be a perl distribution. 11644 Normally this is derived from the file name only, but the index from 11645 CPAN can contain a hint to achieve a return value of true for other 11646 filenames too. 11647 11648 =item CPAN::Distribution::is_tested() 11649 11650 List all the distributions that have been tested sucessfully but not 11651 yet installed. See also C<install_tested>. 11652 11653 =item CPAN::Distribution::look() 11654 11655 Changes to the directory where the distribution has been unpacked and 11656 opens a subshell there. Exiting the subshell returns. 11657 11658 =item CPAN::Distribution::make() 11659 11660 First runs the C<get> method to make sure the distribution is 11661 downloaded and unpacked. Changes to the directory where the 11662 distribution has been unpacked and runs the external commands C<perl 11663 Makefile.PL> or C<perl Build.PL> and C<make> there. 11664 11665 =item CPAN::Distribution::perldoc() 11666 11667 Downloads the pod documentation of the file associated with a 11668 distribution (in html format) and runs it through the external 11669 command lynx specified in C<$CPAN::Config->{lynx}>. If lynx 11670 isn't available, it converts it to plain text with external 11671 command html2text and runs it through the pager specified 11672 in C<$CPAN::Config->{pager}> 11673 11674 =item CPAN::Distribution::prefs() 11675 11676 Returns the hash reference from the first matching YAML file that the 11677 user has deposited in the C<prefs_dir/> directory. The first 11678 succeeding match wins. The files in the C<prefs_dir/> are processed 11679 alphabetically and the canonical distroname (e.g. 11680 AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions 11681 stored in the $root->{match}{distribution} attribute value. 11682 Additionally all module names contained in a distribution are matched 11683 agains the regular expressions in the $root->{match}{module} attribute 11684 value. The two match values are ANDed together. Each of the two 11685 attributes are optional. 11686 11687 =item CPAN::Distribution::prereq_pm() 11688 11689 Returns the hash reference that has been announced by a distribution 11690 as the the C<requires> and C<build_requires> elements. These can be 11691 declared either by the C<META.yml> (if authoritative) or can be 11692 deposited after the run of C<Build.PL> in the file C<./_build/prereqs> 11693 or after the run of C<Makfile.PL> written as the C<PREREQ_PM> hash in 11694 a comment in the produced C<Makefile>. I<Note>: this method only works 11695 after an attempt has been made to C<make> the distribution. Returns 11696 undef otherwise. 11697 11698 =item CPAN::Distribution::readme() 11699 11700 Downloads the README file associated with a distribution and runs it 11701 through the pager specified in C<$CPAN::Config->{pager}>. 11702 11703 =item CPAN::Distribution::reports() 11704 11705 Downloads report data for this distribution from cpantesters.perl.org 11706 and displays a subset of them. 11707 11708 =item CPAN::Distribution::read_yaml() 11709 11710 Returns the content of the META.yml of this distro as a hashref. Note: 11711 works only after an attempt has been made to C<make> the distribution. 11712 Returns undef otherwise. Also returns undef if the content of META.yml 11713 is not authoritative. (The rules about what exactly makes the content 11714 authoritative are still in flux.) 11715 11716 =item CPAN::Distribution::test() 11717 11718 Changes to the directory where the distribution has been unpacked and 11719 runs C<make test> there. 11720 11721 =item CPAN::Distribution::uptodate() 11722 11723 Returns 1 if all the modules contained in the distribution are 11724 uptodate. Relies on containsmods. 11725 11726 =item CPAN::Index::force_reload() 11727 11728 Forces a reload of all indices. 11729 11730 =item CPAN::Index::reload() 11731 11732 Reloads all indices if they have not been read for more than 11733 C<$CPAN::Config->{index_expire}> days. 11734 11735 =item CPAN::InfoObj::dump() 11736 11737 CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution 11738 inherit this method. It prints the data structure associated with an 11739 object. Useful for debugging. Note: the data structure is considered 11740 internal and thus subject to change without notice. 11741 11742 =item CPAN::Module::as_glimpse() 11743 11744 Returns a one-line description of the module in four columns: The 11745 first column contains the word C<Module>, the second column consists 11746 of one character: an equals sign if this module is already installed 11747 and uptodate, a less-than sign if this module is installed but can be 11748 upgraded, and a space if the module is not installed. The third column 11749 is the name of the module and the fourth column gives maintainer or 11750 distribution information. 11751 11752 =item CPAN::Module::as_string() 11753 11754 Returns a multi-line description of the module 11755 11756 =item CPAN::Module::clean() 11757 11758 Runs a clean on the distribution associated with this module. 11759 11760 =item CPAN::Module::cpan_file() 11761 11762 Returns the filename on CPAN that is associated with the module. 11763 11764 =item CPAN::Module::cpan_version() 11765 11766 Returns the latest version of this module available on CPAN. 11767 11768 =item CPAN::Module::cvs_import() 11769 11770 Runs a cvs_import on the distribution associated with this module. 11771 11772 =item CPAN::Module::description() 11773 11774 Returns a 44 character description of this module. Only available for 11775 modules listed in The Module List (CPAN/modules/00modlist.long.html 11776 or 00modlist.long.txt.gz) 11777 11778 =item CPAN::Module::distribution() 11779 11780 Returns the CPAN::Distribution object that contains the current 11781 version of this module. 11782 11783 =item CPAN::Module::dslip_status() 11784 11785 Returns a hash reference. The keys of the hash are the letters C<D>, 11786 C<S>, C<L>, C<I>, and <P>, for development status, support level, 11787 language, interface and public licence respectively. The data for the 11788 DSLIP status are collected by pause.perl.org when authors register 11789 their namespaces. The values of the 5 hash elements are one-character 11790 words whose meaning is described in the table below. There are also 5 11791 hash elements C<DV>, C<SV>, C<LV>, C<IV>, and <PV> that carry a more 11792 verbose value of the 5 status variables. 11793 11794 Where the 'DSLIP' characters have the following meanings: 11795 11796 D - Development Stage (Note: *NO IMPLIED TIMESCALES*): 11797 i - Idea, listed to gain consensus or as a placeholder 11798 c - under construction but pre-alpha (not yet released) 11799 a/b - Alpha/Beta testing 11800 R - Released 11801 M - Mature (no rigorous definition) 11802 S - Standard, supplied with Perl 5 11803 11804 S - Support Level: 11805 m - Mailing-list 11806 d - Developer 11807 u - Usenet newsgroup comp.lang.perl.modules 11808 n - None known, try comp.lang.perl.modules 11809 a - abandoned; volunteers welcome to take over maintainance 11810 11811 L - Language Used: 11812 p - Perl-only, no compiler needed, should be platform independent 11813 c - C and perl, a C compiler will be needed 11814 h - Hybrid, written in perl with optional C code, no compiler needed 11815 + - C++ and perl, a C++ compiler will be needed 11816 o - perl and another language other than C or C++ 11817 11818 I - Interface Style 11819 f - plain Functions, no references used 11820 h - hybrid, object and function interfaces available 11821 n - no interface at all (huh?) 11822 r - some use of unblessed References or ties 11823 O - Object oriented using blessed references and/or inheritance 11824 11825 P - Public License 11826 p - Standard-Perl: user may choose between GPL and Artistic 11827 g - GPL: GNU General Public License 11828 l - LGPL: "GNU Lesser General Public License" (previously known as 11829 "GNU Library General Public License") 11830 b - BSD: The BSD License 11831 a - Artistic license alone 11832 2 - Artistic license 2.0 or later 11833 o - open source: appoved by www.opensource.org 11834 d - allows distribution without restrictions 11835 r - restricted distribtion 11836 n - no license at all 11837 11838 =item CPAN::Module::force($method,@args) 11839 11840 Forces CPAN to perform a task that it normally would have refused to 11841 do. Force takes as arguments a method name to be called and any number 11842 of additional arguments that should be passed to the called method. 11843 The internals of the object get the needed changes so that CPAN.pm 11844 does not refuse to take the action. See also the section above on the 11845 C<force> and the C<fforce> pragma. 11846 11847 =item CPAN::Module::get() 11848 11849 Runs a get on the distribution associated with this module. 11850 11851 =item CPAN::Module::inst_file() 11852 11853 Returns the filename of the module found in @INC. The first file found 11854 is reported just like perl itself stops searching @INC when it finds a 11855 module. 11856 11857 =item CPAN::Module::available_file() 11858 11859 Returns the filename of the module found in PERL5LIB or @INC. The 11860 first file found is reported. The advantage of this method over 11861 C<inst_file> is that modules that have been tested but not yet 11862 installed are included because PERL5LIB keeps track of tested modules. 11863 11864 =item CPAN::Module::inst_version() 11865 11866 Returns the version number of the installed module in readable format. 11867 11868 =item CPAN::Module::available_version() 11869 11870 Returns the version number of the available module in readable format. 11871 11872 =item CPAN::Module::install() 11873 11874 Runs an C<install> on the distribution associated with this module. 11875 11876 =item CPAN::Module::look() 11877 11878 Changes to the directory where the distribution associated with this 11879 module has been unpacked and opens a subshell there. Exiting the 11880 subshell returns. 11881 11882 =item CPAN::Module::make() 11883 11884 Runs a C<make> on the distribution associated with this module. 11885 11886 =item CPAN::Module::manpage_headline() 11887 11888 If module is installed, peeks into the module's manpage, reads the 11889 headline and returns it. Moreover, if the module has been downloaded 11890 within this session, does the equivalent on the downloaded module even 11891 if it is not installed. 11892 11893 =item CPAN::Module::perldoc() 11894 11895 Runs a C<perldoc> on this module. 11896 11897 =item CPAN::Module::readme() 11898 11899 Runs a C<readme> on the distribution associated with this module. 11900 11901 =item CPAN::Module::reports() 11902 11903 Calls the reports() method on the associated distribution object. 11904 11905 =item CPAN::Module::test() 11906 11907 Runs a C<test> on the distribution associated with this module. 11908 11909 =item CPAN::Module::uptodate() 11910 11911 Returns 1 if the module is installed and up-to-date. 11912 11913 =item CPAN::Module::userid() 11914 11915 Returns the author's ID of the module. 11916 11917 =back 11918 11919 =head2 Cache Manager 11920 11921 Currently the cache manager only keeps track of the build directory 11922 ($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that 11923 deletes complete directories below C<build_dir> as soon as the size of 11924 all directories there gets bigger than $CPAN::Config->{build_cache} 11925 (in MB). The contents of this cache may be used for later 11926 re-installations that you intend to do manually, but will never be 11927 trusted by CPAN itself. This is due to the fact that the user might 11928 use these directories for building modules on different architectures. 11929 11930 There is another directory ($CPAN::Config->{keep_source_where}) where 11931 the original distribution files are kept. This directory is not 11932 covered by the cache manager and must be controlled by the user. If 11933 you choose to have the same directory as build_dir and as 11934 keep_source_where directory, then your sources will be deleted with 11935 the same fifo mechanism. 11936 11937 =head2 Bundles 11938 11939 A bundle is just a perl module in the namespace Bundle:: that does not 11940 define any functions or methods. It usually only contains documentation. 11941 11942 It starts like a perl module with a package declaration and a $VERSION 11943 variable. After that the pod section looks like any other pod with the 11944 only difference being that I<one special pod section> exists starting with 11945 (verbatim): 11946 11947 =head1 CONTENTS 11948 11949 In this pod section each line obeys the format 11950 11951 Module_Name [Version_String] [- optional text] 11952 11953 The only required part is the first field, the name of a module 11954 (e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest 11955 of the line is optional. The comment part is delimited by a dash just 11956 as in the man page header. 11957 11958 The distribution of a bundle should follow the same convention as 11959 other distributions. 11960 11961 Bundles are treated specially in the CPAN package. If you say 'install 11962 Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all 11963 the modules in the CONTENTS section of the pod. You can install your 11964 own Bundles locally by placing a conformant Bundle file somewhere into 11965 your @INC path. The autobundle() command which is available in the 11966 shell interface does that for you by including all currently installed 11967 modules in a snapshot bundle file. 11968 11969 =head1 PREREQUISITES 11970 11971 If you have a local mirror of CPAN and can access all files with 11972 "file:" URLs, then you only need a perl better than perl5.003 to run 11973 this module. Otherwise Net::FTP is strongly recommended. LWP may be 11974 required for non-UNIX systems or if your nearest CPAN site is 11975 associated with a URL that is not C<ftp:>. 11976 11977 If you have neither Net::FTP nor LWP, there is a fallback mechanism 11978 implemented for an external ftp command or for an external lynx 11979 command. 11980 11981 =head1 UTILITIES 11982 11983 =head2 Finding packages and VERSION 11984 11985 This module presumes that all packages on CPAN 11986 11987 =over 2 11988 11989 =item * 11990 11991 declare their $VERSION variable in an easy to parse manner. This 11992 prerequisite can hardly be relaxed because it consumes far too much 11993 memory to load all packages into the running program just to determine 11994 the $VERSION variable. Currently all programs that are dealing with 11995 version use something like this 11996 11997 perl -MExtUtils::MakeMaker -le \ 11998 'print MM->parse_version(shift)' filename 11999 12000 If you are author of a package and wonder if your $VERSION can be 12001 parsed, please try the above method. 12002 12003 =item * 12004 12005 come as compressed or gzipped tarfiles or as zip files and contain a 12006 C<Makefile.PL> or C<Build.PL> (well, we try to handle a bit more, but 12007 without much enthusiasm). 12008 12009 =back 12010 12011 =head2 Debugging 12012 12013 The debugging of this module is a bit complex, because we have 12014 interferences of the software producing the indices on CPAN, of the 12015 mirroring process on CPAN, of packaging, of configuration, of 12016 synchronicity, and of bugs within CPAN.pm. 12017 12018 For debugging the code of CPAN.pm itself in interactive mode some more 12019 or less useful debugging aid can be turned on for most packages within 12020 CPAN.pm with one of 12021 12022 =over 2 12023 12024 =item o debug package... 12025 12026 sets debug mode for packages. 12027 12028 =item o debug -package... 12029 12030 unsets debug mode for packages. 12031 12032 =item o debug all 12033 12034 turns debugging on for all packages. 12035 12036 =item o debug number 12037 12038 =back 12039 12040 which sets the debugging packages directly. Note that C<o debug 0> 12041 turns debugging off. 12042 12043 What seems quite a successful strategy is the combination of C<reload 12044 cpan> and the debugging switches. Add a new debug statement while 12045 running in the shell and then issue a C<reload cpan> and see the new 12046 debugging messages immediately without losing the current context. 12047 12048 C<o debug> without an argument lists the valid package names and the 12049 current set of packages in debugging mode. C<o debug> has built-in 12050 completion support. 12051 12052 For debugging of CPAN data there is the C<dump> command which takes 12053 the same arguments as make/test/install and outputs each object's 12054 Data::Dumper dump. If an argument looks like a perl variable and 12055 contains one of C<$>, C<@> or C<%>, it is eval()ed and fed to 12056 Data::Dumper directly. 12057 12058 =head2 Floppy, Zip, Offline Mode 12059 12060 CPAN.pm works nicely without network too. If you maintain machines 12061 that are not networked at all, you should consider working with file: 12062 URLs. Of course, you have to collect your modules somewhere first. So 12063 you might use CPAN.pm to put together all you need on a networked 12064 machine. Then copy the $CPAN::Config->{keep_source_where} (but not 12065 $CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind 12066 of a personal CPAN. CPAN.pm on the non-networked machines works nicely 12067 with this floppy. See also below the paragraph about CD-ROM support. 12068 12069 =head2 Basic Utilities for Programmers 12070 12071 =over 2 12072 12073 =item has_inst($module) 12074 12075 Returns true if the module is installed. Used to load all modules into 12076 the running CPAN.pm which are considered optional. The config variable 12077 C<dontload_list> can be used to intercept the C<has_inst()> call such 12078 that an optional module is not loaded despite being available. For 12079 example the following command will prevent that C<YAML.pm> is being 12080 loaded: 12081 12082 cpan> o conf dontload_list push YAML 12083 12084 See the source for details. 12085 12086 =item has_usable($module) 12087 12088 Returns true if the module is installed and is in a usable state. Only 12089 useful for a handful of modules that are used internally. See the 12090 source for details. 12091 12092 =item instance($module) 12093 12094 The constructor for all the singletons used to represent modules, 12095 distributions, authors and bundles. If the object already exists, this 12096 method returns the object, otherwise it calls the constructor. 12097 12098 =back 12099 12100 =head1 SECURITY 12101 12102 There's no strong security layer in CPAN.pm. CPAN.pm helps you to 12103 install foreign, unmasked, unsigned code on your machine. We compare 12104 to a checksum that comes from the net just as the distribution file 12105 itself. But we try to make it easy to add security on demand: 12106 12107 =head2 Cryptographically signed modules 12108 12109 Since release 1.77 CPAN.pm has been able to verify cryptographically 12110 signed module distributions using Module::Signature. The CPAN modules 12111 can be signed by their authors, thus giving more security. The simple 12112 unsigned MD5 checksums that were used before by CPAN protect mainly 12113 against accidental file corruption. 12114 12115 You will need to have Module::Signature installed, which in turn 12116 requires that you have at least one of Crypt::OpenPGP module or the 12117 command-line F<gpg> tool installed. 12118 12119 You will also need to be able to connect over the Internet to the public 12120 keyservers, like pgp.mit.edu, and their port 11731 (the HKP protocol). 12121 12122 The configuration parameter check_sigs is there to turn signature 12123 checking on or off. 12124 12125 =head1 EXPORT 12126 12127 Most functions in package CPAN are exported per default. The reason 12128 for this is that the primary use is intended for the cpan shell or for 12129 one-liners. 12130 12131 =head1 ENVIRONMENT 12132 12133 When the CPAN shell enters a subshell via the look command, it sets 12134 the environment CPAN_SHELL_LEVEL to 1 or increments it if it is 12135 already set. 12136 12137 When CPAN runs, it sets the environment variable PERL5_CPAN_IS_RUNNING 12138 to the ID of the running process. It also sets 12139 PERL5_CPANPLUS_IS_RUNNING to prevent runaway processes which could 12140 happen with older versions of Module::Install. 12141 12142 When running C<perl Makefile.PL>, the environment variable 12143 C<PERL5_CPAN_IS_EXECUTING> is set to the full path of the 12144 C<Makefile.PL> that is being executed. This prevents runaway processes 12145 with newer versions of Module::Install. 12146 12147 When the config variable ftp_passive is set, all downloads will be run 12148 with the environment variable FTP_PASSIVE set to this value. This is 12149 in general a good idea as it influences both Net::FTP and LWP based 12150 connections. The same effect can be achieved by starting the cpan 12151 shell with this environment variable set. For Net::FTP alone, one can 12152 also always set passive mode by running libnetcfg. 12153 12154 =head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES 12155 12156 Populating a freshly installed perl with my favorite modules is pretty 12157 easy if you maintain a private bundle definition file. To get a useful 12158 blueprint of a bundle definition file, the command autobundle can be used 12159 on the CPAN shell command line. This command writes a bundle definition 12160 file for all modules that are installed for the currently running perl 12161 interpreter. It's recommended to run this command only once and from then 12162 on maintain the file manually under a private name, say 12163 Bundle/my_bundle.pm. With a clever bundle file you can then simply say 12164 12165 cpan> install Bundle::my_bundle 12166 12167 then answer a few questions and then go out for a coffee. 12168 12169 Maintaining a bundle definition file means keeping track of two 12170 things: dependencies and interactivity. CPAN.pm sometimes fails on 12171 calculating dependencies because not all modules define all MakeMaker 12172 attributes correctly, so a bundle definition file should specify 12173 prerequisites as early as possible. On the other hand, it's a bit 12174 annoying that many distributions need some interactive configuring. So 12175 what I try to accomplish in my private bundle file is to have the 12176 packages that need to be configured early in the file and the gentle 12177 ones later, so I can go out after a few minutes and leave CPAN.pm 12178 untended. 12179 12180 =head1 WORKING WITH CPAN.pm BEHIND FIREWALLS 12181 12182 Thanks to Graham Barr for contributing the following paragraphs about 12183 the interaction between perl, and various firewall configurations. For 12184 further information on firewalls, it is recommended to consult the 12185 documentation that comes with the ncftp program. If you are unable to 12186 go through the firewall with a simple Perl setup, it is very likely 12187 that you can configure ncftp so that it works for your firewall. 12188 12189 =head2 Three basic types of firewalls 12190 12191 Firewalls can be categorized into three basic types. 12192 12193 =over 4 12194 12195 =item http firewall 12196 12197 This is where the firewall machine runs a web server and to access the 12198 outside world you must do it via the web server. If you set environment 12199 variables like http_proxy or ftp_proxy to a values beginning with http:// 12200 or in your web browser you have to set proxy information then you know 12201 you are running an http firewall. 12202 12203 To access servers outside these types of firewalls with perl (even for 12204 ftp) you will need to use LWP. 12205 12206 =item ftp firewall 12207 12208 This where the firewall machine runs an ftp server. This kind of 12209 firewall will only let you access ftp servers outside the firewall. 12210 This is usually done by connecting to the firewall with ftp, then 12211 entering a username like "user@outside.host.com" 12212 12213 To access servers outside these type of firewalls with perl you 12214 will need to use Net::FTP. 12215 12216 =item One way visibility 12217 12218 I say one way visibility as these firewalls try to make themselves look 12219 invisible to the users inside the firewall. An FTP data connection is 12220 normally created by sending the remote server your IP address and then 12221 listening for the connection. But the remote server will not be able to 12222 connect to you because of the firewall. So for these types of firewall 12223 FTP connections need to be done in a passive mode. 12224 12225 There are two that I can think off. 12226 12227 =over 4 12228 12229 =item SOCKS 12230 12231 If you are using a SOCKS firewall you will need to compile perl and link 12232 it with the SOCKS library, this is what is normally called a 'socksified' 12233 perl. With this executable you will be able to connect to servers outside 12234 the firewall as if it is not there. 12235 12236 =item IP Masquerade 12237 12238 This is the firewall implemented in the Linux kernel, it allows you to 12239 hide a complete network behind one IP address. With this firewall no 12240 special compiling is needed as you can access hosts directly. 12241 12242 For accessing ftp servers behind such firewalls you usually need to 12243 set the environment variable C<FTP_PASSIVE> or the config variable 12244 ftp_passive to a true value. 12245 12246 =back 12247 12248 =back 12249 12250 =head2 Configuring lynx or ncftp for going through a firewall 12251 12252 If you can go through your firewall with e.g. lynx, presumably with a 12253 command such as 12254 12255 /usr/local/bin/lynx -pscott:tiger 12256 12257 then you would configure CPAN.pm with the command 12258 12259 o conf lynx "/usr/local/bin/lynx -pscott:tiger" 12260 12261 That's all. Similarly for ncftp or ftp, you would configure something 12262 like 12263 12264 o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg" 12265 12266 Your mileage may vary... 12267 12268 =head1 FAQ 12269 12270 =over 4 12271 12272 =item 1) 12273 12274 I installed a new version of module X but CPAN keeps saying, 12275 I have the old version installed 12276 12277 Most probably you B<do> have the old version installed. This can 12278 happen if a module installs itself into a different directory in the 12279 @INC path than it was previously installed. This is not really a 12280 CPAN.pm problem, you would have the same problem when installing the 12281 module manually. The easiest way to prevent this behaviour is to add 12282 the argument C<UNINST=1> to the C<make install> call, and that is why 12283 many people add this argument permanently by configuring 12284 12285 o conf make_install_arg UNINST=1 12286 12287 =item 2) 12288 12289 So why is UNINST=1 not the default? 12290 12291 Because there are people who have their precise expectations about who 12292 may install where in the @INC path and who uses which @INC array. In 12293 fine tuned environments C<UNINST=1> can cause damage. 12294 12295 =item 3) 12296 12297 I want to clean up my mess, and install a new perl along with 12298 all modules I have. How do I go about it? 12299 12300 Run the autobundle command for your old perl and optionally rename the 12301 resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl 12302 with the Configure option prefix, e.g. 12303 12304 ./Configure -Dprefix=/usr/local/perl-5.6.78.9 12305 12306 Install the bundle file you produced in the first step with something like 12307 12308 cpan> install Bundle::mybundle 12309 12310 and you're done. 12311 12312 =item 4) 12313 12314 When I install bundles or multiple modules with one command 12315 there is too much output to keep track of. 12316 12317 You may want to configure something like 12318 12319 o conf make_arg "| tee -ai /root/.cpan/logs/make.out" 12320 o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out" 12321 12322 so that STDOUT is captured in a file for later inspection. 12323 12324 12325 =item 5) 12326 12327 I am not root, how can I install a module in a personal directory? 12328 12329 First of all, you will want to use your own configuration, not the one 12330 that your root user installed. If you do not have permission to write 12331 in the cpan directory that root has configured, you will be asked if 12332 you want to create your own config. Answering "yes" will bring you into 12333 CPAN's configuration stage, using the system config for all defaults except 12334 things that have to do with CPAN's work directory, saving your choices to 12335 your MyConfig.pm file. 12336 12337 You can also manually initiate this process with the following command: 12338 12339 % perl -MCPAN -e 'mkmyconfig' 12340 12341 or by running 12342 12343 mkmyconfig 12344 12345 from the CPAN shell. 12346 12347 You will most probably also want to configure something like this: 12348 12349 o conf makepl_arg "LIB=~/myperl/lib \ 12350 INSTALLMAN1DIR=~/myperl/man/man1 \ 12351 INSTALLMAN3DIR=~/myperl/man/man3 \ 12352 INSTALLSCRIPT=~/myperl/bin \ 12353 INSTALLBIN=~/myperl/bin" 12354 12355 and then (oh joy) the equivalent command for Module::Build. That would 12356 be 12357 12358 o conf mbuildpl_arg "--lib=~/myperl/lib \ 12359 --installman1dir=~/myperl/man/man1 \ 12360 --installman3dir=~/myperl/man/man3 \ 12361 --installscript=~/myperl/bin \ 12362 --installbin=~/myperl/bin" 12363 12364 You can make this setting permanent like all C<o conf> settings with 12365 C<o conf commit> or by setting C<auto_commit> beforehand. 12366 12367 You will have to add ~/myperl/man to the MANPATH environment variable 12368 and also tell your perl programs to look into ~/myperl/lib, e.g. by 12369 including 12370 12371 use lib "$ENV{HOME}/myperl/lib"; 12372 12373 or setting the PERL5LIB environment variable. 12374 12375 While we're speaking about $ENV{HOME}, it might be worth mentioning, 12376 that for Windows we use the File::HomeDir module that provides an 12377 equivalent to the concept of the home directory on Unix. 12378 12379 Another thing you should bear in mind is that the UNINST parameter can 12380 be dangerous when you are installing into a private area because you 12381 might accidentally remove modules that other people depend on that are 12382 not using the private area. 12383 12384 =item 6) 12385 12386 How to get a package, unwrap it, and make a change before building it? 12387 12388 Have a look at the C<look> (!) command. 12389 12390 =item 7) 12391 12392 I installed a Bundle and had a couple of fails. When I 12393 retried, everything resolved nicely. Can this be fixed to work 12394 on first try? 12395 12396 The reason for this is that CPAN does not know the dependencies of all 12397 modules when it starts out. To decide about the additional items to 12398 install, it just uses data found in the META.yml file or the generated 12399 Makefile. An undetected missing piece breaks the process. But it may 12400 well be that your Bundle installs some prerequisite later than some 12401 depending item and thus your second try is able to resolve everything. 12402 Please note, CPAN.pm does not know the dependency tree in advance and 12403 cannot sort the queue of things to install in a topologically correct 12404 order. It resolves perfectly well IF all modules declare the 12405 prerequisites correctly with the PREREQ_PM attribute to MakeMaker or 12406 the C<requires> stanza of Module::Build. For bundles which fail and 12407 you need to install often, it is recommended to sort the Bundle 12408 definition file manually. 12409 12410 =item 8) 12411 12412 In our intranet we have many modules for internal use. How 12413 can I integrate these modules with CPAN.pm but without uploading 12414 the modules to CPAN? 12415 12416 Have a look at the CPAN::Site module. 12417 12418 =item 9) 12419 12420 When I run CPAN's shell, I get an error message about things in my 12421 /etc/inputrc (or ~/.inputrc) file. 12422 12423 These are readline issues and can only be fixed by studying readline 12424 configuration on your architecture and adjusting the referenced file 12425 accordingly. Please make a backup of the /etc/inputrc or ~/.inputrc 12426 and edit them. Quite often harmless changes like uppercasing or 12427 lowercasing some arguments solves the problem. 12428 12429 =item 10) 12430 12431 Some authors have strange characters in their names. 12432 12433 Internally CPAN.pm uses the UTF-8 charset. If your terminal is 12434 expecting ISO-8859-1 charset, a converter can be activated by setting 12435 term_is_latin to a true value in your config file. One way of doing so 12436 would be 12437 12438 cpan> o conf term_is_latin 1 12439 12440 If other charset support is needed, please file a bugreport against 12441 CPAN.pm at rt.cpan.org and describe your needs. Maybe we can extend 12442 the support or maybe UTF-8 terminals become widely available. 12443 12444 Note: this config variable is deprecated and will be removed in a 12445 future version of CPAN.pm. It will be replaced with the conventions 12446 around the family of $LANG and $LC_* environment variables. 12447 12448 =item 11) 12449 12450 When an install fails for some reason and then I correct the error 12451 condition and retry, CPAN.pm refuses to install the module, saying 12452 C<Already tried without success>. 12453 12454 Use the force pragma like so 12455 12456 force install Foo::Bar 12457 12458 Or you can use 12459 12460 look Foo::Bar 12461 12462 and then 'make install' directly in the subshell. 12463 12464 =item 12) 12465 12466 How do I install a "DEVELOPER RELEASE" of a module? 12467 12468 By default, CPAN will install the latest non-developer release of a 12469 module. If you want to install a dev release, you have to specify the 12470 partial path starting with the author id to the tarball you wish to 12471 install, like so: 12472 12473 cpan> install KWILLIAMS/Module-Build-0.27_07.tar.gz 12474 12475 Note that you can use the C<ls> command to get this path listed. 12476 12477 =item 13) 12478 12479 How do I install a module and all its dependencies from the commandline, 12480 without being prompted for anything, despite my CPAN configuration 12481 (or lack thereof)? 12482 12483 CPAN uses ExtUtils::MakeMaker's prompt() function to ask its questions, so 12484 if you set the PERL_MM_USE_DEFAULT environment variable, you shouldn't be 12485 asked any questions at all (assuming the modules you are installing are 12486 nice about obeying that variable as well): 12487 12488 % PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install My::Module' 12489 12490 =item 14) 12491 12492 How do I create a Module::Build based Build.PL derived from an 12493 ExtUtils::MakeMaker focused Makefile.PL? 12494 12495 http://search.cpan.org/search?query=Module::Build::Convert 12496 12497 http://www.refcnt.org/papers/module-build-convert 12498 12499 =item 15) 12500 12501 What's the best CPAN site for me? 12502 12503 The urllist config parameter is yours. You can add and remove sites at 12504 will. You should find out which sites have the best uptodateness, 12505 bandwidth, reliability, etc. and are topologically close to you. Some 12506 people prefer fast downloads, others uptodateness, others reliability. 12507 You decide which to try in which order. 12508 12509 Henk P. Penning maintains a site that collects data about CPAN sites: 12510 12511 http://www.cs.uu.nl/people/henkp/mirmon/cpan.html 12512 12513 =item 16) 12514 12515 Why do I get asked the same questions every time I start the shell? 12516 12517 You can make your configuration changes permanent by calling the 12518 command C<o conf commit>. Alternatively set the C<auto_commit> 12519 variable to true by running C<o conf init auto_commit> and answering 12520 the following question with yes. 12521 12522 =back 12523 12524 =head1 COMPATIBILITY 12525 12526 =head2 OLD PERL VERSIONS 12527 12528 CPAN.pm is regularly tested to run under 5.004, 5.005, and assorted 12529 newer versions. It is getting more and more difficult to get the 12530 minimal prerequisites working on older perls. It is close to 12531 impossible to get the whole Bundle::CPAN working there. If you're in 12532 the position to have only these old versions, be advised that CPAN is 12533 designed to work fine without the Bundle::CPAN installed. 12534 12535 To get things going, note that GBARR/Scalar-List-Utils-1.18.tar.gz is 12536 compatible with ancient perls and that File::Temp is listed as a 12537 prerequisite but CPAN has reasonable workarounds if it is missing. 12538 12539 =head2 CPANPLUS 12540 12541 This module and its competitor, the CPANPLUS module, are both much 12542 cooler than the other. CPAN.pm is older. CPANPLUS was designed to be 12543 more modular but it was never tried to make it compatible with CPAN.pm. 12544 12545 =head1 SECURITY ADVICE 12546 12547 This software enables you to upgrade software on your computer and so 12548 is inherently dangerous because the newly installed software may 12549 contain bugs and may alter the way your computer works or even make it 12550 unusable. Please consider backing up your data before every upgrade. 12551 12552 =head1 BUGS 12553 12554 Please report bugs via L<http://rt.cpan.org/> 12555 12556 Before submitting a bug, please make sure that the traditional method 12557 of building a Perl module package from a shell by following the 12558 installation instructions of that package still works in your 12559 environment. 12560 12561 =head1 AUTHOR 12562 12563 Andreas Koenig C<< <andk@cpan.org> >> 12564 12565 =head1 LICENSE 12566 12567 This program is free software; you can redistribute it and/or 12568 modify it under the same terms as Perl itself. 12569 12570 See L<http://www.perl.com/perl/misc/Artistic.html> 12571 12572 =head1 TRANSLATIONS 12573 12574 Kawai,Takanori provides a Japanese translation of this manpage at 12575 L<http://homepage3.nifty.com/hippo2000/perltips/CPAN.htm> 12576 12577 =head1 SEE ALSO 12578 12579 L<cpan>, L<CPAN::Nox>, L<CPAN::Version> 12580 12581 =cut 12582 12583
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |