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