mirror of
https://github.com/NixOS/nix
synced 2025-06-25 10:41:16 +02:00
199 lines
7 KiB
C++
199 lines
7 KiB
C++
#include "fetch-settings.hh"
|
|
#include "eval-settings.hh"
|
|
#include "common-eval-args.hh"
|
|
#include "shared.hh"
|
|
#include "config-global.hh"
|
|
#include "filetransfer.hh"
|
|
#include "eval.hh"
|
|
#include "fetchers.hh"
|
|
#include "registry.hh"
|
|
#include "flake/flakeref.hh"
|
|
#include "flake/settings.hh"
|
|
#include "store-api.hh"
|
|
#include "command.hh"
|
|
#include "tarball.hh"
|
|
#include "fetch-to-store.hh"
|
|
#include "compatibility-settings.hh"
|
|
#include "eval-settings.hh"
|
|
|
|
namespace nix {
|
|
|
|
namespace fs { using namespace std::filesystem; }
|
|
|
|
fetchers::Settings fetchSettings;
|
|
|
|
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
|
|
|
EvalSettings evalSettings {
|
|
settings.readOnlyMode,
|
|
{
|
|
{
|
|
"flake",
|
|
[](EvalState & state, std::string_view rest) {
|
|
experimentalFeatureSettings.require(Xp::Flakes);
|
|
// FIXME `parseFlakeRef` should take a `std::string_view`.
|
|
auto flakeRef = parseFlakeRef(fetchSettings, std::string { rest }, {}, true, false);
|
|
debug("fetching flake search path element '%s''", rest);
|
|
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first;
|
|
return state.rootPath(state.store->toRealPath(storePath));
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
|
|
|
|
|
flake::Settings flakeSettings;
|
|
|
|
static GlobalConfig::Register rFlakeSettings(&flakeSettings);
|
|
|
|
|
|
CompatibilitySettings compatibilitySettings {};
|
|
|
|
static GlobalConfig::Register rCompatibilitySettings(&compatibilitySettings);
|
|
|
|
|
|
MixEvalArgs::MixEvalArgs()
|
|
{
|
|
addFlag({
|
|
.longName = "arg",
|
|
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
|
.category = category,
|
|
.labels = {"name", "expr"},
|
|
.handler = {[&](std::string name, std::string expr) { autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); }}
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "argstr",
|
|
.description = "Pass the string *string* as the argument *name* to Nix functions.",
|
|
.category = category,
|
|
.labels = {"name", "string"},
|
|
.handler = {[&](std::string name, std::string s) { autoArgs.insert_or_assign(name, AutoArg{AutoArgString{s}}); }},
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "arg-from-file",
|
|
.description = "Pass the contents of file *path* as the argument *name* to Nix functions.",
|
|
.category = category,
|
|
.labels = {"name", "path"},
|
|
.handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }},
|
|
.completer = completePath
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "arg-from-stdin",
|
|
.description = "Pass the contents of stdin as the argument *name* to Nix functions.",
|
|
.category = category,
|
|
.labels = {"name"},
|
|
.handler = {[&](std::string name) { autoArgs.insert_or_assign(name, AutoArg{AutoArgStdin{}}); }},
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "include",
|
|
.shortName = 'I',
|
|
.description = R"(
|
|
Add *path* to search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md)
|
|
|
|
This option may be given multiple times.
|
|
|
|
Paths added through `-I` take precedence over the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path) and the [`NIX_PATH` environment variable](@docroot@/command-ref/env-common.md#env-NIX_PATH).
|
|
)",
|
|
.category = category,
|
|
.labels = {"path"},
|
|
.handler = {[&](std::string s) {
|
|
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
|
|
}}
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "impure",
|
|
.description = "Allow access to mutable paths and repositories.",
|
|
.category = category,
|
|
.handler = {[&]() {
|
|
evalSettings.pureEval = false;
|
|
}},
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "override-flake",
|
|
.description = "Override the flake registries, redirecting *original-ref* to *resolved-ref*.",
|
|
.category = category,
|
|
.labels = {"original-ref", "resolved-ref"},
|
|
.handler = {[&](std::string _from, std::string _to) {
|
|
auto from = parseFlakeRef(fetchSettings, _from, fs::current_path().string());
|
|
auto to = parseFlakeRef(fetchSettings, _to, fs::current_path().string());
|
|
fetchers::Attrs extraAttrs;
|
|
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
|
|
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
|
|
}},
|
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
|
completeFlakeRef(completions, openStore(), prefix);
|
|
}}
|
|
});
|
|
|
|
addFlag({
|
|
.longName = "eval-store",
|
|
.description =
|
|
R"(
|
|
The [URL of the Nix store](@docroot@/store/types/index.md#store-url-format)
|
|
to use for evaluation, i.e. to store derivations (`.drv` files) and inputs referenced by them.
|
|
)",
|
|
.category = category,
|
|
.labels = {"store-url"},
|
|
.handler = {&evalStoreUrl},
|
|
});
|
|
}
|
|
|
|
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
|
{
|
|
auto res = state.buildBindings(autoArgs.size());
|
|
for (auto & [name, arg] : autoArgs) {
|
|
auto v = state.allocValue();
|
|
std::visit(overloaded {
|
|
[&](const AutoArgExpr & arg) {
|
|
state.mkThunk_(*v, state.parseExprFromString(arg.expr, compatibilitySettings.nixShellShebangArgumentsRelativeToScript ? state.rootPath(absPath(getCommandBaseDir())) : state.rootPath(".")));
|
|
},
|
|
[&](const AutoArgString & arg) {
|
|
v->mkString(arg.s);
|
|
},
|
|
[&](const AutoArgFile & arg) {
|
|
v->mkString(readFile(arg.path.string()));
|
|
},
|
|
[&](const AutoArgStdin & arg) {
|
|
v->mkString(readFile(STDIN_FILENO));
|
|
}
|
|
}, arg);
|
|
res.insert(state.symbols.create(name), v);
|
|
}
|
|
return res.finish();
|
|
}
|
|
|
|
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir)
|
|
{
|
|
if (EvalSettings::isPseudoUrl(s)) {
|
|
auto accessor = fetchers::downloadTarball(
|
|
state.store,
|
|
state.fetchSettings,
|
|
EvalSettings::resolvePseudoUrl(s));
|
|
auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy);
|
|
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
|
|
}
|
|
|
|
else if (hasPrefix(s, "flake:")) {
|
|
experimentalFeatureSettings.require(Xp::Flakes);
|
|
auto flakeRef = parseFlakeRef(fetchSettings, std::string(s.substr(6)), {}, true, false);
|
|
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first;
|
|
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
|
|
}
|
|
|
|
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
|
Path p(s.substr(1, s.size() - 2));
|
|
return state.findFile(p);
|
|
}
|
|
|
|
else
|
|
return state.rootPath(baseDir ? absPath(s, *baseDir) : absPath(s));
|
|
}
|
|
|
|
}
|