On 2/12/06, demerphq <[EMAIL PROTECTED]> wrote: > Hi, the attached patch cleans up and enhances the original handling of > the install at reboot stuff. Its against the seperated out bundle you > mention above. >
Er, i forgot the patch. Sorry. Yves -- perl -Mre=debug -e "/just|another|perl|hacker/"
diff -wur ExtUtils-Install-1.35/META.yml ExtUtils-Install/META.yml --- ExtUtils-Install-1.35/META.yml 2006-02-02 05:45:59.000000000 +0100 +++ ExtUtils-Install/META.yml 2006-02-12 17:48:13.000000000 +0100 @@ -1,8 +1,8 @@ --- name: ExtUtils-Install -version: 1.35 +version: 1.36 author: - - Michael G Schwern <[EMAIL PROTECTED]> + - 'Michael G Schwern <[EMAIL PROTECTED]>' abstract: install files from here to there license: perl resources: @@ -30,7 +30,7 @@ provides: ExtUtils::Install: file: lib/ExtUtils/Install.pm - version: 1.35 + version: 1.36 ExtUtils::Install::Warn: file: lib/ExtUtils/Install.pm ExtUtils::Installed: diff -wur ExtUtils-Install-1.35/lib/ExtUtils/Install.pm ExtUtils-Install/lib/ExtUtils/Install.pm --- ExtUtils-Install-1.35/lib/ExtUtils/Install.pm 2006-02-02 05:22:08.000000000 +0100 +++ ExtUtils-Install/lib/ExtUtils/Install.pm 2006-02-12 19:46:13.140625000 +0100 @@ -1,8 +1,8 @@ package ExtUtils::Install; use 5.00503; -use vars qw(@ISA @EXPORT $VERSION); -$VERSION = '1.35'; +use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT); +$VERSION = '1.36'; use Exporter; use Carp (); @@ -11,6 +11,10 @@ @EXPORT = ('install','uninstall','pm_to_blib', 'install_default'); $Is_VMS = $^O eq 'VMS'; $Is_MacPerl = $^O eq 'MacOS'; +$Is_Win32 = $^O eq 'MSWin32'; + +# used by win32 stuff only currently +my $Has_APIFile; # when defined tells whether Win32API::File is installed my $Inc_uninstall_warn_handler; @@ -22,6 +26,17 @@ my $Curdir = File::Spec->curdir; my $Updir = File::Spec->updir; +sub _chmod($$;$) { + my ( $mode, $item, $verbose )[EMAIL PROTECTED]; + $verbose ||= 0; + if (chmod $mode, $item) { + print "chmod($mode, $item)\n" if $verbose > 1; + } else { + my $err="$!"; + warn "Failed chmod($mode, $item): $err\n" + if -e $item; + } +} =head1 NAME @@ -47,6 +62,27 @@ ExtUtils::MakeMaker handles the installation and deinstallation of perl modules. They are not designed as general purpose tools. +=begin DeveloperNotes + +On some operating systems such as Win32 installation may not be possible +until after a reboot has occured. This can have varying consequences: +removing an old DLL does not impact programs using the new one, but if +a new DLL cannot be installed properly until reboot then anything +depending on it must wait. The package variable + + $ExtUtils::Install::MUST_REBOOT + +is used to store this status. + +If this variable is true then such an operation has occured and +anything depending on this module cannot proceed until a reboot +has occured. + +If this value is defined but false then such an operation has +ocurred, but should not impact later operations. + +=end DeveloperNotes + =head2 Functions =over 4 @@ -80,7 +116,7 @@ sub install { my($from_to,$verbose,$nonono,$inc_uninstall) = @_; - $verbose ||= 0; + $verbose ||= $ENV{DEBUG_EUMM} || 0; $nonono ||= 0; use Cwd qw(cwd); @@ -91,9 +127,7 @@ use File::Path qw(mkpath); use File::Compare qw(compare); - my $win32_special=!$nonono && - $^O eq 'MSWin32' && - eval { require Win32API::File; 1 }; + my $win32_special; my(%from_to) = %$from_to; my(%pack, $dir, $warn_permissions); my($packlist) = ExtUtils::Packlist->new(); @@ -173,24 +207,48 @@ } if ($diff){ - if ($win32_special && -f $targetfile && !unlink $targetfile) { - print "Can't remove existing '$targetfile': $!\n"; + if ( !$nonono && $Is_Win32 + && -f $targetfile + && !unlink $targetfile ) + { + my $error="$!"; + + $Has_APIFile= eval { require Win32API::File; 1 } || 0 + if ! defined $Has_APIFile; + + Carp::croak( + "Cannot unlink $targetfile: $error\n", + "If you install Win32API::File I can use ", + "it to try to complete the install at reboot\n" + ) if ! $Has_APIFile; + + print "Can't remove existing '$targetfile': $error\n"; + + # make a temporary file name to use for installation. + # if we can rename then the temp file will used for the + # old file, if we can't then the file will be installed as + # the temp name, and renamed into the correct name at boot my $tmp= "AAA"; ++$tmp while -e "$targetfile.$tmp"; $tmp= "$targetfile.$tmp"; if ( rename $targetfile, $tmp ) { + _chmod(0666, $tmp, $verbose); print "However it has been renamed as '$tmp' which ". - "will be removed at next reboot.\n"; + "will be removed at next boot.\n"; Win32API::File::MoveFileEx( $tmp, [], Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT() ) or die "MoveFileEx/Delete '$tmp' failed: $^E\n"; + $MUST_REBOOT||= 0; } else { + _chmod(0666, $targetfile, $verbose); + print "Installation cannot be completed until you reboot.\n", "Until then using '$tmp' as the install filename.\n"; Win32API::File::MoveFileEx( $tmp, $targetfile, Win32API::File::MOVEFILE_REPLACE_EXISTING() | Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT() ) or die "MoveFileEx/Replace '$tmp' failed: $^E\n"; + $MUST_REBOOT||= 1; $targetfile= $tmp; } } elsif (-f $targetfile) { @@ -204,8 +262,7 @@ utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1; print "utime($atime,$mtime,$targetfile)\n" if $verbose>1; $mode = 0444 | ( $mode & 0111 ? 0111 : 0 ); - chmod $mode, $targetfile; - print "chmod($mode, $targetfile)\n" if $verbose>1; + _chmod( $mode, $targetfile, $verbose ); } else { print "Skipping $targetfile (unchanged)\n" if $verbose; } @@ -231,6 +288,12 @@ print "Writing $pack{'write'}\n"; $packlist->write(install_rooted_file($pack{'write'})) unless $nonono; } + if ($MUST_REBOOT) { + die "You must reboot to complete this installation.\n"; + } elsif (defined $MUST_REBOOT) { + warn "Full installation will not be complete until next reboot.\n", + "However it is not necessary to reboot immediately.\n"; + } } sub install_rooted_file { @@ -250,10 +313,35 @@ } } - +# if tryhard is true then we will use whatever devious tricks we can +# to delete the file. Currently this only applies to only Win32 in +# that it will try to use Win32API::File to schedule a delete at reboot. sub forceunlink { - chmod 0666, $_[0]; - unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!") + my ( $file, $tryhard )= @_; + _chmod( 0666, $file ); + my $ok= unlink $file; + return if $ok; + $error= "$!"; # preserve the error string. + if ( $tryhard && $Is_Win32 ) { + + $Has_APIFile= eval { require Win32API::File; 1 } || 0 + if ! defined $Has_APIFile; + + if ( ! $Has_APIFile ) { + $error .= "\nIf you install Win32API::File I can try to use it to " + . "uninstall this file at reboot."; + } elsif ( Win32API::File::MoveFileEx( $file, [], + Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT() ) + ){ + print "Scheduled '$file' for deletion at next reboot.\n"; + $MUST_REBOOT||= 0; + return; + } else { + $error.="\nCannot schedule '$tmp' for deletion at reboot: $^E.\n"; + } + + } + Carp::croak( "Cannot forceunlink $file: $error\n"); } @@ -345,10 +433,16 @@ foreach (sort(keys(%$packlist))) { chomp; print "unlink $_\n" if $verbose; - forceunlink($_) unless $nonono; + forceunlink($_,'tryhard') unless $nonono; } print "unlink $fil\n" if $verbose; - forceunlink($fil) unless $nonono; + forceunlink($fil,'tryhard') unless $nonono; + if ($MUST_REBOOT) { + die "You must reboot to complete this installation.\n"; + } elsif (defined $MUST_REBOOT) { + warn "Full installation will not be complete until next reboot.\n", + "However it is not necessary to reboot immediately.\n"; + } } sub inc_uninstall { @@ -384,7 +478,7 @@ next unless $diff; if ($nonono) { if ($verbose) { - $Inc_uninstall_warn_handler ||= new ExtUtils::Install::Warn; + $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new(); $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier. $Inc_uninstall_warn_handler->add( File::Spec->catfile($libdir, $file), @@ -394,7 +488,7 @@ # if not verbose, we just say nothing } else { print "Unlinking $targetfile (shadowing?)\n"; - forceunlink($targetfile); + forceunlink($targetfile,'tryhard'); } } } @@ -461,6 +555,7 @@ next; } if (-f $to){ + # we wont try hard here. its too likely to mess things up. forceunlink($to); } else { mkpath(dirname($to),0,0755); @@ -474,7 +569,7 @@ } my($mode,$atime,$mtime) = (stat $from)[2,8,9]; utime($atime,$mtime+$Is_VMS,$to); - chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to); + _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to); next unless $from =~ /\.pm$/; _autosplit($to,$autodir); } @@ -529,7 +624,6 @@ =back - =head1 ENVIRONMENT =over 4