From c1bbb11c5d41b2a0596de5e16d7a2f990e8d2b16 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Mon, 25 Apr 2022 21:23:06 +1200 Subject: [PATCH] Add support for recurseForDerivations This will respect `recurseForDerivations` when iterating over attrsets. Example expression: ``` nix { system ? builtins.currentSystem }: { recurseForDerivations = true; # This should build as it's in the top-level attrset drvA = derivation { inherit system; name = "drvA"; builder = ":"; }; dontRecurse = { # This shouldn't build as `recurseForDerivations = true;` is not set # recurseForDerivations = true; # This should not build drvB = derivation { inherit system; name = "drvA"; builder = ":"; }; }; recurse = { # This should build recurseForDerivations = true; # This should not build drvC = derivation { inherit system; name = "drvC"; builder = ":"; }; }; } ``` --- src/nix-eval-jobs.cc | 13 +++++++++++-- tests/assets/ci.nix | 31 ++++++++++++++++++++++++++++--- tests/test_eval.py | 13 ++++++++----- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/nix-eval-jobs.cc b/src/nix-eval-jobs.cc index 3031c69..8bd2479 100644 --- a/src/nix-eval-jobs.cc +++ b/src/nix-eval-jobs.cc @@ -281,7 +281,8 @@ static void worker( else if (v->type() == nAttrs) { auto attrs = nlohmann::json::array(); - StringSet ss; + bool recurse = attrPath == ""; // Dont require `recurseForDerivations = true;` for top-level attrset + for (auto & i : v->attrs->lexicographicOrder()) { std::string name(i->name); if (name.find('.') != std::string::npos || name.find(' ') != std::string::npos) { @@ -289,8 +290,16 @@ static void worker( continue; } attrs.push_back(name); + + if (name == "recurseForDerivations") { + auto attrv = v->attrs->get(state.sRecurseForDerivations); + recurse = state.forceBool(*attrv->value, *attrv->pos); + } } - reply["attrs"] = std::move(attrs); + if (recurse) + reply["attrs"] = std::move(attrs); + else + reply["attrs"] = nlohmann::json::array(); } else if (v->type() == nNull) diff --git a/tests/assets/ci.nix b/tests/assets/ci.nix index 27b4604..a80ad88 100644 --- a/tests/assets/ci.nix +++ b/tests/assets/ci.nix @@ -1,9 +1,34 @@ -{ pkgs ? import (builtins.getFlake (toString ./.)).inputs.nixpkgs { } }: +{ + pkgs ? import (builtins.getFlake (toString ./.)).inputs.nixpkgs { } + , system ? pkgs.system +}: { builtJob = pkgs.writeText "job1" "job1"; substitutedJob = pkgs.hello; - nested = { - job = pkgs.hello; + + dontRecurse = { + # This shouldn't build as `recurseForDerivations = true;` is not set + # recurseForDerivations = true; + + # This should not build + drvB = derivation { + inherit system; + name = "drvA"; + builder = ":"; + }; }; + + recurse = { + # This should build + recurseForDerivations = true; + + # This should not build + drvB = derivation { + inherit system; + name = "drvB"; + builder = ":"; + }; + }; + } diff --git a/tests/test_eval.py b/tests/test_eval.py index a334d51..0c86524 100644 --- a/tests/test_eval.py +++ b/tests/test_eval.py @@ -23,7 +23,7 @@ def common_test(extra_args: List[str]) -> None: ) results = [json.loads(r) for r in res.stdout.split("\n") if r] - assert len(results) == 3 + assert len(results) == 4 built_job = results[0] assert built_job["attr"] == "builtJob" @@ -32,11 +32,14 @@ def common_test(extra_args: List[str]) -> None: assert built_job["drvPath"].endswith(".drv") assert built_job["meta"]['broken'] is False - nested_job = results[1] - assert nested_job["attr"] == "nested.job" - assert nested_job["name"].startswith("hello-") + recurse_drv = results[1] + assert recurse_drv["attr"] == "recurse.drvB" + assert recurse_drv["name"] == "drvB" - substituted_job = results[2] + recurse_recurse_bool = results[2] + assert "error" in recurse_recurse_bool + + substituted_job = results[3] assert substituted_job["attr"] == "substitutedJob" assert substituted_job["name"].startswith("hello-") assert substituted_job["meta"]['broken'] is False