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 | defaults to true. If set to false, files that are newer than the | ||||
| files in the archive will not be replaced. | 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: | 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> | that support this feature or at the same level as <code>target</code> | ||||
| - i.e., as children of <code>project</code>.</p> | - i.e., as children of <code>project</code>.</p> | ||||
| <p>PatternSets can be specified as nested | <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"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
| <tr> | <tr> | ||||
| <td valign="top"><b>Attribute</b></td> | <td valign="top"><b>Attribute</b></td> | ||||
| @@ -8,15 +8,17 @@ | |||||
| <body> | <body> | ||||
| <h2><a name="patternset">PatternSet</a></h2> | <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"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
| <tr> | <tr> | ||||
| <td valign="top"><b>Attribute</b></td> | <td valign="top"><b>Attribute</b></td> | ||||
| @@ -30,7 +32,8 @@ directory-based task that constitutes an implicit FileSet. In addition, | |||||
| <tr> | <tr> | ||||
| <td valign="top">includesfile</td> | <td valign="top">includesfile</td> | ||||
| <td valign="top">the name of a file; each line of this file is | <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> | ||||
| <tr> | <tr> | ||||
| <td valign="top">excludes</td> | <td valign="top">excludes</td> | ||||
| @@ -40,7 +43,8 @@ directory-based task that constitutes an implicit FileSet. In addition, | |||||
| <tr> | <tr> | ||||
| <td valign="top">excludesfile</td> | <td valign="top">excludesfile</td> | ||||
| <td valign="top">the name of a file; each line of this file is | <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> | </tr> | ||||
| </table> | </table> | ||||
| @@ -61,9 +65,9 @@ by tasks that support this feature, or by FileSets.</p> | |||||
| multiple elements separated by commas or spaces, the nested | multiple elements separated by commas or spaces, the nested | ||||
| <include> and <exclude> elements expect their name | <include> and <exclude> elements expect their name | ||||
| attribute to hold a single pattern.</p> | 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> | <p>For example</p> | ||||
| <blockquote><pre> | <blockquote><pre> | ||||
| <patternset id="sources" > | <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> | </pre></blockquote> | ||||
| <p>will only include the files in the sub-directory <em>prof</em> if the property | <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> | <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> | <hr> | ||||
| <p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | <p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | ||||
| Reserved.</p> | 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 | 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 | is taken as a pattern that is added to the list of include or exclude | ||||
| patterns.</p> | patterns.</p> | ||||
| <h3>Patterns</h3> | |||||
| <h3><a name="patterns">Patterns</a></h3> | |||||
| <p>As described earlier, patterns are used for the inclusion and exclusion. | <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> | These patterns look very much like the patterns used in DOS and UNIX:</p> | ||||
| <p>'*' matches zero or more characters, '?' matches one character.</p> | <p>'*' matches zero or more characters, '?' matches one character.</p> | ||||
| @@ -83,6 +83,13 @@ public abstract class MatchingTask extends Task { | |||||
| return fileset.createInclude(); | 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 | * add a name entry on the exclude list | ||||
| */ | */ | ||||
| @@ -90,6 +97,13 @@ public abstract class MatchingTask extends Task { | |||||
| return fileset.createExclude(); | return fileset.createExclude(); | ||||
| } | } | ||||
| /** | |||||
| * add a name entry on the include files list | |||||
| */ | |||||
| public PatternSet.NameEntry createExcludesFile() { | |||||
| return fileset.createExcludesFile(); | |||||
| } | |||||
| /** | /** | ||||
| * add a set of patterns | * add a set of patterns | ||||
| */ | */ | ||||
| @@ -145,6 +145,16 @@ public class FileSet extends DataType { | |||||
| return defaultPatterns.createInclude(); | 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 | * add a name entry on the exclude list | ||||
| */ | */ | ||||
| @@ -155,6 +165,16 @@ public class FileSet extends DataType { | |||||
| return defaultPatterns.createExclude(); | 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 | * Sets the set of include patterns. Patterns may be separated by a comma | ||||
| * or a space. | * or a space. | ||||
| @@ -79,9 +79,8 @@ import java.util.Vector; | |||||
| public class PatternSet extends DataType { | public class PatternSet extends DataType { | ||||
| private Vector includeList = new Vector(); | private Vector includeList = new Vector(); | ||||
| private Vector excludeList = 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 | * inner class to hold a name on list. "If" and "Unless" attributes | ||||
| @@ -122,23 +121,18 @@ public class PatternSet extends DataType { | |||||
| return true; | 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(":"); | buf.append(":"); | ||||
| String connector = ""; | String connector = ""; | ||||
| if (ifCond != null) | |||||
| { | |||||
| if (ifCond != null) { | |||||
| buf.append("if->"); | buf.append("if->"); | ||||
| buf.append(ifCond); | buf.append(ifCond); | ||||
| connector = ";"; | connector = ";"; | ||||
| } | } | ||||
| if (unlessCond != null) | |||||
| { | |||||
| if (unlessCond != null) { | |||||
| buf.append(connector); | buf.append(connector); | ||||
| buf.append("unless->"); | buf.append("unless->"); | ||||
| buf.append(unlessCond); | buf.append(unlessCond); | ||||
| @@ -176,6 +170,16 @@ public class PatternSet extends DataType { | |||||
| } | } | ||||
| return addPatternToList(includeList); | 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 | * add a name entry on the exclude list | ||||
| @@ -186,6 +190,16 @@ public class PatternSet extends DataType { | |||||
| } | } | ||||
| return addPatternToList(excludeList); | 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 | * 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. | * 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()) { | if (isReference()) { | ||||
| throw tooManyAttributes(); | 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. | * 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()) { | if (isReference()) { | ||||
| throw tooManyAttributes(); | 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. | * helper for FileSet. | ||||
| */ | */ | ||||
| boolean hasPatterns() { | boolean hasPatterns() { | ||||
| return incl != null || excl != null | |||||
| return includesFileList.size() > 0 || excludesFileList.size() > 0 | |||||
| || includeList.size() > 0 || excludeList.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) { | 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", | assertEquals("You must not specify nested elements when using refid", | ||||
| be.getMessage()); | 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 { | try { | ||||
| f.createPatternSet(); | f.createPatternSet(); | ||||
| fail("Can add nested patternset in FileSet that is a reference."); | 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", | assertEquals("You must not specify nested elements when using refid", | ||||
| be.getMessage()); | 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() { | public void testCircularReferenceCheck() { | ||||