]> git.donarmstrong.com Git - debhelper.git/blobdiff - dh_link
Fix build system auto-selection breakage.
[debhelper.git] / dh_link
diff --git a/dh_link b/dh_link
index 8a2805ee9b7b721bce0206dda36770625ad07f99..b035a731da1b6c9a953e120f9a4988ee80f3cddd 100755 (executable)
--- a/dh_link
+++ b/dh_link
@@ -7,11 +7,12 @@ dh_link - create symlinks in package build directories
 =cut
 
 use strict;
+use File::Find;
 use Debian::Debhelper::Dh_Lib;
 
 =head1 SYNOPSIS
 
-  dh_link [debhelper options] [-A] [source destination ...]
+B<dh_link> [S<I<debhelper options>>] [B<-A>] [B<-X>I<item>] [S<I<source destination ...>>]
 
 =head1 DESCRIPTION
 
@@ -23,15 +24,6 @@ files are the already existing files that will be symlinked from. The
 destination files are the symlinks that will be created. There B<must> be
 an equal number of source and destination files specified.
 
-The list can be specified in two ways. A file named debian/package.links
-can list pairs of files. If you use this file, you should put each pair
-of files on its own line, and separate the files within the pair with
-whitespace. Also, pairs of files can be specified as parameters - these
-pairs will only be created in the package build directory of the first
-package dh_link is told to act on. By default, this is the first binary
-package in debian/control, but if you use -p, -i, or -a flags, it will be
-the first package specified by those flags.
-
 Be sure you B<do> specify the full filename to both the source and
 destination files (unlike you would do if you were using something like
 L<ln(1)>).
@@ -41,6 +33,21 @@ when policy says they should be absolute, and relative links with as short
 a path as possible. It will also create any subdirectories it needs to to put
 the symlinks in.
 
+dh_link also scans the package build tree for existing symlinks which do not
+conform to debian policy, and corrects them (v4 or later).
+
+=head1 FILES
+
+=over 4
+
+=item debian/I<package>.links
+
+Lists pairs of source and destination files to be symlinked. Each pair
+should be put on its own line, with the source and destination separated by
+whitespace.
+
+=back
+
 =head1 OPTIONS
 
 =over 4
@@ -50,6 +57,11 @@ the symlinks in.
 Create any links specified by command line parameters in ALL packages
 acted on, not just the first.
 
+=item B<-Xitem>, B<--exclude=item>
+
+Do not correct symlinks that contain "item" anywhere in their filename from
+being corrected to comply with debian policy.
+
 =item I<source destination ...>
 
 Create a file named "destination" as a link to a file named "source". Do
@@ -65,13 +77,49 @@ this in the package build directory of the first package acted on.
 Make bar.1 be a symlink to foo.1
 
  dh_link var/lib/foo usr/lib/foo \
-   usr/X11R6/man/man1/foo.1x usr/share/man/man1/bar.1
+   usr/share/man/man1/foo.1 usr/share/man/man1/bar.1
 
 Make /usr/lib/foo/ be a link to /var/lib/foo/, and bar.1 be a symlink to
-the X man page foo.1x
+the foo.1
 
 =cut
 
+# This expand_path expands all path "." and ".." components, but doesn't
+# resolve symbolic links.
+sub expand_path {
+       my $start = @_ ? shift : '.';
+       my @pathname = split(m:/+:,$start);
+
+       my $entry;
+       my @respath;
+       foreach $entry (@pathname) {
+               if ($entry eq '.' || $entry eq '') {
+                       # Do nothing
+               }
+               elsif ($entry eq '..') {
+                       if ($#respath == -1) {
+                               # Do nothing
+                       }
+                       else {
+                               pop @respath;
+                       }
+               }
+               else {
+                       push @respath, $entry;
+               }
+       }
+
+       my $result;
+       foreach $entry (@respath) {
+               $result .= '/' . $entry;
+       }
+       if (! defined $result) {
+               $result="/"; # special case
+       }
+       return $result;
+}
+
+
 init();
 
 foreach my $package (@{$dh{DOPACKAGES}}) {
@@ -98,16 +146,43 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
                error("parameters list a link without a destination.");
        }
 
+       # v4 or later and only if there is a temp dir already
+       if (! compat(3) && -e $tmp) {
+               # Scan for existing links and add them to @links, so they
+               # are recreated policy conformant.
+               find(
+                       sub {
+                               return unless -l;
+                               return if excludefile($_);
+                               my $dir=$File::Find::dir;
+                               $dir=~s/^\Q$tmp\E//;
+                               my $target = readlink($_);
+                               if ($target=~/^\//) {
+                                       push @links, $target;
+                               }
+                               else {
+                                       push @links, "$dir/$target";
+                               }
+                               push @links, "$dir/$_";
+                               
+                       },
+                       $tmp);
+       }
+       
        while (@links) {
                my $dest=pop @links;
-               my $src=pop @links;
+               my $src=expand_path(pop @links);
 
-               # Relavatize src and dest.
                $src=~s:^/::;
                $dest=~s:^/::;
+               
+               if ($src eq $dest) {
+                       warning("skipping link from $src to self");
+                       next;
+               }
 
                # Make sure the directory the link will be in exists.
-               my $basedir=Debian::Debhelper::Dh_Lib::dirname("$tmp/$dest");
+               my $basedir=dirname("$tmp/$dest");
                if (! -e $basedir) {
                        doit("install","-d",$basedir);
                }
@@ -117,11 +192,11 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
                # top level directories, leave it absolute.
                my @src_dirs=split(m:/+:,$src);
                my @dest_dirs=split(m:/+:,$dest);
-               if ($src_dirs[0] eq $dest_dirs[0]) {
+               if (@src_dirs > 0 && $src_dirs[0] eq $dest_dirs[0]) {
                        # Figure out how much of a path $src and $dest
                        # share in common.
                        my $x;
-                       for ($x=0; $x<$#src_dirs && $src_dirs[$x] eq $dest_dirs[$x]; $x++) {}
+                       for ($x=0; $x < @src_dirs && $src_dirs[$x] eq $dest_dirs[$x]; $x++) {}
                        # Build up the new src.
                        $src="";
                        for (1..$#dest_dirs - $x) {
@@ -130,20 +205,27 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
                        for ($x .. $#src_dirs) {
                                $src.=$src_dirs[$_]."/";
                        }
+                       if ($x > $#src_dirs && ! length $src) {
+                               $src.="."; # special case
+                       }
                        $src=~s:/$::;
                }
                else {
                        # Make sure it's properly absolute.
                        $src="/$src";
                }
-               
-               doit("ln","-sf",$src,"$tmp/$dest");
+
+               if (-d "$tmp/$dest" && ! -l "$tmp/$dest") {
+                       error("link destination $tmp/$dest is a directory");
+               }
+               doit("rm", "-f", "$tmp/$dest");
+               doit("ln","-sf", $src, "$tmp/$dest");
        }
 }
 
 =head1 SEE ALSO
 
-L<debhelper(1)>
+L<debhelper(7)>
 
 This program is a part of debhelper.