From 4cff4130549abf65eb17242a373eb98953252895 Mon Sep 17 00:00:00 2001 From: John Chapman Date: Sat, 9 Oct 2021 12:03:34 +1100 Subject: [PATCH 01/23] Clarify that not all nix packages will use the default build phases --- doc/manual/src/command-ref/nix-shell.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/manual/src/command-ref/nix-shell.md b/doc/manual/src/command-ref/nix-shell.md index 72f6730f1..8bcad85e1 100644 --- a/doc/manual/src/command-ref/nix-shell.md +++ b/doc/manual/src/command-ref/nix-shell.md @@ -117,6 +117,12 @@ $ nix-shell '' -A pan [nix-shell]$ ./pan/gui/pan ``` +Note: Other packages may override these phases (the unpackPhase, +configurePhase, buildPhase, etc). +For those, it may be required to do something like +`eval "$configurePhase-configurePhase"` or `eval "$configurePhase"` +depending on how that package's nix files have been written. + To clear the environment first, and do some additional automatic initialisation of the interactive shell: From eae29b0385981a2a1cc792bdb6551d558f4fa6d3 Mon Sep 17 00:00:00 2001 From: kvtb <76634406+kvtb@users.noreply.github.com> Date: Wed, 13 Oct 2021 18:03:33 +0000 Subject: [PATCH 02/23] fix build with gcc11 --- src/libutil/ref.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/ref.hh b/src/libutil/ref.hh index d6bf53bb8..347b81f73 100644 --- a/src/libutil/ref.hh +++ b/src/libutil/ref.hh @@ -17,7 +17,7 @@ private: public: - ref(const ref & r) + ref(const ref & r) : p(r.p) { } From 3a2fc9ce1dd3b176bdef257be75439bde33c210a Mon Sep 17 00:00:00 2001 From: regnat Date: Thu, 14 Oct 2021 15:42:54 +0200 Subject: [PATCH 03/23] Fix the `isDaemonNewer` check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Don’t hardcode the “newer” version - Remove an ill-placed `return` --- tests/common.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common.sh.in b/tests/common.sh.in index 7daab2460..08f5e0a77 100644 --- a/tests/common.sh.in +++ b/tests/common.sh.in @@ -126,7 +126,7 @@ isDaemonNewer () { [[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0 local requiredVersion="$1" local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) - return [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''2.4''") -ge 0 ]] + [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]] } requireDaemonNewerThan () { From b598e5c47c0e98b45de00b488707f4f92fc093eb Mon Sep 17 00:00:00 2001 From: regnat Date: Thu, 14 Oct 2021 16:00:59 +0200 Subject: [PATCH 04/23] Fix the min bound for the structured-attrs test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The min bound written corresponds to the date of the commit that introduced the change, but it only got merged on master some weeks later. Since the version is essentially the commit date, that means that there’s a whole range of commits on master (including the current `nixUnstable`) that have a higher version but don’t contain the required change. --- tests/structured-attrs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/structured-attrs.sh b/tests/structured-attrs.sh index e585ce37f..378dbc735 100644 --- a/tests/structured-attrs.sh +++ b/tests/structured-attrs.sh @@ -2,7 +2,7 @@ source common.sh # 27ce722638 required some incompatible changes to the nix file, so skip this # tests for the older versions -requireDaemonNewerThan "2.4pre20210622" +requireDaemonNewerThan "2.4pre20210712" clearStore From a9d9e5555118025032eabd9612e03473a97ebff8 Mon Sep 17 00:00:00 2001 From: yvt Date: Fri, 15 Oct 2021 09:48:15 +0900 Subject: [PATCH 05/23] Add another path where a Rosetta 2 configuration file is possibly located --- src/libstore/globals.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 6934801e3..4903d0922 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -148,7 +148,8 @@ StringSet Settings::getDefaultExtraPlatforms() // machines. Note that we can’t force processes from executing // x86_64 in aarch64 environments or vice versa since they can // always exec with their own binary preferences. - if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist")) { + if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist") || + pathExists("/System/Library/LaunchDaemons/com.apple.oahd.plist")) { if (std::string{SYSTEM} == "x86_64-darwin") extraPlatforms.insert("aarch64-darwin"); else if (std::string{SYSTEM} == "aarch64-darwin") From 1bdeef83958251e728abe9398b4286cb6b5e9551 Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Thu, 14 Oct 2021 23:23:04 -0500 Subject: [PATCH 06/23] add pos to EvalState::forceValue - This way we improve error messages on infinite recursion - Demo: ```nix let x = builtins.fetchMercurial x; in x ``` - Before: ```bash $ nix-instantiate --show-trace --strict error: infinite recursion encountered ``` - After: ```bash nix-instantiate --show-trace --strict error: infinite recursion encountered at /data/github/kamadorueda/test/default.nix:2:7: 1| let 2| x = builtins.fetchMercurial x; | ^ 3| in ``` Mentions: #3505 --- src/libexpr/primops/fetchMercurial.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc index 1cd481243..c23480853 100644 --- a/src/libexpr/primops/fetchMercurial.cc +++ b/src/libexpr/primops/fetchMercurial.cc @@ -15,7 +15,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar std::string name = "source"; PathSet context; - state.forceValue(*args[0]); + state.forceValue(*args[0], pos); if (args[0]->type() == nAttrs) { From 0b55c8767dfa15540f47579442350ffad51fc047 Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 15 Oct 2021 14:15:43 +0200 Subject: [PATCH 07/23] Disable the eval-store test when using the daemon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the daemon will break most of the assumptions of this test, so it’s as simple to just disable it --- tests/eval-store.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/eval-store.sh b/tests/eval-store.sh index 9ab7a87be..679da5741 100644 --- a/tests/eval-store.sh +++ b/tests/eval-store.sh @@ -1,6 +1,8 @@ source common.sh -requireDaemonNewerThan "2.4pre20210727" +# Using `--eval-store` with the daemon will eventually copy everything +# to the build store, invalidating most of the tests here +needLocalStore eval_store=$TEST_ROOT/eval-store From 18e3d63341bc03e152659a6836a1b52a1241fe57 Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Fri, 15 Oct 2021 18:56:17 -0500 Subject: [PATCH 08/23] fetchTree: add pos to EvalState::forceValue - This way we improve error messages on infinite recursion - Demo: ```nix let x = builtins.fetchTree x; in x ``` - Before: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered ``` - After: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered at /data/github/kamadorueda/nix/test.nix:1:9: 1| let x = builtins.fetchTree x; | ^ 2| in x ``` Mentions: #3505 --- src/libexpr/primops/fetchTree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index f570f19ae..441edd648 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -97,7 +97,7 @@ static void fetchTree( fetchers::Input input; PathSet context; - state.forceValue(*args[0]); + state.forceValue(*args[0], pos); if (args[0]->type() == nAttrs) { state.forceAttrs(*args[0], pos); From e5a27a3b4e5ae6a1b84e439f880613e6fe5faf98 Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Fri, 15 Oct 2021 19:21:38 -0500 Subject: [PATCH 09/23] fetchTree: add pos to EvalState::forceValue - This way we improve error messages on infinite recursion - Demo: ```nix let x = builtins.fetchTree { type = "git"; inherit x; }; in x ``` - Before: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered ``` - After: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered at /data/github/kamadorueda/nix/test.nix:3:10: 2| type = "git"; 3| inherit x; | ^ 4| }; ``` Mentions: #3505 --- src/libexpr/primops/fetchTree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 441edd648..727b661e1 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -121,7 +121,7 @@ static void fetchTree( for (auto & attr : *args[0]->attrs) { if (attr.name == state.sType) continue; - state.forceValue(*attr.value); + state.forceValue(*attr.value, *attr.pos); if (attr.value->type() == nPath || attr.value->type() == nString) { auto s = state.coerceToString(*attr.pos, *attr.value, context, false, false); attrs.emplace(attr.name, From ffeec5f283464744fc0ba850622671eb1e91e4c7 Mon Sep 17 00:00:00 2001 From: John Chapman Date: Sun, 17 Oct 2021 15:24:22 +1100 Subject: [PATCH 10/23] Clarify that not all nix packages will use the default build phases --- doc/manual/src/command-ref/nix-shell.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/manual/src/command-ref/nix-shell.md b/doc/manual/src/command-ref/nix-shell.md index 8bcad85e1..0bd54b955 100644 --- a/doc/manual/src/command-ref/nix-shell.md +++ b/doc/manual/src/command-ref/nix-shell.md @@ -110,18 +110,18 @@ shell in which to build it: ```console $ nix-shell '' -A pan -[nix-shell]$ unpackPhase +[nix-shell]$ eval ${unpackPhase:-unpackPhase} [nix-shell]$ cd pan-* -[nix-shell]$ configurePhase -[nix-shell]$ buildPhase +[nix-shell]$ eval ${configurePhase:-configurePhase} +[nix-shell]$ eval ${buildPhase:-buildPhase} [nix-shell]$ ./pan/gui/pan ``` -Note: Other packages may override these phases (the unpackPhase, -configurePhase, buildPhase, etc). -For those, it may be required to do something like -`eval "$configurePhase-configurePhase"` or `eval "$configurePhase"` -depending on how that package's nix files have been written. +The reason we use form `eval ${configurePhase:-configurePhase}` here is because +those packages that override these phases do so by exporting the overridden +values in the environment variable of the same name. +Here bash is being told to either evaluate the contents of 'configurePhase', +if it exists as a variable, otherwise evaluate the configurePhase function. To clear the environment first, and do some additional automatic initialisation of the interactive shell: From 823dce945a702c9ae51a83098f78e55ed780a223 Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Fri, 15 Oct 2021 21:03:01 -0500 Subject: [PATCH 11/23] fetch: nicer infinite recursion errors - This change applies to builtins.fetchurl and builtins.fetchTarball - PoC: `let x = builtins.fetchurl x; in x` - Before: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered ``` - After: ```bash $ nix-instantiate --extra-experimental-features flakes --strict error: infinite recursion encountered at /data/github/kamadorueda/nix/test.nix:1:9: 1| let x = builtins.fetchurl x; in x | ^ ``` Mentions: #3505 --- src/libexpr/primops/fetchTree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 727b661e1..b00a79b7f 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -189,7 +189,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, std::optional url; std::optional expectedHash; - state.forceValue(*args[0]); + state.forceValue(*args[0], pos); if (args[0]->type() == nAttrs) { From 2400819809bed9ab75ea0b6abc4b8564e65aeb7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 22:01:24 +0000 Subject: [PATCH 12/23] Bump actions/checkout from 2.3.4 to 2.3.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.4 to 2.3.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.3.4...v2.3.5) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index abaff75ee..9105b5396 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 with: fetch-depth: 0 - uses: cachix/install-nix-action@v14 @@ -41,7 +41,7 @@ jobs: outputs: installerURL: ${{ steps.prepare-installer.outputs.installerURL }} steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 with: fetch-depth: 0 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV @@ -61,7 +61,7 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v2.3.5 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - uses: cachix/install-nix-action@v14 with: From ec9c1286ad5caf2e77907dc2548085f02cce5237 Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Sat, 23 Oct 2021 15:32:48 +0200 Subject: [PATCH 13/23] Fix devShell build on non-NixOS with a different boost version --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 2d0c44889..5c00f744e 100644 --- a/flake.nix +++ b/flake.nix @@ -61,6 +61,7 @@ configureFlags = lib.optionals stdenv.isLinux [ + "--with-boost=${boost}/lib" "--with-sandbox-shell=${sh}/bin/busybox" "LDFLAGS=-fuse-ld=gold" ]; From af99941279b80c962ec9cae3e5fa32976a3f5744 Mon Sep 17 00:00:00 2001 From: regnat Date: Mon, 25 Oct 2021 15:53:01 +0200 Subject: [PATCH 14/23] Make experimental-features a proper type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than having them plain strings scattered through the whole codebase, create an enum containing all the known experimental features. This means that - Nix can now `warn` when an unkwown experimental feature is passed (making it much nicer to spot typos and spot deprecated features) - It’s now easy to remove a feature altogether (once the feature isn’t experimental anymore or is dropped) by just removing the field for the enum and letting the compiler point us to all the now invalid usages of it. --- src/build-remote/build-remote.cc | 5 +- src/libcmd/installables.cc | 2 +- src/libexpr/eval.cc | 2 +- src/libexpr/eval.hh | 3 +- src/libexpr/flake/flake.cc | 4 +- src/libexpr/parser.y | 2 +- src/libexpr/primops.cc | 2 +- src/libexpr/primops/fetchTree.cc | 10 ++-- src/libstore/build/derivation-goal.cc | 6 +-- src/libstore/build/entry-points.cc | 2 +- src/libstore/build/local-derivation-goal.cc | 6 +-- src/libstore/daemon.cc | 2 +- src/libstore/derivations.cc | 2 +- src/libstore/derived-path.cc | 2 +- src/libstore/globals.cc | 15 ++---- src/libstore/globals.hh | 16 ++---- src/libstore/local-store.cc | 10 ++-- src/libstore/store-api.cc | 6 +-- src/libutil/config.cc | 27 ++++++++++ src/libutil/experimental-features.cc | 55 ++++++++++++++++++++ src/libutil/experimental-features.hh | 56 +++++++++++++++++++++ src/nix-build/nix-build.cc | 2 +- src/nix/develop.cc | 2 +- src/nix/flake.cc | 2 +- src/nix/main.cc | 2 +- src/nix/realisation.cc | 2 +- src/nix/sigs.cc | 2 +- tests/config.sh | 2 +- 28 files changed, 188 insertions(+), 61 deletions(-) create mode 100644 src/libutil/experimental-features.cc create mode 100644 src/libutil/experimental-features.hh diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 0559aeaf4..a6722a1f8 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -18,6 +18,7 @@ #include "derivations.hh" #include "local-store.hh" #include "legacy.hh" +#include "experimental-features.hh" using namespace nix; using std::cin; @@ -295,7 +296,7 @@ connected: std::set missingRealisations; StorePathSet missingPaths; - if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) { for (auto & outputName : wantedOutputs) { auto thisOutputHash = outputHashes.at(outputName); auto thisOutputId = DrvOutput{ thisOutputHash, outputName }; @@ -327,7 +328,7 @@ connected: for (auto & realisation : missingRealisations) { // Should hold, because if the feature isn't enabled the set // of missing realisations should be empty - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); store->registerDrvOutput(realisation); } diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 0f0fcf39e..5758b52ad 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -714,7 +714,7 @@ BuiltPaths getBuiltPaths(ref evalStore, ref store, const DerivedPa "the derivation '%s' doesn't have an output named '%s'", store->printStorePath(bfd.drvPath), output); if (settings.isExperimentalFeatureEnabled( - "ca-derivations")) { + Xp::CaDerivations)) { auto outputId = DrvOutput{outputHashes.at(output), output}; auto realisation = diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 3ae05a8d8..db1e7e56d 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -466,7 +466,7 @@ EvalState::~EvalState() void EvalState::requireExperimentalFeatureOnEvaluation( - const std::string & feature, + const ExperimentalFeature & feature, const std::string_view fName, const Pos & pos) { diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 7cc16ef0a..69119599a 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -5,6 +5,7 @@ #include "nixexpr.hh" #include "symbol-table.hh" #include "config.hh" +#include "experimental-features.hh" #include #include @@ -141,7 +142,7 @@ public: ~EvalState(); void requireExperimentalFeatureOnEvaluation( - const std::string & feature, + const ExperimentalFeature &, const std::string_view fName, const Pos & pos ); diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 43bfc3644..c9d848495 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -297,7 +297,7 @@ LockedFlake lockFlake( const FlakeRef & topRef, const LockFlags & lockFlags) { - settings.requireExperimentalFeature("flakes"); + settings.requireExperimentalFeature(Xp::Flakes); FlakeCache flakeCache; @@ -687,7 +687,7 @@ void callFlake(EvalState & state, static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v) { - state.requireExperimentalFeatureOnEvaluation("flakes", "builtins.getFlake", pos); + state.requireExperimentalFeatureOnEvaluation(Xp::Flakes, "builtins.getFlake", pos); auto flakeRefS = state.forceStringNoCtx(*args[0], pos); auto flakeRef = parseFlakeRef(flakeRefS, {}, true); diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 8a0a79c96..380afa6b7 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -418,7 +418,7 @@ expr_simple new ExprString(data->symbols.create(path))); } | URI { - static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals"); + static bool noURLLiterals = settings.isExperimentalFeatureEnabled(Xp::NoUrlLiterals); if (noURLLiterals) throw ParseError({ .msg = hintfmt("URL literals are disabled"), diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 4e0eda7f3..6b3cafec8 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -985,7 +985,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * } if (i->name == state.sContentAddressed) { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); contentAddressed = state.forceBool(*i->value, pos); } diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index b00a79b7f..dacd78fd3 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -176,7 +176,7 @@ static void fetchTree( static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v) { - settings.requireExperimentalFeature("flakes"); + settings.requireExperimentalFeature(Xp::Flakes); fetchTree(state, pos, args, v, std::nullopt, FetchTreeParams { .allowNameArgument = false }); } @@ -290,7 +290,7 @@ static RegisterPrimOp primop_fetchTarball({ The fetched tarball is cached for a certain amount of time (1 hour by default) in `~/.cache/nix/tarballs/`. You can change the cache timeout either on the command line with `--option tarball-ttl number - of seconds` or in the Nix configuration file with this option: ` + of seconds` or in the Nix configuration file with this option: ` number of seconds to cache `. Note that when obtaining the hash with ` nix-prefetch-url ` the @@ -393,7 +393,7 @@ static RegisterPrimOp primop_fetchGit({ ``` > **Note** - > + > > It is nice to always specify the branch which a revision > belongs to. Without the branch being specified, the fetcher > might fail if the default branch changes. Additionally, it can @@ -430,12 +430,12 @@ static RegisterPrimOp primop_fetchGit({ ``` > **Note** - > + > > Nix will refetch the branch in accordance with > the option `tarball-ttl`. > **Note** - > + > > This behavior is disabled in *Pure evaluation mode*. )", .fun = prim_fetchGit, diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 0907120db..67cf8b067 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -204,7 +204,7 @@ void DerivationGoal::haveDerivation() trace("have derivation"); if (drv->type() == DerivationType::CAFloating) - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); retrySubstitution = false; @@ -453,7 +453,7 @@ void DerivationGoal::inputsRealised() if (useDerivation) { auto & fullDrv = *dynamic_cast(drv.get()); - if (settings.isExperimentalFeatureEnabled("ca-derivations") && + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && ((!fullDrv.inputDrvs.empty() && derivationIsCA(fullDrv.type())) || fullDrv.type() == DerivationType::DeferredInputAddressed)) { /* We are be able to resolve this derivation based on the @@ -1273,7 +1273,7 @@ void DerivationGoal::checkPathValidity() : PathStatus::Corrupt, }; } - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { auto drvOutput = DrvOutput{initialOutputs.at(i.first).outputHash, i.first}; if (auto real = worker.store.queryRealisation(drvOutput)) { info.known = { diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc index 2b77e4354..065efc855 100644 --- a/src/libstore/build/entry-points.cc +++ b/src/libstore/build/entry-points.cc @@ -74,7 +74,7 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat outputId, Realisation{ outputId, *staticOutput.second} ); - if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) { auto realisation = this->queryRealisation(outputId); if (realisation) result.builtOutputs.insert_or_assign( diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 8d245f84a..fab6c3a08 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -1259,7 +1259,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo for (auto & [outputName, outputPath] : outputs) if (wantOutput(outputName, bfd.outputs)) { newPaths.insert(outputPath); - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { auto thisRealisation = next->queryRealisation( DrvOutput{drvHashes.at(outputName), outputName} ); @@ -1320,7 +1320,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo void LocalDerivationGoal::startDaemon() { - settings.requireExperimentalFeature("recursive-nix"); + settings.requireExperimentalFeature(Xp::RecursiveNix); Store::Params params; params["path-info-cache-size"] = "0"; @@ -2561,7 +2561,7 @@ void LocalDerivationGoal::registerOutputs() that for floating CA derivations, which otherwise couldn't be cached, but it's fine to do in all cases. */ - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { for (auto& [outputName, newInfo] : infos) { auto thisRealisation = Realisation{ .id = DrvOutput{initialOutputs.at(outputName).outputHash, diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 164a9b2be..4e8a3c417 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -230,7 +230,7 @@ struct ClientSettings else if (name == settings.experimentalFeatures.name) { // We don’t want to forward the experimental features to // the daemon, as that could cause some pretty weird stuff - if (tokenizeString(value) != settings.experimentalFeatures.get()) + if (parseFeatures(tokenizeString(value)) != settings.experimentalFeatures.get()) debug("Ignoring the client-specified experimental features"); } else if (trusted diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index ef8765841..b926bb711 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -187,7 +187,7 @@ static DerivationOutput parseDerivationOutput(const Store & store, }, }; } else { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); assert(pathS == ""); return DerivationOutput { .output = DerivationOutputCAFloating { diff --git a/src/libstore/derived-path.cc b/src/libstore/derived-path.cc index e55af21e9..3d188e981 100644 --- a/src/libstore/derived-path.cc +++ b/src/libstore/derived-path.cc @@ -100,7 +100,7 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const staticOutputHashes(store, store.readDerivation(p.drvPath)); for (auto& [outputName, outputPath] : p.outputs) { if (settings.isExperimentalFeatureEnabled( - "ca-derivations")) { + Xp::CaDerivations)) { auto thisRealisation = store.queryRealisation( DrvOutput{drvHashes.at(outputName), outputName}); assert(thisRealisation); // We’ve built it, so we must h diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 4903d0922..9f1a88130 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -160,21 +160,16 @@ StringSet Settings::getDefaultExtraPlatforms() return extraPlatforms; } -bool Settings::isExperimentalFeatureEnabled(const std::string & name) +bool Settings::isExperimentalFeatureEnabled(const ExperimentalFeature & feature) { auto & f = experimentalFeatures.get(); - return std::find(f.begin(), f.end(), name) != f.end(); + return std::find(f.begin(), f.end(), feature) != f.end(); } -MissingExperimentalFeature::MissingExperimentalFeature(std::string feature) - : Error("experimental Nix feature '%1%' is disabled; use '--extra-experimental-features %1%' to override", feature) - , missingFeature(feature) - {} - -void Settings::requireExperimentalFeature(const std::string & name) +void Settings::requireExperimentalFeature(const ExperimentalFeature & feature) { - if (!isExperimentalFeatureEnabled(name)) - throw MissingExperimentalFeature(name); + if (!isExperimentalFeatureEnabled(feature)) + throw MissingExperimentalFeature(feature); } bool Settings::isWSL1() diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 8784d5faf..165639261 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -3,6 +3,7 @@ #include "types.hh" #include "config.hh" #include "util.hh" +#include "experimental-features.hh" #include #include @@ -45,15 +46,6 @@ struct PluginFilesSetting : public BaseSetting void set(const std::string & str, bool append = false) override; }; -class MissingExperimentalFeature: public Error -{ -public: - std::string missingFeature; - - MissingExperimentalFeature(std::string feature); - virtual const char* sname() const override { return "MissingExperimentalFeature"; } -}; - class Settings : public Config { unsigned int getDefaultCores(); @@ -925,12 +917,12 @@ public: value. )"}; - Setting experimentalFeatures{this, {}, "experimental-features", + Setting> experimentalFeatures{this, {}, "experimental-features", "Experimental Nix features to enable."}; - bool isExperimentalFeatureEnabled(const std::string & name); + bool isExperimentalFeatureEnabled(const ExperimentalFeature &); - void requireExperimentalFeature(const std::string & name); + void requireExperimentalFeature(const ExperimentalFeature &); Setting allowDirty{this, true, "allow-dirty", "Whether to allow dirty Git/Mercurial trees."}; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 5b2490472..1e3b5482e 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -309,7 +309,7 @@ LocalStore::LocalStore(const Params & params) else openDB(*state, false); - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { migrateCASchema(state->db, dbDir + "/ca-schema", globalLock); } @@ -339,7 +339,7 @@ LocalStore::LocalStore(const Params & params) state->stmts->QueryPathFromHashPart.create(state->db, "select path from ValidPaths where path >= ? limit 1;"); state->stmts->QueryValidPaths.create(state->db, "select path from ValidPaths"); - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { state->stmts->RegisterRealisedOutput.create(state->db, R"( insert into Realisations (drvPath, outputName, outputPath, signatures) @@ -708,7 +708,7 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs) { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info)) registerDrvOutput(info); else @@ -717,7 +717,7 @@ void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag check void LocalStore::registerDrvOutput(const Realisation & info) { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); retrySQLite([&]() { auto state(_state.lock()); if (auto oldR = queryRealisation_(*state, info.id)) { @@ -1003,7 +1003,7 @@ LocalStore::queryPartialDerivationOutputMap(const StorePath & path_) return outputs; }); - if (!settings.isExperimentalFeatureEnabled("ca-derivations")) + if (!settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) return outputs; auto drv = readInvalidDerivation(path); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b5ff3dccf..3338cdc1b 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -355,7 +355,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath, StringSet StoreConfig::getDefaultSystemFeatures() { auto res = settings.systemFeatures.get(); - if (settings.isExperimentalFeatureEnabled("ca-derivations")) + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) res.insert("ca-derivations"); return res; } @@ -860,7 +860,7 @@ std::map copyPaths( for (auto & path : paths) { storePaths.insert(path.path()); if (auto realisation = std::get_if(&path.raw)) { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); toplevelRealisations.insert(*realisation); } } @@ -892,7 +892,7 @@ std::map copyPaths( // Don't fail if the remote doesn't support CA derivations is it might // not be within our control to change that, and we might still want // to at least copy the output paths. - if (e.missingFeature == "ca-derivations") + if (e.missingFeature == Xp::CaDerivations) ignoreException(); else throw; diff --git a/src/libutil/config.cc b/src/libutil/config.cc index c247c7dae..026db6574 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -1,6 +1,7 @@ #include "config.hh" #include "args.hh" #include "abstract-setting-to-json.hh" +#include "experimental-features.hh" #include @@ -313,6 +314,31 @@ template<> std::string BaseSetting::to_string() const return concatStringsSep(" ", value); } +template<> void BaseSetting>::set(const std::string & str, bool append) +{ + if (!append) value.clear(); + for (auto & s : tokenizeString(str)) { + auto thisXpFeature = parseExperimentalFeature(s); + if (thisXpFeature) + value.insert(thisXpFeature.value()); + else + warn("Unknown experimental feature %s", s); + } +} + +template<> bool BaseSetting>::isAppendable() +{ + return true; +} + +template<> std::string BaseSetting>::to_string() const +{ + StringSet stringifiedXpFeatures; + for (auto & feature : value) + stringifiedXpFeatures.insert(std::string(showExperimentalFeature(feature))); + return concatStringsSep(" ", stringifiedXpFeatures); +} + template<> void BaseSetting::set(const std::string & str, bool append) { if (!append) value.clear(); @@ -348,6 +374,7 @@ template class BaseSetting; template class BaseSetting; template class BaseSetting; template class BaseSetting; +template class BaseSetting>; void PathSetting::set(const std::string & str, bool append) { diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc new file mode 100644 index 000000000..d1235d8a4 --- /dev/null +++ b/src/libutil/experimental-features.cc @@ -0,0 +1,55 @@ +#include "experimental-features.hh" +#include "nlohmann/json.hpp" + +namespace nix { + +std::map stringifiedXpFeatures = { + { Xp::CaDerivations, "ca-derivations" }, + { Xp::Flakes, "flakes" }, + { Xp::NixCommand, "nix-command" }, + { Xp::RecursiveNix, "recursive-nix" }, + { Xp::NoUrlLiterals, "no-url-literals" }, +}; + +const std::optional parseExperimentalFeature(const std::string_view & name) +{ + using ReverseXpMap = std::map; + static ReverseXpMap * reverseXpMap; + if (!reverseXpMap) { + reverseXpMap = new ReverseXpMap{}; + for (auto & [feature, name] : stringifiedXpFeatures) + (*reverseXpMap)[name] = feature; + } + + auto featureIter = reverseXpMap->find(name); + if (featureIter == reverseXpMap->end()) + return std::nullopt; + return {featureIter->second}; +} + +std::string_view showExperimentalFeature(const ExperimentalFeature feature) +{ + return stringifiedXpFeatures.at(feature); +} + +std::set parseFeatures(const std::set & rawFeatures) +{ + std::set res; + for (auto & rawFeature : rawFeatures) { + if (auto feature = parseExperimentalFeature(rawFeature)) + res.insert(*feature); + } + return res; +} + +MissingExperimentalFeature::MissingExperimentalFeature(ExperimentalFeature feature) + : Error("experimental Nix feature '%1%' is disabled; use '--extra-experimental-features %1%' to override", showExperimentalFeature(feature)) + , missingFeature(feature) + {} + +std::ostream & operator <<(std::ostream & str, const ExperimentalFeature & feature) +{ + return str << showExperimentalFeature(feature); +} + +} diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh new file mode 100644 index 000000000..291a58e32 --- /dev/null +++ b/src/libutil/experimental-features.hh @@ -0,0 +1,56 @@ +#pragma once + +#include "comparator.hh" +#include "error.hh" +#include "nlohmann/json_fwd.hpp" +#include "types.hh" + +namespace nix { + +/** + * The list of available experimental features. + * + * If you update this, don’t forget to also change the map defining their + * string representation in the corresponding `.cc` file. + **/ +enum struct ExperimentalFeature +{ + CaDerivations, + Flakes, + NixCommand, + RecursiveNix, + NoUrlLiterals +}; + +/** + * Just because writing `ExperimentalFeature::CaDerivations` is way too long + */ +using Xp = ExperimentalFeature; + +const std::optional parseExperimentalFeature( + const std::string_view & name); +std::string_view showExperimentalFeature(const ExperimentalFeature); + +std::ostream & operator<<( + std::ostream & str, + const ExperimentalFeature & feature); + +/** + * Parse a set of strings to the corresponding set of experimental features, + * ignoring (but warning for) any unkwown feature. + */ +std::set parseFeatures(const std::set &); + +class MissingExperimentalFeature : public Error +{ +public: + ExperimentalFeature missingFeature; + + MissingExperimentalFeature(ExperimentalFeature); + virtual const char * sname() const override + { + return "MissingExperimentalFeature"; + } +}; + +} diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 77594f046..73d93480e 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -401,7 +401,7 @@ static void main_nix_build(int argc, char * * argv) if (dryRun) return; - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { auto resolvedDrv = drv.tryResolve(*store); assert(resolvedDrv && "Successfully resolved the derivation"); drv = *resolvedDrv; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index f22335023..5aad53919 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -195,7 +195,7 @@ static StorePath getDerivationEnvironment(ref store, ref evalStore 'buildDerivation', but that's privileged. */ drv.name += "-env"; drv.inputSrcs.insert(std::move(getEnvShPath)); - if (settings.isExperimentalFeatureEnabled("ca-derivations")) { + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { for (auto & output : drv.outputs) { output.second = { .output = DerivationOutputDeferred{}, diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 7e4d23f6e..68bb76742 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1138,7 +1138,7 @@ struct CmdFlake : NixMultiCommand { if (!command) throw UsageError("'nix flake' requires a sub-command."); - settings.requireExperimentalFeature("flakes"); + settings.requireExperimentalFeature(Xp::Flakes); command->second->prepare(); command->second->run(); } diff --git a/src/nix/main.cc b/src/nix/main.cc index 2c3976689..1e033f4f2 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -337,7 +337,7 @@ void mainWrapped(int argc, char * * argv) if (args.command->first != "repl" && args.command->first != "doctor" && args.command->first != "upgrade-nix") - settings.requireExperimentalFeature("nix-command"); + settings.requireExperimentalFeature(Xp::NixCommand); if (args.useNet && !haveInternet()) { warn("you don't have Internet access; disabling some network-dependent features"); diff --git a/src/nix/realisation.cc b/src/nix/realisation.cc index dfa8ff449..c9a7157cd 100644 --- a/src/nix/realisation.cc +++ b/src/nix/realisation.cc @@ -46,7 +46,7 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON void run(ref store, BuiltPaths && paths) override { - settings.requireExperimentalFeature("ca-derivations"); + settings.requireExperimentalFeature(Xp::CaDerivations); RealisedPath::Set realisations; for (auto & builtPath : paths) { diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 43e0d9148..6a238efbe 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -219,7 +219,7 @@ struct CmdKey : NixMultiCommand { if (!command) throw UsageError("'nix flake' requires a sub-command."); - settings.requireExperimentalFeature("flakes"); + settings.requireExperimentalFeature(Xp::Flakes); command->second->prepare(); command->second->run(); } diff --git a/tests/config.sh b/tests/config.sh index 01c78f2c3..3d0da3cef 100644 --- a/tests/config.sh +++ b/tests/config.sh @@ -50,4 +50,4 @@ exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs) [[ $prev != $exp_cores ]] [[ $exp_cores == "4242" ]] -[[ $exp_features == "nix-command flakes" ]] +[[ $exp_features == "flakes nix-command" ]] From 9ce84c64c5820847a8084f31da5c5e2f549cbbcf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 26 Oct 2021 14:21:24 +0200 Subject: [PATCH 15/23] Tweak fetchTree docs --- src/libexpr/primops/fetchTree.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index dacd78fd3..e6becdafc 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -287,13 +287,13 @@ static RegisterPrimOp primop_fetchTarball({ stdenv.mkDerivation { … } ``` - The fetched tarball is cached for a certain amount of time (1 hour - by default) in `~/.cache/nix/tarballs/`. You can change the cache - timeout either on the command line with `--option tarball-ttl number - of seconds` or in the Nix configuration file with this option: ` - number of seconds to cache `. + The fetched tarball is cached for a certain amount of time (1 + hour by default) in `~/.cache/nix/tarballs/`. You can change the + cache timeout either on the command line with `--tarball-ttl` + *number-of-seconds* or in the Nix configuration file by adding + the line `tarball-ttl = ` *number-of-seconds*. - Note that when obtaining the hash with ` nix-prefetch-url ` the + Note that when obtaining the hash with `nix-prefetch-url` the option `--unpack` is required. This function can also verify the contents against a hash. In that From 0d9e050ba719515620a2e320a7b6bba35f1d1df6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 26 Oct 2021 14:29:48 +0200 Subject: [PATCH 16/23] parseExperimentalFeature(): Initialize atomically --- src/libutil/experimental-features.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index d1235d8a4..b49f47e1d 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -1,4 +1,6 @@ #include "experimental-features.hh" +#include "util.hh" + #include "nlohmann/json.hpp" namespace nix { @@ -14,17 +16,19 @@ std::map stringifiedXpFeatures = { const std::optional parseExperimentalFeature(const std::string_view & name) { using ReverseXpMap = std::map; - static ReverseXpMap * reverseXpMap; - if (!reverseXpMap) { - reverseXpMap = new ReverseXpMap{}; + + static auto reverseXpMap = []() + { + auto reverseXpMap = std::make_unique(); for (auto & [feature, name] : stringifiedXpFeatures) (*reverseXpMap)[name] = feature; - } + return reverseXpMap; + }(); - auto featureIter = reverseXpMap->find(name); - if (featureIter == reverseXpMap->end()) + if (auto feature = get(*reverseXpMap, name)) + return *feature; + else return std::nullopt; - return {featureIter->second}; } std::string_view showExperimentalFeature(const ExperimentalFeature feature) @@ -45,7 +49,7 @@ std::set parseFeatures(const std::set & rawFea MissingExperimentalFeature::MissingExperimentalFeature(ExperimentalFeature feature) : Error("experimental Nix feature '%1%' is disabled; use '--extra-experimental-features %1%' to override", showExperimentalFeature(feature)) , missingFeature(feature) - {} +{} std::ostream & operator <<(std::ostream & str, const ExperimentalFeature & feature) { From 13a7a24ba5213a536911320c0ee69faf26bc3f53 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 13:01:56 +0200 Subject: [PATCH 17/23] Style --- src/libutil/config.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 026db6574..92ab265d3 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -322,7 +322,7 @@ template<> void BaseSetting>::set(const std::strin if (thisXpFeature) value.insert(thisXpFeature.value()); else - warn("Unknown experimental feature %s", s); + warn("unknown experimental feature '%s'", s); } } From 6e684d1b8747ed0180489eacbdf920a82162e249 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 13:09:13 +0200 Subject: [PATCH 18/23] daemon: Accept 'repeat' setting from untrusted users Fixes #5352. --- src/libstore/daemon.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 4e8a3c417..4b3465da3 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -235,6 +235,7 @@ struct ClientSettings } else if (trusted || name == settings.buildTimeout.name + || name == settings.buildRepeat.name || name == "connect-timeout" || (name == "builders" && value == "")) settings.set(name, value); From f2280749b1d58a56f91ad417b487e920ab23b8b6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 14:21:31 +0200 Subject: [PATCH 19/23] If max-jobs == 0, do preferLocalBuild on remote builders --- src/libstore/build/derivation-goal.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 67cf8b067..b924d23b2 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -616,7 +616,9 @@ void DerivationGoal::tryToBuild() /* Don't do a remote build if the derivation has the attribute `preferLocalBuild' set. Also, check and repair modes are only supported for local builds. */ - bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store); + bool buildLocally = + (buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store)) + && settings.maxBuildJobs.get() != 0; if (!buildLocally) { switch (tryBuildHook()) { From 1254e8753c4f07173b0463afad35d9020c6093d7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 14:25:13 +0200 Subject: [PATCH 20/23] build-remote: Implicitly add the 'builtin' system type to all machines This makes 'nix-env -i --max-jobs 0' work with remote builders. --- src/build-remote/build-remote.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index a6722a1f8..9d541b45d 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -131,11 +131,14 @@ static int main_build_remote(int argc, char * * argv) for (auto & m : machines) { debug("considering building on remote machine '%s'", m.storeUri); - if (m.enabled && std::find(m.systemTypes.begin(), - m.systemTypes.end(), - neededSystem) != m.systemTypes.end() && + if (m.enabled + && (neededSystem == "builtin" + || std::find(m.systemTypes.begin(), + m.systemTypes.end(), + neededSystem) != m.systemTypes.end()) && m.allSupported(requiredFeatures) && - m.mandatoryMet(requiredFeatures)) { + m.mandatoryMet(requiredFeatures)) + { rightType = true; AutoCloseFD free; uint64_t load = 0; From 9c6ac9eb0ee4191dd6ba2a9216e12d68bbc54f8b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 17:32:44 +0200 Subject: [PATCH 21/23] 2.4 release notes: Add some migration notes --- doc/manual/src/release-notes/rl-2.4.md | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/manual/src/release-notes/rl-2.4.md b/doc/manual/src/release-notes/rl-2.4.md index def4a7b66..3c94e6740 100644 --- a/doc/manual/src/release-notes/rl-2.4.md +++ b/doc/manual/src/release-notes/rl-2.4.md @@ -1,4 +1,4 @@ -# Release 2.4 (2021-10-XX) +# Release 2.4 (2021-11-01) This is the first release in more than two years and is the result of more than 2800 commits from 195 contributors since release 2.3. @@ -286,8 +286,35 @@ more than 2800 commits from 195 contributors since release 2.3. to your `nix.conf` if you want to use it, or pass `--extra-experimental-features nix-command` on the command line. -* The old `nix run` has been renamed to `nix shell` (and there is a - new `nix run` that does something else, as described above). +* The `nix` command no longer has a syntax for referring to packages + in a channel. This means that the following no longer works: + + > nix build nixpkgs.hello # Nix 2.3 + + Instead, you can either use the `#` syntax to select a package from + a flake, e.g. + + > nix build nixpkgs#hello + + Or, if you want to use the `nixpkgs` channel in the `NIX_PATH` + environment variable: + + > nix build -f '' hello + +* The old `nix run` has been renamed to `nix shell`, while there is a + new `nix run` that runs a default command. So instead of + + > nix run nixpkgs.hello -c hello # Nix 2.3 + + you should use + + > nix shell nixpkgs#hello -c hello + + or just + + > nix run nixpkgs#hello + + if the command you want to run has the same name as the package. * It is now an error to modify the `plugin-files` setting via a command-line flag that appears after the first non-flag argument to From 5a160171d05c4bde95a7ae75c133912e08186a12 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Oct 2021 18:14:12 +0200 Subject: [PATCH 22/23] Remove redundant 'warning:' --- src/libexpr/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 380afa6b7..813ff2fc3 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -752,7 +752,7 @@ std::pair EvalState::resolveSearchPathElem(const SearchPathEl res = { true, path }; else { logWarning({ - .msg = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second) + .msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", elem.second) }); res = { false, "" }; } From bc4b7521f4a72de1d7a9db0b5be76885e0729e7c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 28 Oct 2021 14:36:47 +0200 Subject: [PATCH 23/23] Rename rl-2.5.md to rl-next.md Having a generically named file for release notes for the next release makes things easier for PRs. --- doc/manual/src/SUMMARY.md.in | 3 ++- doc/manual/src/release-notes/{rl-2.5.md => rl-next.md} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename doc/manual/src/release-notes/{rl-2.5.md => rl-next.md} (100%) diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md.in index df9209c7d..3869f4791 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md.in @@ -70,7 +70,8 @@ - [Hacking](contributing/hacking.md) - [CLI guideline](contributing/cli-guideline.md) - [Release Notes](release-notes/release-notes.md) - - [Release 2.4 (2021-XX-XX)](release-notes/rl-2.4.md) + - [Release X.Y (202?-??-??)](release-notes/rl-next.md) + - [Release 2.4 (2021-11-01)](release-notes/rl-2.4.md) - [Release 2.3 (2019-09-04)](release-notes/rl-2.3.md) - [Release 2.2 (2019-01-11)](release-notes/rl-2.2.md) - [Release 2.1 (2018-09-02)](release-notes/rl-2.1.md) diff --git a/doc/manual/src/release-notes/rl-2.5.md b/doc/manual/src/release-notes/rl-next.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.5.md rename to doc/manual/src/release-notes/rl-next.md