ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bode...@apache.org
Subject svn commit: r693071 - in /ant/core/trunk: ./ src/etc/testcases/taskdefs/optional/unix/ src/main/org/apache/tools/ant/taskdefs/ src/main/org/apache/tools/ant/util/ src/tests/antunit/taskdefs/ src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/
Date Mon, 08 Sep 2008 12:23:55 GMT
Author: bodewig
Date: Mon Sep  8 05:23:54 2008
New Revision: 693071

URL: http://svn.apache.org/viewvc?rev=693071&view=rev
Log:
delete broken symbolic links.  PR 41285

Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/src/etc/testcases/taskdefs/optional/unix/symlink.xml
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Delete.java
    ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java
    ant/core/trunk/src/tests/antunit/taskdefs/delete-test.xml
    ant/core/trunk/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java

Modified: ant/core/trunk/WHATSNEW
URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Mon Sep  8 05:23:54 2008
@@ -204,6 +204,9 @@
    the link's target.
    Bugzilla Report 41525.
 
+ * <delete file="..."> failed to delete broken symbolic links.
+   Bugzilla Report 41285.
+
 Other changes:
 --------------
 

Modified: ant/core/trunk/src/etc/testcases/taskdefs/optional/unix/symlink.xml
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/etc/testcases/taskdefs/optional/unix/symlink.xml?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/src/etc/testcases/taskdefs/optional/unix/symlink.xml (original)
+++ ant/core/trunk/src/etc/testcases/taskdefs/optional/unix/symlink.xml Mon Sep  8 05:23:54
2008
@@ -54,8 +54,8 @@
   </target>
 
   <target name="all"
-	      depends="setup, test-single, test-delete, test-record, test-recreate, teardown"/>
-	
+              depends="setup, test-single, test-delete, test-record, test-recreate, teardown"/>
+        
   <!-- test for action = single -->
   <!-- 
     Creates:
@@ -334,6 +334,22 @@
   </target>
 
 
+  <!-- actually tests the symlink methods in FileUtils, but this
+       testfixture already has all the necessary envirnment in place
+       -->
+  <target name="test-fileutils" depends="setup">
+      <mkdir dir="${tdir}/dir1"/>
+      <mkdir dir="${tdir}/dir2"/>
+      <touch file="${tdir}/file1"/>
+      <touch file="${tdir}/file2"/>
+      <symlink link="${tdir}/dir.there" resource="${tdir}/dir1"/>
+      <symlink link="${tdir}/dir.notthere" resource="${tdir}/dir2"/>
+      <symlink link="${tdir}/file.there" resource="${tdir}/file1"/>
+      <symlink link="${tdir}/file.notthere" resource="${tdir}/file2"/>
+      <delete dir="${tdir}/dir2"/>
+      <delete file="${tdir}/file2"/>
+  </target>
+
 <!-- CALL THIS to clean things up afterwards -->
 
   <target name="teardown">

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Delete.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Delete.java?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Delete.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Delete.java Mon Sep  8 05:23:54
2008
@@ -57,6 +57,7 @@
 import org.apache.tools.ant.types.selectors.MajoritySelector;
 import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
 import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Deletes a file or directory, or set of files defined by a fileset.
@@ -112,6 +113,7 @@
     private boolean failonerror = true;
     private boolean deleteOnExit = false;
     private Resources rcs = null;
