From d8a41c88bee05a818356bf6f4f16f31ccc43940e Mon Sep 17 00:00:00 2001
From: Matthew Jason Benson
Date: Thu, 15 Sep 2005 15:39:15 +0000
Subject: [PATCH] dependset + resource collection support
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@289262 13f79535-47bb-0310-9956-ffa450edef68
---
docs/manual/CoreTasks/dependset.html | 65 ++--
src/etc/testcases/taskdefs/dependset.xml | 58 +++-
.../apache/tools/ant/taskdefs/DependSet.java | 293 ++++++++----------
.../tools/ant/taskdefs/DependSetTest.java | 9 +
4 files changed, 226 insertions(+), 199 deletions(-)
diff --git a/docs/manual/CoreTasks/dependset.html b/docs/manual/CoreTasks/dependset.html
index 4e98bdd0d..96b467548 100644
--- a/docs/manual/CoreTasks/dependset.html
+++ b/docs/manual/CoreTasks/dependset.html
@@ -10,21 +10,20 @@
DependSet
-A task to manage arbitrary dependencies between files.
+A task to manage arbitrary dependencies between resources.
Description
-The dependset task compares a set of source files with a set of target
-files. If any of the source files is more recent than any of
-the target files, all of the target files are removed.
+The dependset task compares a set of sources with a set of target
+files. If any of the sources has been modified more recently than
+any of the target files, all of the target files are removed.
-Source files and target files are specified via nested FileSets and/or nested FileLists. Arbitrarily many
-source and target filesets/filelists may be specified, but at
-least one filelist/fileset is required for both sources and targets.
+Sources and target files are specified via nested
+Resource Collections;
+sources can be resources of any type, while targets are restricted to files
+only. At least one set of sources and one set of targets is required.
Use a FileSet when you want to use wildcard include or exclude
@@ -50,50 +49,64 @@ well as other stylesheets imported by the main stylesheet.
Parameters Specified as Nested Elements
+sources
+
+The <sources>
element is a
+Union into which
+arbitrary resource collections can be nested. Since Ant 1.7
+
+
srcfileset
-The nested srcfileset
element specifies a <srcfileset> element specifies a FileSet. All files included in
this fileset will be compared against all files included in all of the
-targetfileset
filesets and targetfilelist
-filelists. Multiple srcfileset
filesets may be specified.
+<targetfileset>
filesets and <targetfilelist>
+filelists. Multiple <srcfileset>
filesets may be specified.
srcfilelist
-The nested srcfilelist
element specifies a <srcfilelist> element specifies a FileList. All files included in
this filelist will be compared against all files included in all of the
-targetfileset
filesets and targetfilelist
-filelists. Multiple srcfilelist
filelists may be specified.
+<targetfileset>
filesets and <targetfilelist>
+filelists. Multiple <srcfilelist>
filelists may be specified.
+
+
+targets
+
+The <targets>
element is a
+Path and thus can
+include any filesystem-based resource. Since Ant 1.7
targetfileset
-The nested targetfileset
element specifies a <targetfileset> element specifies a FileSet. All files included in
this fileset will be compared against all files included in all of the
-srcfileset
filesets and sourcefilelist
+<srcfileset>
filesets and <sourcefilelist>
filelists, and if any are older, they are all deleted.
-Multiple targetfileset
filesets may be specified.
+Multiple <targetfileset>
filesets may be specified.
targetfilelist
-The nested targetfilelist
element specifies a <targetfilelist> element specifies a FileList. All files included in
this filelist will be compared against all files included in all of the
-srcfileset
filesets and sourcefilelist
+<srcfileset>
filesets and <sourcefilelist>
filelists, and if any are older, they are all deleted.
-Multiple targetfilelist
filelists may be specified.
+Multiple <targetfilelist>
filelists may be specified.
Examples
-
+
<dependset>
<srcfilelist
dir = "${dtd.dir}"
@@ -121,13 +134,13 @@ will be removed if any are out-of-date with respect to:
-If any of the source files in the above example does not exist, all
-target files will also be removed. To ignore missing source files instead,
-use filesets instead of filelists for the source files.
+If any of the sources in the above example does not exist, all
+target files will also be removed. To ignore missing sources instead,
+use filesets instead of filelists for the sources.
-Copyright © 2001,2004-2005 The Apache Software Foundation.
+
Copyright © 2001, 2004-2005 The Apache Software Foundation.
All rights
Reserved.
diff --git a/src/etc/testcases/taskdefs/dependset.xml b/src/etc/testcases/taskdefs/dependset.xml
index a650d3808..9b936bc12 100644
--- a/src/etc/testcases/taskdefs/dependset.xml
+++ b/src/etc/testcases/taskdefs/dependset.xml
@@ -40,7 +40,63 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/DependSet.java b/src/main/org/apache/tools/ant/taskdefs/DependSet.java
index cf57c82ae..a69d63794 100644
--- a/src/main/org/apache/tools/ant/taskdefs/DependSet.java
+++ b/src/main/org/apache/tools/ant/taskdefs/DependSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2005 The Apache Software Foundation
+ * Copyright 2001-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.
@@ -17,15 +17,24 @@
package org.apache.tools.ant.taskdefs;
-import java.io.File;
-import java.util.Date;
-import java.util.Enumeration;
-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.types.FileList;
+import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.FileList;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.TimeComparison;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.Sort;
+import org.apache.tools.ant.types.resources.Union;
+import org.apache.tools.ant.types.resources.Restrict;
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.selectors.Not;
+import org.apache.tools.ant.types.resources.selectors.Exists;
+import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
+import org.apache.tools.ant.types.resources.comparators.Reverse;
+import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
import org.apache.tools.ant.util.FileUtils;
/**
@@ -39,36 +48,32 @@ import org.apache.tools.ant.util.FileUtils;
*
* nested arguments:
*
+ * - sources (resource union describing the source resources to examine)
*
- srcfileset (fileset describing the source files to examine)
*
- srcfilelist (filelist describing the source files to examine)
+ *
- targets (path describing the target files to examine)
*
- targetfileset (fileset describing the target files to examine)
*
- targetfilelist (filelist describing the target files to examine)
*
- * At least one instance of either a fileset or filelist for both source and
- * target are required.
+ * At least one of both source and target entities is required.
*
- * This task will examine each of the source files against each of the target
- * files. If any target files are out of date with respect to any of the source
- * files, all targets are removed. If any files named in a (src or target)
- * filelist do not exist, all targets are removed.
+ * This task will examine each of the sources against each of the target files. If
+ * any target files are out of date with respect to any of the sources, all targets
+ * are removed. If any sources or targets do not exist, all targets are removed.
* Hint: If missing files should be ignored, specify them as include patterns
* in filesets, rather than using filelists.
*
- * This task attempts to optimize speed of dependency checking. It will stop
- * after the first out of date file is found and remove all targets, rather
- * than exhaustively checking every source vs target combination unnecessarily.
+ * This task attempts to optimize speed of dependency checking
+ * by comparing only the dates of the oldest target file and the newest source.
*
* Example uses:
*
-
- * Record the fact that an XML file must be up to date
- * with respect to its XSD (Schema file), even though the XML file
- * itself includes no reference to its XSD.
+ * Record the fact that an XML file must be up to date with respect to its XSD
+ * (Schema file), even though the XML file itself includes no reference to its XSD.
*
-
- * Record the fact that an XSL stylesheet includes other
- * sub-stylesheets
+ * Record the fact that an XSL stylesheet includes other sub-stylesheets
*
-
- * Record the fact that java files must be recompiled if the ant build
- * file changes
+ * Record the fact that java files must be recompiled if the ant build file changes
*
*
* @ant.task category="filesystem"
@@ -76,25 +81,53 @@ import org.apache.tools.ant.util.FileUtils;
*/
public class DependSet extends MatchingTask {
- private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+ private static final ResourceSelector NOT_EXISTS = new Not(new Exists());
+ private static final ResourceComparator DATE_ASC
+ = new org.apache.tools.ant.types.resources.comparators.Date();
+ private static final ResourceComparator DATE_DESC = new Reverse(DATE_ASC);
+
+ private static class NonExistent extends Restrict {
+ private NonExistent(ResourceCollection rc) {
+ super.add(rc);
+ super.add(NOT_EXISTS);
+ }
+ }
+ private static class Xest extends Sort {
+ private Xest(ResourceCollection rc, ResourceComparator c) {
+ super.add(c);
+ super.add(rc);
+ }
+ }
+ private static class Oldest extends Xest {
+ private Oldest(ResourceCollection rc) {
+ super(rc, DATE_ASC);
+ }
+ }
+ private static class Newest extends Xest {
+ private Newest(ResourceCollection rc) {
+ super(rc, DATE_DESC);
+ }
+ }
- private Vector sourceFileSets = new Vector();
- private Vector sourceFileLists = new Vector();
- private Vector targetFileSets = new Vector();
- private Vector targetFileLists = new Vector();
+ private Union sources = null;
+ private Path targets = null;
/**
- * Creates a new DependSet Task.
- **/
- public DependSet() {
- } //-- DependSet
+ * Create a nested sources element.
+ * @return a Union instance.
+ */
+ public synchronized Union createSources() {
+ sources = (sources == null) ? new Union() : sources;
+ return sources;
+ }
/**
* Add a set of source files.
* @param fs the FileSet to add.
*/
public void addSrcfileset(FileSet fs) {
- sourceFileSets.addElement(fs);
+ createSources().add(fs);
}
/**
@@ -102,7 +135,16 @@ public class DependSet extends MatchingTask {
* @param fl the FileList to add.
*/
public void addSrcfilelist(FileList fl) {
- sourceFileLists.addElement(fl);
+ createSources().add(fl);
+ }
+
+ /**
+ * Create a nested targets element.
+ * @return a Union instance.
+ */
+ public synchronized Path createTargets() {
+ targets = (targets == null) ? new Path(getProject()) : targets;
+ return targets;
}
/**
@@ -110,7 +152,7 @@ public class DependSet extends MatchingTask {
* @param fs the FileSet to add.
*/
public void addTargetfileset(FileSet fs) {
- targetFileSets.addElement(fs);
+ createTargets().add(fs);
}
/**
@@ -118,158 +160,65 @@ public class DependSet extends MatchingTask {
* @param fl the FileList to add.
*/
public void addTargetfilelist(FileList fl) {
- targetFileLists.addElement(fl);
+ createTargets().add(fl);
}
/**
- * Executes the task.
+ * Execute the task.
* @throws BuildException if errors occur.
*/
public void execute() throws BuildException {
-
- if ((sourceFileSets.size() == 0) && (sourceFileLists.size() == 0)) {
- throw new BuildException("At least one or "
- + " element must be set");
+ if (sources == null) {
+ throw new BuildException(
+ "At least one set of source resources must be specified");
}
- if ((targetFileSets.size() == 0) && (targetFileLists.size() == 0)) {
- throw new BuildException("At least one or"
- + " element must be set");
+ if (targets == null) {
+ throw new BuildException(
+ "At least one set of target files must be specified");
}
- long now = (new Date()).getTime();
- /*
- We have to munge the time to allow for the filesystem time
- granularity.
- */
- now += FILE_UTILS.getFileTimestampGranularity();
-
- // Grab all the target files specified via filesets:
- Vector allTargets = new Vector();
- long oldestTargetTime = 0;
- File oldestTarget = null;
- Enumeration enumTargetSets = targetFileSets.elements();
- while (enumTargetSets.hasMoreElements()) {
-
- FileSet targetFS = (FileSet) enumTargetSets.nextElement();
- if (!targetFS.getDir(getProject()).exists()) {
- // this is the same as if it was empty, no target files found
- continue;
- }
- DirectoryScanner targetDS = targetFS.getDirectoryScanner(getProject());
- String[] targetFiles = targetDS.getIncludedFiles();
-
- for (int i = 0; i < targetFiles.length; i++) {
-
- File dest = new File(targetFS.getDir(getProject()), targetFiles[i]);
- allTargets.addElement(dest);
-
- if (dest.lastModified() > now) {
- log("Warning: " + targetFiles[i] + " modified in the future.",
- Project.MSG_WARN);
- }
- if (oldestTarget == null
- || dest.lastModified() < oldestTargetTime) {
- oldestTargetTime = dest.lastModified();
- oldestTarget = dest;
- }
- }
+ //no sources = nothing to compare; no targets = nothing to delete:
+ if (sources.size() > 0 && targets.size() > 0 && !uptodate(sources, targets)) {
+ log("Deleting all target files.", Project.MSG_VERBOSE);
+ Delete delete = new Delete();
+ delete.bindToOwner(this);
+ delete.add(targets);
+ delete.perform();
}
- // Grab all the target files specified via filelists:
- boolean upToDate = true;
- Enumeration enumTargetLists = targetFileLists.elements();
- while (enumTargetLists.hasMoreElements()) {
-
- FileList targetFL = (FileList) enumTargetLists.nextElement();
- String[] targetFiles = targetFL.getFiles(getProject());
-
- for (int i = 0; i < targetFiles.length; i++) {
+ }
- File dest = new File(targetFL.getDir(getProject()), targetFiles[i]);
- if (!dest.exists()) {
- log(targetFiles[i] + " does not exist.", Project.MSG_VERBOSE);
- upToDate = false;
- continue;
- } else {
- allTargets.addElement(dest);
- }
- if (dest.lastModified() > now) {
- log("Warning: " + targetFiles[i] + " modified in the future.",
- Project.MSG_WARN);
- }
- if (oldestTarget == null
- || dest.lastModified() < oldestTargetTime) {
- oldestTargetTime = dest.lastModified();
- oldestTarget = dest;
- }
- }
+ private boolean uptodate(ResourceCollection src, ResourceCollection target) {
+ org.apache.tools.ant.types.resources.selectors.Date datesel
+ = new org.apache.tools.ant.types.resources.selectors.Date();
+ datesel.setMillis(System.currentTimeMillis());
+ datesel.setWhen(TimeComparison.AFTER);
+ logFuture(targets, datesel);
+
+ int neTargets = new NonExistent(targets).size();
+ if (neTargets > 0) {
+ log(neTargets + " nonexistent targets", Project.MSG_VERBOSE);
+ return false;
}
- if (oldestTarget != null) {
- log(oldestTarget + " is oldest target file", Project.MSG_VERBOSE);
- } else {
- // no target files, then we cannot remove any target files and
- // skip the following tests right away
- upToDate = false;
- }
- // Check targets vs source files specified via filelists:
- if (upToDate) {
- Enumeration enumSourceLists = sourceFileLists.elements();
- while (upToDate && enumSourceLists.hasMoreElements()) {
-
- FileList sourceFL = (FileList) enumSourceLists.nextElement();
- String[] sourceFiles = sourceFL.getFiles(getProject());
+ FileResource oldestTarget = (FileResource) (new Oldest(targets).iterator().next());
+ log(oldestTarget + " is oldest target file", Project.MSG_VERBOSE);
- for (int i = 0; upToDate && i < sourceFiles.length; i++) {
- File src = new File(sourceFL.getDir(getProject()), sourceFiles[i]);
+ logFuture(sources, datesel);
- if (src.lastModified() > now) {
- log("Warning: " + sourceFiles[i]
- + " modified in the future.", Project.MSG_WARN);
- }
- if (!src.exists()) {
- log(sourceFiles[i] + " does not exist.",
- Project.MSG_VERBOSE);
- upToDate = false;
- break;
- }
- if (src.lastModified() > oldestTargetTime) {
- upToDate = false;
- log(oldestTarget + " is out of date with respect to "
- + sourceFiles[i], Project.MSG_VERBOSE);
- }
- }
- }
+ int neSources = new NonExistent(sources).size();
+ if (neSources > 0) {
+ log(neSources + " nonexistent sources", Project.MSG_VERBOSE);
+ return false;
}
- // Check targets vs source files specified via filesets:
- if (upToDate) {
- Enumeration enumSourceSets = sourceFileSets.elements();
- while (upToDate && enumSourceSets.hasMoreElements()) {
-
- FileSet sourceFS = (FileSet) enumSourceSets.nextElement();
- DirectoryScanner sourceDS = sourceFS.getDirectoryScanner(getProject());
- String[] sourceFiles = sourceDS.getIncludedFiles();
-
- for (int i = 0; upToDate && i < sourceFiles.length; i++) {
- File src = new File(sourceFS.getDir(getProject()), sourceFiles[i]);
+ Resource newestSource = (Resource) (new Newest(sources).iterator().next());
+ log(newestSource.toLongString() + " is newest source", Project.MSG_VERBOSE);
+ return oldestTarget.getLastModified() >= newestSource.getLastModified();
+ }
- if (src.lastModified() > now) {
- log("Warning: " + sourceFiles[i]
- + " modified in the future.", Project.MSG_WARN);
- }
- if (src.lastModified() > oldestTargetTime) {
- upToDate = false;
- log(oldestTarget + " is out of date with respect to "
- + sourceFiles[i], Project.MSG_VERBOSE);
- }
- }
- }
- }
- if (!upToDate) {
- log("Deleting all target files. ", Project.MSG_VERBOSE);
- for (Enumeration e = allTargets.elements(); e.hasMoreElements();) {
- File fileToRemove = (File) e.nextElement();
- log("Deleting file " + fileToRemove.getAbsolutePath(),
- Project.MSG_VERBOSE);
- fileToRemove.delete();
- }
+ private void logFuture(ResourceCollection rc, ResourceSelector rsel) {
+ Restrict r = new Restrict();
+ r.add(rsel);
+ r.add(rc);
+ for (Iterator i = r.iterator(); i.hasNext();) {
+ log("Warning: " + i.next() + " modified in the future.", Project.MSG_WARN);
}
}
}
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/DependSetTest.java b/src/testcases/org/apache/tools/ant/taskdefs/DependSetTest.java
index ab65ba4eb..29a488c76 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/DependSetTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/DependSetTest.java
@@ -57,4 +57,13 @@ public class DependSetTest extends BuildFileTest {
executeTarget("test5");
}
+ public void test6() {
+ executeTarget("test6");
+ }
+ public void test7() {
+ executeTarget("test7");
+ }
+ public void test8() {
+ executeTarget("test8");
+ }
}