You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@apache.org on 2005/09/28 20:42:59 UTC

svn commit: r292247 - in /ant/core/trunk: docs/manual/CoreTasks/ src/etc/testcases/taskdefs/ src/main/org/apache/tools/ant/taskdefs/ src/testcases/org/apache/tools/ant/taskdefs/

Author: bodewig
Date: Wed Sep 28 11:42:46 2005
New Revision: 292247

URL: http://svn.apache.org/viewcvs?rev=292247&view=rev
Log:
Add resource collection support to copy and friends

Modified:
    ant/core/trunk/docs/manual/CoreTasks/copy.html
    ant/core/trunk/docs/manual/CoreTasks/move.html
    ant/core/trunk/docs/manual/CoreTasks/sync.html
    ant/core/trunk/src/etc/testcases/taskdefs/copy.xml
    ant/core/trunk/src/etc/testcases/taskdefs/move.xml
    ant/core/trunk/src/etc/testcases/taskdefs/sync.xml
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Sync.java
    ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/CopyTest.java
    ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/MoveTest.java
    ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java

Modified: ant/core/trunk/docs/manual/CoreTasks/copy.html
URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/CoreTasks/copy.html?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/copy.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/copy.html Wed Sep 28 11:42:46 2005
@@ -10,15 +10,18 @@
 
 <h2><a name="copy">Copy</a></h2>
 <h3>Description</h3>
-<p>Copies a file or FileSet to a new file or directory.  By default, files are
+<p>Copies a file or resource collection to a new file or directory.  By default, files are
 only copied if the source file is newer than the destination file,
 or when the destination file does not exist.  However, you can explicitly
 overwrite files with the <code>overwrite</code> attribute.</p>
 
-<p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select a
-set of files to copy.
-To use a <code>&lt;fileset&gt;</code>, the <code>todir</code> attribute
-must be set.</p>
+<p><a href="../CoreTypes/resources.html#collection">Resource
+Collection</a>s are used to select a group of files to copy.  Only
+file system based resource collections are supported, this includes <a
+href="../CoreTypes/fileset.html">fileset</a>s, <a
+href="../CoreTypes/filelist.html">filelist</a> and <a
+href="../using.html#path">path</a>.  To use a resource collection, the
+<code>todir</code> attribute must be set.</p>
 
 <p>
 <strong>Note: </strong>If you employ filters in your copy operation, you should 
@@ -39,7 +42,7 @@
     <td valign="top">file</td>
     <td valign="top">The file to copy.</td>
     <td valign="top" align="center">Yes, unless a nested
-    <code>&lt;fileset&gt;</code> element is used.</td>
+    resource collection element is used.</td>
   </tr>
   <tr>
     <td valign="top">preservelastmodified</td>
@@ -52,7 +55,7 @@
     <td valign="top">The file to copy to.</td>
     <td valign="top" align="center" rowspan="2">With the <code>file</code>
       attribute, either <code>tofile</code> or <code>todir</code> can be used.
-      With nested <code>&lt;fileset&gt;</code> elements, if the set of files
+      With nested resource collection elements, if the number of included files
       is greater than 1, or if only the <code>dir</code> attribute is
       specified in the <code>&lt;fileset&gt;</code>, or if the
       <code>file</code> attribute is also specified, then only
@@ -141,10 +144,12 @@
 </table>
 <h3>Parameters specified as nested elements</h3>
 
-<h4>fileset</h4>
- <p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select
-sets of files to copy.
- To use a fileset, the <code>todir</code> attribute must be set.</p>
+<h4>fileset or any other filesystem based resource collection</h4>
+<p><a href="../CoreTypes/resources.html#collection">Resource
+Collection</a>s are used to select groups of files to copy.  To use a
+resource collection, the <code>todir</code> attribute must be set.</p>
+<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been
+supported as a nested element.</p>
 
 <h4>mapper</h4>
  <p>You can define filename transformations by using a nested <a
@@ -156,6 +161,13 @@
     one can use a filenamemapper type in place of the mapper element.
   </p>
 
+<p>Note that the source name handed to the mapper depends on the
+resource collection you use.  If you use <code>&lt;fileset&gt;</code>
+or any other collection that provides a base directory, the name
+passed to the mapper will be a relative filename, relative to the base
+directory.  In any other case the absolute filename of the source will
+be used.</p>
+
 <h4>filterset</h4>
  <p><a href="../CoreTypes/filterset.html">FilterSet</a>s are used to replace
 tokens in files that are copied.
