From 26b87e78b5dd62d9cca7c7d08a697dd2d22ae38c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 11 Feb 2025 20:36:28 +0100 Subject: [PATCH] copyPathToStore(): Preserve symlinks E.g. in a derivation attribute `foo = ./bar`, if ./bar is a symlink, we should copy the symlink to the store, not its target. This restores the behaviour of Nix <= 2.19. --- src/libexpr/eval.cc | 2 +- tests/functional/meson.build | 1 + tests/functional/simple.sh | 2 +- tests/functional/symlinks.sh | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/functional/symlinks.sh diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 19ca1a359..dee764429 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2384,7 +2384,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat : [&]() { auto dstPath = fetchToStore( *store, - path.resolveSymlinks(), + path.resolveSymlinks(SymlinkResolution::Ancestors), settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, path.baseName(), ContentAddressMethod::Raw::NixArchive, diff --git a/tests/functional/meson.build b/tests/functional/meson.build index dee003e42..3342ee870 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -164,6 +164,7 @@ suites = [ 'debugger.sh', 'extra-sandbox-profile.sh', 'help.sh', + 'symlinks.sh', ], 'workdir': meson.current_source_dir(), }, diff --git a/tests/functional/simple.sh b/tests/functional/simple.sh index 8afa369c2..c1f2eef41 100755 --- a/tests/functional/simple.sh +++ b/tests/functional/simple.sh @@ -15,7 +15,7 @@ echo "output path is $outPath" [[ ! -w $outPath ]] text=$(cat "$outPath/hello") -if test "$text" != "Hello World!"; then exit 1; fi +[[ "$text" = "Hello World!" ]] TODO_NixOS diff --git a/tests/functional/symlinks.sh b/tests/functional/symlinks.sh new file mode 100644 index 000000000..5eb22b3f9 --- /dev/null +++ b/tests/functional/symlinks.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +source common.sh + +# Check that when we have a derivation attribute that refers to a +# symlink, we copy the symlink, not its target. +# shellcheck disable=SC2016 +nix build --impure --no-link --expr ' + with import ./config.nix; + + mkDerivation { + name = "simple"; + builder = builtins.toFile "builder.sh" "[[ -L \"$symlink\" ]]; mkdir $out"; + symlink = ./lang/symlink-resolution/foo/overlays; + } +'