Restore subdir support in registries

Hacky...
This commit is contained in:
Eelco Dolstra 2020-02-20 22:14:44 +01:00
parent 890df325c7
commit d068f9ffff
6 changed files with 60 additions and 31 deletions

View file

@ -42,9 +42,11 @@ MixEvalArgs::MixEvalArgs()
.description("override a flake registry value") .description("override a flake registry value")
.arity(2) .arity(2)
.handler([&](std::vector<std::string> ss) { .handler([&](std::vector<std::string> ss) {
fetchers::overrideRegistry( auto from = parseFlakeRef(ss[0], absPath("."));
parseFlakeRef(ss[0], absPath(".")).input, auto to = parseFlakeRef(ss[1], absPath("."));
parseFlakeRef(ss[1], absPath(".")).input); fetchers::Input::Attrs extraAttrs;
if (to.subdir != "") extraAttrs["subdir"] = to.subdir;
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
}); });
} }

View file

@ -40,7 +40,8 @@ bool FlakeRef::operator ==(const FlakeRef & other) const
FlakeRef FlakeRef::resolve(ref<Store> store) const FlakeRef FlakeRef::resolve(ref<Store> 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( FlakeRef parseFlakeRef(

View file

@ -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)); input = fetchers::inputFromURL(state.coerceToString(pos, *args[0], context, false, false));
if (!evalSettings.pureEval && !input->isDirect()) if (!evalSettings.pureEval && !input->isDirect())
input = lookupInRegistries(state.store, input); input = lookupInRegistries(state.store, input).first;
if (evalSettings.pureEval && !input->isImmutable()) if (evalSettings.pureEval && !input->isImmutable())
throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input"); throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input");

View file

