diff --git a/doc/build-helpers/dev-shell-tools.chapter.md b/doc/build-helpers/dev-shell-tools.chapter.md index 09b9893daff7..4f6980143210 100644 --- a/doc/build-helpers/dev-shell-tools.chapter.md +++ b/doc/build-helpers/dev-shell-tools.chapter.md @@ -11,4 +11,19 @@ However, `nix-shell` is not the only way to create such environments, and even ` This library provides a set of functions that help create such environments. - +## `devShellTools.stringValue` {#sec-devShellTools-stringValue} + +Converts Nix values to strings in the way the [`derivation` built-in function](https://nix.dev/manual/nix/2.23/language/derivations) does. + +:::{.example} +## `stringValue` usage examples + +```nix +devShellTools.stringValue (builtins.toFile "foo" "bar") +=> "/nix/store/...-foo" +``` + +```nix +devShellTools.stringValue false +=> "" +``` diff --git a/pkgs/build-support/dev-shell-tools/default.nix b/pkgs/build-support/dev-shell-tools/default.nix index b61813bb4eb6..f0f180dc1905 100644 --- a/pkgs/build-support/dev-shell-tools/default.nix +++ b/pkgs/build-support/dev-shell-tools/default.nix @@ -1,4 +1,16 @@ -{ }: - -{ +{ lib }: +let + inherit (builtins) typeOf; +in +rec { + # This function closely mirrors what this Nix code does: + # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1102 + # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/eval.cc#L1981-L2036 + stringValue = value: + # We can't just use `toString` on all derivation attributes because that + # would not put path literals in the closure. So we explicitly copy + # those into the store here + if typeOf value == "path" then "${value}" + else if typeOf value == "list" then toString (map stringValue value) + else toString value; } diff --git a/pkgs/build-support/dev-shell-tools/tests/default.nix b/pkgs/build-support/dev-shell-tools/tests/default.nix index d8147ea85118..d4b0872dd6b8 100644 --- a/pkgs/build-support/dev-shell-tools/tests/default.nix +++ b/pkgs/build-support/dev-shell-tools/tests/default.nix @@ -1,5 +1,45 @@ -{ ... }: - { + devShellTools, + emptyFile, + lib, + stdenv, + hello, +}: +let + inherit (lib) escapeShellArg; +in +{ + # nix-build -A tests.devShellTools.stringValue + stringValue = + let inherit (devShellTools) stringValue; in + stdenv.mkDerivation { + name = "devShellTools-stringValue-built-tests"; + + # Test inputs + inherit emptyFile hello; + one = 1; + boolTrue = true; + boolFalse = false; + foo = "foo"; + list = [ 1 2 3 ]; + pathDefaultNix = ./default.nix; + packages = [ hello emptyFile ]; + # TODO: nested lists + + buildCommand = '' + touch $out + ( set -x + [[ "$one" = ${escapeShellArg (stringValue 1)} ]] + [[ "$boolTrue" = ${escapeShellArg (stringValue true)} ]] + [[ "$boolFalse" = ${escapeShellArg (stringValue false)} ]] + [[ "$foo" = ${escapeShellArg (stringValue "foo")} ]] + [[ "$hello" = ${escapeShellArg (stringValue hello)} ]] + [[ "$list" = ${escapeShellArg (stringValue [ 1 2 3 ])} ]] + [[ "$packages" = ${escapeShellArg (stringValue [ hello emptyFile ])} ]] + [[ "$pathDefaultNix" = ${escapeShellArg (stringValue ./default.nix)} ]] + [[ "$emptyFile" = ${escapeShellArg (stringValue emptyFile)} ]] + ) >log 2>&1 || { cat log; exit 1; } + ''; + }; } diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index 1d1989d27fbb..033969a7fc88 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -4,6 +4,7 @@ , callPackage , closureInfo , coreutils +, devShellTools , e2fsprogs , proot , fakeNss @@ -49,6 +50,10 @@ let toList ; + inherit (devShellTools) + stringValue + ; + mkDbExtraCommand = contents: let contentsList = if builtins.isList contents then contents else [ contents ]; @@ -1173,17 +1178,6 @@ rec { # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/globals.hh#L464-L465 sandboxBuildDir = "/build"; - # This function closely mirrors what this Nix code does: - # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1102 - # https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/eval.cc#L1981-L2036 - stringValue = value: - # We can't just use `toString` on all derivation attributes because that - # would not put path literals in the closure. So we explicitly copy - # those into the store here - if builtins.typeOf value == "path" then "${value}" - else if builtins.typeOf value == "list" then toString (map stringValue value) - else toString value; - # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L992-L1004 drvEnv = lib.mapAttrs' (name: value: let str = stringValue value;