forked from mirrors/nixpkgs
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 File::Path;
|
||||
use File::Basename;
|
||||
use File::Compare;
|
||||
use JSON::PP;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
@ -38,7 +39,7 @@ for my $p (@pathsToLink) {
|
|||
sub findFiles;
|
||||
|
||||
sub findFilesInDir {
|
||||
my ($relName, $target, $ignoreCollisions, $priority) = @_;
|
||||
my ($relName, $target, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||
|
||||
opendir DIR, "$target" or die "cannot open `$target': $!";
|
||||
my @names = readdir DIR or die;
|
||||
|
@ -46,12 +47,28 @@ sub findFilesInDir {
|
|||
|
||||
foreach my $name (@names) {
|
||||
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 {
|
||||
my ($relName, $target, $baseName, $ignoreCollisions, $priority) = @_;
|
||||
my ($relName, $target, $baseName, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||
|
||||
# Urgh, hacky...
|
||||
return if
|
||||
|
@ -79,7 +96,9 @@ sub findFiles {
|
|||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
} else {
|
||||
|
@ -87,8 +106,8 @@ sub findFiles {
|
|||
}
|
||||
}
|
||||
|
||||
findFilesInDir($relName, $oldTarget, $ignoreCollisions, $oldPriority) unless $oldTarget eq "";
|
||||
findFilesInDir($relName, $target, $ignoreCollisions, $priority);
|
||||
findFilesInDir($relName, $oldTarget, $ignoreCollisions, $checkCollisionContents, $oldPriority) unless $oldTarget eq "";
|
||||
findFilesInDir($relName, $target, $ignoreCollisions, $checkCollisionContents, $priority);
|
||||
|
||||
$symlinks{$relName} = ["", $priority]; # denotes directory
|
||||
}
|
||||
|
@ -98,12 +117,12 @@ my %done;
|
|||
my %postponed;
|
||||
|
||||
sub addPkg {
|
||||
my ($pkgDir, $ignoreCollisions, $priority) = @_;
|
||||
my ($pkgDir, $ignoreCollisions, $checkCollisionContents, $priority) = @_;
|
||||
|
||||
return if (defined $done{$pkgDir});
|
||||
$done{$pkgDir} = 1;
|
||||
|
||||
findFiles("", $pkgDir, "", $ignoreCollisions, $priority);
|
||||
findFiles("", $pkgDir, "", $ignoreCollisions, $checkCollisionContents, $priority);
|
||||
|
||||
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
|
||||
if (-e $propagatedFN) {
|
||||
|
@ -132,7 +151,11 @@ if (exists $ENV{"pkgsPath"}) {
|
|||
# user.
|
||||
for my $pkg (@{decode_json $pkgs}) {
|
||||
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.
|
||||
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
|
||||
# symlink (e.g., ["/bin"]). Any file not inside any of the
|
||||
# directories in the list is not symlinked.
|
||||
|
@ -39,7 +43,9 @@
|
|||
}:
|
||||
|
||||
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: {
|
||||
paths =
|
||||
[ drv ]
|
||||
|
|
Loading…
Reference in a new issue