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() );
 +        }
      }
  
      /**