Browse Source

resource collection support for apply and friends

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@292251 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 20 years ago
parent
commit
a7d38cf263
8 changed files with 182 additions and 69 deletions
  1. +22
    -1
      docs/manual/CoreTasks/apply.html
  2. +4
    -0
      docs/manual/CoreTasks/chmod.html
  3. +4
    -0
      docs/manual/OptionalTasks/attrib.html
  4. +4
    -0
      docs/manual/OptionalTasks/chgrp.html
  5. +3
    -0
      docs/manual/OptionalTasks/chown.html
  6. +32
    -0
      src/etc/testcases/taskdefs/exec/apply.xml
  7. +92
    -68
      src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
  8. +21
    -0
      src/testcases/org/apache/tools/ant/taskdefs/ExecuteOnTest.java

+ 22
- 1
docs/manual/CoreTasks/apply.html View File

@@ -16,12 +16,16 @@ compatibility.</i></p>
<p>Executes a system command. When the <i>os</i> attribute is specified, then
the command is only executed when Ant is run on one of the specified operating
systems.</p>
<p>The files and/or directories of a number of

<p>The files and/or directories of a number of <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
&ndash; including but not restricted to
<a href="../CoreTypes/fileset.html">FileSet</a>s,
<a href="../CoreTypes/dirset.html">DirSet</a>s
(<em>since&nbsp;Ant&nbsp;1.6</em>) or
<a href="../CoreTypes/filelist.html">FileList</a>s
(<em>since&nbsp;Ant&nbsp;1.6</em>)
&ndash;
are passed as arguments to the system command.</p>
<p>If you specify a nested <a href="../CoreTypes/mapper.html">mapper</a>,
the timestamp of each source file is compared to the timestamp of a
@@ -283,6 +287,12 @@ elements to define the files for this task and refer to
<p>You can use any number of nested <code>&lt;dirset&gt;</code>
elements to define the directories for this task and refer to
<code>&lt;dirset&gt;</code>s defined elsewhere.</p>

<h4>Any other <a href="../CoreTypes/resources.html#collection">Resource
Collection</a></h4>
<p><em>since Ant 1.7</em></p>
<p>You can use any number of nested resource collections.</p>

<h4>mapper</h4>
<p>A single <code>&lt;mapper&gt;</code> specifies the target files relative
to the <code>dest</code> attribute for dependency checking. If the
@@ -385,6 +395,17 @@ task. A reference to <code>out</code> is then used as an
<code>&lt;outputmapper&gt;</code> nested in a <code>&lt;redirector&gt;</code>, which in turn is
nested beneath this <code>&lt;apply&gt;</code> instance. This allows us to perform
dependency checking against output files--the target files in this case.
<blockquote><pre>
&lt;apply executable="ls" parallel="true"
force="true" dest="${basedir}" append="true" type="both"&gt;
&lt;path&gt;
&lt;pathelement path="${env.PATH}"/&gt;
&lt;/path&gt;
&lt;identitymapper/&gt;
&lt;/apply&gt;
</pre></blockquote>
Applies the "ls" executable to all directories in the PATH, effectively
listing all executables that are available on the PATH.

<hr><p align="center">Copyright &copy; 2000-2005 The Apache Software Foundation. All rights
Reserved.</p>


+ 4
- 0
docs/manual/CoreTasks/chmod.html View File

@@ -26,6 +26,10 @@ specified using nested <code>&lt;fileset&gt;</code> or
<p>Starting with Ant 1.6, this task also supports nested <a
href="../CoreTypes/filelist.html">filelist</a>s.</p>

<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying
chmod command. If you are working on a large number of files this may
result in a command line that is too long for your operating system.


+ 4
- 0
docs/manual/OptionalTasks/attrib.html View File

@@ -23,6 +23,10 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p>

<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying
attrib command. If you are working on a large number of files this
may result in a command line that is too long for your operating


+ 4
- 0
docs/manual/OptionalTasks/chgrp.html View File

@@ -23,6 +23,10 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p>

<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying
chgrp command. If you are working on a large number of files this may
result in a command line that is too long for your operating system.


+ 3
- 0
docs/manual/OptionalTasks/chown.html View File

@@ -23,6 +23,9 @@ href="../CoreTypes/filelist.html">FileList</a>s can be specified using
nested <code>&lt;fileset&gt;</code>, <code>&lt;dirset&gt;</code> and
<code>&lt;filelist&gt;</code> elements.</p>

<p>Starting with Ant 1.7, this task supports arbitrary <a
href="../CoreTypes/resources.html#collection">Resource Collection</a>s
as nested elements.</p>

<p>By default this task will use a single invocation of the underlying
chown command. If you are working on a large number of files this may


+ 32
- 0
src/etc/testcases/taskdefs/exec/apply.xml View File

@@ -31,6 +31,17 @@
<isset property="echo.exe.executable"/>
</or>
</condition>

