From ea42c65bec22316c5ba3c3096b8346e4a7eed6b8 Mon Sep 17 00:00:00 2001 From: Antoine Levy-Lambert Date: Wed, 21 May 2003 07:27:26 +0000 Subject: [PATCH] changes in subant mainly concerning iterations done inside a dirset new attributes ignoremissingbuildfiles and genericantfile genericantfile allows to run the same build file with different base dirs it is not compulsory any more to set the attribute target to quote quote to run the default target PR: 18715 Submitted by: Andreas Ames (Andreas dot Ames at tenovis dot com) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274600 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/CoreTasks/subant.html | 67 ++++++- .../org/apache/tools/ant/taskdefs/SubAnt.xml | 27 ++- src/etc/testcases/taskdefs/subant.xml | 24 +++ .../taskdefs/subant/genericsubant.xml | 5 + .../taskdefs/subant/subant-test1/mysubant.xml | 5 + .../taskdefs/subant/subant-test2/mysubant.xml | 5 + .../org/apache/tools/ant/taskdefs/SubAnt.java | 106 +++++++++-- .../apache/tools/ant/taskdefs/SubAntTest.java | 170 ++++++++++++++++++ 8 files changed, 391 insertions(+), 18 deletions(-) create mode 100644 src/etc/testcases/taskdefs/subant.xml create mode 100644 src/etc/testcases/taskdefs/subant/genericsubant.xml create mode 100644 src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml create mode 100644 src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java diff --git a/docs/manual/CoreTasks/subant.html b/docs/manual/CoreTasks/subant.html index 4ae44af77..b0829d495 100644 --- a/docs/manual/CoreTasks/subant.html +++ b/docs/manual/CoreTasks/subant.html @@ -54,6 +54,31 @@ Calls a given target for all defined sub-builds. This is an extension of ant for bulk project execution.

+ + + + + +
+ + + Use with directories +
+

+ subant can be used with directory sets to execute a build from different directories. + 2 different options are offered : +

+
    +
  • + to run the same build file /somepath/otherpath/mybuild.xml + with different base directories, use the genericantfile attribute +
  • +
  • if you want to run directory1/mybuild.xml, directory2/mybuild.xml, ...., + use the antfile attribute. The subant task does not set the base directory for you in this case.
    because you can specify it in each build file. +
  • +
+ +
@@ -93,12 +118,12 @@ antfile - Sets the default build file name to append to directory names found in the build path -default "build.xml" + Build file name, to use in conjunction with directories.
Defaults to "build.xml".
If genericantfile is set, this attribute is ignored.
String - + Optional @@ -139,6 +164,30 @@ + + + genericantfile + + + Build file path, to use in conjunction with directories.
Use genericantfile, in order to run the same build file with different basedirs.
If this attribute is set, antfile is ignored.
+ + + File + + + + + + ignoremissingbuildfile + + + Sets whether to continue or fail with a build exception if the build file is missing, false by default. + + + boolean + + + inheritall @@ -163,6 +212,18 @@ + + + output + + + Corresponds to <ant>'s output attribute. + + + String + + + target @@ -204,7 +265,7 @@ Adds a directory set to the implicit build path.

Note that the directories will be added to the build path in no particular order, so if order is significant, one should use a file list instead! - Note that the directories will be added to the build path in no particular o]]>]]> + Note that the directories will be added to the build path in no particular order, so if order is significant, one should use a file list instead!]]> diff --git a/proposal/xdocs/src/org/apache/tools/ant/taskdefs/SubAnt.xml b/proposal/xdocs/src/org/apache/tools/ant/taskdefs/SubAnt.xml index 5cdf9561a..f1326c78c 100644 --- a/proposal/xdocs/src/org/apache/tools/ant/taskdefs/SubAnt.xml +++ b/proposal/xdocs/src/org/apache/tools/ant/taskdefs/SubAnt.xml @@ -8,7 +8,22 @@ Calls a given target for all defined sub-builds. This is an extension of ant for bulk project execution.

- + +

+ subant can be used with directory sets to execute a build from different directories. + 2 different options are offered : +

+
    +
  • + to run the same build file /somepath/otherpath/mybuild.xml + with different base directories, use the genericantfile attribute +
  • +
  • if you want to run directory1/mybuild.xml, directory2/mybuild.xml, ...., + use the antfile attribute. The subant task does not set the base directory for you in this case.
    because you can specify it in each build file. +
  • +
+
+
         <project name="subant" default="subant1">
