From 5f6658b9c909894a89da74c3f34b1ebe1434b8e7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 28 Jan 2025 15:32:06 +0100 Subject: [PATCH] fetchTree: Distinguish between fetchGit and fetchTree consistently --- src/libexpr/primops/fetchTree.cc | 31 +++++++++---------- tests/functional/fetchGit.sh | 2 +- .../lang/eval-fail-fetchTree-negative.err.exp | 2 +- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index fe42b88f129..8c2d9ed06ad 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -90,24 +90,26 @@ static void fetchTree( fetchers::Input input { state.fetchSettings }; NixStringContext context; std::optional type; + auto fetcher = params.isFetchGit ? "fetchGit" : "fetchTree"; if (params.isFetchGit) type = "git"; state.forceValue(*args[0], pos); if (args[0]->type() == nAttrs) { - state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.fetchTree"); + state.forceAttrs(*args[0], pos, fmt("while evaluating the argument passed to '%s'", fetcher)); fetchers::Attrs attrs; if (auto aType = args[0]->attrs()->get(state.sType)) { if (type) state.error( - "unexpected attribute 'type'" + "unexpected argument 'type'" ).atPos(pos).debugThrow(); - type = state.forceStringNoCtx(*aType->value, aType->pos, "while evaluating the `type` attribute passed to builtins.fetchTree"); + type = state.forceStringNoCtx(*aType->value, aType->pos, + fmt("while evaluating the `type` argument passed to '%s'", fetcher)); } else if (!type) state.error( - "attribute 'type' is missing in call to 'fetchTree'" + "argument 'type' is missing in call to '%s'", fetcher ).atPos(pos).debugThrow(); attrs.emplace("type", type.value()); @@ -127,9 +129,8 @@ static void fetchTree( else if (attr.value->type() == nInt) { auto intValue = attr.value->integer().value; - if (intValue < 0) { - state.error("negative value given for fetchTree attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow(); - } + if (intValue < 0) + state.error("negative value given for '%s' argument '%s': %d", fetcher, state.symbols[attr.name], intValue).atPos(pos).debugThrow(); attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); } else if (state.symbols[attr.name] == "publicKeys") { @@ -137,8 +138,8 @@ static void fetchTree( attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump()); } else - state.error("fetchTree argument '%s' is %s while a string, Boolean or integer is expected", - state.symbols[attr.name], showType(*attr.value)).debugThrow(); + state.error("argument '%s' to '%s' is %s while a string, Boolean or integer is expected", + state.symbols[attr.name], fetcher, showType(*attr.value)).debugThrow(); } if (params.isFetchGit && !attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) { @@ -153,14 +154,14 @@ static void fetchTree( if (!params.allowNameArgument) if (auto nameIter = attrs.find("name"); nameIter != attrs.end()) state.error( - "attribute 'name' isn’t supported in call to 'fetchTree'" + "argument 'name' isn’t supported in call to '%s'", fetcher ).atPos(pos).debugThrow(); input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs)); } else { auto url = state.coerceToString(pos, *args[0], context, - "while evaluating the first argument passed to the fetcher", - false, false).toOwned(); + fmt("while evaluating the first argument passed to '%s'", fetcher), + false, false).toOwned(); if (params.isFetchGit) { fetchers::Attrs attrs; @@ -173,7 +174,7 @@ static void fetchTree( } else { if (!experimentalFeatureSettings.isEnabled(Xp::Flakes)) state.error( - "passing a string argument to 'fetchTree' requires the 'flakes' experimental feature" + "passing a string argument to '%s' requires the 'flakes' experimental feature", fetcher ).atPos(pos).debugThrow(); input = fetchers::Input::fromURL(state.fetchSettings, url); } @@ -183,10 +184,6 @@ static void fetchTree( input = lookupInRegistries(state.store, input).first; if (state.settings.pureEval && !input.isConsideredLocked(state.fetchSettings)) { - auto fetcher = "fetchTree"; - if (params.isFetchGit) - fetcher = "fetchGit"; - state.error( "in pure evaluation mode, '%s' will not fetch unlocked input '%s'", fetcher, input.to_string() diff --git a/tests/functional/fetchGit.sh b/tests/functional/fetchGit.sh index 78925b5cdd6..2056117cea5 100755 --- a/tests/functional/fetchGit.sh +++ b/tests/functional/fetchGit.sh @@ -79,7 +79,7 @@ path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \" # In pure eval mode, fetchGit with a revision should succeed. [[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]] -# But without a hash, it fails +# But without a hash, it fails. expectStderr 1 nix eval --expr 'builtins.fetchGit "file:///foo"' | grepQuiet "'fetchGit' will not fetch unlocked input" # Fetch again. This should be cached. diff --git a/tests/functional/lang/eval-fail-fetchTree-negative.err.exp b/tests/functional/lang/eval-fail-fetchTree-negative.err.exp index d9ba1f0b2f8..423123ca0a7 100644 --- a/tests/functional/lang/eval-fail-fetchTree-negative.err.exp +++ b/tests/functional/lang/eval-fail-fetchTree-negative.err.exp @@ -5,4 +5,4 @@ error: | ^ 2| type = "file"; - error: negative value given for fetchTree attr owner: -1 + error: negative value given for 'fetchTree' argument 'owner': -1