git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@280944 13f79535-47bb-0310-9956-ffa450edef68master
@@ -12,11 +12,14 @@ | |||
<h3>Description</h3> | |||
<p>Deletes a single file, a specified directory and all its files and | |||
subdirectories, or a set of files specified by one or more | |||
<a href="../CoreTypes/fileset.html">FileSet</a>s. | |||
When specifying a set of files, empty directories are <i>not</i> removed by | |||
default. | |||
To remove empty directories, use the <code>includeEmptyDirs</code> attribute. | |||
</p> | |||
<a href="../CoreTypes/resources.html#collection">resource collection</a>s. | |||
The literal implication of <code><fileset></code> is that | |||
directories are not included; however the removal of empty directories can | |||
be triggered when using nested filesets by setting the | |||
<code>includeEmptyDirs</code> attribute to <i>true</i>. Note that this | |||
attribute is meaningless in the context of any of the various resource | |||
collection types that <i>do</i> include directories, but that no attempt | |||
will be made to delete non-empty directories in any case.</p> | |||
<p> | |||
If you use this task to delete temporary files created by editors | |||
and it doesn't seem to work, read up on the | |||
@@ -37,7 +40,7 @@ in <strong>Directory-based Tasks</strong>, and see the | |||
filename (if the file exists in the current base directory), a | |||
relative-path filename, or a full-path filename.</td> | |||
<td align="center" valign="middle" rowspan="2">At least one of the two, | |||
unless a <code><fileset></code> is specified.</td> | |||
unless nested resource collections are specified | |||
</tr> | |||
<tr> | |||
<td valign="top">dir</td> | |||
@@ -88,7 +91,7 @@ in <strong>Directory-based Tasks</strong>, and see the | |||
</tr> | |||
<tr> | |||
<td valign="top">includes</td> | |||
<td valign="top"><em>Deprecated.</em> Use <code><fileset></code>. | |||
<td valign="top"><em>Deprecated.</em> Use resource collections. | |||
Comma- or space-separated list of patterns of | |||
files that must be deleted. All files are relative to the directory | |||
specified in <code>dir</code>.</td> | |||
@@ -96,14 +99,14 @@ in <strong>Directory-based Tasks</strong>, and see the | |||
</tr> | |||
<tr> | |||
<td valign="top">includesfile</td> | |||
<td valign="top"><em>Deprecated.</em> Use <code><fileset></code>. | |||
<td valign="top"><em>Deprecated.</em> Use resource collections. | |||
The name of a file. Each line of | |||
this file is taken to be an include pattern.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">excludes</td> | |||
<td valign="top"><em>Deprecated.</em> Use <code><fileset></code>. | |||
<td valign="top"><em>Deprecated.</em> Use resource collections. | |||
Comma- or space-separated list of patterns of | |||
files that must be excluded from the deletion list. | |||
All files are relative to the directory specified in <code>dir</code>. | |||
@@ -112,14 +115,14 @@ in <strong>Directory-based Tasks</strong>, and see the | |||
</tr> | |||
<tr> | |||
<td valign="top">excludesfile</td> | |||
<td valign="top"><em>Deprecated.</em> Use <code><fileset></code>. | |||
<td valign="top"><em>Deprecated.</em> Use resource collections. | |||
The name of a file. Each line of | |||
this file is taken to be an exclude pattern</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">defaultexcludes</td> | |||
<td valign="top"><em>Deprecated.</em> Use <code><fileset></code>. | |||
<td valign="top"><em>Deprecated.</em> Use resource collections. | |||
Whether to use <a href="../dirtasks.html#defaultexcludes"> | |||
default excludes.</a></td> | |||
<td align="center" valign="top">No, default "true"</td> | |||
@@ -131,7 +134,7 @@ in <strong>Directory-based Tasks</strong>, and see the | |||
failure to delete a file, this causes the jvm to attempt | |||
to delete the file when the jvm process is terminating. | |||
<em>Since Ant 1.6.2</em></td> | |||
<td align="center" valign="top">No, default "false".</td> | |||
<td align="center" valign="top">No, default "false"</td> | |||
</tr> | |||
</table> | |||
<h3>Examples</h3> | |||
@@ -158,7 +161,7 @@ and any subdirectories.</p> | |||
</pre> | |||
<p>deletes all files and subdirectories of <code>build</code>, without | |||
<code>build</code> itself.</p> | |||
<hr><p align="center">Copyright © 2000-2002,2004-2005 The Apache Software Foundation. | |||
<hr><p align="center">Copyright © 2000-2002, 2004-2005 The Apache Software Foundation. | |||
All rights Reserved.</p> | |||
</body> | |||
@@ -2,27 +2,107 @@ | |||
<project name="delete-test" basedir="." default="test1"> | |||
<target name="test1"> | |||
<delete/> | |||
</target> | |||
<property name="dirname" value="taskdefs.tmp" /> | |||
<property name="dir" location="${dirname}" /> | |||
<macrodef name="expectabsent"> | |||
<sequential> | |||
<fail> | |||
<condition> | |||
<available file="${dir}" /> | |||
</condition> | |||
</fail> | |||
</sequential> | |||
</macrodef> | |||
<macrodef name="expectdirsonly"> | |||
<sequential> | |||
<fail> | |||
<condition> | |||
<or> | |||
<resourcecount when="greater" count="0"> | |||
<fileset refid="fs" /> | |||
</resourcecount> | |||
<not> | |||
<resourcecount count="${srcdirs}"> | |||
<dirset dir="${dir}" /> | |||
</resourcecount> | |||
</not> | |||
</or> | |||
</condition> | |||
</fail> | |||
</sequential> | |||
</macrodef> | |||
<target name="init"> | |||
<mkdir dir="taskdefs.tmp" /> | |||
<copy todir="taskdefs.tmp"> | |||
<fileset dir="." excludes="taskdefs.tmp,taskdefs.tmp/**" /> | |||
<resourcecount property="srcdirs"> | |||
<dirset dir="${basedir}" /> | |||
</resourcecount> | |||
<resourcecount property="srcsize"> | |||
<files includes="${basedir}/" /> | |||
</resourcecount> | |||
<mkdir dir="${dir}" /> | |||
<copy todir="${dir}"> | |||
<fileset dir="${basedir}" excludes="${dirname},${dirname}/**" /> | |||
</copy> | |||
</target> | |||
<target name="test1"> | |||
<delete /> | |||
</target> | |||
<target name="test2" depends="init"> | |||
<delete file="taskdefs.tmp"/> | |||
<delete file="${dir}" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="${srcsize}"> | |||
<files includes="${dir}/" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="test4" depends="init"> | |||
<delete dir="taskdefs.tmp"/> | |||
<delete dir="${dir}" /> | |||
<expectabsent /> | |||
</target> | |||
<target name="cleanup"> | |||
<delete dir="taskdefs.tmp" /> | |||
<target name="test5" depends="init"> | |||
<delete dir="${dir}" includes="**" /> | |||
<expectdirsonly /> | |||
</target> | |||
<target name="test6" depends="init"> | |||
<delete dir="${dir}" includes="**" includeemptydirs="true" /> | |||
<expectabsent /> | |||
</target> | |||
<target name="test7" depends="init"> | |||
<delete> | |||
<fileset id="fs" dir="${dir}" /> | |||
</delete> | |||
<expectdirsonly /> | |||
</target> | |||
<target name="test8" depends="init"> | |||
<delete includeemptydirs="true"> | |||
<fileset dir="${dir}" /> | |||
</delete> | |||
<expectabsent /> | |||
</target> | |||
<target name="test9" depends="init"> | |||
<delete> | |||
<files includes="${dir}/**" /> | |||
</delete> | |||
<expectabsent /> | |||
</target> | |||
<target name="cleanup" depends="test4" /> | |||
</project> |
@@ -19,12 +19,21 @@ package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.taskdefs.condition.Os; | |||
import org.apache.tools.ant.types.Path; | |||
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.resources.Sort; | |||
import org.apache.tools.ant.types.resources.BCFileSet; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.comparators.FileSystem; | |||
import org.apache.tools.ant.types.resources.comparators.Reverse; | |||
import org.apache.tools.ant.types.selectors.AndSelector; | |||
import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; | |||
import org.apache.tools.ant.types.selectors.ContainsSelector; | |||
@@ -70,6 +79,7 @@ public class Delete extends MatchingTask { | |||
private boolean quiet = false; | |||
private boolean failonerror = true; | |||
private boolean deleteOnExit = false; | |||
private Vector rcs = new Vector(); | |||
/** | |||
* Set the name of a single file to be removed. | |||
@@ -87,6 +97,7 @@ public class Delete extends MatchingTask { | |||
*/ | |||
public void setDir(File dir) { | |||
this.dir = dir; | |||
getImplicitFileSet().setDir(dir); | |||
} | |||
/** | |||
@@ -155,6 +166,14 @@ public class Delete extends MatchingTask { | |||
filesets.addElement(set); | |||
} | |||
/** | |||
* Add an arbitrary ResourceCollection to be deleted. | |||
* @param rc the filesystem-only ResourceCollection. | |||
*/ | |||
public void add(ResourceCollection rc) { | |||
rcs.add(rc); | |||
} | |||
/** | |||
* add a name entry on the include list | |||
* @return a NameEntry object to be configured | |||
@@ -442,9 +461,9 @@ public class Delete extends MatchingTask { | |||
+ "Use a nested fileset element instead."); | |||
} | |||
if (file == null && dir == null && filesets.size() == 0) { | |||
if (file == null && dir == null && filesets.size() == 0 && rcs.size() == 0) { | |||
throw new BuildException("At least one of the file or dir " | |||
+ "attributes, or a fileset element, " | |||
+ "attributes, or a nested resource collection, " | |||
+ "must be set."); | |||
} | |||
@@ -453,7 +472,6 @@ public class Delete extends MatchingTask { | |||
+ "set to true", getLocation()); | |||
} | |||
// delete the single file | |||
if (file != null) { | |||
if (file.exists()) { | |||
@@ -497,39 +515,32 @@ public class Delete extends MatchingTask { | |||
} | |||
removeDir(dir); | |||
} | |||
// delete the files in the filesets | |||
Path p = new Path(getProject()); | |||
p.addAll(rcs); | |||
for (int i = 0; i < filesets.size(); i++) { | |||
FileSet fs = (FileSet) filesets.elementAt(i); | |||
try { | |||
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); | |||
String[] files = ds.getIncludedFiles(); | |||
String[] dirs = ds.getIncludedDirectories(); | |||
removeFiles(fs.getDir(getProject()), files, dirs); | |||
} catch (BuildException be) { | |||
// directory doesn't exist or is not readable | |||
if (failonerror) { | |||
throw be; | |||
} else { | |||
log(be.getMessage(), | |||
quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); | |||
} | |||
} | |||
FileSet fs = (FileSet) filesets.get(i); | |||
p.add(includeEmpty ? new BCFileSet(fs) : fs); | |||
} | |||
// delete the files from the default fileset | |||
if (usedMatchingTask && dir != null) { | |||
try { | |||
DirectoryScanner ds = super.getDirectoryScanner(dir); | |||
String[] files = ds.getIncludedFiles(); | |||
String[] dirs = ds.getIncludedDirectories(); | |||
removeFiles(dir, files, dirs); | |||
} catch (BuildException be) { | |||
// directory doesn't exist or is not readable | |||
if (failonerror) { | |||
throw be; | |||
} else { | |||
log(be.getMessage(), | |||
//add the files from the default fileset: | |||
FileSet implicit = getImplicitFileSet(); | |||
p.add(includeEmpty ? new BCFileSet(implicit) : implicit); | |||
} | |||
// delete the files in the resource collections; sort to files, then dirs | |||
Sort s = new Sort(); | |||
s.add(new Reverse(new FileSystem())); | |||
s.add(p); | |||
for (Iterator iter = s.iterator(); iter.hasNext();) { | |||
FileResource r = (FileResource) iter.next(); | |||
if (!(r.isDirectory()) || r.getFile().list().length == 0) { | |||
log("Deleting " + r, verbosity); | |||
if (!delete(r.getFile())) { | |||
String message = "Unable to delete " | |||
+ (r.isDirectory() ? "directory " : "file ") + r; | |||
if (failonerror) { | |||
throw new BuildException(message); | |||
} | |||
log(message, | |||
quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); | |||
} | |||
} | |||
@@ -0,0 +1,71 @@ | |||
/* | |||
* Copyright 2005 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.types.resources; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.FileSet; | |||
/** | |||
* Utility FileSet that includes directories for backwards-compatibility | |||
* with certain tasks e.g. Delete. | |||
* @since Ant 1.7 | |||
*/ | |||
public class BCFileSet extends FileSet { | |||
/** | |||
* Default constructor. | |||
*/ | |||
public BCFileSet() { | |||
} | |||
/** | |||
* Construct a new BCFileSet from the specified FileSet. | |||
* @param fs the FileSet from which to inherit config. | |||
*/ | |||
public BCFileSet(FileSet fs) { | |||
super(fs); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
if (isReference()) { | |||
return ((FileSet) getRef(getProject())).iterator(); | |||
} | |||
FileResourceIterator result = new FileResourceIterator(getDir()); | |||
result.addFiles(getDirectoryScanner().getIncludedFiles()); | |||
result.addFiles(getDirectoryScanner().getIncludedDirectories()); | |||
return result; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
if (isReference()) { | |||
return ((FileSet) getRef(getProject())).size(); | |||
} | |||
return getDirectoryScanner().getIncludedFilesCount() | |||
+ getDirectoryScanner().getIncludedDirsCount(); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* Copyright 2005 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.types.resources.comparators; | |||
import java.io.File; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
* Compares filesystem Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public class FileSystem extends ResourceComparator { | |||
private static FileUtils fileUtils = FileUtils.getFileUtils(); | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws ClassCastException if either resource is not an instance of FileResource. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
File foofile = ((FileResource) foo).getFile(); | |||
File barfile = ((FileResource) bar).getFile(); | |||
return foofile.equals(barfile) ? 0 | |||
: fileUtils.isLeadingPath(foofile, barfile) ? -1 | |||
: fileUtils.normalize(foofile.getAbsolutePath()).compareTo( | |||
fileUtils.normalize(barfile.getAbsolutePath())); | |||
} | |||
} |
@@ -1341,6 +1341,27 @@ public class FileUtils { | |||
return (p.startsWith(l)) ? p.substring(l.length()) : p; | |||
} | |||
/** | |||
* Learn whether one path "leads" another. | |||
* @param leading The leading path, must not be null, must be absolute. | |||
* @param path The path to remove from, must not be null, must be absolute. | |||
* @return true if path starts with leading; false otherwise. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isLeadingPath(File leading, File path) { | |||
String l = normalize(leading.getAbsolutePath()).getAbsolutePath(); | |||
String p = normalize(path.getAbsolutePath()).getAbsolutePath(); | |||
if (l.equals(p)) { | |||
return true; | |||
} | |||
// ensure that l ends with a / | |||
// so we never think /foo was a parent directory of /foobar | |||
if (!l.endsWith(File.separator)) { | |||
l += File.separator; | |||
} | |||
return p.startsWith(l); | |||
} | |||
/** | |||
* Constructs a <code>file:</code> URI that represents the | |||
* external form of the given pathname. | |||
@@ -42,8 +42,23 @@ public class DeleteTest extends BuildFileTest { | |||
public void test2() { | |||
executeTarget("test2"); | |||
} | |||
//where oh where has my test case 3 gone? | |||
public void test4() { | |||
executeTarget("test4"); | |||
} | |||
public void test5() { | |||
executeTarget("test5"); | |||
} | |||
public void test6() { | |||
executeTarget("test6"); | |||
} | |||
public void test7() { | |||
executeTarget("test7"); | |||
} | |||
public void test8() { | |||
executeTarget("test8"); | |||
} | |||
public void test9() { | |||
executeTarget("test9"); | |||
} | |||
} |