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-ffa450edef68master
@@ -346,6 +346,18 @@ Other changes: | |||
that can be used to turn of Microsoft extensions while using the jvc | |||
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 | |||
=================================== | |||
@@ -26,6 +26,7 @@ | |||
<property name="debug" value="true"/> | |||
<property name="chmod.fail" value="true"/> | |||
<property name="chmod.maxparallel" value="250"/> | |||
<property name="deprecation" value="false"/> | |||
<property name="optimize" value="true"/> | |||
<property name="javac.target" value="1.1"/> | |||
@@ -963,7 +964,7 @@ | |||
<chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**" | |||
failonerror="${chmod.fail}"/> | |||
<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}"> | |||
<fileset dir="${dist.bin}"> | |||
<include name="**/ant"/> | |||
@@ -1037,7 +1038,7 @@ | |||
<chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**" | |||
failonerror="${chmod.fail}"/> | |||
<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}"> | |||
<fileset dir="${dist.bin}"> | |||
<include name="**/ant"/> | |||
@@ -15,14 +15,15 @@ compatibility.</i></p> | |||
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 <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> | |||
<p>If you specify a nested <a | |||
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 | |||
target file which is defined by the nested mapper element and searched | |||
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> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
@@ -53,7 +54,7 @@ one mapper.</p> | |||
<td valign="top">relative</td> | |||
<td valign="top">whether the filenames should be passed on 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> | |||
<td align="center" valign="top">No, default is <i>false</i></td> | |||
</tr> | |||
@@ -120,7 +121,8 @@ one mapper.</p> | |||
<td valign="top">skipemptyfilesets</td> | |||
<td valign="top">Don't run the command, if no source files have | |||
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> | |||
</tr> | |||
<tr> | |||
@@ -158,19 +160,45 @@ one mapper.</p> | |||
false as well.</td> | |||
<td align="center" valign="top">No, default is <i>true</i></td> | |||
</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 <= 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> | |||
<h3>Parameters specified as nested elements</h3> | |||
<h4>fileset</h4> | |||
<p>You can use any number of nested <code><fileset></code> | |||
elements to define the files for this task and refer to | |||
<code><fileset></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><filelist></code> | |||
elements to define the files for this task and refer to | |||
<code><filelist></code>s defined elsewhere.</p> | |||
<h4>arg</h4> | |||
<p>Command line arguments should be specified as nested | |||
<code><arg></code> elements. See <a | |||
href="../using.html#arg">Command line arguments</a>.</p> | |||
<h4>srcfile</h4> | |||
<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><srcfile></code> element between your | |||
<code><arg></code> elements to mark the insertion point.</p> | |||
<h4>targetfile</h4> | |||
@@ -19,6 +19,10 @@ write patterns.</p> | |||
supports all of FileSet's attributes and nested elements | |||
directly. More FileSets can be specified using nested | |||
<code><fileset></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> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
<tr> | |||
@@ -74,6 +78,19 @@ directly. More FileSets can be specified using nested | |||
the directories are considered.</td> | |||
<td align="center" valign="top">No, default is <i>file</i></td> | |||
</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 <= 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> | |||
<h3>Examples</h3> | |||
<blockquote> | |||
@@ -254,6 +254,14 @@ public class Chmod extends ExecuteOn { | |||
+ " 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() { | |||
return (Os.isFamily("unix") || Os.isFamily("tandem")) | |||
&& super.isValidOs(); | |||
@@ -63,6 +63,7 @@ import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.Commandline; | |||
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.util.FileNameMapper; | |||
@@ -81,6 +82,7 @@ import org.apache.tools.ant.util.SourceFileScanner; | |||
public class ExecuteOn extends ExecTask { | |||
protected Vector filesets = new Vector(); | |||
private Vector filelists = new Vector(); | |||
private boolean relative = false; | |||
private boolean parallel = false; | |||
private boolean forwardSlash = false; | |||
@@ -91,6 +93,9 @@ public class ExecuteOn extends ExecTask { | |||
protected Mapper mapperElement = null; | |||
protected FileNameMapper mapper = null; | |||
protected File destDir = null; | |||
private int maxParallel = -1; | |||
private boolean addSourceFile = true; | |||
private boolean verbose = false; | |||
/** | |||
* Has <srcfile> been specified before <targetfile> | |||
@@ -104,6 +109,13 @@ public class ExecuteOn extends ExecTask { | |||
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 | |||
* absolute or relative pathnames. Paths are relative to the base | |||
@@ -153,6 +165,38 @@ public class ExecuteOn extends ExecTask { | |||
this.forwardSlash = forwardSlash; | |||
} | |||
/** | |||
* Limit the command line length by passing at maximum this many | |||
* sourcefiles at once to the command. | |||
* | |||
* <p>Set to <= 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 | |||
* be put on the command line. | |||
@@ -202,8 +246,9 @@ public class ExecuteOn extends ExecTask { | |||
} | |||
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 | |||
@@ -221,6 +266,9 @@ public class ExecuteOn extends ExecTask { | |||
} | |||
protected void runExec(Execute exe) throws BuildException { | |||
int totalFiles = 0; | |||
int totalDirs = 0; | |||
boolean haveExecuted = false; | |||
try { | |||
Vector fileNames = new Vector(); | |||
@@ -233,6 +281,7 @@ public class ExecuteOn extends ExecTask { | |||
if (!"dir".equals(type)) { | |||
String[] s = getFiles(base, ds); | |||
for (int j = 0; j < s.length; j++) { | |||
totalFiles++; | |||
fileNames.addElement(s[j]); | |||
baseDirs.addElement(base); | |||
} | |||
@@ -241,6 +290,7 @@ public class ExecuteOn extends ExecTask { | |||
if (!"file".equals(type)) { | |||
String[] s = getDirs(base, ds);; | |||
for (int j = 0; j < s.length; j++) { | |||
totalDirs++; | |||
fileNames.addElement(s[j]); | |||
baseDirs.addElement(base); | |||
} | |||
@@ -261,6 +311,50 @@ public class ExecuteOn extends ExecTask { | |||
Project.MSG_VERBOSE); | |||
exe.setCommandline(command); | |||
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(); | |||
baseDirs.removeAllElements(); | |||
@@ -268,14 +362,17 @@ public class ExecuteOn extends ExecTask { | |||
} | |||
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) { | |||
@@ -321,6 +418,10 @@ public class ExecuteOn extends ExecTask { | |||
String[] targetFiles = new String[targets.size()]; | |||
targets.copyInto(targetFiles); | |||
if (!addSourceFile) { | |||
srcFiles = new String[0]; | |||
} | |||
String[] orig = cmdl.getCommandline(); | |||
String[] result | |||
= 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" | |||
* for the type attribute. | |||