Browse Source

delete + resource collection support

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@280944 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 20 years ago
parent
commit
ec53cbb02a
7 changed files with 306 additions and 57 deletions
  1. +16
    -13
      docs/manual/CoreTasks/delete.html
  2. +90
    -10
      src/etc/testcases/taskdefs/delete.xml
  3. +44
    -33
      src/main/org/apache/tools/ant/taskdefs/Delete.java
  4. +71
    -0
      src/main/org/apache/tools/ant/types/resources/BCFileSet.java
  5. +48
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java
  6. +21
    -0
      src/main/org/apache/tools/ant/util/FileUtils.java
  7. +16
    -1
      src/testcases/org/apache/tools/ant/taskdefs/DeleteTest.java

+ 16
- 13
docs/manual/CoreTasks/delete.html View File

@@ -12,11 +12,14 @@
<h3>Description</h3> <h3>Description</h3>
<p>Deletes a single file, a specified directory and all its files and <p>Deletes a single file, a specified directory and all its files and
subdirectories, or a set of files specified by one or more 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>&lt;fileset&gt;</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> <p>
If you use this task to delete temporary files created by editors If you use this task to delete temporary files created by editors
and it doesn't seem to work, read up on the 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 filename (if the file exists in the current base directory), a
relative-path filename, or a full-path filename.</td> relative-path filename, or a full-path filename.</td>
<td align="center" valign="middle" rowspan="2">At least one of the two, <td align="center" valign="middle" rowspan="2">At least one of the two,
unless a <code>&lt;fileset&gt;</code> is specified.</td>
unless nested resource collections are specified
</tr> </tr>
<tr> <tr>
<td valign="top">dir</td> <td valign="top">dir</td>
@@ -88,7 +91,7 @@ in <strong>Directory-based Tasks</strong>, and see the
</tr> </tr>
<tr> <tr>
<td valign="top">includes</td> <td valign="top">includes</td>
<td valign="top"><em>Deprecated.</em> Use <code>&lt;fileset&gt;</code>.
<td valign="top"><em>Deprecated.</em> Use resource collections.
Comma- or space-separated list of patterns of Comma- or space-separated list of patterns of
files that must be deleted. All files are relative to the directory files that must be deleted. All files are relative to the directory
specified in <code>dir</code>.</td> specified in <code>dir</code>.</td>
@@ -96,14 +99,14 @@ in <strong>Directory-based Tasks</strong>, and see the
</tr> </tr>
<tr> <tr>
<td valign="top">includesfile</td> <td valign="top">includesfile</td>
<td valign="top"><em>Deprecated.</em> Use <code>&lt;fileset&gt;</code>.
<td valign="top"><em>Deprecated.</em> Use resource collections.
The name of a file. Each line of The name of a file. Each line of
this file is taken to be an include pattern.</td> this file is taken to be an include pattern.</td>
<td valign="top" align="center">No</td> <td valign="top" align="center">No</td>
</tr> </tr>
<tr> <tr>
<td valign="top">excludes</td> <td valign="top">excludes</td>
<td valign="top"><em>Deprecated.</em> Use <code>&lt;fileset&gt;</code>.
<td valign="top"><em>Deprecated.</em> Use resource collections.
Comma- or space-separated list of patterns of Comma- or space-separated list of patterns of
files that must be excluded from the deletion list. files that must be excluded from the deletion list.
All files are relative to the directory specified in <code>dir</code>. 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>
<tr> <tr>
<td valign="top">excludesfile</td> <td valign="top">excludesfile</td>
<td valign="top"><em>Deprecated.</em> Use <code>&lt;fileset&gt;</code>.
<td valign="top"><em>Deprecated.</em> Use resource collections.
The name of a file. Each line of The name of a file. Each line of
this file is taken to be an exclude pattern</td> this file is taken to be an exclude pattern</td>
<td valign="top" align="center">No</td> <td valign="top" align="center">No</td>
</tr> </tr>
<tr> <tr>
<td valign="top">defaultexcludes</td> <td valign="top">defaultexcludes</td>
<td valign="top"><em>Deprecated.</em> Use <code>&lt;fileset&gt;</code>.
<td valign="top"><em>Deprecated.</em> Use resource collections.
Whether to use <a href="../dirtasks.html#defaultexcludes"> Whether to use <a href="../dirtasks.html#defaultexcludes">
default excludes.</a></td> default excludes.</a></td>
<td align="center" valign="top">No, default &quot;true&quot;</td> <td align="center" valign="top">No, default &quot;true&quot;</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 failure to delete a file, this causes the jvm to attempt
to delete the file when the jvm process is terminating. to delete the file when the jvm process is terminating.
<em>Since Ant 1.6.2</em></td> <em>Since Ant 1.6.2</em></td>
<td align="center" valign="top">No, default &quot;false&quot;.</td>
<td align="center" valign="top">No, default &quot;false&quot;</td>
</tr> </tr>
</table> </table>
<h3>Examples</h3> <h3>Examples</h3>
@@ -158,7 +161,7 @@ and any subdirectories.</p>
</pre> </pre>
<p>deletes all files and subdirectories of <code>build</code>, without <p>deletes all files and subdirectories of <code>build</code>, without
<code>build</code> itself.</p> <code>build</code> itself.</p>
<hr><p align="center">Copyright &copy; 2000-2002,2004-2005 The Apache Software Foundation.
<hr><p align="center">Copyright &copy; 2000-2002, 2004-2005 The Apache Software Foundation.
All rights Reserved.</p> All rights Reserved.</p>


