RE: [PATCH-for-28089] wince yet another step
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / Install.pm
CommitLineData
4b6d56d3 1package ExtUtils::Install;
57b1a898 2use 5.00503;
3a465856 3use strict;
4
5use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT %Config);
6$VERSION = '1.39';
7$VERSION = eval $VERSION;
f1387719 8
08ad6bd5 9use Exporter;
08ad6bd5 10use Carp ();
c3648e42 11use Config qw(%Config);
3a465856 12
4b6d56d3 13@ISA = ('Exporter');
c3648e42 14@EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
a9d83807 15
479d2113 16=head1 NAME
a9d83807 17
479d2113 18ExtUtils::Install - install files from here to there
4b6d56d3 19
479d2113 20=head1 SYNOPSIS
21
22 use ExtUtils::Install;
23
24 install({ 'blib/lib' => 'some/install/dir' } );
25
26 uninstall($packlist);
27
28 pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
29
3a465856 30=cut
31
32my $Is_VMS = $^O eq 'VMS';
33my $Is_MacPerl = $^O eq 'MacOS';
34my $Is_Win32 = $^O eq 'MSWin32';
35my $Is_cygwin = $^O eq 'cygwin';
36my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin);
37
38# *note* CanMoveAtBoot is only incidentally the same condition as below
39# this needs not hold true in the future.
40my $Has_Win32API_File = ($Is_Win32 || $Is_cygwin)
41 ? (eval {require Win32API::File; 1} || 0)
42 : 0;
43
44
45my $Inc_uninstall_warn_handler;
46
47# install relative to here
48
49my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};
50
51use File::Spec;
52my $Curdir = File::Spec->curdir;
53my $Updir = File::Spec->updir;
54
479d2113 55
56=head1 DESCRIPTION
57
58Handles the installing and uninstalling of perl modules, scripts, man
59pages, etc...
60
61Both install() and uninstall() are specific to the way
62ExtUtils::MakeMaker handles the installation and deinstallation of
63perl modules. They are not designed as general purpose tools.
64
3a465856 65On some operating systems such as Win32 installation may not be possible
66until after a reboot has occured. This can have varying consequences:
67removing an old DLL does not impact programs using the new one, but if
68a new DLL cannot be installed properly until reboot then anything
69depending on it must wait. The package variable
70
71 $ExtUtils::Install::MUST_REBOOT
72
73is used to store this status.
74
75If this variable is true then such an operation has occured and
76anything depending on this module cannot proceed until a reboot
77has occured.
78
79If this value is defined but false then such an operation has
80ocurred, but should not impact later operations.
81
82=begin _private
83
84=item _chmod($$;$)
85
86Wrapper to chmod() for debugging and error trapping.
87
88=end _private
89
90=cut
91
92
93sub _chmod($$;$) {
94 my ( $mode, $item, $verbose )=@_;
95 $verbose ||= 0;
96 if (chmod $mode, $item) {
97 print "chmod($mode, $item)\n" if $verbose > 1;
98 } else {
99 my $err="$!";
100 warn "Failed chmod($mode, $item): $err\n"
101 if -e $item;
102 }
103}
104
105=begin _private
106
107=item _move_file_at_boot( $file, $target, $moan )
108
109OS-Specific, Win32/Cygwin
110
111Schedules a file to be moved/renamed/deleted at next boot.
112$file should be a filespec of an existing file
113$target should be a ref to an array if the file is to be deleted
114otherwise it should be a filespec for a rename. If the file is existing
115it will be replaced.
116
117Sets $MUST_REBOOT to 0 to indicate a deletion operation has occured
118and sets it to 1 to indicate that a move operation has been requested.
119
120returns 1 on success, on failure if $moan is false errors are fatal.
121If $moan is true then returns 0 on error and warns instead of dies.
122
123=end _private
124
125=cut
126
127
128
129sub _move_file_at_boot { #XXX OS-SPECIFIC
130 my ( $file, $target, $moan )= @_;
131 Carp::confess("Panic: Can't _move_file_at_boot on this platform!")
132 unless $CanMoveAtBoot;
133
134 my $descr= ref $target
135 ? "'$file' for deletion"
136 : "'$file' for installation as '$target'";
137
138 if ( ! $Has_Win32API_File ) {
139 my $msg=join "\n",'!' x 72,
140 ( $moan ? "WARNING:" : "ERROR:" )
141 . " Cannot schedule $descr at reboot.",
142 "Try installing Win32API::File to allow operations on locked files",
143 "to be scheduled during reboot. Or try to perform the operation by",
144 "hand yourself. (You may need to close other perl processes first)",
145 '!' x 72,"";
146 if ( $moan ) { warn $msg } else { die $msg }
147 return 0;
148 }
149 my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
150 $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
151 unless ref $target;
152
153 _chmod( 0666, $file );
154 _chmod( 0666, $target ) unless ref $target;
155
156 if (Win32API::File::MoveFileEx( $file, $target, $opts )) {
157 $MUST_REBOOT ||= ref $target ? 0 : 1;
158 return 1;
159 } else {
160 my $msg=join "\n",'!' x 72,
161 ( $moan ? "WARNING:" : "ERROR:" )
162 . "MoveFileEx $descr at reboot failed: $^E",
163 "You may try to perform the operation by hand yourself. ",
164 "(You may need to close other perl processes first).",
165 '!' x 72, "";
166 if ( $moan ) { warn $msg } else { die $msg }
167 }
168 return 0;
169}
170
171
172=begin _private
173
174=item _unlink_or_rename( $file, $tryhard, $installing )
175
176OS-Specific, Win32/Cygwin
177
178Tries to get a file out of the way by unlinking it or renaming it. On
179some OS'es (Win32 based) DLL files can end up locked such that they can
180be renamed but not deleted. Likewise sometimes a file can be locked such
181that it cant even be renamed or changed except at reboot. To handle
182these cases this routine finds a tempfile name that it can either rename
183the file out of the way or use as a proxy for the install so that the
184rename can happen later (at reboot).
185
186 $file : the file to remove.
187 $tryhard : should advanced tricks be used for deletion
188 $installing : we are not merely deleting but we want to overwrite
189
190When $tryhard is not true if the unlink fails its fatal. When $tryhard
191is true then the file is attempted to be renamed. The renamed file is
192then scheduled for deletion. If the rename fails then $installing
193governs what happens. If it is false the failure is fatal. If it is true
194then an attempt is made to schedule installation at boot using a
195temporary file to hold the new file. If this fails then a fatal error is
196thrown, if it succeeds it returns the temporary file name (which will be
197a derivative of the original in the same directory) so that the caller can
198use it to install under. In all other cases of success returns $file.
199On failure throws a fatal error.
200
201=end _private
202
203=cut
204
205
206
207sub _unlink_or_rename { #XXX OS-SPECIFIC
208 my ( $file, $tryhard, $installing )= @_;
209
210 _chmod( 0666, $file );
211 unlink $file
212 and return $file;
213 my $error="$!";
214
215 Carp::croak('!' x 72, "\n",
216 "ERROR: Cannot unlink '$file': $!\n",
217 '!' x 72, "\n")
218 unless $CanMoveAtBoot && $tryhard;
219
220 my $tmp= "AAA";
221 ++$tmp while -e "$file.$tmp";
222 $tmp= "$file.$tmp";
223
224 warn "WARNING: Unable to unlink '$file': $error\n",
225 "Going to try to rename it to '$tmp'.\n";
226
227 if ( rename $file, $tmp ) {
228 warn "Rename succesful. Scheduling '$tmp'\nfor deletion at reboot.\n";
229 # when $installing we can set $moan to true.
230 # IOW, if we cant delete the renamed file at reboot its
231 # not the end of the world. The other cases are more serious
232 # and need to be fatal.
233 _move_file_at_boot( $tmp, [], $installing );
234 return $file;
235 } elsif ( $installing ) {
236 warn "WARNING: Rename failed: $!. Scheduling '$tmp'\nfor".
237 " installation as '$file' at reboot.\n";
238 _move_file_at_boot( $tmp, $file );
239 return $tmp;
240 } else {
241 Carp::croak('!' x 72, "\n",
242 "ERROR: Rename failed:$!\n",
243 "Cannot procede.\n",
244 '!' x 72, "\n");
245 }
246
247}
248
479d2113 249=head2 Functions
250
251=over 4
252
253=item B<install>
254
255 install(\%from_to);
3a465856 256 install(\%from_to, $verbose, $dont_execute, $uninstall_shadows, $skip);
479d2113 257
258Copies each directory tree of %from_to to its corresponding value
259preserving timestamps and permissions.
260
261There are two keys with a special meaning in the hash: "read" and
262"write". These contain packlist files. After the copying is done,
263install() will write the list of target files to $from_to{write}. If
264$from_to{read} is given the contents of this file will be merged into
265the written file. The read and the written file may be identical, but
266on AFS it is quite likely that people are installing to a different
267directory than the one where the files later appear.
268
269If $verbose is true, will print out each file removed. Default is
3a465856 270false. This is "make install VERBINST=1". $verbose values going
271up to 5 show increasingly more diagnostics output.
479d2113 272
273If $dont_execute is true it will only print what it was going to do
274without actually doing it. Default is false.
275
1df8d179 276If $uninstall_shadows is true any differing versions throughout @INC
277will be uninstalled. This is "make install UNINST=1"
278
3a465856 279As of 1.37_02 install() supports the use of a list of patterns to filter
280out files that shouldn't be installed. If $skip is omitted or undefined
281then install will try to read the list from INSTALL.SKIP in the CWD.
282This file is a list of regular expressions and is just like the
283MANIFEST.SKIP file used by L<ExtUtils::Manifest>.
284
285A default site INSTALL.SKIP may be provided by setting then environment
286variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there
287isn't a distribution specific INSTALL.SKIP. If the environment variable
288EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
289performed.
290
291If $skip is undefined then the skip file will be autodetected and used if it
292is found. If $skip is a reference to an array then it is assumed
293the array contains the list of patterns, if $skip is a true non reference it is
294assumed to be the filename holding the list of patterns, any other value of
295$skip is taken to mean that no install filtering should occur.
296
297
479d2113 298=cut
08ad6bd5 299
3a465856 300#
301# Handles the reading the skip file.
302#
303sub _get_install_skip {
304 my ( $skip, $verbose )= @_;
305 if ($ENV{EU_INSTALL_IGNORE_SKIP}) {
306 print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n"
307 if $verbose>2;
308 return [];
309 }
310 if ( ! defined $skip ) {
311 print "Looking for install skip list\n"
312 if $verbose>2;
313 for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) {
314 next unless $file;
315 print "\tChecking for $file\n"
316 if $verbose>2;
317 if (-e $file) {
318 $skip= $file;
319 last;
320 }
321 }
322 }
323 if ($skip && !ref $skip) {
324 print "Reading skip patterns from '$skip'.\n"
325 if $verbose;
326 if (open my $fh,$skip ) {
327 my @patterns;
328 while (<$fh>) {
329 chomp;
330 next if /^\s*(?:#|$)/;
331 print "\tSkip pattern: $_\n" if $verbose>3;
332 push @patterns, $_;
333 }
334 $skip= \@patterns;
335 } else {
336 warn "Can't read skip file:'$skip':$!\n";
337 $skip=[];
338 }
339 } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) {
340 print "Using array for skip list\n"
341 if $verbose>2;
342 } elsif ($verbose) {
343 print "No skip list found.\n"
344 if $verbose>1;
345 $skip= [];
346 }
347 warn "Got @{[0+@$skip]} skip patterns.\n"
348 if $verbose>3;
349 return $skip
350}
351
352
353sub install { #XXX OS-SPECIFIC
354 my($from_to,$verbose,$nonono,$inc_uninstall,$skip) = @_;
4b6d56d3 355 $verbose ||= 0;
356 $nonono ||= 0;
08ad6bd5 357
358 use Cwd qw(cwd);
354f3b56 359 use ExtUtils::Packlist;
08ad6bd5 360 use File::Basename qw(dirname);
361 use File::Copy qw(copy);
362 use File::Find qw(find);
363 use File::Path qw(mkpath);
fb73857a 364 use File::Compare qw(compare);
08ad6bd5 365
3a465856 366 $skip= _get_install_skip($skip,$verbose);
367
479d2113 368 my(%from_to) = %$from_to;
354f3b56 369 my(%pack, $dir, $warn_permissions);
370 my($packlist) = ExtUtils::Packlist->new();
3e3baf6d 371 # -w doesn't work reliably on FAT dirs
3a465856 372 $warn_permissions++ if $Is_Win32; #XXX OS-SPECIFIC
354f3b56 373 local(*DIR);
4b6d56d3 374 for (qw/read write/) {
479d2113 375 $pack{$_}=$from_to{$_};
376 delete $from_to{$_};
4b6d56d3 377 }
08ad6bd5 378 my($source_dir_or_file);
479d2113 379 foreach $source_dir_or_file (sort keys %from_to) {
4b6d56d3 380 #Check if there are files, and if yes, look if the corresponding
381 #target directory is writable for us
08ad6bd5 382 opendir DIR, $source_dir_or_file or next;
f1387719 383 for (readdir DIR) {
479d2113 384 next if $_ eq $Curdir || $_ eq $Updir || $_ eq ".exists";
385 my $targetdir = install_rooted_dir($from_to{$source_dir_or_file});
2530b651 386 mkpath($targetdir) unless $nonono;
387 if (!$nonono && !-w $targetdir) {
388 warn "Warning: You do not have permissions to " .
389 "install into $from_to{$source_dir_or_file}"
390 unless $warn_permissions++;
4b6d56d3 391 }
392 }
393 closedir DIR;
394 }
a9d83807 395 my $tmpfile = install_rooted_file($pack{"read"});
396 $packlist->read($tmpfile) if (-f $tmpfile);
4b6d56d3 397 my $cwd = cwd();
4b6d56d3 398
479d2113 399 MOD_INSTALL: foreach my $source (sort keys %from_to) {
4b6d56d3 400 #copy the tree to the target directory without altering
401 #timestamp and permission and remember for the .packlist
402 #file. The packlist file contains the absolute paths of the
403 #install locations. AFS users may call this a bug. We'll have
404 #to reconsider how to add the means to satisfy AFS users also.
456e5c25 405
406 #October 1997: we want to install .pm files into archlib if
407 #there are any files in arch. So we depend on having ./blib/arch
408 #hardcoded here.
a9d83807 409
479d2113 410 my $targetroot = install_rooted_dir($from_to{$source});
a9d83807 411
479d2113 412 my $blib_lib = File::Spec->catdir('blib', 'lib');
413 my $blib_arch = File::Spec->catdir('blib', 'arch');
414 if ($source eq $blib_lib and
415 exists $from_to{$blib_arch} and
416 directory_not_empty($blib_arch)) {
417 $targetroot = install_rooted_dir($from_to{$blib_arch});
418 print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n";
456e5c25 419 }
479d2113 420
421 chdir $source or next;
3a465856 422
4b6d56d3 423 find(sub {
479d2113 424 my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9];
1df8d179 425
3a465856 426 return if !-f _;
1df8d179 427 my $origfile = $_;
3a465856 428
1df8d179 429 return if $origfile eq ".exists";
3ac85e8f 430 my $targetdir = File::Spec->catdir($targetroot, $File::Find::dir);
1df8d179 431 my $targetfile = File::Spec->catfile($targetdir, $origfile);
479d2113 432 my $sourcedir = File::Spec->catdir($source, $File::Find::dir);
1df8d179 433 my $sourcefile = File::Spec->catfile($sourcedir, $origfile);
479d2113 434
3a465856 435 for my $pat (@$skip) {
436 if ( $sourcefile=~/$pat/ ) {
437 print "Skipping $targetfile (filtered)\n"
438 if $verbose>1;
439 return;
440 }
441 }
442
479d2113 443 my $save_cwd = cwd;
444 chdir $cwd; # in case the target is relative
445 # 5.5.3's File::Find missing no_chdir option.
4b6d56d3 446
f1387719 447 my $diff = 0;
4b6d56d3 448 if ( -f $targetfile && -s _ == $size) {
449 # We have a good chance, we can skip this one
479d2113 450 $diff = compare($sourcefile, $targetfile);
4b6d56d3 451 } else {
4b6d56d3 452 $diff++;
453 }
3a465856 454 print "$sourcefile differs\n" if $diff && $verbose>1;
455 my $realtarget= $targetfile;
3b4a80d1 456 if ($diff) {
3a465856 457 if (-f $targetfile) {
458 print "_unlink_or_rename($targetfile)\n" if $verbose>1;
459 $targetfile= _unlink_or_rename( $targetfile, 'tryhard', 'install' )
460 unless $nonono;
08ad6bd5 461 } else {
462 mkpath($targetdir,0,0755) unless $nonono;
463 print "mkpath($targetdir,0,0755)\n" if $verbose>1;
464 }
479d2113 465 copy($sourcefile, $targetfile) unless $nonono;
f1387719 466 print "Installing $targetfile\n";
3a465856 467 #XXX OS-SPECIFIC
08ad6bd5 468 utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1;
4b6d56d3 469 print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
3a465856 470
471 $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
472 $mode = $mode | 0222
473 if $realtarget ne $targetfile;
474 _chmod( $mode, $targetfile, $verbose );
475
476
4b6d56d3 477 } else {
f1387719 478 print "Skipping $targetfile (unchanged)\n" if $verbose;
479 }
479d2113 480
3a465856 481 if ( defined $inc_uninstall ) {
482 inc_uninstall($sourcefile,$File::Find::dir,$verbose,
483 $inc_uninstall ? 0 : 1,
484 $realtarget ne $targetfile ? $realtarget : "");
4b6d56d3 485 }
479d2113 486
8c05f1d0 487 # Record the full pathname.
007a26ab 488 $packlist->{$targetfile}++;
4b6d56d3 489
479d2113 490 # File::Find can get confused if you chdir in here.
491 chdir $save_cwd;
492
493 # File::Find seems to always be Unixy except on MacPerl :(
3a465856 494 }, $Is_MacPerl ? $Curdir : '.' ); #XXX OS-SPECIFIC
08ad6bd5 495 chdir($cwd) or Carp::croak("Couldn't chdir to $cwd: $!");
4b6d56d3 496 }
3a465856 497
4b6d56d3 498 if ($pack{'write'}) {
a9d83807 499 $dir = install_rooted_dir(dirname($pack{'write'}));
ab00ffcd 500 mkpath($dir,0,0755) unless $nonono;
4b6d56d3 501 print "Writing $pack{'write'}\n";
ab00ffcd 502 $packlist->write(install_rooted_file($pack{'write'})) unless $nonono;
4b6d56d3 503 }
3a465856 504
505 _do_cleanup($verbose);
506}
507
508=begin _private
509
510=item _do_cleanup
511
512Standardize finish event for after another instruction has occured.
513Handles converting $MUST_REBOOT to a die for instance.
514
515=end _private
516
517=cut
518
519sub _do_cleanup {
520 my ($verbose) = @_;
521 if ($MUST_REBOOT) {
522 die
523 '!' x 72, "\n",
524 "Operation not completed: ",
525 "Please reboot to complete the Installation.\n",
526 '!' x 72, "\n",
527 ;
528 } elsif (defined $MUST_REBOOT & $verbose) {
529 warn '-' x 72, "\n",
530 "Installation will be completed at the next reboot.\n",
531 "However it is not necessary to reboot immediately.\n";
532 }
4b6d56d3 533}
534
3a465856 535=begin _undocumented
536
537=item install_rooted_file( $file )
538
539Returns $file, or catfile($INSTALL_ROOT,$file) if $INSTALL_ROOT
540is defined.
541
542=item install_rooted_dir( $dir )
543
544Returns $dir, or catdir($INSTALL_ROOT,$dir) if $INSTALL_ROOT
545is defined.
546
547=end _undocumented
548
549=cut
550
551
479d2113 552sub install_rooted_file {
553 if (defined $INSTALL_ROOT) {
554 File::Spec->catfile($INSTALL_ROOT, $_[0]);
555 } else {
556 $_[0];
557 }
558}
559
560
561sub install_rooted_dir {
562 if (defined $INSTALL_ROOT) {
563 File::Spec->catdir($INSTALL_ROOT, $_[0]);
564 } else {
565 $_[0];
566 }
567}
568
3a465856 569=begin _undocumented
570
571=item forceunlink( $file, $tryhard )
572
573Tries to delete a file. If $tryhard is true then we will use whatever
574devious tricks we can to delete the file. Currently this only applies to
575Win32 in that it will try to use Win32API::File to schedule a delete at
576reboot. A wrapper for _unlink_or_rename().
577
578=end _undocumented
579
580=cut
581
479d2113 582
583sub forceunlink {
3a465856 584 my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC
585 _unlink_or_rename( $file, $tryhard );
479d2113 586}
587
3a465856 588=begin _undocumented
589
590=item directory_not_empty( $dir )
591
592Returns 1 if there is an .exists file somewhere in a directory tree.
593Returns 0 if there is not.
594
595=end _undocumented
596
597=cut
479d2113 598
456e5c25 599sub directory_not_empty ($) {
600 my($dir) = @_;
601 my $files = 0;
602 find(sub {
603 return if $_ eq ".exists";
604 if (-f) {
605 $File::Find::prune++;
606 $files = 1;
607 }
608 }, $dir);
609 return $files;
610}
611
479d2113 612
613=item B<install_default> I<DISCOURAGED>
614
615 install_default();
616 install_default($fullext);
617
618Calls install() with arguments to copy a module from blib/ to the
619default site installation location.
620
621$fullext is the name of the module converted to a directory
622(ie. Foo::Bar would be Foo/Bar). If $fullext is not specified, it
623will attempt to read it from @ARGV.
624
625This is primarily useful for install scripts.
626
627B<NOTE> This function is not really useful because of the hard-coded
628install location with no way to control site vs core vs vendor
629directories and the strange way in which the module name is given.
630Consider its use discouraged.
631
632=cut
633
c3648e42 634sub install_default {
635 @_ < 2 or die "install_default should be called with 0 or 1 argument";
636 my $FULLEXT = @_ ? shift : $ARGV[0];
637 defined $FULLEXT or die "Do not know to where to write install log";
7292dc67 638 my $INST_LIB = File::Spec->catdir($Curdir,"blib","lib");
639 my $INST_ARCHLIB = File::Spec->catdir($Curdir,"blib","arch");
640 my $INST_BIN = File::Spec->catdir($Curdir,'blib','bin');
641 my $INST_SCRIPT = File::Spec->catdir($Curdir,'blib','script');
642 my $INST_MAN1DIR = File::Spec->catdir($Curdir,'blib','man1');
643 my $INST_MAN3DIR = File::Spec->catdir($Curdir,'blib','man3');
c3648e42 644 install({
645 read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist",
646 write => "$Config{installsitearch}/auto/$FULLEXT/.packlist",
456e5c25 647 $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ?
648 $Config{installsitearch} :
649 $Config{installsitelib},
c3648e42 650 $INST_ARCHLIB => $Config{installsitearch},
651 $INST_BIN => $Config{installbin} ,
652 $INST_SCRIPT => $Config{installscript},
653 $INST_MAN1DIR => $Config{installman1dir},
654 $INST_MAN3DIR => $Config{installman3dir},
655 },1,0,0);
656}
657
479d2113 658
659=item B<uninstall>
660
661 uninstall($packlist_file);
662 uninstall($packlist_file, $verbose, $dont_execute);
663
664Removes the files listed in a $packlist_file.
665
666If $verbose is true, will print out each file removed. Default is
667false.
668
669If $dont_execute is true it will only print what it was going to do
670without actually doing it. Default is false.
671
672=cut
673
4b6d56d3 674sub uninstall {
354f3b56 675 use ExtUtils::Packlist;
4b6d56d3 676 my($fil,$verbose,$nonono) = @_;
479d2113 677 $verbose ||= 0;
678 $nonono ||= 0;
679
4b6d56d3 680 die "no packlist file found: $fil" unless -f $fil;
f1387719 681 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
682 # require $my_req; # Hairy, but for the first
354f3b56 683 my ($packlist) = ExtUtils::Packlist->new($fil);
684 foreach (sort(keys(%$packlist))) {
4b6d56d3 685 chomp;
686 print "unlink $_\n" if $verbose;
3a465856 687 forceunlink($_,'tryhard') unless $nonono;
4b6d56d3 688 }
689 print "unlink $fil\n" if $verbose;
3a465856 690 forceunlink($fil, 'tryhard') unless $nonono;
691 _do_cleanup($verbose);
f1387719 692}
693
3a465856 694=begin _undocumented
695
696=item inc_uninstall($filepath,$libdir,$verbose,$nonono,$ignore)
697
698Remove shadowed files. If $ignore is true then it is assumed to hold
699a filename to ignore. This is used to prevent spurious warnings from
700occuring when doing an install at reboot.
701
702=end _undocumented
703
704=cut
705
f1387719 706sub inc_uninstall {
3a465856 707 my($filepath,$libdir,$verbose,$nonono,$ignore) = @_;
f1387719 708 my($dir);
3a465856 709 $ignore||="";
1df8d179 710 my $file = (File::Spec->splitpath($filepath))[2];
f1387719 711 my %seen_dir = ();
1df8d179 712
3a465856 713 my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'}
1df8d179 714 ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
715
456e5c25 716 foreach $dir (@INC, @PERL_ENV_LIB, @Config{qw(archlibexp
717 privlibexp
718 sitearchexp
719 sitelibexp)}) {
3a465856 720 my $canonpath = File::Spec->canonpath($dir);
721 next if $canonpath eq $Curdir;
722 next if $seen_dir{$canonpath}++;
723 my $targetfile = File::Spec->catfile($canonpath,$libdir,$file);
f1387719 724 next unless -f $targetfile;
725
726 # The reason why we compare file's contents is, that we cannot
727 # know, which is the file we just installed (AFS). So we leave
728 # an identical file in place
729 my $diff = 0;
1df8d179 730 if ( -f $targetfile && -s _ == -s $filepath) {
f1387719 731 # We have a good chance, we can skip this one
1df8d179 732 $diff = compare($filepath,$targetfile);
f1387719 733 } else {
f1387719 734 $diff++;
735 }
3a465856 736 print "#$file and $targetfile differ\n" if $diff && $verbose > 1;
f1387719 737
3a465856 738 next if !$diff or $targetfile eq $ignore;
f1387719 739 if ($nonono) {
740 if ($verbose) {
3a465856 741 $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new();
4f44ac69 742 $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier.
479d2113 743 $Inc_uninstall_warn_handler->add(
744 File::Spec->catfile($libdir, $file),
745 $targetfile
746 );
f1387719 747 }
748 # if not verbose, we just say nothing
749 } else {
750 print "Unlinking $targetfile (shadowing?)\n";
3a465856 751 forceunlink($targetfile,'tryhard');
f1387719 752 }
753 }
08ad6bd5 754}
755
3a465856 756=begin _undocumented
757
758=item run_filter($cmd,$src,$dest)
759
760Filter $src using $cmd into $dest.
761
762=end _undocumented
763
764=cut
765
131aa089 766sub run_filter {
767 my ($cmd, $src, $dest) = @_;
1df8d179 768 local(*CMD, *SRC);
57b1a898 769 open(CMD, "|$cmd >$dest") || die "Cannot fork: $!";
770 open(SRC, $src) || die "Cannot open $src: $!";
131aa089 771 my $buf;
772 my $sz = 1024;
57b1a898 773 while (my $len = sysread(SRC, $buf, $sz)) {
774 syswrite(CMD, $buf, $len);
131aa089 775 }
57b1a898 776 close SRC;
777 close CMD or die "Filter command '$cmd' failed for $src";
131aa089 778}
779
479d2113 780
781=item B<pm_to_blib>
782
783 pm_to_blib(\%from_to, $autosplit_dir);
784 pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
785
786Copies each key of %from_to to its corresponding value efficiently.
787Filenames with the extension .pm are autosplit into the $autosplit_dir.
af7522e5 788Any destination directories are created.
479d2113 789
790$filter_cmd is an optional shell command to run each .pm file through
791prior to splitting and copying. Input is the contents of the module,
792output the new module contents.
793
794You can have an environment variable PERL_INSTALL_ROOT set which will
795be prepended as a directory to each installed file (and directory).
796
797=cut
798
08ad6bd5 799sub pm_to_blib {
131aa089 800 my($fromto,$autodir,$pm_filter) = @_;
08ad6bd5 801
802 use File::Basename qw(dirname);
803 use File::Copy qw(copy);
804 use File::Path qw(mkpath);
fb73857a 805 use File::Compare qw(compare);
08ad6bd5 806 use AutoSplit;
807
08ad6bd5 808 mkpath($autodir,0,0755);
479d2113 809 while(my($from, $to) = each %$fromto) {
dedf98bc 810 if( -f $to && -s $from == -s $to && -M $to < -M $from ) {
811 print "Skip $to (unchanged)\n";
812 next;
813 }
131aa089 814
815 # When a pm_filter is defined, we need to pre-process the source first
816 # to determine whether it has changed or not. Therefore, only perform
817 # the comparison check when there's no filter to be ran.
818 # -- RAM, 03/01/2001
819
3a465856 820 my $need_filtering = defined $pm_filter && length $pm_filter &&
479d2113 821 $from =~ /\.pm$/;
131aa089 822
479d2113 823 if (!$need_filtering && 0 == compare($from,$to)) {
824 print "Skip $to (unchanged)\n";
08ad6bd5 825 next;
826 }
479d2113 827 if (-f $to){
3a465856 828 # we wont try hard here. its too likely to mess things up.
479d2113 829 forceunlink($to);
131aa089 830 } else {
479d2113 831 mkpath(dirname($to),0,0755);
131aa089 832 }
833 if ($need_filtering) {
479d2113 834 run_filter($pm_filter, $from, $to);
835 print "$pm_filter <$from >$to\n";
08ad6bd5 836 } else {
479d2113 837 copy($from,$to);
838 print "cp $from $to\n";
08ad6bd5 839 }
479d2113 840 my($mode,$atime,$mtime) = (stat $from)[2,8,9];
841 utime($atime,$mtime+$Is_VMS,$to);
3a465856 842 _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
479d2113 843 next unless $from =~ /\.pm$/;
844 _autosplit($to,$autodir);
08ad6bd5 845 }
4b6d56d3 846}
847
479d2113 848
849=begin _private
850
851=item _autosplit
852
853From 1.0307 back, AutoSplit will sometimes leave an open filehandle to
854the file being split. This causes problems on systems with mandatory
855locking (ie. Windows). So we wrap it and close the filehandle.
856
857=end _private
858
859=cut
860
3a465856 861sub _autosplit { #XXX OS-SPECIFIC
479d2113 862 my $retval = autosplit(@_);
863 close *AutoSplit::IN if defined *AutoSplit::IN{IO};
864
865 return $retval;
866}
867
868
f1387719 869package ExtUtils::Install::Warn;
870
871sub new { bless {}, shift }
872
873sub add {
874 my($self,$file,$targetfile) = @_;
875 push @{$self->{$file}}, $targetfile;
876}
877
878sub DESTROY {
479d2113 879 unless(defined $INSTALL_ROOT) {
880 my $self = shift;
881 my($file,$i,$plural);
882 foreach $file (sort keys %$self) {
883 $plural = @{$self->{$file}} > 1 ? "s" : "";
884 print "## Differing version$plural of $file found. You might like to\n";
885 for (0..$#{$self->{$file}}) {
886 print "rm ", $self->{$file}[$_], "\n";
887 $i++;
888 }
889 }
890 $plural = $i>1 ? "all those files" : "this file";
3a465856 891 my $inst = (_invokant() eq 'ExtUtils::MakeMaker')
892 ? ( $Config::Config{make} || 'make' ).' install UNINST=1'
893 : './Build install uninst=1';
894 print "## Running '$inst' will unlink $plural for you.\n";
479d2113 895 }
f1387719 896}
897
3a465856 898=begin _private
899
900=item _invokant
901
902Does a heuristic on the stack to see who called us for more intelligent
903error messages. Currently assumes we will be called only by Module::Build
904or by ExtUtils::MakeMaker.
905
906=end _private
907
908=cut
909
910sub _invokant {
911 my @stack;
912 my $frame = 0;
913 while (my $file = (caller($frame++))[1]) {
914 push @stack, (File::Spec->splitpath($file))[2];
915 }
916
917 my $builder;
918 my $top = pop @stack;
919 if ($top =~ /^Build/i || exists($INC{'Module/Build.pm'})) {
920 $builder = 'Module::Build';
921 } else {
922 $builder = 'ExtUtils::MakeMaker';
923 }
924 return $builder;
925}
926
4b6d56d3 927
3a465856 928=back
4b6d56d3 929
479d2113 930=head1 ENVIRONMENT
4b6d56d3 931
479d2113 932=over 4
4b6d56d3 933
479d2113 934=item B<PERL_INSTALL_ROOT>
4b6d56d3 935
479d2113 936Will be prepended to each install path.
4b6d56d3 937
3a465856 938=item B<EU_INSTALL_IGNORE_SKIP>
939
940Will prevent the automatic use of INSTALL.SKIP as the install skip file.
941
942=item B<EU_INSTALL_SITE_SKIPFILE>
943
944If there is no INSTALL.SKIP file in the make directory then this value
945can be used to provide a default.
946
479d2113 947=back
4b6d56d3 948
479d2113 949=head1 AUTHOR
4b6d56d3 950
479d2113 951Original author lost in the mists of time. Probably the same as Makemaker.
08ad6bd5 952
3a465856 953Production release currently maintained by demerphq C<yves at cpan.org>
4b6d56d3 954
479d2113 955Send bug reports via http://rt.cpan.org/. Please send your
956generated Makefile along with your report.
4b6d56d3 957
479d2113 958=head1 LICENSE
959
3a465856 960This program is free software; you can redistribute it and/or
479d2113 961modify it under the same terms as Perl itself.
962
a7d1454b 963See L<http://www.perl.com/perl/misc/Artistic.html>
4b6d56d3 964
ae1d6394 965
08ad6bd5 966=cut
479d2113 967
9681;