@@ -207,7 +219,6 @@
   &lt;/copy&gt;
 </pre>
 
-
 <p><b>Copy a set of files to a directory, replacing @TITLE@ with Foo Bar
 in all files.</b></p>
 <pre>
@@ -216,6 +227,16 @@
     &lt;filterset&gt;
       &lt;filter token=&quot;TITLE&quot; value=&quot;Foo Bar&quot;/&gt;
     &lt;/filterset&gt;
+  &lt;/copy&gt;
+</pre>
+
+<p><b>Collect all items from the current CLASSPATH setting into a
+destination directory, flattening the directory structure.</b></p>
+<pre>
+  &lt;copy todir="dest" flatten="true"&gt;
+    &lt;path&gt;
+      &lt;pathelement path="${java.class.path}"/&gt;
+    &lt;/path&gt;
   &lt;/copy&gt;
 </pre>
 

Modified: ant/core/trunk/docs/manual/CoreTasks/move.html
URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/CoreTasks/move.html?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/move.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/move.html Wed Sep 28 11:42:46 2005
@@ -10,13 +10,22 @@
 
 <h2><a name="move">Move</a></h2>
 <h3>Description</h3>
-<p>Moves a file to a new file or directory, or sets of files to
+<p>Moves a file to a new file or directory, or collections of files to
 a new directory.  By default, the
 destination file is overwritten if it already exists.  When <var>overwrite</var> is
 turned off, then files are only moved if the source file is newer than
 the destination file, or when the destination file does not exist.</p>
-<p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select sets of files
-to move to the <var>todir</var> directory.</p>
+
+<p><a href="../CoreTypes/resources.html#collection">Resource
+Collection</a>s are used to select a group of files to move.  Only
+file system based resource collections are supported, this includes <a
+href="../CoreTypes/fileset.html">fileset</a>s, <a
+href="../CoreTypes/filelist.html">filelist</a> and <a
+href="../using.html#path">path</a>.  Prior to Ant 1.7 only
+<code>&lt;fileset&gt;</code> has been supported as a nested element.
+To use a resource collection, the <code>todir</code> attribute must be
+set.</p>
+
 <p><b>Since Ant 1.6.3</b>, the <i>file</i> attribute may be used to move
 (rename) an entire directory.  If <i>tofile</i> denotes an existing file, or
 there is a directory by the same name in <i>todir</i>, the action will fail.
@@ -32,7 +41,7 @@
     <td valign="top">file</td>
     <td valign="top">the file or directory to move</td>
     <td valign="top" align="center">One of <var>file</var> or
-     at least one nested fileset element</td>
+     at least one nested resource collection element</td>
   </tr>
   <tr>
     <td valign="top">preservelastmodified</td>
@@ -135,6 +144,12 @@
 href="../CoreTypes/mapper.html">mapper</a> element. The default mapper used by
 <code>&lt;move&gt;</code> is the <a
 href="../CoreTypes/mapper.html#identity-mapper">identity</a>.</p>
+<p>Note that the source name handed to the mapper depends on the
+resource collection you use.  If you use <code>&lt;fileset&gt;</code>
+or any other collection that provides a base directory, the name
+passed to the mapper will be a relative filename, relative to the base
+directory.  In any other case the absolute filename of the source will
+be used.</p>
 <h4>filterchain</h4>
 <p>The Move task supports nested <a href="../CoreTypes/filterchain.html">
 FilterChain</a>s.</p>
@@ -171,6 +186,15 @@
       &lt;include name=&quot;**/*.jar&quot;/&gt;
       &lt;exclude name=&quot;**/ant.jar&quot;/&gt;
     &lt;/fileset&gt;
+  &lt;/move&gt;
+</pre>
+<p><b>Move a list of files to a new directory</b></p>
+<pre>
+  &lt;move todir=&quot;some/new/dir&quot;&gt;
+    &lt;filelist dir=&quot;my/src/dir&quot;&gt;
+      &lt;file name="file1.txt"/&gt;
+      &lt;file name="file2.txt"/&gt;
+    &lt;/filelist&gt;
   &lt;/move&gt;
 </pre>
 <p><b>Append <code>&quot;.bak&quot;</code> to the names of all files

