Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/private/zip/build_zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ def add_manifest_entry(self, entry):
# Set directory bits
entry_info.external_attr |= (UNIX_SYMLINK_BIT << 16)
self.zip_file.writestr(entry_info, src.encode('utf-8'))
elif entry_type == manifest.ENTRY_IS_RAW_LINK:
entry_info.compress_type = zipfile.ZIP_STORED
# Set directory bits
entry_info.external_attr |= (UNIX_SYMLINK_BIT << 16)
self.zip_file.writestr(entry_info, os.readlink(src).encode('utf-8'))
elif entry_type == manifest.ENTRY_IS_TREE:
self.add_tree(src, dst_path, mode)
elif entry_type == manifest.ENTRY_IS_EMPTY_FILE:
Expand Down
16 changes: 16 additions & 0 deletions tests/zip/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ load("//pkg:mappings.bzl", "pkg_attributes", "pkg_mkdirs", "pkg_mklink")
load("//pkg:zip.bzl", "pkg_zip")
load("//tests:my_package_name.bzl", "my_package_naming")
load("//tests/util:defs.bzl", "directory")
load("//tests/zip:symlink_util.bzl", "create_fake_symlink")

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

Expand Down Expand Up @@ -268,6 +269,20 @@ pkg_zip(
compression_type = "stored",
)

create_fake_symlink(
name = "fake_symlink",
link = "fake_symlink",
target = "../does_not_exist",
)

pkg_zip(
name = "test_zip_symlink",
srcs = [
":fake_symlink",
"//tests:file_and_link",
],
)

py_test(
name = "zip_test",
srcs = [
Expand All @@ -287,6 +302,7 @@ py_test(
":test_zip_package_dir_substitution.zip",
":test_zip_permissions.zip",
":test_zip_stored",
":test_zip_symlink",
":test_zip_timestamp.zip",
":test_zip_tree.zip",
],
Expand Down
14 changes: 14 additions & 0 deletions tests/zip/symlink_util.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Helpers for testing zip packaging."""

def _create_fake_symlink_impl(ctx):
symlink = ctx.actions.declare_symlink(ctx.attr.link)
ctx.actions.symlink(output = symlink, target_path = ctx.attr.target)
return [DefaultInfo(files = depset([symlink]))]

create_fake_symlink = rule(
implementation = _create_fake_symlink_impl,
attrs = {
"link": attr.string(mandatory = True),
"target": attr.string(mandatory = True),
},
)
7 changes: 7 additions & 0 deletions tests/zip/zip_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ def test_compression_stored(self):
{"filename": "loremipsum.txt", "crc": LOREM_CRC, "size": 543},
])

def test_symlink(self):
self.assertZipFileContent("test_zip_symlink.zip", [
{"filename": "BUILD", "islink": False},
{"filename": "fake_symlink", "islink": True}, # raw symlink -> keep symlink
{"filename": "outer_BUILD", "islink": False},# nonraw symlink -> copy
])



if __name__ == "__main__":
Expand Down
13 changes: 12 additions & 1 deletion tests/zip/zip_test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
MSDOS_DIR_BIT = 0x10
UNIX_RWX_BITS = 0o777
UNIX_RX_BITS = 0o555
UNIX_SYMLINK_BIT = 0o120000

# The ZIP epoch date: (1980, 1, 1, 0, 0, 0)
_ZIP_EPOCH_DT = datetime.datetime(1980, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
Expand Down Expand Up @@ -77,7 +78,17 @@ def assertZipFileContent(self, zip_file, content):
oct(expected.get("attr", 0o755)))
elif "isexe" in expected:
got_mode = (info.external_attr >> 16) & UNIX_RX_BITS
self.assertEqual(oct(got_mode), oct(UNIX_RX_BITS))
if expected['isexe']:
self.assertEqual(oct(got_mode), oct(UNIX_RX_BITS))
else:
self.assertNotEqual(oct(got_mode), oct(UNIX_RX_BITS))
elif "islink" in expected:
got_mode = (info.external_attr >> 16) & UNIX_SYMLINK_BIT
if expected['islink']:
self.assertEqual(oct(got_mode), oct(UNIX_SYMLINK_BIT))
else:
self.assertNotEqual(oct(got_mode), oct(UNIX_SYMLINK_BIT))

elif "size" in expected:
self.assertEqual(info.compress_size, expected["size"])

Expand Down