1package ExtUtils::Install; 2use strict; 3 4use Config qw(%Config); 5use Cwd qw(cwd); 6use Exporter (); 7use File::Basename qw(dirname); 8use File::Copy; 9use File::Path; 10use File::Spec; 11 12our @ISA = ('Exporter'); 13our @EXPORT = ('install','uninstall','pm_to_blib', 'install_default'); 14 15our $MUST_REBOOT; 16 17=pod 18 19=head1 NAME 20 21ExtUtils::Install - install files from here to there 22 23=head1 SYNOPSIS 24 25 use ExtUtils::Install; 26 27 install({ 'blib/lib' => 'some/install/dir' } ); 28 29 uninstall($packlist); 30 31 pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' }); 32 33=head1 VERSION 34 352.14 36 37=cut 38 39our $VERSION = '2.14'; # <-- do not forget to update the POD section just above this line! 40$VERSION = eval $VERSION; 41 42=pod 43 44=head1 DESCRIPTION 45 46Handles the installing and uninstalling of perl modules, scripts, man 47pages, etc... 48 49Both install() and uninstall() are specific to the way 50ExtUtils::MakeMaker handles the installation and deinstallation of 51perl modules. They are not designed as general purpose tools. 52 53On some operating systems such as Win32 installation may not be possible 54until after a reboot has occurred. This can have varying consequences: 55removing an old DLL does not impact programs using the new one, but if 56a new DLL cannot be installed properly until reboot then anything 57depending on it must wait. The package variable 58 59 $ExtUtils::Install::MUST_REBOOT 60 61is used to store this status. 62 63If this variable is true then such an operation has occurred and 64anything depending on this module cannot proceed until a reboot 65has occurred. 66 67If this value is defined but false then such an operation has 68ocurred, but should not impact later operations. 69 70=over 71 72=begin _private 73 74=item _chmod($$;$) 75 76Wrapper to chmod() for debugging and error trapping. 77 78=item _warnonce(@) 79 80Warns about something only once. 81 82=item _choke(@) 83 84Dies with a special message. 85 86=back 87 88=end _private 89 90=cut 91 92BEGIN { 93 *Is_VMS = $^O eq 'VMS' ? sub(){1} : sub(){0}; 94 *Is_Win32 = $^O eq 'MSWin32' ? sub(){1} : sub(){0}; 95 *Is_cygwin = $^O eq 'cygwin' ? sub(){1} : sub(){0}; 96 *CanMoveAtBoot = ($^O eq 'MSWin32' || $^O eq 'cygwin') ? sub(){1} : sub(){0}; 97} 98 99my $Inc_uninstall_warn_handler; 100 101# install relative to here 102 103my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT}; 104my $INSTALL_QUIET = $ENV{PERL_INSTALL_QUIET}; 105$INSTALL_QUIET = 1 106 if (!exists $ENV{PERL_INSTALL_QUIET} and 107 defined $ENV{MAKEFLAGS} and 108 $ENV{MAKEFLAGS} =~ /\b(s|silent|quiet)\b/); 109 110my $Curdir = File::Spec->curdir; 111my $Perm_Dir = $ENV{PERL_CORE} ? 0770 : 0755; 112 113sub _estr(@) { 114 return join "\n",'!' x 72,@_,'!' x 72,''; 115} 116 117{my %warned; 118sub _warnonce(@) { 119 my $first=shift; 120 my $msg=_estr "WARNING: $first",@_; 121 warn $msg unless $warned{$msg}++; 122}} 123 124sub _choke(@) { 125 my $first=shift; 126 my $msg=_estr "ERROR: $first",@_; 127 require Carp; 128 Carp::croak($msg); 129} 130 131sub _croak { 132 require Carp; 133 Carp::croak(@_); 134} 135sub _confess { 136 require Carp; 137 Carp::confess(@_); 138} 139 140sub _compare { 141 require File::Compare; 142 File::Compare::compare(@_); 143} 144 145 146sub _chmod($$;$) { 147 my ( $mode, $item, $verbose )=@_; 148 $verbose ||= 0; 149 if (chmod $mode, $item) { 150 printf "chmod(0%o, %s)\n",$mode, $item if $verbose > 1; 151 } else { 152 my $err="$!"; 153 _warnonce sprintf "WARNING: Failed chmod(0%o, %s): %s\n", 154 $mode, $item, $err 155 if -e $item; 156 } 157} 158 159=begin _private 160 161=over 162 163=item _move_file_at_boot( $file, $target, $moan ) 164 165OS-Specific, Win32/Cygwin 166 167Schedules a file to be moved/renamed/deleted at next boot. 168$file should be a filespec of an existing file 169$target should be a ref to an array if the file is to be deleted 170otherwise it should be a filespec for a rename. If the file is existing 171it will be replaced. 172 173Sets $MUST_REBOOT to 0 to indicate a deletion operation has occurred 174and sets it to 1 to indicate that a move operation has been requested. 175 176returns 1 on success, on failure if $moan is false errors are fatal. 177If $moan is true then returns 0 on error and warns instead of dies. 178 179=end _private 180 181=cut 182 183{ 184 my $Has_Win32API_File; 185 sub _move_file_at_boot { #XXX OS-SPECIFIC 186 my ( $file, $target, $moan )= @_; 187 _confess("Panic: Can't _move_file_at_boot on this platform!") 188 unless CanMoveAtBoot; 189 190 my $descr= ref $target 191 ? "'$file' for deletion" 192 : "'$file' for installation as '$target'"; 193 194 # *note* CanMoveAtBoot is only incidentally the same condition as below 195 # this needs not hold true in the future. 196 $Has_Win32API_File = (Is_Win32 || Is_cygwin) 197 ? (eval {require Win32API::File; 1} || 0) 198 : 0 unless defined $Has_Win32API_File; 199 if ( ! $Has_Win32API_File ) { 200 201 my @msg=( 202 "Cannot schedule $descr at reboot.", 203 "Try installing Win32API::File to allow operations on locked files", 204 "to be scheduled during reboot. Or try to perform the operation by", 205 "hand yourself. (You may need to close other perl processes first)" 206 ); 207 if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) } 208 return 0; 209 } 210 my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT(); 211 $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING() 212 unless ref $target; 213 214 _chmod( 0666, $file ); 215 _chmod( 0666, $target ) unless ref $target; 216 217 if (Win32API::File::MoveFileEx( $file, $target, $opts )) { 218 $MUST_REBOOT ||= ref $target ? 0 : 1; 219 return 1; 220 } else { 221 my @msg=( 222 "MoveFileEx $descr at reboot failed: $^E", 223 "You may try to perform the operation by hand yourself. ", 224 "(You may need to close other perl processes first).", 225 ); 226 if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) } 227 } 228 return 0; 229 } 230} 231 232 233=begin _private 234 235 236=item _unlink_or_rename( $file, $tryhard, $installing ) 237 238OS-Specific, Win32/Cygwin 239 240Tries to get a file out of the way by unlinking it or renaming it. On 241some OS'es (Win32 based) DLL files can end up locked such that they can 242be renamed but not deleted. Likewise sometimes a file can be locked such 243that it cant even be renamed or changed except at reboot. To handle 244these cases this routine finds a tempfile name that it can either rename 245the file out of the way or use as a proxy for the install so that the 246rename can happen later (at reboot). 247 248 $file : the file to remove. 249 $tryhard : should advanced tricks be used for deletion 250 $installing : we are not merely deleting but we want to overwrite 251 252When $tryhard is not true if the unlink fails its fatal. When $tryhard 253is true then the file is attempted to be renamed. The renamed file is 254then scheduled for deletion. If the rename fails then $installing 255governs what happens. If it is false the failure is fatal. If it is true 256then an attempt is made to schedule installation at boot using a 257temporary file to hold the new file. If this fails then a fatal error is 258thrown, if it succeeds it returns the temporary file name (which will be 259a derivative of the original in the same directory) so that the caller can 260use it to install under. In all other cases of success returns $file. 261On failure throws a fatal error. 262 263=end _private 264 265=cut 266 267 268 269sub _unlink_or_rename { #XXX OS-SPECIFIC 270 my ( $file, $tryhard, $installing )= @_; 271 272 # this chmod was originally unconditional. However, its not needed on 273 # POSIXy systems since permission to unlink a file is specified by the 274 # directory rather than the file; and in fact it screwed up hard- and 275 # symlinked files. Keep it for other platforms in case its still 276 # needed there. 277 if ($^O =~ /^(dos|os2|MSWin32|VMS)$/) { 278 _chmod( 0666, $file ); 279 } 280 my $unlink_count = 0; 281 while (unlink $file) { $unlink_count++; } 282 return $file if $unlink_count > 0; 283 my $error="$!"; 284 285 _choke("Cannot unlink '$file': $!") 286 unless CanMoveAtBoot && $tryhard; 287 288 my $tmp= "AAA"; 289 ++$tmp while -e "$file.$tmp"; 290 $tmp= "$file.$tmp"; 291 292 warn "WARNING: Unable to unlink '$file': $error\n", 293 "Going to try to rename it to '$tmp'.\n"; 294 295 if ( rename $file, $tmp ) { 296 warn "Rename successful. Scheduling '$tmp'\nfor deletion at reboot.\n"; 297 # when $installing we can set $moan to true. 298 # IOW, if we cant delete the renamed file at reboot its 299 # not the end of the world. The other cases are more serious 300 # and need to be fatal. 301 _move_file_at_boot( $tmp, [], $installing ); 302 return $file; 303 } elsif ( $installing ) { 304 _warnonce("Rename failed: $!. Scheduling '$tmp'\nfor". 305 " installation as '$file' at reboot.\n"); 306 _move_file_at_boot( $tmp, $file ); 307 return $tmp; 308 } else { 309 _choke("Rename failed:$!", "Cannot proceed."); 310 } 311 312} 313 314 315=pod 316 317=back 318 319=head2 Functions 320 321=begin _private 322 323=over 324 325=item _get_install_skip 326 327Handles loading the INSTALL.SKIP file. Returns an array of patterns to use. 328 329=cut 330 331 332 333sub _get_install_skip { 334 my ( $skip, $verbose )= @_; 335 if ($ENV{EU_INSTALL_IGNORE_SKIP}) { 336 print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n" 337 if $verbose>2; 338 return []; 339 } 340 if ( ! defined $skip ) { 341 print "Looking for install skip list\n" 342 if $verbose>2; 343 for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) { 344 next unless $file; 345 print "\tChecking for $file\n" 346 if $verbose>2; 347 if (-e $file) { 348 $skip= $file; 349 last; 350 } 351 } 352 } 353 if ($skip && !ref $skip) { 354 print "Reading skip patterns from '$skip'.\n" 355 if $verbose; 356 if (open my $fh,$skip ) { 357 my @patterns; 358 while (<$fh>) { 359 chomp; 360 next if /^\s*(?:#|$)/; 361 print "\tSkip pattern: $_\n" if $verbose>3; 362 push @patterns, $_; 363 } 364 $skip= \@patterns; 365 } else { 366 warn "Can't read skip file:'$skip':$!\n"; 367 $skip=[]; 368 } 369 } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) { 370 print "Using array for skip list\n" 371 if $verbose>2; 372 } elsif ($verbose) { 373 print "No skip list found.\n" 374 if $verbose>1; 375 $skip= []; 376 } 377 warn "Got @{[0+@$skip]} skip patterns.\n" 378 if $verbose>3; 379 return $skip 380} 381 382=pod 383 384=item _have_write_access 385 386Abstract a -w check that tries to use POSIX::access() if possible. 387 388=cut 389 390{ 391 my $has_posix; 392 sub _have_write_access { 393 my $dir=shift; 394 unless (defined $has_posix) { 395 $has_posix = (!Is_cygwin && !Is_Win32 396 && eval { local $^W; require POSIX; 1} ) || 0; 397 } 398 if ($has_posix) { 399 return POSIX::access($dir, POSIX::W_OK()); 400 } else { 401 return -w $dir; 402 } 403 } 404} 405 406=pod 407 408=item _can_write_dir(C<$dir>) 409 410Checks whether a given directory is writable, taking account 411the possibility that the directory might not exist and would have to 412be created first. 413 414Returns a list, containing: C<($writable, $determined_by, @create)> 415 416C<$writable> says whether the directory is (hypothetically) writable 417 418C<$determined_by> is the directory the status was determined from. It will be 419either the C<$dir>, or one of its parents. 420 421C<@create> is a list of directories that would probably have to be created 422to make the requested directory. It may not actually be correct on 423relative paths with C<..> in them. But for our purposes it should work ok 424 425=cut 426 427 428sub _can_write_dir { 429 my $dir=shift; 430 return 431 unless defined $dir and length $dir; 432 433 my ($vol, $dirs, $file) = File::Spec->splitpath($dir,1); 434 my @dirs = File::Spec->splitdir($dirs); 435 unshift @dirs, File::Spec->curdir 436 unless File::Spec->file_name_is_absolute($dir); 437 438 my $path=''; 439 my @make; 440 while (@dirs) { 441 if (Is_VMS) { 442 $dir = File::Spec->catdir($vol,@dirs); 443 } 444 else { 445 $dir = File::Spec->catdir(@dirs); 446 $dir = File::Spec->catpath($vol,$dir,'') 447 if defined $vol and length $vol; 448 } 449 next if ( $dir eq $path ); 450 if ( ! -e $dir ) { 451 unshift @make,$dir; 452 next; 453 } 454 if ( _have_write_access($dir) ) { 455 return 1,$dir,@make 456 } else { 457 return 0,$dir,@make 458 } 459 } continue { 460 pop @dirs; 461 } 462 return 0; 463} 464 465=pod 466 467=item _mkpath($dir,$show,$mode,$verbose,$dry_run) 468 469Wrapper around File::Path::mkpath() to handle errors. 470 471If $verbose is true and >1 then additional diagnostics will be produced, also 472this will force $show to true. 473 474If $dry_run is true then the directory will not be created but a check will be 475made to see whether it would be possible to write to the directory, or that 476it would be possible to create the directory. 477 478If $dry_run is not true dies if the directory can not be created or is not 479writable. 480 481=cut 482 483sub _mkpath { 484 my ($dir,$show,$mode,$verbose,$dry_run)=@_; 485 if ( $verbose && $verbose > 1 && ! -d $dir) { 486 $show= 1; 487 printf "mkpath(%s,%d,%#o)\n", $dir, $show, $mode; 488 } 489 if (!$dry_run) { 490 if ( ! eval { File::Path::mkpath($dir,$show,$mode); 1 } ) { 491 _choke("Can't create '$dir'","$@"); 492 } 493 494 } 495 my ($can,$root,@make)=_can_write_dir($dir); 496 if (!$can) { 497 my @msg=( 498 "Can't create '$dir'", 499 $root ? "Do not have write permissions on '$root'" 500 : "Unknown Error" 501 ); 502 if ($dry_run) { 503 _warnonce @msg; 504 } else { 505 _choke @msg; 506 } 507 } elsif ($show and $dry_run) { 508 print "$_\n" for @make; 509 } 510 511} 512 513=pod 514 515=item _copy($from,$to,$verbose,$dry_run) 516 517Wrapper around File::Copy::copy to handle errors. 518 519If $verbose is true and >1 then additional diagnostics will be emitted. 520 521If $dry_run is true then the copy will not actually occur. 522 523Dies if the copy fails. 524 525=cut 526 527 528sub _copy { 529 my ( $from, $to, $verbose, $dry_run)=@_; 530 if ($verbose && $verbose>1) { 531 printf "copy(%s,%s)\n", $from, $to; 532 } 533 if (!$dry_run) { 534 File::Copy::copy($from,$to) 535 or _croak( _estr "ERROR: Cannot copy '$from' to '$to': $!" ); 536 } 537} 538 539=pod 540 541=item _chdir($from) 542 543Wrapper around chdir to catch errors. 544 545If not called in void context returns the cwd from before the chdir. 546 547dies on error. 548 549=cut 550 551sub _chdir { 552 my ($dir)= @_; 553 my $ret; 554 if (defined wantarray) { 555 $ret= cwd; 556 } 557 chdir $dir 558 or _choke("Couldn't chdir to '$dir': $!"); 559 return $ret; 560} 561 562=pod 563 564=back 565 566=end _private 567 568=over 569 570=item B<install> 571 572 # deprecated forms 573 install(\%from_to); 574 install(\%from_to, $verbose, $dry_run, $uninstall_shadows, 575 $skip, $always_copy, \%result); 576 577 # recommended form as of 1.47 578 install([ 579 from_to => \%from_to, 580 verbose => 1, 581 dry_run => 0, 582 uninstall_shadows => 1, 583 skip => undef, 584 always_copy => 1, 585 result => \%install_results, 586 ]); 587 588 589Copies each directory tree of %from_to to its corresponding value 590preserving timestamps and permissions. 591 592There are two keys with a special meaning in the hash: "read" and 593"write". These contain packlist files. After the copying is done, 594install() will write the list of target files to $from_to{write}. If 595$from_to{read} is given the contents of this file will be merged into 596the written file. The read and the written file may be identical, but 597on AFS it is quite likely that people are installing to a different 598directory than the one where the files later appear. 599 600If $verbose is true, will print out each file removed. Default is 601false. This is "make install VERBINST=1". $verbose values going 602up to 5 show increasingly more diagnostics output. 603 604If $dry_run is true it will only print what it was going to do 605without actually doing it. Default is false. 606 607If $uninstall_shadows is true any differing versions throughout @INC 608will be uninstalled. This is "make install UNINST=1" 609 610As of 1.37_02 install() supports the use of a list of patterns to filter out 611files that shouldn't be installed. If $skip is omitted or undefined then 612install will try to read the list from INSTALL.SKIP in the CWD. This file is 613a list of regular expressions and is just like the MANIFEST.SKIP file used 614by L<ExtUtils::Manifest>. 615 616A default site INSTALL.SKIP may be provided by setting then environment 617variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there isn't a 618distribution specific INSTALL.SKIP. If the environment variable 619EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be 620performed. 621 622If $skip is undefined then the skip file will be autodetected and used if it 623is found. If $skip is a reference to an array then it is assumed the array 624contains the list of patterns, if $skip is a true non reference it is 625assumed to be the filename holding the list of patterns, any other value of 626$skip is taken to mean that no install filtering should occur. 627 628B<Changes As of Version 1.47> 629 630As of version 1.47 the following additions were made to the install interface. 631Note that the new argument style and use of the %result hash is recommended. 632 633The $always_copy parameter which when true causes files to be updated 634regardless as to whether they have changed, if it is defined but false then 635copies are made only if the files have changed, if it is undefined then the 636value of the environment variable EU_INSTALL_ALWAYS_COPY is used as default. 637 638The %result hash will be populated with the various keys/subhashes reflecting 639the install. Currently these keys and their structure are: 640 641 install => { $target => $source }, 642 install_fail => { $target => $source }, 643 install_unchanged => { $target => $source }, 644 645 install_filtered => { $source => $pattern }, 646 647 uninstall => { $uninstalled => $source }, 648 uninstall_fail => { $uninstalled => $source }, 649 650where C<$source> is the filespec of the file being installed. C<$target> is where 651it is being installed to, and C<$uninstalled> is any shadow file that is in C<@INC> 652or C<$ENV{PERL5LIB}> or other standard locations, and C<$pattern> is the pattern that 653caused a source file to be skipped. In future more keys will be added, such as to 654show created directories, however this requires changes in other modules and must 655therefore wait. 656 657These keys will be populated before any exceptions are thrown should there be an 658error. 659 660Note that all updates of the %result are additive, the hash will not be 661cleared before use, thus allowing status results of many installs to be easily 662aggregated. 663 664B<NEW ARGUMENT STYLE> 665 666If there is only one argument and it is a reference to an array then 667the array is assumed to contain a list of key-value pairs specifying 668the options. In this case the option "from_to" is mandatory. This style 669means that you do not have to supply a cryptic list of arguments and can 670use a self documenting argument list that is easier to understand. 671 672This is now the recommended interface to install(). 673 674B<RETURN> 675 676If all actions were successful install will return a hashref of the results 677as described above for the $result parameter. If any action is a failure 678then install will die, therefore it is recommended to pass in the $result 679parameter instead of using the return value. If the result parameter is 680provided then the returned hashref will be the passed in hashref. 681 682=cut 683 684sub install { #XXX OS-SPECIFIC 685 my($from_to,$verbose,$dry_run,$uninstall_shadows,$skip,$always_copy,$result) = @_; 686 if (@_==1 and eval { 1+@$from_to }) { 687 my %opts = @$from_to; 688 $from_to = $opts{from_to} 689 or _confess("from_to is a mandatory parameter"); 690 $verbose = $opts{verbose}; 691 $dry_run = $opts{dry_run}; 692 $uninstall_shadows = $opts{uninstall_shadows}; 693 $skip = $opts{skip}; 694 $always_copy = $opts{always_copy}; 695 $result = $opts{result}; 696 } 697 698 $result ||= {}; 699 $verbose ||= 0; 700 $dry_run ||= 0; 701 702 $skip= _get_install_skip($skip,$verbose); 703 $always_copy = $ENV{EU_INSTALL_ALWAYS_COPY} 704 || $ENV{EU_ALWAYS_COPY} 705 || 0 706 unless defined $always_copy; 707 708 my(%from_to) = %$from_to; 709 my(%pack, $dir, %warned); 710 require ExtUtils::Packlist; 711 my($packlist) = ExtUtils::Packlist->new(); 712 713 local(*DIR); 714 for (qw/read write/) { 715 $pack{$_}=$from_to{$_}; 716 delete $from_to{$_}; 717 } 718 my $tmpfile = install_rooted_file($pack{"read"}); 719 $packlist->read($tmpfile) if (-f $tmpfile); 720 my $cwd = cwd(); 721 my @found_files; 722 my %check_dirs; 723 require File::Find; 724 725 my $blib_lib = File::Spec->catdir('blib', 'lib'); 726 my $blib_arch = File::Spec->catdir('blib', 'arch'); 727 728 # File::Find seems to always be Unixy except on MacPerl :( 729 my $current_directory = $^O eq 'MacOS' ? $Curdir : '.'; 730 731 MOD_INSTALL: foreach my $source (sort keys %from_to) { 732 #copy the tree to the target directory without altering 733 #timestamp and permission and remember for the .packlist 734 #file. The packlist file contains the absolute paths of the 735 #install locations. AFS users may call this a bug. We'll have 736 #to reconsider how to add the means to satisfy AFS users also. 737 738 #October 1997: we want to install .pm files into archlib if 739 #there are any files in arch. So we depend on having ./blib/arch 740 #hardcoded here. 741 742 my $targetroot = install_rooted_dir($from_to{$source}); 743 744 if ($source eq $blib_lib and 745 exists $from_to{$blib_arch} and 746 directory_not_empty($blib_arch) 747 ){ 748 $targetroot = install_rooted_dir($from_to{$blib_arch}); 749 print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n"; 750 } 751 752 next unless -d $source; 753 _chdir($source); 754 # 5.5.3's File::Find missing no_chdir option 755 # XXX OS-SPECIFIC 756 File::Find::find(sub { 757 my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9]; 758 759 return if !-f _; 760 my $origfile = $_; 761 762 return if $origfile eq ".exists"; 763 my $targetdir = File::Spec->catdir($targetroot, $File::Find::dir); 764 my $targetfile = File::Spec->catfile($targetdir, $origfile); 765 my $sourcedir = File::Spec->catdir($source, $File::Find::dir); 766 my $sourcefile = File::Spec->catfile($sourcedir, $origfile); 767 768 for my $pat (@$skip) { 769 if ( $sourcefile=~/$pat/ ) { 770 print "Skipping $targetfile (filtered)\n" 771 if $verbose>1; 772 $result->{install_filtered}{$sourcefile} = $pat; 773 return; 774 } 775 } 776 # we have to do this for back compat with old File::Finds 777 # and because the target is relative 778 my $save_cwd = _chdir($cwd); 779 my $diff = 0; 780 # XXX: I wonder how useful this logic is actually -- demerphq 781 if ( $always_copy or !-f $targetfile or -s $targetfile != $size) { 782 $diff++; 783 } else { 784 # we might not need to copy this file 785 $diff = _compare($sourcefile, $targetfile); 786 } 787 $check_dirs{$targetdir}++ 788 unless -w $targetfile; 789 790 push @found_files, 791 [ $diff, $File::Find::dir, $origfile, 792 $mode, $size, $atime, $mtime, 793 $targetdir, $targetfile, $sourcedir, $sourcefile, 794 795 ]; 796 #restore the original directory we were in when File::Find 797 #called us so that it doesn't get horribly confused. 798 _chdir($save_cwd); 799 }, $current_directory ); 800 _chdir($cwd); 801 } 802 foreach my $targetdir (sort keys %check_dirs) { 803 _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run ); 804 } 805 foreach my $found (@found_files) { 806 my ($diff, $ffd, $origfile, $mode, $size, $atime, $mtime, 807 $targetdir, $targetfile, $sourcedir, $sourcefile)= @$found; 808 809 my $realtarget= $targetfile; 810 if ($diff) { 811 eval { 812 if (-f $targetfile) { 813 print "_unlink_or_rename($targetfile)\n" if $verbose>1; 814 $targetfile= _unlink_or_rename( $targetfile, 'tryhard', 'install' ) 815 unless $dry_run; 816 } elsif ( ! -d $targetdir ) { 817 _mkpath( $targetdir, 0, $Perm_Dir, $verbose, $dry_run ); 818 } 819 print "Installing $targetfile\n"; 820 821 _copy( $sourcefile, $targetfile, $verbose, $dry_run, ); 822 823 824 #XXX OS-SPECIFIC 825 print "utime($atime,$mtime,$targetfile)\n" if $verbose>1; 826 utime($atime,$mtime + Is_VMS,$targetfile) unless $dry_run>1; 827 828 829 $mode = 0444 | ( $mode & 0111 ? 0111 : 0 ); 830 $mode = $mode | 0222 831 if $realtarget ne $targetfile; 832 _chmod( $mode, $targetfile, $verbose ); 833 $result->{install}{$targetfile} = $sourcefile; 834 1 835 } or do { 836 $result->{install_fail}{$targetfile} = $sourcefile; 837 die $@; 838 }; 839 } else { 840 $result->{install_unchanged}{$targetfile} = $sourcefile; 841 print "Skipping $targetfile (unchanged)\n" if $verbose; 842 } 843 844 if ( $uninstall_shadows ) { 845 inc_uninstall($sourcefile,$ffd, $verbose, 846 $dry_run, 847 $realtarget ne $targetfile ? $realtarget : "", 848 $result); 849 } 850 851 # Record the full pathname. 852 $packlist->{$targetfile}++; 853 } 854 855 if ($pack{'write'}) { 856 $dir = install_rooted_dir(dirname($pack{'write'})); 857 _mkpath( $dir, 0, $Perm_Dir, $verbose, $dry_run ); 858 print "Writing $pack{'write'}\n" if $verbose; 859 $packlist->write(install_rooted_file($pack{'write'})) unless $dry_run; 860 } 861 862 _do_cleanup($verbose); 863 return $result; 864} 865 866=begin _private 867 868=item _do_cleanup 869 870Standardize finish event for after another instruction has occurred. 871Handles converting $MUST_REBOOT to a die for instance. 872 873=end _private 874 875=cut 876 877sub _do_cleanup { 878 my ($verbose) = @_; 879 if ($MUST_REBOOT) { 880 die _estr "Operation not completed! ", 881 "You must reboot to complete the installation.", 882 "Sorry."; 883 } elsif (defined $MUST_REBOOT & $verbose) { 884 warn _estr "Installation will be completed at the next reboot.\n", 885 "However it is not necessary to reboot immediately.\n"; 886 } 887} 888 889=begin _undocumented 890 891=item install_rooted_file( $file ) 892 893Returns $file, or catfile($INSTALL_ROOT,$file) if $INSTALL_ROOT 894is defined. 895 896=item install_rooted_dir( $dir ) 897 898Returns $dir, or catdir($INSTALL_ROOT,$dir) if $INSTALL_ROOT 899is defined. 900 901=end _undocumented 902 903=cut 904 905 906sub install_rooted_file { 907 if (defined $INSTALL_ROOT) { 908 File::Spec->catfile($INSTALL_ROOT, $_[0]); 909 } else { 910 $_[0]; 911 } 912} 913 914 915sub install_rooted_dir { 916 if (defined $INSTALL_ROOT) { 917 File::Spec->catdir($INSTALL_ROOT, $_[0]); 918 } else { 919 $_[0]; 920 } 921} 922 923=begin _undocumented 924 925=item forceunlink( $file, $tryhard ) 926 927Tries to delete a file. If $tryhard is true then we will use whatever 928devious tricks we can to delete the file. Currently this only applies to 929Win32 in that it will try to use Win32API::File to schedule a delete at 930reboot. A wrapper for _unlink_or_rename(). 931 932=end _undocumented 933 934=cut 935 936 937sub forceunlink { 938 my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC 939 _unlink_or_rename( $file, $tryhard, not("installing") ); 940} 941 942=begin _undocumented 943 944=item directory_not_empty( $dir ) 945 946Returns 1 if there is an .exists file somewhere in a directory tree. 947Returns 0 if there is not. 948 949=end _undocumented 950 951=cut 952 953sub directory_not_empty ($) { 954 my($dir) = @_; 955 my $files = 0; 956 require File::Find; 957 File::Find::find(sub { 958 return if $_ eq ".exists"; 959 if (-f) { 960 $File::Find::prune++; 961 $files = 1; 962 } 963 }, $dir); 964 return $files; 965} 966 967=pod 968 969=item B<install_default> I<DISCOURAGED> 970 971 install_default(); 972 install_default($fullext); 973 974Calls install() with arguments to copy a module from blib/ to the 975default site installation location. 976 977$fullext is the name of the module converted to a directory 978(ie. Foo::Bar would be Foo/Bar). If $fullext is not specified, it 979will attempt to read it from @ARGV. 980 981This is primarily useful for install scripts. 982 983B<NOTE> This function is not really useful because of the hard-coded 984install location with no way to control site vs core vs vendor 985directories and the strange way in which the module name is given. 986Consider its use discouraged. 987 988=cut 989 990sub install_default { 991 @_ < 2 or _croak("install_default should be called with 0 or 1 argument"); 992 my $FULLEXT = @_ ? shift : $ARGV[0]; 993 defined $FULLEXT or die "Do not know to where to write install log"; 994 my $INST_LIB = File::Spec->catdir($Curdir,"blib","lib"); 995 my $INST_ARCHLIB = File::Spec->catdir($Curdir,"blib","arch"); 996 my $INST_BIN = File::Spec->catdir($Curdir,'blib','bin'); 997 my $INST_SCRIPT = File::Spec->catdir($Curdir,'blib','script'); 998 my $INST_MAN1DIR = File::Spec->catdir($Curdir,'blib','man1'); 999 my $INST_MAN3DIR = File::Spec->catdir($Curdir,'blib','man3'); 1000 1001 my @INST_HTML; 1002 if($Config{installhtmldir}) { 1003 my $INST_HTMLDIR = File::Spec->catdir($Curdir,'blib','html'); 1004 @INST_HTML = ($INST_HTMLDIR => $Config{installhtmldir}); 1005 } 1006 1007 install({ 1008 read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist", 1009 write => "$Config{installsitearch}/auto/$FULLEXT/.packlist", 1010 $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ? 1011 $Config{installsitearch} : 1012 $Config{installsitelib}, 1013 $INST_ARCHLIB => $Config{installsitearch}, 1014 $INST_BIN => $Config{installbin} , 1015 $INST_SCRIPT => $Config{installscript}, 1016 $INST_MAN1DIR => $Config{installman1dir}, 1017 $INST_MAN3DIR => $Config{installman3dir}, 1018 @INST_HTML, 1019 },1,0,0); 1020} 1021 1022 1023=item B<uninstall> 1024 1025 uninstall($packlist_file); 1026 uninstall($packlist_file, $verbose, $dont_execute); 1027 1028Removes the files listed in a $packlist_file. 1029 1030If $verbose is true, will print out each file removed. Default is 1031false. 1032 1033If $dont_execute is true it will only print what it was going to do 1034without actually doing it. Default is false. 1035 1036=cut 1037 1038sub uninstall { 1039 my($fil,$verbose,$dry_run) = @_; 1040 $verbose ||= 0; 1041 $dry_run ||= 0; 1042 1043 die _estr "ERROR: no packlist file found: '$fil'" 1044 unless -f $fil; 1045 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al)); 1046 # require $my_req; # Hairy, but for the first 1047 require ExtUtils::Packlist; 1048 my ($packlist) = ExtUtils::Packlist->new($fil); 1049 foreach (sort(keys(%$packlist))) { 1050 chomp; 1051 print "unlink $_\n" if $verbose; 1052 forceunlink($_,'tryhard') unless $dry_run; 1053 } 1054 print "unlink $fil\n" if $verbose; 1055 forceunlink($fil, 'tryhard') unless $dry_run; 1056 _do_cleanup($verbose); 1057} 1058 1059=begin _undocumented 1060 1061=item inc_uninstall($filepath,$libdir,$verbose,$dry_run,$ignore,$results) 1062 1063Remove shadowed files. If $ignore is true then it is assumed to hold 1064a filename to ignore. This is used to prevent spurious warnings from 1065occurring when doing an install at reboot. 1066 1067We now only die when failing to remove a file that has precedence over 1068our own, when our install has precedence we only warn. 1069 1070$results is assumed to contain a hashref which will have the keys 1071'uninstall' and 'uninstall_fail' populated with keys for the files 1072removed and values of the source files they would shadow. 1073 1074=end _undocumented 1075 1076=cut 1077 1078sub inc_uninstall { 1079 my($filepath,$libdir,$verbose,$dry_run,$ignore,$results) = @_; 1080 my($dir); 1081 $ignore||=""; 1082 my $file = (File::Spec->splitpath($filepath))[2]; 1083 my %seen_dir = (); 1084 1085 my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'} 1086 ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || ''; 1087 1088 my @dirs=( @PERL_ENV_LIB, 1089 @INC, 1090 @Config{qw(archlibexp 1091 privlibexp 1092 sitearchexp 1093 sitelibexp)}); 1094 1095 #warn join "\n","---",@dirs,"---"; 1096 my $seen_ours; 1097 foreach $dir ( @dirs ) { 1098 my $canonpath = Is_VMS ? $dir : File::Spec->canonpath($dir); 1099 next if $canonpath eq $Curdir; 1100 next if $seen_dir{$canonpath}++; 1101 my $targetfile = File::Spec->catfile($canonpath,$libdir,$file); 1102 next unless -f $targetfile; 1103 1104 # The reason why we compare file's contents is, that we cannot 1105 # know, which is the file we just installed (AFS). So we leave 1106 # an identical file in place 1107 my $diff = 0; 1108 if ( -f $targetfile && -s _ == -s $filepath) { 1109 # We have a good chance, we can skip this one 1110 $diff = _compare($filepath,$targetfile); 1111 } else { 1112 $diff++; 1113 } 1114 print "#$file and $targetfile differ\n" if $diff && $verbose > 1; 1115 1116 if (!$diff or $targetfile eq $ignore) { 1117 $seen_ours = 1; 1118 next; 1119 } 1120 if ($dry_run) { 1121 $results->{uninstall}{$targetfile} = $filepath; 1122 if ($verbose) { 1123 $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new(); 1124 $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier. 1125 $Inc_uninstall_warn_handler->add( 1126 File::Spec->catfile($libdir, $file), 1127 $targetfile 1128 ); 1129 } 1130 # if not verbose, we just say nothing 1131 } else { 1132 print "Unlinking $targetfile (shadowing?)\n" if $verbose; 1133 eval { 1134 die "Fake die for testing" 1135 if $ExtUtils::Install::Testing and 1136 ucase(File::Spec->canonpath($ExtUtils::Install::Testing)) eq ucase($targetfile); 1137 forceunlink($targetfile,'tryhard'); 1138 $results->{uninstall}{$targetfile} = $filepath; 1139 1; 1140 } or do { 1141 $results->{fail_uninstall}{$targetfile} = $filepath; 1142 if ($seen_ours) { 1143 warn "Failed to remove probably harmless shadow file '$targetfile'\n"; 1144 } else { 1145 die "$@\n"; 1146 } 1147 }; 1148 } 1149 } 1150} 1151 1152=begin _undocumented 1153 1154=item run_filter($cmd,$src,$dest) 1155 1156Filter $src using $cmd into $dest. 1157 1158=end _undocumented 1159 1160=cut 1161 1162sub run_filter { 1163 my ($cmd, $src, $dest) = @_; 1164 local(*CMD, *SRC); 1165 open(CMD, "|$cmd >$dest") || die "Cannot fork: $!"; 1166 open(SRC, $src) || die "Cannot open $src: $!"; 1167 my $buf; 1168 my $sz = 1024; 1169 while (my $len = sysread(SRC, $buf, $sz)) { 1170 syswrite(CMD, $buf, $len); 1171 } 1172 close SRC; 1173 close CMD or die "Filter command '$cmd' failed for $src"; 1174} 1175 1176=pod 1177 1178=item B<pm_to_blib> 1179 1180 pm_to_blib(\%from_to); 1181 pm_to_blib(\%from_to, $autosplit_dir); 1182 pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd); 1183 1184Copies each key of %from_to to its corresponding value efficiently. 1185If an $autosplit_dir is provided, all .pm files will be autosplit into it. 1186Any destination directories are created. 1187 1188$filter_cmd is an optional shell command to run each .pm file through 1189prior to splitting and copying. Input is the contents of the module, 1190output the new module contents. 1191 1192You can have an environment variable PERL_INSTALL_ROOT set which will 1193be prepended as a directory to each installed file (and directory). 1194 1195By default verbose output is generated, setting the PERL_INSTALL_QUIET 1196environment variable will silence this output. 1197 1198=cut 1199 1200sub pm_to_blib { 1201 my($fromto,$autodir,$pm_filter) = @_; 1202 1203 _mkpath($autodir,0,$Perm_Dir) if defined $autodir; 1204 while(my($from, $to) = each %$fromto) { 1205 if( -f $to && -s $from == -s $to && -M $to < -M $from ) { 1206 print "Skip $to (unchanged)\n" unless $INSTALL_QUIET; 1207 next; 1208 } 1209 1210 # When a pm_filter is defined, we need to pre-process the source first 1211 # to determine whether it has changed or not. Therefore, only perform 1212 # the comparison check when there's no filter to be ran. 1213 # -- RAM, 03/01/2001 1214 1215 my $need_filtering = defined $pm_filter && length $pm_filter && 1216 $from =~ /\.pm$/; 1217 1218 if (!$need_filtering && 0 == _compare($from,$to)) { 1219 print "Skip $to (unchanged)\n" unless $INSTALL_QUIET; 1220 next; 1221 } 1222 if (-f $to){ 1223 # we wont try hard here. its too likely to mess things up. 1224 forceunlink($to); 1225 } else { 1226 _mkpath(dirname($to),0,$Perm_Dir); 1227 } 1228 if ($need_filtering) { 1229 run_filter($pm_filter, $from, $to); 1230 print "$pm_filter <$from >$to\n"; 1231 } else { 1232 _copy( $from, $to ); 1233 print "cp $from $to\n" unless $INSTALL_QUIET; 1234 } 1235 my($mode,$atime,$mtime) = (stat $from)[2,8,9]; 1236 utime($atime,$mtime+Is_VMS,$to); 1237 _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to); 1238 next unless $from =~ /\.pm$/; 1239 _autosplit($to,$autodir) if defined $autodir; 1240 } 1241} 1242 1243 1244=begin _private 1245 1246=item _autosplit 1247 1248From 1.0307 back, AutoSplit will sometimes leave an open filehandle to 1249the file being split. This causes problems on systems with mandatory 1250locking (ie. Windows). So we wrap it and close the filehandle. 1251 1252=end _private 1253 1254=cut 1255 1256sub _autosplit { #XXX OS-SPECIFIC 1257 require AutoSplit; 1258 my $retval = AutoSplit::autosplit(@_); 1259 close *AutoSplit::IN if defined *AutoSplit::IN{IO}; 1260 1261 return $retval; 1262} 1263 1264 1265package ExtUtils::Install::Warn; 1266 1267sub new { bless {}, shift } 1268 1269sub add { 1270 my($self,$file,$targetfile) = @_; 1271 push @{$self->{$file}}, $targetfile; 1272} 1273 1274sub DESTROY { 1275 unless(defined $INSTALL_ROOT) { 1276 my $self = shift; 1277 my($file,$i,$plural); 1278 foreach $file (sort keys %$self) { 1279 $plural = @{$self->{$file}} > 1 ? "s" : ""; 1280 print "## Differing version$plural of $file found. You might like to\n"; 1281 for (0..$#{$self->{$file}}) { 1282 print "rm ", $self->{$file}[$_], "\n"; 1283 $i++; 1284 } 1285 } 1286 $plural = $i>1 ? "all those files" : "this file"; 1287 my $inst = (_invokant() eq 'ExtUtils::MakeMaker') 1288 ? ( $Config::Config{make} || 'make' ).' install' 1289 . ( ExtUtils::Install::Is_VMS ? '/MACRO="UNINST"=1' : ' UNINST=1' ) 1290 : './Build install uninst=1'; 1291 print "## Running '$inst' will unlink $plural for you.\n"; 1292 } 1293} 1294 1295=begin _private 1296 1297=item _invokant 1298 1299Does a heuristic on the stack to see who called us for more intelligent 1300error messages. Currently assumes we will be called only by Module::Build 1301or by ExtUtils::MakeMaker. 1302 1303=end _private 1304 1305=cut 1306 1307sub _invokant { 1308 my @stack; 1309 my $frame = 0; 1310 while (my $file = (caller($frame++))[1]) { 1311 push @stack, (File::Spec->splitpath($file))[2]; 1312 } 1313 1314 my $builder; 1315 my $top = pop @stack; 1316 if ($top =~ /^Build/i || exists($INC{'Module/Build.pm'})) { 1317 $builder = 'Module::Build'; 1318 } else { 1319 $builder = 'ExtUtils::MakeMaker'; 1320 } 1321 return $builder; 1322} 1323 1324=pod 1325 1326=back 1327 1328=head1 ENVIRONMENT 1329 1330=over 4 1331 1332=item B<PERL_INSTALL_ROOT> 1333 1334Will be prepended to each install path. 1335 1336=item B<EU_INSTALL_IGNORE_SKIP> 1337 1338Will prevent the automatic use of INSTALL.SKIP as the install skip file. 1339 1340=item B<EU_INSTALL_SITE_SKIPFILE> 1341 1342If there is no INSTALL.SKIP file in the make directory then this value 1343can be used to provide a default. 1344 1345=item B<EU_INSTALL_ALWAYS_COPY> 1346 1347If this environment variable is true then normal install processes will 1348always overwrite older identical files during the install process. 1349 1350Note that the alias EU_ALWAYS_COPY will be supported if EU_INSTALL_ALWAYS_COPY 1351is not defined until at least the 1.50 release. Please ensure you use the 1352correct EU_INSTALL_ALWAYS_COPY. 1353 1354=back 1355 1356=head1 AUTHOR 1357 1358Original author lost in the mists of time. Probably the same as Makemaker. 1359 1360Production release currently maintained by demerphq C<yves at cpan.org>, 1361extensive changes by Michael G. Schwern. 1362 1363Send bug reports via http://rt.cpan.org/. Please send your 1364generated Makefile along with your report. 1365 1366=head1 LICENSE 1367 1368This program is free software; you can redistribute it and/or 1369modify it under the same terms as Perl itself. 1370 1371See L<http://www.perl.com/perl/misc/Artistic.html> 1372 1373 1374=cut 1375 13761; 1377