Modified: ant/core/trunk/docs/manual/CoreTasks/sync.html
URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/CoreTasks/sync.html?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/sync.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/sync.html Wed Sep 28 11:42:46 2005
@@ -13,10 +13,10 @@
 <h3>Description</h3>
 
 <p>Synchronize a target directory from the files defined in one or
-more filesets.</p>
+more filesystem based <a href="../CoreTypes/resources.html#collection">Resource Collection</a>s.</p>
 
 <p>Any file in the target directory that has not been matched by at
-least one of the nested filesets gets removed.  I.e. if you exclude a
+least one of the nested resource collection gets removed.  I.e. if you exclude a
 file in your sources and a file of that name is present in the target
 dir, it will get removed from the target.</p>
 
@@ -29,7 +29,7 @@
   </tr>
   <tr>
     <td valign="top">todir</td>
-    <td valign="top">the target directory to sync with the filesets</td>
+    <td valign="top">the target directory to sync with the resource collections</td>
     <td align="center" valign="top">Yes</td>
   </tr>  
   <tr>
@@ -40,7 +40,7 @@
   </tr>
   <tr>
     <td valign="top">includeEmptyDirs</td>
-     <td valign="top">Copy any empty directories included in the FileSet(s).
+     <td valign="top">Copy any empty directories included in the resource collection(s).
      </td>
      <td valign="top" align="center">No; defaults to true.</td>
   </tr>
@@ -72,9 +72,12 @@
 
 <h3>Parameters specified as nested elements</h3>
 
-<h4>fileset</h4>
-<p><a href="../CoreTypes/fileset.html">FileSet</a>s are used to select
-sets of files and directories.</p>
+<h4>fileset or any other filesystem based resource collection</h4>
+<p><a href="../CoreTypes/resources.html#collection">Resource
+Collection</a>s are used to select groups of files to copy.  To use a
+resource collection, the <code>todir</code> attribute must be set.</p>
+<p>Prior to Ant 1.7 only <code>&lt;fileset&gt;</code> has been
+supported as a nested element.</p>
 
 <h4>preserveInTarget</h4>
 

Modified: ant/core/trunk/src/etc/testcases/taskdefs/copy.xml
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/etc/testcases/taskdefs/copy.xml?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/etc/testcases/taskdefs/copy.xml (original)
+++ ant/core/trunk/src/etc/testcases/taskdefs/copy.xml Wed Sep 28 11:42:46 2005
@@ -76,6 +76,14 @@
     </copy>
   </target>
   
+  <target name="test_single_file_path">
+    <copy tofile="copytest_single_file_path.tmp">
+      <path>
+        <pathelement location="copy.xml"/>
+      </path>
+    </copy>
+  </target>
+  
   <target name="testFilterSet">
     <copy file="copy.filterset" tofile="copy.filterset.tmp">
       <filterset>
@@ -121,76 +129,75 @@
     </copy>
   </target>
 
-<!--	
+<!--    
   <typedef name="resource" classname="org.apache.tools.ant.types.Resource"/>
   <typedef name="resources" classname="org.apache.tools.ant.types.resources.Resources"/>
 -->  
-	
+        
+  <property name="to.dir" value="copy-todir-tmp"/>
+  <property name="from.dir" value="copy-fromdir-tmp"/>
+        
+  <target name="testResource.prepare">
+    <mkdir dir="${from.dir}"/>
+    <concat destfile="${from.dir}/file1.txt">This is file 1</concat>
+    <concat destfile="${from.dir}/file2.txt">This is file 2</concat>
+    <concat destfile="${from.dir}/file3.txt">This is file 3</concat>
+    <concat destfile="${from.dir}/fileNR.txt">This is file @NR@</concat>
+  </target>
+        
   <target name="testFileResourcePlain" depends="testResource.prepare">
-  	<copy todir="${to.dir}">
+    <copy todir="${to.dir}" flatten="true">
       <resources>
         <file file="${from.dir}/file1.txt"/>
         <file file="${from.dir}/file2.txt"/>
         <file file="${from.dir}/file3.txt"/>
