1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-14 14:32:42 +01:00

Merge pull request #14550 from roberth/fetchers-settings-arg

Remove setting from Input
This commit is contained in:
John Ericson 2025-11-13 22:59:27 +00:00 committed by GitHub
commit 805496657d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 181 additions and 168 deletions

View file

@ -33,7 +33,8 @@ EvalSettings evalSettings{
// FIXME `parseFlakeRef` should take a `std::string_view`. // FIXME `parseFlakeRef` should take a `std::string_view`.
auto flakeRef = parseFlakeRef(fetchSettings, std::string{rest}, {}, true, false); auto flakeRef = parseFlakeRef(fetchSettings, std::string{rest}, {}, true, false);
debug("fetching flake search path element '%s''", rest); debug("fetching flake search path element '%s''", rest);
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store); auto [accessor, lockedRef] =
flakeRef.resolve(fetchSettings, state.store).lazyFetch(fetchSettings, state.store);
auto storePath = nix::fetchToStore( auto storePath = nix::fetchToStore(
state.fetchSettings, state.fetchSettings,
*state.store, *state.store,
@ -131,7 +132,7 @@ MixEvalArgs::MixEvalArgs()
fetchers::Attrs extraAttrs; fetchers::Attrs extraAttrs;
if (to.subdir != "") if (to.subdir != "")
extraAttrs["dir"] = to.subdir; extraAttrs["dir"] = to.subdir;
fetchers::overrideRegistry(from.input, to.input, extraAttrs); fetchers::overrideRegistry(fetchSettings, from.input, to.input, extraAttrs);
}}, }},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeRef(completions, openStore(), prefix); completeFlakeRef(completions, openStore(), prefix);
@ -187,7 +188,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
else if (hasPrefix(s, "flake:")) { else if (hasPrefix(s, "flake:")) {
experimentalFeatureSettings.require(Xp::Flakes); experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false); auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false);
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store); auto [accessor, lockedRef] = flakeRef.resolve(fetchSettings, state.store).lazyFetch(fetchSettings, state.store);
auto storePath = nix::fetchToStore( auto storePath = nix::fetchToStore(
state.fetchSettings, *state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName()); state.fetchSettings, *state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
state.allowPath(storePath); state.allowPath(storePath);

View file

@ -185,6 +185,7 @@ MixFlakeOptions::MixFlakeOptions()
} }
overrideRegistry( overrideRegistry(
fetchSettings,
fetchers::Input::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", inputName}}), fetchers::Input::fromAttrs(fetchSettings, {{"type", "indirect"}, {"id", inputName}}),
input3->lockedRef.input, input3->lockedRef.input,
extraAttrs); extraAttrs);

View file

@ -738,7 +738,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
} }
auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, cwd.string(), true); auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, cwd.string(), true);
if (evalSettings.pureEval && !flakeRef.input.isLocked()) if (evalSettings.pureEval && !flakeRef.input.isLocked(fetchSettings))
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS); throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
Value v; Value v;

View file

@ -81,7 +81,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value ** ar
attrs.insert_or_assign("rev", rev->gitRev()); attrs.insert_or_assign("rev", rev->gitRev());
auto input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs)); auto input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
auto [storePath, input2] = input.fetchToStore(state.store); auto [storePath, input2] = input.fetchToStore(state.fetchSettings, state.store);
auto attrs2 = state.buildBindings(8); auto attrs2 = state.buildBindings(8);
state.mkStorePathString(storePath, attrs2.alloc(state.s.outPath)); state.mkStorePathString(storePath, attrs2.alloc(state.s.outPath));

View file

@ -82,7 +82,7 @@ struct FetchTreeParams
static void fetchTree( static void fetchTree(
EvalState & state, const PosIdx pos, Value ** args, Value & v, const FetchTreeParams & params = FetchTreeParams{}) EvalState & state, const PosIdx pos, Value ** args, Value & v, const FetchTreeParams & params = FetchTreeParams{})
{ {
fetchers::Input input{state.fetchSettings}; fetchers::Input input{};
NixStringContext context; NixStringContext context;
std::optional<std::string> type; std::optional<std::string> type;
auto fetcher = params.isFetchGit ? "fetchGit" : "fetchTree"; auto fetcher = params.isFetchGit ? "fetchGit" : "fetchTree";
@ -194,9 +194,9 @@ static void fetchTree(
} }
if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes)) if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes))
input = lookupInRegistries(state.store, input, fetchers::UseRegistries::Limited).first; input = lookupInRegistries(state.fetchSettings, state.store, input, fetchers::UseRegistries::Limited).first;
if (state.settings.pureEval && !input.isLocked()) { if (state.settings.pureEval && !input.isLocked(state.fetchSettings)) {
if (input.getNarHash()) if (input.getNarHash())
warn( warn(
"Input '%s' is unlocked (e.g. lacks a Git revision) but is checked by NAR hash. " "Input '%s' is unlocked (e.g. lacks a Git revision) but is checked by NAR hash. "
@ -219,7 +219,8 @@ static void fetchTree(
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string()); throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
} }
auto cachedInput = state.inputCache->getAccessor(state.store, input, fetchers::UseRegistries::No); auto cachedInput =
state.inputCache->getAccessor(state.fetchSettings, state.store, input, fetchers::UseRegistries::No);
auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor); auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor);

View file

@ -196,7 +196,7 @@ TEST_F(GitTest, submodulePeriodSupport)
{"ref", "main"}, {"ref", "main"},
}); });
auto [accessor, i] = input.getAccessor(store); auto [accessor, i] = input.getAccessor(settings, store);
ASSERT_EQ(accessor->readFile(CanonPath("deps/sub/lib.txt")), "hello from submodule\n"); ASSERT_EQ(accessor->readFile(CanonPath("deps/sub/lib.txt")), "hello from submodule\n");
} }

View file

@ -89,7 +89,7 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs)
// but not all of them. Doing this is to support those other // but not all of them. Doing this is to support those other
// operations which are supposed to be robust on // operations which are supposed to be robust on
// unknown/uninterpretable inputs. // unknown/uninterpretable inputs.
Input input{settings}; Input input;
input.attrs = attrs; input.attrs = attrs;
fixupInput(input); fixupInput(input);
return input; return input;
@ -159,9 +159,9 @@ bool Input::isDirect() const
return !scheme || scheme->isDirect(*this); return !scheme || scheme->isDirect(*this);
} }
bool Input::isLocked() const bool Input::isLocked(const Settings & settings) const
{ {
return scheme && scheme->isLocked(*this); return scheme && scheme->isLocked(settings, *this);
} }
bool Input::isFinal() const bool Input::isFinal() const
@ -198,17 +198,17 @@ bool Input::contains(const Input & other) const
} }
// FIXME: remove // FIXME: remove
std::pair<StorePath, Input> Input::fetchToStore(ref<Store> store) const std::pair<StorePath, Input> Input::fetchToStore(const Settings & settings, ref<Store> store) const
{ {
if (!scheme) if (!scheme)
throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs())); throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs()));
auto [storePath, input] = [&]() -> std::pair<StorePath, Input> { auto [storePath, input] = [&]() -> std::pair<StorePath, Input> {
try { try {
auto [accessor, result] = getAccessorUnchecked(store); auto [accessor, result] = getAccessorUnchecked(settings, store);
auto storePath = auto storePath =
nix::fetchToStore(*settings, *store, SourcePath(accessor), FetchMode::Copy, result.getName()); nix::fetchToStore(settings, *store, SourcePath(accessor), FetchMode::Copy, result.getName());
auto narHash = store->queryPathInfo(storePath)->narHash; auto narHash = store->queryPathInfo(storePath)->narHash;
result.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); result.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
@ -297,10 +297,10 @@ void Input::checkLocks(Input specified, Input & result)
} }
} }
std::pair<ref<SourceAccessor>, Input> Input::getAccessor(ref<Store> store) const std::pair<ref<SourceAccessor>, Input> Input::getAccessor(const Settings & settings, ref<Store> store) const
{ {
try { try {
auto [accessor, result] = getAccessorUnchecked(store); auto [accessor, result] = getAccessorUnchecked(settings, store);
result.attrs.insert_or_assign("__final", Explicit<bool>(true)); result.attrs.insert_or_assign("__final", Explicit<bool>(true));
@ -313,7 +313,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessor(ref<Store> store) const
} }
} }
std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> store) const std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(const Settings & settings, ref<Store> store) const
{ {
// FIXME: cache the accessor // FIXME: cache the accessor
@ -349,7 +349,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
if (accessor->fingerprint) { if (accessor->fingerprint) {
ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive; ContentAddressMethod method = ContentAddressMethod::Raw::NixArchive;
auto cacheKey = makeFetchToStoreCacheKey(getName(), *accessor->fingerprint, method, "/"); auto cacheKey = makeFetchToStoreCacheKey(getName(), *accessor->fingerprint, method, "/");
settings->getCache()->upsert(cacheKey, *store, {}, storePath); settings.getCache()->upsert(cacheKey, *store, {}, storePath);
} }
accessor->setPathDisplay("«" + to_string() + "»"); accessor->setPathDisplay("«" + to_string() + "»");
@ -360,7 +360,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(ref<Store> sto
} }
} }
auto [accessor, result] = scheme->getAccessor(store, *this); auto [accessor, result] = scheme->getAccessor(settings, store, *this);
if (!accessor->fingerprint) if (!accessor->fingerprint)
accessor->fingerprint = result.getFingerprint(store); accessor->fingerprint = result.getFingerprint(store);
@ -377,10 +377,10 @@ Input Input::applyOverrides(std::optional<std::string> ref, std::optional<Hash>
return scheme->applyOverrides(*this, ref, rev); return scheme->applyOverrides(*this, ref, rev);
} }
void Input::clone(const Path & destDir) const void Input::clone(const Settings & settings, const Path & destDir) const
{ {
assert(scheme); assert(scheme);
scheme->clone(*this, destDir); scheme->clone(settings, *this, destDir);
} }
std::optional<std::filesystem::path> Input::getSourcePath() const std::optional<std::filesystem::path> Input::getSourcePath() const
@ -493,7 +493,7 @@ void InputScheme::putFile(
throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path); throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
} }
void InputScheme::clone(const Input & input, const Path & destDir) const void InputScheme::clone(const Settings & settings, const Input & input, const Path & destDir) const
{ {
throw Error("do not know how to clone input '%s'", input.to_string()); throw Error("do not know how to clone input '%s'", input.to_string());
} }

