Browse Source

You can now limit the parallelism of <apply> and <chmod> by using the

new maxparallel attribute.
Submitted by:	Frank A. Hunleth <fhunleth at cs dot wustl dot edu>
used in build.xml to fix PR: 17640

With the new addsourcefile attribute, you can make <apply> ommit the
source file names from the command line.
PR: 13654

<apply> and <chmod> now support nested <filelist>s as well.
PR: 15929

<apply> and <chmod> will display a summary if you set the new verbose
attribute to true.
PR: 19883


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274587 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
0d7f1ce40f
6 changed files with 224 additions and 17 deletions
  1. +12
    -0
      WHATSNEW
  2. +3
    -2
      build.xml
  3. +33
    -5
      docs/manual/CoreTasks/apply.html
  4. +17
    -0
      docs/manual/CoreTasks/chmod.html
  5. +8
    -0
      src/main/org/apache/tools/ant/taskdefs/Chmod.java
  6. +151
    -10
      src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java

+ 12
- 0
WHATSNEW View File

@@ -346,6 +346,18 @@ Other changes:
that can be used to turn of Microsoft extensions while using the jvc that can be used to turn of Microsoft extensions while using the jvc
compiler. Bugzilla Report 19826. compiler. Bugzilla Report 19826.


* You can now limit the parallelism of <apply> and <chmod> by using the new
maxparallel attribute.

* With the new addsourcefile attribute, you can make <apply> ommit the
source file names from the command line. Bugzilla Report 13654.

* <apply> and <chmod> now support nested <filelist>s as well.
Bugzilla Report 15929.

* <apply> and <chmod> will display a summary if you set the new
verbose attribute to true. Bugzilla Report 19883.

Changes from Ant 1.5.2 to Ant 1.5.3 Changes from Ant 1.5.2 to Ant 1.5.3
=================================== ===================================




+ 3
- 2
build.xml View File

@@ -26,6 +26,7 @@


<property name="debug" value="true"/> <property name="debug" value="true"/>
<property name="chmod.fail" value="true"/> <property name="chmod.fail" value="true"/>
<property name="chmod.maxparallel" value="250"/>
<property name="deprecation" value="false"/> <property name="deprecation" value="false"/>
<property name="optimize" value="true"/> <property name="optimize" value="true"/>
<property name="javac.target" value="1.1"/> <property name="javac.target" value="1.1"/>
@@ -963,7 +964,7 @@
<chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**" <chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**"
failonerror="${chmod.fail}"/> failonerror="${chmod.fail}"/>
<chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**" <chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**"
failonerror="${chmod.fail}"/>
failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/>
<chmod perm="ugo+x" type="file" failonerror="${chmod.fail}"> <chmod perm="ugo+x" type="file" failonerror="${chmod.fail}">
<fileset dir="${dist.bin}"> <fileset dir="${dist.bin}">
<include name="**/ant"/> <include name="**/ant"/>
@@ -1037,7 +1038,7 @@
<chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**" <chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**"
failonerror="${chmod.fail}"/> failonerror="${chmod.fail}"/>
<chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**" <chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**"
failonerror="${chmod.fail}"/>
failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/>
<chmod perm="ugo+x" type="file" failonerror="${chmod.fail}"> <chmod perm="ugo+x" type="file" failonerror="${chmod.fail}">
<fileset dir="${dist.bin}"> <fileset dir="${dist.bin}">
<include name="**/ant"/> <include name="**/ant"/>


+ 33
- 5
docs/manual/CoreTasks/apply.html View File

