Skip to content

Commit 8a4f12e

Browse files
authored
Merge pull request #297 from DeterminateSystems/eelcodolstra/fh-1214-make-fetchtree-final
fetchTree: Implicitly set __final = true when a narHash is supplied
2 parents 8edd688 + b378e48 commit 8a4f12e

File tree

7 files changed

+7
-57
lines changed

7 files changed

+7
-57
lines changed

src/libexpr/primops/fetchTree.cc

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ struct FetchTreeParams
7777
bool emptyRevFallback = false;
7878
bool allowNameArgument = false;
7979
bool isFetchGit = false;
80-
bool isFinal = false;
8180
};
8281

8382
static void fetchTree(
@@ -202,12 +201,8 @@ static void fetchTree(
202201

203202
state.checkURI(input.toURLString());
204203

205-
if (params.isFinal) {
204+
if (input.getNarHash())
206205
input.attrs.insert_or_assign("__final", Explicit<bool>(true));
207-
} else {
208-
if (input.isFinal())
209-
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
210-
}
211206

212207
auto cachedInput =
213208
state.inputCache->getAccessor(state.fetchSettings, *state.store, input, fetchers::UseRegistries::No);
@@ -348,18 +343,6 @@ static RegisterPrimOp primop_fetchTree({
348343
.fun = prim_fetchTree,
349344
});
350345

351-
void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value ** args, Value & v)
352-
{
353-
fetchTree(state, pos, args, v, {.isFinal = true});
354-
}
355-
356-
static RegisterPrimOp primop_fetchFinalTree({
357-
.name = "fetchFinalTree",
358-
.args = {"input"},
359-
.fun = prim_fetchFinalTree,
360-
.internal = true,
361-
});
362-
363346
static void fetch(
364347
EvalState & state,
365348
const PosIdx pos,

src/libflake/call-flake.nix

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ lockFileStr:
1010
# unlocked trees.
1111
overrides:
1212

13-
# This is `prim_fetchFinalTree`.
14-
fetchTreeFinal:
15-
1613
let
1714
inherit (builtins) mapAttrs;
1815

@@ -62,7 +59,7 @@ let
6259
else
6360
# FIXME: remove obsolete node.info.
6461
# Note: lock file entries are always final.
65-
fetchTreeFinal (node.info or { } // removeAttrs node.locked [ "dir" ]);
62+
builtins.fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]);
6663

6764
subdir = overrides.${key}.dir or node.locked.dir or "";
6865

src/libflake/flake.cc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,10 +1008,7 @@ void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & vRes)
10081008
auto vLocks = state.allocValue();
10091009
vLocks->mkString(lockFileStr, state.mem);
10101010

1011-
auto vFetchFinalTree = get(state.internalPrimOps, "fetchFinalTree");
1012-
assert(vFetchFinalTree);
1013-
1014-
Value * args[] = {vLocks, &vOverrides, *vFetchFinalTree};
1011+
Value * args[] = {vLocks, &vOverrides};
10151012
state.callFunction(*vCallFlake, args, vRes, noPos);
10161013
}
10171014

src/libflake/include/nix/flake/flake.hh

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,4 @@ void emitTreeAttrs(
246246
bool emptyRevFallback = false,
247247
bool forceDirty = false);
248248

249-
/**
250-
* An internal builtin similar to `fetchTree`, except that it
251-
* always treats the input as final (i.e. no attributes can be
252-
* added/removed/changed).
253-
*/
254-
void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value ** args, Value & v);
255-
256249
} // namespace nix

tests/functional/tarball.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ test_tarball() {
3838

3939
[[ $(nix eval --impure --expr "(fetchTree file://$tarball).lastModified") = 1000000000 ]]
4040

41+
# fetchTree with a narHash is implicitly final, so it doesn't return attributes like lastModified.
42+
[[ $(nix eval --impure --expr "(fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; }) ? lastModified") = false ]]
43+
4144
nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" >&2
4245
nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" 2>&1 | grep 'true'
4346

tests/nixos/fetchers-substitute.nix

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,28 +150,5 @@
150150
content = importer.succeed(f"cat {result_path}/hello.txt").strip()
151151
assert content == "Hello from tarball!", f"Content mismatch: {content}"
152152
print("✓ fetchTarball content verified!")
153-
154-
##########################################
155-
# Test 3: Verify fetchTree does NOT substitute (preserves metadata)
156-
##########################################
157-
158-
print("Testing that fetchTree without __final does NOT use substitution...")
159-
160-
# fetchTree with just narHash (not __final) should try to download, which will fail
161-
# since the file doesn't exist on the importer
162-
exit_code = importer.fail(f"""
163-
nix-instantiate --eval --json --read-write-mode --expr '
164-
builtins.fetchTree {{
165-
type = "tarball";
166-
url = "file:///only-on-substituter.tar.gz";
167-
narHash = "{tarball_hash_sri}";
168-
}}
169-
' 2>&1
170-
""")
171-
172-
# Should fail with "does not exist" since it tries to download instead of substituting
173-
assert "does not exist" in exit_code or "Couldn't open file" in exit_code, f"Expected download failure, got: {exit_code}"
174-
print("✓ fetchTree correctly does NOT substitute non-final inputs!")
175-
print(" (This preserves metadata like lastModified from the actual fetch)")
176153
'';
177154
}

tests/nixos/github-flakes.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ in
266266
267267
# Fetching with an incorrect NAR hash should fail.
268268
out = client.fail(f"nix eval --no-trust-tarballs-from-git-forges --raw --expr '(fetchTree \"github:fancy-enterprise/private-flake/{info['revision']}?narHash=sha256-HsrRFZYg69qaVe/wDyWBYLeS6ca7ACEJg2Z%2BGpEFw4A%3D\").narHash' 2>&1")
269-
assert "NAR hash mismatch in input" in out, "NAR hash check did not fail with the expected error"
269+
assert "mismatch in field 'narHash'" in out, "NAR hash check did not fail with the expected error"
270270
271271
# Fetching without a narHash should succeed if trust-github is set and fail otherwise.
272272
client.succeed(f"nix eval --raw --expr 'builtins.fetchTree github:github:fancy-enterprise/private-flake/{info['revision']}'")

0 commit comments

Comments
 (0)