aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/realisation.hh
diff options
context:
space:
mode:
authorregnat <rg@regnat.ovh>2020-12-14 17:24:30 +0100
committerregnat <rg@regnat.ovh>2021-01-28 09:38:44 +0100
commit9355ecd54301372b6a919a2205340f904c7a51c6 (patch)
tree94f055cc7c91e90dba6ca4f8dc325c95ca34a8f1 /src/libstore/realisation.hh
parentb8f345b29a65669f4d6966ba3837fda2341c5ec2 (diff)
Add a new Cmd type working on RealisedPaths
Where a `RealisedPath` is a store path with its history, meaning either an opaque path for stuff that has been directly added to the store, or a `Realisation` for stuff that has been built by a derivation This is a low-level refactoring that doesn't bring anything by itself (except a few dozen extra lines of code :/ ), but raising the abstraction level a bit is important on a number of levels: - Commands like `nix build` have to query for the realisations after the build is finished which is fragile (see 27905f12e4a7207450abe37c9ed78e31603b67e1 for example). Having them oprate directly at the realisation level would avoid that - Others like `nix copy` currently operate directly on (built) store paths, but need a bit more information as they will need to register the realisations on the remote side
Diffstat (limited to 'src/libstore/realisation.hh')
-rw-r--r--src/libstore/realisation.hh90
1 files changed, 82 insertions, 8 deletions
diff --git a/src/libstore/realisation.hh b/src/libstore/realisation.hh
index 4b8ead3c5..1ecddc4d1 100644
--- a/src/libstore/realisation.hh
+++ b/src/libstore/realisation.hh
@@ -3,6 +3,34 @@
#include "path.hh"
#include <nlohmann/json_fwd.hpp>
+
+/* Awfull hacky generation of the comparison operators by doing a lexicographic
+ * comparison between the choosen fields
+ * ```
+ * GENERATE_CMP(ClassName, my->field1, my->field2, ...)
+ * ```
+ *
+ * will generate comparison operators semantically equivalent to:
+ * ```
+ * bool operator<(const ClassName& other) {
+ * return field1 < other.field1 && field2 < other.field2 && ...;
+ * }
+ * ```
+ */
+#define GENERATE_ONE_CMP(COMPARATOR, MY_TYPE, FIELDS...) \
+ bool operator COMPARATOR(const MY_TYPE& other) const { \
+ const MY_TYPE* me = this; \
+ auto fields1 = std::make_tuple( FIELDS ); \
+ me = &other; \
+ auto fields2 = std::make_tuple( FIELDS ); \
+ return fields1 COMPARATOR fields2; \
+ }
+#define GENERATE_EQUAL(args...) GENERATE_ONE_CMP(==, args)
+#define GENERATE_LEQ(args...) GENERATE_ONE_CMP(<, args)
+#define GENERATE_CMP(args...) \
+ GENERATE_EQUAL(args) \
+ GENERATE_LEQ(args)
+
namespace nix {
struct DrvOutput {
@@ -17,13 +45,7 @@ struct DrvOutput {
static DrvOutput parse(const std::string &);
- bool operator<(const DrvOutput& other) const { return to_pair() < other.to_pair(); }
- bool operator==(const DrvOutput& other) const { return to_pair() == other.to_pair(); }
-
-private:
- // Just to make comparison operators easier to write
- std::pair<Hash, std::string> to_pair() const
- { return std::make_pair(drvHash, outputName); }
+ GENERATE_CMP(DrvOutput, me->drvHash, me->outputName);
};
struct Realisation {
@@ -32,8 +54,60 @@ struct Realisation {
nlohmann::json toJSON() const;
static Realisation fromJSON(const nlohmann::json& json, const std::string& whence);
+
+ StorePath getPath() const { return outPath; }
+
+ GENERATE_CMP(Realisation, me->id, me->outPath);
+};
+
+struct OpaquePath {
+ StorePath path;
+
+ StorePath getPath() const { return path; }
+
+ GENERATE_CMP(OpaquePath, me->path);
};
-typedef std::map<DrvOutput, Realisation> DrvOutputs;
+
+/**
+ * A store path with all the history of how it went into the store
+ */
+struct RealisedPath {
+ /*
+ * A path is either the result of the realisation of a derivation or
+ * an opaque blob that has been directly added to the store
+ */
+ using Raw = std::variant<Realisation, OpaquePath>;
+ Raw raw;
+
+ using Set = std::set<RealisedPath>;
+
+ RealisedPath(StorePath path) : raw(OpaquePath{path}) {}
+ RealisedPath(Realisation r) : raw(r) {}
+
+ /**
+ * Syntactic sugar to run `std::visit` on the raw value:
+ * path.visit(blah) == std::visit(blah, path.raw)
+ */
+ template <class Visitor>
+ constexpr decltype(auto) visit(Visitor && vis) {
+ return std::visit(vis, raw);
+ }
+ template <class Visitor>
+ constexpr decltype(auto) visit(Visitor && vis) const {
+ return std::visit(vis, raw);
+ }
+
+ /**
+ * Get the raw store path associated to this
+ */
+ StorePath path() const;
+
+ void closure(Store& store, Set& ret) const;
+ static void closure(Store& store, const Set& startPaths, Set& ret);
+ Set closure(Store& store) const;
+
+ GENERATE_CMP(RealisedPath, me->raw);
+};
}