From 35e9c976aca460e541e62bd67f88fa8482014f1e Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Mon, 10 May 2010 14:35:56 +0000 Subject: [PATCH] be consistent when it comes to overwriting read-only files, add an option to do just that to . PR 49261 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@942752 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 9 +++ docs/manual/CoreTasks/copy.html | 6 ++ .../org/apache/tools/ant/taskdefs/Copy.java | 25 +++++-- .../org/apache/tools/ant/util/FileUtils.java | 51 ++++++++++++-- .../apache/tools/ant/util/ResourceUtils.java | 62 +++++++++++++++-- src/tests/antunit/taskdefs/copy-test.xml | 67 ++++++++++++++++--- 6 files changed, 200 insertions(+), 20 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index 4e925b785..1d6e52913 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -4,6 +4,15 @@ Changes from Ant 1.8.1 TO current SVN version Changes that could break older environments: ------------------------------------------- + * Prior to Ant 1.8.0 the 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 task now has a new force attribute that can be used to + make the task overwrite read-only destinations. + Bugzilla Report 49261. + Fixed bugs: ----------- diff --git a/docs/manual/CoreTasks/copy.html b/docs/manual/CoreTasks/copy.html index 4e16b8957..e8e240e59 100644 --- a/docs/manual/CoreTasks/copy.html +++ b/docs/manual/CoreTasks/copy.html @@ -89,6 +89,12 @@ operation as filtersets. files are newer. No; defaults to false. + + force + Overwrite read-only destination + files. since Ant 1.8.2 + No; defaults to false. + filtering Indicates whether token filtering using the global diff --git a/src/main/org/apache/tools/ant/taskdefs/Copy.java b/src/main/org/apache/tools/ant/taskdefs/Copy.java index 2da7f665e..6c49fe0a2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Copy.java +++ b/src/main/org/apache/tools/ant/taskdefs/Copy.java @@ -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. @@ -228,6 +229,17 @@ public class Copy extends Task { this.forceOverwrite = overwrite; } + /** + * Whether read-only destinations will be overwritten. + * + *

Defaults to false

+ * + * @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 @@ -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 diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 31d627adf..b36f01f1a 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -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 + * destFile file should be made equal + * to the last modified time of sourceFile. + * + * @param sourceFile the file to copy from. + * Must not be null. + * @param destFile the file to copy to. + * Must not be null. + * @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 diff --git a/src/main/org/apache/tools/ant/util/ResourceUtils.java b/src/main/org/apache/tools/ant/util/ResourceUtils.java index 9c1fb433e..c7ce29b4b 100644 --- a/src/main/org/apache/tools/ant/util/ResourceUtils.java +++ b/src/main/org/apache/tools/ant/util/ResourceUtils.java @@ -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 dest file should be made + * equal to the last modified time of source. + * + * @param source the Resource to copy from. + * Must not be null. + * @param dest the Resource to copy to. + * Must not be null. + * @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() diff --git a/src/tests/antunit/taskdefs/copy-test.xml b/src/tests/antunit/taskdefs/copy-test.xml index 346d622d5..b47b758bd 100644 --- a/src/tests/antunit/taskdefs/copy-test.xml +++ b/src/tests/antunit/taskdefs/copy-test.xml @@ -314,18 +314,69 @@ public class NullByteStreamResource extends Resource { - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -333,18 +384,18 @@ public class NullByteStreamResource extends Resource { - - + - - +