git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277591 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -158,14 +158,6 @@ | |||||
| </or> | </or> | ||||
| </selector> | </selector> | ||||
| <!-- classes that should be present in Sun based JVMs, but not in | |||||
| Kaffe for example --> | |||||
| <selector id="needs.sun.tools"> | |||||
| <or> | |||||
| <filename name="${optional.package}/Javah*"/> | |||||
| </or> | |||||
| </selector> | |||||
| <selector id="needs.sun.uue"> | <selector id="needs.sun.uue"> | ||||
| <filename name="${ant.package}/taskdefs/email/UUMailer*"/> | <filename name="${ant.package}/taskdefs/email/UUMailer*"/> | ||||
| </selector> | </selector> | ||||
| @@ -647,7 +639,6 @@ | |||||
| <selector refid="needs.jdk1.3+" unless="jdk1.3+"/> | <selector refid="needs.jdk1.3+" unless="jdk1.3+"/> | ||||
| <selector refid="needs.jdk1.4+" unless="jdk1.4+"/> | <selector refid="needs.jdk1.4+" unless="jdk1.4+"/> | ||||
| <selector refid="needs.jdk1.5+" unless="jdk1.5+"/> | <selector refid="needs.jdk1.5+" unless="jdk1.5+"/> | ||||
| <selector refid="needs.sun.tools" unless="sun.tools.present"/> | |||||
| <selector refid="needs.sun.uue" unless="sunuue.present"/> | <selector refid="needs.sun.uue" unless="sunuue.present"/> | ||||
| <selector refid="needs.sun.b64" unless="base64.present"/> | <selector refid="needs.sun.b64" unless="base64.present"/> | ||||
| @@ -1670,4 +1661,4 @@ | |||||
| description="--> creates a minimum distribution in ./dist" | description="--> creates a minimum distribution in ./dist" | ||||
| depends="dist-lite"/> | depends="dist-lite"/> | ||||
| </project> | |||||
| </project> | |||||
| @@ -35,6 +35,17 @@ | |||||
| </sync> | </sync> | ||||
| </target> | </target> | ||||
| <target name="copyandremove-emptypreserve" 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}"/> | |||||
| <preserveintarget/> | |||||
| </sync> | |||||
| </target> | |||||
| <target name="emptycopy" depends="setup"> | <target name="emptycopy" depends="setup"> | ||||
| <mkdir dir="${src}/a/b/c"/> | <mkdir dir="${src}/a/b/c"/> | ||||
| <touch file="${src}/a/b/c/d"/> | <touch file="${src}/a/b/c/d"/> | ||||
| @@ -69,9 +80,22 @@ | |||||
| <touch file="${dest}/e/f"/> | <touch file="${dest}/e/f"/> | ||||
| <sync todir="${dest}"> | <sync todir="${dest}"> | ||||
| <fileset dir="${src}"/> | <fileset dir="${src}"/> | ||||
| <deletefromtarget> | |||||
| <exclude name="e/f"/> | |||||
| </deletefromtarget> | |||||
| <preserveintarget> | |||||
| <include name="e/f"/> | |||||
| </preserveintarget> | |||||
| </sync> | |||||
| </target> | |||||
| <target name="copynoremove-selectors" 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}"/> | |||||
| <preserveintarget> | |||||
| <filename name="e/f"/> | |||||
| </preserveintarget> | |||||
| </sync> | </sync> | ||||
| </target> | </target> | ||||
| @@ -34,6 +34,9 @@ import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.types.AbstractFileSet; | import org.apache.tools.ant.types.AbstractFileSet; | ||||
| import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
| import org.apache.tools.ant.types.PatternSet; | |||||
| import org.apache.tools.ant.types.selectors.FileSelector; | |||||
| import org.apache.tools.ant.types.selectors.NoneSelector; | |||||
| /** | /** | ||||
| * Synchronize a local target directory from the files defined | * Synchronize a local target directory from the files defined | ||||
| @@ -163,8 +166,33 @@ public class Sync extends Task { | |||||
| DirectoryScanner ds = null; | DirectoryScanner ds = null; | ||||
| if (syncTarget != null) { | if (syncTarget != null) { | ||||
| syncTarget.setTargetDir(toDir); | |||||
| ds = syncTarget.getDirectoryScanner(getProject()); | |||||
| FileSet fs = new FileSet(); | |||||
| fs.setDir(toDir); | |||||
| fs.setCaseSensitive(syncTarget.isCaseSensitive()); | |||||
| fs.setFollowSymlinks(syncTarget.isFollowSymlinks()); | |||||
| // preserveInTarget would find all files we want to keep, | |||||
| // but we need to find all that we want to delete - so the | |||||
| // meaning of all patterns and selectors must be inverted | |||||
| PatternSet ps = syncTarget.mergePatterns(getProject()); | |||||
| String[] excludes = ps.getExcludePatterns(getProject()); | |||||
| fs.appendExcludes(ps.getIncludePatterns(getProject())); | |||||
| fs.appendIncludes(ps.getExcludePatterns(getProject())); | |||||
| fs.setDefaultexcludes(!syncTarget.getDefaultexcludes()); | |||||
| // selectors are implicitly ANDed in DirectoryScanner. To | |||||
| // revert their logic we wrap them into a <none> selector | |||||
| // instead. | |||||
| FileSelector[] s = syncTarget.getSelectors(getProject()); | |||||
| if (s.length > 0) { | |||||
| NoneSelector ns = new NoneSelector(); | |||||
| for (int i = 0; i < s.length; i++) { | |||||
| ns.appendSelector(s[i]); | |||||
| } | |||||
| fs.appendSelector(ns); | |||||
| } | |||||
| ds = fs.getDirectoryScanner(getProject()); | |||||
| } else { | } else { | ||||
| ds = new DirectoryScanner(); | ds = new DirectoryScanner(); | ||||
| ds.setBasedir(toDir); | ds.setBasedir(toDir); | ||||
| @@ -180,7 +208,7 @@ public class Sync extends Task { | |||||
| ++removedCount[1]; | ++removedCount[1]; | ||||
| } | } | ||||
| String[] dirs = ds.getIncludedDirectories(); | String[] dirs = ds.getIncludedDirectories(); | ||||
| // ds returns the directories as it has visited them. | |||||
| // ds returns the directories in lexicographic order. | |||||
| // iterating through the array backwards means we are deleting | // iterating through the array backwards means we are deleting | ||||
| // leaves before their parent nodes - thus making sure (well, | // leaves before their parent nodes - thus making sure (well, | ||||
| // more likely) that the directories are empty when we try to | // more likely) that the directories are empty when we try to | ||||
| @@ -306,13 +334,13 @@ public class Sync extends Task { | |||||
| * are not present in any source directory. | * are not present in any source directory. | ||||
| * | * | ||||
| * <p>You must not invoke this method more than once.</p> | * <p>You must not invoke this method more than once.</p> | ||||
| * @param s a deletefromtarget nested element | |||||
| * @param s a preserveintarget nested element | |||||
| * @since Ant 1.7 | * @since Ant 1.7 | ||||
| */ | */ | ||||
| public void addDeleteFromTarget(SyncTarget s) { | |||||
| public void addPreserveInTarget(SyncTarget s) { | |||||
| if (syncTarget != null) { | if (syncTarget != null) { | ||||
| throw new BuildException("you must not specify multiple " | throw new BuildException("you must not specify multiple " | ||||
| + "deletefromtaget elements."); | |||||
| + "preserveintarget elements."); | |||||
| } | } | ||||
| syncTarget = s; | syncTarget = s; | ||||
| } | } | ||||
| @@ -381,24 +409,19 @@ public class Sync extends Task { | |||||
| */ | */ | ||||
| public SyncTarget() { | public SyncTarget() { | ||||
| super(); | super(); | ||||
| setDefaultexcludes(false); | |||||
| } | } | ||||
| /** | /** | ||||
| * Override AbstractFileSet#setDir(File) to disallow | * Override AbstractFileSet#setDir(File) to disallow | ||||
| * setting the directory. This is now set by #setTargetDir(File). | |||||
| * setting the directory. | |||||
| * @param dir ignored | * @param dir ignored | ||||
| * @throws BuildException always | * @throws BuildException always | ||||
| */ | */ | ||||
| public void setDir(File dir) throws BuildException { | public void setDir(File dir) throws BuildException { | ||||
| throw new BuildException("synctarget doesn't support the dir " | |||||
| throw new BuildException("preserveintarget doesn't support the dir " | |||||
| + "attribute"); | + "attribute"); | ||||
| } | } | ||||
| private void setTargetDir(File dir) throws BuildException { | |||||
| super.setDir(dir); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -1,5 +1,5 @@ | |||||
| /* | /* | ||||
| * Copyright 2002-2004 The Apache Software Foundation | |||||
| * Copyright 2002-2005 The Apache Software Foundation | |||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| * you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
| @@ -63,7 +63,7 @@ public abstract class AbstractFileSet extends DataType | |||||
| private File dir; | private File dir; | ||||
| private boolean useDefaultExcludes = true; | private boolean useDefaultExcludes = true; | ||||
| private boolean isCaseSensitive = true; | |||||
| private boolean caseSensitive = true; | |||||
| private boolean followSymlinks = true; | private boolean followSymlinks = true; | ||||
| /** | /** | ||||
| @@ -84,7 +84,7 @@ public abstract class AbstractFileSet extends DataType | |||||
| this.additionalPatterns = fileset.additionalPatterns; | this.additionalPatterns = fileset.additionalPatterns; | ||||
| this.selectors = fileset.selectors; | this.selectors = fileset.selectors; | ||||
| this.useDefaultExcludes = fileset.useDefaultExcludes; | this.useDefaultExcludes = fileset.useDefaultExcludes; | ||||
| this.isCaseSensitive = fileset.isCaseSensitive; | |||||
| this.caseSensitive = fileset.caseSensitive; | |||||
| this.followSymlinks = fileset.followSymlinks; | this.followSymlinks = fileset.followSymlinks; | ||||
| setProject(fileset.getProject()); | setProject(fileset.getProject()); | ||||
| } | } | ||||
| @@ -215,6 +215,24 @@ public abstract class AbstractFileSet extends DataType | |||||
| defaultPatterns.setIncludes(includes); | defaultPatterns.setIncludes(includes); | ||||
| } | } | ||||
| /** | |||||
| * Appends <code>includes</code> to the current list of include | |||||
| * patterns. | |||||
| * | |||||
| * @param includes array containing the include patterns. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public void appendIncludes(String[] includes) { | |||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| if (includes != null) { | |||||
| for (int i = 0; i < includes.length; i++) { | |||||
| defaultPatterns.createInclude().setName(includes[i]); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Appends <code>excludes</code> to the current list of exclude | * Appends <code>excludes</code> to the current list of exclude | ||||
| * patterns. | * patterns. | ||||
| @@ -230,6 +248,24 @@ public abstract class AbstractFileSet extends DataType | |||||
| defaultPatterns.setExcludes(excludes); | defaultPatterns.setExcludes(excludes); | ||||
| } | } | ||||
| /** | |||||
| * Appends <code>excludes</code> to the current list of include | |||||
| * patterns. | |||||
| * | |||||
| * @param excludes array containing the exclude patterns. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public void appendExcludes(String[] excludes) { | |||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| if (excludes != null) { | |||||
| for (int i = 0; i < excludes.length; i++) { | |||||
| defaultPatterns.createExclude().setName(excludes[i]); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Sets the <code>File</code> containing the includes patterns. | * Sets the <code>File</code> containing the includes patterns. | ||||
| * | * | ||||
| @@ -266,16 +302,38 @@ public abstract class AbstractFileSet extends DataType | |||||
| this.useDefaultExcludes = useDefaultExcludes; | this.useDefaultExcludes = useDefaultExcludes; | ||||
| } | } | ||||
| /** | |||||
| * Whether default exclusions should be used or not. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean getDefaultexcludes() { | |||||
| return (isReference()) | |||||
| ? getRef(getProject()).getDefaultexcludes() : useDefaultExcludes; | |||||
| } | |||||
| /** | /** | ||||
| * Sets case sensitivity of the file system. | * Sets case sensitivity of the file system. | ||||
| * | * | ||||
| * @param isCaseSensitive <code>boolean</code>. | * @param isCaseSensitive <code>boolean</code>. | ||||
| */ | */ | ||||
| public void setCaseSensitive(boolean isCaseSensitive) { | |||||
| public void setCaseSensitive(boolean caseSensitive) { | |||||
| if (isReference()) { | if (isReference()) { | ||||
| throw tooManyAttributes(); | throw tooManyAttributes(); | ||||
| } | } | ||||
| this.isCaseSensitive = isCaseSensitive; | |||||
| this.caseSensitive = caseSensitive; | |||||
| } | |||||
| /** | |||||
| * Find out if the fileset is case sensitive. | |||||
| * | |||||
| * @return <code>boolean</code> indicating whether the fileset is | |||||
| * case sensitive. | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean isCaseSensitive() { | |||||
| return (isReference()) | |||||
| ? getRef(getProject()).isCaseSensitive() : caseSensitive; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -365,16 +423,12 @@ public abstract class AbstractFileSet extends DataType | |||||
| } | } | ||||
| ds.setBasedir(dir); | ds.setBasedir(dir); | ||||
| final int count = additionalPatterns.size(); | |||||
| for (int i = 0; i < count; i++) { | |||||
| Object o = additionalPatterns.elementAt(i); | |||||
| defaultPatterns.append((PatternSet) o, p); | |||||
| } | |||||
| PatternSet ps = mergePatterns(p); | |||||
| p.log(getDataTypeName() + ": Setup scanner in dir " + dir | p.log(getDataTypeName() + ": Setup scanner in dir " + dir | ||||
| + " with " + defaultPatterns, Project.MSG_DEBUG); | |||||
| + " with " + ps, Project.MSG_DEBUG); | |||||
| ds.setIncludes(defaultPatterns.getIncludePatterns(p)); | |||||
| ds.setExcludes(defaultPatterns.getExcludePatterns(p)); | |||||
| ds.setIncludes(ps.getIncludePatterns(p)); | |||||
| ds.setExcludes(ps.getExcludePatterns(p)); | |||||
| if (ds instanceof SelectorScanner) { | if (ds instanceof SelectorScanner) { | ||||
| SelectorScanner ss = (SelectorScanner) ds; | SelectorScanner ss = (SelectorScanner) ds; | ||||
| ss.setSelectors(getSelectors(p)); | ss.setSelectors(getSelectors(p)); | ||||
| @@ -382,7 +436,7 @@ public abstract class AbstractFileSet extends DataType | |||||
| if (useDefaultExcludes) { | if (useDefaultExcludes) { | ||||
| ds.addDefaultExcludes(); | ds.addDefaultExcludes(); | ||||
| } | } | ||||
| ds.setCaseSensitive(isCaseSensitive); | |||||
| ds.setCaseSensitive(caseSensitive); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -683,4 +737,44 @@ public abstract class AbstractFileSet extends DataType | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * @return the include patterns of the default pattern set and all | |||||
| * nested patternsets. | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public String[] mergeIncludes(Project p) { | |||||
| return mergePatterns(p).getIncludePatterns(p); | |||||
| } | |||||
| /** | |||||
| * @return the exclude patterns of the default pattern set and all | |||||
| * nested patternsets. | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public String[] mergeExcludes(Project p) { | |||||
| return mergePatterns(p).getExcludePatterns(p); | |||||
| } | |||||
| /** | |||||
| * @return the default patternset merged with the additional sets | |||||
| * in a new PatternSet instance. | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public PatternSet mergePatterns(Project p) { | |||||
| if (isReference()) { | |||||
| return getRef(p).mergePatterns(p); | |||||
| } | |||||
| PatternSet ps = new PatternSet(); | |||||
| ps.append(defaultPatterns, p); | |||||
| final int count = additionalPatterns.size(); | |||||
| for (int i = 0; i < count; i++) { | |||||
| Object o = additionalPatterns.elementAt(i); | |||||
| ps.append((PatternSet) o, p); | |||||
| } | |||||
| return ps; | |||||
| } | |||||
| } | } | ||||
| @@ -74,7 +74,7 @@ public class CommandlineJava implements Cloneable { | |||||
| * Specialized Environment class for System properties | * Specialized Environment class for System properties | ||||
| */ | */ | ||||
| public static class SysProperties extends Environment implements Cloneable { | public static class SysProperties extends Environment implements Cloneable { | ||||
| private Properties sys = null; | |||||
| Properties sys = null; | |||||
| private Vector propertySets = new Vector(); | private Vector propertySets = new Vector(); | ||||
| /** | /** | ||||
| @@ -1,5 +1,5 @@ | |||||
| /* | /* | ||||
| * Copyright 2002-2004 The Apache Software Foundation | |||||
| * Copyright 2002-2005 The Apache Software Foundation | |||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| * you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | ||||
| @@ -34,6 +34,16 @@ public class NotSelector extends NoneSelector { | |||||
| public NotSelector() { | public NotSelector() { | ||||
| } | } | ||||
| /** | |||||
| * Constructor that inverts the meaning of its argument. | |||||
| * @param other the selector to invert | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public NotSelector(FileSelector other) { | |||||
| this(); | |||||
| appendSelector(other); | |||||
| } | |||||
| /** | /** | ||||
| * @return a string representation of the selector | * @return a string representation of the selector | ||||
| */ | */ | ||||
| @@ -28,6 +28,7 @@ import org.apache.tools.ant.Project; | |||||
| /** | /** | ||||
| * Special <CODE>PipedInputStream</CODE> that will not die | * Special <CODE>PipedInputStream</CODE> that will not die | ||||
| * when the writing <CODE>Thread</CODE> is no longer alive. | * when the writing <CODE>Thread</CODE> is no longer alive. | ||||
| * @since Ant 1.6.2 | |||||
| */ | */ | ||||
| public class LeadPipeInputStream extends PipedInputStream { | public class LeadPipeInputStream extends PipedInputStream { | ||||
| private ProjectComponent managingPc; | private ProjectComponent managingPc; | ||||
| @@ -39,6 +40,16 @@ public class LeadPipeInputStream extends PipedInputStream { | |||||
| super(); | super(); | ||||
| } | } | ||||
| /** | |||||
| * Construct a new <CODE>LeadPipeInputStream</CODE> | |||||
| * with the specified buffer size. | |||||
| * @param size the size of the circular buffer. | |||||
| */ | |||||
| public LeadPipeInputStream(int size) { | |||||
| super(); | |||||
| setBufferSize(size); | |||||
| } | |||||
| /** | /** | ||||
| * Construct a new <CODE>LeadPipeInputStream</CODE> to pull | * Construct a new <CODE>LeadPipeInputStream</CODE> to pull | ||||
| * from the specified <CODE>PipedOutputStream</CODE>. | * from the specified <CODE>PipedOutputStream</CODE>. | ||||
| @@ -49,6 +60,18 @@ public class LeadPipeInputStream extends PipedInputStream { | |||||
| super(src); | super(src); | ||||
| } | } | ||||
| /** | |||||
| * Construct a new <CODE>LeadPipeInputStream</CODE> to pull | |||||
| * from the specified <CODE>PipedOutputStream</CODE>, using a | |||||
| * circular buffer of the specified size. | |||||
| * @param src the <CODE>PipedOutputStream</CODE> source. | |||||
| * @param size the size of the circular buffer. | |||||
| */ | |||||
| public LeadPipeInputStream(PipedOutputStream src, int size) throws IOException { | |||||
| super(src); | |||||
| setBufferSize(size); | |||||
| } | |||||
| //inherit doc | //inherit doc | ||||
| public synchronized int read() throws IOException { | public synchronized int read() throws IOException { | ||||
| int result = -1; | int result = -1; | ||||
| @@ -68,6 +91,28 @@ public class LeadPipeInputStream extends PipedInputStream { | |||||
| return result; | return result; | ||||
| } | } | ||||
| /** | |||||
| * Set the size of the buffer. | |||||
| * @param size the new buffer size. Ignored if <= current size. | |||||
| */ | |||||
| public synchronized void setBufferSize(int size) { | |||||
| if (size > buffer.length) { | |||||
| byte[] newBuffer = new byte[size]; | |||||
| if (in >= 0) { | |||||
| if (in > out) { | |||||
| System.arraycopy(buffer, out, newBuffer, out, in - out); | |||||
| } else { | |||||
| int outlen = buffer.length - out; | |||||
| System.arraycopy(buffer, out, newBuffer, 0, outlen); | |||||
| System.arraycopy(buffer, 0, newBuffer, outlen, in); | |||||
| in+= outlen; | |||||
| out = 0; | |||||
| } | |||||
| } | |||||
| buffer = newBuffer; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Set a managing <CODE>Task</CODE> for | * Set a managing <CODE>Task</CODE> for | ||||
| * this <CODE>LeadPipeInputStream</CODE>. | * this <CODE>LeadPipeInputStream</CODE>. | ||||
| @@ -34,7 +34,7 @@ import junit.framework.TestSuite; | |||||
| /** | /** | ||||
| * Very limited test class for Project. Waiting to be extended. | * Very limited test class for Project. Waiting to be extended. | ||||
| * | * | ||||
| */ | |||||
| */ | |||||
| public class ProjectTest extends TestCase { | public class ProjectTest extends TestCase { | ||||
| private Project p; | private Project p; | ||||
| @@ -70,6 +70,17 @@ public class SyncTest extends BuildFileTest { | |||||
| assertDebuglogContaining("Removed 1 dangling directory from"); | assertDebuglogContaining("Removed 1 dangling directory from"); | ||||
| } | } | ||||
| public void testCopyAndRemoveEmptyPreserve() { | |||||
| executeTarget("copyandremove-emptypreserve"); | |||||
| 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() { | public void testEmptyDirCopyAndRemove() { | ||||
| executeTarget("emptydircopyandremove"); | executeTarget("emptydircopyandremove"); | ||||
| String d = getProject().getProperty("dest") + "/a/b/c/d"; | String d = getProject().getProperty("dest") + "/a/b/c/d"; | ||||
| @@ -92,6 +103,15 @@ public class SyncTest extends BuildFileTest { | |||||
| assertTrue(getFullLog().indexOf("Removing orphan file:") == -1); | assertTrue(getFullLog().indexOf("Removing orphan file:") == -1); | ||||
| } | } | ||||
| public void testCopyNoRemoveSelectors() { | |||||
| executeTarget("copynoremove-selectors"); | |||||
| String d = getProject().getProperty("dest") + "/a/b/c/d"; | |||||
| assertFileIsPresent(d); | |||||
| String f = getProject().getProperty("dest") + "/e/f"; | |||||
| assertFileIsPresent(f); | |||||
| assertTrue(getFullLog().indexOf("Removing orphan file:") == -1); | |||||
| } | |||||
| public void assertFileIsPresent(String f) { | public void assertFileIsPresent(String f) { | ||||
| assertTrue("Expected file " + f, | assertTrue("Expected file " + f, | ||||
| getProject().resolveFile(f).exists()); | getProject().resolveFile(f).exists()); | ||||