<!-- UNIX -->
<available file="ls" filepath="${env.PATH}" property="ls.executable"/>
<!-- CYGWIN -->
<available file="ls.exe" filepath="${env.PATH}" property="ls.exe.executable"/>
<condition property="ls.can.run">
<or>
<isset property="ls.executable"/>
<isset property="ls.exe.executable"/>
</or>
</condition>
</target>

<target name="xyz">
@@ -394,6 +405,7 @@

<ekko outputproperty="foo" />
<ekko outputproperty="bar" force="true" />

<fail>
<condition>
<not>
@@ -428,6 +440,26 @@
</fail>
</target>

<target name="lsPath" depends="init" if="ls.can.run">
<apply executable="ls" parallel="false" outputproperty="foo"
force="true" dest="${basedir}" append="true" type="both">
<path>
<pathelement path="${env.PATH}"/>
</path>
<identitymapper/>
</apply>
</target>

<target name="lsPathParallel" depends="init" if="ls.can.run">
<apply executable="ls" parallel="true" outputproperty="foo"
force="true" dest="${basedir}" append="true" type="both">
<path>
<pathelement path="${env.PATH}"/>
</path>
<identitymapper/>
</apply>
</target>

<target name="cleanup">
<delete>
<fileset refid="xyz" />


+ 92
- 68
src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java View File

@@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
@@ -31,6 +32,10 @@ import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileList;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.SourceFileScanner;

