cleanup cycle checking
authorEvan Martin <martine@danga.com>
Sat, 4 Dec 2010 03:01:18 +0000 (19:01 -0800)
committerEvan Martin <martine@danga.com>
Sat, 4 Dec 2010 03:01:18 +0000 (19:01 -0800)
build.cc
build.h
build_test.cc

index 42062214d2d1339e5bd2b1fe04d11d0e3cd28b13..4a155f97cf6876c5352f882d696aa0c049cd7ea1 100644 (file)
--- a/build.cc
+++ b/build.cc
@@ -21,23 +21,8 @@ bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
   }
   assert(edge);
 
-  // Check for a dependency cycle.
-  vector<Node*>::reverse_iterator i =
-      find(stack->rbegin(), stack->rend(), node);
-  if (i != stack->rend()) {
-    // Add this node onto the stack to make it clearer where the loop
-    // is.
-    stack->push_back(node);
-
-    vector<Node*>::iterator i =
-        find(stack->begin(), stack->end(), node);
-    for (; i != stack->end(); ++i) {
-      if (!err->empty())
-        err->append(" -> ");
-      err->append((*i)->file_->path_);
-    }
+  if (CheckDependencyCycle(node, stack, err))
     return false;
-  }
 
   if (!node->dirty())
     return false;  // Don't need to do anything.
@@ -63,6 +48,26 @@ bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
   return true;
 }
 
+bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
+  vector<Node*>::reverse_iterator ri =
+      find(stack->rbegin(), stack->rend(), node);
+  if (ri == stack->rend())
+    return false;
+
+  // Add this node onto the stack to make it clearer where the loop
+  // is.
+  stack->push_back(node);
+
+  vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
+  *err = "dependency cycle: ";
+  for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
+    if (i != start)
+      err->append(" -> ");
+    err->append((*i)->file_->path_);
+  }
+  return true;
+}
+
 Edge* Plan::FindWork() {
   if (ready_.empty())
     return NULL;
diff --git a/build.h b/build.h
index 7fef9f7c7e141cb59f23d6b6e8c0f7f8e298fc54..41df8ba299d24b92e36303db6fc8cd5ae050b666 100644 (file)
--- a/build.h
+++ b/build.h
@@ -36,6 +36,7 @@ struct Plan {
 
 private:
   bool AddSubTarget(Node* node, vector<Node*>* stack, string* err);
+  bool CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err);
   void NodeFinished(Node* node);
 
   set<Edge*> want_;
index a6eaa54badecb7af2698073fe92facefd71727dc..26d10801673f2b5432e5872779da79729465b166 100644 (file)
@@ -145,7 +145,7 @@ TEST_F(PlanTest, DoubleDependent) {
   ASSERT_FALSE(edge);  // done
 }
 
-TEST_F(PlanTest, DependencyLoop) {
+TEST_F(PlanTest, DependencyCycle) {
   AssertParse(&state_,
 "build out: cat mid\n"
 "build mid: cat in\n"
@@ -154,7 +154,7 @@ TEST_F(PlanTest, DependencyLoop) {
   GetNode("pre")->MarkDependentsDirty();
   string err;
   EXPECT_FALSE(plan_.AddTarget(GetNode("out"), &err));
-  ASSERT_EQ("out -> mid -> in -> pre -> out", err);
+  ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err);
 }
 
 struct BuildTest : public StateTestWithBuiltinRules,