This patch allows developers using DirectoryScanner to specify whether or
not a given instance should report files for which File.getCanoniacalPath()
and File.getAbsolutePath() are not equal (such as symbolic links in linux).
The default value of true, retains the existing behavior, while
DirectoryScanner ds = new DirectoryScanner();
ds.setFollowLinks(false);
changes the behavior to igore symlinks (and their analogs on other OS's).
The patch also includes a test case for this behavior change.
I have tried to follow the guidelines in ant_task_guidelines.html, but this
is the first patch I have submitted, so be alert for things I may have
missed. I'll be glad to clean up anything that isn't quite right about my
code or my submission, but it is working on my machine :).
This patch is a precursor to the symlink task I am working on which will use
this functionality.
Thanks,
Gus
Index: src/main/org/apache/tools/ant/DirectoryScanner.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/DirectoryScanner.java,v
retrieving revision 1.24
diff -u -r1.24 DirectoryScanner.java
--- src/main/org/apache/tools/ant/DirectoryScanner.java 9 Apr 2002 15:27:07
-0000 1.24
+++ src/main/org/apache/tools/ant/DirectoryScanner.java 28 Apr 2002 19:24:01
-0000
@@ -55,6 +55,7 @@
package org.apache.tools.ant;
import java.io.File;
+import java.io.IOException;
import java.util.Vector;
import java.util.StringTokenizer;
@@ -203,6 +204,13 @@
*/
protected boolean isCaseSensitive = true;
+ /**
+ * Whether or not we should traverse into something for which
+ * File.getAbsolutePath() != File.getCannonicalPath()
+ * (for example: a symbolic link in Linux)
+ */
+ protected boolean followLinks = true;
+
/** Whether or not everything tested so far has been included. */
protected boolean everythingIncluded = true;
@@ -688,6 +696,19 @@
}
/**
+ * Sets whether or not this scanner will return files or directories
+ * for which <code>File.getCannonicalPath() != File.getAbsolutePath</code>.
+ * Such files or directories are symbolic links in linux or their
+ * analog in other operating systems.
+ *
+ * @param followLinks false to ignore links true to return them (default)
+ */
+
+ public void setFollowLinks(boolean followLinks) {
+ this.followLinks = followLinks;
+ }
+
+ /**
* Sets the list of include patterns to use. All '/' and '\' characters
* are replaced by <code>File.separatorChar</code>, so the separator used
* need not match <code>File.separatorChar</code>.
@@ -873,6 +894,37 @@
*/
throw new BuildException("IO error scanning directory "
+ dir.getAbsolutePath());
+ }
+
+ if (!followLinks) {
+ Vector noLinks = new Vector();
+ File tester, tempdir;
+ String can, abs;
+
+ try {
+ // We could be running underneath a symlink so...
+ tempdir = new File(dir.getCanonicalPath());
+
+ // Now we can successfully distingiush links from non-links
+ for (int i = 0; i < newfiles.length; i++) {
+ tester = new File(tempdir, newfiles[i]);
+ can = tester.getCanonicalPath();
+ abs = tester.getAbsolutePath();
+
+ // This is the actual test for a link
+ if (can.equals(abs)) {
+ noLinks.add(newfiles[i]);
+ }
+ }
+ } catch (IOException ioe) {
+ throw new BuildException("IOException caught while checking "+
+ "for links, couldn't get " +
+ "cannonical path!");
+ }
+ newfiles = new String[noLinks.size()];
+ for (int i=0; i<noLinks.size(); i++){
+ newfiles[i] = (String) noLinks.elementAt(i);
+ }
}
for (int i = 0; i < newfiles.length; i++) {
Index: src/testcases/org/apache/tools/ant/DirectoryScannerTest.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/testcases/org/apache/tools/ant/DirectoryScannerTest.java,v
retrieving revision 1.4
diff -u -r1.4 DirectoryScannerTest.java
--- src/testcases/org/apache/tools/ant/DirectoryScannerTest.java 10 Jan
2002 10:13:11 -0000 1.4
+++ src/testcases/org/apache/tools/ant/DirectoryScannerTest.java 28 Apr
2002 19:24:05 -0000
@@ -57,6 +57,7 @@
import junit.framework.TestCase;
import junit.framework.AssertionFailedError;
import java.io.File;
+import java.io.IOException;
/**
* JUnit 3 testcases for org.apache.tools.ant.DirectoryScanner
@@ -66,6 +67,128 @@
public class DirectoryScannerTest extends TestCase {
public DirectoryScannerTest(String name) {super(name);}
+
+
+ // keep track of what operating systems are supported here.
+ private boolean supportedOSForTestSetFollowLinks(String os)
+ {
+ String[] sups = {"Linux"};
+ boolean result = false;
+
+ for (int i=0; i<sups.length; i++) {
+ result = (result || os.equals(sups[i]));
+ }
+ return result;
+ }
+
+ /**
+ * Test case for setFollowLinks() and associated funtionality.
+ * Only supports test on linux, at the moment because Java has
+ * no real notion of symlinks built in, so an os-specfic call
+ * to Runtime.exec() must be made to create a link to test against.
+ */
+
+ public void testSetFollowLinks() {
+ String os = System.getProperty("os.name");
+
+ if (supportedOSForTestSetFollowLinks(os)) {
+
+ // add additional if() statements to create a link under
+ // additional platforms. (or expand the condition of this
+ // if() for platforms that use the same syntax.
+ try {
+ if (os.equals("Linux")) {
+ Runtime rt = Runtime.getRuntime();
+ try {
+ rt.exec("ln -s ant " +
+ "src/main/org/apache/tools/ThisIsALink");
+
+ // give ourselves some time for the system call
+ // to execute... tweak if you have a really over
+ // loaded system.
+ Thread.sleep(1000);
+ } catch (IOException ioe) {
+ assertTrue("IOException making link", false);
+ } catch (InterruptedException ie) {
+ assertTrue("InterruptedException after making link",
+ false);
+ }
+
+ }
+
+ File dir = new File("src/main/org/apache/tools");
+ DirectoryScanner ds = new DirectoryScanner();
+
+ // followLinks should be true by default, but if this ever
+ // changes we will need this line.
+ ds.setFollowLinks(true);
+
+ ds.setBasedir(dir);
+ ds.setExcludes(new String[] {"ant/**"});
+ ds.scan();
+
+ boolean haveZipPackage = false;
+ boolean haveTaskdefsPackage = false;
+
+ String[] included = ds.getIncludedDirectories();
+ for (int i=0; i<included.length; i++) {
+ if (included[i].equals("zip")) {
+ haveZipPackage = true;
+ } else if (included[i].equals("ThisIsALink"+File.separator+
+ "taskdefs")) {
+ haveTaskdefsPackage = true;
+ }
+ }
+
+ // if we followed the symlink we just made we should
+ // bypass the excludes.
+
+ assertTrue("(1) zip package included", haveZipPackage);
+ assertTrue("(1) taskdefs package included",
+ haveTaskdefsPackage);
+
+
+ ds = new DirectoryScanner();
+ ds.setFollowLinks(false);
+
+ ds.setBasedir(dir);
+ ds.setExcludes(new String[] {"ant/**"});
+ ds.scan();
+
+ haveZipPackage = false;
+ haveTaskdefsPackage = false;
+ included = ds.getIncludedDirectories();
+ for (int i=0; i<included.length; i++) {
+ if (included[i].equals("zip")) {
+ haveZipPackage = true;
+ } else if (included[i].equals("ThisIsALink"+File.separator+
+ "taskdefs")) {
+ haveTaskdefsPackage = true;
+ }
+ }
+ assertTrue("(2) zip package included", haveZipPackage);
+ assertTrue("(2) taskdefs package not included",
+ !haveTaskdefsPackage);
+
+ } finally {
+ // add additional if statments to clean up the link created
+ // for each supported platform.
+
+ if (os.equals("Linux")) {
+ Runtime rt = Runtime.getRuntime();
+ try {
+ rt.exec("rm -rf
src/main/org/apache/tools/ThisIsALink");
+ } catch (IOException ioe) {
+ assertTrue("IOException clearing link", false);
+ }
+ }
+ }
+ }else {
+ System.out.println("Warning: DirectoryScaner.setFollowLinks "+
+ "not tested. Test for this functionality "+
+ "doesn't support this Operating System");
+ }
+ }
/**
* Test inspired by Bug#1415.
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>