Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libfetchers improvements without libflake #9069

Merged
merged 5 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/libexpr/flake/flakeref.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,6 @@ std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragment
return {std::move(flakeRef), fragment, std::move(extendedOutputsSpec)};
}

std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript);

}
3 changes: 3 additions & 0 deletions src/libexpr/flake/flakeref.hh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "fetchers.hh"
#include "outputs-spec.hh"

#include <regex>
#include <variant>

namespace nix {
Expand Down Expand Up @@ -91,5 +92,7 @@ std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragment
bool allowMissing = false,
bool isFlake = true);

const static std::string flakeIdRegexS = "[a-zA-Z][a-zA-Z0-9_-]*";
extern std::regex flakeIdRegex;

}
8 changes: 2 additions & 6 deletions src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ static void fetchTree(

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 });
}

Expand Down Expand Up @@ -237,12 +236,9 @@ static RegisterPrimOp primop_fetchTree({
```nix
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,
Expand Down
6 changes: 6 additions & 0 deletions src/libfetchers/attrs.hh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
namespace nix::fetchers {

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;

Attrs jsonToAttrs(const nlohmann::json & json);
Expand Down
10 changes: 9 additions & 1 deletion src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Input Input::fromURL(const ParsedURL & url, bool requireTree)
for (auto & inputScheme : *inputSchemes) {
auto res = inputScheme->inputFromURL(url, requireTree);
if (res) {
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
res->scheme = inputScheme;
fixupInput(*res);
return std::move(*res);
Expand All @@ -50,6 +51,7 @@ Input Input::fromAttrs(Attrs && attrs)
for (auto & inputScheme : *inputSchemes) {
auto res = inputScheme->inputFromAttrs(attrs);
if (res) {
experimentalFeatureSettings.require(inputScheme->experimentalFeature());
res->scheme = inputScheme;
fixupInput(*res);
return std::move(*res);
Expand Down Expand Up @@ -254,7 +256,8 @@ std::optional<Hash> Input::getRev() const
try {
hash = Hash::parseAnyPrefixed(*s);
} 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);
}
}
Expand Down Expand Up @@ -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());
}

std::optional<ExperimentalFeature> InputScheme::experimentalFeature()
{
return {};
}

}
36 changes: 25 additions & 11 deletions src/libfetchers/fetchers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ struct Tree
struct InputScheme;

/**
* The Input object is generated by a specific fetcher, based on the
* user-supplied input attribute in the flake.nix file, and contains
* The `Input` object is generated by a specific fetcher, based on
* user-supplied information, and contains
* the information that the specific fetcher needs to perform the
* actual fetch. The Input object is most commonly created via the
* "fromURL()" or "fromAttrs()" static functions which are provided
* the url or attrset specified in the flake file.
* `fromURL()` or `fromAttrs()` static functions.
*/
struct Input
{
Expand All @@ -44,10 +43,20 @@ struct Input
std::optional<Path> parent;

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 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);

ParsedURL toURL() const;
Expand Down Expand Up @@ -116,13 +125,13 @@ public:


/**
* The InputScheme represents a type of fetcher. Each fetcher
* registers with nix at startup time. When processing an input for a
* flake, each scheme is given an opportunity to "recognize" that
* input from the url or attributes in the flake file's specification
* and return an Input object to represent the input if it is
* recognized. The Input object contains the information the fetcher
* needs to actually perform the "fetch()" when called.
* The `InputScheme` represents a type of fetcher. Each fetcher
* registers with nix at startup time. When processing an `Input`,
* each scheme is given an opportunity to "recognize" that
* input from the user-provided url or attributes
* and return an `Input` object to represent the input if it is
* recognized. The `Input` object contains the information the fetcher
* needs to actually perform the `fetch()` when called.
*/
struct InputScheme
{
Expand All @@ -149,6 +158,11 @@ struct InputScheme
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;

/**
* Is this `InputScheme` part of an experimental feature?
*/
virtual std::optional<ExperimentalFeature> experimentalFeature();
};

void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
Expand Down
5 changes: 5 additions & 0 deletions src/libfetchers/indirect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ struct IndirectInputScheme : InputScheme
{
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>()); });
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/args.hh
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ struct Command : virtual public Args

static constexpr Category catDefault = 0;

virtual std::optional<ExperimentalFeature> experimentalFeature ();
virtual std::optional<ExperimentalFeature> experimentalFeature();

virtual Category category() { return catDefault; }
};
Expand Down
3 changes: 0 additions & 3 deletions src/libutil/url-parts.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,4 @@ extern std::regex revRegex;
/// A ref or revision, or a ref followed by a revision.
const static std::string refAndOrRevRegex = "(?:(" + revRegexS + ")|(?:(" + refRegexS + ")(?:/(" + revRegexS + "))?))";

const static std::string flakeIdRegexS = "[a-zA-Z][a-zA-Z0-9_-]*";
extern std::regex flakeIdRegex;

}
1 change: 0 additions & 1 deletion src/libutil/url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace nix {
std::regex refRegex(refRegexS, std::regex::ECMAScript);
std::regex badGitRefRegex(badGitRefRegexS, std::regex::ECMAScript);
std::regex revRegex(revRegexS, std::regex::ECMAScript);
std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript);

ParsedURL parseURL(const std::string & url)
{
Expand Down
Loading