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

Reply via email to