Browse Source

be consistent when it comes to overwriting read-only files, add an option to do just that to <copy>. PR 49261

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@942752 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 15 years ago
parent
commit
35e9c976ac
6 changed files with 200 additions and 20 deletions
  1. +9
    -0
      WHATSNEW
  2. +6
    -0
      docs/manual/CoreTasks/copy.html
  3. +21
    -4
      src/main/org/apache/tools/ant/taskdefs/Copy.java
  4. +47
    -4
      src/main/org/apache/tools/ant/util/FileUtils.java
  5. +58
    -4
      src/main/org/apache/tools/ant/util/ResourceUtils.java
  6. +59
    -8
      src/tests/antunit/taskdefs/copy-test.xml

+ 9
- 0
WHATSNEW View File

@@ -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 <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:
-----------



+ 6
- 0
docs/manual/CoreTasks/copy.html View File

@@ -89,6 +89,12 @@ operation as <a href="../CoreTypes/filterset.html">filtersets</a>.
files are newer.</td>
<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


+ 21
- 4
src/main/org/apache/tools/ant/taskdefs/Copy.java View File

@@ -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.
*
* <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
@@ -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


+ 47
- 4
src/main/org/apache/tools/ant/util/FileUtils.java View File

@@ -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


+ 58
- 4
src/main/org/apache/tools/ant/util/ResourceUtils.java View File

@@ -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()


+ 59
- 8
src/tests/antunit/taskdefs/copy-test.xml View File

@@ -314,18 +314,69 @@ public class NullByteStreamResource extends Resource {
<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 extends Resource {
</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"/>


Loading…
Cancel
Save