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:
commit
805496657d
27 changed files with 181 additions and 168 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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 != "")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue