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]