=head1 SYNOPSIS
-B<dh_link> [S<I<debhelper options>>] [B<-A>] [S<I<source destination ...>>]
+B<dh_link> [S<I<debhelper options>>] [B<-A>] [B<-X>I<item>] [S<I<source destination ...>>]
=head1 DESCRIPTION
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 only).
+conform to debian policy, and corrects them (v4 or later).
=head1 OPTIONS
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
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}}) {
error("parameters list a link without a destination.");
}
- # v4 only and only if there is a temp dir already
+ # 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($_);
push @links, "$dir/$target";
}
push @links, "$dir/$_";
- doit("rm","-f",$_);
},
$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=dirname("$tmp/$dest");
# 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) {
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");
}
}