From d068f9ffff3d2a98e6dde0834a250e4930d44778 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Feb 2020 22:14:44 +0100 Subject: [PATCH] Restore subdir support in registries Hacky... --- src/libexpr/common-eval-args.cc | 8 ++++-- src/libexpr/flake/flakeref.cc | 3 +- src/libexpr/primops/fetchTree.cc | 2 +- src/libstore/fetchers/registry.cc | 47 ++++++++++++++++++++----------- src/libstore/fetchers/registry.hh | 19 +++++++++---- src/nix/flake.cc | 12 +++++--- 6 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/libexpr/common-eval-args.cc b/src/libexpr/common-eval-args.cc index e3135b472..1fdd4e9ec 100644 --- a/src/libexpr/common-eval-args.cc +++ b/src/libexpr/common-eval-args.cc @@ -42,9 +42,11 @@ MixEvalArgs::MixEvalArgs() .description("override a flake registry value") .arity(2) .handler([&](std::vector ss) { - fetchers::overrideRegistry( - parseFlakeRef(ss[0], absPath(".")).input, - parseFlakeRef(ss[1], absPath(".")).input); + auto from = parseFlakeRef(ss[0], absPath(".")); + auto to = parseFlakeRef(ss[1], absPath(".")); + fetchers::Input::Attrs extraAttrs; + if (to.subdir != "") extraAttrs["subdir"] = to.subdir; + fetchers::overrideRegistry(from.input, to.input, extraAttrs); }); } diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index c46661df8..b61352749 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -40,7 +40,8 @@ bool FlakeRef::operator ==(const FlakeRef & other) const FlakeRef FlakeRef::resolve(ref store) const { - return FlakeRef(lookupInRegistries(store, input), subdir); + auto [input2, extraAttrs] = lookupInRegistries(store, input); + return FlakeRef(input2, fetchers::maybeGetStrAttr(extraAttrs, "subdir").value_or(subdir)); } FlakeRef parseFlakeRef( diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 8fa1f1a11..60bd2ed11 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -36,7 +36,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V input = fetchers::inputFromURL(state.coerceToString(pos, *args[0], context, false, false)); if (!evalSettings.pureEval && !input->isDirect()) - input = lookupInRegistries(state.store, input); + input = lookupInRegistries(state.store, input).first; if (evalSettings.pureEval && !input->isImmutable()) throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input"); diff --git a/src/libstore/fetchers/registry.cc b/src/libstore/fetchers/registry.cc index 1fd42a169..ebf326bcc 100644 --- a/src/libstore/fetchers/registry.cc +++ b/src/libstore/fetchers/registry.cc @@ -29,16 +29,25 @@ std::shared_ptr Registry::read( throw Error("flake registry '%s' lacks a 'url' attribute for entry '%s'", path, i.key()); registry->entries.push_back( - {inputFromURL(i.key()), inputFromURL(url)}); + {inputFromURL(i.key()), inputFromURL(url), {}}); } } else if (version == 2) { - for (auto & i : json["flakes"]) + for (auto & i : json["flakes"]) { + auto toAttrs = jsonToAttrs(i["to"]); + Input::Attrs extraAttrs; + auto j = toAttrs.find("subdir"); + if (j != toAttrs.end()) { + extraAttrs.insert(*j); + toAttrs.erase(j); + } registry->entries.push_back( { inputFromAttrs(jsonToAttrs(i["from"])) - , inputFromAttrs(jsonToAttrs(i["to"])) + , inputFromAttrs(toAttrs) + , extraAttrs }); + } } else @@ -53,8 +62,9 @@ void Registry::write(const Path & path) nlohmann::json arr; for (auto & elem : entries) { nlohmann::json obj; - obj["from"] = attrsToJson(elem.first->toAttrs()); - obj["to"] = attrsToJson(elem.second->toAttrs()); + obj["from"] = attrsToJson(std::get<0>(elem)->toAttrs()); + obj["to"] = attrsToJson(std::get<1>(elem)->toAttrs()); + obj["to"].update(attrsToJson(std::get<2>(elem))); arr.emplace_back(std::move(obj)); } @@ -68,16 +78,17 @@ void Registry::write(const Path & path) void Registry::add( const std::shared_ptr & from, - const std::shared_ptr & to) + const std::shared_ptr & to, + const Input::Attrs & extraAttrs) { - entries.emplace_back(from, to); + entries.emplace_back(from, to, extraAttrs); } void Registry::remove(const std::shared_ptr & input) { // FIXME: use C++20 std::erase. for (auto i = entries.begin(); i != entries.end(); ) - if (*i->first == *input) + if (*std::get<0>(*i) == *input) i = entries.erase(i); else ++i; @@ -103,9 +114,10 @@ std::shared_ptr getFlagRegistry() void overrideRegistry( const std::shared_ptr & from, - const std::shared_ptr & to) + const std::shared_ptr & to, + const Input::Attrs & extraAttrs) { - flagRegistry->add(from, to); + flagRegistry->add(from, to, extraAttrs); } static std::shared_ptr getGlobalRegistry(ref store) @@ -135,10 +147,11 @@ Registries getRegistries(ref store) return registries; } -std::shared_ptr lookupInRegistries( +std::pair, Input::Attrs> lookupInRegistries( ref store, std::shared_ptr input) { + Input::Attrs extraAttrs; int n = 0; restart: @@ -149,10 +162,12 @@ std::shared_ptr lookupInRegistries( for (auto & registry : getRegistries(store)) { // FIXME: O(n) for (auto & entry : registry->entries) { - if (entry.first->contains(*input)) { - input = entry.second->applyOverrides( - !entry.first->getRef() && input->getRef() ? input->getRef() : std::optional(), - !entry.first->getRev() && input->getRev() ? input->getRev() : std::optional()); + auto from = std::get<0>(entry); + if (from->contains(*input)) { + input = std::get<1>(entry)->applyOverrides( + !from->getRef() && input->getRef() ? input->getRef() : std::optional(), + !from->getRev() && input->getRev() ? input->getRev() : std::optional()); + extraAttrs = std::get<2>(entry); goto restart; } } @@ -161,7 +176,7 @@ std::shared_ptr lookupInRegistries( if (!input->isDirect()) throw Error("cannot find flake '%s' in the flake registries", input->to_string()); - return input; + return {input, extraAttrs}; } } diff --git a/src/libstore/fetchers/registry.hh b/src/libstore/fetchers/registry.hh index e29f78486..6063f51d6 100644 --- a/src/libstore/fetchers/registry.hh +++ b/src/libstore/fetchers/registry.hh @@ -1,13 +1,12 @@ #pragma once #include "types.hh" +#include "fetchers.hh" namespace nix { class Store; } namespace nix::fetchers { -struct Input; - struct Registry { enum RegistryType { @@ -18,7 +17,13 @@ struct Registry RegistryType type; - std::vector, std::shared_ptr>> entries; + std::vector< + std::tuple< + std::shared_ptr, // from + std::shared_ptr, // to + Input::Attrs // extra attributes + > + > entries; Registry(RegistryType type) : type(type) @@ -31,7 +36,8 @@ struct Registry void add( const std::shared_ptr & from, - const std::shared_ptr & to); + const std::shared_ptr & to, + const Input::Attrs & extraAttrs); void remove(const std::shared_ptr & input); }; @@ -46,9 +52,10 @@ Registries getRegistries(ref store); void overrideRegistry( const std::shared_ptr & from, - const std::shared_ptr & to); + const std::shared_ptr & to, + const Input::Attrs & extraAttrs); -std::shared_ptr lookupInRegistries( +std::pair, Input::Attrs> lookupInRegistries( ref store, std::shared_ptr input); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 9c94c59fc..42f5b2ce0 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -70,8 +70,8 @@ struct CmdFlakeList : EvalCommand registry->type == Registry::Flag ? "flags " : registry->type == Registry::User ? "user " : "global", - entry.first->to_string(), - entry.second->to_string()); + std::get<0>(entry)->to_string(), + std::get<1>(entry)->to_string()); } } } @@ -506,9 +506,11 @@ struct CmdFlakeAdd : MixEvalArgs, Command { auto fromRef = parseFlakeRef(fromUrl); auto toRef = parseFlakeRef(toUrl); + fetchers::Input::Attrs extraAttrs; + if (toRef.subdir != "") extraAttrs["subdir"] = toRef.subdir; auto userRegistry = fetchers::getUserRegistry(); userRegistry->remove(fromRef.input); - userRegistry->add(fromRef.input, toRef.input); + userRegistry->add(fromRef.input, toRef.input, extraAttrs); userRegistry->write(fetchers::getUserRegistryPath()); } }; @@ -555,7 +557,9 @@ struct CmdFlakePin : virtual Args, EvalCommand auto userRegistry = fetchers::getUserRegistry(); userRegistry->remove(ref.input); auto [tree, resolved] = ref.resolve(store).input->fetchTree(store); - userRegistry->add(ref.input, resolved); + fetchers::Input::Attrs extraAttrs; + if (ref.subdir != "") extraAttrs["subdir"] = ref.subdir; + userRegistry->add(ref.input, resolved, extraAttrs); } };