aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2011-12-30 14:47:14 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2011-12-30 14:47:14 +0000
commitb1004f40f7e4dd02feec2d0cb26bd6c95dd66dde (patch)
tree185519967aa2ef3c9a03309d9838d5418eb1d2a3 /src/libstore/gc.cc
parent254b3399ba3d7cf161fa54f9cf6cdc65c17164fb (diff)
* Reject a build if there is a cycle among the outputs. This is
necessary because existing code assumes that the references graph is acyclic.
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index feaab573e..ec7751133 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -372,8 +372,13 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
static void dfsVisit(StoreAPI & store, const PathSet & paths,
- const Path & path, PathSet & visited, Paths & sorted)
+ const Path & path, PathSet & visited, Paths & sorted,
+ PathSet & parents)
{
+ if (parents.find(path) != parents.end())
+ throw BuildError(format("cycle detected in the references of `%1%'") % path);
+ parents.insert(path);
+
if (visited.find(path) != visited.end()) return;
visited.insert(path);
@@ -385,18 +390,19 @@ static void dfsVisit(StoreAPI & store, const PathSet & paths,
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (*i != path && paths.find(*i) != paths.end())
- dfsVisit(store, paths, *i, visited, sorted);
+ dfsVisit(store, paths, *i, visited, sorted, parents);
sorted.push_front(path);
+ parents.erase(path);
}
Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
{
Paths sorted;
- PathSet visited;
+ PathSet visited, parents;
foreach (PathSet::const_iterator, i, paths)
- dfsVisit(store, paths, *i, visited, sorted);
+ dfsVisit(store, paths, *i, visited, sorted, parents);
return sorted;
}