buildEnv: Check the content of colliding paths.
Originally wanted to include ignoreCollisions in cups-progs, but I think it's better if we use ignoreCollisions only if there are _real_ collisions between files with different contents. Of course, we also check whether the file permissions match, so you get a collision if contents are the same but the permissions are different. Signed-off-by: aszlig <aszlig@redmoonstudios.org>
This commit is contained in:
parent
85dd89f6eb
commit
4529ed1259
|
@ -5,6 +5,7 @@ use Cwd 'abs_path';
|
||||||
use IO::Handle;
|
use IO::Handle;
|
||||||
use File::Path;
|
use File::Path;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
|
use File::Compare;
|
||||||
use JSON::PP;
|
use JSON::PP;
|
||||||
|
|
||||||
STDOUT->autoflush(1);
|
STDOUT->autoflush(1);
|
||||||
|
@ -38,7 +39,7 @@ for my $p (@pathsToLink) {
|
||||||
sub findFiles;
|
sub findFiles;
|
||||||
|
|
||||||
sub findFilesInDir {
|
sub findFilesInDir {
|
||||||
my ($relName, $target, $ignoreCollisions, $priority) = @_;
|
my ($relName, $target, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||||
|
|
||||||
opendir DIR, "$target" or die "cannot open `$target': $!";
|
opendir DIR, "$target" or die "cannot open `$target': $!";
|
||||||
my @names = readdir DIR or die;
|
my @names = readdir DIR or die;
|
||||||
|
@ -46,12 +47,28 @@ sub findFilesInDir {
|
||||||
|
|
||||||
foreach my $name (@names) {
|
foreach my $name (@names) {
|
||||||
next if $name eq "." || $name eq "..";
|
next if $name eq "." || $name eq "..";
|
||||||
findFiles("$relName/$name", "$target/$name", $name, $ignoreCollisions, $priority);
|
findFiles("$relName/$name", "$target/$name", $name, $ignoreCollisions, $checkCollisionContents, $priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub checkCollision {
|
||||||
|
my ($path1, $path2) = @_;
|
||||||
|
|
||||||
|
my $stat1 = (stat($path1))[2];
|
||||||
|
my $stat2 = (stat($path2))[2];
|
||||||
|
|
||||||
|
if ($stat1 != $stat2) {
|
||||||
|
warn "different permissions in `$path1' and `$path2': "
|
||||||
|
. sprintf("%04o", $stat1 & 07777) . " <-> "
|
||||||
|
. sprintf("%04o", $stat2 & 07777);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return compare($path1, $path2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
sub findFiles {
|
sub findFiles {
|
||||||
my ($relName, $target, $baseName, $ignoreCollisions, $priority) = @_;
|
my ($relName, $target, $baseName, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||||
|
|
||||||
# Urgh, hacky...
|
# Urgh, hacky...
|
||||||
return if
|
return if
|
||||||
|
@ -79,7 +96,9 @@ sub findFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
unless (-d $target && ($oldTarget eq "" || -d $oldTarget)) {
|
unless (-d $target && ($oldTarget eq "" || -d $oldTarget)) {
|
||||||
if ($ignoreCollisions) {
|
if ($checkCollisionContents && checkCollision($oldTarget, $target)) {
|
||||||
|
return;
|
||||||
|
} elsif ($ignoreCollisions) {
|
||||||
warn "collision between `$target' and `$oldTarget'\n" if $ignoreCollisions == 1;
|
warn "collision between `$target' and `$oldTarget'\n" if $ignoreCollisions == 1;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,8 +106,8 @@ sub findFiles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findFilesInDir($relName, $oldTarget, $ignoreCollisions, $oldPriority) unless $oldTarget eq "";
|
findFilesInDir($relName, $oldTarget, $ignoreCollisions, $checkCollisionContents, $oldPriority) unless $oldTarget eq "";
|
||||||
findFilesInDir($relName, $target, $ignoreCollisions, $priority);
|
findFilesInDir($relName, $target, $ignoreCollisions, $checkCollisionContents, $priority);
|
||||||
|
|
||||||
$symlinks{$relName} = ["", $priority]; # denotes directory
|
$symlinks{$relName} = ["", $priority]; # denotes directory
|
||||||
}
|
}
|
||||||
|
@ -98,12 +117,12 @@ my %done;
|
||||||
my %postponed;
|
my %postponed;
|
||||||
|
|
||||||
sub addPkg {
|
sub addPkg {
|
||||||
my ($pkgDir, $ignoreCollisions, $priority) = @_;
|
my ($pkgDir, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||||
|
|
||||||
return if (defined $done{$pkgDir});
|
return if (defined $done{$pkgDir});
|
||||||
$done{$pkgDir} = 1;
|
$done{$pkgDir} = 1;
|
||||||
|
|
||||||
findFiles("", $pkgDir, "", $ignoreCollisions, $priority);
|
findFiles("", $pkgDir, "", $ignoreCollisions, $checkCollisionContents, $priority);
|
||||||
|
|
||||||
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
|
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
|
||||||
if (-e $propagatedFN) {
|
if (-e $propagatedFN) {
|
||||||
|
@ -132,7 +151,11 @@ if (exists $ENV{"pkgsPath"}) {
|
||||||
# user.
|
# user.
|
||||||
for my $pkg (@{decode_json $pkgs}) {
|
for my $pkg (@{decode_json $pkgs}) {
|
||||||
for my $path (@{$pkg->{paths}}) {
|
for my $path (@{$pkg->{paths}}) {
|
||||||
addPkg($path, $ENV{"ignoreCollisions"} eq "1", $pkg->{priority}) if -e $path;
|
addPkg($path,
|
||||||
|
$ENV{"ignoreCollisions"} eq "1",
|
||||||
|
$ENV{"checkCollisionContents"} eq "1",
|
||||||
|
$pkg->{priority})
|
||||||
|
if -e $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
, # Whether to ignore collisions or abort.
|
, # Whether to ignore collisions or abort.
|
||||||
ignoreCollisions ? false
|
ignoreCollisions ? false
|
||||||
|
|
||||||
|
, # If there is a collision, check whether the contents and permissions match
|
||||||
|
# and only if not, throw a collision error.
|
||||||
|
checkCollisionContents ? true
|
||||||
|
|
||||||
, # The paths (relative to each element of `paths') that we want to
|
, # The paths (relative to each element of `paths') that we want to
|
||||||
# symlink (e.g., ["/bin"]). Any file not inside any of the
|
# symlink (e.g., ["/bin"]). Any file not inside any of the
|
||||||
# directories in the list is not symlinked.
|
# directories in the list is not symlinked.
|
||||||
|
@ -39,7 +43,9 @@
|
||||||
}:
|
}:
|
||||||
|
|
||||||
runCommand name
|
runCommand name
|
||||||
rec { inherit manifest ignoreCollisions passthru meta pathsToLink extraPrefix postBuild buildInputs;
|
rec {
|
||||||
|
inherit manifest ignoreCollisions checkCollisionContents passthru
|
||||||
|
meta pathsToLink extraPrefix postBuild buildInputs;
|
||||||
pkgs = builtins.toJSON (map (drv: {
|
pkgs = builtins.toJSON (map (drv: {
|
||||||
paths =
|
paths =
|
||||||
[ drv ]
|
[ drv ]
|
||||||
|
|
Loading…
Reference in a new issue