View file

@ -229,7 +229,7 @@ struct GitInputScheme : InputScheme
if (auto ref = maybeGetStrAttr(attrs, "ref"); ref && !isLegalRefName(*ref)) if (auto ref = maybeGetStrAttr(attrs, "ref"); ref && !isLegalRefName(*ref))
throw BadURL("invalid Git branch/tag name '%s'", *ref); throw BadURL("invalid Git branch/tag name '%s'", *ref);
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
input.attrs["url"] = fixGitURL(getStrAttr(attrs, "url")).to_string(); input.attrs["url"] = fixGitURL(getStrAttr(attrs, "url")).to_string();
getShallowAttr(input); getShallowAttr(input);
@ -278,7 +278,7 @@ struct GitInputScheme : InputScheme
return res; return res;
} }
void clone(const Input & input, const Path & destDir) const override void clone(const Settings & settings, const Input & input, const Path & destDir) const override
{ {
auto repoInfo = getRepoInfo(input); auto repoInfo = getRepoInfo(input);
@ -623,7 +623,7 @@ struct GitInputScheme : InputScheme
} }
std::pair<ref<SourceAccessor>, Input> std::pair<ref<SourceAccessor>, Input>
getAccessorFromCommit(ref<Store> store, RepoInfo & repoInfo, Input && input) const getAccessorFromCommit(const Settings & settings, ref<Store> store, RepoInfo & repoInfo, Input && input) const
{ {
assert(!repoInfo.workdirInfo.isDirty); assert(!repoInfo.workdirInfo.isDirty);
@ -733,10 +733,10 @@ struct GitInputScheme : InputScheme
auto rev = *input.getRev(); auto rev = *input.getRev();
input.attrs.insert_or_assign("lastModified", getLastModified(*input.settings, repoInfo, repoDir, rev)); input.attrs.insert_or_assign("lastModified", getLastModified(settings, repoInfo, repoDir, rev));
if (!getShallowAttr(input)) if (!getShallowAttr(input))
input.attrs.insert_or_assign("revCount", getRevCount(*input.settings, repoInfo, repoDir, rev)); input.attrs.insert_or_assign("revCount", getRevCount(settings, repoInfo, repoDir, rev));
printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.locationToArg()); printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.locationToArg());
@ -779,8 +779,8 @@ struct GitInputScheme : InputScheme
attrs.insert_or_assign("submodules", Explicit<bool>{true}); attrs.insert_or_assign("submodules", Explicit<bool>{true});
attrs.insert_or_assign("lfs", Explicit<bool>{smudgeLfs}); attrs.insert_or_assign("lfs", Explicit<bool>{smudgeLfs});
attrs.insert_or_assign("allRefs", Explicit<bool>{true}); attrs.insert_or_assign("allRefs", Explicit<bool>{true});
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs)); auto submoduleInput = fetchers::Input::fromAttrs(settings, std::move(attrs));
auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(store); auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(settings, store);
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»"); submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
mounts.insert_or_assign(submodule.path, submoduleAccessor); mounts.insert_or_assign(submodule.path, submoduleAccessor);
} }
@ -797,7 +797,7 @@ struct GitInputScheme : InputScheme
} }
std::pair<ref<SourceAccessor>, Input> std::pair<ref<SourceAccessor>, Input>
getAccessorFromWorkdir(ref<Store> store, RepoInfo & repoInfo, Input && input) const getAccessorFromWorkdir(const Settings & settings, ref<Store> store, RepoInfo & repoInfo, Input && input) const
{ {
auto repoPath = repoInfo.getPath().value(); auto repoPath = repoInfo.getPath().value();
@ -829,8 +829,8 @@ struct GitInputScheme : InputScheme
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out // TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
// attrs.insert_or_assign("allRefs", Explicit<bool>{ true }); // attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs)); auto submoduleInput = fetchers::Input::fromAttrs(settings, std::move(attrs));
auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(store); auto [submoduleAccessor, submoduleInput2] = submoduleInput.getAccessor(settings, store);
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»"); submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
/* If the submodule is dirty, mark this repo dirty as /* If the submodule is dirty, mark this repo dirty as
@ -857,12 +857,12 @@ struct GitInputScheme : InputScheme
input.attrs.insert_or_assign("rev", rev.gitRev()); input.attrs.insert_or_assign("rev", rev.gitRev());
if (!getShallowAttr(input)) { if (!getShallowAttr(input)) {
input.attrs.insert_or_assign( input.attrs.insert_or_assign(
"revCount", rev == nullRev ? 0 : getRevCount(*input.settings, repoInfo, repoPath, rev)); "revCount", rev == nullRev ? 0 : getRevCount(settings, repoInfo, repoPath, rev));
} }
verifyCommit(input, repo); verifyCommit(input, repo);
} else { } else {
repoInfo.warnDirty(*input.settings); repoInfo.warnDirty(settings);
if (repoInfo.workdirInfo.headRev) { if (repoInfo.workdirInfo.headRev) {
input.attrs.insert_or_assign("dirtyRev", repoInfo.workdirInfo.headRev->gitRev() + "-dirty"); input.attrs.insert_or_assign("dirtyRev", repoInfo.workdirInfo.headRev->gitRev() + "-dirty");
@ -874,14 +874,14 @@ struct GitInputScheme : InputScheme
input.attrs.insert_or_assign( input.attrs.insert_or_assign(
"lastModified", "lastModified",
repoInfo.workdirInfo.headRev repoInfo.workdirInfo.headRev ? getLastModified(settings, repoInfo, repoPath, *repoInfo.workdirInfo.headRev)
? getLastModified(*input.settings, repoInfo, repoPath, *repoInfo.workdirInfo.headRev) : 0);
: 0);
return {accessor, std::move(input)}; return {accessor, std::move(input)};
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);
@ -897,8 +897,8 @@ struct GitInputScheme : InputScheme
} }
auto [accessor, final] = input.getRef() || input.getRev() || !repoInfo.getPath() auto [accessor, final] = input.getRef() || input.getRev() || !repoInfo.getPath()
? getAccessorFromCommit(store, repoInfo, std::move(input)) ? getAccessorFromCommit(settings, store, repoInfo, std::move(input))
: getAccessorFromWorkdir(store, repoInfo, std::move(input)); : getAccessorFromWorkdir(settings, store, repoInfo, std::move(input));
return {accessor, std::move(final)}; return {accessor, std::move(final)};
} }
@ -934,7 +934,7 @@ struct GitInputScheme : InputScheme
} }
} }
bool isLocked(const Input & input) const override bool isLocked(const Settings & settings, const Input & input) const override
{ {
auto rev = input.getRev(); auto rev = input.getRev();
return rev && rev != nullRev; return rev && rev != nullRev;

View file

@ -92,7 +92,7 @@ struct GitArchiveInputScheme : InputScheme
if (ref && rev) if (ref && rev)
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url, *ref, rev->gitRev()); throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url, *ref, rev->gitRev());
Input input{settings}; Input input{};
input.attrs.insert_or_assign("type", std::string{schemeName()}); input.attrs.insert_or_assign("type", std::string{schemeName()});
input.attrs.insert_or_assign("owner", path[0]); input.attrs.insert_or_assign("owner", path[0]);
input.attrs.insert_or_assign("repo", path[1]); input.attrs.insert_or_assign("repo", path[1]);
@ -129,7 +129,7 @@ struct GitArchiveInputScheme : InputScheme
getStrAttr(attrs, "owner"); getStrAttr(attrs, "owner");
getStrAttr(attrs, "repo"); getStrAttr(attrs, "repo");
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
return input; return input;
} }
@ -233,9 +233,9 @@ struct GitArchiveInputScheme : InputScheme
std::optional<Hash> treeHash; std::optional<Hash> treeHash;
}; };
virtual RefInfo getRevFromRef(nix::ref<Store> store, const Input & input) const = 0; virtual RefInfo getRevFromRef(const Settings & settings, nix::ref<Store> store, const Input & input) const = 0;
virtual DownloadUrl getDownloadUrl(const Input & input) const = 0; virtual DownloadUrl getDownloadUrl(const Settings & settings, const Input & input) const = 0;
struct TarballInfo struct TarballInfo
{ {
@ -243,7 +243,7 @@ struct GitArchiveInputScheme : InputScheme
time_t lastModified; time_t lastModified;
}; };
std::pair<Input, TarballInfo> downloadArchive(ref<Store> store, Input input) const std::pair<Input, TarballInfo> downloadArchive(const Settings & settings, ref<Store> store, Input input) const
{ {
if (!maybeGetStrAttr(input.attrs, "ref")) if (!maybeGetStrAttr(input.attrs, "ref"))
input.attrs.insert_or_assign("ref", "HEAD"); input.attrs.insert_or_assign("ref", "HEAD");
@ -252,7 +252,7 @@ struct GitArchiveInputScheme : InputScheme
auto rev = input.getRev(); auto rev = input.getRev();
if (!rev) { if (!rev) {
auto refInfo = getRevFromRef(store, input); auto refInfo = getRevFromRef(settings, store, input);
rev = refInfo.rev; rev = refInfo.rev;
upstreamTreeHash = refInfo.treeHash; upstreamTreeHash = refInfo.treeHash;
debug("HEAD revision for '%s' is %s", input.to_string(), refInfo.rev.gitRev()); debug("HEAD revision for '%s' is %s", input.to_string(), refInfo.rev.gitRev());
@ -261,7 +261,7 @@ struct GitArchiveInputScheme : InputScheme
input.attrs.erase("ref"); input.attrs.erase("ref");
input.attrs.insert_or_assign("rev", rev->gitRev()); input.attrs.insert_or_assign("rev", rev->gitRev());
auto cache = input.settings->getCache(); auto cache = settings.getCache();
Cache::Key treeHashKey{"gitRevToTreeHash", {{"rev", rev->gitRev()}}}; Cache::Key treeHashKey{"gitRevToTreeHash", {{"rev", rev->gitRev()}}};
Cache::Key lastModifiedKey{"gitRevToLastModified", {{"rev", rev->gitRev()}}}; Cache::Key lastModifiedKey{"gitRevToLastModified", {{"rev", rev->gitRev()}}};
@ -270,7 +270,7 @@ struct GitArchiveInputScheme : InputScheme
if (auto lastModifiedAttrs = cache->lookup(lastModifiedKey)) { if (auto lastModifiedAttrs = cache->lookup(lastModifiedKey)) {
auto treeHash = getRevAttr(*treeHashAttrs, "treeHash"); auto treeHash = getRevAttr(*treeHashAttrs, "treeHash");
auto lastModified = getIntAttr(*lastModifiedAttrs, "lastModified"); auto lastModified = getIntAttr(*lastModifiedAttrs, "lastModified");
if (input.settings->getTarballCache()->hasObject(treeHash)) if (settings.getTarballCache()->hasObject(treeHash))
return {std::move(input), TarballInfo{.treeHash = treeHash, .lastModified = (time_t) lastModified}}; return {std::move(input), TarballInfo{.treeHash = treeHash, .lastModified = (time_t) lastModified}};
else else
debug("Git tree with hash '%s' has disappeared from the cache, refetching...", treeHash.gitRev()); debug("Git tree with hash '%s' has disappeared from the cache, refetching...", treeHash.gitRev());
@ -278,7 +278,7 @@ struct GitArchiveInputScheme : InputScheme
} }
/* Stream the tarball into the tarball cache. */ /* Stream the tarball into the tarball cache. */
auto url = getDownloadUrl(input); auto url = getDownloadUrl(settings, input);
auto source = sinkToSource([&](Sink & sink) { auto source = sinkToSource([&](Sink & sink) {
FileTransferRequest req(url.url); FileTransferRequest req(url.url);
@ -290,7 +290,7 @@ struct GitArchiveInputScheme : InputScheme
*logger, lvlInfo, actUnknown, fmt("unpacking '%s' into the Git cache", input.to_string())); *logger, lvlInfo, actUnknown, fmt("unpacking '%s' into the Git cache", input.to_string()));
TarArchive archive{*source}; TarArchive archive{*source};
auto tarballCache = input.settings->getTarballCache(); auto tarballCache = settings.getTarballCache();
auto parseSink = tarballCache->getFileSystemObjectSink(); auto parseSink = tarballCache->getFileSystemObjectSink();
auto lastModified = unpackTarfileToSink(archive, *parseSink); auto lastModified = unpackTarfileToSink(archive, *parseSink);
auto tree = parseSink->flush(); auto tree = parseSink->flush();
@ -315,9 +315,10 @@ struct GitArchiveInputScheme : InputScheme
return {std::move(input), tarballInfo}; return {std::move(input), tarballInfo};
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
auto [input, tarballInfo] = downloadArchive(store, _input); auto [input, tarballInfo] = downloadArchive(settings, store, _input);
#if 0 #if 0
input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev()); input.attrs.insert_or_assign("treeHash", tarballInfo.treeHash.gitRev());
@ -325,19 +326,18 @@ struct GitArchiveInputScheme : InputScheme
input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified)); input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified));
auto accessor = auto accessor =
input.settings->getTarballCache()->getAccessor(tarballInfo.treeHash, false, "«" + input.to_string() + "»"); settings.getTarballCache()->getAccessor(tarballInfo.treeHash, false, "«" + input.to_string() + "»");
return {accessor, input}; return {accessor, input};
} }
bool isLocked(const Input & input) const override bool isLocked(const Settings & settings, const Input & input) const override
{ {
/* Since we can't verify the integrity of the tarball from the /* Since we can't verify the integrity of the tarball from the
Git revision alone, we also require a NAR hash for Git revision alone, we also require a NAR hash for
locking. FIXME: in the future, we may want to require a Git locking. FIXME: in the future, we may want to require a Git
tree hash instead of a NAR hash. */ tree hash instead of a NAR hash. */
return input.getRev().has_value() return input.getRev().has_value() && (settings.trustTarballsFromGitForges || input.getNarHash().has_value());
&& (input.settings->trustTarballsFromGitForges || input.getNarHash().has_value());
} }
std::optional<ExperimentalFeature> experimentalFeature() const override std::optional<ExperimentalFeature> experimentalFeature() const override
@ -387,7 +387,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
return getStrAttr(input.attrs, "repo"); return getStrAttr(input.attrs, "repo");
} }
RefInfo getRevFromRef(nix::ref<Store> store, const Input & input) const override RefInfo getRevFromRef(const Settings & settings, nix::ref<Store> store, const Input & input) const override
{ {
auto host = getHost(input); auto host = getHost(input);
auto url = fmt( auto url = fmt(
@ -397,9 +397,9 @@ struct GitHubInputScheme : GitArchiveInputScheme
getRepo(input), getRepo(input),
*input.getRef()); *input.getRef());
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
auto downloadResult = downloadFile(store, *input.settings, url, "source", headers); auto downloadResult = downloadFile(store, settings, url, "source", headers);
auto json = nlohmann::json::parse( auto json = nlohmann::json::parse(
store->requireStoreObjectAccessor(downloadResult.storePath)->readFile(CanonPath::root)); store->requireStoreObjectAccessor(downloadResult.storePath)->readFile(CanonPath::root));
@ -408,11 +408,11 @@ struct GitHubInputScheme : GitArchiveInputScheme
.treeHash = Hash::parseAny(std::string{json["commit"]["tree"]["sha"]}, HashAlgorithm::SHA1)}; .treeHash = Hash::parseAny(std::string{json["commit"]["tree"]["sha"]}, HashAlgorithm::SHA1)};
} }
DownloadUrl getDownloadUrl(const Input & input) const override DownloadUrl getDownloadUrl(const Settings & settings, const Input & input) const override
{ {
auto host = getHost(input); auto host = getHost(input);
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
// If we have no auth headers then we default to the public archive // If we have no auth headers then we default to the public archive
// urls so we do not run into rate limits. // urls so we do not run into rate limits.
@ -426,12 +426,12 @@ struct GitHubInputScheme : GitArchiveInputScheme
return DownloadUrl{parseURL(url), headers}; return DownloadUrl{parseURL(url), headers};
} }
void clone(const Input & input, const Path & destDir) const override void clone(const Settings & settings, const Input & input, const Path & destDir) const override
{ {
auto host = getHost(input); auto host = getHost(input);
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input))) Input::fromURL(settings, fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input)))
.applyOverrides(input.getRef(), input.getRev()) .applyOverrides(input.getRef(), input.getRev())
.clone(destDir); .clone(settings, destDir);
} }
}; };
@ -461,7 +461,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
return std::make_pair(token.substr(0, fldsplit), token.substr(fldsplit + 1)); return std::make_pair(token.substr(0, fldsplit), token.substr(fldsplit + 1));
} }
RefInfo getRevFromRef(nix::ref<Store> store, const Input & input) const override RefInfo getRevFromRef(const Settings & settings, nix::ref<Store> store, const Input & input) const override
{ {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
// See rate limiting note below // See rate limiting note below
@ -472,9 +472,9 @@ struct GitLabInputScheme : GitArchiveInputScheme
getStrAttr(input.attrs, "repo"), getStrAttr(input.attrs, "repo"),
*input.getRef()); *input.getRef());
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
auto downloadResult = downloadFile(store, *input.settings, url, "source", headers); auto downloadResult = downloadFile(store, settings, url, "source", headers);
auto json = nlohmann::json::parse( auto json = nlohmann::json::parse(
store->requireStoreObjectAccessor(downloadResult.storePath)->readFile(CanonPath::root)); store->requireStoreObjectAccessor(downloadResult.storePath)->readFile(CanonPath::root));
@ -488,7 +488,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
} }
} }
DownloadUrl getDownloadUrl(const Input & input) const override DownloadUrl getDownloadUrl(const Settings & settings, const Input & input) const override
{ {
// This endpoint has a rate limit threshold that may be // This endpoint has a rate limit threshold that may be
// server-specific and vary based whether the user is // server-specific and vary based whether the user is
@ -503,19 +503,19 @@ struct GitLabInputScheme : GitArchiveInputScheme
getStrAttr(input.attrs, "repo"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(HashFormat::Base16, false)); input.getRev()->to_string(HashFormat::Base16, false));
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
return DownloadUrl{parseURL(url), headers}; return DownloadUrl{parseURL(url), headers};
} }
void clone(const Input & input, const Path & destDir) const override void clone(const Settings & settings, const Input & input, const Path & destDir) const override
{ {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
// FIXME: get username somewhere // FIXME: get username somewhere
Input::fromURL( Input::fromURL(
*input.settings, settings,
fmt("git+https://%s/%s/%s.git", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) fmt("git+https://%s/%s/%s.git", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
.applyOverrides(input.getRef(), input.getRev()) .applyOverrides(input.getRef(), input.getRev())
.clone(destDir); .clone(settings, destDir);
} }
}; };
@ -536,7 +536,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
// Once it is implemented, however, should work as expected. // Once it is implemented, however, should work as expected.
} }
RefInfo getRevFromRef(nix::ref<Store> store, const Input & input) const override RefInfo getRevFromRef(const Settings & settings, nix::ref<Store> store, const Input & input) const override
{ {
// TODO: In the future, when the sourcehut graphql API is implemented for mercurial // TODO: In the future, when the sourcehut graphql API is implemented for mercurial
// and with anonymous access, this method should use it instead. // and with anonymous access, this method should use it instead.
@ -547,11 +547,11 @@ struct SourceHutInputScheme : GitArchiveInputScheme
auto base_url = auto base_url =
fmt("https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")); fmt("https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
std::string refUri; std::string refUri;
if (ref == "HEAD") { if (ref == "HEAD") {
auto downloadFileResult = downloadFile(store, *input.settings, fmt("%s/HEAD", base_url), "source", headers); auto downloadFileResult = downloadFile(store, settings, fmt("%s/HEAD", base_url), "source", headers);
auto contents = store->requireStoreObjectAccessor(downloadFileResult.storePath)->readFile(CanonPath::root); auto contents = store->requireStoreObjectAccessor(downloadFileResult.storePath)->readFile(CanonPath::root);
auto remoteLine = git::parseLsRemoteLine(getLine(contents).first); auto remoteLine = git::parseLsRemoteLine(getLine(contents).first);
@ -564,8 +564,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
} }
std::regex refRegex(refUri); std::regex refRegex(refUri);
auto downloadFileResult = auto downloadFileResult = downloadFile(store, settings, fmt("%s/info/refs", base_url), "source", headers);
downloadFile(store, *input.settings, fmt("%s/info/refs", base_url), "source", headers);
auto contents = store->requireStoreObjectAccessor(downloadFileResult.storePath)->readFile(CanonPath::root); auto contents = store->requireStoreObjectAccessor(downloadFileResult.storePath)->readFile(CanonPath::root);
std::istringstream is(contents); std::istringstream is(contents);
@ -583,7 +582,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
return RefInfo{.rev = Hash::parseAny(*id, HashAlgorithm::SHA1)}; return RefInfo{.rev = Hash::parseAny(*id, HashAlgorithm::SHA1)};
} }
DownloadUrl getDownloadUrl(const Input & input) const override DownloadUrl getDownloadUrl(const Settings & settings, const Input & input) const override
{ {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
auto url = auto url =
@ -593,18 +592,18 @@ struct SourceHutInputScheme : GitArchiveInputScheme
getStrAttr(input.attrs, "repo"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(HashFormat::Base16, false)); input.getRev()->to_string(HashFormat::Base16, false));
Headers headers = makeHeadersWithAuthTokens(*input.settings, host, input); Headers headers = makeHeadersWithAuthTokens(settings, host, input);
return DownloadUrl{parseURL(url), headers}; return DownloadUrl{parseURL(url), headers};
} }
void clone(const Input & input, const Path & destDir) const override void clone(const Settings & settings, const Input & input, const Path & destDir) const override
{ {
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht"); auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
Input::fromURL( Input::fromURL(
*input.settings, settings,
fmt("git+https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"))) fmt("git+https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
.applyOverrides(input.getRef(), input.getRev()) .applyOverrides(input.getRef(), input.getRev())
.clone(destDir); .clone(settings, destDir);
} }
}; };

