aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-06-04 20:01:21 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-06-04 20:01:21 +0200
commit9e99b5205c4035753106448241ae44e7447f019c (patch)
treea73cbbbc815f940bae5a2bbfc25aaab4c4e8474e /src/libexpr/primops
parent278114d559109199ff8e6f23b6700ab7909f5320 (diff)
Move LockFile and related types to a separate file
Diffstat (limited to 'src/libexpr/primops')
-rw-r--r--src/libexpr/primops/flake.cc103
-rw-r--r--src/libexpr/primops/flake.hh85
-rw-r--r--src/libexpr/primops/lockfile.cc104
-rw-r--r--src/libexpr/primops/lockfile.hh110
4 files changed, 218 insertions, 184 deletions
diff --git a/src/libexpr/primops/flake.cc b/src/libexpr/primops/flake.cc
index d0405a377..b38971c36 100644
--- a/src/libexpr/primops/flake.cc
+++ b/src/libexpr/primops/flake.cc
@@ -1,4 +1,5 @@
#include "flake.hh"
+#include "lockfile.hh"
#include "primops.hh"
#include "eval-inline.hh"
#include "fetchGit.hh"
@@ -50,104 +51,6 @@ void writeRegistry(const FlakeRegistry & registry, const Path & path)
writeFile(path, json.dump(4)); // The '4' is the number of spaces used in the indentation in the json file.
}
-AbstractDep::AbstractDep(const nlohmann::json & json)
- : ref(json["uri"])
- , narHash(Hash((std::string) json["narHash"]))
-{
- if (!ref.isImmutable())
- throw Error("lockfile contains mutable flakeref '%s'", ref);
-}
-
-nlohmann::json AbstractDep::toJson() const
-{
- nlohmann::json json;
- json["uri"] = ref.to_string();
- json["narHash"] = narHash.to_string(SRI);
- return json;
-}
-
-Path AbstractDep::computeStorePath(Store & store) const
-{
- return store.makeFixedOutputPath(true, narHash, "source");
-}
-
-FlakeDep::FlakeDep(const nlohmann::json & json)
- : FlakeInputs(json)
- , AbstractDep(json)
- , id(json["id"])
-{
-}
-
-nlohmann::json FlakeDep::toJson() const
-{
- auto json = FlakeInputs::toJson();
- json.update(AbstractDep::toJson());
- json["id"] = id;
- return json;
-}
-
-FlakeInputs::FlakeInputs(const nlohmann::json & json)
-{
- auto nonFlakeInputs = json["nonFlakeInputs"];
- for (auto i = nonFlakeInputs.begin(); i != nonFlakeInputs.end(); ++i)
- nonFlakeDeps.insert_or_assign(i.key(), NonFlakeDep(*i));
-
- auto inputs = json["inputs"];
- for (auto i = inputs.begin(); i != inputs.end(); ++i)
- flakeDeps.insert_or_assign(i.key(), FlakeDep(*i));
-}
-
-nlohmann::json FlakeInputs::toJson() const
-{
- nlohmann::json json;
- {
- auto j = nlohmann::json::object();
- for (auto & i : nonFlakeDeps)
- j[i.first] = i.second.toJson();
- json["nonFlakeInputs"] = std::move(j);
- }
- {
- auto j = nlohmann::json::object();
- for (auto & i : flakeDeps)
- j[i.first.to_string()] = i.second.toJson();
- json["inputs"] = std::move(j);
- }
- return json;
-}
-
-nlohmann::json LockFile::toJson() const
-{
- auto json = FlakeInputs::toJson();
- json["version"] = 2;
- return json;
-}
-
-LockFile readLockFile(const Path & path)
-{
- if (pathExists(path)) {
- auto json = nlohmann::json::parse(readFile(path));
-
- auto version = json.value("version", 0);
- if (version != 2)
- throw Error("lock file '%s' has unsupported version %d", path, version);
-
- return LockFile(json);
- } else
- return LockFile();
-}
-
-std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile)
-{
- stream << lockFile.toJson().dump(4); // '4' = indentation in json file
- return stream;
-}
-
-void writeLockFile(const LockFile & lockFile, const Path & path)
-{
- createDirs(dirOf(path));
- writeFile(path, fmt("%s\n", lockFile));
-}
-
Path getUserRegistryPath()
{
return getHome() + "/.config/nix/registry.json";
@@ -471,7 +374,7 @@ ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLoc
if (!recreateLockFile(handleLockFile)) {
// If recreateLockFile, start with an empty lockfile
// FIXME: symlink attack
- oldLockFile = readLockFile(
+ oldLockFile = LockFile::read(
state.store->toRealPath(flake.sourceInfo.storePath)
+ "/" + flake.sourceInfo.resolvedRef.subdir + "/flake.lock");
}
@@ -483,7 +386,7 @@ ResolvedFlake resolveFlake(EvalState & state, const FlakeRef & topRef, HandleLoc
if (!(lockFile == oldLockFile)) {
if (allowedToWrite(handleLockFile)) {
if (auto refData = std::get_if<FlakeRef::IsPath>(&topRef.data)) {
- writeLockFile(lockFile, refData->path + (topRef.subdir == "" ? "" : "/" + topRef.subdir) + "/flake.lock");
+ lockFile.write(refData->path + (topRef.subdir == "" ? "" : "/" + topRef.subdir) + "/flake.lock");
// Hack: Make sure that flake.lock is visible to Git, so it ends up in the Nix store.
runProgram("git", true, { "-C", refData->path, "add",
diff --git a/src/libexpr/primops/flake.hh b/src/libexpr/primops/flake.hh
index 933bc2593..bbf35da02 100644
--- a/src/libexpr/primops/flake.hh
+++ b/src/libexpr/primops/flake.hh
@@ -2,15 +2,12 @@
#include "types.hh"
#include "flakeref.hh"
-
-#include <variant>
-#include <nlohmann/json.hpp>
+#include "lockfile.hh"
namespace nix {
struct Value;
class EvalState;
-class Store;
namespace flake {
@@ -40,86 +37,6 @@ enum HandleLockFile : unsigned int
, UseNewLockFile // `RecreateLockFile` without writing to file
};
-struct AbstractDep
-{
- FlakeRef ref;
- Hash narHash;
-
- AbstractDep(const FlakeRef & flakeRef, const Hash & narHash)
- : ref(flakeRef), narHash(narHash) {};
-
- AbstractDep(const nlohmann::json & json);
-
- nlohmann::json toJson() const;
-
- Path computeStorePath(Store & store) const;
-};
-
-struct NonFlakeDep : AbstractDep
-{
- using AbstractDep::AbstractDep;
-
- bool operator ==(const NonFlakeDep & other) const
- {
- return ref == other.ref && narHash == other.narHash;
- }
-};
-
-struct FlakeDep;
-
-struct FlakeInputs
-{
- std::map<FlakeRef, FlakeDep> flakeDeps;
- std::map<FlakeAlias, NonFlakeDep> nonFlakeDeps;
-
- FlakeInputs() {};
- FlakeInputs(const nlohmann::json & json);
-
- nlohmann::json toJson() const;
-};
-
-struct FlakeDep : FlakeInputs, AbstractDep
-{
- FlakeId id;
-
- FlakeDep(const FlakeId & id, const FlakeRef & flakeRef, const Hash & narHash)
- : AbstractDep(flakeRef, narHash), id(id) {};
-
- FlakeDep(const nlohmann::json & json);
-
- bool operator ==(const FlakeDep & other) const
- {
- return
- id == other.id
- && ref == other.ref
- && narHash == other.narHash
- && flakeDeps == other.flakeDeps
- && nonFlakeDeps == other.nonFlakeDeps;
- }
-
- nlohmann::json toJson() const;
-};
-
-struct LockFile : FlakeInputs
-{
- bool operator ==(const LockFile & other) const
- {
- return
- flakeDeps == other.flakeDeps
- && nonFlakeDeps == other.nonFlakeDeps;
- }
-
- LockFile() {}
- LockFile(const nlohmann::json & json) : FlakeInputs(json) {}
- LockFile(FlakeDep && dep)
- {
- flakeDeps = std::move(dep.flakeDeps);
- nonFlakeDeps = std::move(dep.nonFlakeDeps);
- }
-
- nlohmann::json toJson() const;
-};
-
struct SourceInfo
{
// Immutable flakeref that this source tree was obtained from.
diff --git a/src/libexpr/primops/lockfile.cc b/src/libexpr/primops/lockfile.cc
new file mode 100644
index 000000000..ea0a93510
--- /dev/null
+++ b/src/libexpr/primops/lockfile.cc
@@ -0,0 +1,104 @@
+#include "lockfile.hh"
+#include "store-api.hh"
+
+namespace nix::flake {
+
+AbstractDep::AbstractDep(const nlohmann::json & json)
+ : ref(json["uri"])
+ , narHash(Hash((std::string) json["narHash"]))
+{
+ if (!ref.isImmutable())
+ throw Error("lockfile contains mutable flakeref '%s'", ref);
+}
+
+nlohmann::json AbstractDep::toJson() const
+{
+ nlohmann::json json;
+ json["uri"] = ref.to_string();
+ json["narHash"] = narHash.to_string(SRI);
+ return json;
+}
+
+Path AbstractDep::computeStorePath(Store & store) const
+{
+ return store.makeFixedOutputPath(true, narHash, "source");
+}
+
+FlakeDep::FlakeDep(const nlohmann::json & json)
+ : FlakeInputs(json)
+ , AbstractDep(json)
+ , id(json["id"])
+{
+}
+
+nlohmann::json FlakeDep::toJson() const
+{
+ auto json = FlakeInputs::toJson();
+ json.update(AbstractDep::toJson());
+ json["id"] = id;
+ return json;
+}
+
+FlakeInputs::FlakeInputs(const nlohmann::json & json)
+{
+ auto nonFlakeInputs = json["nonFlakeInputs"];
+ for (auto i = nonFlakeInputs.begin(); i != nonFlakeInputs.end(); ++i)
+ nonFlakeDeps.insert_or_assign(i.key(), NonFlakeDep(*i));
+
+ auto inputs = json["inputs"];
+ for (auto i = inputs.begin(); i != inputs.end(); ++i)
+ flakeDeps.insert_or_assign(i.key(), FlakeDep(*i));
+}
+
+nlohmann::json FlakeInputs::toJson() const
+{
+ nlohmann::json json;
+ {
+ auto j = nlohmann::json::object();
+ for (auto & i : nonFlakeDeps)
+ j[i.first] = i.second.toJson();
+ json["nonFlakeInputs"] = std::move(j);
+ }
+ {
+ auto j = nlohmann::json::object();
+ for (auto & i : flakeDeps)
+ j[i.first.to_string()] = i.second.toJson();
+ json["inputs"] = std::move(j);
+ }
+ return json;
+}
+
+nlohmann::json LockFile::toJson() const
+{
+ auto json = FlakeInputs::toJson();
+ json["version"] = 2;
+ return json;
+}
+
+LockFile LockFile::read(const Path & path)
+{
+ if (pathExists(path)) {
+ auto json = nlohmann::json::parse(readFile(path));
+
+ auto version = json.value("version", 0);
+ if (version != 2)
+ throw Error("lock file '%s' has unsupported version %d", path, version);
+
+ return LockFile(json);
+ } else
+ return LockFile();
+}
+
+std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile)
+{
+ stream << lockFile.toJson().dump(4); // '4' = indentation in json file
+ return stream;
+}
+
+void LockFile::write(const Path & path) const
+{
+ createDirs(dirOf(path));
+ writeFile(path, fmt("%s\n", *this));
+}
+
+}
diff --git a/src/libexpr/primops/lockfile.hh b/src/libexpr/primops/lockfile.hh
new file mode 100644
index 000000000..fee15c1da
--- /dev/null
+++ b/src/libexpr/primops/lockfile.hh
@@ -0,0 +1,110 @@
+#pragma once
+
+#include "flakeref.hh"
+
+#include <nlohmann/json.hpp>
+
+namespace nix {
+class Store;
+}
+
+namespace nix::flake {
+
+/* Common lock file information about a flake input, namely the
+ immutable ref and the NAR hash. */
+struct AbstractDep
+{
+ FlakeRef ref;
+ Hash narHash;
+
+ AbstractDep(const FlakeRef & flakeRef, const Hash & narHash)
+ : ref(flakeRef), narHash(narHash)
+ {
+ assert(ref.isImmutable());
+ };
+
+ AbstractDep(const nlohmann::json & json);
+
+ nlohmann::json toJson() const;
+
+ Path computeStorePath(Store & store) const;
+};
+
+/* Lock file information about a non-flake input. */
+struct NonFlakeDep : AbstractDep
+{
+ using AbstractDep::AbstractDep;
+
+ bool operator ==(const NonFlakeDep & other) const
+ {
+ return ref == other.ref && narHash == other.narHash;
+ }
+};
+
+struct FlakeDep;
+
+/* Lock file information about the dependencies of a flake. */
+struct FlakeInputs
+{
+ std::map<FlakeRef, FlakeDep> flakeDeps;
+ std::map<FlakeAlias, NonFlakeDep> nonFlakeDeps;
+
+ FlakeInputs() {};
+ FlakeInputs(const nlohmann::json & json);
+
+ nlohmann::json toJson() const;
+};
+
+/* Lock file information about a flake input. */
+struct FlakeDep : FlakeInputs, AbstractDep
+{
+ FlakeId id;
+
+ FlakeDep(const FlakeId & id, const FlakeRef & flakeRef, const Hash & narHash)
+ : AbstractDep(flakeRef, narHash), id(id) {};
+
+ FlakeDep(const nlohmann::json & json);
+
+ bool operator ==(const FlakeDep & other) const
+ {
+ return
+ id == other.id
+ && ref == other.ref
+ && narHash == other.narHash
+ && flakeDeps == other.flakeDeps
+ && nonFlakeDeps == other.nonFlakeDeps;
+ }
+
+ nlohmann::json toJson() const;
+};
+
+/* An entire lock file. Note that this cannot be a FlakeDep for the
+ top-level flake, because then the lock file would need to contain
+ the hash of the top-level flake, but committing the lock file
+ would invalidate that hash. */
+struct LockFile : FlakeInputs
+{
+ bool operator ==(const LockFile & other) const
+ {
+ return
+ flakeDeps == other.flakeDeps
+ && nonFlakeDeps == other.nonFlakeDeps;
+ }
+
+ LockFile() {}
+ LockFile(const nlohmann::json & json) : FlakeInputs(json) {}
+ LockFile(FlakeDep && dep)
+ {
+ flakeDeps = std::move(dep.flakeDeps);
+ nonFlakeDeps = std::move(dep.nonFlakeDeps);
+ }
+
+ nlohmann::json toJson() const;
+
+ static LockFile read(const Path & path);
+
+ void write(const Path & path) const;
+};
+
+}
+