diff options
-rw-r--r-- | docs/manual/tasks/relentless.html | 141 | ||||
-rw-r--r-- | docs/manual/tasks/toc.html | 1 | ||||
-rw-r--r-- | src/java/net/sf/antcontrib/antcontrib.properties | 1 | ||||
-rw-r--r-- | src/java/net/sf/antcontrib/logic/Relentless.java | 97 | ||||
-rw-r--r-- | test/resources/logic/relentless.xml | 55 | ||||
-rw-r--r-- | test/src/net/sf/antcontrib/logic/RelentlessTaskTest.java | 62 |
6 files changed, 357 insertions, 0 deletions
diff --git a/docs/manual/tasks/relentless.html b/docs/manual/tasks/relentless.html new file mode 100644 index 0000000..b30be41 --- /dev/null +++ b/docs/manual/tasks/relentless.html @@ -0,0 +1,141 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <title>Ant-contrib Tasks: Relentless</title> + </head> + + <body> + <h1>Relentless</h1> + + <p>The <relentless> task will execute all of the + nested tasks, regardless of whether one or more of the + nested tasks fails. When <relentless> has completed + executing the nested tasks, it will either + <ul> + <li>fail, if any one or more of the nested tasks failed; or + <li>succeed, if all of the nested tasks succeeded. + </ul> + An appropriate message will be written to the log. + </p> + <P> + Tasks are executed in the order that they appear within the + <relentless> task. It is up to the user to ensure that + relentless execution of the + nested tasks is safe. + </p> + <p><em> + This task only works for ant version greater than or equal + to ant 1.6.0. + </em> + </p> + + <h2>Parameters</h2> + <table border="1" cellpadding="2" cellspacing="0"> + <tr> + <th>Attribute</th> + <th>Description</th> + <th>Required</th> + </tr> + <tr> + <td valign="top">description</td> + <td valign="top">A string that will be included in the log output. This + can be useful for helping to identify sections of large Ant builds.</td> + <td align="center" valign="top">No</td> + </tr> + <tr> + <td valign="top">terse</td> + <td valign="top">Setting this to <code>true</code> will eliminate some of the progress + output generated by <relentless>. This can reduce clutter in some + cases. The default value is <code>false</code>.</td> + <td align="center" valign="top">No</td> + </tr> + </table> + + <h2>Nested elements</h2> + + <h3>task list</h3> + + <p> + The only nested element supported by <relentless> is a list of tasks + to be executed. At least one task must be specified. + </p> + <P> + It is important to note that <relentless> only proceeds relentlessly + from one task to the next - it does <b>not</b> apply recursively to any tasks + that might be invoked by these + nested tasks. If a nested task invokes some other list of tasks (perhaps + by <antcall> for example), and one of those other tasks fails, then the + nested task will stop at that point. + </p> + + <h3>Example</h3> + <p> + A relentless task to print out the first five canonical variable names: + <blockquote> + <pre><relentless description="The first five canonical variable names."> + <echo>foo</echo> + <echo>bar</echo> + <echo>baz</echo> + <echo>bat</echo> + <echo>blah</echo> +</relentless></pre> + </blockquote> + which should produce output looking more or less like + <blockquote> + <pre>[relentless] Relentlessly executing: The first five canonical variable names. +[relentless] Executing: task 1 + [echo] foo +[relentless] Executing: task 2 + [echo] bar +[relentless] Executing: task 3 + [echo] baz +[relentless] Executing: task 4 + [echo] bat +[relentless] Executing: task 5 + [echo] blah +[relentless] All tasks completed successfully.</pre> + </blockquote> + </p> + If you change the first line to set the <code>terse</code> parameter, + <pre> <relentless terse="true" description="The first five canonical variable names."/></pre>the + output will look more like this: + <blockquote> + <pre>[relentless] Relentlessly executing: The first five canonical variable names. + [echo] foo + [echo] bar + [echo] baz + [echo] bat + [echo] blah +[relentless] All tasks completed successfully.</pre> + </blockquote> + </p> + <p> + If we change the third task to deliberately fail + <blockquote> + <pre><relentless terse="true" description="The first five canonical variable names."> + <echo>foo</echo> + <echo>bar</echo> + <fail>baz</fail> + <echo>bat</echo> + <echo>blah</echo> +</relentless></pre> + </blockquote> + then the output should look something like this. + <blockquote> + <pre>[relentless] Relentlessly executing: The first five canonical variable names. + [echo] foo + [echo] bar +[relentless] Task task 3 failed: baz + [echo] bat + [echo] blah + +BUILD FAILED +/home/richter/firmware/sensor/build.xml:1177: Relentless execution: 1 of 5 tasks failed.</pre> + </blockquote> + </p> + <hr> + <p align="center">Copyright © 2005 Ant-Contrib Project. All + rights Reserved.</p> + + </body> +</html> diff --git a/docs/manual/tasks/toc.html b/docs/manual/tasks/toc.html index b1d926f..df60d23 100644 --- a/docs/manual/tasks/toc.html +++ b/docs/manual/tasks/toc.html @@ -14,6 +14,7 @@ <li><a href="for.html" target="mainFrame">For</a></li> <li><a href="if.html" target="mainFrame">If</a></li> <li><a href="outofdate.html" target="mainFrame">Outoutdate</a></li> + <li><a href="relentless.html" target="mainFrame">Relentless</a></li> <li><a href="runtarget.html" target="mainFrame">RunTarget</a></li> <li><a href="switch.html" target="mainFrame">Switch</a></li> <li><a href="throw.html" target="mainFrame">Throw</a></li> diff --git a/src/java/net/sf/antcontrib/antcontrib.properties b/src/java/net/sf/antcontrib/antcontrib.properties index 3ddba23..b42b4ec 100644 --- a/src/java/net/sf/antcontrib/antcontrib.properties +++ b/src/java/net/sf/antcontrib/antcontrib.properties @@ -24,6 +24,7 @@ timestampselector=net.sf.antcontrib.logic.TimestampSelector antcallback=net.sf.antcontrib.logic.AntCallBack
antfetch=net.sf.antcontrib.logic.AntFetch
assert=net.sf.antcontrib.logic.Assert
+relentless=net.sf.antcontrib.logic.Relentless
# Math Tasks
math=net.sf.antcontrib.math.MathTask
diff --git a/src/java/net/sf/antcontrib/logic/Relentless.java b/src/java/net/sf/antcontrib/logic/Relentless.java new file mode 100644 index 0000000..63cabc9 --- /dev/null +++ b/src/java/net/sf/antcontrib/logic/Relentless.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2004-2005 Ant-Contrib project. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.sf.antcontrib.logic; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.TaskContainer; + +import java.util.Iterator; +import java.util.Vector; + +/** Relentless is an Ant task that will relentlessly execute other tasks, + * ignoring any failures until all tasks have completed. If any of the + * executed tasks fail, then Relentless will fail; otherwise it will succeed. + * + * @author Christopher Heiny + * @version $Id$ + */ +public class Relentless extends Task implements TaskContainer { + /** We keep the list of tasks we will execute here. + */ + private Vector taskList = new Vector(); + + /** Flag indicating how much output to generate. + */ + private boolean terse = false; + + /** Creates a new Relentless task. */ + public Relentless() { + } + + /** This method will be called when it is time to execute the task. + */ + public void execute() throws BuildException { + int failCount = 0; + int taskNo = 0; + if ( taskList.size() == 0 ) { + throw new BuildException( "No tasks specified for <relentless>." ); + } + log("Relentlessly executing: " + this.getDescription()); + Iterator iter = taskList.iterator(); + while ( iter.hasNext() ) { + Task t = (Task) iter.next(); + taskNo++; + String desc = t.getDescription(); + if ( desc == null ) { + desc = "task " + taskNo; + } + if (!terse) log("Executing: " + desc); + try { + t.perform(); + } catch (BuildException x) { + log("Task " + desc + " failed: " + x.getMessage()); + failCount++; + } + } + if ( failCount > 0 ) { + throw new BuildException( "Relentless execution: " + failCount + " of " + taskList.size() + " tasks failed." ); + } + else { + log("All tasks completed successfully."); + } + } + + /** Ant will call this to inform us of nested tasks. + */ + public void addTask(org.apache.tools.ant.Task task) { + taskList.add(task); + } + + /** Set this to true to reduce the amount of output generated. + */ + public void setTerse(boolean terse) { + this.terse = terse; + } + + /** Retrieve the terse property, indicating how much output we will generate. + */ + public boolean isTerse() { + return terse; + } + +} diff --git a/test/resources/logic/relentless.xml b/test/resources/logic/relentless.xml new file mode 100644 index 0000000..db25f6b --- /dev/null +++ b/test/resources/logic/relentless.xml @@ -0,0 +1,55 @@ +<project name="relentless unit tests" default="invalid"> + <target name="invalid"> + <fail>Don't call this file directly.</fail> + </target> + + <target name="setup"> + <taskdef resource="net/sf/antcontrib/antcontrib.properties"> + <classpath location="${antcontrib.jar}"/> + </taskdef> + </target> + + <target name="teardown"> + <delete dir="relentless"/> + </target> + + <target name="echo"> + <echo>Called with param: ${param}</echo> + </target> + + <target name="failTask" depends="setup" description="2 tasks should fail" > + <relentless> + <antcall target="echo" > + <param name="param" value="1" /> + </antcall> + <fail message="This task has failed." /> + <antcall target="echo" > + <param name="param" value="3" /> + </antcall> + <fail message="This task has failed as well." /> + </relentless> + </target> + + <target name="simpleTasks" depends="setup"> + <relentless> + <antcall target="echo" > + <param name="param" value="1" /> + </antcall> + <antcall target="echo" > + <param name="param" value="2" /> + </antcall> + <antcall target="echo" > + <param name="param" value="3" /> + </antcall> + <antcall target="echo" > + <param name="param" value="4" /> + </antcall> + </relentless> + </target> + + <target name="noTasks" depends="setup"> + <relentless> + </relentless> + </target> + +</project> diff --git a/test/src/net/sf/antcontrib/logic/RelentlessTaskTest.java b/test/src/net/sf/antcontrib/logic/RelentlessTaskTest.java new file mode 100644 index 0000000..a6b2246 --- /dev/null +++ b/test/src/net/sf/antcontrib/logic/RelentlessTaskTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005 Ant-Contrib project. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.logic; + +import org.apache.tools.ant.BuildFileTest; + +/** + * Testcase for <relentless>. + * @author Christopher Heiny + */ +public class RelentlessTaskTest extends BuildFileTest { + + public RelentlessTaskTest(String name) { + super(name); + } + + public void setUp() { + configureProject("test/resources/logic/relentless.xml"); + } + + public void tearDown() { + executeTarget("teardown"); + } + + public void testSimpleTasks() { + simpleTest("simpleTasks"); + } + + public void testFailTask() { + expectSpecificBuildException("failTask", "2 failed tasks", + "Relentless execution: 2 of 4 tasks failed."); + } + + public void testNoTasks() { + expectSpecificBuildException("noTasks", "missing task list", + "No tasks specified for <relentless>."); + } + + + private void simpleTest(String target) { + executeTarget(target); + int last = -1; + for (int i = 1; i < 4; i++) { + int thisIdx = getLog().indexOf("Called with param: " + i); + assertTrue(thisIdx > last); + last = thisIdx; + } + } +} |