View file

@ -36,13 +36,6 @@ struct Input
{ {
friend struct InputScheme; friend struct InputScheme;
const Settings * settings;
Input(const Settings & settings)
: settings{&settings}
{
}
std::shared_ptr<InputScheme> scheme; // note: can be null std::shared_ptr<InputScheme> scheme; // note: can be null
Attrs attrs; Attrs attrs;
@ -87,7 +80,7 @@ public:
* attributes like a Git revision or NAR hash that uniquely * attributes like a Git revision or NAR hash that uniquely
* identify its contents. * identify its contents.
*/ */
bool isLocked() const; bool isLocked(const Settings & settings) const;
/** /**
* Only for relative path flakes, i.e. 'path:./foo', returns the * Only for relative path flakes, i.e. 'path:./foo', returns the
@ -120,7 +113,7 @@ public:
* Fetch the entire input into the Nix store, returning the * Fetch the entire input into the Nix store, returning the
* location in the Nix store and the locked input. * location in the Nix store and the locked input.
*/ */
std::pair<StorePath, Input> fetchToStore(ref<Store> store) const; std::pair<StorePath, Input> fetchToStore(const Settings & settings, ref<Store> store) const;
/** /**
* Check the locking attributes in `result` against * Check the locking attributes in `result` against
@ -140,17 +133,17 @@ public:
* input without copying it to the store. Also return a possibly * input without copying it to the store. Also return a possibly
* unlocked input. * unlocked input.
*/ */
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store) const; std::pair<ref<SourceAccessor>, Input> getAccessor(const Settings & settings, ref<Store> store) const;
private: private:
std::pair<ref<SourceAccessor>, Input> getAccessorUnchecked(ref<Store> store) const; std::pair<ref<SourceAccessor>, Input> getAccessorUnchecked(const Settings & settings, ref<Store> store) const;
public: public:
Input applyOverrides(std::optional<std::string> ref, std::optional<Hash> rev) const; Input applyOverrides(std::optional<std::string> ref, std::optional<Hash> rev) const;
void clone(const Path & destDir) const; void clone(const Settings & settings, const Path & destDir) const;
std::optional<std::filesystem::path> getSourcePath() const; std::optional<std::filesystem::path> getSourcePath() const;
@ -223,7 +216,7 @@ struct InputScheme
virtual Input applyOverrides(const Input & input, std::optional<std::string> ref, std::optional<Hash> rev) const; virtual Input applyOverrides(const Input & input, std::optional<std::string> ref, std::optional<Hash> rev) const;
virtual void clone(const Input & input, const Path & destDir) const; virtual void clone(const Settings & settings, const Input & input, const Path & destDir) const;
virtual std::optional<std::filesystem::path> getSourcePath(const Input & input) const; virtual std::optional<std::filesystem::path> getSourcePath(const Input & input) const;
@ -233,7 +226,8 @@ struct InputScheme
std::string_view contents, std::string_view contents,
std::optional<std::string> commitMsg) const; std::optional<std::string> commitMsg) const;
virtual std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const = 0; virtual std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & input) const = 0;
/** /**
* Is this `InputScheme` part of an experimental feature? * Is this `InputScheme` part of an experimental feature?
@ -250,7 +244,7 @@ struct InputScheme
return std::nullopt; return std::nullopt;
} }
virtual bool isLocked(const Input & input) const virtual bool isLocked(const Settings & settings, const Input & input) const
{ {
return false; return false;
} }

View file

@ -3,6 +3,7 @@
namespace nix::fetchers { namespace nix::fetchers {
enum class UseRegistries : int; enum class UseRegistries : int;
struct Settings;
struct InputCache struct InputCache
{ {
@ -14,7 +15,8 @@ struct InputCache
Attrs extraAttrs; Attrs extraAttrs;
}; };
CachedResult getAccessor(ref<Store> store, const Input & originalInput, UseRegistries useRegistries); CachedResult
getAccessor(const Settings & settings, ref<Store> store, const Input & originalInput, UseRegistries useRegistries);
struct CachedInput struct CachedInput
{ {

View file

@ -59,7 +59,7 @@ Path getUserRegistryPath();
Registries getRegistries(const Settings & settings, ref<Store> store); Registries getRegistries(const Settings & settings, ref<Store> store);
void overrideRegistry(const Input & from, const Input & to, const Attrs & extraAttrs); void overrideRegistry(const Settings & settings, const Input & from, const Input & to, const Attrs & extraAttrs);
enum class UseRegistries : int { enum class UseRegistries : int {
No, No,
@ -71,6 +71,7 @@ enum class UseRegistries : int {
* Rewrite a flakeref using the registries. If `filter` is set, only * Rewrite a flakeref using the registries. If `filter` is set, only
* use the registries for which the filter function returns true. * use the registries for which the filter function returns true.
*/ */
std::pair<Input, Attrs> lookupInRegistries(ref<Store> store, const Input & input, UseRegistries useRegistries); std::pair<Input, Attrs>
lookupInRegistries(const Settings & settings, ref<Store> store, const Input & input, UseRegistries useRegistries);
} // namespace nix::fetchers } // namespace nix::fetchers

