You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ol...@apache.org on 2020/05/27 01:38:29 UTC
[maven-shared-utils] 01/01: Merge branch 'pr-28'
This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-shared-utils.git
commit 4b5edb196986a767b3454c111915c88fb61ef099
Merge: 87da81f e571803
Author: olivier lamy <ol...@apache.org>
AuthorDate: Wed May 27 11:37:47 2020 +1000
Merge branch 'pr-28'
.../apache/maven/shared/utils/io/FileUtils.java | 164 ++++++++---
.../maven/shared/utils/io/FileUtilsTest.java | 321 ++++++++++++++++++++-
2 files changed, 426 insertions(+), 59 deletions(-)
diff --cc src/main/java/org/apache/maven/shared/utils/io/FileUtils.java
index 24dcf98,8929c4d..3bce615
--- a/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/FileUtils.java
@@@ -39,10 -37,14 +37,15 @@@ import java.io.RandomAccessFile
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
+ import java.nio.Buffer;
+ import java.nio.ByteBuffer;
+ import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
+ import java.nio.charset.CharsetEncoder;
+ import java.nio.charset.CoderResult;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.util.ArrayList;
@@@ -1833,48 -1820,79 +1823,111 @@@ public class FileUtil
wrapped = wrapper.getReader( wrapped );
}
- IOUtil.copy( wrapped, fileWriter );
- }
- }
- else
- {
- if ( to.lastModified() < from.lastModified() || overwrite )
- {
- copyFile( from, to );
+ if ( overwrite || !to.exists() )
+ {
+ try ( Writer fileWriter = Files.newBufferedWriter( to.toPath(), charset ) )
+ {
+ IOUtil.copy( wrapped, fileWriter );
+ }
+ }
+ else
+ {
+ CharsetEncoder encoder = charset.newEncoder();
+
+ int totalBufferSize = FILE_COPY_BUFFER_SIZE;
+
+ int charBufferSize = ( int ) Math.floor( totalBufferSize / ( 2 + 2 * encoder.maxBytesPerChar() ) );
+ int byteBufferSize = ( int ) Math.ceil( charBufferSize * encoder.maxBytesPerChar() );
+
+ CharBuffer newChars = CharBuffer.allocate( charBufferSize );
+ ByteBuffer newBytes = ByteBuffer.allocate( byteBufferSize );
+ ByteBuffer existingBytes = ByteBuffer.allocate( byteBufferSize );
+
+ CoderResult coderResult;
+ int existingRead;
+ boolean writing = false;
+
+ try ( final RandomAccessFile existing = new RandomAccessFile( to, "rw" ) )
+ {
+ int n;
+ while ( -1 != ( n = wrapped.read( newChars ) ) )
+ {
+ ( ( Buffer ) newChars ).flip();
+
+ coderResult = encoder.encode( newChars, newBytes, n != 0 );
+ if ( coderResult.isError() )
+ {
+ coderResult.throwException();
+ }
+
+ ( ( Buffer ) newBytes ).flip();
+
+ if ( !writing )
+ {
+ existingRead = existing.read( existingBytes.array(), 0, newBytes.remaining() );
+ ( ( Buffer ) existingBytes ).position( existingRead );
+ ( ( Buffer ) existingBytes ).flip();
+
+ if ( newBytes.compareTo( existingBytes ) != 0 )
+ {
+ writing = true;
+ if ( existingRead > 0 )
+ {
+ existing.seek( existing.getFilePointer() - existingRead );
+ }
+ }
+ }
+
+ if ( writing )
+ {
+ existing.write( newBytes.array(), 0, newBytes.remaining() );
+ }
+
+ ( ( Buffer ) newChars ).clear();
+ ( ( Buffer ) newBytes ).clear();
+ ( ( Buffer ) existingBytes ).clear();
+ }
+
+ if ( existing.length() > existing.getFilePointer() )
+ {
+ existing.setLength( existing.getFilePointer() );
+ }
+ }
+ }
}
}
+
+ copyFilePermissions( from, to );
+ }
+
+ /**
+ * Attempts to copy file permissions from the source to the destination file.
+ * Initially attempts to copy posix file permissions, assuming that the files are both on posix filesystems.
+ * If the initial attempts fail then a second attempt using less precise permissions model.
+ * Note that permissions are copied on a best-efforts basis,
+ * failure to copy permissions will not result in an exception.
+ *
+ * @param source the file to copy permissions from.
+ * @param destination the file to copy permissions to.
+ */
+ private static void copyFilePermissions( @Nonnull File source, @Nonnull File destination )
+ throws IOException
+ {
+ try
+ {
+ // attempt to copy posix file permissions
+ Files.setPosixFilePermissions(
+ destination.toPath(),
+ Files.getPosixFilePermissions( source.toPath() )
+ );
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ // fallback to setting partial permissions
+ destination.setExecutable( source.canExecute() );
+ destination.setReadable( source.canRead() );
+ destination.setWritable( source.canWrite() );
+ }
}
/**