| 1 | #include "misc.hh"
|
| 2 | #include <math.h>
|
| 3 | #include "store-api.hh"
|
| 4 | #include "local-store.hh"
|
| 5 |
|
| 6 | #include <format>
|
| 7 |
|
| 8 | namespace nix {
|
| 9 |
|
| 10 |
|
| 11 | Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
|
| 12 | {
|
| 13 | assertStorePath(drvPath);
|
| 14 | store.ensurePath(drvPath);
|
| 15 | return readDerivation(drvPath);
|
| 16 | }
|
| 17 |
|
| 18 |
|
| 19 | void 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 |
|
| 63 | static 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 | |
| 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 |
|
| 89 | Paths 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 |
|
| 99 | string 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 | }
|