diff --git a/WHATSNEW b/WHATSNEW
index e65f11bf5..33130dd29 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -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
The files and/or directories of a number of FileSets are passed as arguments +href="../CoreTypes/fileset.html">FileSets or FileLists are passed as arguments to the system command.
If you specify a nested mapper and the dest 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.
-At least one fileset is required, and you must not specify more than +
At least one fileset or filelist is required, and you must not specify more than one mapper.
relative | 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 dest attribute for target files). | No, default is false | @@ -120,7 +121,8 @@ one mapper.skipemptyfilesets | Don't run the command, if no source files have been found or are newer than their corresponding target - files. | + files. Despite its name, this attribute applies to filelists as + well.No, default is false |
No, default is true | ||
maxparallel | +Limit the amount of parallelism by passing at + most this many sourcefiles at once. Set it to <= 0 for + unlimited. Defaults to unlimited. Since Ant 1.6. | +No | +
addsourcefile | +Whether source file names should be added to the
+ command automatically. Defaults to true .
+ Since Ant 1.6. |
+ No | +
verbose | +Whether to print a summary after execution or not.
+ Defaults to false . Since Ant 1.6. |
+ No | +
You can use any number of nested <fileset>
elements to define the files for this task and refer to
<fileset>
s defined elsewhere.
Since Ant 1.6
+You can use any number of nested <filelist>
+elements to define the files for this task and refer to
+<filelist>
s defined elsewhere.
Command line arguments should be specified as nested
<arg>
elements. See Command line arguments.
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
+false
). If you need to place it somewhere different,
use a nested <srcfile>
element between your
<arg>
elements to mark the insertion point.
<fileset>
elements.
+
+Starting with Ant 1.6, this task also supports nested filelists.
+No, default is file | ||
maxparallel | +Limit the amount of parallelism by passing at + most this many sourcefiles at once. Set it to <= 0 for + unlimited. Defaults to unlimited. Since Ant 1.6. | +No | +
verbose | +Whether to print a summary after execution or not.
+ Defaults to false . Since Ant 1.6. |
+ No | +
diff --git a/src/main/org/apache/tools/ant/taskdefs/Chmod.java b/src/main/org/apache/tools/ant/taskdefs/Chmod.java index f8327cb75..eaf329028 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Chmod.java +++ b/src/main/org/apache/tools/ant/taskdefs/Chmod.java @@ -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(); diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java index 4ee472c22..4c826edb4 100644 --- a/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java @@ -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. + * + *Set to <= 0 for unlimited - this is the default.
+ * + * @since Ant 1.6 + */ + public void setMaxParallel(int max) { + maxParallel = max; + } + + /** + * Whether to send the source file name on the command line. + * + *Defaults to
true
. + * + * @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.