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")
.arity(2)
.handler([&](std::vector<std::string> 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);
});
}

View file

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

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

View file

@ -29,16 +29,25 @@ std::shared_ptr<Registry> 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<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)
{
// 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<Registry> getFlagRegistry()
void overrideRegistry(
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)
@ -135,10 +147,11 @@ Registries getRegistries(ref<Store> store)
return registries;
}
std::shared_ptr<const Input> lookupInRegistries(
std::pair<std::shared_ptr<const Input>, Input::Attrs> lookupInRegistries(
ref<Store> store,
std::shared_ptr<const Input> input)
{
Input::Attrs extraAttrs;
int n = 0;
restart:
@ -149,10 +162,12 @@ std::shared_ptr<const Input> 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<std::string>(),
!entry.first->getRev() && input->getRev() ? input->getRev() : std::optional<Hash>());
auto from = std::get<0>(entry);
if (from->contains(*input)) {
input = std::get<1>(entry)->applyOverrides(
!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;
}
}
@ -161,7 +176,7 @@ std::shared_ptr<const Input> lookupInRegistries(
if (!input->isDirect())
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
#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::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)
: type(type)
@ -31,7 +36,8 @@ struct Registry
void add(
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);
};
@ -46,9 +52,10 @@ Registries getRegistries(ref<Store> store);
void overrideRegistry(
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,
std::shared_ptr<const Input> input);

View file

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