Skip to content

Commit 0026581

Browse files
authored
Implement pkg_install(symlink) also for pkg_zip (#982)
I start to use hermetic python environment and saw #929. It mostly works, but in my case I use pkg_zip instead of pkg_tar. 4eed546 implements `raw_symlink`/ support for `pkg_tar`. This MR adds the same functionality for `pkg_zip`. The exception when the feature is not implemented yet: ``` Exception: ('Unknown type for manifest entry:', ManifestEntry<{'type': 'raw_symlink', 'dest': 'system_impl.runfiles/_main/example/_impl_py_client_install.venv/bin/python3', 'src': 'bazel-out/k8-fastbuild/bin/example/_impl_py_client_install.venv/bin/python3', 'mode': '0555', 'user': None, 'group': None, 'uid': None, 'gid': None, 'origin': '@@//example:system_impl'}>) ```
2 parents 38f29af + 0fa07e1 commit 0026581

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

pkg/private/zip/build_zip.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ def add_manifest_entry(self, entry):
182182
# Set directory bits
183183
entry_info.external_attr |= (UNIX_SYMLINK_BIT << 16)
184184
self.zip_file.writestr(entry_info, src.encode('utf-8'))
185+
elif entry_type == manifest.ENTRY_IS_RAW_LINK:
186+
entry_info.compress_type = zipfile.ZIP_STORED
187+
# Set directory bits
188+
entry_info.external_attr |= (UNIX_SYMLINK_BIT << 16)
189+
self.zip_file.writestr(entry_info, os.readlink(src).encode('utf-8'))
185190
elif entry_type == manifest.ENTRY_IS_TREE:
186191
self.add_tree(src, dst_path, mode)
187192
elif entry_type == manifest.ENTRY_IS_EMPTY_FILE:

tests/zip/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load("//pkg:mappings.bzl", "pkg_attributes", "pkg_mkdirs", "pkg_mklink")
1919
load("//pkg:zip.bzl", "pkg_zip")
2020
load("//tests:my_package_name.bzl", "my_package_naming")
2121
load("//tests/util:defs.bzl", "directory")
22+
load("//tests/zip:symlink_util.bzl", "create_fake_symlink")
2223

2324
package(default_applicable_licenses = ["//:license"])
2425

@@ -268,6 +269,20 @@ pkg_zip(
268269
compression_type = "stored",
269270
)
270271

272+
create_fake_symlink(
273+
name = "fake_symlink",
274+
link = "fake_symlink",
275+
target = "../does_not_exist",
276+
)
277+
278+
pkg_zip(
279+
name = "test_zip_symlink",
280+
srcs = [
281+
":fake_symlink",
282+
"//tests:file_and_link",
283+
],
284+
)
285+
271286
py_test(
272287
name = "zip_test",
273288
srcs = [
@@ -287,6 +302,7 @@ py_test(
287302
":test_zip_package_dir_substitution.zip",
288303
":test_zip_permissions.zip",
289304
":test_zip_stored",
305+
":test_zip_symlink",
290306
":test_zip_timestamp.zip",
291307
":test_zip_tree.zip",
292308
],

tests/zip/symlink_util.bzl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Helpers for testing zip packaging."""
2+
3+
def _create_fake_symlink_impl(ctx):
4+
symlink = ctx.actions.declare_symlink(ctx.attr.link)
5+
ctx.actions.symlink(output = symlink, target_path = ctx.attr.target)
6+
return [DefaultInfo(files = depset([symlink]))]
7+
8+
create_fake_symlink = rule(
9+
implementation = _create_fake_symlink_impl,
10+
attrs = {
11+
"link": attr.string(mandatory = True),
12+
"target": attr.string(mandatory = True),
13+
},
14+
)

tests/zip/zip_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ def test_compression_stored(self):
150150
{"filename": "loremipsum.txt", "crc": LOREM_CRC, "size": 543},
151151
])
152152

153+
def test_symlink(self):
154+
self.assertZipFileContent("test_zip_symlink.zip", [
155+
{"filename": "BUILD", "islink": False},
156+
{"filename": "fake_symlink", "islink": True}, # raw symlink -> keep symlink
157+
{"filename": "outer_BUILD", "islink": False},# nonraw symlink -> copy
158+
])
159+
153160

154161

155162
if __name__ == "__main__":

tests/zip/zip_test_lib.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
MSDOS_DIR_BIT = 0x10
2626
UNIX_RWX_BITS = 0o777
2727
UNIX_RX_BITS = 0o555
28+
UNIX_SYMLINK_BIT = 0o120000
2829

2930
# The ZIP epoch date: (1980, 1, 1, 0, 0, 0)
3031
_ZIP_EPOCH_DT = datetime.datetime(1980, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
@@ -77,7 +78,17 @@ def assertZipFileContent(self, zip_file, content):
7778
oct(expected.get("attr", 0o755)))
7879
elif "isexe" in expected:
7980
got_mode = (info.external_attr >> 16) & UNIX_RX_BITS
80-
self.assertEqual(oct(got_mode), oct(UNIX_RX_BITS))
81+
if expected['isexe']:
82+
self.assertEqual(oct(got_mode), oct(UNIX_RX_BITS))
83+
else:
84+
self.assertNotEqual(oct(got_mode), oct(UNIX_RX_BITS))
85+
elif "islink" in expected:
86+
got_mode = (info.external_attr >> 16) & UNIX_SYMLINK_BIT
87+
if expected['islink']:
88+
self.assertEqual(oct(got_mode), oct(UNIX_SYMLINK_BIT))
89+
else:
90+
self.assertNotEqual(oct(got_mode), oct(UNIX_SYMLINK_BIT))
91+
8192
elif "size" in expected:
8293
self.assertEqual(info.compress_size, expected["size"])
8394

0 commit comments

Comments
 (0)