projects/guix·blob java-team · refs

119 lines · 3.4 KiB

1#include "misc.hh"
2#include <math.h>
3#include "store-api.hh"
4#include "local-store.hh"
5
6#include <format>
7
8namespace nix {
9
10
11Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
12{
13 assertStorePath(drvPath);
14 store.ensurePath(drvPath);
15 return readDerivation(drvPath);
16}
17
18
19void computeFSClosure(StoreAPI & store, const Path & path,
20 PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
21{
22 if (paths.find(path) != paths.end()) return;
23 paths.insert(path);
24
25 PathSet edges;
26
27 if (flipDirection) {
28 store.queryReferrers(path, edges);
29
30 if (includeOutputs) {
31 PathSet derivers = store.queryValidDerivers(path);
32 for (auto& i : derivers)
33 edges.insert(i);
34 }
35
36 if (includeDerivers && isDerivation(path)) {
37 PathSet outputs = store.queryDerivationOutputs(path);
38 for (auto& i : outputs)
39 if (store.isValidPath(i) && store.queryDeriver(i) == path)
40 edges.insert(i);
41 }
42
43 } else {
44 store.queryReferences(path, edges);
45
46 if (includeOutputs && isDerivation(path)) {
47 PathSet outputs = store.queryDerivationOutputs(path);
48 for (auto& i : outputs)
49 if (store.isValidPath(i)) edges.insert(i);
50 }
51
52 if (includeDerivers) {
53 Path deriver = store.queryDeriver(path);
54 if (store.isValidPath(deriver)) edges.insert(deriver);
55 }
56 }
57
58 for (auto& i : edges)
59 computeFSClosure(store, i, paths, flipDirection, includeOutputs, includeDerivers);
60}
61
62
63static void dfsVisit(StoreAPI & store, const PathSet & paths,
64 const Path & path, PathSet & visited, Paths & sorted,
65 PathSet & parents)
66{
67 if (parents.find(path) != parents.end())
68 throw BuildError(std::format("cycle detected in the references of `{}'", path));
69
70 if (visited.find(path) != visited.end()) return;
71 visited.insert(path);
72 parents.insert(path);
73
74 PathSet references;
75 if (store.isValidPath(path))
76 store.queryReferences(path, references);
77
78 for (auto& i : references)
79 /* Don't traverse into paths that don't exist. That can
80 happen due to substitutes for non-existent paths. */
81 if (i != path && paths.find(i) != paths.end())
82 dfsVisit(store, paths, i, visited, sorted, parents);
83
84 sorted.push_front(path);
85 parents.erase(path);
86}
87
88
89Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
90{
91 Paths sorted;
92 PathSet visited, parents;
93 for (const auto& i : paths)
94 dfsVisit(store, paths, i, visited, sorted, parents);
95 return sorted;
96}
97
98/* Max of LLONG_MAX is 8 EiB */
99string showBytes(long long bytes)
100{
101 if (llabs(bytes > exp2l(60))) {
102 return std::format("{:7.2f} EiB", bytes / exp2l(60));
103 } else if (llabs(bytes > exp2l(50))) {
104 return std::format("{:7.2f} PiB", bytes / exp2l(50));
105 } else if (llabs(bytes > exp2l(40))) {
106 return std::format("{:7.2f} TiB", bytes / exp2l(40));
107 } else if (llabs(bytes > exp2l(30))) {
108 return std::format("{:7.2f} GiB", bytes / exp2l(30));
109 } else if (llabs(bytes > exp2l(20))) {
110 return std::format("{:7.2f} MiB", bytes / exp2l(20));
111 } else if (llabs(bytes > exp2l(10))) {
112 return std::format("{:7.2f} KiB", bytes / exp2l(10));
113 } else {
114 return std::format("{:4} bytes", bytes);
115 }
116}
117
118
119}