Author: bodewig
Date: Mon May 10 14:35:56 2010
New Revision: 942752
URL: http://svn.apache.org/viewvc?rev=942752&view=rev
Log:
be consistent when it comes to overwriting read-only files, add an option to do
just that to <copy>. PR 49261
Modified:
ant/core/trunk/WHATSNEW
ant/core/trunk/docs/manual/CoreTasks/copy.html
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Copy.java
ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java
ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java
ant/core/trunk/src/tests/antunit/taskdefs/copy-test.xml
Modified: ant/core/trunk/WHATSNEW
URL:
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=942752&r1=942751&r2=942752&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Mon May 10 14:35:56 2010
@@ -4,6 +4,15 @@ 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.
+ Bugzilla Report 49261.
+
Fixed bugs:
-----------
Modified: ant/core/trunk/docs/manual/CoreTasks/copy.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/copy.html?rev=942752&r1=942751&r2=942752&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/copy.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/copy.html Mon May 10 14:35:56 2010
@@ -90,6 +90,12 @@ operation as <a href="../CoreTypes/filte
<td valign="top" align="center">No; defaults to false.</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 using the <a
href="../using.html#filters">global
build-file filters</a> should take place during the copy.
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=942752&r1=942751&r2=942752&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 Mon May 10
14:35:56 2010
@@ -100,6 +100,7 @@ public class Copy extends Task {
private String inputEncoding = null;
private String outputEncoding = null;
private long granularity = 0;
+ private boolean force = false;
/**
* Copy task constructor.
@@ -229,6 +230,17 @@ public class Copy extends Task {
}
/**
+ * Whether read-only destinations will be overwritten.
+ *
+ * <p>Defaults to false</p>
+ *
+ * @since Ant 1.8.2
+ */
+ public void setForce(boolean f) {
+ force = f;
+ }
+
+ /**
* 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
@@ -838,10 +850,13 @@ public class Copy extends Task {
executionFilters
.addFilterSet((FilterSet)
filterEnum.nextElement());
}
- fileUtils.copyFile(fromFile, toFile, executionFilters,
+ fileUtils.copyFile(new File(fromFile), new
File(toFile),
+ executionFilters,
filterChains, forceOverwrite,
- preserveLastModified, inputEncoding,
- outputEncoding, getProject());
+ preserveLastModified,
+ /* append: */ false, inputEncoding,
+ outputEncoding, getProject(),
+ force);
} catch (IOException ioe) {
String msg = "Failed to copy " + fromFile + " to " +
toFile
+ " due to " + getDueTo(ioe);
@@ -928,9 +943,11 @@ public class Copy extends Task {
filterChains,
forceOverwrite,
preserveLastModified,
+ /* append: */ false,
inputEncoding,
outputEncoding,
- getProject());
+ getProject(),
+ force);
} catch (IOException ioe) {
String msg = "Failed to copy " + fromResource
+ " to " + toFile
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=942752&r1=942751&r2=942752&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 May 10
14:35:56 2010
@@ -513,12 +513,55 @@ public class FileUtils {
*/
public void copyFile(File sourceFile, File destFile,
FilterSetCollection filters, Vector filterChains,
- boolean overwrite, boolean preserveLastModified,
boolean append,
+ boolean overwrite, boolean preserveLastModified,
+ boolean append,
String inputEncoding, String outputEncoding,
Project project) throws IOException {
- ResourceUtils.copyResource(new FileResource(sourceFile), new
FileResource(destFile),
- filters, filterChains, overwrite, preserveLastModified,
append, inputEncoding,
- outputEncoding, project);
+ copyFile(sourceFile, destFile, filters, filterChains, overwrite,
+ preserveLastModified, append, inputEncoding, outputEncoding,
+ project, /* force: */ false);
+ }
+
+ /**
+ * Convenience method to copy a file from a source to a
+ * destination specifying if token filtering must be used, if
+ * filter chains must be used, if source files may overwrite
+ * newer destination files and the last modified time of
+ * <code>destFile</code> file should be made equal
+ * to the last modified time of <code>sourceFile</code>.
+ *
+ * @param sourceFile the file to copy from.
+ * Must not be <code>null</code>.
+ * @param destFile the file to copy to.
+ * Must not be <code>null</code>.
+ * @param filters the collection of filters to apply to this copy.
+ * @param filterChains filterChains to apply during the copy.
+ * @param overwrite Whether or not the destination file should be
+ * overwritten if it already exists.
+ * @param preserveLastModified Whether or not the last modified time of
+ * the resulting file should be set to that
+ * of the source file.
+ * @param append whether to append to the destination file.
+ * @param inputEncoding the encoding used to read the files.
+ * @param outputEncoding the encoding used to write the files.
+ * @param project the project instance.
+ * @param force whether to overwrite read-only destination files.
+ *
+ * @throws IOException if the copying fails.
+ *
+ * @since Ant 1.8.2
+ */
+ public void copyFile(File sourceFile, File destFile,
+ FilterSetCollection filters, Vector filterChains,
+ boolean overwrite, boolean preserveLastModified,
+ boolean append,
+ String inputEncoding, String outputEncoding,
+ Project project, boolean force) throws IOException {
+ ResourceUtils.copyResource(new FileResource(sourceFile),
+ new FileResource(destFile),
+ filters, filterChains, overwrite,
+ preserveLastModified, append, inputEncoding,
+ outputEncoding, project, force);
}
// CheckStyle:ParameterNumberCheck ON
Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java?rev=942752&r1=942751&r2=942752&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java Mon
May 10 14:35:56 2010
@@ -339,10 +339,51 @@ public class ResourceUtils {
*/
public static void copyResource(Resource source, Resource dest,
FilterSetCollection filters, Vector filterChains,
- boolean overwrite, boolean preserveLastModified,
boolean append,
+ boolean overwrite, boolean preserveLastModified,
+ boolean append,
String inputEncoding, String outputEncoding,
Project project)
throws IOException {
+ copyResource(source, dest, filters, filterChains, overwrite,
+ preserveLastModified, append, inputEncoding,
+ outputEncoding, project, /* force: */ false);
+ }
+
+ /**
+ * Convenience method to copy content from one Resource to another
+ * specifying whether token filtering must be used, whether filter chains
+ * must be used, whether newer destination files may be overwritten and
+ * whether the last modified time of <code>dest</code> file should be made
+ * equal to the last modified time of <code>source</code>.
+ *
+ * @param source the Resource to copy from.
+ * Must not be <code>null</code>.
+ * @param dest the Resource to copy to.
+ * Must not be <code>null</code>.
+ * @param filters the collection of filters to apply to this copy.
+ * @param filterChains filterChains to apply during the copy.
+ * @param overwrite Whether or not the destination Resource should be
+ * overwritten if it already exists.
+ * @param preserveLastModified Whether or not the last modified time of
+ * the destination Resource should be set to
that
+ * of the source.
+ * @param append Whether to append to an Appendable Resource.
+ * @param inputEncoding the encoding used to read the files.
+ * @param outputEncoding the encoding used to write the files.
+ * @param project the project instance.
+ * @param force whether read-only taret files will be overwritten
+ *
+ * @throws IOException if the copying fails.
+ *
+ * @since Ant 1.8.2
+ */
+ public static void copyResource(Resource source, Resource dest,
+ FilterSetCollection filters, Vector filterChains,
+ boolean overwrite, boolean preserveLastModified,
+ boolean append,
+ String inputEncoding, String
outputEncoding,
+ Project project, boolean force)
+ throws IOException {
if (!(overwrite || SelectorUtils.isOutOfDate(source, dest,
FileUtils.getFileUtils()
.getFileTimestampGranularity()))) {
return;
@@ -351,6 +392,21 @@ public class ResourceUtils {
&& filters.hasFilters());
final boolean filterChainsAvailable = (filterChains != null
&& filterChains.size() > 0);
+
+ File destFile = null;
+ if (dest.as(FileProvider.class) != null) {
+ destFile = ((FileProvider) dest.as(FileProvider.class)).getFile();
+ }
+ if (destFile != null && destFile.isFile() && !destFile.canWrite()) {
+ if (!force) {
+ throw new IOException("can't write to read-only destination "
+ + "file " + destFile);
+ } else if (!FILE_UTILS.tryHardToDelete(destFile)) {
+ throw new IOException("failed to delete read-only "
+ + "destination file " + destFile);
+ }
+ }
+
if (filterSetsAvailable) {
BufferedReader in = null;
BufferedWriter out = null;
@@ -444,11 +500,9 @@ public class ResourceUtils {
FileUtils.close(in);
}
} else if (source.as(FileProvider.class) != null
- && dest.as(FileProvider.class) != null) {
+ && destFile != null) {
File sourceFile =
((FileProvider) source.as(FileProvider.class)).getFile();
- File destFile =
- ((FileProvider) dest.as(FileProvider.class)).getFile();
File parent = destFile.getParentFile();
if (parent != null && !parent.isDirectory()
Modified: ant/core/trunk/src/tests/antunit/taskdefs/copy-test.xml
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/tests/antunit/taskdefs/copy-test.xml?rev=942752&r1=942751&r2=942752&view=diff
==============================================================================
--- ant/core/trunk/src/tests/antunit/taskdefs/copy-test.xml (original)
+++ ant/core/trunk/src/tests/antunit/taskdefs/copy-test.xml Mon May 10 14:35:56
2010
@@ -314,18 +314,69 @@ public class NullByteStreamResource exte
<attrib file="${output}/${file}" readonly="true"/>
</target>
- <target name="XtestCopyOverReadOnlyFile" depends="makeFileUnwritable">
+ <target name="testCopyOverReadOnlyFile" depends="makeFileUnwritable">
<sleep seconds="2"/>
<touch file="${input}/${file}"/>
- <copy toDir="${output}">
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <copy toDir="${output}">
+ <fileset dir="${input}"/>
+ </copy>
+ </au:expectfailure>
+ </target>
+
+ <target name="testFilteredCopyOverReadOnlyFile" depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <copy toDir="${output}">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </copy>
+ </au:expectfailure>
+ </target>
+
+ <target name="testCopyOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <copy toDir="${output}" overwrite="true">
+ <fileset dir="${input}"/>
+ </copy>
+ </au:expectfailure>
+ </target>
+
+ <target name="testFilteredCopyOverReadOnlyFileWithOverwrite"
+ depends="makeFileUnwritable">
+ <touch file="${input}/${file}"/>
+ <au:expectfailure
+ expectedMessage="can't write to read-only destination file ">
+ <copy toDir="${output}" overwrite="true">
+ <fileset dir="${input}"/>
+ <filterset>
+ <filter token="foo" value="bar"/>
+ </filterset>
+ </copy>
+ </au:expectfailure>
+ </target>
+
+ <target name="testForcedCopyOverReadOnlyFile" depends="makeFileUnwritable">
+ <sleep seconds="2"/>
+ <touch file="${input}/${file}"/>
+ <copy toDir="${output}" force="true">
<fileset dir="${input}"/>
</copy>
</target>
- <target name="testFilteredCopyOverReadOnlyFile" depends="makeFileUnwritable">
+ <target name="testForcedFilteredCopyOverReadOnlyFile"
+ depends="makeFileUnwritable">
<sleep seconds="2"/>
<touch file="${input}/${file}"/>
- <copy toDir="${output}">
+ <copy toDir="${output}" force="true">
<fileset dir="${input}"/>
<filterset>
<filter token="foo" value="bar"/>
@@ -333,18 +384,18 @@ public class NullByteStreamResource exte
</copy>
</target>
- <target name="XtestCopyOverReadOnlyFileWithOverwrite"
+ <target name="testForcedCopyOverReadOnlyFileWithOverwrite"
depends="makeFileUnwritable">
<touch file="${input}/${file}"/>
- <copy toDir="${output}" overwrite="true">
+ <copy toDir="${output}" overwrite="true" force="true">
<fileset dir="${input}"/>
</copy>
</target>
- <target name="testFilteredCopyOverReadOnlyFileWithOverwrite"
+ <target name="testForcedFilteredCopyOverReadOnlyFileWithOverwrite"
depends="makeFileUnwritable">
<touch file="${input}/${file}"/>
- <copy toDir="${output}" overwrite="true">
+ <copy toDir="${output}" overwrite="true" force="true">
<fileset dir="${input}"/>
<filterset>
<filter token="foo" value="bar"/>