]> git.donarmstrong.com Git - debhelper.git/blobdiff - dh_install
Fix build system auto-selection breakage.
[debhelper.git] / dh_install
index 65a99772ed8311a87088e85b12694c052468edf1..875f80bfe45d3be04e07525799ec98b45105d0f8 100755 (executable)
@@ -7,11 +7,12 @@ dh_install - install files into package build directories
 =cut
 
 use strict;
+use File::Find;
 use Debian::Debhelper::Dh_Lib;
 
 =head1 SYNOPSIS
 
-B<dh_install> [B<-X>I<item>] [S<I<debhelper options>>] [S<I<file [...] dest>>]
+B<dh_install> [B<-X>I<item>] [B<--autodest>] [B<--sourcedir=>I<dir>] [S<I<debhelper options>>] [S<I<file [...] dest>>]
 
 =head1 DESCRIPTION
 
@@ -23,31 +24,69 @@ those particular tasks. dh_install, then, is useful for installing everything
 else, for which no particular intelligence is needed. It is a replacement for
 the old dh_movefiles command.
 
-Files named debian/package.install list the files to install into each
-package and where they should be installed to. The format is a set of
-lines, where each line lists a file or files to install, and at the end of
-the line tells the directory it should be installed in. The name of the
-files (or directories) to install should be given relative to the current
-directory, while the installation directory is given relative to the
-package build directory. You may use wildcards in the names of the files to
-install (in v3 mode and above).
-
 This program may be used in one of two ways. If you just have a file or two
 that the upstream Makefile does not install for you, you can run dh_install
 on them to move them into place. On the other hand, maybe you have a large
-package that builds multiple binary packages. You can use the upstream Makefile
-to install it all into debian/tmp, and then use dh_install to copy
+package that builds multiple binary packages. You can use the upstream
+Makefile to install it all into debian/tmp, and then use dh_install to copy
 directories and files from there into the proper package build directories.
 