@@ -15,14 +15,15 @@ compatibility.</i></p>
the command is only executed when Ant is run on one of the specified operating the command is only executed when Ant is run on one of the specified operating
systems.</p> systems.</p>
<p>The files and/or directories of a number of <a <p>The files and/or directories of a number of <a
href="../CoreTypes/fileset.html">FileSet</a>s are passed as arguments
href="../CoreTypes/fileset.html">FileSet</a>s or <a
href="../CoreTypes/filelist.html">FileList</a>s are passed as arguments
to the system command.</p> to the system command.</p>
<p>If you specify a nested <a <p>If you specify a nested <a
href="../CoreTypes/mapper.html">mapper</a> and the <i>dest</i> attribute, href="../CoreTypes/mapper.html">mapper</a> and the <i>dest</i> attribute,
the timestamp of each source file is compared to the timestamp of a the timestamp of each source file is compared to the timestamp of a
target file which is defined by the nested mapper element and searched target file which is defined by the nested mapper element and searched
for in the given dest.</p> for in the given dest.</p>
<p>At least one fileset is required, and you must not specify more than
<p>At least one fileset or filelist is required, and you must not specify more than
one mapper.</p> one mapper.</p>
<h3>Parameters</h3> <h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0"> <table border="1" cellpadding="2" cellspacing="0">
@@ -53,7 +54,7 @@ one mapper.</p>
<td valign="top">relative</td> <td valign="top">relative</td>
<td valign="top">whether the filenames should be passed on the <td valign="top">whether the filenames should be passed on the
command line as absolute or relative pathnames (relative to the command line as absolute or relative pathnames (relative to the
base directory of the corresponding fileset for source files or
base directory of the corresponding fileset/list for source files or
the <i>dest</i> attribute for target files).</td> the <i>dest</i> attribute for target files).</td>
<td align="center" valign="top">No, default is <i>false</i></td> <td align="center" valign="top">No, default is <i>false</i></td>
</tr> </tr>
@@ -120,7 +121,8 @@ one mapper.</p>
<td valign="top">skipemptyfilesets</td> <td valign="top">skipemptyfilesets</td>
<td valign="top">Don't run the command, if no source files have <td valign="top">Don't run the command, if no source files have
been found or are newer than their corresponding target been found or are newer than their corresponding target
files.</td>
files. Despite its name, this attribute applies to filelists as
well.</td>
<td align="center" valign="top">No, default is <i>false</i></td> <td align="center" valign="top">No, default is <i>false</i></td>
</tr> </tr>
<tr> <tr>
@@ -158,19 +160,45 @@ one mapper.</p>
false as well.</td> false as well.</td>
<td align="center" valign="top">No, default is <i>true</i></td> <td align="center" valign="top">No, default is <i>true</i></td>
</tr> </tr>
<tr>
<td valign="top">maxparallel</td>
<td valign="top">Limit the amount of parallelism by passing at
most this many sourcefiles at once. Set it to &lt;= 0 for
unlimited. Defaults to unlimited. <em>Since Ant 1.6.</em></td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">addsourcefile</td>
<td valign="top">Whether source file names should be added to the
command automatically. Defaults to <code>true</code>.
<em>Since Ant 1.6.</em></td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">verbose</td>
<td valign="top">Whether to print a summary after execution or not.
Defaults to <code>false</code>. <em>Since Ant 1.6.</em></td>
<td align="center" valign="top">No</td>
</tr>
</table> </table>
<h3>Parameters specified as nested elements</h3> <h3>Parameters specified as nested elements</h3>
<h4>fileset</h4> <h4>fileset</h4>
<p>You can use any number of nested <code>&lt;fileset&gt;</code> <p>You can use any number of nested <code>&lt;fileset&gt;</code>
elements to define the files for this task and refer to elements to define the files for this task and refer to
<code>&lt;fileset&gt;</code>s defined elsewhere.</p> <code>&lt;fileset&gt;</code>s defined elsewhere.</p>
<h4>filelist</h4>
<p><em>Since Ant 1.6</em></p>
<p>You can use any number of nested <code>&lt;filelist&gt;</code>
elements to define the files for this task and refer to
<code>&lt;filelist&gt;</code>s defined elsewhere.</p>
<h4>arg</h4> <h4>arg</h4>
<p>Command line arguments should be specified as nested <p>Command line arguments should be specified as nested
<code>&lt;arg&gt;</code> elements. See <a <code>&lt;arg&gt;</code> elements. See <a
href="../using.html#arg">Command line arguments</a>.</p> href="../using.html#arg">Command line arguments</a>.</p>
<h4>srcfile</h4> <h4>srcfile</h4>
<p>By default the file names of the source files will be added to the <p>By default the file names of the source files will be added to the
end of the command line. If you need to place it somewhere different,
end of the command line (unless you set addsourcefile to
<code>false</code>). If you need to place it somewhere different,
use a nested <code>&lt;srcfile&gt;</code> element between your use a nested <code>&lt;srcfile&gt;</code> element between your
<code>&lt;arg&gt;</code> elements to mark the insertion point.</p> <code>&lt;arg&gt;</code> elements to mark the insertion point.</p>
<h4>targetfile</h4> <h4>targetfile</h4>


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

