git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1555363 13f79535-47bb-0310-9956-ffa450edef68master
@@ -64,6 +64,10 @@ Fixed bugs: | |||||
* reading of compiler args has become more defensive | * reading of compiler args has become more defensive | ||||
Bugzilla Report 53754 | Bugzilla Report 53754 | ||||
* <copy> without force="true" would not only fail to overwrite a | |||||
read-only file as expected but also remove the existing file. | |||||
Bugzilla Report 53095 | |||||
Other changes: | Other changes: | ||||
-------------- | -------------- | ||||
@@ -898,7 +898,9 @@ public class Copy extends Task { | |||||
String msg = "Failed to copy " + fromFile + " to " + toFile | String msg = "Failed to copy " + fromFile + " to " + toFile | ||||
+ " due to " + getDueTo(ioe); | + " due to " + getDueTo(ioe); | ||||
File targetFile = new File(toFile); | File targetFile = new File(toFile); | ||||
if (targetFile.exists() && !targetFile.delete()) { | |||||
if (!(ioe instanceof | |||||
ResourceUtils.ReadOnlyTargetFileException) | |||||
&& targetFile.exists() && !targetFile.delete()) { | |||||
msg += " and I couldn't delete the corrupt " + toFile; | msg += " and I couldn't delete the corrupt " + toFile; | ||||
} | } | ||||
if (failonerror) { | if (failonerror) { | ||||
@@ -980,7 +982,9 @@ public class Copy extends Task { | |||||
+ " to " + toFile | + " to " + toFile | ||||
+ " due to " + getDueTo(ioe); | + " due to " + getDueTo(ioe); | ||||
File targetFile = new File(toFile); | File targetFile = new File(toFile); | ||||
if (targetFile.exists() && !targetFile.delete()) { | |||||
if (!(ioe instanceof | |||||
ResourceUtils.ReadOnlyTargetFileException) | |||||
&& targetFile.exists() && !targetFile.delete()) { | |||||
msg += " and I couldn't delete the corrupt " + toFile; | msg += " and I couldn't delete the corrupt " + toFile; | ||||
} | } | ||||
if (failonerror) { | if (failonerror) { | ||||
@@ -406,8 +406,7 @@ public class ResourceUtils { | |||||
} | } | ||||
if (destFile != null && destFile.isFile() && !destFile.canWrite()) { | if (destFile != null && destFile.isFile() && !destFile.canWrite()) { | ||||
if (!force) { | if (!force) { | ||||
throw new IOException("can't write to read-only destination " | |||||
+ "file " + destFile); | |||||
throw new ReadOnlyTargetFileException(destFile); | |||||
} else if (!FILE_UTILS.tryHardToDelete(destFile)) { | } else if (!FILE_UTILS.tryHardToDelete(destFile)) { | ||||
throw new IOException("failed to delete read-only " | throw new IOException("failed to delete read-only " | ||||
+ "destination file " + destFile); | + "destination file " + destFile); | ||||
@@ -785,4 +784,13 @@ public class ResourceUtils { | |||||
public static interface ResourceSelectorProvider { | public static interface ResourceSelectorProvider { | ||||
ResourceSelector getTargetSelectorForSource(Resource source); | ResourceSelector getTargetSelectorForSource(Resource source); | ||||
} | } | ||||
/** | |||||
* @since Ant 1.9.4 | |||||
*/ | |||||
public static class ReadOnlyTargetFileException extends IOException { | |||||
public ReadOnlyTargetFileException(File destFile) { | |||||
super("can't write to read-only destination file " + destFile); | |||||
} | |||||
} | |||||
} | } |
@@ -446,4 +446,26 @@ public class NullByteStreamResource extends Resource { | |||||
<au:assertResourceDoesntContain resource="${input}/somefile" | <au:assertResourceDoesntContain resource="${input}/somefile" | ||||
value="default contents"/> | value="default contents"/> | ||||
</target> | </target> | ||||
<target name="testCopyDoesntDeleteReadonlyTargetWhenCopyFails" | |||||
description="https://issues.apache.org/bugzilla/show_bug.cgi?id=53095"> | |||||
<mkdir dir="${input}"/> | |||||
<mkdir dir="${output}"/> | |||||
<touch file="${input}/somefile"/> | |||||
<touch file="${output}/somefile"/> | |||||
<exec executable="chmod" osfamily="unix"> | |||||
<arg value="-w"/> | |||||
<arg file="${output}/somefile"/> | |||||
</exec> | |||||
<exec executable="attrib" osfamily="dos"> | |||||
<arg value="+r"/> | |||||
<arg file="${output}/somefile"/> | |||||
</exec> | |||||
<au:expectfailure> | |||||
<copy todir="${output}" file="${input}/somefile" | |||||
overwrite="true"/> | |||||
</au:expectfailure> | |||||
<au:assertFileExists file="${input}/somefile"/> | |||||
<au:assertFileExists file="${output}/somefile"/> | |||||
</target> | |||||
</project> | </project> |