@ -29,16 +29,25 @@ std::shared_ptr<Registry> Registry::read(
throw Error("flake registry '%s' lacks a 'url' attribute for entry '%s'", throw Error("flake registry '%s' lacks a 'url' attribute for entry '%s'",
path, i.key()); path, i.key());
registry->entries.push_back( registry->entries.push_back(
{inputFromURL(i.key()), inputFromURL(url)}); {inputFromURL(i.key()), inputFromURL(url), {}});
} }
} }
else if (version == 2) { 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( registry->entries.push_back(
{ inputFromAttrs(jsonToAttrs(i["from"])) { inputFromAttrs(jsonToAttrs(i["from"]))
, inputFromAttrs(jsonToAttrs(i["to"])) , inputFromAttrs(toAttrs)
, extraAttrs
}); });
}
} }
else else
@ -53,8 +62,9 @@ void Registry::write(const Path & path)
nlohmann::json arr; nlohmann::json arr;
for (auto & elem : entries) { for (auto & elem : entries) {
nlohmann::json obj; nlohmann::json obj;
obj["from"] = attrsToJson(elem.first->toAttrs()); obj["from"] = attrsToJson(std::get<0>(elem)->toAttrs());
obj["to"] = attrsToJson(elem.second->toAttrs()); obj["to"] = attrsToJson(std::get<1>(elem)->toAttrs());
obj["to"].update(attrsToJson(std::get<2>(elem)));
arr.emplace_back(std::move(obj)); arr.emplace_back(std::move(obj));
} }
@ -68,16 +78,17 @@ void Registry::write(const Path & path)
void Registry::add( void Registry::add(
const std::shared_ptr<const Input> & from, const std::shared_ptr<const Input> & from,
const std::shared_ptr<const Input> & to) const std::shared_ptr<const Input> & to,
const Input::Attrs & extraAttrs)
{ {
entries.emplace_back(from, to); entries.emplace_back(from, to, extraAttrs);
} }
void Registry::remove(const std::shared_ptr<const Input> & input) void Registry::remove(const std::shared_ptr<const Input> & input)
{ {
// FIXME: use C++20 std::erase. // FIXME: use C++20 std::erase.
for (auto i = entries.begin(); i != entries.end(); ) for (auto i = entries.begin(); i != entries.end(); )
if (*i->first == *input) if (*std::get<0>(*i) == *input)
i = entries.erase(i); i = entries.erase(i);
else else
++i; ++i;
@ -103,9 +114,10 @@ std::shared_ptr<Registry> getFlagRegistry()
void overrideRegistry( void overrideRegistry(
const std::shared_ptr<const Input> & from, const std::shared_ptr<const Input> & from,
const std::shared_ptr<const Input> & to) const std::shared_ptr<const Input> & to,
const Input::Attrs & extraAttrs)
{ {
flagRegistry->add(from, to); flagRegistry->add(from, to, extraAttrs);
} }
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store) static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
@ -135,10 +147,11 @@ Registries getRegistries(ref<Store> store)
return registries; return registries;
} }
std::shared_ptr<const Input> lookupInRegistries( std::pair<std::shared_ptr<const Input>, Input::Attrs> lookupInRegistries(
ref<Store> store, ref<Store> store,
std::shared_ptr<const Input> input) std::shared_ptr<const Input> input)
{ {
Input::Attrs extraAttrs;
int n = 0; int n = 0;
restart: restart:
@ -149,10 +162,12 @@ std::shared_ptr<const Input> lookupInRegistries(
for (auto & registry : getRegistries(store)) { for (auto & registry : getRegistries(store)) {
// FIXME: O(n) // FIXME: O(n)
for (auto & entry : registry->entries) { for (auto & entry : registry->entries) {
if (entry.first->contains(*input)) { auto from = std::get<0>(entry);
input = entry.second->applyOverrides( if (from->contains(*input)) {
!entry.first->getRef() && input->getRef() ? input->getRef() : std::optional<std::string>(), input = std::get<1>(entry)->applyOverrides(
!entry.first->getRev() && input->getRev() ? input->getRev() : std::optional<Hash>()); !from->getRef() && input->getRef() ? input->getRef() : std::optional<std::string>(),
!from->getRev() && input->getRev() ? input->getRev() : std::optional<Hash>());
extraAttrs = std::get<2>(entry);
goto restart; goto restart;
} }
} }
@ -161,7 +176,7 @@ std::shared_ptr<const Input> lookupInRegistries(
if (!input->isDirect()) if (!input->isDirect())
throw Error("cannot find flake '%s' in the flake registries", input->to_string()); throw Error("cannot find flake '%s' in the flake registries", input->to_string());
return input; return {input, extraAttrs};
} }
} }

View file

@ -1,13 +1,12 @@
#pragma once #pragma once
#include "types.hh" #include "types.hh"
#include "fetchers.hh"
namespace nix { class Store; } namespace nix { class Store; }
namespace nix::fetchers { namespace nix::fetchers {
struct Input;
struct Registry struct Registry
{ {
enum RegistryType { enum RegistryType {
@ -18,7 +17,13 @@ struct Registry
RegistryType type; RegistryType type;
std::vector<std::pair<std::shared_ptr<const Input>, std::shared_ptr<const Input>>> entries; std::vector<
std::tuple<
std::shared_ptr<const Input>, // from
std::shared_ptr<const Input>, // to
Input::Attrs // extra attributes
>
> entries;
Registry(RegistryType type) Registry(RegistryType type)
: type(type) : type(type)
@ -31,7 +36,8 @@ struct Registry
void add( void add(
const std::shared_ptr<const Input> & from, const std::shared_ptr<const Input> & from,
const std::shared_ptr<const Input> & to); const std::shared_ptr<const Input> & to,
const Input::Attrs & extraAttrs);
void remove(const std::shared_ptr<const Input> & input); void remove(const std::shared_ptr<const Input> & input);
}; };
@ -46,9 +52,10 @@ Registries getRegistries(ref<Store> store);
void overrideRegistry( void overrideRegistry(
const std::shared_ptr<const Input> & from, const std::shared_ptr<const Input> & from,
const std::shared_ptr<const Input> & to); const std::shared_ptr<const Input> & to,
const Input::Attrs & extraAttrs);
std::shared_ptr<const Input> lookupInRegistries( std::pair<std::shared_ptr<const Input>, Input::Attrs> lookupInRegistries(
ref<Store> store, ref<Store> store,
std::shared_ptr<const Input> input); std::shared_ptr<const Input> input);

View file

@ -70,8 +70,8 @@ struct CmdFlakeList : EvalCommand
registry->type == Registry::Flag ? "flags " : registry->type == Registry::Flag ? "flags " :
registry->type == Registry::User ? "user " : registry->type == Registry::User ? "user " :
"global", "global",
entry.first->to_string(), std::get<0>(entry)->to_string(),
entry.second->to_string()); std::get<1>(entry)->to_string());
} }
} }
} }
@ -506,9 +506,11 @@ struct CmdFlakeAdd : MixEvalArgs, Command
{ {
auto fromRef = parseFlakeRef(fromUrl); auto fromRef = parseFlakeRef(fromUrl);
auto toRef = parseFlakeRef(toUrl); auto toRef = parseFlakeRef(toUrl);
fetchers::Input::Attrs extraAttrs;
if (toRef.subdir != "") extraAttrs["subdir"] = toRef.subdir;
auto userRegistry = fetchers::getUserRegistry(); auto userRegistry = fetchers::getUserRegistry();
userRegistry->remove(fromRef.input); userRegistry->remove(fromRef.input);
userRegistry->add(fromRef.input, toRef.input); userRegistry->add(fromRef.input, toRef.input, extraAttrs);
userRegistry->write(fetchers::getUserRegistryPath()); userRegistry->write(fetchers::getUserRegistryPath());
} }
}; };
@ -555,7 +557,9 @@ struct CmdFlakePin : virtual Args, EvalCommand
auto userRegistry = fetchers::getUserRegistry(); auto userRegistry = fetchers::getUserRegistry();
userRegistry->remove(ref.input); userRegistry->remove(ref.input);
auto [tree, resolved] = ref.resolve(store).input->fetchTree(store); 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);
} }
}; };