This is an automated email from the ASF dual-hosted git repository. bodewig pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ant.git
The following commit(s) were added to refs/heads/master by this push: new bb02a4d80 try to preserve file permissions of exisiting target when renaming bb02a4d80 is described below commit bb02a4d806652d6e01e8eb1b74fc74d5c94b3317 Author: Stefan Bodewig <bode...@apache.org> AuthorDate: Sat Mar 18 10:42:58 2023 +0100 try to preserve file permissions of exisiting target when renaming https://bz.apache.org/bugzilla/show_bug.cgi?id=66522 --- WHATSNEW | 4 +++ .../org/apache/tools/ant/taskdefs/FixCRLF.java | 2 +- .../org/apache/tools/ant/taskdefs/Replace.java | 2 +- .../tools/ant/taskdefs/optional/ReplaceRegExp.java | 2 +- src/main/org/apache/tools/ant/util/FileUtils.java | 33 +++++++++++++++++++++ .../org/apache/tools/ant/util/FileUtilsTest.java | 34 ++++++++++++++++++++++ 6 files changed, 74 insertions(+), 3 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index cd2d2bcfc..267b0d549 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -18,6 +18,10 @@ Fixed bugs: This is now fixed. Bugzilla Report 66468 + * <fixcrlf>, <replace> and <replaceregexp> now try to preserve the + file permissions of the files they modify. + Bugzilla Report 66522 + Other changes: -------------- diff --git a/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java b/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java index cff7ed820..82f7843ba 100644 --- a/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java +++ b/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java @@ -372,7 +372,7 @@ public class FixCRLF extends MatchingTask implements ChainableReader { Project.MSG_DEBUG); } if (destIsWrong) { - FILE_UTILS.rename(tmpFile, destFile); + FILE_UTILS.rename(tmpFile, destFile, true); if (preserveLastModified) { log("preserved lastModified for " + destFile, Project.MSG_DEBUG); diff --git a/src/main/org/apache/tools/ant/taskdefs/Replace.java b/src/main/org/apache/tools/ant/taskdefs/Replace.java index 66cdef43b..a7daa0370 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Replace.java +++ b/src/main/org/apache/tools/ant/taskdefs/Replace.java @@ -670,7 +670,7 @@ public class Replace extends MatchingTask { if (changes) { fileCount++; long origLastModified = src.lastModified(); - FILE_UTILS.rename(temp, src); + FILE_UTILS.rename(temp, src, true); if (preserveLastModified) { FILE_UTILS.setFileLastModified(src, origLastModified); } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java index 5b7e3e695..c5b9d7d43 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java @@ -434,7 +434,7 @@ public class ReplaceRegExp extends Task { log("File has changed; saving the updated file", Project.MSG_VERBOSE); try { long origLastModified = f.lastModified(); - FILE_UTILS.rename(temp, f); + FILE_UTILS.rename(temp, f, true); if (preserveLastModified) { FILE_UTILS.setFileLastModified(f, origLastModified); } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 0deecaa7c..150bf5f85 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -40,6 +40,7 @@ import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; +import java.lang.UnsupportedOperationException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; @@ -48,6 +49,7 @@ import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.Random; +import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; import java.util.Vector; @@ -1450,6 +1452,27 @@ public class FileUtils { * @since Ant 1.6 */ public void rename(File from, File to) throws IOException { + rename(from, to, false); + } + + /** + * Renames a file, even if that involves crossing file system boundaries. + * + * <p>This will remove <code>to</code> (if it exists), ensure that + * <code>to</code>'s parent directory exists and move + * <code>from</code>, which involves deleting <code>from</code> as + * well.</p> + * + * @param from the file to move. + * @param to the new file name. + * @param keepTargetFilePermissions keep target file permissions + * @throws IOException if anything bad happens during this + * process. Note that <code>to</code> may have been deleted + * already when this happens. + * @since Ant 1.6 + */ + public void rename(File from, File to, boolean keepTargetFilePermissions) throws IOException { + Set<PosixFilePermission> existingFilePermissions = null; // identical logic lives in Move.renameFile(): from = normalize(from.getAbsolutePath()).getCanonicalFile(); to = normalize(to.getAbsolutePath()); @@ -1461,6 +1484,13 @@ public class FileUtils { System.err.println("Rename of " + from + " to " + to + " is a no-op."); return; } + if (keepTargetFilePermissions) { + try { + existingFilePermissions = Files.getPosixFilePermissions(to.toPath()); + } catch (UnsupportedOperationException | IOException exc) { + //ignore + } + } if (to.exists() && !(areSame(from, to) || tryHardToDelete(to))) { throw new IOException("Failed to delete " + to + " while trying to rename " + from); } @@ -1476,6 +1506,9 @@ public class FileUtils { throw new IOException("Failed to delete " + from + " while trying to rename it."); } } + if (existingFilePermissions != null) { + Files.setPosixFilePermissions(to.toPath(), existingFilePermissions); + } } /** diff --git a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java index 555916cac..5a168a514 100644 --- a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java +++ b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java @@ -26,6 +26,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; import java.util.Locale; import java.util.Optional; import java.util.Set; @@ -119,6 +120,39 @@ public class FileUtilsTest { assertNotEquals(thirdModTime, secondModTime); } + /** + * test file permissions for FileUtils#rename. + * Since Ant1.10.7, ant uses FileUtils#rename for various tasks (eg. ReplaceRegExp). + * Test that file permission set stays the same. + * @see FileUtils#rename(java.io.File, java.io.File, boolean) + * @throws IOException if something goes wrong + */ + @Test + public void testFilePermissions() throws IOException { + assumeFalse("Test doesn't run on DOS", Os.isFamily("dos")); + File removeThis = getFileUtils().createTempFile("permis", "sion", folder.getRoot(), true, true); + File toBeMoved1 = getFileUtils().createTempFile("permis", "sion", folder.getRoot(), true, true); + File toBeMoved2 = getFileUtils().createTempFile("permis", "sion", folder.getRoot(), true, true); + try (FileOutputStream fos = new FileOutputStream(removeThis)) { + fos.write(new byte[0]); + } + try (FileOutputStream fos = new FileOutputStream(toBeMoved1)) { + fos.write(new byte[0]); + } + try (FileOutputStream fos = new FileOutputStream(toBeMoved2)) { + fos.write(new byte[0]); + } + Set<PosixFilePermission> allAllowed = PosixFilePermissions.fromString("rwxrwxrwx"); + Files.setPosixFilePermissions(removeThis.toPath(), allAllowed); + + getFileUtils().rename(toBeMoved1, removeThis, true); + assertEquals(allAllowed,Files.getPosixFilePermissions(removeThis.toPath())); + + Set<PosixFilePermission> tempAllowed = Files.getPosixFilePermissions(toBeMoved2.toPath()); + getFileUtils().rename(toBeMoved2, removeThis); + assertEquals(tempAllowed,Files.getPosixFilePermissions(removeThis.toPath())); + } + @Test public void testResolveFilePosix() { assumeTrue("DOS or NetWare", !Os.isFamily("dos") && !Os.isFamily("netware"));