-	  </resources>  	  
-  	</copy>
+      </resources>            
+    </copy>
   </target>
 
   <target name="testFileResourceWithMapper" depends="testResource.prepare">
-  	<copy todir="${to.dir}">
+    <copy todir="${to.dir}" flatten="true">
       <resources>
         <file file="${from.dir}/file1.txt"/>
         <file file="${from.dir}/file2.txt"/>
         <file file="${from.dir}/file3.txt"/>
-	  </resources>  	  
+      </resources>            
       <regexpmapper from="^(.*)\.txt$$" to="\1.txt.bak"/>
-  	</copy>
+    </copy>
   </target>
 
-
-  <property name="to.dir" value="copy-todir-tmp"/>
-  <property name="from.dir" value="copy-todir-tmp"/>
-	
-  <target name="testResource.prepare">
-  	<mkdir dir="${from.dir}"/>
-  	<concat destfile="${to.dir}/file1.txt">This is file 1</concat>
-  	<concat destfile="${to.dir}/file2.txt">This is file 2</concat>
-  	<concat destfile="${to.dir}/file3.txt">This is file 3</concat>
-  	<concat destfile="${to.dir}/fileNR.txt">This is file @nr@</concat>
-  </target>
-	
   <target name="testFileResourceWithFilter" depends="testResource.prepare">
-  	<copy todir="${to.dir}">
+    <copy todir="${to.dir}" flatten="true">
       <resources>
         <file file="${from.dir}/fileNR.txt"/>
-	  </resources>  	  
+      </resources>            
       <filterset>
-  	    <filter token="NR" value="42"/>
-  	  </filterset>
-  	</copy>
+        <filter token="NR" value="42"/>
+      </filterset>
+    </copy>
   </target>
-		
+                
   <target name="testResourcePlain">
   </target>
-  	
+        
   <target name="testResourcePlainWithMapper">
   </target>
     
   <target name="testResourcePlainWithFilter">
   </target>
-	
+        
   <target name="testOnlineResources">
   </target>
-	
-  <target name="testPathAsResource">
+        
+  <target name="testPathAsResource" depends="testResource.prepare">
     <copy todir="${to.dir}">
       <path>
         <fileset dir="${from.dir}"/>
-      </path> 	
-    </copy>  	
+      </path>   
+    </copy>     
   </target>
-	
-	
+        
+        
   
   <target name="cleanup"> 
     <delete file="copytest1.tmp"/>
@@ -204,7 +211,8 @@
     <delete dir="copytest1dir"/>
     <delete quiet="yes" file="copy.filter.out"/>
     <delete quiet="yes" file="copy.filter.inp"/>
-  	<delete dir="${to.dir}"/>
+    <delete dir="${from.dir}"/>
+    <delete dir="${to.dir}"/>
   </target>
 
 </project>

Modified: ant/core/trunk/src/etc/testcases/taskdefs/move.xml
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/etc/testcases/taskdefs/move.xml?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/etc/testcases/taskdefs/move.xml (original)
+++ ant/core/trunk/src/etc/testcases/taskdefs/move.xml Wed Sep 28 11:42:46 2005
@@ -59,6 +59,26 @@
     </move>
   </target>
 
+  <target name="testCompleteDirectoryMove2">
+    <mkdir dir="A"/>
+    <touch file="A/1"/>
+    <move todir="E">
+      <path>
+        <fileset dir="A"/>
+      </path>
+    </move>
+  </target>
+
+  <target name="testPathElementMove">
+    <mkdir dir="A"/>
+    <touch file="A/1"/>
+    <move todir="E" flatten="true">
+      <path>
+        <pathelement location="A/1"/>
+      </path>
+    </move>
+  </target>
+
   <target name="testMoveFileAndFileset">
     <mkdir dir="A" />
     <touch>

Modified: ant/core/trunk/src/etc/testcases/taskdefs/sync.xml
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/etc/testcases/taskdefs/sync.xml?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/etc/testcases/taskdefs/sync.xml (original)
+++ ant/core/trunk/src/etc/testcases/taskdefs/sync.xml Wed Sep 28 11:42:46 2005
@@ -35,6 +35,19 @@
     </sync>
   </target>
 
