gnu: guix: Update to 846403e.
[jackhill/guix/guix.git] / nix / libstore / misc.cc
CommitLineData
36457566
LC
1#include "misc.hh"
2#include "store-api.hh"
3#include "local-store.hh"
4#include "globals.hh"
5
6
7namespace nix {
8
9
10Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
11{
12 assertStorePath(drvPath);
13 store.ensurePath(drvPath);
15ddeff5 14 return readDerivation(drvPath);
36457566
LC
15}
16
17
18void computeFSClosure(StoreAPI & store, const Path & path,
19 PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
20{
21 if (paths.find(path) != paths.end()) return;
22 paths.insert(path);
23
24 PathSet edges;
25
26 if (flipDirection) {
27 store.queryReferrers(path, edges);
28
29 if (includeOutputs) {
30 PathSet derivers = store.queryValidDerivers(path);
31 foreach (PathSet::iterator, i, derivers)
32 edges.insert(*i);
33 }
34
35 if (includeDerivers && isDerivation(path)) {
36 PathSet outputs = store.queryDerivationOutputs(path);
37 foreach (PathSet::iterator, i, outputs)
38 if (store.isValidPath(*i) && store.queryDeriver(*i) == path)
39 edges.insert(*i);
40 }
41
42 } else {
43 store.queryReferences(path, edges);
44
45 if (includeOutputs && isDerivation(path)) {
46 PathSet outputs = store.queryDerivationOutputs(path);
47 foreach (PathSet::iterator, i, outputs)
48 if (store.isValidPath(*i)) edges.insert(*i);
49 }
50
51 if (includeDerivers) {
52 Path deriver = store.queryDeriver(path);
53 if (store.isValidPath(deriver)) edges.insert(deriver);
54 }
55 }
56
57 foreach (PathSet::iterator, i, edges)
58 computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
59}
60
61
62Path findOutput(const Derivation & drv, string id)
63{
64 foreach (DerivationOutputs::const_iterator, i, drv.outputs)
65 if (i->first == id) return i->second.path;
66 throw Error(format("derivation has no output `%1%'") % id);
67}
68
69
36457566
LC
70static void dfsVisit(StoreAPI & store, const PathSet & paths,
71 const Path & path, PathSet & visited, Paths & sorted,
72 PathSet & parents)
73{
74 if (parents.find(path) != parents.end())
75 throw BuildError(format("cycle detected in the references of `%1%'") % path);
76
77 if (visited.find(path) != visited.end()) return;
78 visited.insert(path);
79 parents.insert(path);
80
81 PathSet references;
82 if (store.isValidPath(path))
83 store.queryReferences(path, references);
84
85 foreach (PathSet::iterator, i, references)
86 /* Don't traverse into paths that don't exist. That can
87 happen due to substitutes for non-existent paths. */
88 if (*i != path && paths.find(*i) != paths.end())
89 dfsVisit(store, paths, *i, visited, sorted, parents);
90
91 sorted.push_front(path);
92 parents.erase(path);
93}
94
95
96Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
97{
98 Paths sorted;
99 PathSet visited, parents;
100 foreach (PathSet::const_iterator, i, paths)
101 dfsVisit(store, paths, *i, visited, sorted, parents);
102 return sorted;
103}
104
105
106}