forked from lix-project/lix
jade
3e151d4d77
This reverts commit35eec921af
. Reason for revert: Regressed nix-eval-jobs, and it appears to be this change is buggy/missing a case. It just needs another pass. Code causing the problem in n-e-j, when invoked with `nix-eval-jobs --flake '.#hydraJobs'`: ``` n-e-j/tests/assets » ../../build/src/nix-eval-jobs --meta --workers 1 --flake .#hydraJobs warning: unknown setting 'trusted-users' warning: `--gc-roots-dir' not specified error: unsupported Git input attribute 'dir' error: worker error: error: unsupported Git input attribute 'dir' ``` ``` nix::Value *vRoot = [&]() { if (args.flake) { auto [flakeRef, fragment, outputSpec] = nix::parseFlakeRefWithFragmentAndExtendedOutputsSpec( args.releaseExpr, nix::absPath(".")); nix::InstallableFlake flake{ {}, state, std::move(flakeRef), fragment, outputSpec, {}, {}, args.lockFlags}; return flake.toValue(*state).first; } else { return releaseExprTopLevelValue(*state, autoArgs, args); } }(); ``` Inspecting the program behaviour reveals that `dir` was in fact set in the URL going into the fetcher. This is in turn because unlike in the case changed in this commit, it was not erased before handing it to libfetchers, which is probably just a mistake. ``` (rr) up 3 0x00007ffff60262ae in nix::fetchers::Input::fromURL (url=..., requireTree=requireTree@entry=true) at src/libfetchers/fetchers.cc:39 warning: Source file is more recent than executable. 39 auto res = inputScheme->inputFromURL(url, requireTree); (rr) p url $1 = (const nix::ParsedURL &) @0x7fffdc874190: {url = "git+file:///home/jade/lix/nix-eval-jobs", base = "git+file:///home/jade/lix/nix-eval-jobs", scheme = "git+file", authority = std::optional<std::string> = {[contained value] = ""}, path = "/home/jade/lix/nix-eval-jobs", query = std::map with 1 element = {["dir"] = "tests/assets"}, fragment = ""} (rr) up 4 0x00007ffff789d904 in nix::parseFlakeRefWithFragment (url=".#hydraJobs", baseDir=std::optional<std::string> = {...}, allowMissing=allowMissing@entry=false, isFlake=isFlake@entry=true) at src/libexpr/flake/flakeref.cc:179 warning: Source file is more recent than executable. 179 FlakeRef(Input::fromURL(parsedURL, isFlake), getOr(parsedURL.query, "dir", "")), (rr) p parsedURL $2 = {url = "git+file:///home/jade/lix/nix-eval-jobs", base = "git+file:///home/jade/lix/nix-eval-jobs", scheme = "git+file", authority = std::optional<std::string> = {[contained value] = ""}, path = "/home/jade/lix/nix-eval-jobs", query = std::map with 1 element = { ["dir"] = "tests/assets"}, fragment = ""} (rr) list 174 175 if (pathExists(flakeRoot + "/.git/shallow")) 176 parsedURL.query.insert_or_assign("shallow", "1"); 177 178 return std::make_pair( 179 FlakeRef(Input::fromURL(parsedURL, isFlake), getOr(parsedURL.query, "dir", "")), 180 fragment); 181 } ``` Change-Id:Ib55a882eaeb3e59228857761dc1e3b2e366b0f5e
106 lines
3.6 KiB
C++
106 lines
3.6 KiB
C++
#include "fetchers.hh"
|
|
#include "url-parts.hh"
|
|
#include "path.hh"
|
|
|
|
namespace nix::fetchers {
|
|
|
|
std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
|
|
|
|
struct IndirectInputScheme : InputScheme
|
|
{
|
|
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
|
{
|
|
if (url.scheme != "flake") return {};
|
|
|
|
auto path = tokenizeString<std::vector<std::string>>(url.path, "/");
|
|
|
|
std::optional<Hash> rev;
|
|
std::optional<std::string> ref;
|
|
|
|
if (path.size() == 1) {
|
|
} else if (path.size() == 2) {
|
|
if (std::regex_match(path[1], revRegex))
|
|
rev = Hash::parseAny(path[1], htSHA1);
|
|
else if (std::regex_match(path[1], refRegex))
|
|
ref = path[1];
|
|
else
|
|
throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[1]);
|
|
} else if (path.size() == 3) {
|
|
if (!std::regex_match(path[1], refRegex))
|
|
throw BadURL("in flake URL '%s', '%s' is not a branch/tag name", url.url, path[1]);
|
|
ref = path[1];
|
|
if (!std::regex_match(path[2], revRegex))
|
|
throw BadURL("in flake URL '%s', '%s' is not a commit hash", url.url, path[2]);
|
|
rev = Hash::parseAny(path[2], htSHA1);
|
|
} else
|
|
throw BadURL("GitHub URL '%s' is invalid", url.url);
|
|
|
|
std::string id = path[0];
|
|
if (!std::regex_match(id, flakeRegex))
|
|
throw BadURL("'%s' is not a valid flake ID", id);
|
|
|
|
// FIXME: forbid query params?
|
|
|
|
Input input;
|
|
input.direct = false;
|
|
input.attrs.insert_or_assign("type", "indirect");
|
|
input.attrs.insert_or_assign("id", id);
|
|
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
|
if (ref) input.attrs.insert_or_assign("ref", *ref);
|
|
|
|
return input;
|
|
}
|
|
|
|
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
|
{
|
|
if (maybeGetStrAttr(attrs, "type") != "indirect") return {};
|
|
|
|
for (auto & [name, value] : attrs)
|
|
if (name != "type" && name != "id" && name != "ref" && name != "rev" && name != "narHash")
|
|
throw Error("unsupported indirect input attribute '%s'", name);
|
|
|
|
auto id = getStrAttr(attrs, "id");
|
|
if (!std::regex_match(id, flakeRegex))
|
|
throw BadURL("'%s' is not a valid flake ID", id);
|
|
|
|
Input input;
|
|
input.direct = false;
|
|
input.attrs = attrs;
|
|
return input;
|
|
}
|
|
|
|
ParsedURL toURL(const Input & input) const override
|
|
{
|
|
ParsedURL url;
|
|
url.scheme = "flake";
|
|
url.path = getStrAttr(input.attrs, "id");
|
|
if (auto ref = input.getRef()) { url.path += '/'; url.path += *ref; };
|
|
if (auto rev = input.getRev()) { url.path += '/'; url.path += rev->gitRev(); };
|
|
return url;
|
|
}
|
|
|
|
bool hasAllInfo(const Input & input) const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Input applyOverrides(
|
|
const Input & _input,
|
|
std::optional<std::string> ref,
|
|
std::optional<Hash> rev) const override
|
|
{
|
|
auto input(_input);
|
|
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
|
if (ref) input.attrs.insert_or_assign("ref", *ref);
|
|
return input;
|
|
}
|
|
|
|
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
|
|
{
|
|
throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
|
|
}
|
|
};
|
|
|
|
static auto rIndirectInputScheme = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });
|
|
|
|
}
|