aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/realisation.hh
blob: 1ecddc4d114867b6bfc228d735c3de9aee90fa15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#pragma once

#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 {
    // The hash modulo of the derivation
    Hash drvHash;
    std::string outputName;

    std::string to_string() const;

    std::string strHash() const
    { return drvHash.to_string(Base16, true); }

    static DrvOutput parse(const std::string &);

    GENERATE_CMP(DrvOutput, me->drvHash, me->outputName);
};

struct Realisation {
    DrvOutput id;
    StorePath outPath;

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


/**
 * 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);
};

}