mirror of
https://github.com/NixOS/nix.git
synced 2025-12-03 15:40:59 +01:00
No global settings in libnixfetchers and libnixflake
Progress on #5638
There are still a global fetcher and eval settings, but they are pushed
down into `libnixcmd`, which is a lot less bad a place for this sort of
thing.
Continuing process pioneered in
52bfccf8d8.
This commit is contained in:
parent
b57c361097
commit
3fc77f281e
50 changed files with 401 additions and 271 deletions
|
|
@ -1,14 +1,9 @@
|
|||
#include "fetch-settings.hh"
|
||||
#include "config-global.hh"
|
||||
|
||||
namespace nix {
|
||||
namespace nix::fetchers {
|
||||
|
||||
FetchSettings::FetchSettings()
|
||||
Settings::Settings()
|
||||
{
|
||||
}
|
||||
|
||||
FetchSettings fetchSettings;
|
||||
|
||||
static GlobalConfig::Register rFetchSettings(&fetchSettings);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace nix {
|
||||
namespace nix::fetchers {
|
||||
|
||||
struct FetchSettings : public Config
|
||||
struct Settings : public Config
|
||||
{
|
||||
FetchSettings();
|
||||
Settings();
|
||||
|
||||
Setting<StringMap> accessTokens{this, {}, "access-tokens",
|
||||
R"(
|
||||
|
|
@ -84,9 +84,14 @@ struct FetchSettings : public Config
|
|||
`narHash` attribute is specified,
|
||||
e.g. `github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f?narHash=sha256-PPXqKY2hJng4DBVE0I4xshv/vGLUskL7jl53roB8UdU%3D`.
|
||||
)"};
|
||||
|
||||
Setting<std::string> flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry",
|
||||
R"(
|
||||
Path or URI of the global flake registry.
|
||||
|
||||
When empty, disables the global flake registry.
|
||||
)",
|
||||
{}, true, Xp::Flakes};
|
||||
};
|
||||
|
||||
// FIXME: don't use a global variable.
|
||||
extern FetchSettings fetchSettings;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,11 @@ nlohmann::json dumpRegisterInputSchemeInfo() {
|
|||
return res;
|
||||
}
|
||||
|
||||
Input Input::fromURL(const std::string & url, bool requireTree)
|
||||
Input Input::fromURL(
|
||||
const Settings & settings,
|
||||
const std::string & url, bool requireTree)
|
||||
{
|
||||
return fromURL(parseURL(url), requireTree);
|
||||
return fromURL(settings, parseURL(url), requireTree);
|
||||
}
|
||||
|
||||
static void fixupInput(Input & input)
|
||||
|
|
@ -49,10 +51,12 @@ static void fixupInput(Input & input)
|
|||
input.getLastModified();
|
||||
}
|
||||
|
||||
Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
||||
Input Input::fromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree)
|
||||
{
|
||||
for (auto & [_, inputScheme] : *inputSchemes) {
|
||||
auto res = inputScheme->inputFromURL(url, requireTree);
|
||||
auto res = inputScheme->inputFromURL(settings, url, requireTree);
|
||||
if (res) {
|
||||
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
|
||||
res->scheme = inputScheme;
|
||||
|
|
@ -64,7 +68,7 @@ Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
|||
throw Error("input '%s' is unsupported", url.url);
|
||||
}
|
||||
|
||||
Input Input::fromAttrs(Attrs && attrs)
|
||||
Input Input::fromAttrs(const Settings & settings, Attrs && attrs)
|
||||
{
|
||||
auto schemeName = ({
|
||||
auto schemeNameOpt = maybeGetStrAttr(attrs, "type");
|
||||
|
|
@ -78,7 +82,7 @@ Input Input::fromAttrs(Attrs && attrs)
|
|||
// but not all of them. Doing this is to support those other
|
||||
// operations which are supposed to be robust on
|
||||
// unknown/uninterpretable inputs.
|
||||
Input input;
|
||||
Input input { settings };
|
||||
input.attrs = attrs;
|
||||
fixupInput(input);
|
||||
return input;
|
||||
|
|
@ -99,7 +103,7 @@ Input Input::fromAttrs(Attrs && attrs)
|
|||
if (name != "type" && allowedAttrs.count(name) == 0)
|
||||
throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName);
|
||||
|
||||
auto res = inputScheme->inputFromAttrs(attrs);
|
||||
auto res = inputScheme->inputFromAttrs(settings, attrs);
|
||||
if (!res) return raw();
|
||||
res->scheme = inputScheme;
|
||||
fixupInput(*res);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ namespace nix::fetchers {
|
|||
|
||||
struct InputScheme;
|
||||
|
||||
struct Settings;
|
||||
|
||||
/**
|
||||
* The `Input` object is generated by a specific fetcher, based on
|
||||
* user-supplied information, and contains
|
||||
|
|
@ -28,6 +30,12 @@ struct Input
|
|||
{
|
||||
friend struct InputScheme;
|
||||
|
||||
const Settings * settings;
|
||||
|
||||
Input(const Settings & settings)
|
||||
: settings{&settings}
|
||||
{ }
|
||||
|
||||
std::shared_ptr<InputScheme> scheme; // note: can be null
|
||||
Attrs attrs;
|
||||
|
||||
|
|
@ -42,16 +50,22 @@ public:
|
|||
*
|
||||
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
||||
*/
|
||||
static Input fromURL(const std::string & url, bool requireTree = true);
|
||||
static Input fromURL(
|
||||
const Settings & settings,
|
||||
const std::string & url, bool requireTree = true);
|
||||
|
||||
static Input fromURL(const ParsedURL & url, bool requireTree = true);
|
||||
static Input fromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree = true);
|
||||
|
||||
/**
|
||||
* Create an `Input` from a an `Attrs`.
|
||||
*
|
||||
* The URL indicate which sort of fetcher, and provides information to that fetcher.
|
||||
*/
|
||||
static Input fromAttrs(Attrs && attrs);
|
||||
static Input fromAttrs(
|
||||
const Settings & settings,
|
||||
Attrs && attrs);
|
||||
|
||||
ParsedURL toURL() const;
|
||||
|
||||
|
|
@ -146,9 +160,13 @@ struct InputScheme
|
|||
virtual ~InputScheme()
|
||||
{ }
|
||||
|
||||
virtual std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const = 0;
|
||||
virtual std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const = 0;
|
||||
|
||||
virtual std::optional<Input> inputFromAttrs(const Attrs & attrs) const = 0;
|
||||
virtual std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const = 0;
|
||||
|
||||
/**
|
||||
* What is the name of the scheme?
|
||||
|
|
|
|||
|
|
@ -164,7 +164,9 @@ static const Hash nullRev{HashAlgorithm::SHA1};
|
|||
|
||||
struct GitInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
||||
std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const override
|
||||
{
|
||||
if (url.scheme != "git" &&
|
||||
url.scheme != "git+http" &&
|
||||
|
|
@ -190,7 +192,7 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
attrs.emplace("url", url2.to_string());
|
||||
|
||||
return inputFromAttrs(attrs);
|
||||
return inputFromAttrs(settings, attrs);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -222,7 +224,9 @@ struct GitInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
for (auto & [name, _] : attrs)
|
||||
if (name == "verifyCommit"
|
||||
|
|
@ -238,7 +242,7 @@ struct GitInputScheme : InputScheme
|
|||
throw BadURL("invalid Git branch/tag name '%s'", *ref);
|
||||
}
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
auto url = fixGitURL(getStrAttr(attrs, "url"));
|
||||
parseURL(url);
|
||||
|
|
@ -366,13 +370,13 @@ struct GitInputScheme : InputScheme
|
|||
/* URL of the repo, or its path if isLocal. Never a `file` URL. */
|
||||
std::string url;
|
||||
|
||||
void warnDirty() const
|
||||
void warnDirty(const Settings & settings) const
|
||||
{
|
||||
if (workdirInfo.isDirty) {
|
||||
if (!fetchSettings.allowDirty)
|
||||
if (!settings.allowDirty)
|
||||
throw Error("Git tree '%s' is dirty", url);
|
||||
|
||||
if (fetchSettings.warnDirty)
|
||||
if (settings.warnDirty)
|
||||
warn("Git tree '%s' is dirty", url);
|
||||
}
|
||||
}
|
||||
|
|
@ -653,7 +657,7 @@ struct GitInputScheme : InputScheme
|
|||
attrs.insert_or_assign("exportIgnore", Explicit<bool>{ exportIgnore });
|
||||
attrs.insert_or_assign("submodules", Explicit<bool>{ true });
|
||||
attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
||||
auto submoduleInput = fetchers::Input::fromAttrs(std::move(attrs));
|
||||
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs));
|
||||
auto [submoduleAccessor, submoduleInput2] =
|
||||
submoduleInput.getAccessor(store);
|
||||
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
||||
|
|
@ -711,7 +715,7 @@ struct GitInputScheme : InputScheme
|
|||
// TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out
|
||||
// attrs.insert_or_assign("allRefs", Explicit<bool>{ true });
|
||||
|
||||
auto submoduleInput = fetchers::Input::fromAttrs(std::move(attrs));
|
||||
auto submoduleInput = fetchers::Input::fromAttrs(*input.settings, std::move(attrs));
|
||||
auto [submoduleAccessor, submoduleInput2] =
|
||||
submoduleInput.getAccessor(store);
|
||||
submoduleAccessor->setPathDisplay("«" + submoduleInput.to_string() + "»");
|
||||
|
|
@ -743,7 +747,7 @@ struct GitInputScheme : InputScheme
|
|||
|
||||
verifyCommit(input, repo);
|
||||
} else {
|
||||
repoInfo.warnDirty();
|
||||
repoInfo.warnDirty(*input.settings);
|
||||
|
||||
if (repoInfo.workdirInfo.headRev) {
|
||||
input.attrs.insert_or_assign("dirtyRev",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ struct GitArchiveInputScheme : InputScheme
|
|||
{
|
||||
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
||||
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
||||
std::optional<Input> inputFromURL(
|
||||
const fetchers::Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const override
|
||||
{
|
||||
if (url.scheme != schemeName()) return {};
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
if (ref && rev)
|
||||
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev());
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs.insert_or_assign("type", std::string { schemeName() });
|
||||
input.attrs.insert_or_assign("owner", path[0]);
|
||||
input.attrs.insert_or_assign("repo", path[1]);
|
||||
|
|
@ -119,12 +121,14 @@ struct GitArchiveInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const fetchers::Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
getStrAttr(attrs, "owner");
|
||||
getStrAttr(attrs, "repo");
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
return input;
|
||||
}
|
||||
|
|
@ -168,18 +172,20 @@ struct GitArchiveInputScheme : InputScheme
|
|||
return input;
|
||||
}
|
||||
|
||||
std::optional<std::string> getAccessToken(const std::string & host) const
|
||||
std::optional<std::string> getAccessToken(const fetchers::Settings & settings, const std::string & host) const
|
||||
{
|
||||
auto tokens = fetchSettings.accessTokens.get();
|
||||
auto tokens = settings.accessTokens.get();
|
||||
if (auto token = get(tokens, host))
|
||||
return *token;
|
||||
return {};
|
||||
}
|
||||
|
||||
Headers makeHeadersWithAuthTokens(const std::string & host) const
|
||||
Headers makeHeadersWithAuthTokens(
|
||||
const fetchers::Settings & settings,
|
||||
const std::string & host) const
|
||||
{
|
||||
Headers headers;
|
||||
auto accessToken = getAccessToken(host);
|
||||
auto accessToken = getAccessToken(settings, host);
|
||||
if (accessToken) {
|
||||
auto hdr = accessHeaderFromToken(*accessToken);
|
||||
if (hdr)
|
||||
|
|
@ -295,7 +301,7 @@ struct GitArchiveInputScheme : InputScheme
|
|||
locking. FIXME: in the future, we may want to require a Git
|
||||
tree hash instead of a NAR hash. */
|
||||
return input.getRev().has_value()
|
||||
&& (fetchSettings.trustTarballsFromGitForges ||
|
||||
&& (input.settings->trustTarballsFromGitForges ||
|
||||
input.getNarHash().has_value());
|
||||
}
|
||||
|
||||
|
|
@ -352,7 +358,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
: "https://%s/api/v3/repos/%s/%s/commits/%s",
|
||||
host, getOwner(input), getRepo(input), *input.getRef());
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
|
||||
auto json = nlohmann::json::parse(
|
||||
readFile(
|
||||
|
|
@ -369,7 +375,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
{
|
||||
auto host = getHost(input);
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
|
||||
// If we have no auth headers then we default to the public archive
|
||||
// urls so we do not run into rate limits.
|
||||
|
|
@ -389,7 +395,7 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
|||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto host = getHost(input);
|
||||
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
||||
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git",
|
||||
host, getOwner(input), getRepo(input)))
|
||||
.applyOverrides(input.getRef(), input.getRev())
|
||||
.clone(destDir);
|
||||
|
|
@ -426,7 +432,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
|
||||
auto json = nlohmann::json::parse(
|
||||
readFile(
|
||||
|
|
@ -456,7 +462,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(HashFormat::Base16, false));
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
return DownloadUrl { url, headers };
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +470,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
|||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
||||
// FIXME: get username somewhere
|
||||
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
||||
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s.git",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||
.applyOverrides(input.getRef(), input.getRev())
|
||||
.clone(destDir);
|
||||
|
|
@ -496,7 +502,7 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
|||
auto base_url = fmt("https://%s/%s/%s",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
|
||||
std::string refUri;
|
||||
if (ref == "HEAD") {
|
||||
|
|
@ -543,14 +549,14 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
|||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
||||
input.getRev()->to_string(HashFormat::Base16, false));
|
||||
|
||||
Headers headers = makeHeadersWithAuthTokens(host);
|
||||
Headers headers = makeHeadersWithAuthTokens(*input.settings, host);
|
||||
return DownloadUrl { url, headers };
|
||||
}
|
||||
|
||||
void clone(const Input & input, const Path & destDir) const override
|
||||
{
|
||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
||||
Input::fromURL(fmt("git+https://%s/%s/%s",
|
||||
Input::fromURL(*input.settings, fmt("git+https://%s/%s/%s",
|
||||
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||
.applyOverrides(input.getRef(), input.getRev())
|
||||
.clone(destDir);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ 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
|
||||
std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const override
|
||||
{
|
||||
if (url.scheme != "flake") return {};
|
||||
|
||||
|
|
@ -41,7 +43,7 @@ struct IndirectInputScheme : InputScheme
|
|||
|
||||
// FIXME: forbid query params?
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs.insert_or_assign("type", "indirect");
|
||||
input.attrs.insert_or_assign("id", id);
|
||||
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
||||
|
|
@ -65,13 +67,15 @@ struct IndirectInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
auto id = getStrAttr(attrs, "id");
|
||||
if (!std::regex_match(id, flakeRegex))
|
||||
throw BadURL("'%s' is not a valid flake ID", id);
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
return input;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ static std::string runHg(const Strings & args, const std::optional<std::string>
|
|||
|
||||
struct MercurialInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
||||
std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const override
|
||||
{
|
||||
if (url.scheme != "hg+http" &&
|
||||
url.scheme != "hg+https" &&
|
||||
|
|
@ -68,7 +70,7 @@ struct MercurialInputScheme : InputScheme
|
|||
|
||||
attrs.emplace("url", url2.to_string());
|
||||
|
||||
return inputFromAttrs(attrs);
|
||||
return inputFromAttrs(settings, attrs);
|
||||
}
|
||||
|
||||
std::string_view schemeName() const override
|
||||
|
|
@ -88,7 +90,9 @@ struct MercurialInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
parseURL(getStrAttr(attrs, "url"));
|
||||
|
||||
|
|
@ -97,7 +101,7 @@ struct MercurialInputScheme : InputScheme
|
|||
throw BadURL("invalid Mercurial branch/tag name '%s'", *ref);
|
||||
}
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
return input;
|
||||
}
|
||||
|
|
@ -182,10 +186,10 @@ struct MercurialInputScheme : InputScheme
|
|||
/* This is an unclean working tree. So copy all tracked
|
||||
files. */
|
||||
|
||||
if (!fetchSettings.allowDirty)
|
||||
if (!input.settings->allowDirty)
|
||||
throw Error("Mercurial tree '%s' is unclean", actualUrl);
|
||||
|
||||
if (fetchSettings.warnDirty)
|
||||
if (input.settings->warnDirty)
|
||||
warn("Mercurial tree '%s' is unclean", actualUrl);
|
||||
|
||||
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
|
||||
|
|
|
|||
|
|
@ -7,14 +7,16 @@ namespace nix::fetchers {
|
|||
|
||||
struct PathInputScheme : InputScheme
|
||||
{
|
||||
std::optional<Input> inputFromURL(const ParsedURL & url, bool requireTree) const override
|
||||
std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & url, bool requireTree) const override
|
||||
{
|
||||
if (url.scheme != "path") return {};
|
||||
|
||||
if (url.authority && *url.authority != "")
|
||||
throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority);
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs.insert_or_assign("type", "path");
|
||||
input.attrs.insert_or_assign("path", url.path);
|
||||
|
||||
|
|
@ -54,11 +56,13 @@ struct PathInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
getStrAttr(attrs, "path");
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
return input;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "fetch-settings.hh"
|
||||
#include "registry.hh"
|
||||
#include "tarball.hh"
|
||||
#include "users.hh"
|
||||
#include "config-global.hh"
|
||||
#include "globals.hh"
|
||||
#include "store-api.hh"
|
||||
#include "local-fs-store.hh"
|
||||
|
|
@ -11,12 +11,13 @@
|
|||
namespace nix::fetchers {
|
||||
|
||||
std::shared_ptr<Registry> Registry::read(
|
||||
const Settings & settings,
|
||||
const Path & path, RegistryType type)
|
||||
{
|
||||
auto registry = std::make_shared<Registry>(type);
|
||||
auto registry = std::make_shared<Registry>(settings, type);
|
||||
|
||||
if (!pathExists(path))
|
||||
return std::make_shared<Registry>(type);
|
||||
return std::make_shared<Registry>(settings, type);
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -36,8 +37,8 @@ std::shared_ptr<Registry> Registry::read(
|
|||
auto exact = i.find("exact");
|
||||
registry->entries.push_back(
|
||||
Entry {
|
||||
.from = Input::fromAttrs(jsonToAttrs(i["from"])),
|
||||
.to = Input::fromAttrs(std::move(toAttrs)),
|
||||
.from = Input::fromAttrs(settings, jsonToAttrs(i["from"])),
|
||||
.to = Input::fromAttrs(settings, std::move(toAttrs)),
|
||||
.extraAttrs = extraAttrs,
|
||||
.exact = exact != i.end() && exact.value()
|
||||
});
|
||||
|
|
@ -106,10 +107,10 @@ static Path getSystemRegistryPath()
|
|||
return settings.nixConfDir + "/registry.json";
|
||||
}
|
||||
|
||||
static std::shared_ptr<Registry> getSystemRegistry()
|
||||
static std::shared_ptr<Registry> getSystemRegistry(const Settings & settings)
|
||||
{
|
||||
static auto systemRegistry =
|
||||
Registry::read(getSystemRegistryPath(), Registry::System);
|
||||
Registry::read(settings, getSystemRegistryPath(), Registry::System);
|
||||
return systemRegistry;
|
||||
}
|
||||
|
||||
|
|
@ -118,25 +119,24 @@ Path getUserRegistryPath()
|
|||
return getConfigDir() + "/nix/registry.json";
|
||||
}
|
||||
|
||||
std::shared_ptr<Registry> getUserRegistry()
|
||||
std::shared_ptr<Registry> getUserRegistry(const Settings & settings)
|
||||
{
|
||||
static auto userRegistry =
|
||||
Registry::read(getUserRegistryPath(), Registry::User);
|
||||
Registry::read(settings, getUserRegistryPath(), Registry::User);
|
||||
return userRegistry;
|
||||
}
|
||||
|
||||
std::shared_ptr<Registry> getCustomRegistry(const Path & p)
|
||||
std::shared_ptr<Registry> getCustomRegistry(const Settings & settings, const Path & p)
|
||||
{
|
||||
static auto customRegistry =
|
||||
Registry::read(p, Registry::Custom);
|
||||
Registry::read(settings, p, Registry::Custom);
|
||||
return customRegistry;
|
||||
}
|
||||
|
||||
static std::shared_ptr<Registry> flagRegistry =
|
||||
std::make_shared<Registry>(Registry::Flag);
|
||||
|
||||
std::shared_ptr<Registry> getFlagRegistry()
|
||||
std::shared_ptr<Registry> getFlagRegistry(const Settings & settings)
|
||||
{
|
||||
static auto flagRegistry =
|
||||
std::make_shared<Registry>(settings, Registry::Flag);
|
||||
return flagRegistry;
|
||||
}
|
||||
|
||||
|
|
@ -145,30 +145,15 @@ void overrideRegistry(
|
|||
const Input & to,
|
||||
const Attrs & extraAttrs)
|
||||
{
|
||||
flagRegistry->add(from, to, extraAttrs);
|
||||
getFlagRegistry(*from.settings)->add(from, to, extraAttrs);
|
||||
}
|
||||
|
||||
struct RegistrySettings : Config
|
||||
{
|
||||
Setting<std::string> flakeRegistry{this, "https://channels.nixos.org/flake-registry.json", "flake-registry",
|
||||
R"(
|
||||
Path or URI of the global flake registry.
|
||||
|
||||
When empty, disables the global flake registry.
|
||||
)",
|
||||
{}, true, Xp::Flakes};
|
||||
};
|
||||
|
||||
RegistrySettings registrySettings;
|
||||
|
||||
static GlobalConfig::Register rRegistrySettings(®istrySettings);
|
||||
|
||||
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
|
||||
static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, ref<Store> store)
|
||||
{
|
||||
static auto reg = [&]() {
|
||||
auto path = registrySettings.flakeRegistry.get();
|
||||
auto path = settings.flakeRegistry.get();
|
||||
if (path == "") {
|
||||
return std::make_shared<Registry>(Registry::Global); // empty registry
|
||||
return std::make_shared<Registry>(settings, Registry::Global); // empty registry
|
||||
}
|
||||
|
||||
if (!hasPrefix(path, "/")) {
|
||||
|
|
@ -178,19 +163,19 @@ static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
|
|||
path = store->toRealPath(storePath);
|
||||
}
|
||||
|
||||
return Registry::read(path, Registry::Global);
|
||||
return Registry::read(settings, path, Registry::Global);
|
||||
}();
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
Registries getRegistries(ref<Store> store)
|
||||
Registries getRegistries(const Settings & settings, ref<Store> store)
|
||||
{
|
||||
Registries registries;
|
||||
registries.push_back(getFlagRegistry());
|
||||
registries.push_back(getUserRegistry());
|
||||
registries.push_back(getSystemRegistry());
|
||||
registries.push_back(getGlobalRegistry(store));
|
||||
registries.push_back(getFlagRegistry(settings));
|
||||
registries.push_back(getUserRegistry(settings));
|
||||
registries.push_back(getSystemRegistry(settings));
|
||||
registries.push_back(getGlobalRegistry(settings, store));
|
||||
return registries;
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +192,7 @@ std::pair<Input, Attrs> lookupInRegistries(
|
|||
n++;
|
||||
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
|
||||
|
||||
for (auto & registry : getRegistries(store)) {
|
||||
for (auto & registry : getRegistries(*input.settings, store)) {
|
||||
// FIXME: O(n)
|
||||
for (auto & entry : registry->entries) {
|
||||
if (entry.exact) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ namespace nix::fetchers {
|
|||
|
||||
struct Registry
|
||||
{
|
||||
const Settings & settings;
|
||||
|
||||
enum RegistryType {
|
||||
Flag = 0,
|
||||
User = 1,
|
||||
|
|
@ -29,11 +31,13 @@ struct Registry
|
|||
|
||||
std::vector<Entry> entries;
|
||||
|
||||
Registry(RegistryType type)
|
||||
: type(type)
|
||||
Registry(const Settings & settings, RegistryType type)
|
||||
: settings{settings}
|
||||
, type{type}
|
||||
{ }
|
||||
|
||||
static std::shared_ptr<Registry> read(
|
||||
const Settings & settings,
|
||||
const Path & path, RegistryType type);
|
||||
|
||||
void write(const Path & path);
|
||||
|
|
@ -48,13 +52,13 @@ struct Registry
|
|||
|
||||
typedef std::vector<std::shared_ptr<Registry>> Registries;
|
||||
|
||||
std::shared_ptr<Registry> getUserRegistry();
|
||||
std::shared_ptr<Registry> getUserRegistry(const Settings & settings);
|
||||
|
||||
std::shared_ptr<Registry> getCustomRegistry(const Path & p);
|
||||
std::shared_ptr<Registry> getCustomRegistry(const Settings & settings, const Path & p);
|
||||
|
||||
Path getUserRegistryPath();
|
||||
|
||||
Registries getRegistries(ref<Store> store);
|
||||
Registries getRegistries(const Settings & settings, ref<Store> store);
|
||||
|
||||
void overrideRegistry(
|
||||
const Input & from,
|
||||
|
|
|
|||
|
|
@ -214,12 +214,14 @@ struct CurlInputScheme : InputScheme
|
|||
|
||||
static const std::set<std::string> specialParams;
|
||||
|
||||
std::optional<Input> inputFromURL(const ParsedURL & _url, bool requireTree) const override
|
||||
std::optional<Input> inputFromURL(
|
||||
const Settings & settings,
|
||||
const ParsedURL & _url, bool requireTree) const override
|
||||
{
|
||||
if (!isValidURL(_url, requireTree))
|
||||
return std::nullopt;
|
||||
|
||||
Input input;
|
||||
Input input{settings};
|
||||
|
||||
auto url = _url;
|
||||
|
||||
|
|
@ -267,9 +269,11 @@ struct CurlInputScheme : InputScheme
|
|||
};
|
||||
}
|
||||
|
||||
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
||||
std::optional<Input> inputFromAttrs(
|
||||
const Settings & settings,
|
||||
const Attrs & attrs) const override
|
||||
{
|
||||
Input input;
|
||||
Input input{settings};
|
||||
input.attrs = attrs;
|
||||
|
||||
//input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
|
||||
|
|
@ -349,7 +353,7 @@ struct TarballInputScheme : CurlInputScheme
|
|||
result.accessor->setPathDisplay("«" + input.to_string() + "»");
|
||||
|
||||
if (result.immutableUrl) {
|
||||
auto immutableInput = Input::fromURL(*result.immutableUrl);
|
||||
auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl);
|
||||
// FIXME: would be nice to support arbitrary flakerefs
|
||||
// here, e.g. git flakes.
|
||||
if (immutableInput.getType() != "tarball")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue