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