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() { | ||||