@@ -19,6 +19,10 @@ write patterns.</p>
supports all of FileSet's attributes and nested elements supports all of FileSet's attributes and nested elements
directly. More FileSets can be specified using nested directly. More FileSets can be specified using nested
<code>&lt;fileset&gt;</code> elements.</p> <code>&lt;fileset&gt;</code> elements.</p>

<p>Starting with Ant 1.6, this task also supports nested <a
href="../CoreTypes/filelist.html">filelist</a>s.</p>

<h3>Parameters</h3> <h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0"> <table border="1" cellpadding="2" cellspacing="0">
<tr> <tr>
@@ -74,6 +78,19 @@ directly. More FileSets can be specified using nested
the directories are considered.</td> the directories are considered.</td>
<td align="center" valign="top">No, default is <i>file</i></td> <td align="center" valign="top">No, default is <i>file</i></td>
</tr> </tr>
<tr>
<td valign="top">maxparallel</td>
<td valign="top">Limit the amount of parallelism by passing at
most this many sourcefiles at once. Set it to &lt;= 0 for
unlimited. Defaults to unlimited. <em>Since Ant 1.6.</em></td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">verbose</td>
<td valign="top">Whether to print a summary after execution or not.
Defaults to <code>false</code>. <em>Since Ant 1.6.</em></td>
<td align="center" valign="top">No</td>
</tr>
</table> </table>
<h3>Examples</h3> <h3>Examples</h3>
<blockquote> <blockquote>


+ 8
- 0
src/main/org/apache/tools/ant/taskdefs/Chmod.java View File

@@ -254,6 +254,14 @@ public class Chmod extends ExecuteOn {
+ " doesn\'t support the skipemptyfileset attribute", getLocation()); + " doesn\'t support the skipemptyfileset attribute", getLocation());
} }


/**
* @ant.attribute ignore="true"
*/
public void setAddsourcefile(boolean b) {
throw new BuildException(getTaskType()
+ " doesn\'t support the addsourcefile attribute", getLocation());
}

