aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-03-27 14:40:36 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-03-27 14:40:36 +0100
commitc101b29133200442de05275c725c8d77aa888b27 (patch)
tree3c1f2b64cb63b1944acc0aa38433e8ec45fc4879 /src
parentbe7fd6359559717b83833d96d4b6dc38ceb83092 (diff)
parenta554f523db34a5d6a8281c5228acfc128a8bd589 (diff)
Merge remote-tracking branch 'tweag/flake-registries' into flakes
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.hh4
-rw-r--r--src/libexpr/primops/flake.cc104
-rw-r--r--src/libexpr/primops/flake.hh4
-rw-r--r--src/nix/flake.cc8
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";
+ }
}
}
};