about summary refs log tree commit diff
path: root/pkgs/build-support/build-sandbox/src/nix-query.cc
blob: 712086938fb15a34466d4565a3deb0508c0eff72 (plain) (blame)
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
114
115
116
117
118
#include <iostream>

#if NIX_VERSION >= 112
#include <nix/config.h>
#endif
#include <nix/util.hh>
#include <nix/local-store.hh>
#include <nix/store-api.hh>

#if NIX_VERSION < 112
#include <nix/misc.hh>
#include <nix/globals.hh>
#endif

using namespace nix;

struct query_state {
#if NIX_VERSION >= 112
    std::shared_ptr<Store> store;
#else
    std::shared_ptr<StoreAPI> store;
#endif
    PathSet paths;
    PathSet::iterator iter;
};

static Path get_store_path(query_state *qs, Path path)
{
    Path canonicalized = canonPath(path, true);
#if NIX_VERSION >= 112
    return qs->store->toStorePath(canonicalized);
#else
    return toStorePath(canonicalized);
#endif
}

static Path get_ancestor(query_state *qs, Path path)
{
    size_t pos = 0;
    std::string tmp;

    while (pos != std::string::npos) {
        if ((pos = path.find('/', pos + 1)) != std::string::npos) {
            Path current = path.substr(0, pos);

            if (!isLink(current))
                continue;

            try {
                current = get_store_path(qs, current);
            } catch (...) {
                continue;
            }

            return current;
        }
    }

    return get_store_path(qs, path);
}

extern "C" {
    struct query_state *new_query(void)
    {
        query_state *initial = new query_state();
#if NIX_VERSION >= 112
        initial->store = openStore();
#else
        settings.processEnvironment();
        settings.loadConfFile();
        initial->store = openStore(false);
#endif
        return initial;
    }

    void free_query(query_state *qs)
    {
        delete qs;
    }

    bool query_requisites(query_state *qs, const char *path)
    {
        Path query(path);

        try {
            query = get_ancestor(qs, query);

#if NIX_VERSION >= 112
            qs->store->computeFSClosure(
                qs->store->followLinksToStorePath(query),
                qs->paths, false, true
            );
#else
            computeFSClosure(
                *qs->store, followLinksToStorePath(query),
                qs->paths, false, true
            );
#endif
        } catch (Error &e) {
            std::cerr << "Error while querying requisites for "
                      << query << ": " << e.what()
                      << std::endl;
            return false;
        }

        qs->iter = qs->paths.begin();

        return true;
    }

    const char *next_query_result(query_state *qs)
    {
        if (qs->iter == qs->paths.end())
            return NULL;

        return (qs->iter++)->c_str();
    }
}