From 0172558e8278eda2f08f9fc02ff831538548ced3 Mon Sep 17 00:00:00 2001 From: Alexey Shmalko Date: Sat, 9 Jul 2016 23:47:15 +0300 Subject: buildEnv: build the whole tree of directories to pathsToLink This patch fixes #16614 and #16741. The first issue was caused by the fact that both `/share` and `/share/fish/vendor_completions.d` end in the `pathsToLink`. The `pkgs/build-support/buildenv/builder.pl` creates `/share`, then links `/share/fish` under `/share` and then tries to create the directory `/share/fish/vendor_completions.d` and fails because it already exists. The simplest way to reproduce the issue is to build the next Nix expression: ```nix let pkgs = import { }; in pkgs.buildEnv { name = "buildenv-issue"; paths = [ pkgs.fish pkgs.vim ]; pathsToLink = [ "/share" "/share/fish/vendor_completions.d" ]; } ``` The second issue is more critical and was caused by the fact findFiles doesn't recurse deep enough. It stops at first unique directory for the package (e.g., "/share" or even "/") and later the scripts decides it shouldn't link it as it doesn't match pathsToLink (e.g., "/share/fish"), so the result is empty. The test: ```nix let pkgs = import { }; in pkgs.buildEnv { name = "buildenv-issue"; paths = [ pkgs.fish pkgs.vim ]; pathsToLink = [ "/share/fish/functions" ]; } ``` or ```nix let pkgs = import { }; in pkgs.buildEnv { name = "buildenv-issue"; paths = [ pkgs.vim ]; pathsToLink = [ "/share" ]; } ``` --- pkgs/build-support/buildenv/builder.pl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'pkgs/build-support/buildenv/builder.pl') diff --git a/pkgs/build-support/buildenv/builder.pl b/pkgs/build-support/buildenv/builder.pl index f6cfe52dc318..678f5a3fe9e6 100755 --- a/pkgs/build-support/buildenv/builder.pl +++ b/pkgs/build-support/buildenv/builder.pl @@ -31,9 +31,23 @@ sub isInPathsToLink { my %symlinks; +# Add all pathsToLink and all parent directories. +# +# For "/a/b/c" that will include +# [ "", "/a", "/a/b", "/a/b/c" ] +# +# That ensures the whole directory tree needed by pathsToLink is +# created as directories and not symlinks. +$symlinks{""} = ["", 0]; for my $p (@pathsToLink) { - $p = "" if $p eq "/"; - $symlinks{$p} = ["", 0]; + my @parts = split '/', $p; + + my $cur = ""; + for my $x (@parts) { + $cur = $cur . "/$x"; + $cur = "" if $cur eq "/"; + $symlinks{$cur} = ["", 0]; + } } sub findFiles; -- cgit 1.4.1