Author: bodewig
Date: Tue May 11 09:13:27 2010
New Revision: 943056
URL: http://svn.apache.org/viewvc?rev=943056&view=rev
Log:
Make <move> behave consistently for read-only destinations. PR 49261
Modified:
ant/core/trunk/WHATSNEW
ant/core/trunk/docs/manual/CoreTasks/move.html
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Move.java
ant/core/trunk/src/tests/antunit/taskdefs/move-test.xml
Modified: ant/core/trunk/WHATSNEW
URL:
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=943056&r1=943055&r2=943056&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Tue May 11 09:13:27 2010
@@ -4,13 +4,13 @@ Changes from Ant 1.8.1 TO current SVN ve
Changes that could break older environments:
-------------------------------------------
- * Prior to Ant 1.8.0 the <copy> task would overwrite read-only
- destination files. Starting with 1.8.0 it would only do so if
- under special circumstances. Ant 1.8.2 now consistently won't
- replace a read-only file by default. The same is true for a number
- of other tasks.
- The <copy> task now has a new force attribute that can be used to
- make the task overwrite read-only destinations.
+ * Prior to Ant 1.8.0 the <copy> task and several other tasks would
+ overwrite read-only destination files. Starting with 1.8.0 it
+ would only do so if under special circumstances. Ant 1.8.2 now
+ consistently won't replace a read-only file by default. The same is
+ true for a number of other tasks.
+ The <copy> and <move> task now have a new force attribute that can
+ be used to make the task overwrite read-only destinations.
Bugzilla Report 49261.
Fixed bugs:
Modified: ant/core/trunk/docs/manual/CoreTasks/move.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/move.html?rev=943056&r1=943055&r2=943056&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/move.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/move.html Tue May 11 09:13:27 2010
@@ -86,6 +86,12 @@ there is a directory by the same name in
<td valign="top" align="center">No</td>
</tr>
<tr>
+ <td valign="top">force</td>
+ <td valign="top">Overwrite read-only destination
+ files. <em>since Ant 1.8.2</em></td>
+ <td valign="top" align="center">No; defaults to false.</td>
+ </tr>
+ <tr>
<td valign="top">filtering</td>
<td valign="top">indicates whether token filtering should take place during
the move. See the <a href="filter.html">filter</a> task for a
description of
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java?rev=943056&r1=943055&r2=943056&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java Tue May 11
09:13:27 2010
@@ -241,6 +241,15 @@ public class Copy extends Task {
}
/**
+ * Whether read-only destinations will be overwritten.
+ *
+ * @since Ant 1.8.2
+ */
+ public boolean getForce() {
+ return force;
+ }
+
+ /**
* Set whether files copied from directory trees will be "flattened"
* into a single directory. If there are multiple files with
* the same name in the source directory tree, only the first
@@ -856,7 +865,7 @@ public class Copy extends Task {
preserveLastModified,
/* append: */ false, inputEncoding,
outputEncoding, getProject(),
- force);
+ getForce());
} catch (IOException ioe) {
String msg = "Failed to copy " + fromFile + " to " +
toFile
+ " due to " + getDueTo(ioe);
@@ -947,7 +956,7 @@ public class Copy extends Task {
inputEncoding,
outputEncoding,
getProject(),
- force);
+ getForce());
} catch (IOException ioe) {
String msg = "Failed to copy " + fromResource
+ " to " + toFile
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Move.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Move.java?rev=943056&r1=943055&r2=943056&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Move.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Move.java Tue May 11
09:13:27 2010
@@ -233,9 +233,10 @@ public class Move extends Copy {
getFilterChains(),
forceOverwrite,
getPreserveLastModified(),
+ /* append: */ false,
getEncoding(),
getOutputEncoding(),
- getProject());
+ getProject(), getForce());
} catch (IOException ioe) {
String msg = "Failed to copy " + fromFile
+ " to " + toFile + " due to " + ioe.getMessage();
@@ -329,6 +330,18 @@ public class Move extends Copy {
|| getFilterChains().size() > 0) {
return false;
}
+
+ // identical logic lives in ResourceUtils.copyResource():
+ if (destFile.isFile() && !destFile.canWrite()) {
+ if (!getForce()) {
+ throw new IOException("can't replace read-only destination "
+ + "file " + destFile);
+ } else if (!getFileUtils().tryHardToDelete(destFile)) {
+ throw new IOException("failed to delete read-only "
+ + "destination file " + destFile);
+ }
+ }
+
// identical logic lives in FileUtils.rename():
File parent = destFile.getParentFile();
if (parent != null && !parent.exists()) {
Modified: ant/core/trunk/src/tests/antunit/taskdefs/move-test.xml
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/tests/antunit/taskdefs/move-test.xml?rev=943056&r1=943055&r2=943056&view=diff
==============================================================================
--- ant/core/trunk/src/tests/antunit/taskdefs/move-test.xml (original)
+++ ant/core/trunk/src/tests/antunit/taskdefs/move-test.xml Tue May 11 09:13:27
2010
@@ -124,4 +124,111 @@
value="Y"/>
</target>
+ <!-- stolen from ../types/readwrite-test.xml - create a read-only file -->
+ <property name="file" value="testfile"/>
+ <condition property="unix">
+ <os family="unix"/>
+ </condition>
+ <target name="createTestdir">
+ <mkdir dir="${output}"/>
+ <mkdir dir="${input}"/>
+ <touch file="${output}/${file}"/>
+ </target>
+ <target name="makeFileUnwritable"
+
depends="createTestdir,makeFileUnwritable-Unix,makeFileUnwritable-Windows"/>
+ <target name="makeFileUnwritable-Unix" id="unix">
+ <chmod file="${output}/${file}" perm="444"/>
+ </target>
+ <target name="makeFileUnwritable-Windows" unless="unix">
+ <attrib file="${output}/${file}" readonly="true"/>
+ </target>
+
+ <target name="testMoveOverReadOnlyFile" depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't replace read-only destination file ">
+ <move toDir="${output}">
+ <fileset dir="${input}"/>
+ </move>
+ </au:expectfailure>
+ </target>
+
+ <target name="testFilteredMoveOverReadOnlyFile" depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <move toDir="${output}">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </move>
+ </au:expectfailure>
+ </target>
+
+ <target name="testMoveOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't replace read-only destination file ">
+ <move toDir="${output}" overwrite="true">
+ <fileset dir="${input}"/>
+ </move>
+ </au:expectfailure>
+ </target>
+
+ <target name="testFilteredMoveOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <move toDir="${output}" overwrite="true">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </move>
+ </au:expectfailure>
+ </target>
+
+ <target name="testForcedMoveOverReadOnlyFile" depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <move toDir="${output}" force="true">
+ <fileset dir="${input}"/>
+ </move>
+ </target>
+
+ <target name="testForcedFilteredMoveOverReadOnlyFile"
+ depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <move toDir="${output}" force="true">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </move>
+ </target>
+
+ <target name="testForcedMoveOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <move toDir="${output}" overwrite="true" force="true">
+ <fileset dir="${input}"/>
+ </move>
+ </target>
+
+ <target name="testForcedFilteredMoveOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <move toDir="${output}" overwrite="true" force="true">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </move>
+ </target>
</project>