Skip to content

Commit e8a38e2

Browse files
committed
Preserve permissions for modifying a zip file in place
1 parent 4127ca1 commit e8a38e2

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

os/src/ZipOps.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ object zip {
2424
def open(path: Path): ZipRoot = {
2525
new ZipRoot(FileSystems.newFileSystem(
2626
new URI("jar", path.wrapped.toUri.toString, null),
27-
Map("create" -> "true").asJava
27+
Map("create" -> "true", "enablePosixFileAttributes" -> "true").asJava
2828
))
2929
}
3030

@@ -71,6 +71,8 @@ object zip {
7171
includePatterns,
7272
(path, sub) => {
7373
os.copy(path, opened / sub, createFolders = true)
74+
if (!scala.util.Properties.isWin && Runtime.version.feature >= 14)
75+
Files.setPosixFilePermissions((opened / sub).wrapped, os.perms(path).toSet())
7476
if (!preserveMtimes) {
7577
os.mtime.set(opened / sub, 0)
7678
// This is the only way we can properly zero out filesystem metadata within the

os/test/src/ZipOpTests.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,51 @@ object ZipOpTests extends TestSuite {
388388
assert(os.read(os.readLink.absolute(source / link)) == os.read(unzippedLink))
389389
}
390390
}
391+
392+
test("") - prep { wd =>
393+
if (!scala.util.Properties.isWin) {
394+
val (source, unzipped, link) = prepare(wd, preserveLinks = true)
395+
396+
val newSource = os.pwd / "source"
397+
os.makeDir(newSource)
398+
399+
val newFile = os.sub / "new.txt"
400+
val perms = os.PermSet.fromString("rw-rw-rw-")
401+
os.write(newSource / newFile, "Contents of new.txt")
402+
os.perms.set(newSource / newFile, perms)
403+
404+
val newLink = os.sub / "newLink.txt"
405+
os.symlink(newSource / newLink, os.rel / "new.txt")
406+
407+
val newZipped = os.zip(
408+
dest = wd / "zipped.zip",
409+
sources = List(newSource / newFile, newSource / newLink)
410+
)
411+
412+
val newUnzipped = os.unzip(
413+
source = newZipped,
414+
dest = wd / "newUnzipped"
415+
)
416+
417+
assert((walkRel(source) ++ walkRel(newSource)).toSet == walkRel(newUnzipped).toSet)
418+
419+
if (Runtime.version.feature >= 14) {
420+
assert(os.walk.stream(source)
421+
.filter(!os.isLink(_))
422+
.forall(p => os.perms(p) == os.perms(newUnzipped / p.relativeTo(source))))
423+
}
424+
425+
val unzippedNewLink = newUnzipped / newLink
426+
assert(os.isFile(unzippedNewLink))
427+
assert(os.read(os.readLink.absolute(newSource / newLink)) == os.read(unzippedNewLink))
428+
429+
val unzippedNewFile = newUnzipped / newFile
430+
if (Runtime.version.feature >= 14) {
431+
assert(os.perms(unzippedNewFile) == perms)
432+
assert(os.perms(unzippedNewLink) == perms)
433+
}
434+
}
435+
}
391436
}
392437

393438
test("unzipStream") - prep { wd =>

0 commit comments

Comments
 (0)