+  <target name="copyandremove-with-filelist" depends="setup">
+    <mkdir dir="${src}/a/b/c"/>
+    <touch file="${src}/a/b/c/d"/>
+    <mkdir dir="${dest}/e"/>
+    <touch file="${dest}/e/f"/>
+    <sync todir="${dest}">
+      <filelist dir="${src}">
+        <file name="a/b/c/d"/>
+        <file name="not-there"/>
+      </filelist>
+    </sync>
+  </target>
+
   <target name="copyandremove-emptypreserve" depends="setup">
     <mkdir dir="${src}/a/b/c"/>
     <touch file="${src}/a/b/c/d"/>

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java Wed Sep 28 11:42:46 2005
@@ -19,9 +19,15 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Vector;
-import java.util.Hashtable;
+import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.BuildException;
@@ -32,9 +38,8 @@
 import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.FilterSetCollection;
 import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.types.resources.Resources;
+import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.IdentityMapper;
@@ -57,10 +62,12 @@
  * @ant.task category="filesystem"
  */
 public class Copy extends Task {
+    private static final File NULL_FILE_PLACEHOLDER = new File("/NULL_FILE");
+
     protected File file = null;     // the source file
     protected File destFile = null; // the destination file
     protected File destDir = null;  // the destination directory
-    protected Vector filesets = new Vector();
+    protected Vector rcs = new Vector();
 
     private boolean enableMultipleMappings = false;
     protected boolean filtering = false;
@@ -276,43 +283,17 @@
      * @param set a set of files to copy.
      */
     public void addFileset(FileSet set) {
-        filesets.addElement(set);
+	add(set);
     }
     
-    /* JHM: It would be the finest solution to use this method directly.
-     * But if I understood the IntrospectionHelper(final Class bean) 
-     * right - especially line 258ff (the last "else if" statement), 
-     * I must have a <b>class</b> with an no-arg constructor. But I only 
-     * have an interface. :-(
-     * So I have to add the three methods ... But I can reuse this
-     * method :-)
-     *  
-     */
-    public void add(ResourceCollection res) {
-    	//TODO: implement resources
-    }
     /**
-     * Adds a <code>path</code> element as a nested ResourceCollection.
-     * @param path
+     * Add a collection of files to copy.
+     * @param res a resource collection to copy.
+     * @since Ant 1.7
      */
-    public void addPath(Path path) {
-    	//add((ResourceCollection)path);
-    }
-    /**
-     * Adds a Resource element as a nested ResourceCollection.
-     * @param path
-     * /
-    public void add(Resource res) {
-    	add((ResourceCollection)res);
-    }
-    /**
-     * Adds a <code>resources</code> element as a nested ResourceCollection.
-     * @param path
-     * /
-    public void add(Resources res) {
-    	add((ResourceCollection)res);
+    public void add(ResourceCollection res) {
+	rcs.add(res);
     }
-    */
     
     /**
      * Define the mapper to map source to destination files.
@@ -400,10 +381,10 @@
         File savedFile = file; // may be altered in validateAttributes
         File savedDestFile = destFile;
         File savedDestDir = destDir;
-        FileSet savedFileSet = null;
-        if (file == null && destFile != null && filesets.size() == 1) {
+	ResourceCollection savedRc = null;
+        if (file == null && destFile != null && rcs.size() == 1) {
             // will be removed in validateAttributes
-            savedFileSet = (FileSet) filesets.elementAt(0);
+	    savedRc = (ResourceCollection) rcs.elementAt(0);
         }
         // make sure we don't have an illegal set of options
         validateAttributes();
@@ -434,30 +415,96 @@
                     }
                 }
             }
-            // deal with the filesets
-            for (int i = 0; i < filesets.size(); i++) {
-                FileSet fs = (FileSet) filesets.elementAt(i);
-                DirectoryScanner ds = null;
-                try {
-                    ds = fs.getDirectoryScanner(getProject());
-                } catch (BuildException e) {
-                    if (failonerror
-                        || !e.getMessage().endsWith(" not found.")) {
-                        throw e;
-                    } else {
-                        log("Warning: " + e.getMessage());
-                        continue;
-                    }
-                }
-                File fromDir = fs.getDir(getProject());
+            // deal with the ResourceCollections
 
-                String[] srcFiles = ds.getIncludedFiles();
-                String[] srcDirs = ds.getIncludedDirectories();
-                if (!flatten && mapperElement == null
-                    && ds.isEverythingIncluded() && !fs.hasPatterns()) {
-                    completeDirMap.put(fromDir, destDir);
-                }
-                scan(fromDir, destDir, srcFiles, srcDirs);
+	    /* for historical and performance reasons we have to do
+	       things in a rather complex way.
+	    
+	       (1) Move is optimized to move directories if a fileset
+	       has been included completely, therefore FileSets need a
+	       special treatment.  This is also required to support
+	       the failOnError semantice (skip filesets with broken
+	       basedir but handle the remaining collections).
+
+	       (2) We carry around a few protected methods that work
+	       on basedirs and arrays of names.  To optimize stuff, all
+	       resources with the same basedir get collected in
+	       separate lists and then each list is handled in one go.
+	    */
+
+	    HashMap filesByBasedir = new HashMap();
+	    HashMap dirsByBasedir = new HashMap();
+	    HashSet baseDirs = new HashSet();
+            for (int i = 0; i < rcs.size(); i++) {
+		ResourceCollection rc = (ResourceCollection) rcs.elementAt(i);
+
+		if (rc.isFilesystemOnly()) {
+
+		    // Step (1)
+		    if (rc instanceof FileSet) {
+			FileSet fs = (FileSet) rc;
+			DirectoryScanner ds = null;
+			try {
+			    ds = fs.getDirectoryScanner(getProject());
+			} catch (BuildException e) {
+			    if (failonerror
+				|| !e.getMessage().endsWith(" not found.")) {
+				throw e;
+			    } else {
+				log("Warning: " + e.getMessage());
+				continue;
+			    }
+			}
+			File fromDir = fs.getDir(getProject());
+
+			String[] srcFiles = ds.getIncludedFiles();
+			String[] srcDirs = ds.getIncludedDirectories();
+			if (!flatten && mapperElement == null
+			    && ds.isEverythingIncluded() && !fs.hasPatterns()) {
+			    completeDirMap.put(fromDir, destDir);
+			}
+			add(fromDir, srcFiles, filesByBasedir);
+			add(fromDir, srcDirs, dirsByBasedir);
+			baseDirs.add(fromDir);
+		    } else { // not a fileset
+
+			Iterator resources = rc.iterator();
+			while (resources.hasNext()) {
+			    FileResource fr = (FileResource) resources.next();
+			    if (!fr.isExists()) {
+				continue;
+			    }
+			    File baseDir = getKeyFile(fr.getBaseDir());
+			    add(baseDir, 
+				baseDir == NULL_FILE_PLACEHOLDER
+				? fr.getFile().getAbsolutePath() : fr.getName(),
+				fr.isDirectory() ? dirsByBasedir 
+				                 : filesByBasedir);
+			    baseDirs.add(baseDir);
+			}
+		    }
+
+		    Iterator iter = baseDirs.iterator();
+		    while (iter.hasNext()) {
+			File f = (File) iter.next();
+			List files = (List) filesByBasedir.get(f);
+			List dirs = (List) dirsByBasedir.get(f);
+
+			String[] srcFiles = new String[0];
+			if (files != null) {
+			    srcFiles = (String[]) files.toArray(srcFiles);
+			}
+			String[] srcDirs = new String[0];
+			if (dirs != null) {
+			    srcDirs = (String[]) dirs.toArray(srcDirs);
+			}
+			scan(f == NULL_FILE_PLACEHOLDER ? null : f, destDir,
+			     srcFiles, srcDirs);
+		    }
+		} else { // not a File resource collection
+		    throw new BuildException("Only FileSystem resources are"
+					     + " supported.");
+		}
             }
             // do all the copy operations now...
             try {
@@ -475,8 +522,8 @@
             file = savedFile;
             destFile = savedDestFile;
             destDir = savedDestDir;
-            if (savedFileSet != null) {
-                filesets.insertElementAt(savedFileSet, 0);
+            if (savedRc != null) {
+                rcs.insertElementAt(savedRc, 0);
             }
             fileCopyMap.clear();
             dirCopyMap.clear();
@@ -495,9 +542,9 @@
      * @exception BuildException if an error occurs.
      */
     protected void validateAttributes() throws BuildException {
-        if (file == null && filesets.size() == 0) {
+        if (file == null && rcs.size() == 0) {
             throw new BuildException(
-                "Specify at least one source--a file or a fileset.");
+                "Specify at least one source--a file or a resource collection.");
         }
         if (destFile != null && destDir != null) {
             throw new BuildException(
@@ -507,24 +554,26 @@
             throw new BuildException("One of tofile or todir must be set.");
         }
         if (file != null && file.isDirectory()) {
-            throw new BuildException("Use a fileset to copy directories.");
+            throw new BuildException("Use a resource collection to copy directories.");
         }
-        if (destFile != null && filesets.size() > 0) {
-            if (filesets.size() > 1) {
+        if (destFile != null && rcs.size() > 0) {
+            if (rcs.size() > 1) {
                 throw new BuildException(
                     "Cannot concatenate multiple files into a single file.");
             } else {
-                FileSet fs = (FileSet) filesets.elementAt(0);
-                DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-                String[] srcFiles = ds.getIncludedFiles();
-
-                if (srcFiles.length == 0) {
+		ResourceCollection rc = (ResourceCollection) rcs.elementAt(0);
+		if (!rc.isFilesystemOnly()) {
+		    throw new BuildException("Only FileSystem resources are"
+					     + " supported.");
+		}
+		if (rc.size() == 0) {
                     throw new BuildException(
                         "Cannot perform operation from directory to file.");
-                } else if (srcFiles.length == 1) {
+                } else if (rc.size() == 1) {
+		    FileResource r = (FileResource) rc.iterator().next();
                     if (file == null) {
-                        file = new File(ds.getBasedir(), srcFiles[0]);
-                        filesets.removeElementAt(0);
+                        file = r.getFile();
+                        rcs.removeElementAt(0);
                     } else {
                         throw new BuildException(
                             "Cannot concatenate multiple files into a single file.");
@@ -688,5 +737,38 @@
                     + destDir.getAbsolutePath());
             }
         }
+    }
+
+    /**
+     * Adds the given strings to a list contained in the given map.
+     * The file is the key into the map.
+     */
+    private static void add(File baseDir, String[] names, Map m) {
+	if (names != null) {
+	    baseDir = getKeyFile(baseDir);
+	    List l = (List) m.get(baseDir);
+	    if (l == null) {
+		l = new ArrayList(names.length);
+		m.put(baseDir, l);
+	    }
+	    l.addAll(java.util.Arrays.asList(names));
+	}
+    }
+
+    /**
+     * Adds the given string to a list contained in the given map.
+     * The file is the key into the map.
+     */
+    private static void add(File baseDir, String name, Map m) {
+	if (name != null) {
+	    add(baseDir, new String[] {name}, m);
+	}
+    }
+
+    /**
+     * Either returns its argument or a plaeholder if the argument is null.
+     */
+    private static File getKeyFile(File f) {
+	return f == null ? NULL_FILE_PLACEHOLDER : f;
     }
 }

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Sync.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Sync.java?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Sync.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Sync.java Wed Sep 28 11:42:46 2005
@@ -35,6 +35,7 @@
 import org.apache.tools.ant.types.AbstractFileSet;
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.types.PatternSet;
+import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.selectors.FileSelector;
 import org.apache.tools.ant.types.selectors.NoneSelector;
 
@@ -212,9 +213,11 @@
         // delete them.
         for (int i = dirs.length - 1; i >= 0; --i) {
             File f = new File(toDir, dirs[i]);
+	    if (f.list().length < 1) {
             log("Removing orphan directory: " + f, Project.MSG_DEBUG);
             f.delete();
             ++removedCount[0];
+	    }
         }
         return removedCount;
     }
@@ -310,7 +313,16 @@
      * @param set a fileset
      */
     public void addFileset(FileSet set) {
-        myCopy.addFileset(set);
+        add(set);
+    }
+
+    /**
+     * Adds a collection of filesystem resources to copy.
+     * @param rc a resource collection
+     * @since Ant 1.7
+     */
+    public void add(ResourceCollection rc) {
+        myCopy.add(rc);
     }
 
     /**

Modified: ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/CopyTest.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/CopyTest.java?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/CopyTest.java (original)
+++ ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/CopyTest.java Wed Sep 28 11:42:46 2005
@@ -121,6 +121,13 @@
         assertTrue(file.exists());
     }
 
+    public void testSingleFilePath() {
+        executeTarget("test_single_file_path");
+        File file  = new File(getProjectDir(),
+                                        "copytest_single_file_path.tmp");
+        assertTrue(file.exists());
+    }
+
     public void testTranscoding() throws IOException {
         executeTarget("testTranscoding");
         File f1 = getProject().resolveFile("copy/expected/utf-8");
@@ -148,7 +155,7 @@
         assertTrue(getBuildException().getMessage().endsWith(" not found."));
     }
     
-    public void _testFileResourcePlain() {
+    public void testFileResourcePlain() {
     	executeTarget("testFileResourcePlain");
     	File file1 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file1.txt");
     	File file2 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file2.txt");
@@ -168,23 +175,23 @@
     	assertTrue(file3.exists());
     }
     
-    public void _testFileResourceWithFilter() {
+    public void testFileResourceWithFilter() {
     	executeTarget("testFileResourceWithFilter");
     	File file1 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/fileNR.txt");
     	assertTrue(file1.exists());
     	try {
-			String file1Content = FILE_UTILS.readFully(new FileReader(file1));
-			assertEquals(file1Content, "This is file 42");
-		} catch (IOException e) {
-			// no-op: not a real business error
-		}
+	    String file1Content = FILE_UTILS.readFully(new FileReader(file1));
+	    assertEquals("This is file 42", file1Content);
+	} catch (IOException e) {
+	    // no-op: not a real business error
+	}
     }
     
-    public void _testPathAsResource() {
+    public void testPathAsResource() {
     	executeTarget("testPathAsResource");
-    	File file1 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file1.txt.bak");
-    	File file2 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file2.txt.bak");
-    	File file3 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file3.txt.bak");
+    	File file1 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file1.txt");
+    	File file2 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file2.txt");
+    	File file3 = new File(getProjectDir(), getProject().getProperty("to.dir")+"/file3.txt");
     	assertTrue(file1.exists());
     	assertTrue(file2.exists());
     	assertTrue(file3.exists());

Modified: ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/MoveTest.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/MoveTest.java?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/MoveTest.java (original)
+++ ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/MoveTest.java Wed Sep 28 11:42:46 2005
@@ -82,11 +82,28 @@
     }
 
     public void testCompleteDirectoryMove() throws IOException {
-        executeTarget("testCompleteDirectoryMove");
+	testCompleteDirectoryMove("testCompleteDirectoryMove");
+    }
+
+    public void testCompleteDirectoryMove2() throws IOException {
+	testCompleteDirectoryMove("testCompleteDirectoryMove2");
+    }
+
+    private void testCompleteDirectoryMove(String target) throws IOException {
+        executeTarget(target);
         assertTrue(getProject().resolveFile("E").exists());
         assertTrue(getProject().resolveFile("E/1").exists());
         assertTrue(!getProject().resolveFile("A/1").exists());
-        assertTrue(!getProject().resolveFile("A").exists());
+	// <path> swallows the basedir, it seems
+	//assertTrue(!getProject().resolveFile("A").exists());
+    }
+
+    public void testPathElementMove() throws IOException {
+        executeTarget("testPathElementMove");
+        assertTrue(getProject().resolveFile("E").exists());
+        assertTrue(getProject().resolveFile("E/1").exists());
+        assertTrue(!getProject().resolveFile("A/1").exists());
+        assertTrue(getProject().resolveFile("A").exists());
     }
 
     public void testMoveFileAndFileset() {

Modified: ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java?rev=292247&r1=292246&r2=292247&view=diff
==============================================================================
--- ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java (original)
+++ ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java Wed Sep 28 11:42:46 2005
@@ -60,7 +60,15 @@
     }
 
     public void testCopyAndRemove() {
-        executeTarget("copyandremove");
+	testCopyAndRemove("copyandremove");
+    }
+
+    public void testCopyAndRemoveWithFileList() {
+	testCopyAndRemove("copyandremove-with-filelist");
+    }
+
+    private void testCopyAndRemove(String target) {
+        executeTarget(target);
         String d = getProject().getProperty("dest") + "/a/b/c/d";
         assertFileIsPresent(d);
         String f = getProject().getProperty("dest") + "/e/f";



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org