aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/fetchClosure.cc
blob: 22a4649a42e54470d8c39a70f5640fab125b52e3 (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
#include "primops.hh"
#include "store-api.hh"

namespace nix {

static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
    state.forceAttrs(*args[0], pos);

    std::optional<StorePath> storePath;
    std::optional<std::string> from;

    for (auto & attr : *args[0]->attrs) {
        if (attr.name == "storePath") {
            PathSet context;
            storePath = state.coerceToStorePath(*attr.pos, *attr.value, context);
        }

        else if (attr.name == "from")
            from = state.forceStringNoCtx(*attr.value, *attr.pos);

        else
            throw Error({
                .msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attr.name),
                .errPos = pos
            });
    }

    if (!storePath)
        throw Error({
            .msg = hintfmt("attribute '%s' is missing in call to 'fetchClosure'", "storePath"),
            .errPos = pos
        });

    if (!from)
        throw Error({
            .msg = hintfmt("attribute '%s' is missing in call to 'fetchClosure'", "from"),
            .errPos = pos
        });

    // FIXME: only allow some "trusted" store types (like BinaryCacheStore).
    auto srcStore = openStore(*from);

    copyClosure(*srcStore, *state.store, RealisedPath::Set { *storePath });

    /* In pure mode, require a CA path. */
    if (evalSettings.pureEval) {
        auto info = state.store->queryPathInfo(*storePath);
        if (!info->isContentAddressed(*state.store))
            throw Error({
                .msg = hintfmt("in pure mode, 'fetchClosure' requires a content-addressed path, which '%s' isn't",
                    state.store->printStorePath(*storePath)),
                .errPos = pos
            });
    }

    auto storePathS = state.store->printStorePath(*storePath);
    v.mkString(storePathS, {storePathS});
}

static RegisterPrimOp primop_fetchClosure({
    .name = "__fetchClosure",
    .args = {"args"},
    .doc = R"(
    )",
    .fun = prim_fetchClosure,
});

}