@@ -43,13 +48,20 @@ import org.apache.tools.ant.util.SourceFileScanner;
*/
public class ExecuteOn extends ExecTask {

// filesets has been protected so we need to keep that even after
// switching to resource collections. In fact, they will still
// get a different treatment form the other resource collections
// even in execute since we have some subtle special features like
// switching type to "dir" when we encounter a DirSet that would
// be more difficult to achieve otherwise.

protected Vector filesets = new Vector(); // contains AbstractFileSet
// (both DirSet and FileSet)
private Vector filelists = new Vector();
private Union resources = new Union();
private boolean relative = false;
private boolean parallel = false;
private boolean forwardSlash = false;
protected String type = "file";
protected String type = FileDirBoth.FILE;
protected Commandline.Marker srcFilePos = null;
private boolean skipEmpty = false;
protected Commandline.Marker targetFilePos = null;
@@ -91,7 +103,18 @@ public class ExecuteOn extends ExecTask {
* @param list the FileList to add.
*/
public void addFilelist(FileList list) {
filelists.addElement(list);
add(list);
}

/**
* Add a collection of resources upon which to operate.
* @param rc resource collection to add.
* @since Ant 1.7
*/
public void add(ResourceCollection rc) {
if (rc instanceof FileSet)
throw new BuildException("Huh?");
resources.add(rc);
}

/**
@@ -273,8 +296,8 @@ public class ExecuteOn extends ExecTask {
log("!! execon is deprecated. Use apply instead. !!");
}
super.checkConfiguration();
if (filesets.size() == 0 && filelists.size() == 0) {
throw new BuildException("no filesets and no filelists specified",
if (filesets.size() == 0 && resources.size() == 0) {
throw new BuildException("no resources specified",
getLocation());
}
if (targetFilePos != null && mapperElement == null) {
@@ -326,19 +349,19 @@ public class ExecuteOn extends ExecTask {
String currentType = type;
AbstractFileSet fs = (AbstractFileSet) filesets.elementAt(i);
if (fs instanceof DirSet) {
if (!"dir".equals(type)) {
if (!FileDirBoth.DIR.equals(type)) {
log("Found a nested dirset but type is " + type + ". "
+ "Temporarily switching to type=\"dir\" on the"
+ " assumption that you really did mean"
+ " <dirset> not <fileset>.", Project.MSG_DEBUG);
currentType = "dir";
currentType = FileDirBoth.DIR;
}
}
File base = fs.getDir(getProject());

DirectoryScanner ds = fs.getDirectoryScanner(getProject());

if (!"dir".equals(currentType)) {
if (!FileDirBoth.DIR.equals(currentType)) {
String[] s = getFiles(base, ds);
for (int j = 0; j < s.length; j++) {
totalFiles++;
@@ -346,7 +369,7 @@ public class ExecuteOn extends ExecTask {
baseDirs.addElement(base);
}
}
if (!"file".equals(currentType)) {
if (!FileDirBoth.FILE.equals(currentType)) {
String[] s = getDirs(base, ds);
for (int j = 0; j < s.length; j++) {
totalDirs++;
@@ -356,9 +379,9 @@ public class ExecuteOn extends ExecTask {
}
if (fileNames.size() == 0 && skipEmpty) {
int includedCount
= ((!"dir".equals(currentType))
= ((!FileDirBoth.DIR.equals(currentType))
? ds.getIncludedFilesCount() : 0)
+ ((!"file".equals(currentType))
+ ((!FileDirBoth.FILE.equals(currentType))
? ds.getIncludedDirsCount() : 0);

log("Skipping fileset for directory " + base + ". It is "
@@ -392,68 +415,67 @@ public class ExecuteOn extends ExecTask {
baseDirs.removeAllElements();
}
}
for (int i = 0; i < filelists.size(); i++) {
FileList list = (FileList) filelists.elementAt(i);
File base = list.getDir(getProject());
String[] names = getFilesAndDirs(list);

for (int j = 0; j < names.length; j++) {
File f = new File(base, names[j]);
if ((!ignoreMissing) || (f.isFile() && !"dir".equals(type))
|| (f.isDirectory() && !"file".equals(type))) {

if (ignoreMissing || f.isFile()) {
totalFiles++;
} else {
totalDirs++;
}
fileNames.addElement(names[j]);
baseDirs.addElement(base);
}
}
if (fileNames.size() == 0 && skipEmpty) {
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(base);
ds.setIncludes(list.getFiles(getProject()));
ds.scan();
int includedCount
= ds.getIncludedFilesCount() + ds.getIncludedDirsCount();
Iterator iter = resources.iterator();
while (iter.hasNext()) {
Resource res = (Resource) iter.next();

if (!res.isExists() && ignoreMissing) {
continue;
}

File base = null;
String name = res.getName();
if (res instanceof FileResource) {
FileResource fr = (FileResource) res;
base = fr.getBaseDir();
if (base == null) {
name = fr.getFile().getAbsolutePath();
}
}

if (restrict(new String[] {name}, base).length == 0) {
continue;
}

if ((!res.isDirectory() || !res.isExists())
&& !FileDirBoth.DIR.equals(type)) {
totalFiles++;
} else if (res.isDirectory() && !FileDirBoth.FILE.equals(type)) {
totalDirs++;
} else {
continue;
}

baseDirs.add(base);
fileNames.add(name);

log("Skipping filelist for directory " + base + ". It is "
+ ((includedCount > 0) ? "up to date." : "empty."),
Project.MSG_INFO);
continue;
}
if (!parallel) {
String[] s = new String[fileNames.size()];
fileNames.copyInto(s);
for (int j = 0; j < s.length; j++) {
String[] command = getCommandline(s[j], base);
log(Commandline.describeCommand(command),
Project.MSG_VERBOSE);
exe.setCommandline(command);

if (redirectorElement != null) {
setupRedirector();
redirectorElement.configure(redirector, s[j]);
}
if (redirectorElement != null || haveExecuted) {
// need to reset the stream handler to restart
// reading of pipes;
// go ahead and do it always w/ nested redirectors
exe.setStreamHandler(redirector.createHandler());
}
runExecute(exe);
haveExecuted = true;
}
fileNames.removeAllElements();
baseDirs.removeAllElements();
}
String[] command = getCommandline(name, base);
log(Commandline.describeCommand(command),
Project.MSG_VERBOSE);
exe.setCommandline(command);

if (redirectorElement != null) {
setupRedirector();
redirectorElement.configure(redirector, name);
}
if (redirectorElement != null || haveExecuted) {
// need to reset the stream handler to restart
// reading of pipes;
// go ahead and do it always w/ nested redirectors
exe.setStreamHandler(redirector.createHandler());
}
runExecute(exe);
haveExecuted = true;
fileNames.removeAllElements();
baseDirs.removeAllElements();
}
}
if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
runParallel(exe, fileNames, baseDirs);
haveExecuted = true;
}
}
if (haveExecuted) {
log("Applied " + cmdl.getExecutable() + " to "
+ totalFiles + " file"
@@ -697,11 +719,13 @@ public class ExecuteOn extends ExecTask {
* for the type attribute.
*/
public static class FileDirBoth extends EnumeratedAttribute {
public static final String FILE = "file";
public static final String DIR = "dir";
/**
* @see EnumeratedAttribute#getValues
*/
public String[] getValues() {
return new String[] {"file", "dir", "both"};
return new String[] {FILE, DIR, "both"};
}
}
}

+ 21
- 0
src/testcases/org/apache/tools/ant/taskdefs/ExecuteOnTest.java View File

@@ -31,6 +31,7 @@ import java.io.OutputStream;
public class ExecuteOnTest extends BuildFileTest {
private static final String BUILD_PATH = "src/etc/testcases/taskdefs/exec/";
private static final String BUILD_FILE = BUILD_PATH + "apply.xml";
private static final String LINE_SEP = System.getProperty("line.separator");
public ExecuteOnTest(String name) {
super(name);
@@ -562,6 +563,26 @@ public class ExecuteOnTest extends BuildFileTest {
executeTarget("testNoDest");
}

public void testLsPath() {
testLsPath("lsPath");
}

public void testLsPathParallel() {
testLsPath("lsPathParallel");
}

private void testLsPath(String target) {
executeTarget(target);
if (getProject().getProperty("ls.can.run") == null) {
return;
}
String foo = getProject().getProperty("foo");
assertNotNull(foo);
int indNoExt = foo.indexOf("ls" + LINE_SEP);
int indExe = foo.indexOf("ls.exe" + LINE_SEP);
assertTrue(indNoExt >= 0 || indExe >= 0);
}

//borrowed from TokenFilterTest
private String getFileString(String filename) throws IOException {
String result = null;


Loading…
Cancel
Save