diff --git a/src/etc/testcases/taskdefs/ant.xml b/src/etc/testcases/taskdefs/ant.xml index cc62d2ea1..5d3ce07d6 100644 --- a/src/etc/testcases/taskdefs/ant.xml +++ b/src/etc/testcases/taskdefs/ant.xml @@ -162,4 +162,11 @@ test2 is ${test2} test1.x is ${test1.x} + + + + + + + diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index e308286a4..ea358e941 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -1589,8 +1589,7 @@ public class Project { * Must not be null. * @param targets A map of names to targets (String to Target). * Must not be null. - * @return a vector of strings with the names of the targets in - * sorted order. + * @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. */ @@ -2096,4 +2095,4 @@ public class Project { // is private/protected. } } -} \ No newline at end of file +} diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java index 69cf71ff7..d82ee5568 100644 --- a/src/main/org/apache/tools/ant/Target.java +++ b/src/main/org/apache/tools/ant/Target.java @@ -255,6 +255,22 @@ public class Target implements TaskContainer { } } + /** + * Does this target depend on the named target? + * + * @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; + } + /** * Sets the "if" condition to test on execution. This is the * name of a property to test for existence - if the property diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java index 2d7b00d19..19738e5f3 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Ant.java +++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java @@ -68,6 +68,7 @@ import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.ProjectHelper; +import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.util.FileUtils; @@ -363,7 +364,10 @@ public class Ant extends Task { if (newProject.getProperty("ant.file") .equals(getProject().getProperty("ant.file")) && getOwningTarget() != null) { - if (getOwningTarget().getName().equals("")) { + + String owningTargetName = getOwningTarget().getName(); + + if (owningTargetName.equals("")) { if (getTaskName().equals("antcall")) { throw new BuildException("antcall must not be used at" + " the top level."); @@ -372,9 +376,20 @@ public class Ant extends Task { + " top level must not invoke" + " its own build file."); } - } else if (getOwningTarget().getName().equals(target)) { + } else if (owningTargetName.equals(target)) { throw new BuildException(getTaskName() + " task calling " + "its own parent target."); + } else { + Target other = + (Target) getProject().getTargets().get(target); + if (other != null && other.dependsOn(owningTargetName)) { + throw new BuildException(getTaskName() + + " task calling a target" + + " that depends on" + + " its parent target \'" + + owningTargetName + + "\'."); + } } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java index 0ccb93e83..9dc3d1e5a 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/AntTest.java @@ -302,6 +302,10 @@ public class AntTest extends BuildFileTest { assertTrue(getLog().indexOf("test1.x is 1") > -1); } + public void testInfiniteLoopViaDepends() { + expectBuildException("infinite-loop-via-depends", "recursive call"); + } + private class BasedirChecker implements BuildListener { private String[] expectedBasedirs; private int calls = 0;