mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-24 23:06:16 +02:00
8ec1ba0210
This will allow documenting them (in later commits). Note that we keep the old constructor even if it is no longer used by Nix code, because it is used in tests/plugins/plugintest.cc, which suggests that it might be used by some external plugin.
97 lines
3.6 KiB
C++
97 lines
3.6 KiB
C++
#include "primops.hh"
|
|
#include "eval-inline.hh"
|
|
#include "store-api.hh"
|
|
#include "fetchers.hh"
|
|
#include "url.hh"
|
|
#include "url-parts.hh"
|
|
|
|
namespace nix {
|
|
|
|
static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
|
{
|
|
std::string url;
|
|
std::optional<Hash> rev;
|
|
std::optional<std::string> ref;
|
|
std::string_view name = "source";
|
|
NixStringContext context;
|
|
|
|
state.forceValue(*args[0], pos);
|
|
|
|
if (args[0]->type() == nAttrs) {
|
|
|
|
for (auto & attr : *args[0]->attrs) {
|
|
std::string_view n(state.symbols[attr.name]);
|
|
if (n == "url")
|
|
url = state.coerceToString(attr.pos, *attr.value, context,
|
|
"while evaluating the `url` attribute passed to builtins.fetchMercurial",
|
|
false, false).toOwned();
|
|
else if (n == "rev") {
|
|
// Ugly: unlike fetchGit, here the "rev" attribute can
|
|
// be both a revision or a branch/tag name.
|
|
auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial");
|
|
if (std::regex_match(value.begin(), value.end(), revRegex))
|
|
rev = Hash::parseAny(value, htSHA1);
|
|
else
|
|
ref = value;
|
|
}
|
|
else if (n == "name")
|
|
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial");
|
|
else
|
|
throw EvalError({
|
|
.msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]),
|
|
.errPos = state.positions[attr.pos]
|
|
});
|
|
}
|
|
|
|
if (url.empty())
|
|
throw EvalError({
|
|
.msg = hintfmt("'url' argument required"),
|
|
.errPos = state.positions[pos]
|
|
});
|
|
|
|
} else
|
|
url = state.coerceToString(pos, *args[0], context,
|
|
"while evaluating the first argument passed to builtins.fetchMercurial",
|
|
false, false).toOwned();
|
|
|
|
// FIXME: git externals probably can be used to bypass the URI
|
|
// whitelist. Ah well.
|
|
state.checkURI(url);
|
|
|
|
if (evalSettings.pureEval && !rev)
|
|
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
|
|
|
|
fetchers::Attrs attrs;
|
|
attrs.insert_or_assign("type", "hg");
|
|
attrs.insert_or_assign("url", url.find("://") != std::string::npos ? url : "file://" + url);
|
|
attrs.insert_or_assign("name", std::string(name));
|
|
if (ref) attrs.insert_or_assign("ref", *ref);
|
|
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
|
|
auto input = fetchers::Input::fromAttrs(std::move(attrs));
|
|
|
|
// FIXME: use name
|
|
auto [tree, input2] = input.fetch(state.store);
|
|
|
|
auto attrs2 = state.buildBindings(8);
|
|
state.mkStorePathString(tree.storePath, attrs2.alloc(state.sOutPath));
|
|
if (input2.getRef())
|
|
attrs2.alloc("branch").mkString(*input2.getRef());
|
|
// Backward compatibility: set 'rev' to
|
|
// 0000000000000000000000000000000000000000 for a dirty tree.
|
|
auto rev2 = input2.getRev().value_or(Hash(htSHA1));
|
|
attrs2.alloc("rev").mkString(rev2.gitRev());
|
|
attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(0, 12));
|
|
if (auto revCount = input2.getRevCount())
|
|
attrs2.alloc("revCount").mkInt(*revCount);
|
|
v.mkAttrs(attrs2);
|
|
|
|
state.allowPath(tree.storePath);
|
|
}
|
|
|
|
static RegisterPrimOp r_fetchMercurial({
|
|
.name = "fetchMercurial",
|
|
.arity = 1,
|
|
.fun = prim_fetchMercurial
|
|
});
|
|
|
|
}
|