@@ -41,5 +56,15 @@
             where a file called build.xml can be found.
             All properties whose name starts with "foo" are passed, their names are changed to start with "bar" instead
         

+
+          <subant target="compile" genericantfile="/opt/project/build1.xml">
+             <dirset dir="." includes="projects*"/>
+          </subant>
+        
+

+ assuming the subdirs of the project dir are called projects1, projects2, projects3 + this snippet will execute the compile target of /opt/project/build1.xml, + setting the basedir to projects1, projects2, projects3 +

\ No newline at end of file diff --git a/src/etc/testcases/taskdefs/subant.xml b/src/etc/testcases/taskdefs/subant.xml new file mode 100644 index 000000000..e2c00c01a --- /dev/null +++ b/src/etc/testcases/taskdefs/subant.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/etc/testcases/taskdefs/subant/genericsubant.xml b/src/etc/testcases/taskdefs/subant/genericsubant.xml new file mode 100644 index 000000000..a121a7fa7 --- /dev/null +++ b/src/etc/testcases/taskdefs/subant/genericsubant.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml b/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml new file mode 100644 index 000000000..6c5d17d4d --- /dev/null +++ b/src/etc/testcases/taskdefs/subant/subant-test1/mysubant.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml b/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml new file mode 100644 index 000000000..055267426 --- /dev/null +++ b/src/etc/testcases/taskdefs/subant/subant-test2/mysubant.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java index 292c0b18d..d283f1709 100644 --- a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java +++ b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java @@ -80,9 +80,25 @@ import org.apache.tools.ant.taskdefs.Property; *

* Calls a given target for all defined sub-builds. This is an extension * of ant for bulk project execution. - * + *

+ *

Use with directories

+ *

+ * subant can be used with directory sets to execute a build from different directories. + * 2 different options are offered + *

