forked from lix-project/lix
Merge pull request #9069 from obsidiansystems/libfetchers-prep-0
`libfetchers` improvements without `libflake`
This commit is contained in:
commit
461902b860
|
@ -289,4 +289,6 @@ std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragment
|
||||||
return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)};
|
return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "outputs-spec.hh"
|
#include "outputs-spec.hh"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -91,5 +92,7 @@ std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragment
|
||||||
bool allowMissing = false,
|
bool allowMissing = false,
|
||||||
bool isFlake = true);
|
bool isFlake = true);
|
||||||
|
|
||||||
|
const static std::string flakeIdRegexS = "[a-zA-Z][a-zA-Z0-9_-]*";
|
||||||
|
extern std::regex flakeIdRegex;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,6 @@ static void fetchTree(
|
||||||
|
|
||||||
static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
experimentalFeatureSettings.require(Xp::Flakes);
|
|
||||||
fetchTree(state, pos, args, v, std::nullopt, FetchTreeParams { .allowNameArgument = false });
|
fetchTree(state, pos, args, v, std::nullopt, FetchTreeParams { .allowNameArgument = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,12 +236,9 @@ static RegisterPrimOp primop_fetchTree({
|
||||||
```nix
|
```nix
|
||||||
builtins.fetchTree "https://example.com/"
|
builtins.fetchTree "https://example.com/"
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> This function requires the [`flakes` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-flakes) to be enabled.
|
|
||||||
)",
|
)",
|
||||||
.fun = prim_fetchTree
|
.fun = prim_fetchTree,
|
||||||
|
.experimentalFeature = Xp::Flakes,
|
||||||
});
|
});
|
||||||
|
|
||||||
static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v,
|
static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v,
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
namespace nix::fetchers {
|
namespace nix::fetchers {
|
||||||
|
|
||||||
typedef std::variant<std::string, uint64_t, Explicit<bool>> Attr;
|
typedef std::variant<std::string, uint64_t, Explicit<bool>> Attr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An `Attrs` can be thought of a JSON object restricted or simplified
|
||||||
|
* to be "flat", not containing any subcontainers (arrays or objects)
|
||||||
|
* and also not containing any `null`s.
|
||||||
|
*/
|
||||||
typedef std::map<std::string, Attr> Attrs;
|
typedef std::map<std::string, Attr> Attrs;
|
||||||
|
|
||||||
Attrs jsonToAttrs(const nlohmann::json & json);
|
Attrs jsonToAttrs(const nlohmann::json & json);
|
||||||
|
|
|
@ -36,6 +36,7 @@ Input Input::fromURL(const ParsedURL & url, bool requireTree)
|
||||||
for (auto & inputScheme : *inputSchemes) {
|
for (auto & inputScheme : *inputSchemes) {
|
||||||
auto res = inputScheme->inputFromURL(url, requireTree);
|
auto res = inputScheme->inputFromURL(url, requireTree);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
|
||||||
res->scheme = inputScheme;
|
res->scheme = inputScheme;
|
||||||
fixupInput(*res);
|
fixupInput(*res);
|
||||||
return std::move(*res);
|
return std::move(*res);
|
||||||
|
@ -50,6 +51,7 @@ Input Input::fromAttrs(Attrs && attrs)
|
||||||
for (auto & inputScheme : *inputSchemes) {
|
for (auto & inputScheme : *inputSchemes) {
|
||||||
auto res = inputScheme->inputFromAttrs(attrs);
|
auto res = inputScheme->inputFromAttrs(attrs);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
|
||||||
res->scheme = inputScheme;
|
res->scheme = inputScheme;
|
||||||
fixupInput(*res);
|
fixupInput(*res);
|
||||||
return std::move(*res);
|
return std::move(*res);
|
||||||
|
@ -254,7 +256,8 @@ std::optional<Hash> Input::getRev() const
|
||||||
try {
|
try {
|
||||||
hash = Hash::parseAnyPrefixed(*s);
|
hash = Hash::parseAnyPrefixed(*s);
|
||||||
} catch (BadHash &e) {
|
} catch (BadHash &e) {
|
||||||
// Default to sha1 for backwards compatibility with existing flakes
|
// Default to sha1 for backwards compatibility with existing
|
||||||
|
// usages (e.g. `builtins.fetchTree` calls or flake inputs).
|
||||||
hash = Hash::parseAny(*s, htSHA1);
|
hash = Hash::parseAny(*s, htSHA1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,4 +311,9 @@ void InputScheme::clone(const Input & input, const Path & destDir) const
|
||||||
throw Error("do not know how to clone input '%s'", input.to_string());
|
throw Error("do not know how to clone input '%s'", input.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ExperimentalFeature> InputScheme::experimentalFeature()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,11 @@ struct Tree
|
||||||
struct InputScheme;
|
struct InputScheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Input object is generated by a specific fetcher, based on the
|
* The `Input` object is generated by a specific fetcher, based on
|
||||||
* user-supplied input attribute in the flake.nix file, and contains
|
* user-supplied information, and contains
|
||||||
* the information that the specific fetcher needs to perform the
|
* the information that the specific fetcher needs to perform the
|
||||||
* actual fetch. The Input object is most commonly created via the
|
* actual fetch. The Input object is most commonly created via the
|
||||||
* "fromURL()" or "fromAttrs()" static functions which are provided
|
* `fromURL()` or `fromAttrs()` static functions.
|
||||||
* the url or attrset specified in the flake file.
|
|
||||||
*/
|
*/
|
||||||
struct Input
|
struct Input
|
||||||
{
|
{
|
||||||
|
@ -44,10 +43,20 @@ struct Input
|
||||||
std::optional<Path> parent;
|
std::optional<Path> parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Create an `Input` from a URL.
|
||||||
|
*
|
||||||
|
* 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 std::string & url, bool requireTree = true);
|
||||||
|
|
||||||
static Input fromURL(const ParsedURL & url, bool requireTree = true);
|
static Input fromURL(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(Attrs && attrs);
|
||||||
|
|
||||||
ParsedURL toURL() const;
|
ParsedURL toURL() const;
|
||||||
|
@ -116,13 +125,13 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The InputScheme represents a type of fetcher. Each fetcher
|
* The `InputScheme` represents a type of fetcher. Each fetcher
|
||||||
* registers with nix at startup time. When processing an input for a
|
* registers with nix at startup time. When processing an `Input`,
|
||||||
* flake, each scheme is given an opportunity to "recognize" that
|
* each scheme is given an opportunity to "recognize" that
|
||||||
* input from the url or attributes in the flake file's specification
|
* input from the user-provided url or attributes
|
||||||
* and return an Input object to represent the input if it is
|
* and return an `Input` object to represent the input if it is
|
||||||
* recognized. The Input object contains the information the fetcher
|
* recognized. The `Input` object contains the information the fetcher
|
||||||
* needs to actually perform the "fetch()" when called.
|
* needs to actually perform the `fetch()` when called.
|
||||||
*/
|
*/
|
||||||
struct InputScheme
|
struct InputScheme
|
||||||
{
|
{
|
||||||
|
@ -149,6 +158,11 @@ struct InputScheme
|
||||||
virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
|
virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
|
||||||
|
|
||||||
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
|
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this `InputScheme` part of an experimental feature?
|
||||||
|
*/
|
||||||
|
virtual std::optional<ExperimentalFeature> experimentalFeature();
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
||||||
|
|
|
@ -98,6 +98,11 @@ struct IndirectInputScheme : InputScheme
|
||||||
{
|
{
|
||||||
throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
|
throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ExperimentalFeature> experimentalFeature() override
|
||||||
|
{
|
||||||
|
return Xp::Flakes;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto rIndirectInputScheme = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });
|
static auto rIndirectInputScheme = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });
|
||||||
|
|
|
@ -236,7 +236,7 @@ struct Command : virtual public Args
|
||||||
|
|
||||||
static constexpr Category catDefault = 0;
|
static constexpr Category catDefault = 0;
|
||||||
|
|
||||||
virtual std::optional<ExperimentalFeature> experimentalFeature ();
|
virtual std::optional<ExperimentalFeature> experimentalFeature();
|
||||||
|
|
||||||
virtual Category category() { return catDefault; }
|
virtual Category category() { return catDefault; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,4 @@ extern std::regex revRegex;
|
||||||
/// A ref or revision, or a ref followed by a revision.
|
/// A ref or revision, or a ref followed by a revision.
|
||||||
const static std::string refAndOrRevRegex = "(?:(" + revRegexS + ")|(?:(" + refRegexS + ")(?:/(" + revRegexS + "))?))";
|
const static std::string refAndOrRevRegex = "(?:(" + revRegexS + ")|(?:(" + refRegexS + ")(?:/(" + revRegexS + "))?))";
|
||||||
|
|
||||||
const static std::string flakeIdRegexS = "[a-zA-Z][a-zA-Z0-9_-]*";
|
|
||||||
extern std::regex flakeIdRegex;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ namespace nix {
|
||||||
std::regex refRegex(refRegexS, std::regex::ECMAScript);
|
std::regex refRegex(refRegexS, std::regex::ECMAScript);
|
||||||
std::regex badGitRefRegex(badGitRefRegexS, std::regex::ECMAScript);
|
std::regex badGitRefRegex(badGitRefRegexS, std::regex::ECMAScript);
|
||||||
std::regex revRegex(revRegexS, std::regex::ECMAScript);
|
std::regex revRegex(revRegexS, std::regex::ECMAScript);
|
||||||
std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript);
|
|
||||||
|
|
||||||
ParsedURL parseURL(const std::string & url)
|
ParsedURL parseURL(const std::string & url)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue