X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=inline;f=dh_install;h=875f80bfe45d3be04e07525799ec98b45105d0f8;hb=725a4d769be1573cca18ced3581a55ef906235ff;hp=4aa7142d2e94e4e2490d76c346b8e238ed63d69f;hpb=6acd7f22222118dc5f51c251bd0078edbe280e87;p=debhelper.git diff --git a/dh_install b/dh_install index 4aa7142..875f80b 100755 --- a/dh_install +++ b/dh_install @@ -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 [B<-X>I] [S>] [S>] +B [B<-X>I] [B<--autodest>] [B<--sourcedir=>I] [S>] [S>] =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.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 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 $ret=0; +my @installed; + +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,50 +142,138 @@ 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; } - - foreach my $src (map { glob } @$set) { # glob now + + 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; } - $src = "$srcdir/$src"; # do this now, to avoid the parsing above - # Make sure the destination directory exists. if (! -e "$tmp/$dest") { 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 +L This program is a part of debhelper.