Skip to content

Commit 85f6bf3

Browse files
authored
Switch tar verification to a manifest comparison. (#4458)
This removes the install marker-relative path checks, and replaces it with bidirectional verification: previously, files in the tar file had to be in install data, but there was no check that files in install data were all in the tar.
1 parent d944347 commit 85f6bf3

File tree

3 files changed

+49
-65
lines changed

3 files changed

+49
-65
lines changed

toolchain/install/BUILD

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
66
load("//bazel/cc_toolchains:defs.bzl", "cc_env")
7+
load("//bazel/manifest:defs.bzl", "manifest")
78
load("install_filegroups.bzl", "install_filegroup", "install_symlink", "install_target", "make_install_filegroups")
89
load("pkg_helpers.bzl", "pkg_naming_variables", "pkg_tar_and_test")
910
load("run_tool.bzl", "run_tool")
@@ -145,6 +146,11 @@ make_install_filegroups(
145146
prefix = "prefix_root",
146147
)
147148

149+
manifest(
150+
name = "install_data_manifest.txt",
151+
srcs = [":install_data"],
152+
)
153+
148154
pkg_naming_variables(
149155
name = "packaging_variables",
150156
)
@@ -157,18 +163,12 @@ pkg_naming_variables(
157163
# `carbon_toolchain_tar_gz_rule`.
158164
pkg_tar_and_test(
159165
srcs = [":pkg_data"],
166+
install_data_manifest = ":install_data_manifest.txt",
160167
name_base = "carbon_toolchain",
161168
package_dir = "carbon_toolchain-$(version)",
162169
package_file_name_base = "carbon_toolchain-$(version)",
163170
package_variables = ":packaging_variables",
164171
stamp = -1, # Allow `--stamp` builds to produce file timestamps.
165-
test_data = [
166-
":install_data",
167-
],
168-
# TODO: This is used to make sure that tar files are in install_data (one
169-
# direction). Replace with a check that the files in install_data and tar
170-
# match (bidirectional).
171-
test_install_marker = "prefix_root/lib/carbon/carbon_install.txt",
172172
)
173173

174174
# Support `bazel run` on specific binaries.

toolchain/install/pkg_helpers.bzl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pkg_naming_variables = rule(
2525
attrs = VERSION_ATTRS,
2626
)
2727

28-
def pkg_tar_and_test(name_base, package_file_name_base, test_data, test_install_marker, **kwargs):
28+
def pkg_tar_and_test(name_base, package_file_name_base, install_data_manifest, **kwargs):
2929
"""Create a `pkg_tar` and a test for both `.tar` and `.tar.gz` extensions.
3030
3131
Args:
@@ -35,10 +35,8 @@ def pkg_tar_and_test(name_base, package_file_name_base, test_data, test_install_
3535
package_file_name_base:
3636
The base of the `package_file_name` attribute to `pkg_tar`. The file
3737
extensions will be appended after a `.`.
38-
test_data:
39-
The test data to verify the tar file against.
40-
test_install_marker:
41-
The install marker within the test data to locate the installation.
38+
install_data_manifest:
39+
The install data manifest file to compare with.
4240
**kwargs:
4341
Passed to `pkg_tar` for all the rest of its attributes.
4442
"""
@@ -58,11 +56,11 @@ def pkg_tar_and_test(name_base, package_file_name_base, test_data, test_install_
5856
name = name_base + "_" + target_ext + "_test",
5957
size = "small",
6058
srcs = ["toolchain_tar_test.py"],
61-
data = [":" + tar_target, test_install_marker] + test_data,
62-
args = [
63-
"$(location :{})".format(tar_target),
64-
"$(location {})".format(test_install_marker),
65-
],
59+
data = [":" + tar_target, install_data_manifest],
60+
env = {
61+
"INSTALL_DATA_MANIFEST": "$(location {})".format(install_data_manifest),
62+
"TAR_FILE": "$(location :{})".format(tar_target),
63+
},
6664
main = "toolchain_tar_test.py",
6765
# The compressed tar is slow, exclude building and testing that.
6866
tags = ["manual"] if file_ext == "tar.gz" else [],

toolchain/install/toolchain_tar_test.py

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,43 @@
88
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
99
"""
1010

11-
import argparse
12-
import sys
1311
from pathlib import Path
12+
import os
13+
import re
1414
import tarfile
15-
16-
17-
def main() -> None:
18-
parser = argparse.ArgumentParser(description=__doc__)
19-
parser.add_argument(
20-
"tar_file",
21-
type=Path,
22-
help="The tar file to test.",
23-
)
24-
parser.add_argument(
25-
"install_marker",
26-
type=Path,
27-
help="The path of the install marker in a prefix root to test against.",
28-
)
29-
args = parser.parse_args()
30-
31-
# Locate the prefix root from the install marker.
32-
if not args.install_marker.exists():
33-
sys.exit("ERROR: No install marker: " + args.install_marker)
34-
prefix_root_path = args.install_marker.parents[2]
35-
36-
# First check that every file and directory in the tar file exists in our
37-
# prefix root, and build a set of those paths.
38-
installed_paths = set()
39-
with tarfile.open(args.tar_file) as tar:
40-
for tarinfo in tar:
41-
relative_path = Path(*Path(tarinfo.name).parts[1:])
42-
installed_paths.add(relative_path)
43-
if not prefix_root_path.joinpath(relative_path).exists():
44-
sys.exit(
45-
"ERROR: File `{0}` is not in prefix root: `{1}`".format(
46-
tarinfo.name, prefix_root_path
47-
)
48-
)
49-
50-
# If we found an empty tar file, it's always an error.
51-
if len(installed_paths) == 0:
52-
sys.exit("ERROR: Tar file `{0}` was empty.".format(args.tar_file))
53-
54-
# Now check that every file and directory in the prefix root is in that set.
55-
for prefix_path in prefix_root_path.glob("**/*"):
56-
relative_path = prefix_path.relative_to(prefix_root_path)
57-
if relative_path not in installed_paths:
58-
sys.exit(
59-
"ERROR: File `{0}` is not in tar file.".format(relative_path)
15+
import unittest
16+
17+
18+
class ToolchainTarTest(unittest.TestCase):
19+
def test_tar(self) -> None:
20+
install_data_manifest = Path(os.environ["INSTALL_DATA_MANIFEST"])
21+
tar_file = Path(os.environ["TAR_FILE"])
22+
23+
# Gather install data files.
24+
with open(install_data_manifest) as manifest:
25+
# Remove everything up to and including `prefix_root`.
26+
install_files = set(
27+
[
28+
re.sub("^.*/prefix_root/", "", entry.strip())
29+
for entry in manifest.readlines()
30+
]
6031
)
32+
self.assertTrue(install_files, f"`{install_data_manifest}` is empty.")
33+
34+
# Gather tar files.
35+
with tarfile.open(tar_file) as tar:
36+
# Remove the first path component.
37+
tar_files = set(
38+
[
39+
str(Path(*Path(tarinfo.name).parts[1:]))
40+
for tarinfo in tar
41+
if not tarinfo.isdir()
42+
]
43+
)
44+
self.assertTrue(tar_files, f"`{tar_file}` is empty.")
45+
46+
self.assertSetEqual(install_files, tar_files)
6147

6248

6349
if __name__ == "__main__":
64-
main()
50+
unittest.main()

0 commit comments

Comments
 (0)