]> git.donarmstrong.com Git - debhelper.git/blob - dh_installdocs
Bug#545676: dh_installdocs: option to link documentation directories
[debhelper.git] / dh_installdocs
1 #!/usr/bin/perl -w
2
3 =head1 NAME
4
5 dh_installdocs - install documentation into package build directories
6
7 =cut
8
9 use strict;
10 use Debian::Debhelper::Dh_Lib;
11
12 =head1 SYNOPSIS
13
14 B<dh_installdocs> [S<I<debhelper options>>] [B<-A>] [B<-X>I<item>] [S<I<file ...>>]
15
16 =head1 DESCRIPTION
17
18 dh_installdocs is a debhelper program that is responsible for installing
19 documentation into usr/share/doc/package in package build directories.
20
21 =head1 FILES
22
23 =over 4
24
25 =item debian/I<package>.docs
26
27 List documentaton files to be installed into I<package>.
28
29 =item debian/copyright
30
31 =item debian/README.Debian
32
33 =item debian/TODO
34
35 =item debian/I<package>.copyright
36
37 =item debian/I<package>.README.Debian
38
39 =item debian/I<package>.TODO
40
41 Each of these files is automatically installed if present. Use the package
42 specific name if I<package> needs a different version of the file.
43
44 Note that debian/README.debian is also installed as README.Debian,
45 and debian/TODO will be installed as TODO.Debian in non-native packages.
46
47 =item debian/I<package>.doc-base
48
49 Installed as doc-base control files. Note that the doc-id will be
50 determined from the "Document:" entry in the doc-base control file in
51 question.
52
53 =item debian/I<package>.doc-base.*
54
55 If your package needs to register more than one document, you need multiple
56 doc-base files, and can name them like this.
57
58 =back
59
60 =head1 OPTIONS
61
62 =over 4
63
64 =item B<-A>, B<--all>
65
66 Install all files specified by command line parameters in ALL packages
67 acted on.
68
69 =item B<-Xitem>, B<--exclude=item>
70
71 Exclude files that contain "item" anywhere in their filename from
72 being installed. Note that this includes doc-base files.
73
74 =item B<--link-doc=>I<package>
75
76 Make the documentation directory of all packages acted on be a symlink to
77 the documentation directory of I<package>. This has no effect when acting on
78 I<package> itself, or if the documentation directory to be created already
79 exists when B<dh_installdocs> is run. To comply with policy, I<package> must
80 be a binary package that comes from the same source package.
81
82 debhelper will try to avoid installing files into linked documentation
83 directories that would cause conflicts with the linked package. The B<-A>
84 option will have no effect on packages with linked documentation
85 directories, and copyright, changelog, README.Debian, and TODO files will
86 not be installed.
87
88 =item I<file ...>
89
90 Install these files as documentation into the first package acted on. (Or
91 in all packages if B<-A> is specified).
92
93 =back
94
95 =head1 EXAMPLES
96
97 This is an example of a debian/package.docs file:
98
99   README
100   TODO
101   debian/notes-for-maintainers.txt
102   docs/manual.txt
103   docs/manual.pdf
104   docs/manual-html/
105
106 =head1 NOTES
107
108 Note that dh_installdocs will happily copy entire directory hierarchies if
109 you ask it to (similar to cp -a). If it is asked to install a
110 directory, it will install the complete contents of the directory.
111
112 Note that this command is not idempotent. L<dh_prep(1)> should be called
113 between invocations of this command. Otherwise, it may cause multiple
114 instances of the same text to be added to maintainer scripts.
115
116 =cut
117
118 my %docdir_created;
119 # Create documentation directories on demand. This allows us to use dangling
120 # symlinks for linked documentation directories unless additional files need
121 # to be installed.
122 sub ensure_docdir {
123         my $package=shift;
124         return if $docdir_created{$package};
125         my $tmp=tmpdir($package);
126
127         my $target;
128         if ($dh{LINK_DOC} && $dh{LINK_DOC} ne $package) {
129                 $target="$tmp/usr/share/doc/$dh{LINK_DOC}";
130         }
131         else {
132                 $target="$tmp/usr/share/doc/$package";
133         }
134
135         # If this is a symlink, leave it alone.
136         if (! -d $target && ! -l $target) {
137                 doit("install","-g",0,"-o",0,"-d",$target);
138         }
139         $docdir_created{$package}=1;
140 }
141
142 init(options => {
143         "link-doc=s" => \$dh{LINK_DOC},
144 });
145
146 foreach my $package (@{$dh{DOPACKAGES}}) {
147         next if is_udeb($package);
148         
149         my $tmp=tmpdir($package);
150         my $file=pkgfile($package,"docs");
151         my $link_doc=($dh{LINK_DOC} && $dh{LINK_DOC} ne $package);
152
153         if ($link_doc) {
154                 # Make sure that the parent directory exists.
155                 if (! -d "$tmp/usr/share/doc" && ! -l "$tmp/usr/share/doc") {
156                         doit("install","-g",0,"-o",0,"-d","$tmp/usr/share/doc");
157                 }
158                 # Create symlink to another documentation directory if
159                 # necessary.
160                 if (! -d "$tmp/usr/share/doc/$package" &&
161                     ! -l "$tmp/usr/share/doc/$package") {
162                         doit("ln", "-sf", $dh{LINK_DOC}, "$tmp/usr/share/doc/$package");
163                         # Policy says that if you make your documentation
164                         # directory a symlink, then you have to depend on
165                         # the target.
166                         addsubstvar($package, "misc:Depends", $dh{LINK_DOC});
167                 }
168         }
169         else {
170                 ensure_docdir($package);
171         }
172
173         my @docs;
174
175         if ($file) {
176                 @docs=filearray($file, ".");
177         }
178
179         if (($package eq $dh{FIRSTPACKAGE} || ($dh{PARAMS_ALL} && ! $link_doc)) && @ARGV) {
180                 push @docs, @ARGV;
181         }
182
183         if (@docs) {
184                 my $exclude = '';
185                 if ($dh{EXCLUDE_FIND}) {
186                         $exclude .= ' -and ! \( '.$dh{EXCLUDE_FIND}.' \)';
187                 }
188                 if (! compat(4)) {
189                         # ignore empty files in subdirs
190                         $exclude .= ' -and ! -empty';
191                 }
192                 foreach my $doc (@docs) {
193                         next if excludefile($doc);
194                         next if -e $doc && ! -s $doc && ! compat(4); # ignore empty files
195                         ensure_docdir($package);
196                         if (-d $doc && length $exclude) {
197                                 my $basename = basename($doc);
198                                 my $dir = ($basename eq '.') ? $doc : "$doc/..";
199                                 my $pwd=`pwd`;
200                                 chomp $pwd;
201                                 complex_doit("cd '$dir' && find '$basename' \\( -type f -or -type l \\)$exclude -exec cp --parents -dp {} $pwd/$tmp/usr/share/doc/$package \\;");
202                         }
203                         else {
204                                 doit("cp", "-a", $doc, "$tmp/usr/share/doc/$package");
205                         }
206                 }
207                 doit("chown","-R","0:0","$tmp/usr/share/doc");
208                 doit("chmod","-R","go=rX","$tmp/usr/share/doc");
209                 doit("chmod","-R","u+rw","$tmp/usr/share/doc");
210         }
211
212         # .Debian is correct, according to policy, but I'm easy.
213         my $readme_debian=pkgfile($package,'README.Debian');
214         if (! $readme_debian) {
215                 $readme_debian=pkgfile($package,'README.debian');
216         }
217         if (! $link_doc && $readme_debian && ! excludefile($readme_debian)) {
218                 ensure_docdir($package);
219                 doit("install","-g",0,"-o",0,"-m","644","-p","$readme_debian",
220                         "$tmp/usr/share/doc/$package/README.Debian");
221         }
222
223         my $todo=pkgfile($package,'TODO');
224         if (! $link_doc && $todo && ! excludefile($todo)) {
225                 ensure_docdir($package);
226                 if (isnative($package)) {
227                         doit("install","-g",0,"-o",0,"-m","644","-p",$todo,
228                                 "$tmp/usr/share/doc/$package/TODO");
229                 }
230                 else {
231                         doit("install","-g",0,"-o",0,"-m","644","-p",$todo,
232                                 "$tmp/usr/share/doc/$package/TODO.Debian");
233                 }
234         }
235
236         # If the "directory" is a dangling symlink, then don't install
237         # the copyright file. This is useful for multibinary packages 
238         # that share a doc directory.
239         if (! $link_doc && (! -l "$tmp/usr/share/doc/$package" || -d "$tmp/usr/share/doc/$package")) {
240                 # Support debian/package.copyright, but if not present, fall
241                 # back on debian/copyright for all packages, not just the 
242                 # main binary package.
243                 my $copyright=pkgfile($package,'copyright');
244                 if (! $copyright && -e "debian/copyright") {
245                         $copyright="debian/copyright";
246                 }
247                 if ($copyright && ! excludefile($copyright)) {
248                         ensure_docdir($package);
249                         doit("install","-g",0,"-o",0,"-m","644","-p",$copyright,
250                                 "$tmp/usr/share/doc/$package/copyright");
251                 }
252         }
253
254         # Handle doc-base files. There are two filename formats, the usual
255         # plus an extended format (debian/package.*).
256         my %doc_ids;
257         
258         opendir(DEB,"debian/") || error("can't read debian directory: $!");
259         # If this is the main package, we need to handle unprefixed filenames.
260         # For all packages, we must support both the usual filename format plus
261         # that format with a period an something appended.
262         my $regexp="\Q$package\E\.";
263         if ($package eq $dh{MAINPACKAGE}) {
264                 $regexp="(|$regexp)";
265         }
266         foreach my $fn (grep {/^${regexp}doc-base(\..*)?$/} readdir(DEB)) {
267                 # .EX are example files, generated by eg, dh-make
268                 next if $fn=~/\.EX$/;
269                 next if excludefile($fn);
270                 # Parse the file to get the doc id.
271                 open (IN, "debian/$fn") || die "Cannot read debian/$fn.";
272                 while (<IN>) {
273                         s/\s*$//;
274                         if (/^Document\s*:\s*(.*)/) {
275                                 $doc_ids{$fn}=$1;
276                                 last;
277                         }
278                 }
279                 close IN;
280         }
281         closedir(DEB);
282         
283         if (%doc_ids) {
284                 if (! -d "$tmp/usr/share/doc-base/") {
285                         doit("install","-g",0,"-o",0,"-d","$tmp/usr/share/doc-base/");
286                 }
287         }
288         foreach my $fn (keys %doc_ids) {
289                 doit("install","-g",0,"-o",0,"-m644","-p","debian/$fn",
290                      "$tmp/usr/share/doc-base/$doc_ids{$fn}");
291         }
292 }
293
294 =head1 SEE ALSO
295
296 L<debhelper(7)>
297
298 This program is a part of debhelper.
299
300 =head1 AUTHOR
301
302 Joey Hess <joeyh@debian.org>
303
304 =cut