+From debhelper compatibility level 7 on, dh_install will fall back to
+looking in debian/tmp for files, if it doesn't find them in the current
+directory (or whereever you've told it to look using --sourcedir).
+
+=head1 FILES
+
+=over 4
+
+=item debian/I<package>.install
+
+List the files to install into each package and the directory they should be
+installed to. The format is a set of lines, where each line lists a file or
+files to install, and at the end of the line tells the directory it should be
+installed in. The name of the files (or directories) to install should be given
+relative to the current directory, while the installation directory is given
+relative to the package build directory. You may use wildcards in the names of
+the files to install (in v3 mode and above).
+
+=back
+
 =head1 OPTIONS
 
 =over 4
 
+=item B<--list-missing>
+
+This option makes dh_install keep track of the files it installs, and then at
+the end, compare that list with the files in the source directory. If any of
+the files (and symlinks) in the source directory were not installed to
+somewhere, it will warn on stderr about that.
+
+This may be useful if you have a large package and want to make sure that
+you don't miss installing newly added files in new upstream releases.
+
+Note that files that are excluded from being moved via the -X option are not
+warned about.
+
+=item B<--fail-missing>
+
+This option is like --list-missing, except if a file was missed, it will
+not only list the missing files, but also fail with a nonzero exit code. 
+
 =item B<-Xitem>, B<--exclude=item>
 
 Exclude files that contain "item" anywhere in their filename from
 being installed.
 
+=item B<--sourcedir=dir>
+
+Look in the specified directory for files to be installed.
+
+Note that this is not the same as the --sourcedirectory option used
+by the dh_auto_* commands. You rarely need to use this option, since
+dh_install automatically looks for files in debian/tmp in debhelper
+compatibility level 7 and above.
+
 =item B<--autodest>
 
 Guess as the destination directory to install things to. If this is
@@ -55,28 +94,17 @@ specified, you should not list destination directories in
 debian/package.install files or on the command line. Instead, dh_install
 will guess as follows:
 
-Strip off debian/tmp from the front of the filename, of it is present, and
-install into the dirname of the filename. So if the filename is
-debian/tmp/usr/bin, then that directory will be copied to 
-debian/package/usr/. If the filename is debian/tmp/etc/passwd, it will be 
-copied to debian/package/etc/.
+Strip off debian/tmp (or the sourcedir if one is given) from the front of
+the filename, if it is present, and install into the dirname of the
+filename. So if the filename is debian/tmp/usr/bin, then that directory
+will be copied to debian/package/usr/. If the filename is
+debian/tmp/etc/passwd, it will be copied to debian/package/etc/.
 
-Note that if you list only a filename on a line by itself in a
+Note that if you list exactly one filename or wildcard-pattern on a line by
+itself in a
 debian/package.install file, with no explicit destination, then dh_install
 will automatically guess the destination even if this flag is not set.
 
-=item B<--sourcedir=dir>
-
-Makes all source files relative to "dir". If this is specified, it is akin 
-to all the source files having "dir" prepended to them. By default, "dir"
-is '.'.
-
-To make dh_install behave like the old dh_movefiles, move your
-package.files file to package.install and call dh_install with
-"--sourcedir=debian/tmp" appended to the command. This will
-approximate dh_movefiles behaviour, except it will copy files instead
-of moving them.
-
 =item I<file [...] dest>
 
 Lists files (or directories) to install and where to install them to.
@@ -86,22 +114,27 @@ The files will be installed into the first package dh_install acts on.
 
 =cut
 
-init();
+init(options => {
+       "autodest" => \$dh{AUTODEST},
+       "list-missing" => \$dh{LIST_MISSING},
+       "fail-missing" => \$dh{FAIL_MISSING},
+       "sourcedir=s" => \$dh{SOURCEDIR},       
+});
+
+my @installed;
 
-my $ret=0;
+my $srcdir = '.';
+$srcdir = $dh{SOURCEDIR} if defined $dh{SOURCEDIR};
 
 foreach my $package (@{$dh{DOPACKAGES}}) {
        my $tmp=tmpdir($package);
        my $file=pkgfile($package,"install");
-       my $srcdir = '.';
 
        my @install;
        if ($file) {
                @install=filedoublearray($file); # no globbing yet
        }
        
-       $srcdir = $dh{SOURCEDIR}."/" if defined $dh{SOURCEDIR};
-       
        if (($package eq $dh{FIRSTPACKAGE} || $dh{PARAMS_ALL}) && @ARGV) {
                push @install, [@ARGV];
        }
@@ -109,24 +142,44 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
        # Support for -X flag.
        my $exclude = '';
        if ($dh{EXCLUDE_FIND}) {
-               $exclude = ' -and ! \( '.$dh{EXCLUDE_FIND}.' \)';
+               $exclude = '! \( '.$dh{EXCLUDE_FIND}.' \)';
        }
        
        foreach my $set (@install) {
                my $dest;
+               my $tmpdest=0;
                
                if (! defined $dh{AUTODEST} && @$set > 1) {
                        $dest=pop @$set;
                }
-               # glob now, relative to srcdir
-               foreach my $src (map { glob "$srcdir/$_" } @$set) { 
+
+               my @filelist;
+               foreach my $glob (@$set) {
+                       my @found = glob "$srcdir/$glob";
+                       if (! compat(6)) {
+                               # Fall back to looking in debian/tmp.
+                               if (! @found || ! (-e $found[0] || -l $found[0])) {
+                                       @found = glob "debian/tmp/$glob";
+                               }
+                       }
+                       push @filelist, @found;
+               }
+
+               if (! compat(4)) { # check added in v5
+                       if (! @filelist) {
+                               error("$package missing files (@$set), aborting");
+                       }
+               }
+               foreach my $src (@filelist) { 
                        next if excludefile($src);
                
                        if (! defined $dest) {
                                # Guess at destination directory.
                                $dest=$src;
-                               $dest=~s/^(.*\/)?debian\/tmp//;
-                               $dest=dirname($dest);
+                               $dest=~s/^(.*\/)?\Q$srcdir\E\///;
+                               $dest=~s/^(.*\/)?debian\/tmp\///;
+                               $dest=dirname("/".$dest);
+                               $tmpdest=1;
                        }
                        
                        # Make sure the destination directory exists.
@@ -134,23 +187,93 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
                                doit("install","-d","$tmp/$dest");
                        }
 
+                       # Keep track of what's installed.
+                       if ($dh{LIST_MISSING} || $dh{FAIL_MISSING}) {
+                               # Kill any extra slashes. Makes the
+                               # @installed stuff more robust.
+                               $src=~y:/:/:s;
+                               $src=~s:/+$::;
+                               $src=~s:^(\./)*::;
+                               push @installed, "\Q$src\E\/.*|\Q$src\E";
+                       }
+                       
                        if (-d $src && $exclude) {
-                               my ($dir_basename) = basename($src);
-                               # Pity there's no cp --exclude ..
+                               my $basename = basename($src);
+                               my $dir = ($basename eq '.') ? $src : "$src/..";
                                my $pwd=`pwd`;
                                chomp $pwd;
-                               complex_doit("cd $src/.. && find $dir_basename -type f$exclude -exec cp --parents -dp {} $pwd/$tmp/$dest/ \\;");
+                               complex_doit("cd '$dir' && find '$basename' $exclude \\( -type f -or -type l \\) -exec cp --parents -dp {} $pwd/$tmp/$dest/ \\;");
+                               # cp is annoying so I need a separate pass
+                               # just for empty directories
+                               complex_doit("cd '$dir' && find '$basename' $exclude \\( -type d -and -empty \\) -exec cp --parents -a {} $pwd/$tmp/$dest/ \\;");
                        }
                        else {
                                doit("cp", "-a", $src, "$tmp/$dest/");
                        }
+
+                       if ($tmpdest) {
+                               $dest=undef;
+                       }
                }
        }
 }
 
+if ($dh{LIST_MISSING} || $dh{FAIL_MISSING}) {
+       # . as srcdir makes no sense, so this is a special case.
+       if ($srcdir eq '.') {
+               $srcdir='debian/tmp';
+       }
+       
+       my @missing;
+       my $installed=join("|", @installed);
+       $installed=qr{^($installed)$};
+       find(sub {
+               -f || -l || return;
+               $_="$File::Find::dir/$_";
+               if (! /$installed/ && ! excludefile($_)) {
+                       my $file=$_;
+                       $file=~s/^\Q$srcdir\E\///;
+                       push @missing, $file;
+               }
+       }, $srcdir);
+       if (@missing) {
+               warning "$_ exists in $srcdir but is not installed to anywhere" foreach @missing;
+               if ($dh{FAIL_MISSING}) {
+                       error("missing files, aborting");
+               }
+       }
+}
+
+=head1 EXAMPLE
+
+Suppose your package's upstream Makefile installs a binary, a man page, and
+a library into appropriate subdirectories of debian/tmp. You want to put
+the library into package libfoo, and the rest into package foo. Your rules
+file will run "dh_install --sourcedir=debian/tmp". Make debian/foo.install
+contain:
+
+  usr/bin
+  usr/share/man/man1
+
+While debian/libfoo.install contains:
+
+  usr/lib/libfoo*.so.*
+
+If you want a libfoo-dev package too, debian/libfoo-dev.install might contain:
+
+  usr/include
+  usr/lib/libfoo*.so
+  usr/share/man/man3
+
+=head1 LIMITATIONS
+
+dh_install cannot rename files or directories, it can only install them
+with the names they already have into wherever you want in the package
+build tree.
+  
 =head1 SEE ALSO
 
-L<debhelper(1)>
+L<debhelper(7)>
 
 This program is a part of debhelper.