1 package ExtUtils::Install;
3 $VERSION = substr q$Revision: 1.16 $, 10;
4 # $Date: 1996/12/17 00:31:26 $
9 use vars qw(@ISA @EXPORT $VERSION);
11 @EXPORT = ('install','uninstall','pm_to_blib');
12 $Is_VMS = $^O eq 'VMS';
14 my $splitchar = $^O eq 'VMS' ? '|' : $^O eq 'os2' ? ';' : ':';
15 my @PERL_ENV_LIB = split $splitchar, defined $ENV{'PERL5LIB'} ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
16 my $Inc_uninstall_warn_handler;
18 #use vars qw( @EXPORT @ISA $Is_VMS );
23 unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!")
27 my($hash,$verbose,$nonono,$inc_uninstall) = @_;
32 use ExtUtils::MakeMaker; # to implement a MY class
33 use File::Basename qw(dirname);
34 use File::Copy qw(copy);
35 use File::Find qw(find);
36 use File::Path qw(mkpath);
39 my(%pack, %write, $dir, $warn_permissions);
41 for (qw/read write/) {
45 my($source_dir_or_file);
46 foreach $source_dir_or_file (sort keys %hash) {
47 #Check if there are files, and if yes, look if the corresponding
48 #target directory is writable for us
49 opendir DIR, $source_dir_or_file or next;
51 next if $_ eq "." || $_ eq ".." || $_ eq ".exists";
52 next if /^P\d+$/ && -d "$source_dir_or_file/$_"; # no Chip bk's
53 if (-w $hash{$source_dir_or_file} || mkpath($hash{$source_dir_or_file})) {
56 warn "Warning: You do not have permissions to install into $hash{$source_dir_or_file}"
57 unless $warn_permissions++;
62 if (-f $pack{"read"}) {
63 open P, $pack{"read"} or Carp::croak("Couldn't read $pack{'read'}");
64 # Remember what you found
72 my $umask = umask 0 unless $Is_VMS;
74 # This silly reference is just here to be able to call MY->catdir
75 # without a warning (Waiting for a proper path/directory module,
80 MOD_INSTALL: foreach $source (sort keys %hash) {
81 #copy the tree to the target directory without altering
82 #timestamp and permission and remember for the .packlist
83 #file. The packlist file contains the absolute paths of the
84 #install locations. AFS users may call this a bug. We'll have
85 #to reconsider how to add the means to satisfy AFS users also.
86 chdir($source) or next;
88 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
89 $atime,$mtime,$ctime,$blksize,$blocks) = stat;
91 return if $_ eq ".exists";
92 return if /\bP\d+\b/; # no Chip-style backups
93 my $targetdir = $MY->catdir($hash{$source},$File::Find::dir);
94 my $targetfile = $MY->catfile($targetdir,$_);
97 if ( -f $targetfile && -s _ == $size) {
98 # We have a good chance, we can skip this one
99 $diff = my_cmp($_,$targetfile);
101 print "$_ differs\n" if $verbose>1;
107 forceunlink($targetfile) unless $nonono;
109 mkpath($targetdir,0,0755) unless $nonono;
110 print "mkpath($targetdir,0,0755)\n" if $verbose>1;
112 copy($_,$targetfile) unless $nonono;
113 print "Installing $targetfile\n";
114 utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1;
115 print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
116 $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
117 chmod $mode, $targetfile;
118 print "chmod($mode, $targetfile)\n" if $verbose>1;
120 print "Skipping $targetfile (unchanged)\n" if $verbose;
123 if (! defined $inc_uninstall) { # it's called
124 } elsif ($inc_uninstall == 0){
125 inc_uninstall($_,$File::Find::dir,$verbose,1); # nonono set to 1
127 inc_uninstall($_,$File::Find::dir,$verbose,0); # nonono set to 0
129 $write{$targetfile}++;
132 chdir($cwd) or Carp::croak("Couldn't chdir to $cwd: $!");
134 umask $umask unless $Is_VMS;
135 if ($pack{'write'}) {
136 $dir = dirname($pack{'write'});
138 print "Writing $pack{'write'}\n";
139 open P, ">$pack{'write'}" or Carp::croak("Couldn't write $pack{'write'}: $!");
140 for (sort keys %write) {
151 open T, $two or return 1;
152 open F, $one or Carp::croak("Couldn't open $one: $!");
153 my($fr, $tr, $fbuf, $tbuf, $size);
155 # print "Reading $one\n";
156 while ( $fr = read(F,$fbuf,$size)) {
158 $tr = read(T,$tbuf,$size) and
174 my($fil,$verbose,$nonono) = @_;
175 die "no packlist file found: $fil" unless -f $fil;
176 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
177 # require $my_req; # Hairy, but for the first
179 open P, $fil or Carp::croak("uninstall: Could not read packlist file $fil: $!");
182 print "unlink $_\n" if $verbose;
183 forceunlink($_) unless $nonono;
185 print "unlink $fil\n" if $verbose;
186 forceunlink($fil) unless $nonono;
190 my($file,$libdir,$verbose,$nonono) = @_;
195 foreach $dir (@INC, @PERL_ENV_LIB, @Config::Config{qw/archlibexp privlibexp sitearchexp sitelibexp/}) {
197 next if $seen_dir{$dir}++;
198 my($targetfile) = $MY->catfile($dir,$libdir,$file);
199 next unless -f $targetfile;
201 # The reason why we compare file's contents is, that we cannot
202 # know, which is the file we just installed (AFS). So we leave
203 # an identical file in place
205 if ( -f $targetfile && -s _ == -s $file) {
206 # We have a good chance, we can skip this one
207 $diff = my_cmp($file,$targetfile);
209 print "#$file and $targetfile differ\n" if $verbose>1;
216 $Inc_uninstall_warn_handler ||= new ExtUtils::Install::Warn;
217 $libdir =~ s|^\./|| ; # That's just cosmetics, no need to port. It looks prettier.
218 $Inc_uninstall_warn_handler->add("$libdir/$file",$targetfile);
220 # if not verbose, we just say nothing
222 print "Unlinking $targetfile (shadowing?)\n";
223 forceunlink($targetfile);
229 my($fromto,$autodir) = @_;
231 use File::Basename qw(dirname);
232 use File::Copy qw(copy);
233 use File::Path qw(mkpath);
235 # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
236 # require $my_req; # Hairy, but for the first
238 if (!ref($fromto) && -r $fromto)
240 # Win32 has severe command line length limitations, but
241 # can generate temporary files on-the-fly
242 # so we pass name of file here - eval it to get hash
243 open(FROMTO,"<$fromto") or die "Cannot open $fromto:$!";
244 my $str = '$fromto = {qw{'.join('',<FROMTO>).'}}';
249 my $umask = umask 0022 unless $Is_VMS;
250 mkpath($autodir,0,0755);
251 foreach (keys %$fromto) {
252 next if -f $fromto->{$_} && -M $fromto->{$_} < -M $_;
253 unless (my_cmp($_,$fromto->{$_})){
254 print "Skip $fromto->{$_} (unchanged)\n";
257 if (-f $fromto->{$_}){
258 forceunlink($fromto->{$_});
260 mkpath(dirname($fromto->{$_}),0,0755);
262 copy($_,$fromto->{$_});
263 my($mode,$atime,$mtime) = (stat)[2,8,9];
264 utime($atime,$mtime+$Is_VMS,$fromto->{$_});
265 chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$fromto->{$_});
266 print "cp $_ $fromto->{$_}\n";
268 autosplit($fromto->{$_},$autodir);
270 umask $umask unless $Is_VMS;
273 package ExtUtils::Install::Warn;
275 sub new { bless {}, shift }
278 my($self,$file,$targetfile) = @_;
279 push @{$self->{$file}}, $targetfile;
284 my($file,$i,$plural);
285 foreach $file (sort keys %$self) {
286 $plural = @{$self->{$file}} > 1 ? "s" : "";
287 print "## Differing version$plural of $file found. You might like to\n";
288 for (0..$#{$self->{$file}}) {
289 print "rm ", $self->{$file}[$_], "\n";
293 $plural = $i>1 ? "all those files" : "this file";
294 print "## Running 'make install UNINST=1' will unlink $plural for you.\n";
303 ExtUtils::Install - install files from here to there
307 B<use ExtUtils::Install;>
309 B<install($hashref,$verbose,$nonono);>
311 B<uninstall($packlistfile,$verbose,$nonono);>
313 B<pm_to_blib($hashref);>
317 Both install() and uninstall() are specific to the way
318 ExtUtils::MakeMaker handles the installation and deinstallation of
319 perl modules. They are not designed as general purpose tools.
321 install() takes three arguments. A reference to a hash, a verbose
322 switch and a don't-really-do-it switch. The hash ref contains a
323 mapping of directories: each key/value pair is a combination of
324 directories to be copied. Key is a directory to copy from, value is a
325 directory to copy to. The whole tree below the "from" directory will
326 be copied preserving timestamps and permissions.
328 There are two keys with a special meaning in the hash: "read" and
329 "write". After the copying is done, install will write the list of
330 target files to the file named by C<$hashref-E<gt>{write}>. If there is
331 another file named by C<$hashref-E<gt>{read}>, the contents of this file will
332 be merged into the written file. The read and the written file may be
333 identical, but on AFS it is quite likely, people are installing to a
334 different directory than the one where the files later appear.
336 uninstall() takes as first argument a file containing filenames to be
337 unlinked. The second argument is a verbose switch, the third is a
338 no-don't-really-do-it-now switch.
340 pm_to_blib() takes a hashref as the first argument and copies all keys
341 of the hash to the corresponding values efficiently. Filenames with
342 the extension pm are autosplit. Second argument is the autosplit