misc.cc 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. static void dfsVisit(StoreAPI & store, const PathSet & paths,
  47. const Path & path, PathSet & visited, Paths & sorted,
  48. PathSet & parents)
  49. {
  50. if (parents.find(path) != parents.end())
  51. throw BuildError(format("cycle detected in the references of `%1%'") % path);
  52. if (visited.find(path) != visited.end()) return;
  53. visited.insert(path);
  54. parents.insert(path);
  55. PathSet references;
  56. if (store.isValidPath(path))
  57. store.queryReferences(path, references);
  58. foreach (PathSet::iterator, i, references)
  59. /* Don't traverse into paths that don't exist. That can
  60. happen due to substitutes for non-existent paths. */
  61. if (*i != path && paths.find(*i) != paths.end())
  62. dfsVisit(store, paths, *i, visited, sorted, parents);
  63. sorted.push_front(path);
  64. parents.erase(path);
  65. }
  66. Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
  67. {
  68. Paths sorted;
  69. PathSet visited, parents;
  70. foreach (PathSet::const_iterator, i, paths)
  71. dfsVisit(store, paths, *i, visited, sorted, parents);
  72. return sorted;
  73. }
  74. }