aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/fetchTree.cc
blob: 60bd2ed1156f76b85536028f5c4bf71f25336a0f (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
#include "primops.hh"
#include "eval-inline.hh"
#include "store-api.hh"
#include "fetchers/fetchers.hh"
#include "fetchers/registry.hh"

namespace nix {

static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
    settings.requireExperimentalFeature("fetch-tree");

    std::shared_ptr<const fetchers::Input> input;
    PathSet context;

    state.forceValue(*args[0]);

    if (args[0]->type == tAttrs) {
        state.forceAttrs(*args[0], pos);

        fetchers::Input::Attrs attrs;

        for (auto & attr : *args[0]->attrs) {
            state.forceValue(*attr.value);
            if (attr.value->type == tString)
                attrs.emplace(attr.name, attr.value->string.s);
            else
                throw Error("unsupported attribute type");
        }

        if (!attrs.count("type"))
            throw Error("attribute 'type' is missing in call to 'fetchTree', at %s", pos);

        input = fetchers::inputFromAttrs(attrs);
    } else
        input = fetchers::inputFromURL(state.coerceToString(pos, *args[0], context, false, false));

    if (!evalSettings.pureEval && !input->isDirect())
        input = lookupInRegistries(state.store, input).first;

    if (evalSettings.pureEval && !input->isImmutable())
        throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input");

    auto [tree, input2] = input->fetchTree(state.store);

    state.mkAttrs(v, 8);
    auto storePath = state.store->printStorePath(tree.storePath);
    mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
    if (input2->getRev()) {
        mkString(*state.allocAttr(v, state.symbols.create("rev")), input2->getRev()->gitRev());
        mkString(*state.allocAttr(v, state.symbols.create("shortRev")), input2->getRev()->gitShortRev());
    }
    if (tree.info.revCount)
        mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);
    v.attrs->sort();

    if (state.allowedPaths)
        state.allowedPaths->insert(tree.actualPath);
}

static RegisterPrimOp r("fetchTree", 1, prim_fetchTree);

}