diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2019-03-27 14:40:36 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2019-03-27 14:40:36 +0100 |
commit | c101b29133200442de05275c725c8d77aa888b27 (patch) | |
tree | 3c1f2b64cb63b1944acc0aa38433e8ec45fc4879 /src | |
parent | be7fd6359559717b83833d96d4b6dc38ceb83092 (diff) | |
parent | a554f523db34a5d6a8281c5228acfc128a8bd589 (diff) |
Merge remote-tracking branch 'tweag/flake-registries' into flakes
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.hh | 4 | ||||
-rw-r--r-- | src/libexpr/primops/flake.cc | 104 | ||||
-rw-r--r-- | src/libexpr/primops/flake.hh | 4 | ||||
-rw-r--r-- | src/nix/flake.cc | 8 |
4 files changed, 73 insertions, 47 deletions
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 95431e6a4..3f537da89 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -316,10 +316,10 @@ private: public: - const FlakeRegistry & getFlakeRegistry(); + const std::vector<std::shared_ptr<FlakeRegistry>> getFlakeRegistries(); private: - std::unique_ptr<FlakeRegistry> _flakeRegistry; + std::shared_ptr<FlakeRegistry> _flakeRegistry; std::once_flag _flakeRegistryInit; }; diff --git a/src/libexpr/primops/flake.cc b/src/libexpr/primops/flake.cc index 00eeba632..a8d46825f 100644 --- a/src/libexpr/primops/flake.cc +++ b/src/libexpr/primops/flake.cc @@ -12,16 +12,11 @@ namespace nix { -Path getUserRegistryPath() -{ - return getHome() + "/.config/nix/registry.json"; -} - /* Read the registry or a lock file. (Currently they have an identical format. */ -std::unique_ptr<FlakeRegistry> readRegistry(const Path & path) +std::shared_ptr<FlakeRegistry> readRegistry(const Path & path) { - auto registry = std::make_unique<FlakeRegistry>(); + auto registry = std::make_shared<FlakeRegistry>(); try { auto json = nlohmann::json::parse(readFile(path)); @@ -55,37 +50,71 @@ void writeRegistry(FlakeRegistry registry, Path path) writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file. } -const FlakeRegistry & EvalState::getFlakeRegistry() +Path getUserRegistryPath() { - std::call_once(_flakeRegistryInit, [&]() - { -#if 0 - auto registryUri = "file:///home/eelco/Dev/gists/nix-flakes/registry.json"; + return getHome() + "/.config/nix/registry.json"; +} + +std::shared_ptr<FlakeRegistry> getGlobalRegistry() +{ + // TODO: Make a global registry, and return it here. + return std::make_shared<FlakeRegistry>(); +} - auto registryFile = getDownloader()->download(DownloadRequest(registryUri)); -#endif +std::shared_ptr<FlakeRegistry> getUserRegistry() +{ + return readRegistry(getUserRegistryPath()); +} - auto registryFile = settings.nixDataDir + "/nix/flake-registry.json"; +// Project-specific registry saved in flake-registry.json. +std::shared_ptr<FlakeRegistry> getLocalRegistry() +{ + Path registryFile = settings.nixDataDir + "/nix/flake-registry.json"; + return readRegistry(registryFile); +} - _flakeRegistry = readRegistry(registryFile); - }); +std::shared_ptr<FlakeRegistry> getFlagRegistry() +{ + return std::make_shared<FlakeRegistry>(); + // TODO: Implement this once the right flags are implemented. +} - return *_flakeRegistry; +// This always returns a vector with globalReg, userReg, localReg, flakeReg. +// If one of them doesn't exist, the registry is left empty but does exist. +const std::vector<std::shared_ptr<FlakeRegistry>> EvalState::getFlakeRegistries() +{ + std::vector<std::shared_ptr<FlakeRegistry>> registries; + if (!evalSettings.pureEval) { + registries.push_back(std::make_shared<FlakeRegistry>()); // global + registries.push_back(std::make_shared<FlakeRegistry>()); // user + registries.push_back(std::make_shared<FlakeRegistry>()); // local + } else { + registries.push_back(getGlobalRegistry()); + registries.push_back(getUserRegistry()); + registries.push_back(getLocalRegistry()); + } + registries.push_back(getFlagRegistry()); + return registries; } Value * makeFlakeRegistryValue(EvalState & state) { auto v = state.allocValue(); - auto registry = state.getFlakeRegistry(); + auto registries = state.getFlakeRegistries(); - state.mkAttrs(*v, registry.entries.size()); + int size = 0; + for (auto registry : registries) + size += registry->entries.size(); + state.mkAttrs(*v, size); - for (auto & entry : registry.entries) { - auto vEntry = state.allocAttr(*v, entry.first); - state.mkAttrs(*vEntry, 2); - mkString(*state.allocAttr(*vEntry, state.symbols.create("uri")), entry.second.ref.to_string()); - vEntry->attrs->sort(); + for (auto & registry : registries) { + for (auto & entry : registry->entries) { + auto vEntry = state.allocAttr(*v, entry.first); + state.mkAttrs(*vEntry, 2); + mkString(*state.allocAttr(*vEntry, state.symbols.create("uri")), entry.second.ref.to_string()); + vEntry->attrs->sort(); + } } v->attrs->sort(); @@ -94,7 +123,7 @@ Value * makeFlakeRegistryValue(EvalState & state) } static FlakeRef lookupFlake(EvalState & state, const FlakeRef & flakeRef, - std::vector<const FlakeRegistry *> registries) + std::vector<std::shared_ptr<FlakeRegistry>> registries) { if (auto refData = std::get_if<FlakeRef::IsFlakeId>(&flakeRef.data)) { for (auto registry : registries) { @@ -122,13 +151,7 @@ static FlakeSourceInfo fetchFlake(EvalState & state, const FlakeRef & flakeRef) FlakeRef directFlakeRef = FlakeRef(flakeRef); if (!flakeRef.isDirect()) { - std::vector<const FlakeRegistry *> registries; - // 'pureEval' is a setting which cannot be changed in `nix flake`, - // but without flagging it off, we can't use any FlakeIds. - // if (!evalSettings.pureEval) { - registries.push_back(&state.getFlakeRegistry()); - // } - directFlakeRef = lookupFlake(state, flakeRef, registries); + directFlakeRef = lookupFlake(state, flakeRef, state.getFlakeRegistries()); } assert(directFlakeRef.isDirect()); // NOTE FROM NICK: I don't see why one wouldn't fetch FlakeId flakes.. @@ -251,11 +274,8 @@ static std::tuple<FlakeId, std::map<FlakeId, Flake>> resolveFlake(EvalState & st std::optional<FlakeId> topFlakeId; /// FIXME: ambiguous todo.push({topRef, true}); - std::vector<const FlakeRegistry *> registries; - FlakeRegistry localRegistry; - registries.push_back(&localRegistry); - if (!evalSettings.pureEval) - registries.push_back(&state.getFlakeRegistry()); + std::vector<std::shared_ptr<FlakeRegistry>> registries = state.getFlakeRegistries(); + std::shared_ptr<FlakeRegistry> localRegistry = registries.at(2); while (!todo.empty()) { auto [flakeRef, toplevel] = todo.front(); @@ -264,6 +284,7 @@ static std::tuple<FlakeId, std::map<FlakeId, Flake>> resolveFlake(EvalState & st if (auto refData = std::get_if<FlakeRef::IsFlakeId>(&flakeRef.data)) { if (done.count(refData->id)) continue; // optimization flakeRef = lookupFlake(state, flakeRef, registries); + // This is why we need the `registries`. } if (evalSettings.pureEval && !flakeRef.isImmutable() && (!toplevel || !impureTopRef)) @@ -278,10 +299,13 @@ static std::tuple<FlakeId, std::map<FlakeId, Flake>> resolveFlake(EvalState & st for (auto & require : flake.requires) todo.push({require, false}); + // The following piece of code basically adds the FlakeRefs from + // the lockfiles of dependencies to the localRegistry. This is used + // to resolve future `FlakeId`s, in `lookupFlake` a bit above this. if (flake.lockFile) for (auto & entry : flake.lockFile->entries) { - if (localRegistry.entries.count(entry.first)) continue; - localRegistry.entries.emplace(entry.first, entry.second); + if (localRegistry->entries.count(entry.first)) continue; + localRegistry->entries.emplace(entry.first, entry.second); } done.emplace(flake.id, std::move(flake)); diff --git a/src/libexpr/primops/flake.hh b/src/libexpr/primops/flake.hh index 4e49becc7..53cea1cc2 100644 --- a/src/libexpr/primops/flake.hh +++ b/src/libexpr/primops/flake.hh @@ -25,7 +25,7 @@ Value * makeFlakeRegistryValue(EvalState & state); Value * makeFlakeValue(EvalState & state, std::string flakeUri, Value & v); -std::unique_ptr<FlakeRegistry> readRegistry(const Path &); +std::shared_ptr<FlakeRegistry> readRegistry(const Path &); void writeRegistry(FlakeRegistry, Path); @@ -36,7 +36,7 @@ struct Flake std::string description; Path path; std::vector<FlakeRef> requires; - std::unique_ptr<FlakeRegistry> lockFile; + std::shared_ptr<FlakeRegistry> lockFile; Value * vProvides; // FIXME: gc // commit hash // date diff --git a/src/nix/flake.cc b/src/nix/flake.cc index fda903944..470dfdc08 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -24,12 +24,14 @@ struct CmdFlakeList : StoreCommand, MixEvalArgs { auto evalState = std::make_shared<EvalState>(searchPath, store); - auto registry = evalState->getFlakeRegistry(); + auto registries = evalState->getFlakeRegistries(); stopProgressBar(); - for (auto & entry : registry.entries) { - std::cout << entry.first << " " << entry.second.ref.to_string() << "\n"; + for (auto & registry : registries) { + for (auto & entry : registry->entries) { + std::cout << entry.first << " " << entry.second.ref.to_string() << "\n"; + } } } }; |