diff --git a/WHATSNEW b/WHATSNEW index 292a3cb2f..3f611c611 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -404,6 +404,12 @@ Other changes: * now supports selectors for remote directories as well. Bugzilla Report 44726. + * In some cases Ant fails to rename files if the source or target + file has just recently been closed on Windows. It will now try to + delete the offending file once again after giving the Java VM time + to really close the file. + Bugzilla Report 45960. + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java index 6cc2b16f0..76cafafd7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Delete.java +++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java @@ -57,6 +57,7 @@ import org.apache.tools.ant.types.selectors.FilenameSelector; 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; import org.apache.tools.ant.util.SymbolicLinkUtils; /** @@ -74,7 +75,6 @@ import org.apache.tools.ant.util.SymbolicLinkUtils; * @ant.task category="filesystem" */ public class Delete extends MatchingTask { - private static final int DELETE_RETRY_SLEEP_MILLIS = 10; private static final ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem()); private static final ResourceSelector EXISTS = new Exists(); @@ -114,6 +114,7 @@ public class Delete extends MatchingTask { private boolean failonerror = true; private boolean deleteOnExit = false; private Resources rcs = null; + private static FileUtils FILE_UTILS = FileUtils.getFileUtils(); private static SymbolicLinkUtils SYMLINK_UTILS = SymbolicLinkUtils.getSymbolicLinkUtils(); @@ -659,16 +660,7 @@ public class Delete extends MatchingTask { * wait a little and try again. */ private boolean delete(File f) { - if (!f.delete()) { - if (Os.isFamily("windows")) { - System.gc(); - } - try { - Thread.sleep(DELETE_RETRY_SLEEP_MILLIS); - } catch (InterruptedException ex) { - // Ignore Exception - } - if (!f.delete()) { + if (!FILE_UTILS.tryHardToDelete(f)) { if (deleteOnExit) { int level = quiet ? Project.MSG_VERBOSE : Project.MSG_INFO; log("Failed to delete " + f + ", calling deleteOnExit." @@ -678,7 +670,6 @@ public class Delete extends MatchingTask { return true; } return false; - } } return true; } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index abb7f2061..b3477afe0 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -54,6 +54,7 @@ import org.apache.tools.ant.types.resources.FileResource; * */ public class FileUtils { + private static final int DELETE_RETRY_SLEEP_MILLIS = 10; private static final int EXPAND_SPACE = 50; private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); @@ -1229,7 +1230,7 @@ public class FileUtils { System.err.println("Rename of " + from + " to " + to + " is a no-op."); return; } - if (to.exists() && !(from.equals(to.getCanonicalFile()) || to.delete())) { + if (to.exists() && !(from.equals(to.getCanonicalFile()) || tryHardToDelete(to))) { throw new IOException("Failed to delete " + to + " while trying to rename " + from); } File parent = to.getParentFile(); @@ -1239,7 +1240,7 @@ public class FileUtils { } if (!from.renameTo(to)) { copyFile(from, to); - if (!from.delete()) { + if (!tryHardToDelete(from)) { throw new IOException("Failed to delete " + from + " while trying to rename it."); } } @@ -1437,6 +1438,30 @@ public class FileUtils { } } + /** + * Accommodate Windows bug encountered in both Sun and IBM JDKs. + * Others possible. If the delete does not work, call System.gc(), + * wait a little and try again. + * + * @return whether deletion was successful + * @since Ant 1.8.0 + */ + public boolean tryHardToDelete(File f) { + if (!f.delete()) { + if (ON_WINDOWS) { + System.gc(); + } + try { + Thread.sleep(DELETE_RETRY_SLEEP_MILLIS); + } catch (InterruptedException ex) { + // Ignore Exception + } + return f.delete(); + } + return true; + } + + /** * Calculates the relative path between two files. *