Factor out flake:... lookup path from evaluator

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
John Ericson 2024-06-24 17:33:15 -04:00
parent 88f9d8ccb1
commit 52730d38e2
4 changed files with 68 additions and 20 deletions

View File

@ -15,7 +15,20 @@
namespace nix {
EvalSettings evalSettings {
settings.readOnlyMode
settings.readOnlyMode,
{
{
"flake",
[](ref<Store> store, std::string_view rest) {
experimentalFeatureSettings.require(Xp::Flakes);
// FIXME `parseFlakeRef` should take a `std::string_view`.
auto flakeRef = parseFlakeRef(std::string { rest }, {}, true, false);
debug("fetching flake search path element '%s''", rest);
auto storePath = flakeRef.resolve(store).fetchTree(store).first;
return store->toRealPath(storePath);
},
},
},
};
static GlobalConfig::Register rEvalSettings(&evalSettings);

View File

@ -45,8 +45,9 @@ static Strings parseNixPath(const std::string & s)
return res;
}
EvalSettings::EvalSettings(bool & readOnlyMode)
EvalSettings::EvalSettings(bool & readOnlyMode, EvalSettings::LookupPathHooks lookupPathHooks)
: readOnlyMode{readOnlyMode}
, lookupPathHooks{lookupPathHooks}
{
auto var = getEnv("NIX_PATH");
if (var) nixPath = parseNixPath(*var);

View File

@ -5,9 +5,40 @@
namespace nix {
class Store;
struct EvalSettings : Config
{
EvalSettings(bool & readOnlyMode);
/**
* Function used to interpet look path entries of a given scheme.
*
* The argument is the non-scheme part of the lookup path entry (see
* `LookupPathHooks` below).
*
* The return value is (a) whether the entry was valid, and, if so,
* what does it map to.
*
* @todo Return (`std::optional` of) `SourceAccssor` or something
* more structured instead of mere `std::string`?
*/
using LookupPathHook = std::optional<std::string>(ref<Store> store, std::string_view);
/**
* Map from "scheme" to a `LookupPathHook`.
*
* Given a lookup path value (i.e. either the whole thing, or after
* the `<key>=`) in the form of:
*
* ```
* <scheme>:<arbitrary string>
* ```
*
* if `<scheme>` is a key in this map, then `<arbitrary string>` is
* passed to the hook that is the value in this map.
*/
using LookupPathHooks = std::map<std::string, std::function<LookupPathHook>>;
EvalSettings(bool & readOnlyMode, LookupPathHooks lookupPathHooks = {});
bool & readOnlyMode;
@ -17,6 +48,8 @@ struct EvalSettings : Config
static std::string resolvePseudoUrl(std::string_view url);
LookupPathHooks lookupPathHooks;
Setting<bool> enableNativeCode{this, false, "allow-unsafe-native-code-during-evaluation", R"(
Enable built-in functions that allow executing native code.

View File

@ -2760,14 +2760,18 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
auto i = lookupPathResolved.find(value);
if (i != lookupPathResolved.end()) return i->second;
std::optional<std::string> res;
auto finish = [&](std::string res) {
debug("resolved search path element '%s' to '%s'", value, res);
lookupPathResolved.emplace(value, res);
return res;
};
if (EvalSettings::isPseudoUrl(value)) {
try {
auto accessor = fetchers::downloadTarball(
EvalSettings::resolvePseudoUrl(value)).accessor;
auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy);
res = { store->toRealPath(storePath) };
return finish(store->toRealPath(storePath));
} catch (Error & e) {
logWarning({
.msg = HintFmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value)
@ -2775,15 +2779,17 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
}
}
else if (hasPrefix(value, "flake:")) {
experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false);
debug("fetching flake search path element '%s''", value);
auto storePath = flakeRef.resolve(store).fetchTree(store).first;
res = { store->toRealPath(storePath) };
if (auto colPos = value.find(':'); colPos != value.npos) {
auto scheme = value.substr(0, colPos);
auto rest = value.substr(colPos + 1);
if (auto * hook = get(settings.lookupPathHooks, scheme)) {
auto res = (*hook)(store, rest);
if (res)
return finish(std::move(*res));
}
}
else {
{
auto path = absPath(value);
/* Allow access to paths in the search path. */
@ -2800,22 +2806,17 @@ std::optional<std::string> EvalState::resolveLookupPathPath(const LookupPath::Pa
}
if (pathExists(path))
res = { path };
return finish(std::move(path));
else {
logWarning({
.msg = HintFmt("Nix search path entry '%1%' does not exist, ignoring", value)
});
res = std::nullopt;
}
}
if (res)
debug("resolved search path element '%s' to '%s'", value, *res);
else
debug("failed to resolve search path element '%s'", value);
debug("failed to resolve search path element '%s'", value);
return std::nullopt;
lookupPathResolved.emplace(value, res);
return res;
}