diff --git a/src/etc/testcases/taskdefs/ant.xml b/src/etc/testcases/taskdefs/ant.xml
index aa69d6488..dc570ab5b 100644
--- a/src/etc/testcases/taskdefs/ant.xml
+++ b/src/etc/testcases/taskdefs/ant.xml
@@ -206,6 +206,13 @@
+
+
+
+
+
+
+
ta
tb
tc
diff --git a/src/etc/testcases/taskdefs/calltarget.xml b/src/etc/testcases/taskdefs/calltarget.xml
index 17c9f0574..479f653c9 100644
--- a/src/etc/testcases/taskdefs/calltarget.xml
+++ b/src/etc/testcases/taskdefs/calltarget.xml
@@ -65,6 +65,13 @@
+
+
+
+
+
+
+
ta
tb
tc
diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java
index 1f55cf08b..0a337939b 100644
--- a/src/main/org/apache/tools/ant/Project.java
+++ b/src/main/org/apache/tools/ant/Project.java
@@ -1181,14 +1181,11 @@ public class Project {
throw new BuildException(msg);
}
- // Sort the dependency tree, and run everything from the
- // beginning until we hit our targetName.
+ // Sort and run the dependency tree.
// Sorting checks if all the targets (and dependencies)
// exist, and if there is any cycle in the dependency
// graph.
- Vector sortedTargets = topoSort(targetName, targets);
- sortedTargets.setSize(sortedTargets.indexOf(targets.get(targetName)) + 1);
- executeSortedTargets(sortedTargets);
+ executeSortedTargets(topoSort(targetName, targets, false));
}
/**
@@ -1557,38 +1554,65 @@ public class Project {
}
/**
- * Topologically sorts a set of targets.
+ * Topologically sorts a set of targets. Equivalent to calling
+ * topoSort(new String[] {root}, targets, true)
.
*
* @param root The name of the root target. The sort is created in such
* a way that the sequence of Targets up to the root
* target is the minimum possible such sequence.
* Must not be null
.
- * @param targets A map of names to targets (String to Target).
+ * @param targets A Hashtable mapping names to Targets.
* Must not be null
.
- * @return a vector of Target objects in sorted order.
+ * @return a Vector of ALL Target objects in sorted order.
* @exception BuildException if there is a cyclic dependency among the
* targets, or if a named target does not exist.
*/
public final Vector topoSort(String root, Hashtable targets)
throws BuildException {
- return topoSort(new String[] {root}, targets);
+ return topoSort(new String[] {root}, targets, true);
+ }
+
+ /**
+ * Topologically sorts a set of targets. Equivalent to calling
+ * topoSort(new String[] {root}, targets, returnAll)
.
+ *
+ * @param root The name of the root target. The sort is created in such
+ * a way that the sequence of Targets up to the root
+ * target is the minimum possible such sequence.
+ * Must not be null
.
+ * @param targets A Hashtable mapping names to Targets.
+ * Must not be null
.
+ * @param returnAll boolean
indicating whether to return all
+ * targets, or the execution sequence only.
+ * @return a Vector of Target objects in sorted order.
+ * @exception BuildException if there is a cyclic dependency among the
+ * targets, or if a named target does not exist.
+ * @since Ant 1.6.3
+ */
+ public final Vector topoSort(String root, Hashtable targets,
+ boolean returnAll) throws BuildException {
+ return topoSort(new String[] {root}, targets, returnAll);
}
/**
* Topologically sorts a set of targets.
*
* @param root String[]
containing the names of the root targets.
- * The sort is created in such a way that the sequence of Targets
- * up to the root target is the minimum possible such sequence.
+ * The sort is created in such a way that the ordered sequence of
+ * Targets is the minimum possible such sequence to the specified
+ * root targets.
* Must not be null
.
* @param targets A map of names to targets (String to Target).
* Must not be null
.
- * @return a vector of Target objects in sorted order.
+ * @param returnAll boolean
indicating whether to return all
+ * targets, or the execution sequence only.
+ * @return a Vector of Target objects in sorted order.
* @exception BuildException if there is a cyclic dependency among the
* targets, or if a named target does not exist.
+ * @since Ant 1.6.3
*/
- public final Vector topoSort(String[] root, Hashtable targets)
- throws BuildException {
+ public final Vector topoSort(String[] root, Hashtable targets,
+ boolean returnAll) throws BuildException {
Vector ret = new Vector();
Hashtable state = new Hashtable();
Stack visiting = new Stack();
@@ -1602,7 +1626,13 @@ public class Project {
// build Target.
for (int i = 0; i < root.length; i++) {
- tsort(root[i], targets, state, visiting, ret);
+ String st = (String)(state.get(root[i]));
+ if (st == null) {
+ tsort(root[i], targets, state, visiting, ret);
+ } else if (st == VISITING) {
+ throw new RuntimeException("Unexpected node in visiting state: "
+ + root[i]);
+ }
}
StringBuffer buf = new StringBuffer("Build sequence for target(s)");
@@ -1612,17 +1642,18 @@ public class Project {
buf.append(" is " + ret);
log(buf.toString(), MSG_VERBOSE);
+ Vector complete = (returnAll) ? ret : new Vector(ret);
for (Enumeration en = targets.keys(); en.hasMoreElements();) {
String curTarget = (String) en.nextElement();
String st = (String) state.get(curTarget);
if (st == null) {
- tsort(curTarget, targets, state, visiting, ret);
+ tsort(curTarget, targets, state, visiting, complete);
} else if (st == VISITING) {
throw new RuntimeException("Unexpected node in visiting state: "
+ curTarget);
}
}
- log("Complete build sequence is " + ret, MSG_VERBOSE);
+ log("Complete build sequence is " + complete, MSG_VERBOSE);
return ret;
}
diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java
index beecdf964..8d375c1bd 100644
--- a/src/main/org/apache/tools/ant/Target.java
+++ b/src/main/org/apache/tools/ant/Target.java
@@ -219,14 +219,9 @@ public class Target implements TaskContainer {
* @since Ant 1.6
*/
public boolean dependsOn(String other) {
- if (getProject() != null) {
- List l = getProject().topoSort(getName(),
- getProject().getTargets());
- int myIdx = l.indexOf(this);
- int otherIdx = l.indexOf(getProject().getTargets().get(other));
- return myIdx >= otherIdx;
- }
- return false;
+ Project p = getProject();
+ Hashtable t = (p == null) ? null : p.getTargets();
+ return (p != null && p.topoSort(getName(), t, false).contains(t.get(other)));
}
/**
diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java
index 3a06830a6..0bc0b7af5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Ant.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java
@@ -397,12 +397,9 @@ public class Ant extends Task {
String[] nameArray =
(String[])(locals.toArray(new String[locals.size()]));
- Hashtable targets = newProject.getTargets();
- Vector sortedTargets = newProject.topoSort(nameArray, targets);
+ newProject.executeSortedTargets(newProject.topoSort(
+ nameArray, newProject.getTargets(), false));
- sortedTargets.setSize(sortedTargets.indexOf(targets.get(
- locals.lastElement())) + 1);
- newProject.executeSortedTargets(sortedTargets);
} catch (BuildException ex) {
t = ProjectHelper
.addLocationToBuildException(ex, getLocation());
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java
index 23c67f98e..61c2eb625 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java
@@ -303,6 +303,10 @@ public class AntTest extends BuildFileTest {
expectLog("multiple-targets", "tadadctbdbtc");
}
+ public void testMultipleTargets2() {
+ expectLog("multiple-targets-2", "dadctb");
+ }
+
private class BasedirChecker implements BuildListener {
private String[] expectedBasedirs;
private int calls = 0;
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java b/src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java
index bd2d07a99..c15dd4858 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/CallTargetTest.java
@@ -63,6 +63,10 @@ public class CallTargetTest extends BuildFileTest {
expectLog("multiple-targets", "tadadctbdbtc");
}
+ public void testMultipleTargets2() {
+ expectLog("multiple-targets-2", "dadctb");
+ }
+
public void tearDown() {
project.executeTarget("cleanup");
}