+    private static FileUtils FILE_UTILS = FileUtils.getFileUtils();
     // CheckStyle:VisibilityModifier ON
 
     /**
@@ -523,6 +525,13 @@
                         handle("Unable to delete file " + file.getAbsolutePath());
                     }
                 }
+            } else if (isDanglingSymlink(file)) {
+                log("Trying to delete file " + file.getAbsolutePath()
+                    + " which looks like a broken symlink.",
+                    quiet ? Project.MSG_VERBOSE : verbosity);
+                if (!delete(file)) {
+                    handle("Unable to delete file " + file.getAbsolutePath());
+                }
             } else {
                 log("Could not find file " + file.getAbsolutePath()
                     + " to delete.", quiet ? Project.MSG_VERBOSE : verbosity);
@@ -530,8 +539,9 @@
         }
 
         // delete the directory
-        if (dir != null && dir.exists() && dir.isDirectory()
+        if (dir != null
             && !usedMatchingTask) {
+            if (dir.exists() && dir.isDirectory()) {
             /*
                If verbosity is MSG_VERBOSE, that mean we are doing
                regular logging (backwards as that sounds).  In that
@@ -543,6 +553,15 @@
                 log("Deleting directory " + dir.getAbsolutePath());
             }
             removeDir(dir);
+            } else if (isDanglingSymlink(dir)) {
+                log("Trying to delete directory " + dir.getAbsolutePath()
+                    + " which looks like a broken symlink.",
+                    quiet ? Project.MSG_VERBOSE : verbosity);
+                if (!delete(dir)) {
+                    handle("Unable to delete directory "
+                           + dir.getAbsolutePath());
+                }
+            }
         }
         Resources resourcesToDelete = new Resources();
         resourcesToDelete.setProject(getProject());
@@ -739,4 +758,16 @@
             }
         }
     }
+
+    private boolean isDanglingSymlink(File f) {
+        try {
+            return FILE_UTILS.isDanglingSymbolicLink(f.getParentFile(),
+                                                     f.getName());
+        } catch (java.io.IOException e) {
+            log("Error while trying to detect " + f.getAbsolutePath()
+                + " as broken symbolic link. " + e.getMessage(),
+                quiet ? Project.MSG_VERBOSE : verbosity);
+            return false;
+        }
+    }
 }

Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java Mon Sep  8 05:23:54 2008
@@ -1052,6 +1052,47 @@
     }
 
     /**
+     * Checks whether a given file is a broken symbolic link.
+     *
+     * <p>It doesn't really test for symbolic links but whether Java
+     * reports that the File doesn't exist but its parent's child list
+     * contains it--this may lead to false positives on some
+     * platforms.</p>
+     *
+     * <p>Note that #isSymbolicLink returns false if this method
+     * returns true since Java won't produce a canonical name
+     * different from the abolute one if the link is broken.</p>
+     *
+     * @param parent the parent directory of the file to test
+     * @param name the name of the file to test.
+     *
+     * @return true if the file is a broken symbolic link.
+     * @throws IOException on error.
+     * @since Ant 1.8.0
+     */
+    public boolean isDanglingSymbolicLink(File parent, String name) 
+        throws IOException {
+        File f = null;
+        if (parent == null) {
+            f = new File(name);
+            parent = f.getParentFile();
+            name = f.getName();
+        } else {
+            f = new File(parent, name);
+        }
+        if (!f.exists()) {
+            final String localName = f.getName();
+            String[] c = parent.list(new FilenameFilter() {
+                    public boolean accept(File d, String n) {
+                        return localName.equals(n);
+                    }
+                });
+            return c != null && c.length > 0;
+        }
+        return false;
+    }
+
+    /**
      * Removes a leading path from a second path.
      *
      * @param leading The leading path, must not be null, must be absolute.

Modified: ant/core/trunk/src/tests/antunit/taskdefs/delete-test.xml
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/tests/antunit/taskdefs/delete-test.xml?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/src/tests/antunit/taskdefs/delete-test.xml (original)
+++ ant/core/trunk/src/tests/antunit/taskdefs/delete-test.xml Mon Sep  8 05:23:54 2008
@@ -67,4 +67,31 @@
 
   </target>
 
+  <target name="checkOs">
+    <condition property="unix">
+      <os family="unix" />
+    </condition>
+  </target>
+
+  <target name="testDanglingSymlinkInDir" if="unix" depends="checkOs,init">
+    <touch file="${output}/foo"/>
+    <symlink link="${existing.dir}/link"
+             resource="${output}/foo"/>
+    <delete file="${output}/foo"/>
+    <delete dir="${existing.dir}"/>
+    <au:assertFileDoesntExist file="${existing.dir}" />
+  </target>
+
+  <target name="testDanglingSymlink" if="unix" depends="checkOs,init">
+    <touch file="${output}/foo"/>
+    <symlink link="${output}/link"
+             resource="${output}/foo"/>
+    <delete file="${output}/foo"/>
+    <delete file="${output}/link"/>
+
+    <!-- since File.exists returns false for dangling links, recreate
+         the file so that assertFileDoesntExist can actually work -->
+    <touch file="${output}/foo"/>
+    <au:assertFileDoesntExist file="${output}/link" />
+  </target>
 </project>

Modified: ant/core/trunk/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java?rev=693071&r1=693070&r2=693071&view=diff
==============================================================================
--- ant/core/trunk/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
(original)
+++ ant/core/trunk/src/tests/junit/org/apache/tools/ant/taskdefs/optional/unix/SymlinkTest.java
Mon Sep  8 05:23:54 2008
@@ -33,6 +33,7 @@
 
 import org.apache.tools.ant.BuildFileTest;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Test cases for the Symlink task. Link creation, link deletion, recording
@@ -181,6 +182,103 @@
         }
     }
 
+    public void testFileUtilsMethods() throws Exception {
+        if (supportsSymlinks) {
+            executeTarget("test-fileutils");
+            FileUtils fu = FileUtils.getFileUtils();
+
+            java.io.File f = getProject().resolveFile("test-working/file1");
+            assertTrue(f.exists());
+            assertFalse(f.isDirectory());
+            assertTrue(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+            f = getProject().resolveFile("test-working/dir1");
+            assertTrue(f.exists());
+            assertTrue(f.isDirectory());
+            assertFalse(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+            f = getProject().resolveFile("test-working/file2");
+            assertFalse(f.exists());
+            assertFalse(f.isDirectory());
+            assertFalse(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+            f = getProject().resolveFile("test-working/dir2");
+            assertFalse(f.exists());
+            assertFalse(f.isDirectory());
+            assertFalse(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+
+            f = getProject().resolveFile("test-working/file.there");
+            assertTrue(f.exists());
+            assertFalse(f.isDirectory());
+            assertTrue(f.isFile());
+            assertTrue(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertTrue(fu.isSymbolicLink(f.getParentFile(),
+                                         f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+            f = getProject().resolveFile("test-working/dir.there");
+            assertTrue(f.exists());
+            assertTrue(f.isDirectory());
+            assertFalse(f.isFile());
+            assertTrue(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertTrue(fu.isSymbolicLink(f.getParentFile(),
+                                         f.getName()));
+            assertFalse(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                  f.getName()));
+
+            f = getProject().resolveFile("test-working/file.notthere");
+            assertFalse(f.exists());
+            assertFalse(f.isDirectory());
+            assertFalse(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertTrue(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertTrue(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                 f.getName()));
+
+            f = getProject().resolveFile("test-working/dir.notthere");
+            assertFalse(f.exists());
+            assertFalse(f.isDirectory());
+            assertFalse(f.isFile());
+            assertFalse(fu.isSymbolicLink(null, f.getAbsolutePath()));
+            assertFalse(fu.isSymbolicLink(f.getParentFile(),
+                                          f.getName()));
+            assertTrue(fu.isDanglingSymbolicLink(null, f.getAbsolutePath()));
+            assertTrue(fu.isDanglingSymbolicLink(f.getParentFile(),
+                                                 f.getName()));
+
+        }
+    }
+
     public void tearDown() {
         if (supportsSymlinks) {
             executeTarget("teardown");



Mime
View raw message