View file

@ -44,7 +44,7 @@ struct IndirectInputScheme : InputScheme
// FIXME: forbid query params? // FIXME: forbid query params?
Input input{settings}; Input input{};
input.attrs.insert_or_assign("type", "indirect"); input.attrs.insert_or_assign("type", "indirect");
input.attrs.insert_or_assign("id", id); input.attrs.insert_or_assign("id", id);
if (rev) if (rev)
@ -76,7 +76,7 @@ struct IndirectInputScheme : InputScheme
if (!std::regex_match(id, flakeRegex)) if (!std::regex_match(id, flakeRegex))
throw BadURL("'%s' is not a valid flake ID", id); throw BadURL("'%s' is not a valid flake ID", id);
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
return input; return input;
} }
@ -106,7 +106,8 @@ struct IndirectInputScheme : InputScheme
return input; return input;
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & input) const override
{ {
throw Error("indirect input '%s' cannot be fetched directly", input.to_string()); throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
} }

View file

@ -5,23 +5,23 @@
namespace nix::fetchers { namespace nix::fetchers {
InputCache::CachedResult InputCache::CachedResult InputCache::getAccessor(
InputCache::getAccessor(ref<Store> store, const Input & originalInput, UseRegistries useRegistries) const Settings & settings, ref<Store> store, const Input & originalInput, UseRegistries useRegistries)
{ {
auto fetched = lookup(originalInput); auto fetched = lookup(originalInput);
Input resolvedInput = originalInput; Input resolvedInput = originalInput;
if (!fetched) { if (!fetched) {
if (originalInput.isDirect()) { if (originalInput.isDirect()) {
auto [accessor, lockedInput] = originalInput.getAccessor(store); auto [accessor, lockedInput] = originalInput.getAccessor(settings, store);
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor}); fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
} else { } else {
if (useRegistries != UseRegistries::No) { if (useRegistries != UseRegistries::No) {
auto [res, extraAttrs] = lookupInRegistries(store, originalInput, useRegistries); auto [res, extraAttrs] = lookupInRegistries(settings, store, originalInput, useRegistries);
resolvedInput = std::move(res); resolvedInput = std::move(res);
fetched = lookup(resolvedInput); fetched = lookup(resolvedInput);
if (!fetched) { if (!fetched) {
auto [accessor, lockedInput] = resolvedInput.getAccessor(store); auto [accessor, lockedInput] = resolvedInput.getAccessor(settings, store);
fetched.emplace( fetched.emplace(
CachedInput{.lockedInput = lockedInput, .accessor = accessor, .extraAttrs = extraAttrs}); CachedInput{.lockedInput = lockedInput, .accessor = accessor, .extraAttrs = extraAttrs});
} }

View file

@ -89,7 +89,7 @@ struct MercurialInputScheme : InputScheme
throw BadURL("invalid Mercurial branch/tag name '%s'", *ref); throw BadURL("invalid Mercurial branch/tag name '%s'", *ref);
} }
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
return input; return input;
} }
@ -154,7 +154,7 @@ struct MercurialInputScheme : InputScheme
return {isLocal, isLocal ? renderUrlPathEnsureLegal(url.path) : url.to_string()}; return {isLocal, isLocal ? renderUrlPathEnsureLegal(url.path) : url.to_string()};
} }
StorePath fetchToStore(ref<Store> store, Input & input) const StorePath fetchToStore(const Settings & settings, ref<Store> store, Input & input) const
{ {
auto origRev = input.getRev(); auto origRev = input.getRev();
@ -176,10 +176,10 @@ struct MercurialInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked /* This is an unclean working tree. So copy all tracked
files. */ files. */
if (!input.settings->allowDirty) if (!settings.allowDirty)
throw Error("Mercurial tree '%s' is unclean", actualUrl); throw Error("Mercurial tree '%s' is unclean", actualUrl);
if (input.settings->warnDirty) if (settings.warnDirty)
warn("Mercurial tree '%s' is unclean", actualUrl); warn("Mercurial tree '%s' is unclean", actualUrl);
input.attrs.insert_or_assign("ref", chomp(runHg({"branch", "-R", actualUrl}))); input.attrs.insert_or_assign("ref", chomp(runHg({"branch", "-R", actualUrl})));
@ -240,13 +240,13 @@ struct MercurialInputScheme : InputScheme
Cache::Key refToRevKey{"hgRefToRev", {{"url", actualUrl}, {"ref", *input.getRef()}}}; Cache::Key refToRevKey{"hgRefToRev", {{"url", actualUrl}, {"ref", *input.getRef()}}};
if (!input.getRev()) { if (!input.getRev()) {
if (auto res = input.settings->getCache()->lookupWithTTL(refToRevKey)) if (auto res = settings.getCache()->lookupWithTTL(refToRevKey))
input.attrs.insert_or_assign("rev", getRevAttr(*res, "rev").gitRev()); input.attrs.insert_or_assign("rev", getRevAttr(*res, "rev").gitRev());
} }
/* If we have a rev, check if we have a cached store path. */ /* If we have a rev, check if we have a cached store path. */
if (auto rev = input.getRev()) { if (auto rev = input.getRev()) {
if (auto res = input.settings->getCache()->lookupStorePath(revInfoKey(*rev), *store)) if (auto res = settings.getCache()->lookupStorePath(revInfoKey(*rev), *store))
return makeResult(res->value, res->storePath); return makeResult(res->value, res->storePath);
} }
@ -300,7 +300,7 @@ struct MercurialInputScheme : InputScheme
/* Now that we have the rev, check the cache again for a /* Now that we have the rev, check the cache again for a
cached store path. */ cached store path. */
if (auto res = input.settings->getCache()->lookupStorePath(revInfoKey(rev), *store)) if (auto res = settings.getCache()->lookupStorePath(revInfoKey(rev), *store))
return makeResult(res->value, res->storePath); return makeResult(res->value, res->storePath);
Path tmpDir = createTempDir(); Path tmpDir = createTempDir();
@ -317,18 +317,19 @@ struct MercurialInputScheme : InputScheme
}); });
if (!origRev) if (!origRev)
input.settings->getCache()->upsert(refToRevKey, {{"rev", rev.gitRev()}}); settings.getCache()->upsert(refToRevKey, {{"rev", rev.gitRev()}});
input.settings->getCache()->upsert(revInfoKey(rev), *store, infoAttrs, storePath); settings.getCache()->upsert(revInfoKey(rev), *store, infoAttrs, storePath);
return makeResult(infoAttrs, std::move(storePath)); return makeResult(infoAttrs, std::move(storePath));
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);
auto storePath = fetchToStore(store, input); auto storePath = fetchToStore(settings, store, input);
auto accessor = store->requireStoreObjectAccessor(storePath); auto accessor = store->requireStoreObjectAccessor(storePath);
accessor->setPathDisplay("«" + input.to_string() + "»"); accessor->setPathDisplay("«" + input.to_string() + "»");
@ -336,7 +337,7 @@ struct MercurialInputScheme : InputScheme
return {accessor, input}; return {accessor, input};
} }
bool isLocked(const Input & input) const override bool isLocked(const Settings & settings, const Input & input) const override
{ {
return (bool) input.getRev(); return (bool) input.getRev();
} }

