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-build-cache-extension.git


The following commit(s) were added to refs/heads/master by this push:
     new 697f01e  fix for issue #450 - fixed CacheUtils.unzip to properly 
restore unix permissions on file systems that support it (#451)
697f01e is described below

commit 697f01eba273a245fc8e5ad24963a54facbb1f97
Author: Andrei Karneyenka <[email protected]>
AuthorDate: Thu Feb 12 17:18:02 2026 -0500

    fix for issue #450 - fixed CacheUtils.unzip to properly restore unix 
permissions on file systems that support it (#451)
    
    * fix for issue #450 - fixed CacheUtils.unzip to properly restore unix 
permissions on file systems that support it
    
    CacheUtils.unzip() is using ZipArchiveInputStream which is not properly 
reading unix permissions. Apparently, it's a known shortcoming documented in 
commons-compress javadocs. Switched to using ZipFile and permissions are now 
extracted correctly.
    
    * fix for issue #450 - updated test description for better clarity
    
    * addressed code review feedback from @olamy
---
 .../org/apache/maven/buildcache/CacheUtils.java    | 17 ++++++++------
 .../buildcache/CacheUtilsPermissionsTest.java      | 27 ++++++++++++++++++++++
 2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/apache/maven/buildcache/CacheUtils.java 
b/src/main/java/org/apache/maven/buildcache/CacheUtils.java
index df3bb49..1265d0d 100644
--- a/src/main/java/org/apache/maven/buildcache/CacheUtils.java
+++ b/src/main/java/org/apache/maven/buildcache/CacheUtils.java
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -32,6 +33,7 @@
 import java.nio.file.attribute.PosixFilePermission;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -39,8 +41,8 @@
 import java.util.stream.Stream;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Strings;
 import org.apache.commons.lang3.mutable.MutableBoolean;
@@ -210,9 +212,10 @@ public static void unzip(Path zip, Path out, boolean 
preservePermissions) throws
         final boolean supportsPosix = preservePermissions
                 && 
out.getFileSystem().supportedFileAttributeViews().contains("posix");
 
-        try (ZipArchiveInputStream zis = new 
ZipArchiveInputStream(Files.newInputStream(zip))) {
-            ZipArchiveEntry entry = zis.getNextEntry();
-            while (entry != null) {
+        try (ZipFile zipFile = ZipFile.builder().setFile(zip.toFile()).get()) {
+            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
+            while (entries.hasMoreElements()) {
+                ZipArchiveEntry entry = entries.nextElement();
                 Path file = out.resolve(entry.getName());
                 if (!file.normalize().startsWith(out.normalize())) {
                     throw new RuntimeException("Bad zip entry");
@@ -222,7 +225,9 @@ public static void unzip(Path zip, Path out, boolean 
preservePermissions) throws
                 } else {
                     Path parent = file.getParent();
                     Files.createDirectories(parent);
-                    Files.copy(zis, file, StandardCopyOption.REPLACE_EXISTING);
+                    try (InputStream is = zipFile.getInputStream(entry)) {
+                        Files.copy(is, file, 
StandardCopyOption.REPLACE_EXISTING);
+                    }
                 }
                 Files.setLastModifiedTime(file, 
FileTime.fromMillis(entry.getTime()));
 
@@ -234,8 +239,6 @@ public static void unzip(Path zip, Path out, boolean 
preservePermissions) throws
                         Files.setPosixFilePermissions(file, permissions);
                     }
                 }
-
-                entry = zis.getNextEntry();
             }
         }
     }
diff --git 
a/src/test/java/org/apache/maven/buildcache/CacheUtilsPermissionsTest.java 
b/src/test/java/org/apache/maven/buildcache/CacheUtilsPermissionsTest.java
index fe2a6ec..0ce8685 100644
--- a/src/test/java/org/apache/maven/buildcache/CacheUtilsPermissionsTest.java
+++ b/src/test/java/org/apache/maven/buildcache/CacheUtilsPermissionsTest.java
@@ -149,6 +149,33 @@ void testPermissionsDoNotAffectHashWhenDisabled() throws 
IOException {
                         + "Files should use system default permissions 
(umask).");
     }
 
+    @Test
+    @DisabledOnOs(OS.WINDOWS)
+    void testPermissionsAreRestoredOnUnzip() throws Exception {
+        // Given: a source directory with a file that has "execute" permission
+        Path source = tempDir.resolve("source");
+        Files.createDirectories(source);
+
+        Path script = source.resolve("script.sh");
+        writeString(script, "#!/bin/bash\necho hello");
+        Set<PosixFilePermission> execPermissions = 
PosixFilePermissions.fromString("rwxr-xr-x");
+        Files.setPosixFilePermissions(script, execPermissions);
+
+        // When: ZIP file is created from that directory with 
"preservePermissions=true"
+        Path zippedFile = tempDir.resolve("target.zip");
+        CacheUtils.zip(source, zippedFile, "*", true);
+
+        // And: ZIP file is extracted with "preservePermissions=true"
+        Path unzippedDir = tempDir.resolve("target-unzipped");
+        Files.createDirectories(unzippedDir);
+        CacheUtils.unzip(zippedFile, unzippedDir, true);
+
+        // Then: extracted file should have executable permissions
+        Path extractedScript = unzippedDir.resolve("script.sh");
+        assertTrue(Files.exists(extractedScript), "Extracted script should 
exist.");
+        assertTrue(Files.isExecutable(extractedScript), "Permissions should be 
restored when the file is extracted");
+    }
+
     /**
      * Java 8 compatible version of Files.writeString().
      */

Reply via email to