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