aboutsummaryrefslogtreecommitdiff
path: root/src/libfetchers/indirect.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-05-30 00:44:11 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-05-30 00:44:11 +0200
commit950b46821f644eb3f92725460584a3102f356179 (patch)
tree0916b068dad6c03dfb81a80dd51b199464376bf4 /src/libfetchers/indirect.cc
parent5633c0975b9dec6bceaa85003223a346d7d1bd0b (diff)
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount, lastModified) are now stored in Input. This makes it less arbitrary what attributes are stored where. As a result, the lock file format has changed. An entry like "info": { "lastModified": 1585405475, "narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE=" }, "locked": { "owner": "NixOS", "repo": "nixpkgs", "rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be", "type": "github" }, is now stored as "locked": { "owner": "NixOS", "repo": "nixpkgs", "rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be", "type": "github", "lastModified": 1585405475, "narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE=" }, The 'Input' class is now a dumb set of attributes. All the fetcher implementations subclass InputScheme, not Input. This simplifies the API. Also, fix substitution of flake inputs. This was broken since lazy flake fetching started using fetchTree internally.
Diffstat (limited to 'src/libfetchers/indirect.cc')
-rw-r--r--src/libfetchers/indirect.cc154
1 files changed, 59 insertions, 95 deletions
diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc
index 380b69fe0..91dc83740 100644
--- a/src/libfetchers/indirect.cc
+++ b/src/libfetchers/indirect.cc
@@ -4,135 +4,99 @@ namespace nix::fetchers {
std::regex flakeRegex("[a-zA-Z][a-zA-Z0-9_-]*", std::regex::ECMAScript);
-struct IndirectInput : Input
-{
- std::string id;
- std::optional<Hash> rev;
- std::optional<std::string> ref;
-
- std::string type() const override { return "indirect"; }
-
- bool operator ==(const Input & other) const override
- {
- auto other2 = dynamic_cast<const IndirectInput *>(&other);
- return
- other2
- && id == other2->id
- && rev == other2->rev
- && ref == other2->ref;
- }
-
- bool isDirect() const override
- {
- return false;
- }
-
- std::optional<std::string> getRef() const override { return ref; }
-
- std::optional<Hash> getRev() const override { return rev; }
-
- bool contains(const Input & other) const override
- {
- auto other2 = dynamic_cast<const IndirectInput *>(&other);
- return
- other2
- && id == other2->id
- && (!ref || ref == other2->ref)
- && (!rev || rev == other2->rev);
- }
-
- ParsedURL toURL() const override
- {
- ParsedURL url;
- url.scheme = "flake";
- url.path = id;
- if (ref) { url.path += '/'; url.path += *ref; };
- if (rev) { url.path += '/'; url.path += rev->gitRev(); };
- return url;
- }
-
- Attrs toAttrsInternal() const override
- {
- Attrs attrs;
- attrs.emplace("id", id);
- if (ref)
- attrs.emplace("ref", *ref);
- if (rev)
- attrs.emplace("rev", rev->gitRev());
- return attrs;
- }
-
- std::shared_ptr<const Input> applyOverrides(
- std::optional<std::string> ref,
- std::optional<Hash> rev) const override
- {
- if (!ref && !rev) return shared_from_this();
-
- auto res = std::make_shared<IndirectInput>(*this);
-
- if (ref) res->ref = ref;
- if (rev) res->rev = rev;
-
- return res;
- }
-
- std::pair<Tree, std::shared_ptr<const Input>> fetchTreeInternal(nix::ref<Store> store) const override
- {
- throw Error("indirect input '%s' cannot be fetched directly", to_string());
- }
-};
-
struct IndirectInputScheme : InputScheme
{
- std::unique_ptr<Input> inputFromURL(const ParsedURL & url) override
+ std::optional<Input> inputFromURL(const ParsedURL & url) override
{
- if (url.scheme != "flake") return nullptr;
+ if (url.scheme != "flake") return {};
auto path = tokenizeString<std::vector<std::string>>(url.path, "/");
- auto input = std::make_unique<IndirectInput>();
+
+ 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))
- input->rev = Hash(path[1], htSHA1);
+ rev = Hash(path[1], htSHA1);
else if (std::regex_match(path[1], refRegex))
- input->ref = path[1];
+ 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]);
- input->ref = 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]);
- input->rev = Hash(path[2], htSHA1);
+ rev = Hash(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->id = path[0];
- if (!std::regex_match(input->id, flakeRegex))
- throw BadURL("'%s' is not a valid flake ID", input->id);
+ 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::unique_ptr<Input> inputFromAttrs(const Attrs & attrs) override
+ std::optional<Input> inputFromAttrs(const Attrs & attrs) override
{
if (maybeGetStrAttr(attrs, "type") != "indirect") return {};
for (auto & [name, value] : attrs)
- if (name != "type" && name != "id" && name != "ref" && name != "rev")
+ if (name != "type" && name != "id" && name != "ref" && name != "rev" && name != "narHash")
throw Error("unsupported indirect input attribute '%s'", name);
- auto input = std::make_unique<IndirectInput>();
- input->id = getStrAttr(attrs, "id");
- input->ref = maybeGetStrAttr(attrs, "ref");
- if (auto rev = maybeGetStrAttr(attrs, "rev"))
- input->rev = Hash(*rev, htSHA1);
+ 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) 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) override
+ {
+ return false;
+ }
+
+ Input applyOverrides(
+ const Input & _input,
+ std::optional<std::string> ref,
+ std::optional<Hash> rev) 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<Tree, Input> fetch(ref<Store> store, const Input & input) override
+ {
+ throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
+ }
};
static auto r1 = OnStartup([] { registerInputScheme(std::make_unique<IndirectInputScheme>()); });