diff --git a/src/libcmd/installable-value.cc b/src/libcmd/installable-value.cc index c8a3e1b21..1aa2e65c1 100644 --- a/src/libcmd/installable-value.cc +++ b/src/libcmd/installable-value.cc @@ -45,7 +45,7 @@ ref InstallableValue::require(ref installable) std::optional InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx) { if (v.type() == nPath) { - auto storePath = fetchToStore(*state->store, v.path()); + auto storePath = fetchToStore(*state->store, v.path(), FetchMode::Copy); return {{ .path = DerivedPath::Opaque { .path = std::move(storePath), diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6fc9df237..4919ac358 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2339,7 +2339,14 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat auto dstPath = i != srcToStore.end() ? i->second : [&]() { - auto dstPath = fetchToStore(*store, path.resolveSymlinks(), path.baseName(), FileIngestionMethod::Recursive, nullptr, repair); + auto dstPath = fetchToStore( + *store, + path.resolveSymlinks(), + settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, + path.baseName(), + FileIngestionMethod::Recursive, + nullptr, + repair); allowPath(dstPath); srcToStore.insert_or_assign(path, dstPath); printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath)); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 8c6aeffac..89d9704ee 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2228,7 +2228,14 @@ static void addPath( }); if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) { - auto dstPath = fetchToStore(*state.store, path.resolveSymlinks(), name, method, filter.get(), state.repair); + auto dstPath = fetchToStore( + *state.store, + path.resolveSymlinks(), + settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, + name, + method, + filter.get(), + state.repair); if (expectedHash && expectedStorePath != dstPath) state.error( "store path mismatch in (possibly filtered) path added from '%s'", diff --git a/src/libfetchers/fetch-to-store.cc b/src/libfetchers/fetch-to-store.cc index f5c740266..398286065 100644 --- a/src/libfetchers/fetch-to-store.cc +++ b/src/libfetchers/fetch-to-store.cc @@ -7,6 +7,7 @@ namespace nix { StorePath fetchToStore( Store & store, const SourcePath & path, + FetchMode mode, std::string_view name, ContentAddressMethod method, PathFilter * filter, @@ -33,21 +34,19 @@ StorePath fetchToStore( } else debug("source path '%s' is uncacheable", path); - auto readOnly = settings.readOnlyMode; - Activity act(*logger, lvlChatty, actUnknown, - fmt(readOnly ? "hashing '%s'" : "copying '%s' to the store", path)); + fmt(mode == FetchMode::DryRun ? "hashing '%s'" : "copying '%s' to the store", path)); auto filter2 = filter ? *filter : defaultPathFilter; auto storePath = - readOnly + mode == FetchMode::DryRun ? store.computeStorePath( name, *path.accessor, path.path, method, HashAlgorithm::SHA256, {}, filter2).first : store.addToStore( name, *path.accessor, path.path, method, HashAlgorithm::SHA256, {}, filter2, repair); - if (cacheKey) + if (cacheKey && mode == FetchMode::Copy) fetchers::getCache()->add(store, *cacheKey, {}, storePath, true); return storePath; diff --git a/src/libfetchers/fetch-to-store.hh b/src/libfetchers/fetch-to-store.hh index e5e039340..81af1e240 100644 --- a/src/libfetchers/fetch-to-store.hh +++ b/src/libfetchers/fetch-to-store.hh @@ -8,12 +8,15 @@ namespace nix { +enum struct FetchMode { DryRun, Copy }; + /** * Copy the `path` to the Nix store. */ StorePath fetchToStore( Store & store, const SourcePath & path, + FetchMode mode, std::string_view name = "source", ContentAddressMethod method = FileIngestionMethod::Recursive, PathFilter * filter = nullptr, diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 7f282c972..9a534c1e2 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -376,7 +376,7 @@ void InputScheme::clone(const Input & input, const Path & destDir) const std::pair InputScheme::fetch(ref store, const Input & input) { auto [accessor, input2] = getAccessor(store, input); - auto storePath = fetchToStore(*store, SourcePath(accessor), input2.getName()); + auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy, input2.getName()); return {storePath, input2}; } diff --git a/tests/functional/fetchGit.sh b/tests/functional/fetchGit.sh index ea90f8ebe..4e71cfe8c 100644 --- a/tests/functional/fetchGit.sh +++ b/tests/functional/fetchGit.sh @@ -30,7 +30,10 @@ echo hello >> $TEST_ROOT/worktree/hello rev2=$(git -C $repo rev-parse HEAD) git -C $repo tag -a tag2 -m tag2 -# Fetch a worktree +# Check whether fetching in read-only mode works. +nix-instantiate --eval -E "builtins.readFile ((builtins.fetchGit file://$TEST_ROOT/worktree) + \"/hello\") == \"utrecht\\n\"" + +# Fetch a worktree. unset _NIX_FORCE_HTTP path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath") path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath")