Merge pull request #323398 from NixOS/prep-dev-shell

init `devShellTools`
This commit is contained in:
Silvan Mosberger 2024-07-03 05:19:42 +02:00 committed by GitHub
commit 06a8bee760
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 115 additions and 13 deletions

View File

@ -20,6 +20,7 @@ There is no uniform interface for build helpers.
build-helpers/fetchers.chapter.md build-helpers/fetchers.chapter.md
build-helpers/trivial-build-helpers.chapter.md build-helpers/trivial-build-helpers.chapter.md
build-helpers/testers.chapter.md build-helpers/testers.chapter.md
build-helpers/dev-shell-tools.chapter.md
build-helpers/special.md build-helpers/special.md
build-helpers/images.md build-helpers/images.md
hooks/index.md hooks/index.md

View File

@ -0,0 +1,29 @@
# Development Shell helpers {#chap-devShellTools}
The `nix-shell` command has popularized the concept of transient shell environments for development or testing purposes.
<!--
We should try to document the product, not its development process in the Nixpkgs reference manual,
but *something* needs to be said to provide context for this library.
This is the most future proof sentence I could come up with while Nix itself does yet make use of this.
Relevant is the current status of the devShell attribute "project": https://github.com/NixOS/nix/issues/7501
-->
However, `nix-shell` is not the only way to create such environments, and even `nix-shell` itself can indirectly benefit from this library.
This library provides a set of functions that help create such environments.
## `devShellTools.valueToString` {#sec-devShellTools-valueToString}
Converts Nix values to strings in the way the [`derivation` built-in function](https://nix.dev/manual/nix/2.23/language/derivations) does.
:::{.example}
## `valueToString` usage examples
```nix
devShellTools.valueToString (builtins.toFile "foo" "bar")
=> "/nix/store/...-foo"
```
```nix
devShellTools.valueToString false
=> ""
```

View File

@ -0,0 +1,13 @@
# `devShellTools`
This directory implements the `pkgs.devShellTools` library.
# Contributing to `devShellTools`
- Documentation should be contributed to the Nixpkgs manual, not here.
- Tests are available in the `tests` directory.
You may run them with `nix-build -A tests.devShellTools`.
- See [../../README.md](../../README.md) for more information on contributing to Nixpkgs.

View File

@ -0,0 +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
valueToString = 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 valueToString value)
else toString value;
}

View File

@ -0,0 +1,45 @@
{
devShellTools,
emptyFile,
lib,
stdenv,
hello,
}:
let
inherit (lib) escapeShellArg;
in
{
# nix-build -A tests.devShellTools.valueToString
valueToString =
let inherit (devShellTools) valueToString; in
stdenv.mkDerivation {
name = "devShellTools-valueToString-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 (valueToString 1)} ]]
[[ "$boolTrue" = ${escapeShellArg (valueToString true)} ]]
[[ "$boolFalse" = ${escapeShellArg (valueToString false)} ]]
[[ "$foo" = ${escapeShellArg (valueToString "foo")} ]]
[[ "$hello" = ${escapeShellArg (valueToString hello)} ]]
[[ "$list" = ${escapeShellArg (valueToString [ 1 2 3 ])} ]]
[[ "$packages" = ${escapeShellArg (valueToString [ hello emptyFile ])} ]]
[[ "$pathDefaultNix" = ${escapeShellArg (valueToString ./default.nix)} ]]
[[ "$emptyFile" = ${escapeShellArg (valueToString emptyFile)} ]]
) >log 2>&1 || { cat log; exit 1; }
'';
};
}

View File

@ -4,6 +4,7 @@
, callPackage , callPackage
, closureInfo , closureInfo
, coreutils , coreutils
, devShellTools
, e2fsprogs , e2fsprogs
, proot , proot
, fakeNss , fakeNss
@ -49,6 +50,10 @@ let
toList toList
; ;
inherit (devShellTools)
valueToString
;
mkDbExtraCommand = contents: mkDbExtraCommand = contents:
let let
contentsList = if builtins.isList contents then contents else [ contents ]; contentsList = if builtins.isList contents then contents else [ contents ];
@ -1141,7 +1146,7 @@ rec {
# A binary that calls the command to build the derivation # A binary that calls the command to build the derivation
builder = writeShellScriptBin "buildDerivation" '' builder = writeShellScriptBin "buildDerivation" ''
exec ${lib.escapeShellArg (stringValue drv.drvAttrs.builder)} ${lib.escapeShellArgs (map stringValue drv.drvAttrs.args)} exec ${lib.escapeShellArg (valueToString drv.drvAttrs.builder)} ${lib.escapeShellArgs (map valueToString drv.drvAttrs.args)}
''; '';
staticPath = "${dirOf shell}:${lib.makeBinPath [ builder ]}"; staticPath = "${dirOf shell}:${lib.makeBinPath [ builder ]}";
@ -1173,20 +1178,9 @@ rec {
# https://github.com/NixOS/nix/blob/2.8.0/src/libstore/globals.hh#L464-L465 # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/globals.hh#L464-L465
sandboxBuildDir = "/build"; 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 # https://github.com/NixOS/nix/blob/2.8.0/src/libstore/build/local-derivation-goal.cc#L992-L1004
drvEnv = lib.mapAttrs' (name: value: drvEnv = lib.mapAttrs' (name: value:
let str = stringValue value; let str = valueToString value;
in if lib.elem name (drv.drvAttrs.passAsFile or []) in if lib.elem name (drv.drvAttrs.passAsFile or [])
then lib.nameValuePair "${name}Path" (writeText "pass-as-text-${name}" str) then lib.nameValuePair "${name}Path" (writeText "pass-as-text-${name}" str)
else lib.nameValuePair name str else lib.nameValuePair name str

View File

@ -83,6 +83,8 @@ with pkgs;
inherit gccTests; inherit gccTests;
}; };
devShellTools = callPackage ../build-support/dev-shell-tools/tests { };
stdenv-inputs = callPackage ./stdenv-inputs { }; stdenv-inputs = callPackage ./stdenv-inputs { };
stdenv = callPackage ./stdenv { }; stdenv = callPackage ./stdenv { };

View File

@ -837,6 +837,8 @@ with pkgs;
grsync = callPackage ../applications/misc/grsync { }; grsync = callPackage ../applications/misc/grsync { };
devShellTools = callPackage ../build-support/dev-shell-tools { };
dockerTools = callPackage ../build-support/docker { dockerTools = callPackage ../build-support/docker {
writePython3 = buildPackages.writers.writePython3; writePython3 = buildPackages.writers.writePython3;
}; };