protected boolean isValidOs() { protected boolean isValidOs() {
return (Os.isFamily("unix") || Os.isFamily("tandem")) return (Os.isFamily("unix") || Os.isFamily("tandem"))
&& super.isValidOs(); && super.isValidOs();


+ 151
- 10
src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java View File

@@ -63,6 +63,7 @@ import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.EnumeratedAttribute; 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.FileSet;
import org.apache.tools.ant.types.Mapper; import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.FileNameMapper;
@@ -81,6 +82,7 @@ import org.apache.tools.ant.util.SourceFileScanner;
public class ExecuteOn extends ExecTask { public class ExecuteOn extends ExecTask {


protected Vector filesets = new Vector(); protected Vector filesets = new Vector();
private Vector filelists = new Vector();
private boolean relative = false; private boolean relative = false;
private boolean parallel = false; private boolean parallel = false;
private boolean forwardSlash = false; private boolean forwardSlash = false;
@@ -91,6 +93,9 @@ public class ExecuteOn extends ExecTask {
protected Mapper mapperElement = null; protected Mapper mapperElement = null;
protected FileNameMapper mapper = null; protected FileNameMapper mapper = null;
protected File destDir = null; protected File destDir = null;
private int maxParallel = -1;
private boolean addSourceFile = true;
private boolean verbose = false;


/** /**
* Has &lt;srcfile&gt; been specified before &lt;targetfile&gt; * Has &lt;srcfile&gt; been specified before &lt;targetfile&gt;
@@ -104,6 +109,13 @@ public class ExecuteOn extends ExecTask {
filesets.addElement(set); filesets.addElement(set);
} }


/**
* Source files to operate upon.
*/
public void addFilelist(FileList list) {
filelists.addElement(list);
}

/** /**
* Whether the filenames should be passed on the command line as * Whether the filenames should be passed on the command line as
* absolute or relative pathnames. Paths are relative to the base * absolute or relative pathnames. Paths are relative to the base
@@ -153,6 +165,38 @@ public class ExecuteOn extends ExecTask {
this.forwardSlash = forwardSlash; this.forwardSlash = forwardSlash;
} }


/**
* Limit the command line length by passing at maximum this many
* sourcefiles at once to the command.
*
* <p>Set to &lt;= 0 for unlimited - this is the default.</p>
*
* @since Ant 1.6
*/
public void setMaxParallel(int max) {
maxParallel = max;
}

/**
* Whether to send the source file name on the command line.
*
* <p>Defaults to <code>true</code>.
*
* @since Ant 1.6
*/
public void setAddsourcefile(boolean b) {
addSourceFile = b;
}

/**
* Whether to print a verbose summary after execution.
*
* @since Ant 1.6
*/
public void setVerbose(boolean b) {
verbose = b;
}

/** /**
* Marker that indicates where the name of the source file should * Marker that indicates where the name of the source file should
* be put on the command line. * be put on the command line.
@@ -202,8 +246,9 @@ public class ExecuteOn extends ExecTask {
} }
super.checkConfiguration(); super.checkConfiguration();
if (filesets.size() == 0) {
throw new BuildException("no filesets specified", getLocation());
if (filesets.size() == 0 && filelists.size() == 0) {
throw new BuildException("no filesets and no filelists specified",
getLocation());
} }


if (targetFilePos != null || mapperElement != null if (targetFilePos != null || mapperElement != null
@@ -221,6 +266,9 @@ public class ExecuteOn extends ExecTask {
} }


protected void runExec(Execute exe) throws BuildException { protected void runExec(Execute exe) throws BuildException {
int totalFiles = 0;
int totalDirs = 0;
boolean haveExecuted = false;
try { try {


Vector fileNames = new Vector(); Vector fileNames = new Vector();
@@ -233,6 +281,7 @@ public class ExecuteOn extends ExecTask {
if (!"dir".equals(type)) { if (!"dir".equals(type)) {
String[] s = getFiles(base, ds); String[] s = getFiles(base, ds);
for (int j = 0; j < s.length; j++) { for (int j = 0; j < s.length; j++) {
totalFiles++;
fileNames.addElement(s[j]); fileNames.addElement(s[j]);
baseDirs.addElement(base); baseDirs.addElement(base);
} }
@@ -241,6 +290,7 @@ public class ExecuteOn extends ExecTask {
if (!"file".equals(type)) { if (!"file".equals(type)) {
String[] s = getDirs(base, ds);; String[] s = getDirs(base, ds);;
for (int j = 0; j < s.length; j++) { for (int j = 0; j < s.length; j++) {
totalDirs++;
fileNames.addElement(s[j]); fileNames.addElement(s[j]);
baseDirs.addElement(base); baseDirs.addElement(base);
} }
@@ -261,6 +311,50 @@ public class ExecuteOn extends ExecTask {
Project.MSG_VERBOSE); Project.MSG_VERBOSE);
exe.setCommandline(command); exe.setCommandline(command);
runExecute(exe); runExecute(exe);
haveExecuted = true;
}
fileNames.removeAllElements();
baseDirs.removeAllElements();
}
}

for (int i = 0; i < filelists.size(); i++) {
FileList list = (FileList) filelists.elementAt(i);
File base = list.getDir(getProject());
String[] names = list.getFiles(getProject());

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

if (f.isFile()) {
totalFiles++;
} else {
totalDirs++;
}

fileNames.addElement(names[j]);
baseDirs.addElement(base);
}
}

if (fileNames.size() == 0 && skipEmpty) {
log("Skipping filelist for directory "
+ base + ". It is 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);
runExecute(exe);
haveExecuted = true;
} }
fileNames.removeAllElements(); fileNames.removeAllElements();
baseDirs.removeAllElements(); baseDirs.removeAllElements();
@@ -268,14 +362,17 @@ public class ExecuteOn extends ExecTask {
} }


if (parallel && (fileNames.size() > 0 || !skipEmpty)) { if (parallel && (fileNames.size() > 0 || !skipEmpty)) {
String[] s = new String[fileNames.size()];
fileNames.copyInto(s);
File[] b = new File[baseDirs.size()];
baseDirs.copyInto(b);
String[] command = getCommandline(s, b);
log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
exe.setCommandline(command);
runExecute(exe);
runParallel(exe, fileNames, baseDirs);
haveExecuted = true;
}

if (haveExecuted) {
log("Applied " + cmdl.getExecutable() + " to "
+ totalFiles + " file"
+ (totalFiles != 1 ? "s" : "") + " and "
+ totalDirs + " director"
+ (totalDirs != 1 ? "ies" : "y") + ".",
verbose ? Project.MSG_INFO : Project.MSG_VERBOSE);
} }


} catch (IOException e) { } catch (IOException e) {
@@ -321,6 +418,10 @@ public class ExecuteOn extends ExecTask {
String[] targetFiles = new String[targets.size()]; String[] targetFiles = new String[targets.size()];
targets.copyInto(targetFiles); targets.copyInto(targetFiles);
if (!addSourceFile) {
srcFiles = new String[0];
}

String[] orig = cmdl.getCommandline(); String[] orig = cmdl.getCommandline();
String[] result String[] result
= new String[orig.length + srcFiles.length + targetFiles.length]; = new String[orig.length + srcFiles.length + targetFiles.length];
@@ -439,6 +540,46 @@ public class ExecuteOn extends ExecTask {
} }
} }


/**
* Runs the command in "parallel" mode, making sure that at most
* maxParallel sourcefiles get passed on the command line.
*
* @since Ant 1.6
*/
protected void runParallel(Execute exe, Vector fileNames,
Vector baseDirs)
throws IOException, BuildException {
String[] s = new String[fileNames.size()];
fileNames.copyInto(s);
File[] b = new File[baseDirs.size()];
baseDirs.copyInto(b);

if (maxParallel <= 0
|| s.length == 0 /* this is skipEmpty == false */) {
String[] command = getCommandline(s, b);
log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
exe.setCommandline(command);
runExecute(exe);
} else {
int stillToDo = fileNames.size();
int currentOffset = 0;
while (stillToDo > 0) {
int currentAmount = Math.min(stillToDo, maxParallel);
String[] cs = new String[currentAmount];
System.arraycopy(s, currentOffset, cs, 0, currentAmount);
File[] cb = new File[currentAmount];
System.arraycopy(b, currentOffset, cb, 0, currentAmount);
String[] command = getCommandline(cs, cb);
log(Commandline.describeCommand(command), Project.MSG_VERBOSE);
exe.setCommandline(command);
runExecute(exe);

stillToDo -= currentAmount;
currentOffset += currentAmount;
}
}
}

/** /**
* Enumerated attribute with the values "file", "dir" and "both" * Enumerated attribute with the values "file", "dir" and "both"
* for the type attribute. * for the type attribute.


Loading…
Cancel
Save