thus allowing for more than one file of each type. Submitted by: Mark Womack <mwomack@bevocal.com> Add pointer to "Directory Based Tasks" in the documentation of patternsets where patterns are actually defined. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269419 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -131,6 +131,10 @@ Other changes: | |||
| defaults to true. If set to false, files that are newer than the | |||
| files in the archive will not be replaced. | |||
| * <patternset> and <fileset> now support nested <in/excludesfile> | |||
| elements - using these you can have more than one in/excludes file | |||
| per <patternset>. | |||
| Fixed bugs: | |||
| ----------- | |||
| @@ -15,11 +15,12 @@ href="patternset.html">PatternSets</a>. FileSets can appear inside tasks | |||
| that support this feature or at the same level as <code>target</code> | |||
| - i.e., as children of <code>project</code>.</p> | |||
| <p>PatternSets can be specified as nested | |||
| <code><patternset></code> | |||
| elements. In addition, FileSet holds an implicit PatternSet and | |||
| supports the nested <code><include></code> and | |||
| <code><exclude></code> elements of PatternSet directly, as well | |||
| as PatternSet's attributes.</p> | |||
| <code><patternset></code> elements. In addition, FileSet holds | |||
| an implicit PatternSet and supports the nested | |||
| <code><include></code>, <code><includesfile></code>, | |||
| <code><exclude></code> and <code><excludesfile></code> | |||
| elements of PatternSet directly, as well as PatternSet's | |||
| attributes.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| @@ -8,15 +8,17 @@ | |||
| <body> | |||
| <h2><a name="patternset">PatternSet</a></h2> | |||
| <p>Patterns can be grouped to sets and later be referenced by their | |||
| <code>id</code> | |||
| attribute. They are defined via a <code>patternset</code> element, | |||
| which can appear nested into a <a href="fileset.html">FileSet</a> or a | |||
| directory-based task that constitutes an implicit FileSet. In addition, | |||
| <code>patternset</code>s can be defined at the same level as | |||
| <code>target</code> — i.e., as children of <code>project</code>.</p> | |||
| <p>Patterns can be specified by nested <code><include></code> or | |||
| <code><exclude></code> elements or the following attributes.</p> | |||
| <p><a href="../dirtasks.html#patterns">Patterns</a> can be grouped to | |||
| sets and later be referenced by their <code>id</code> attribute. They | |||
| are defined via a <code>patternset</code> element, which can appear | |||
| nested into a <a href="fileset.html">FileSet</a> or a directory-based | |||
| task that constitutes an implicit FileSet. In addition, | |||
| <code>patternset</code>s can be defined as a stand alone element at | |||
| the same level as <code>target</code> — i.e., as children of | |||
| <code>project</code> as well as as children of | |||
| <code>target</code>.</p> <p>Patterns can be specified by nested | |||
| <code><include></code>, or <code><exclude></code> elements | |||
| or the following attributes.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| @@ -30,7 +32,8 @@ directory-based task that constitutes an implicit FileSet. In addition, | |||
| <tr> | |||
| <td valign="top">includesfile</td> | |||
| <td valign="top">the name of a file; each line of this file is | |||
| taken to be an include pattern.</td> | |||
| taken to be an include pattern. You can specify more than one | |||
| include file by using a nested includesfile elements.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">excludes</td> | |||
| @@ -40,7 +43,8 @@ directory-based task that constitutes an implicit FileSet. In addition, | |||
| <tr> | |||
| <td valign="top">excludesfile</td> | |||
| <td valign="top">the name of a file; each line of this file is | |||
| taken to be an exclude pattern.</td> | |||
| taken to be an exclude pattern. You can specify more than one | |||
| exclude file by using a nested excludesfile elements.</td> | |||
| </tr> | |||
| </table> | |||
| @@ -61,9 +65,9 @@ by tasks that support this feature, or by FileSets.</p> | |||
| multiple elements separated by commas or spaces, the nested | |||
| <include> and <exclude> elements expect their name | |||
| attribute to hold a single pattern.</p> | |||
| <p>The nested <include> and <exclude> elements allow you to use | |||
| if and unless arguments to specify that the element should only be used if a | |||
| property is set, or that it should be used only if a property is not set.</p> | |||
| <p>The nested elements allow you to use if and unless arguments to | |||
| specify that the element should only be used if a property is set, or | |||
| that it should be used only if a property is not set.</p> | |||
| <p>For example</p> | |||
| <blockquote><pre> | |||
| <patternset id="sources" > | |||
| @@ -74,7 +78,34 @@ property is set, or that it should be used only if a property is not set.</p> | |||
| </pre></blockquote> | |||
| <p>will only include the files in the sub-directory <em>prof</em> if the property | |||
| <em>professional</em> is set to some value.</p> | |||
| <p>If you want to list the files to include or exclude external to | |||
| your build file, you should use the includesfile/excludesfile | |||
| attributes or elements. Using the attribute, you can only specify a | |||
| single file of each type, while the nested elements can be specified | |||
| more than once - the nested elements also support if/unless attributes | |||
| you can use to test the existance of a property. For example:</p> | |||
| <blockquote><pre> | |||
| <patternset includesfile="some-file" /> | |||
| </pre></blockquote> | |||
| <p>and</p> | |||
| <blockquote><pre> | |||
| <patternset> | |||
| <includesfile name="some-file" /> | |||
| <patternset/> | |||
| </pre></blockquote> | |||
| <p>are identical. The include patterns will be read from the file | |||
| <code>some-file</code>, one pattern per line.</p> | |||
| <blockquote><pre> | |||
| <patternset> | |||
| <includesfile name="some-file" /> | |||
| <includesfile name="${some-other-file}" | |||
| if="some-other-file" | |||
| /> | |||
| <patternset/> | |||
| </pre></blockquote> | |||
| <p>will also read include patterns from the file the property | |||
| <code>some-other-file</code> points to, if a property of that name has | |||
| been defined.</p> | |||
| <hr> | |||
| <p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| @@ -28,7 +28,7 @@ the include patterns, and don't match the exclude patterns, are used.</p> | |||
| nested elements and via external files. Each line of the external file | |||
| is taken as a pattern that is added to the list of include or exclude | |||
| patterns.</p> | |||
| <h3>Patterns</h3> | |||
| <h3><a name="patterns">Patterns</a></h3> | |||
| <p>As described earlier, patterns are used for the inclusion and exclusion. | |||
| These patterns look very much like the patterns used in DOS and UNIX:</p> | |||
| <p>'*' matches zero or more characters, '?' matches one character.</p> | |||
| @@ -83,6 +83,13 @@ public abstract class MatchingTask extends Task { | |||
| return fileset.createInclude(); | |||
| } | |||
| /** | |||
| * add a name entry on the include files list | |||
| */ | |||
| public PatternSet.NameEntry createIncludesFile() { | |||
| return fileset.createIncludesFile(); | |||
| } | |||
| /** | |||
| * add a name entry on the exclude list | |||
| */ | |||
| @@ -90,6 +97,13 @@ public abstract class MatchingTask extends Task { | |||
| return fileset.createExclude(); | |||
| } | |||
| /** | |||
| * add a name entry on the include files list | |||
| */ | |||
| public PatternSet.NameEntry createExcludesFile() { | |||
| return fileset.createExcludesFile(); | |||
| } | |||
| /** | |||
| * add a set of patterns | |||
| */ | |||
| @@ -145,6 +145,16 @@ public class FileSet extends DataType { | |||
| return defaultPatterns.createInclude(); | |||
| } | |||
| /** | |||
| * add a name entry on the include files list | |||
| */ | |||
| public PatternSet.NameEntry createIncludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| return defaultPatterns.createIncludesFile(); | |||
| } | |||
| /** | |||
| * add a name entry on the exclude list | |||
| */ | |||
| @@ -155,6 +165,16 @@ public class FileSet extends DataType { | |||
| return defaultPatterns.createExclude(); | |||
| } | |||
| /** | |||
| * add a name entry on the include files list | |||
| */ | |||
| public PatternSet.NameEntry createExcludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| return defaultPatterns.createExcludesFile(); | |||
| } | |||
| /** | |||
| * Sets the set of include patterns. Patterns may be separated by a comma | |||
| * or a space. | |||
| @@ -79,9 +79,8 @@ import java.util.Vector; | |||
| public class PatternSet extends DataType { | |||
| private Vector includeList = new Vector(); | |||
| private Vector excludeList = new Vector(); | |||
| private File incl = null; | |||
| private File excl = null; | |||
| private Vector includesFileList = new Vector(); | |||
| private Vector excludesFileList = new Vector(); | |||
| /** | |||
| * inner class to hold a name on list. "If" and "Unless" attributes | |||
| @@ -122,23 +121,18 @@ public class PatternSet extends DataType { | |||
| return true; | |||
| } | |||
| public String toString() | |||
| { | |||
| StringBuffer buf = new StringBuffer(); | |||
| buf.append( name ); | |||
| if ((ifCond != null) || (unlessCond != null)) | |||
| { | |||
| public String toString() { | |||
| StringBuffer buf = new StringBuffer(name); | |||
| if ((ifCond != null) || (unlessCond != null)) { | |||
| buf.append(":"); | |||
| String connector = ""; | |||
| if (ifCond != null) | |||
| { | |||
| if (ifCond != null) { | |||
| buf.append("if->"); | |||
| buf.append(ifCond); | |||
| connector = ";"; | |||
| } | |||
| if (unlessCond != null) | |||
| { | |||
| if (unlessCond != null) { | |||
| buf.append(connector); | |||
| buf.append("unless->"); | |||
| buf.append(unlessCond); | |||
| @@ -176,6 +170,16 @@ public class PatternSet extends DataType { | |||
| } | |||
| return addPatternToList(includeList); | |||
| } | |||
| /** | |||
| * add a name entry on the include files list | |||
| */ | |||
| public NameEntry createIncludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| return addPatternToList(includesFileList); | |||
| } | |||
| /** | |||
| * add a name entry on the exclude list | |||
| @@ -186,6 +190,16 @@ public class PatternSet extends DataType { | |||
| } | |||
| return addPatternToList(excludeList); | |||
| } | |||
| /** | |||
| * add a name entry on the exclude files list | |||
| */ | |||
| public NameEntry createExcludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| return addPatternToList(excludesFileList); | |||
| } | |||
| /** | |||
| * Sets the set of include patterns. Patterns may be separated by a comma | |||
| @@ -235,33 +249,25 @@ public class PatternSet extends DataType { | |||
| /** | |||
| * Sets the name of the file containing the includes patterns. | |||
| * | |||
| * @param incl The file to fetch the include patterns from. | |||
| * @param includesFile The file to fetch the include patterns from. | |||
| */ | |||
| public void setIncludesfile(File incl) throws BuildException { | |||
| public void setIncludesfile(File includesFile) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| if (!incl.exists()) { | |||
| throw new BuildException("Includesfile "+incl.getAbsolutePath() | |||
| +" not found."); | |||
| } | |||
| this.incl = incl; | |||
| createIncludesFile().setName(includesFile.getAbsolutePath()); | |||
| } | |||
| /** | |||
| * Sets the name of the file containing the excludes patterns. | |||
| * | |||
| * @param excl The file to fetch the exclude patterns from. | |||
| * @param excludesFile The file to fetch the exclude patterns from. | |||
| */ | |||
| public void setExcludesfile(File excl) throws BuildException { | |||
| public void setExcludesfile(File excludesFile) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| if (!excl.exists()) { | |||
| throw new BuildException("Excludesfile "+excl.getAbsolutePath() | |||
| +" not found."); | |||
| } | |||
| this.excl = excl; | |||
| createExcludesFile().setName(excludesFile.getAbsolutePath()); | |||
| } | |||
| /** | |||
| @@ -345,7 +351,7 @@ public class PatternSet extends DataType { | |||
| * helper for FileSet. | |||
| */ | |||
| boolean hasPatterns() { | |||
| return incl != null || excl != null | |||
| return includesFileList.size() > 0 || excludesFileList.size() > 0 | |||
| || includeList.size() > 0 || excludeList.size() > 0; | |||
| } | |||
| @@ -390,23 +396,42 @@ public class PatternSet extends DataType { | |||
| } | |||
| /** | |||
| * Read includefile ot excludefile if not already done so. | |||
| * Read includesfile ot excludesfile if not already done so. | |||
| */ | |||
| private void readFiles(Project p) { | |||
| if (incl != null) { | |||
| readPatterns(incl, includeList, p); | |||
| incl = null; | |||
| } | |||
| if (excl != null) { | |||
| readPatterns(excl, excludeList, p); | |||
| excl = null; | |||
| if (includesFileList.size() > 0) { | |||
| Enumeration e = includesFileList.elements(); | |||
| while (e.hasMoreElements()) { | |||
| NameEntry ne = (NameEntry)e.nextElement(); | |||
| String fileName = ne.evalName(p); | |||
| if (fileName != null) { | |||
| File inclFile = p.resolveFile(fileName); | |||
| if (!inclFile.exists()) | |||
| throw new BuildException("Includesfile " | |||
| + inclFile.getAbsolutePath() | |||
| + " not found."); | |||
| readPatterns(inclFile, includeList, p); | |||
| } | |||
| } | |||
| includesFileList.clear(); | |||
| } | |||
| } | |||
| public String toString() | |||
| { | |||
| return "patternSet{ includes: " + includeList + | |||
| " excludes: " + excludeList + " }"; | |||
| if (excludesFileList.size() > 0) { | |||
| Enumeration e = includesFileList.elements(); | |||
| while (e.hasMoreElements()) { | |||
| NameEntry ne = (NameEntry)e.nextElement(); | |||
| String fileName = ne.evalName(p); | |||
| if (fileName != null) { | |||
| File exclFile = p.resolveFile(fileName); | |||
| if (!exclFile.exists()) | |||
| throw new BuildException("Excludesfile " | |||
| + exclFile.getAbsolutePath() | |||
| + " not found."); | |||
| readPatterns(exclFile, excludeList, p); | |||
| } | |||
| } | |||
| excludesFileList.clear(); | |||
| } | |||
| } | |||
| } | |||
| @@ -165,6 +165,20 @@ public class FileSetTest extends TestCase { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| try { | |||
| f.createIncludesFile(); | |||
| fail("Can add nested includesfile in FileSet that is a reference."); | |||
| } catch (BuildException be) { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| try { | |||
| f.createExcludesFile(); | |||
| fail("Can add nested excludesfile in FileSet that is a reference."); | |||
| } catch (BuildException be) { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| try { | |||
| f.createPatternSet(); | |||
| fail("Can add nested patternset in FileSet that is a reference."); | |||
| @@ -141,6 +141,20 @@ public class PatternSetTest extends TestCase { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| try { | |||
| p.createIncludesFile(); | |||
| fail("Can add nested includesfile in PatternSet that is a reference."); | |||
| } catch (BuildException be) { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| try { | |||
| p.createExcludesFile(); | |||
| fail("Can add nested excludesfile in PatternSet that is a reference."); | |||
| } catch (BuildException be) { | |||
| assertEquals("You must not specify nested elements when using refid", | |||
| be.getMessage()); | |||
| } | |||
| } | |||
| public void testCircularReferenceCheck() { | |||