</body> </body>


+ 90
- 10
src/etc/testcases/taskdefs/delete.xml View File

@@ -2,27 +2,107 @@


<project name="delete-test" basedir="." default="test1"> <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"> <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> </copy>
</target> </target>


<target name="test1">
<delete />
</target>

<target name="test2" depends="init"> <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>


<target name="test4" depends="init"> <target name="test4" depends="init">
<delete dir="taskdefs.tmp"/>
<delete dir="${dir}" />
<expectabsent />
</target> </target>


<target name="cleanup">
<delete dir="taskdefs.tmp" />
<target name="test5" depends="init">
<delete dir="${dir}" includes="**" />
<expectdirsonly />
</target> </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> </project>

+ 44
- 33
src/main/org/apache/tools/ant/taskdefs/Delete.java View File

@@ -19,12 +19,21 @@ package org.apache.tools.ant.taskdefs;


import java.io.File; import java.io.File;
import java.util.Vector; import java.util.Vector;
import java.util.Iterator;

import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.condition.Os; 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.FileSet;
import org.apache.tools.ant.types.PatternSet; 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.AndSelector;
import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
import org.apache.tools.ant.types.selectors.ContainsSelector; import org.apache.tools.ant.types.selectors.ContainsSelector;
@@ -70,6 +79,7 @@ public class Delete extends MatchingTask {
private boolean quiet = false; private boolean quiet = false;
private boolean failonerror = true; private boolean failonerror = true;
private boolean deleteOnExit = false; private boolean deleteOnExit = false;
private Vector rcs = new Vector();


/** /**
* Set the name of a single file to be removed. * Set the name of a single file to be removed.
@@ -87,6 +97,7 @@ public class Delete extends MatchingTask {
*/ */
public void setDir(File dir) { public void setDir(File dir) {
this.dir = dir; this.dir = dir;
getImplicitFileSet().setDir(dir);
} }


/** /**
@@ -155,6 +166,14 @@ public class Delete extends MatchingTask {
filesets.addElement(set); 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 * add a name entry on the include list
* @return a NameEntry object to be configured * @return a NameEntry object to be configured
@@ -442,9 +461,9 @@ public class Delete extends MatchingTask {
+ "Use a nested fileset element instead."); + "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 " 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."); + "must be set.");
} }


@@ -453,7 +472,6 @@ public class Delete extends MatchingTask {
+ "set to true", getLocation()); + "set to true", getLocation());
} }



// delete the single file // delete the single file
if (file != null) { if (file != null) {
if (file.exists()) { if (file.exists()) {
@@ -497,39 +515,32 @@ public class Delete extends MatchingTask {
} }
removeDir(dir); removeDir(dir);
} }
// delete the files in the filesets
Path p = new Path(getProject());
p.addAll(rcs);
for (int i = 0; i < filesets.size(); i++) { 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) { 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); quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
} }
} }


+ 71
- 0
src/main/org/apache/tools/ant/types/resources/BCFileSet.java View File

@@ -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();
}

}

+ 48
- 0
src/main/org/apache/tools/ant/types/resources/comparators/FileSystem.java View File

@@ -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()));
}

}

+ 21
- 0
src/main/org/apache/tools/ant/util/FileUtils.java View File

@@ -1341,6 +1341,27 @@ public class FileUtils {
return (p.startsWith(l)) ? p.substring(l.length()) : p; 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 * Constructs a <code>file:</code> URI that represents the
* external form of the given pathname. * external form of the given pathname.


+ 16
- 1
src/testcases/org/apache/tools/ant/taskdefs/DeleteTest.java View File

@@ -42,8 +42,23 @@ public class DeleteTest extends BuildFileTest {
public void test2() { public void test2() {
executeTarget("test2"); executeTarget("test2");
} }
//where oh where has my test case 3 gone?
public void test4() { public void test4() {
executeTarget("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");
}
} }

Loading…
Cancel
Save