View file

@ -17,7 +17,7 @@ struct PathInputScheme : InputScheme
if (url.authority && url.authority->host.size()) if (url.authority && url.authority->host.size())
throw Error("path URL '%s' should not have an authority ('%s')", url, *url.authority); throw Error("path URL '%s' should not have an authority ('%s')", url, *url.authority);
Input input{settings}; Input input{};
input.attrs.insert_or_assign("type", "path"); input.attrs.insert_or_assign("type", "path");
input.attrs.insert_or_assign("path", renderUrlPathEnsureLegal(url.path)); input.attrs.insert_or_assign("path", renderUrlPathEnsureLegal(url.path));
@ -60,7 +60,7 @@ struct PathInputScheme : InputScheme
{ {
getStrAttr(attrs, "path"); getStrAttr(attrs, "path");
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
return input; return input;
} }
@ -101,7 +101,7 @@ struct PathInputScheme : InputScheme
return path; return path;
} }
bool isLocked(const Input & input) const override bool isLocked(const Settings & settings, const Input & input) const override
{ {
return (bool) input.getNarHash(); return (bool) input.getNarHash();
} }
@ -116,7 +116,8 @@ struct PathInputScheme : InputScheme
throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string()); throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
Input input(_input); Input input(_input);
auto path = getStrAttr(input.attrs, "path"); auto path = getStrAttr(input.attrs, "path");
@ -145,7 +146,7 @@ struct PathInputScheme : InputScheme
auto info = store->queryPathInfo(*storePath); auto info = store->queryPathInfo(*storePath);
accessor->fingerprint = accessor->fingerprint =
fmt("path:%s", store->queryPathInfo(*storePath)->narHash.to_string(HashFormat::SRI, true)); fmt("path:%s", store->queryPathInfo(*storePath)->narHash.to_string(HashFormat::SRI, true));
input.settings->getCache()->upsert( settings.getCache()->upsert(
makeFetchToStoreCacheKey( makeFetchToStoreCacheKey(
input.getName(), *accessor->fingerprint, ContentAddressMethod::Raw::NixArchive, "/"), input.getName(), *accessor->fingerprint, ContentAddressMethod::Raw::NixArchive, "/"),
*store, *store,

View file

@ -131,9 +131,9 @@ std::shared_ptr<Registry> getFlagRegistry(const Settings & settings)
return flagRegistry; return flagRegistry;
} }
void overrideRegistry(const Input & from, const Input & to, const Attrs & extraAttrs) void overrideRegistry(const Settings & settings, const Input & from, const Input & to, const Attrs & extraAttrs)
{ {
getFlagRegistry(*from.settings)->add(from, to, extraAttrs); getFlagRegistry(settings)->add(from, to, extraAttrs);
} }
static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, ref<Store> store) static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, ref<Store> store)
@ -172,7 +172,8 @@ Registries getRegistries(const Settings & settings, ref<Store> store)
return registries; return registries;
} }
std::pair<Input, Attrs> lookupInRegistries(ref<Store> store, const Input & _input, UseRegistries useRegistries) std::pair<Input, Attrs>
lookupInRegistries(const Settings & settings, ref<Store> store, const Input & _input, UseRegistries useRegistries)
{ {
Attrs extraAttrs; Attrs extraAttrs;
int n = 0; int n = 0;
@ -187,7 +188,7 @@ restart:
if (n > 100) if (n > 100)
throw Error("cycle detected in flake registry for '%s'", input.to_string()); throw Error("cycle detected in flake registry for '%s'", input.to_string());
for (auto & registry : getRegistries(*input.settings, store)) { for (auto & registry : getRegistries(settings, store)) {
if (useRegistries == UseRegistries::Limited if (useRegistries == UseRegistries::Limited
&& !(registry->type == fetchers::Registry::Flag || registry->type == fetchers::Registry::Global)) && !(registry->type == fetchers::Registry::Flag || registry->type == fetchers::Registry::Global))
continue; continue;

View file

@ -224,7 +224,7 @@ ref<SourceAccessor> downloadTarball(ref<Store> store, const Settings & settings,
auto input = Input::fromAttrs(settings, std::move(attrs)); auto input = Input::fromAttrs(settings, std::move(attrs));
return input.getAccessor(store).first; return input.getAccessor(settings, store).first;
} }
// An input scheme corresponding to a curl-downloadable resource. // An input scheme corresponding to a curl-downloadable resource.
@ -252,7 +252,7 @@ struct CurlInputScheme : InputScheme
if (!isValidURL(_url, requireTree)) if (!isValidURL(_url, requireTree))
return std::nullopt; return std::nullopt;
Input input{settings}; Input input{};
auto url = _url; auto url = _url;
@ -302,7 +302,7 @@ struct CurlInputScheme : InputScheme
std::optional<Input> inputFromAttrs(const Settings & settings, const Attrs & attrs) const override std::optional<Input> inputFromAttrs(const Settings & settings, const Attrs & attrs) const override
{ {
Input input{settings}; Input input{};
input.attrs = attrs; input.attrs = attrs;
// input.locked = (bool) maybeGetStrAttr(input.attrs, "hash"); // input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
@ -319,7 +319,7 @@ struct CurlInputScheme : InputScheme
return url; return url;
} }
bool isLocked(const Input & input) const override bool isLocked(const Settings & settings, const Input & input) const override
{ {
return (bool) input.getNarHash(); return (bool) input.getNarHash();
} }
@ -340,7 +340,8 @@ struct FileInputScheme : CurlInputScheme
: (!requireTree && !hasTarballExtension(url))); : (!requireTree && !hasTarballExtension(url)));
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
auto input(_input); auto input(_input);
@ -348,7 +349,7 @@ struct FileInputScheme : CurlInputScheme
the Nix store directly, since there is little deduplication the Nix store directly, since there is little deduplication
benefit in using the Git cache for single big files like benefit in using the Git cache for single big files like
tarballs. */ tarballs. */
auto file = downloadFile(store, *input.settings, getStrAttr(input.attrs, "url"), input.getName()); auto file = downloadFile(store, settings, getStrAttr(input.attrs, "url"), input.getName());
auto narHash = store->queryPathInfo(file.storePath)->narHash; auto narHash = store->queryPathInfo(file.storePath)->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
@ -377,15 +378,15 @@ struct TarballInputScheme : CurlInputScheme
: (requireTree || hasTarballExtension(url))); : (requireTree || hasTarballExtension(url)));
} }
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override std::pair<ref<SourceAccessor>, Input>
getAccessor(const Settings & settings, ref<Store> store, const Input & _input) const override
{ {
auto input(_input); auto input(_input);
auto result = auto result = downloadTarball_(settings, getStrAttr(input.attrs, "url"), {}, "«" + input.to_string() + "»");
downloadTarball_(*input.settings, getStrAttr(input.attrs, "url"), {}, "«" + input.to_string() + "»");
if (result.immutableUrl) { if (result.immutableUrl) {
auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl); auto immutableInput = Input::fromURL(settings, *result.immutableUrl);
// FIXME: would be nice to support arbitrary flakerefs // FIXME: would be nice to support arbitrary flakerefs
// here, e.g. git flakes. // here, e.g. git flakes.
if (immutableInput.getType() != "tarball") if (immutableInput.getType() != "tarball")
@ -398,9 +399,7 @@ struct TarballInputScheme : CurlInputScheme
input.attrs.insert_or_assign( input.attrs.insert_or_assign(
"narHash", "narHash",
input.settings->getTarballCache() settings.getTarballCache()->treeHashToNarHash(settings, result.treeHash).to_string(HashFormat::SRI, true));
->treeHashToNarHash(*input.settings, result.treeHash)
.to_string(HashFormat::SRI, true));
return {result.accessor, input}; return {result.accessor, input};
} }

View file

@ -38,7 +38,7 @@ PrimOp getFlake(const Settings & settings)
std::string flakeRefS( std::string flakeRefS(
state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake")); state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
auto flakeRef = nix::parseFlakeRef(state.fetchSettings, flakeRefS, {}, true); auto flakeRef = nix::parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
if (state.settings.pureEval && !flakeRef.input.isLocked()) if (state.settings.pureEval && !flakeRef.input.isLocked(state.fetchSettings))
throw Error( throw Error(
"cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", "cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)",
flakeRefS, flakeRefS,

View file

@ -372,7 +372,8 @@ static Flake getFlake(
const InputAttrPath & lockRootAttrPath) const InputAttrPath & lockRootAttrPath)
{ {
// Fetch a lazy tree first. // Fetch a lazy tree first.
auto cachedInput = state.inputCache->getAccessor(state.store, originalRef.input, useRegistries); auto cachedInput =
state.inputCache->getAccessor(state.fetchSettings, state.store, originalRef.input, useRegistries);
auto subdir = fetchers::maybeGetStrAttr(cachedInput.extraAttrs, "dir").value_or(originalRef.subdir); auto subdir = fetchers::maybeGetStrAttr(cachedInput.extraAttrs, "dir").value_or(originalRef.subdir);
auto resolvedRef = FlakeRef(std::move(cachedInput.resolvedInput), subdir); auto resolvedRef = FlakeRef(std::move(cachedInput.resolvedInput), subdir);
@ -388,7 +389,8 @@ static Flake getFlake(
debug("refetching input '%s' due to self attribute", newLockedRef); debug("refetching input '%s' due to self attribute", newLockedRef);
// FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'. // FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'.
newLockedRef.input.attrs.erase("narHash"); newLockedRef.input.attrs.erase("narHash");
auto cachedInput2 = state.inputCache->getAccessor(state.store, newLockedRef.input, fetchers::UseRegistries::No); auto cachedInput2 = state.inputCache->getAccessor(
state.fetchSettings, state.store, newLockedRef.input, fetchers::UseRegistries::No);
cachedInput.accessor = cachedInput2.accessor; cachedInput.accessor = cachedInput2.accessor;
lockedRef = FlakeRef(std::move(cachedInput2.lockedInput), newLockedRef.subdir); lockedRef = FlakeRef(std::move(cachedInput2.lockedInput), newLockedRef.subdir);
} }
@ -704,7 +706,8 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
this input. */ this input. */
debug("creating new input '%s'", inputAttrPathS); debug("creating new input '%s'", inputAttrPathS);
if (!lockFlags.allowUnlocked && !input.ref->input.isLocked() && !input.ref->input.isRelative()) if (!lockFlags.allowUnlocked && !input.ref->input.isLocked(state.fetchSettings)
&& !input.ref->input.isRelative())
throw Error("cannot update unlocked flake input '%s' in pure mode", inputAttrPathS); throw Error("cannot update unlocked flake input '%s' in pure mode", inputAttrPathS);
/* Note: in case of an --override-input, we use /* Note: in case of an --override-input, we use
@ -753,7 +756,7 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
return {*resolvedPath, *input.ref}; return {*resolvedPath, *input.ref};
} else { } else {
auto cachedInput = state.inputCache->getAccessor( auto cachedInput = state.inputCache->getAccessor(
state.store, input.ref->input, useRegistriesInputs); state.fetchSettings, state.store, input.ref->input, useRegistriesInputs);
auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), input.ref->subdir); auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), input.ref->subdir);

View file

@ -64,9 +64,10 @@ std::ostream & operator<<(std::ostream & str, const FlakeRef & flakeRef)
return str; return str;
} }
FlakeRef FlakeRef::resolve(ref<Store> store, fetchers::UseRegistries useRegistries) const FlakeRef FlakeRef::resolve(
const fetchers::Settings & fetchSettings, ref<Store> store, fetchers::UseRegistries useRegistries) const
{ {
auto [input2, extraAttrs] = lookupInRegistries(store, input, useRegistries); auto [input2, extraAttrs] = lookupInRegistries(fetchSettings, store, input, useRegistries);
return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir)); return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));
} }
@ -287,9 +288,10 @@ FlakeRef FlakeRef::fromAttrs(const fetchers::Settings & fetchSettings, const fet
fetchers::maybeGetStrAttr(attrs, "dir").value_or("")); fetchers::maybeGetStrAttr(attrs, "dir").value_or(""));
} }
std::pair<ref<SourceAccessor>, FlakeRef> FlakeRef::lazyFetch(ref<Store> store) const std::pair<ref<SourceAccessor>, FlakeRef>
FlakeRef::lazyFetch(const fetchers::Settings & fetchSettings, ref<Store> store) const
{ {
auto [accessor, lockedInput] = input.getAccessor(store); auto [accessor, lockedInput] = input.getAccessor(fetchSettings, store);
return {accessor, FlakeRef(std::move(lockedInput), subdir)}; return {accessor, FlakeRef(std::move(lockedInput), subdir)};
} }

View file

@ -71,11 +71,15 @@ struct FlakeRef
fetchers::Attrs toAttrs() const; fetchers::Attrs toAttrs() const;
FlakeRef resolve(ref<Store> store, fetchers::UseRegistries useRegistries = fetchers::UseRegistries::All) const; FlakeRef resolve(
const fetchers::Settings & fetchSettings,
ref<Store> store,
fetchers::UseRegistries useRegistries = fetchers::UseRegistries::All) const;
static FlakeRef fromAttrs(const fetchers::Settings & fetchSettings, const fetchers::Attrs & attrs); static FlakeRef fromAttrs(const fetchers::Settings & fetchSettings, const fetchers::Attrs & attrs);
std::pair<ref<SourceAccessor>, FlakeRef> lazyFetch(ref<Store> store) const; std::pair<ref<SourceAccessor>, FlakeRef>
lazyFetch(const fetchers::Settings & fetchSettings, ref<Store> store) const;
/** /**
* Canonicalize a flakeref for the purpose of comparing "old" and * Canonicalize a flakeref for the purpose of comparing "old" and

View file

@ -74,7 +74,7 @@ LockedNode::LockedNode(const fetchers::Settings & fetchSettings, const nlohmann:
, parentInputAttrPath( , parentInputAttrPath(
json.find("parent") != json.end() ? (std::optional<InputAttrPath>) json["parent"] : std::nullopt) json.find("parent") != json.end() ? (std::optional<InputAttrPath>) json["parent"] : std::nullopt)
{ {
if (!lockedRef.input.isLocked() && !lockedRef.input.isRelative()) { if (!lockedRef.input.isLocked(fetchSettings) && !lockedRef.input.isRelative()) {
if (lockedRef.input.getNarHash()) if (lockedRef.input.getNarHash())
warn( warn(
"Lock file entry '%s' is unlocked (e.g. lacks a Git revision) but is checked by NAR hash. " "Lock file entry '%s' is unlocked (e.g. lacks a Git revision) but is checked by NAR hash. "
@ -282,7 +282,7 @@ std::optional<FlakeRef> LockFile::isUnlocked(const fetchers::Settings & fetchSet
latter case, we can verify the input but we may not be able to latter case, we can verify the input but we may not be able to
fetch it from anywhere. */ fetch it from anywhere. */
auto isConsideredLocked = [&](const fetchers::Input & input) { auto isConsideredLocked = [&](const fetchers::Input & input) {
return input.isLocked() || (fetchSettings.allowDirtyLocks && input.getNarHash()); return input.isLocked(fetchSettings) || (fetchSettings.allowDirtyLocks && input.getNarHash());
}; };
for (auto & i : nodes) { for (auto & i : nodes) {

View file

@ -45,7 +45,7 @@ struct CmdFlakePrefetchInputs : FlakeCommand
if (auto lockedNode = dynamic_cast<const LockedNode *>(&node)) { if (auto lockedNode = dynamic_cast<const LockedNode *>(&node)) {
try { try {
Activity act(*logger, lvlInfo, actUnknown, fmt("fetching '%s'", lockedNode->lockedRef)); Activity act(*logger, lvlInfo, actUnknown, fmt("fetching '%s'", lockedNode->lockedRef));
auto accessor = lockedNode->lockedRef.input.getAccessor(store).first; auto accessor = lockedNode->lockedRef.input.getAccessor(fetchSettings, store).first;
fetchToStore( fetchToStore(
fetchSettings, *store, accessor, FetchMode::Copy, lockedNode->lockedRef.input.getName()); fetchSettings, *store, accessor, FetchMode::Copy, lockedNode->lockedRef.input.getName());
} catch (Error & e) { } catch (Error & e) {

View file

@ -245,7 +245,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
printJSON(j); printJSON(j);
} else { } else {
logger->cout(ANSI_BOLD "Resolved URL:" ANSI_NORMAL " %s", flake.resolvedRef.to_string()); logger->cout(ANSI_BOLD "Resolved URL:" ANSI_NORMAL " %s", flake.resolvedRef.to_string());
if (flake.lockedRef.input.isLocked()) if (flake.lockedRef.input.isLocked(fetchSettings))
logger->cout(ANSI_BOLD "Locked URL:" ANSI_NORMAL " %s", flake.lockedRef.to_string()); logger->cout(ANSI_BOLD "Locked URL:" ANSI_NORMAL " %s", flake.lockedRef.to_string());
if (flake.description) if (flake.description)
logger->cout(ANSI_BOLD "Description:" ANSI_NORMAL " %s", *flake.description); logger->cout(ANSI_BOLD "Description:" ANSI_NORMAL " %s", *flake.description);
@ -1049,7 +1049,7 @@ struct CmdFlakeClone : FlakeCommand
if (destDir.empty()) if (destDir.empty())
throw Error("missing flag '--dest'"); throw Error("missing flag '--dest'");
getFlakeRef().resolve(store).input.clone(destDir); getFlakeRef().resolve(fetchSettings, store).input.clone(fetchSettings, destDir);
} }
}; };
@ -1100,7 +1100,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun, MixNoCheckSigs
std::optional<StorePath> storePath; std::optional<StorePath> storePath;
if (!(*inputNode)->lockedRef.input.isRelative()) { if (!(*inputNode)->lockedRef.input.isRelative()) {
storePath = dryRun ? (*inputNode)->lockedRef.input.computeStorePath(*store) storePath = dryRun ? (*inputNode)->lockedRef.input.computeStorePath(*store)
: (*inputNode)->lockedRef.input.fetchToStore(store).first; : (*inputNode)->lockedRef.input.fetchToStore(fetchSettings, store).first;
sources.insert(*storePath); sources.insert(*storePath);
} }
if (json) { if (json) {
@ -1496,8 +1496,8 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto originalRef = getFlakeRef(); auto originalRef = getFlakeRef();
auto resolvedRef = originalRef.resolve(store); auto resolvedRef = originalRef.resolve(fetchSettings, store);
auto [accessor, lockedRef] = resolvedRef.lazyFetch(store); auto [accessor, lockedRef] = resolvedRef.lazyFetch(getEvalState()->fetchSettings, store);
auto storePath = auto storePath =
fetchToStore(getEvalState()->fetchSettings, *store, accessor, FetchMode::Copy, lockedRef.input.getName()); fetchToStore(getEvalState()->fetchSettings, *store, accessor, FetchMode::Copy, lockedRef.input.getName());
auto hash = store->queryPathInfo(storePath)->narHash; auto hash = store->queryPathInfo(storePath)->narHash;

View file

@ -711,7 +711,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
element.identifier()); element.identifier());
continue; continue;
} }
if (element.source->originalRef.input.isLocked()) { if (element.source->originalRef.input.isLocked(getEvalState()->fetchSettings)) {
warn( warn(
"Found package '%s', but it was added from a locked flake reference so it can't be upgraded!", "Found package '%s', but it was added from a locked flake reference so it can't be upgraded!",
element.identifier()); element.identifier());
@ -740,7 +740,8 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
assert(infop); assert(infop);
auto & info = *infop; auto & info = *infop;
if (info.flake.lockedRef.input.isLocked() && element.source->lockedRef == info.flake.lockedRef) if (info.flake.lockedRef.input.isLocked(getEvalState()->fetchSettings)
&& element.source->lockedRef == info.flake.lockedRef)
continue; continue;
printInfo( printInfo(

View file

@ -190,8 +190,9 @@ struct CmdRegistryPin : RegistryCommand, EvalCommand
auto ref = parseFlakeRef(fetchSettings, url); auto ref = parseFlakeRef(fetchSettings, url);
auto lockedRef = parseFlakeRef(fetchSettings, locked); auto lockedRef = parseFlakeRef(fetchSettings, locked);
registry->remove(ref.input); registry->remove(ref.input);
auto resolved = lockedRef.resolve(store).input.getAccessor(store).second; auto resolvedInput = lockedRef.resolve(fetchSettings, store).input;
if (!resolved.isLocked()) auto resolved = resolvedInput.getAccessor(fetchSettings, store).second;
if (!resolved.isLocked(fetchSettings))
warn("flake '%s' is not locked", resolved.to_string()); warn("flake '%s' is not locked", resolved.to_string());
fetchers::Attrs extraAttrs; fetchers::Attrs extraAttrs;
if (ref.subdir != "") if (ref.subdir != "")