Package: debhelper
Followup-For: Bug #894549
Hello.
This new diff should fix the same issues in dh_usrlocal.
The result is more readable in my opinion, hopefully preventing
similar errors in the future.
It should also be a bit more efficient: instead of sorting two huge
lists of paths all starting with "/usr/share/", it sorts once simple
names in each directory.
When a normal file is encountered, it displays an error instead of a
warning. This does not change much, as rmdir would fail with a less
explicit message when attempting to remove the containing directory.
--- a/dh_usrlocal
+++ b/dh_usrlocal
@@ -76,55 +76,50 @@
my $tmp = tmpdir($package);
if (-d "$tmp/usr/local") {
- my (@dirs, @justdirs);
- find({bydepth => 1,
- no_chdir => 1,
+ my ($dirs, $justdirs);
+ find({no_chdir => 1,
+ preprocess => sub {
+ # Ensure a reproducible traversal.
+ return sort @_;
+ },
+ postprocess => sub {
+ # Uninstall, unless a direct child of /usr/local.
+ $_ = $File::Find::dir;
+ s!^\Q$tmp\E!!;
+ $justdirs .= "\\\\\n$_" if m!/usr/local/.*/!;
+ # Remove a directory after its childs.
+ doit('rmdir', $File::Find::dir);
+ },
wanted => sub {
+ # rmdir would fail later anyways.
+ error("${File::Find::name} is not a directory")
+ if not -d $File::Find::name;
+ # Install directory before its childs.
my $fn = $File::Find::name;
- if (-d $fn) {
- my $user = 'root';
- my $group = 'staff';
- my $mode = '02775';
- if (should_use_root()) {
- my $stat = stat $fn;
- $user = getpwuid $stat->uid;
- $group = getgrgid $stat->gid;
- $mode = sprintf "%04lo", ($stat->mode & 07777);
- if ($stat->uid == 0 && $stat->gid == 0) {
- $group = 'staff';
- $mode = '02775';
- }
+ $fn =~ s!^\Q$tmp\E!!;
+ return if $fn eq '/usr/local';
+ if (should_use_root()) {
+ my $stat = stat $File::Find::dir;
+ if ($stat->uid == 0 && $stat->gid == 0) {
+ $dirs .= "\\\\\n$fn 02775 root staff";
+ } else {
+ my $user = getpwuid $stat->uid;
+ my $group = getgrgid $stat->gid;
+ my $mode = sprintf "%04lo", ($stat->mode & 07777);
+ $dirs .= "\\\\\n$fn $mode $user $group";
}
-
-
-
- $fn =~ s!^\Q$tmp\E!!;
- return if $fn eq '/usr/local';
-
- # @dirs is in parents-first order for dir creation...
- unshift @dirs, "$fn $mode $user $group";
- # ...whereas @justdirs is depth-first for removal.
- push @justdirs, $fn;
- doit('rmdir', $_);
- }
- else {
- warning("$fn is not a directory");
+ } else {
+ $dirs .= "\\\\\n$fn 02775 root staff";
}
}}, "$tmp/usr/local");
- doit('rmdir', "$tmp/usr/local");
-
- my $bs = "\\"; # A single plain backslash
- my $ebs = $bs x 2; # Escape the backslash from the shell
+
# This constructs the body of a 'sed' c\ expression which
# is parsed by the shell in double-quotes
- my $dirs = join("$ebs\n", sort @dirs);
- pop @justdirs; # don't remove directories directly in /usr/local
- my $justdirs = join("$ebs\n", reverse sort @justdirs);
if (! $dh{NOSCRIPTS}) {
autoscript($package,"postinst", "postinst-usrlocal",
- "/#DIRS#/ c${ebs}\n${dirs}");
+ "/#DIRS#/ c$dirs") if $dirs;
autoscript($package,"prerm", "prerm-usrlocal",
- "/#JUSTDIRS#/ c${ebs}\n${justdirs}") if length $justdirs;
+ "/#JUSTDIRS#/ c$justdirs") if $justdirs;
}
}
}