Re: [PATCH] sv.c: consting
[p5sagit/p5-mst-13.2.git] / installman
1 #!./perl -w
2 BEGIN { @INC = qw(lib) }
3 use strict;
4
5 BEGIN {
6     use Config;
7     if ($Config{userelocatableinc}) {
8         # This might be a considered a hack. Need to get information about the
9         # configuration from Config.pm *before* Config.pm expands any .../
10         # prefixes.
11         #
12         # So we set $^X to pretend that we're the already installed perl, so
13         # Config.pm doesits ... expansion off that location.
14
15         my $location = $Config{initialinstalllocation};
16         die <<'OS' unless defined $location;
17 $Config{initialinstalllocation} is not defined - can't install a relocatable
18 perl without this.
19 OS
20         $^X = "$location/perl";
21         # And then remove all trace of ever having loaded Config.pm, so that
22         # it will reload with the revised $^X
23         undef %Config::;
24         delete $INC{"Config.pm"};
25         delete $INC{"Config_heavy.pl"};
26         # You never saw us. We weren't here.
27     }
28 }
29
30 use Config;
31 use Getopt::Long;
32 use File::Find;
33 use File::Copy;
34 use File::Path qw(mkpath);
35 use ExtUtils::Packlist;
36 use Pod::Man;
37 use subs qw(unlink chmod rename link);
38 use vars qw($packlist);
39
40 if ($Config{d_umask}) {
41     umask(022); # umasks like 077 aren't that useful for installations
42 }
43
44 $ENV{SHELL} = 'sh' if $^O eq 'os2';
45
46 my $ver = $Config{version};     # Not used presently.
47 my $release = substr($],0,3);   # Not used presently.
48 my $patchlevel = substr($],3,2);
49 die "Patchlevel of perl ($patchlevel)",
50     "and patchlevel of config.sh ($Config{'PERL_VERSION'}) don't match\n"
51         if $patchlevel != $Config{'PERL_VERSION'};
52
53 my $usage =
54 "Usage:  installman --man1dir=/usr/wherever --man1ext=1
55                    --man3dir=/usr/wherever --man3ext=3
56                    --batchlimit=40
57                    --notify --verbose --silent --help
58         Defaults are:
59         man1dir = $Config{'installman1dir'};
60         man1ext = $Config{'man1ext'};
61         man3dir = $Config{'installman3dir'};
62         man3ext = $Config{'man3ext'};
63         --notify  (or -n) just lists commands that would be executed.
64         --verbose (or -V) report all progress.
65         --silent  (or -S) be silent. Only report errors.\n";
66
67 my %opts;
68 GetOptions( \%opts,
69             qw( man1dir=s man1ext=s man3dir=s man3ext=s batchlimit=i
70                 destdir:s notify n help silent S verbose V)) 
71         || die $usage;
72 die $usage if $opts{help};
73 $opts{destdir} //= '';
74
75 $opts{man1dir} = "$opts{destdir}$Config{'installman1dir'}"
76     unless defined($opts{man1dir}); 
77 $opts{man1ext} = $Config{'man1ext'}
78     unless defined($opts{man1ext}); 
79 $opts{man3dir} = "$opts{destdir}$Config{'installman3dir'}"
80     unless defined($opts{man3dir}); 
81 $opts{man3ext} = $Config{'man3ext'}
82     unless defined($opts{man3ext}); 
83 $opts{silent} ||= $opts{S};
84 $opts{notify} ||= $opts{n};
85 $opts{verbose} ||= $opts{V} || $opts{notify};
86
87 #Sanity checks
88
89 -x  "./perl$Config{exe_ext}" 
90   or warn "./perl$Config{exe_ext} not found!  Have you run make?\n";
91 -d  "$opts{destdir}$Config{'installprivlib'}"
92         || warn "Perl library directory $Config{'installprivlib'} not found.
93                 Have you run make install?.  (Installing anyway.)\n";
94 -x "t/perl$Config{exe_ext}"             || warn "WARNING: You've never run 'make test'!!!",
95         "  (Installing anyway.)\n";
96
97 $packlist = ExtUtils::Packlist->new("$opts{destdir}$Config{installarchlib}/.packlist");
98
99
100 # Install the main pod pages.
101 pod2man('pod', $opts{man1dir}, $opts{man1ext});
102
103 # Install the pods for library modules.
104 pod2man('lib', $opts{man3dir}, $opts{man3ext});
105
106 # Install the pods embedded in the installed scripts
107 my $has_man1dir = $opts{man1dir} ne '' && -d $opts{man1dir};
108 open UTILS, "utils.lst" or die "Can't open 'utils.lst': $!";
109 while (<UTILS>) {
110     next if /^#/;
111     chomp;
112     $_ = $1 if /#.*pod\s*=\s*(\S+)/;
113     my ($where, $what) = m|^(\S*)/(\S+)|;
114     pod2man($where, $opts{man1dir}, $opts{man1ext}, $what);
115     if ($has_man1dir) {
116         if (my ($where2, $what2) = m|#.*link\s*=\s*(\S+)/(\S+)|) {
117             my $old = "$opts{man1dir}/$what.$opts{man1ext}";
118             my $new = "$opts{man1dir}/$what2.$opts{man1ext}";
119             unlink($new);
120             link($old, $new);
121             my $xold = $old;
122             $xold =~ s/^\Q$opts{'destdir'}\E// if $opts{'destdir'};
123             my $xnew = $new;
124             $xnew =~ s/^\Q$opts{'destdir'}\E// if $opts{'destdir'};
125             $packlist->{$xnew} = { from => $xold, type => 'link' };
126         }
127     }
128 }
129
130 sub pod2man {
131     # @script is scripts names if we are installing manpages embedded 
132     # in scripts, () otherwise
133     my($poddir, $mandir, $manext, @script) = @_;
134     if ($mandir eq ' ' or $mandir eq '') {
135         if (@script) {
136             warn "Skipping installation of $poddir/$_ man page.\n"
137                 foreach @script;
138         } else {
139             warn "Skipping installation of $poddir man pages.\n";
140         }
141         return;
142     }
143
144     print "installing from $poddir\n" if $opts{verbose};
145
146     mkpath($mandir, $opts{verbose}, 0777) unless $opts{notify};  # In File::Path
147     # Make a list of all the .pm and .pod files in the directory.  We avoid
148     # chdir because we are running with @INC = '../lib', and modules may wish
149     # to dynamically require Carp::Heavy or other diagnostics warnings.
150     # Hash the names of files we find, keys are names relative to perl build
151     # dir ('.'), values are names relative to $poddir.
152     my %modpods;
153     if (@script) {
154         %modpods = (map {+"$poddir/$_", $_} @script);
155     }
156     else {
157         File::Find::find({no_chdir=>1,
158                           wanted => sub {
159                               # $_ is $File::Find::name when using no_chdir
160                               if (-f $_ and /\.p(?:m|od)$/) {
161                                   my $fullname = $_;
162                                   s!^\Q$poddir\E/!!;
163                                   $modpods{$fullname} = $_;
164                               }
165                           }},
166                          $poddir);
167     }
168     my @to_process;
169     foreach my $mod (sort keys %modpods) {
170         my $manpage = $modpods{$mod};
171         my $tmp;
172         # Skip .pm files that have corresponding .pod files, and Functions.pm.
173         next if (($tmp = $mod) =~ s/\.pm$/.pod/ && -f $tmp);
174         next if $mod =~ m:/t/:; # no pods from test directories 
175         next if ($manpage eq 'Pod/Functions.pm'); #### Used only by pod itself
176
177         # Skip files without pod docs
178         my $has_pod;
179         if (open T, $mod)
180         {
181             local $_;
182             while (<T>)
183             {
184                 ++$has_pod and last if /^=(?:head\d+|item|pod)\b/;
185             }
186
187             close T;
188         }
189
190         unless ($has_pod)
191         {
192             warn "no documentation in $mod\n";
193             next;
194         }
195
196         # Convert name from  File/Basename.pm to File::Basename.3 format,
197         # if necessary.
198         $manpage =~ s#\.p(m|od)$##;
199         if ($^O eq 'os2' || $^O eq 'amigaos' || $^O eq 'uwin' || $^O eq 'cygwin') {
200           $manpage =~ s#/#.#g;
201         }
202         else {
203           $manpage =~ s#/#::#g;
204         }
205         $tmp = "${mandir}/${manpage}.tmp";
206         $manpage = "${mandir}/${manpage}.${manext}";
207         push @to_process, [$mod, $tmp, $manpage];
208     }
209
210     foreach my $page (@to_process) {
211         my($pod, $tmp, $manpage) = @$page;
212
213         my $parser = Pod::Man->new( section => $manext,
214                                     official=> 1,
215                                     center  => 'Perl Programmers Reference Guide'
216                                   );
217         my $xmanpage = $manpage;
218         $xmanpage =~ s/^\Q$opts{'destdir'}\E// if $opts{'destdir'};
219         print "  $xmanpage\n";
220         if (!$opts{notify} && $parser->parse_from_file($pod, $tmp)) {
221             if (-s $tmp) {
222                 if (rename($tmp, $manpage)) {
223                     $packlist->{$xmanpage} = { type => 'file' };
224                     next;
225                 }
226             }
227             unlink($tmp);
228         }
229     }
230 }
231
232 $packlist->write() unless $opts{notify};
233 print "  Installation complete\n" if $opts{verbose};
234
235 exit 0;
236
237 ###############################################################################
238 # Utility subroutines from installperl
239
240 sub unlink {
241     my(@names) = @_;
242     my $cnt = 0;
243
244     foreach my $name (@names) {
245         next unless -e $name;
246         chmod 0777, $name if $^O eq 'os2';
247         print "  unlink $name\n" if $opts{verbose};
248         ( CORE::unlink($name) and ++$cnt 
249             or warn "Couldn't unlink $name: $!\n" ) unless $opts{notify};
250     }
251     return $cnt;
252 }
253
254 sub link {
255     my($from,$to) = @_;
256     my($success) = 0;
257
258     print "  ln $from $to\n" if $opts{verbose};
259     eval {
260         CORE::link($from, $to)
261             ? $success++
262             : ($from =~ m#^/afs/# || $to =~ m#^/afs/#)
263               ? die "AFS"  # okay inside eval {}
264               : warn "Couldn't link $from to $to: $!\n"
265           unless $opts{notify};
266     };
267     if ($@) {
268         File::Copy::copy($from, $to)
269             ? $success++
270             : warn "Couldn't copy $from to $to: $!\n"
271           unless $opts{notify};
272     }
273     $success;
274 }
275
276 sub rename {
277     my($from,$to) = @_;
278     if (-f $to and not unlink($to)) {
279         my($i);
280         for ($i = 1; $i < 50; $i++) {
281             last if CORE::rename($to, "$to.$i");
282         }
283         warn("Cannot rename to `$to.$i': $!"), return 0 
284             if $i >= 50;        # Give up!
285     }
286     link($from,$to) || return 0;
287     unlink($from);
288 }
289
290 sub chmod {
291     my($mode,$name) = @_;
292
293     printf "  chmod %o %s\n", $mode, $name if $opts{verbose};
294     CORE::chmod($mode,$name) || warn sprintf("Couldn't chmod %o %s: $!\n",$mode,$name)
295         unless $opts{notify};
296 }
297
298 sub samepath {
299     my($p1, $p2) = @_;
300     my($dev1, $ino1, $dev2, $ino2);
301
302     if ($p1 ne $p2) {
303         ($dev1, $ino1) = stat($p1);
304         ($dev2, $ino2) = stat($p2);
305         ($dev1 == $dev2 && $ino1 == $ino2);
306     }
307     else {
308         1;
309     }
310 }