misc.cc 2.9 KB

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