You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add support for permissions and symlinks in os.zip/unzip with vendored zip source code from Apache Ant (#374)
### Vendored code
Follow the discussion in #356, this adds support for permissions and
symlinks in `os.zip`/`unzip` with vendored zip source code from Apache
Ant.
The vendored source code is generated by the `os.zip.apacheAntZipSource`
task and put in `os/zip`. It's shaded with the package renamed from
`org.apache.tools.zip` to `os.shaded_org_apache_tools_zip`.
`scala-steward.conf` was added and configured to run
`os.zip.apacheAntZipSource` on `org.apache.ant:ant` updates.
### Features
This brings support for permissions and symlinks to `zip` (for creating
new zips, not modifying existing ones), `zip.stream` and `unzip`. As for
modifying existing zips, we would still have to rely on `jdk.zipfs`
which does not support symlinks.
| | file permissions | symlinks |
| --- | --- | --- |
| `os.zip.open` | if Java Runtime Version >= 14 | |
| `os.zip` (create new) | ✅ | ✅ |
| `os.zip` (modify existing) | if Java Runtime Version >= 14 | |
| `os.zip.stream` | ✅ | ✅ |
| `os.unzip` | ✅ | ✅ |
| `os.unzip.stream` | | |
### TODO
- [ ] **(Advice needed)** make sure we comply with Apache Ant's license
to include the code here. Would appreciate opinions on this as I'm not
an expert.
- [ ] **(Advice needed)** make `ZipOps` JVM only
- [x] tests
- [x] make sure things don't break on Windows
- [x] add permission support to modifying existing zips with `jdk.zipfs`
like what @sake92 did in #371
Copy file name to clipboardExpand all lines: Readme.adoc
+20-7Lines changed: 20 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1233,7 +1233,8 @@ def apply(dest: os.Path,
1233
1233
includePatterns: Seq[Regex] = List(),
1234
1234
preserveMtimes: Boolean = false,
1235
1235
deletePatterns: Seq[Regex] = List(),
1236
-
compressionLevel: Int = -1 /* 0-9 */): os.Path
1236
+
compressionLevel: Int = -1, /* 0-9 */
1237
+
followLinks: Boolean = true): os.Path
1237
1238
----
1238
1239
1239
1240
The zip object provides functionality to create or modify zip archives. It supports:
@@ -1243,14 +1244,19 @@ The zip object provides functionality to create or modify zip archives. It suppo
1243
1244
- Exclude Patterns (-x): You can specify files or patterns to exclude while zipping.
1244
1245
- Include Patterns (-i): You can include specific files or patterns while zipping.
1245
1246
- Delete Patterns (-d): You can delete specific files from an existing zip archive.
1246
-
- Configuring whether or not to preserve filesyste mtimes and permissions
1247
+
- Symbolic Links (-y): You can configure to zip symbolic links as symbolic links on Linux/Unix by setting `followLinks = false`. Symbolic links are zipped as the referenced files by default on Linux/Unix, and always on Windows.
1248
+
- Configuring whether or not to preserve filesyste mtimes.
1249
+
- Preserving Unix file permissions.
1247
1250
1248
1251
This will create a new zip archive at `dest` containing `file1.txt` and everything
1249
1252
inside `sources`. If `dest` already exists as a zip, the files will be appended to the
1250
1253
existing zip, and any existing zip entries matching `deletePatterns` will be removed.
1251
1254
1252
-
Note that `os.zip` doesn't support creating/unpacking symlinks or filesystem permissions
1253
-
in Zip files, because the underlying `java.util.zip.Zip*Stream` doesn't support them.
1255
+
When modifying an existing zip file,
1256
+
- Unix file permissions will be preserved if Java Runtime Version >= 14.
1257
+
- If using Java Runtime Version < 14, Unix file permissions are not preserved, even for existing zip entries.
1258
+
- Symbolics links will always be stored as the referenced files.
1259
+
- Existing symbolic links stored in the zip might lose their symbolic link file type field and become broken.
This can be useful for streaming the zipped data to places which are not files:
1376
1382
over the network, over a pipe, etc.
1377
1383
1384
+
File permissions will be preserved. Symbolic links will be zipped as the referenced files by default on Linux/Unix, and always on Windows. To zip them as symbolic links on Linux/Unix, set `followLinks = false`.
1385
+
1378
1386
==== `os.unzip`
1379
1387
1380
1388
===== Unzipping Files
@@ -1384,7 +1392,7 @@ over the network, over a pipe, etc.
This extracts the contents of `archive.zip` to the specified destination.
1395
+
This extracts the contents of `archive.zip` to the specified destination. It supports preserving file permissions and symbolic links.
1388
1396
1389
1397
1390
1398
===== Excluding Files While Unzipping
@@ -1407,7 +1415,7 @@ You can list the contents of the zip file without extracting them:
1407
1415
os.unzip.list(os.Path("/path/to/archive.zip"))
1408
1416
----
1409
1417
1410
-
This will print all the file paths contained in the zip archive.
1418
+
This will print all the file paths contained in the zip archive. File permissions and symbolic links will not be preserved.
1411
1419
1412
1420
==== `os.unzip.stream`
1413
1421
@@ -1427,6 +1435,9 @@ os.unzip.stream(
1427
1435
This can be useful if the zip file does not exist on disk, e.g. if it is received over the network
1428
1436
or produced in-memory by application logic.
1429
1437
1438
+
File permissions and symbolic links are not supported since permissions and symlink mode are stored as external attributes which might reside in the central directory located at the end of the zip archive.
1439
+
For more a more detailed explanation see the `ZipArchiveInputStream` vs `ZipFile` section at https://commons.apache.org/proper/commons-compress/zip.html.
1440
+
1430
1441
OS-Lib also provides the `os.unzip.streamRaw` API, which is a lower level API used internally
1431
1442
within `os.unzip.stream` but can also be used directly if lower-level control is necessary.
1432
1443
@@ -1464,6 +1475,8 @@ finally zipFile3.close()
1464
1475
of the zip file rather than a bare path on the filesystem. Note that you need to call `ZipRoot#close()`
1465
1476
when you are done with it to avoid leaking filesystem resources.
1466
1477
1478
+
File permissions are only supported for Java Runtime Version >= 14. Symbolic links are not supported. Using `os.zip.open` on a zip archive that contains symbolic links might break the links.
1479
+
1467
1480
=== Filesystem Metadata
1468
1481
1469
1482
==== `os.stat`
@@ -1793,7 +1806,7 @@ is run:
1793
1806
1794
1807
* `cwd`: the working directory of the subprocess
1795
1808
* `env`: any additional environment variables you wish to set in the subprocess
1796
-
in addition to those passed via `propagateEnv`. You can also set their values
1809
+
in addition to those passed via `propagateEnv`. You can also set their values
1797
1810
to `null` to remove specific variables.
1798
1811
* `stdin`: any data you wish to pass to the subprocess's standard input
1799
1812
* `stdout`/`stderr`: these are ``os.Redirect``s that let you configure how the
0 commit comments