gnu: linux-libre: Update to 5.1.4.
[guix.git] / nix / libstore / misc.cc
blob97618089bdfd1b41b920989ade7d42a9711eecc9
1 #include "misc.hh"
2 #include "store-api.hh"
3 #include "local-store.hh"
4 #include "globals.hh"
7 namespace nix {
10 Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
12 assertStorePath(drvPath);
13 store.ensurePath(drvPath);
14 return readDerivation(drvPath);
18 void computeFSClosure(StoreAPI & store, const Path & path,
19 PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
21 if (paths.find(path) != paths.end()) return;
22 paths.insert(path);
24 PathSet edges;
26 if (flipDirection) {
27 store.queryReferrers(path, edges);
29 if (includeOutputs) {
30 PathSet derivers = store.queryValidDerivers(path);
31 foreach (PathSet::iterator, i, derivers)
32 edges.insert(*i);
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);
42 } else {
43 store.queryReferences(path, edges);
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);
51 if (includeDerivers) {
52 Path deriver = store.queryDeriver(path);
53 if (store.isValidPath(deriver)) edges.insert(deriver);
57 foreach (PathSet::iterator, i, edges)
58 computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
62 Path findOutput(const Derivation & drv, string id)
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);
70 static void dfsVisit(StoreAPI & store, const PathSet & paths,
71 const Path & path, PathSet & visited, Paths & sorted,
72 PathSet & parents)
74 if (parents.find(path) != parents.end())
75 throw BuildError(format("cycle detected in the references of `%1%'") % path);
77 if (visited.find(path) != visited.end()) return;
78 visited.insert(path);
79 parents.insert(path);
81 PathSet references;
82 if (store.isValidPath(path))
83 store.queryReferences(path, references);
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);
91 sorted.push_front(path);
92 parents.erase(path);
96 Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
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;