summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2014-11-23 20:42:14 +0100
committeraszlig <aszlig@redmoonstudios.org>2016-01-18 03:54:22 +0100
commit4529ed12590d7f814e40223437c7df4fea492e2d (patch)
tree82ff5794c928d58fa28e9b4c0731d8c44628a7e8 /pkgs/build-support
parent85dd89f6eb02aacdde2932652c628b06f8e562da (diff)
downloadnixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar.gz
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar.bz2
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar.lz
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar.xz
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.tar.zst
nixlib-4529ed12590d7f814e40223437c7df4fea492e2d.zip
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>
Diffstat (limited to 'pkgs/build-support')
-rwxr-xr-xpkgs/build-support/buildenv/builder.pl41
-rw-r--r--pkgs/build-support/buildenv/default.nix8
2 files changed, 39 insertions, 10 deletions
diff --git a/pkgs/build-support/buildenv/builder.pl b/pkgs/build-support/buildenv/builder.pl
index 155af314397b..7f1be3925443 100755
--- a/pkgs/build-support/buildenv/builder.pl
+++ b/pkgs/build-support/buildenv/builder.pl
@@ -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;
     }
 }
 
diff --git a/pkgs/build-support/buildenv/default.nix b/pkgs/build-support/buildenv/default.nix
index 9b8b9daad94d..a9a4d95d7d8f 100644
--- a/pkgs/build-support/buildenv/default.nix
+++ b/pkgs/build-support/buildenv/default.nix
@@ -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 ]