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