+ * * @since Ant1.6 * @author Dominique Devienne + * @author Andreas Ames * @ant.task name="subant" category="control" */ public class SubAnt @@ -92,14 +108,16 @@ public class SubAnt private String target = null; private String antfile = "build.xml"; + private File genericantfile = null; private boolean inheritAll = false; private boolean inheritRefs = false; private boolean failOnError = true; + private boolean ignoreMissingBuildFile = false; + private String output = null; private Vector properties = new Vector(); private Vector references = new Vector(); private Vector propertySets = new Vector(); - /** * Runs the various sub-builds. */ @@ -122,11 +140,27 @@ public class SubAnt } */ for (int i=0; ifailOnError is true. Otherwise, * a warning log message is simply output. */ - private void execute(File file) + private void execute(File file, File directory) throws BuildException { if (!file.exists() || file.isDirectory() || !file.canRead()) { String msg = "Invalid file: "+file; @@ -150,7 +185,7 @@ public class SubAnt return; } - Ant ant = createAntTask(); + Ant ant = createAntTask(directory); String antfilename = null; try { antfilename = file.getCanonicalPath(); @@ -172,8 +207,9 @@ public class SubAnt } /** - * Sets the default build file name to append to directory - * names found in the build path -default "build.xml" + * Build file name, to use in conjunction with directories.
+ * Defaults to "build.xml".
+ * If genericantfile is set, this attribute is ignored. * * @param antfile the short build file name. Defaults to "build.xml". */ @@ -181,6 +217,17 @@ public class SubAnt this.antfile = antfile; } + /** + * Build file path, to use in conjunction with directories.
+ * Use genericantfile, in order to run the same build file with different basedirs.
+ * If this attribute is set, antfile is ignored. + * + * @param afile (path of the generic ant file, absolute or relative to project base directory) + * */ + public void setGenericAntfile(File afile) { + this.genericantfile=afile; + } + /** * Sets whether to fail with a build exception on error, or go on. * @@ -190,6 +237,16 @@ public class SubAnt this.failOnError = failOnError; } + /** + * Sets whether to continue or fail with a build exception if the build + * file is missing, false by default. + * + * @param ignoreMissingBuildFile the new value for this boolean flag. + */ + public void setIgnoreMissingBuildFile(boolean ignoreMissingBuildFile) { + this.ignoreMissingBuildFile = ignoreMissingBuildFile; + } + /** * The target to call on the different sub-builds. Set to "" to execute * the default target. @@ -200,6 +257,16 @@ public class SubAnt this.target = target; } + /** + * Corresponds to <ant>'s + * output attribute. + * + * @param s the filename to write the output to. + */ + public void setOutput(String s) { + this.output = s; + } + /** * Corresponds to <ant>'s * inheritall attribute. @@ -288,13 +355,13 @@ public class SubAnt /** * Set the buildpath to be used to find sub-projects. - * + * * @param s an Ant Path object containing the buildpath. */ public void setBuildpath(Path s) { getBuildpath().append(s); } - + /** * Creates a nested build path, and add it to the implicit build path. * @@ -339,26 +406,37 @@ public class SubAnt /** * Creates the <ant> task configured to run a specific target. * + * @param directory : if not null the directory where the build should run + * * @return the ant task, configured with the explicit properties and * references necessary to run the sub-build. */ - private Ant createAntTask() { + private Ant createAntTask(File directory) { Ant ant = (Ant) getProject().createTask("ant"); ant.setOwningTarget(getOwningTarget()); ant.init(); - if(target.length()>0) { + if(target != null && target.length()>0) { ant.setTarget(target); } + + if (output != null) { + ant.setOutput(output); + } + + if (directory != null) { + ant.setDir(directory); + } + ant.setInheritAll(inheritAll); for (Enumeration i = properties.elements(); i.hasMoreElements();) { copyProperty(ant.createProperty(), (Property) i.nextElement()); } - + for (Enumeration i = propertySets.elements(); i.hasMoreElements();) { ant.addPropertyset((PropertySet) i.nextElement()); } - + ant.setInheritRefs(inheritRefs); for (Enumeration i = references.elements(); i.hasMoreElements();) { ant.addReference((Ant.Reference) i.nextElement()); diff --git a/src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java b/src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java new file mode 100644 index 000000000..9cb4c7091 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/SubAntTest.java @@ -0,0 +1,170 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Ant" and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.File; + +import junit.framework.AssertionFailedError; + +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildFileTest; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.input.InputHandler; +import org.apache.tools.ant.types.Path; + +/** + * @author Antoine Levy-Lambert + * @version $Revision$ + */ +public class SubAntTest extends BuildFileTest { + + public SubAntTest(String name) { + super(name); + } + + public void setUp() { + configureProject("src/etc/testcases/taskdefs/subant.xml"); + } + + public void tearDown() { + executeTarget("cleanup"); + } + + public void testnodirs() { + project.executeTarget("testnodirs"); + expectLog("testnodirs", "No sub-builds to iterate on"); + } + + // target must be specified + public void testgenericantfile() { + File dir1 = project.resolveFile("."); + File dir2 = project.resolveFile("subant/subant-test1"); + File dir3 = project.resolveFile("subant/subant-test2"); + + testBaseDirs("testgenericantfile", + new String[] { dir1.getAbsolutePath(), + dir2.getAbsolutePath(), + dir3.getAbsolutePath() + + }); + } + + public void testantfile() { + File dir1 = project.resolveFile("."); + // basedir of subant/subant-test1/subant.xml is .. + // therefore we expect here the subant/subant-test1 subdirectory + File dir2 = project.resolveFile("subant/subant-test1"); + // basedir of subant/subant-test2/subant.xml is .. + // therefore we expect here the subant subdirectory + File dir3 = project.resolveFile("subant"); + + testBaseDirs("testantfile", + new String[] { dir1.getAbsolutePath(), + dir2.getAbsolutePath(), + dir3.getAbsolutePath() + + }); + + } + + protected void testBaseDirs(String target, String[] dirs) { + SubAntTest.BasedirChecker bc = new SubAntTest.BasedirChecker(dirs); + project.addBuildListener(bc); + executeTarget(target); + AssertionFailedError ae = bc.getError(); + if (ae != null) { + throw ae; + } + project.removeBuildListener(bc); + } + + private class BasedirChecker implements BuildListener { + private String[] expectedBasedirs; + private int calls = 0; + private AssertionFailedError error; + + BasedirChecker(String[] dirs) { + expectedBasedirs = dirs; + } + + public void buildStarted(BuildEvent event) {} + public void buildFinished(BuildEvent event) {} + public void targetFinished(BuildEvent event){} + public void taskStarted(BuildEvent event) {} + public void taskFinished(BuildEvent event) {} + public void messageLogged(BuildEvent event) {} + + public void targetStarted(BuildEvent event) { + if (event.getTarget().getName().equals("")) { + return; + } + if (error == null) { + try { + assertEquals(expectedBasedirs[calls++], + event.getProject().getBaseDir().getAbsolutePath()); + } catch (AssertionFailedError e) { + error = e; + } + } + } + + AssertionFailedError getError() { + return error; + } + + } + + +}