bodewig 2004/11/09 02:19:52
Modified: src/main/org/apache/tools/ant/taskdefs Sync.java
src/main/org/apache/tools/ant/types PatternSet.java
src/testcases/org/apache/tools/ant BuildFileTest.java
Added: src/etc/testcases/taskdefs sync.xml
src/testcases/org/apache/tools/ant/taskdefs SyncTest.java
Log:
Preparations for PR: 21832, in particular unit tests and some
refactorings for <sync>
Changes to Sync:
* drop JDK 1.1 compatibility,
* override scan instead of buildMap in MyCopy so that we get the
included directories even if includeEmptyDirs is false.
* use a DirectoryScanner to find orphaned files instead of the
recursive algorithm.
Revision Changes Path
1.1 ant/src/etc/testcases/taskdefs/sync.xml
Index: sync.xml
===================================================================
<?xml version="1.0"?>
<project name="sync-test" default="not-me">
<property name="scratch" location="synctest"/>
<target name="not-me">
<fail>This file must be used from a test case</fail>
</target>
<target name="cleanup">
<delete dir="${scratch}"/>
</target>
<target name="setup">
<property name="src" location="${scratch}/source"/>
<property name="dest" location="${scratch}/target"/>
<mkdir dir="${src}"/>
<mkdir dir="${dest}"/>
</target>
<target name="simplecopy" depends="setup">
<mkdir dir="${src}/a/b/c"/>
<touch file="${src}/a/b/c/d"/>
<sync todir="${dest}">
<fileset dir="${src}"/>
</sync>
</target>
<target name="copyandremove" 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}">
<fileset dir="${src}"/>
</sync>
</target>
<target name="emptycopy" depends="setup">
<mkdir dir="${src}/a/b/c"/>
<touch file="${src}/a/b/c/d"/>
<sync todir="${dest}">
<fileset dir="${src}" excludes="**/d"/>
</sync>
</target>
<target name="emptydircopy" depends="setup">
<mkdir dir="${src}/a/b/c"/>
<touch file="${src}/a/b/c/d"/>
<sync todir="${dest}"
includeemptydirs="true">
<fileset dir="${src}" excludes="**/d"/>
</sync>
</target>
<target name="emptydircopyandremove" depends="setup">
<mkdir dir="${src}/a/b/c"/>
<touch file="${src}/a/b/c/d"/>
<mkdir dir="${dest}/e/f"/>
<sync todir="${dest}"
includeemptydirs="true">
<fileset dir="${src}" excludes="**/d"/>
</sync>
</target>
</project>
1.14 +41 -65 ant/src/main/org/apache/tools/ant/taskdefs/Sync.java
Index: Sync.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Sync.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Sync.java 25 May 2004 12:14:07 -0000 1.13
+++ Sync.java 9 Nov 2004 10:19:51 -0000 1.14
@@ -25,12 +25,16 @@
import java.io.File;
-import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.IdentityMapper;
@@ -82,7 +86,7 @@
File toDir = _copy.getToDir();
// The complete list of files to copy
- Hashtable allFiles = _copy._dest2src;
+ Set allFiles = _copy.nonOrphans;
// If the destination directory didn't already exist,
// or was empty, then no previous file removal is necessary!
@@ -143,54 +147,29 @@
* @return the number of orphaned files and directories actually removed.
* Position 0 of the array is the number of orphaned directories.
* Position 1 of the array is the number or orphaned files.
- * Position 2 is meaningless.
*/
- private int[] removeOrphanFiles(Hashtable nonOrphans, File file) {
- int[] removedCount = new int[] {0, 0, 0};
- if (file.isDirectory()) {
- File[] children = file.listFiles();
- for (int i = 0; i < children.length; ++i) {
- int[] temp = removeOrphanFiles(nonOrphans, children[i]);
- removedCount[0] += temp[0];
- removedCount[1] += temp[1];
- removedCount[2] += temp[2];
- }
-
- if (nonOrphans.get(file) == null && removedCount[2] == 0) {
- log("Removing orphan directory: " + file, Project.MSG_DEBUG);
- file.delete();
- ++removedCount[0];
- } else {
- /*
- Contrary to what is said above, position 2 is not
- meaningless inside the recursion.
- Position 2 is used to carry information back up the
- recursion about whether or not a directory contains
- a directory or file at any depth that is not an
- orphan
- This has to be done, because if you have the
- following directory structure: c:\src\a\file and
- your mapper src files were constructed like so:
- <include name="**\a\**\*"/>
- The folder 'a' will not be in the hashtable of
- nonorphans. So, before deleting it as an orphan, we
- have to know whether or not any of its children at
- any level are orphans.
- If no, then this folder is also an orphan, and may
- be deleted. I do this by changing position 2 to a
- '1'.
- */
- removedCount[2] = 1;
- }
-
- } else {
- if (nonOrphans.get(file) == null) {
- log("Removing orphan file: " + file, Project.MSG_DEBUG);
- file.delete();
- ++removedCount[1];
- } else {
- removedCount[2] = 1;
- }
+ private int[] removeOrphanFiles(Set nonOrphans, File toDir) {
+ int[] removedCount = new int[] {0, 0};
+ DirectoryScanner ds = new DirectoryScanner();
+ ds.setBasedir(toDir);
+ Set s = new HashSet(nonOrphans);
+ s.add("");
+ String[] excls = (String[]) s.toArray(new String[s.size()]);
+ ds.setExcludes(excls);
+ ds.scan();
+ String[] files = ds.getIncludedFiles();
+ for (int i = 0; i < files.length; i++) {
+ File f = new File(toDir, files[i]);
+ log("Removing orphan file: " + f, Project.MSG_DEBUG);
+ f.delete();
+ ++removedCount[1];
+ }
+ String[] dirs = ds.getIncludedDirectories();
+ for (int i = dirs.length - 1 ; i >= 0 ; --i) {
+ File f = new File(toDir, dirs[i]);
+ log("Removing orphan directory: " + f, Project.MSG_DEBUG);
+ f.delete();
+ ++removedCount[0];
}
return removedCount;
}
@@ -303,25 +282,22 @@
// List of files that must be copied, irrelevant from the
// fact that they are newer or not than the destination.
- private Hashtable _dest2src = new Hashtable();
+ private Set nonOrphans = new HashSet();
public MyCopy() {
}
- protected void buildMap(File fromDir, File toDir, String[] names,
- FileNameMapper mapper, Hashtable map) {
- assertTrue("No mapper", mapper instanceof IdentityMapper);
-
- super.buildMap(fromDir, toDir, names, mapper, map);
-
- for (int i = 0; i < names.length; ++i) {
- String name = names[i];
- File dest = new File(toDir, name);
- // No need to instantiate the src file, as we use the
- // table as a set (to remain Java 1.1 compatible!!!).
- //File src = new File(fromDir, name);
- //_dest2src.put(dest, src);
- _dest2src.put(dest, fromDir);
+ protected void scan(File fromDir, File toDir, String[] files,
+ String[] dirs) {
+ assertTrue("No mapper", mapperElement == null);
+
+ super.scan(fromDir, toDir, files, dirs);
+
+ for (int i = 0; i < files.length; ++i) {
+ nonOrphans.add(files[i]);
+ }
+ for (int i = 0; i < dirs.length; ++i) {
+ nonOrphans.add(dirs[i]);
}
}
1.41 +1 -1 ant/src/main/org/apache/tools/ant/types/PatternSet.java
Index: PatternSet.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/types/PatternSet.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- PatternSet.java 9 Mar 2004 16:48:41 -0000 1.40
+++ PatternSet.java 9 Nov 2004 10:19:51 -0000 1.41
@@ -434,7 +434,7 @@
*/
private String[] makeArray(Vector list, Project p) {
if (list.size() == 0) {
- return null;
+ return null;
}
Vector tmpNames = new Vector();
1.30 +12 -0 ant/src/testcases/org/apache/tools/ant/BuildFileTest.java
Index: BuildFileTest.java
===================================================================
RCS file:
/home/cvs/ant/src/testcases/org/apache/tools/ant/BuildFileTest.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- BuildFileTest.java 9 Mar 2004 16:48:56 -0000 1.29
+++ BuildFileTest.java 9 Nov 2004 10:19:51 -0000 1.30
@@ -112,6 +112,18 @@
}
/**
+ * Assert that the given substring is in the log messages
+ */
+
+ protected void assertDebuglogContaining(String substring) {
+ String realLog = getFullLog();
+ assertTrue("expecting debug log to contain \"" + substring
+ + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf(substring) >= 0);
+ }
+
+ /**
* Gets the log the BuildFileTest object.
* only valid if configureProject() has
* been called.
1.1
ant/src/testcases/org/apache/tools/ant/taskdefs/SyncTest.java
Index: SyncTest.java
===================================================================
/*
* Copyright 2000-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.BuildFileTest;
import java.io.File;
public class SyncTest extends BuildFileTest {
public SyncTest(String name) {
super(name);
}
public void setUp() {
configureProject("src/etc/testcases/taskdefs/sync.xml");
}
public void tearDown() {
executeTarget("cleanup");
}
public void testSimpleCopy() {
executeTarget("simplecopy");
String d = getProject().getProperty("dest") + "/a/b/c/d";
assertFileIsPresent(d);
assertTrue(getFullLog().indexOf("dangling") == -1);
}
public void testEmptyCopy() {
executeTarget("emptycopy");
String d = getProject().getProperty("dest") + "/a/b/c/d";
assertFileIsNotPresent(d);
String c = getProject().getProperty("dest") + "/a/b/c";
assertFileIsNotPresent(c);
assertTrue(getFullLog().indexOf("dangling") == -1);
}
public void testEmptyDirCopy() {
executeTarget("emptydircopy");
String d = getProject().getProperty("dest") + "/a/b/c/d";
assertFileIsNotPresent(d);
String c = getProject().getProperty("dest") + "/a/b/c";
assertFileIsPresent(c);
assertTrue(getFullLog().indexOf("dangling") == -1);
}
public void testCopyAndRemove() {
executeTarget("copyandremove");
String d = getProject().getProperty("dest") + "/a/b/c/d";
assertFileIsPresent(d);
String f = getProject().getProperty("dest") + "/e/f";
assertFileIsNotPresent(f);
assertTrue(getFullLog().indexOf("Removing orphan file:") > -1);
assertDebuglogContaining("Removed 1 dangling file from");
assertDebuglogContaining("Removed 1 dangling directory from");
}
public void testEmptyDirCopyAndRemove() {
executeTarget("emptydircopyandremove");
String d = getProject().getProperty("dest") + "/a/b/c/d";
assertFileIsNotPresent(d);
String c = getProject().getProperty("dest") + "/a/b/c";
assertFileIsPresent(c);
String f = getProject().getProperty("dest") + "/e/f";
assertFileIsNotPresent(f);
assertTrue(getFullLog().indexOf("Removing orphan directory:") > -1);
assertDebuglogContaining("NO dangling file to remove from");
assertDebuglogContaining("Removed 2 dangling directories from");
}
public void assertFileIsPresent(String f) {
assertTrue("Expected file " + f,
getProject().resolveFile(f).exists());
}
public void assertFileIsNotPresent(String f) {
assertTrue("Didn't expect file " + f,
!getProject().resolveFile(f).exists());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]