summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraiuto <aiuto@google.com>2022-09-12 23:58:39 -0400
committerGitHub <noreply@github.com>2022-09-12 23:58:39 -0400
commit46eabd36cf957920406d2a8b05f178a0bd0f851a (patch)
tree6a66193d3343ec8249b8dfd1d30177f782767017
parent60dbd92d1ce3338cbb8adcb8ae8800ea3421d7b8 (diff)
downloadbazelbuild-rules_pkg-46eabd36cf957920406d2a8b05f178a0bd0f851a.tar.gz
Create an example of the kind of link tree Node users must create (#603)
* Create an example of the kind of link tree Node users muse create
-rw-r--r--pkg/private/pkg_files.bzl15
-rw-r--r--tests/BUILD9
-rw-r--r--tests/mappings/BUILD29
-rwxr-xr-xtests/mappings/node_modules_manifest.golden9
-rw-r--r--tests/tar/BUILD53
l---------tests/testdata/outer_BUILD1
-rw-r--r--tests/util/create_directory_with_contents.py10
-rw-r--r--tests/util/defs.bzl42
8 files changed, 156 insertions, 12 deletions
diff --git a/pkg/private/pkg_files.bzl b/pkg/private/pkg_files.bzl
index 5922b35..75e12db 100644
--- a/pkg/private/pkg_files.bzl
+++ b/pkg/private/pkg_files.bzl
@@ -127,12 +127,15 @@ def _process_pkg_symlink(content_map, pkg_symlink_info, origin, default_mode, de
)
def _process_pkg_filegroup(content_map, pkg_filegroup_info, origin, default_mode, default_user, default_group):
- for d in pkg_filegroup_info.pkg_dirs:
- _process_pkg_dirs(content_map, d[0], d[1], default_mode, default_user, default_group)
- for pf in pkg_filegroup_info.pkg_files:
- _process_pkg_files(content_map, pf[0], pf[1], default_mode, default_user, default_group)
- for psl in pkg_filegroup_info.pkg_symlinks:
- _process_pkg_symlink(content_map, psl[0], psl[1], default_mode, default_user, default_group)
+ if hasattr(pkg_filegroup_info, "pkg_dirs"):
+ for d in pkg_filegroup_info.pkg_dirs:
+ _process_pkg_dirs(content_map, d[0], d[1], default_mode, default_user, default_group)
+ if hasattr(pkg_filegroup_info, "pkg_files"):
+ for pf in pkg_filegroup_info.pkg_files:
+ _process_pkg_files(content_map, pf[0], pf[1], default_mode, default_user, default_group)
+ if hasattr(pkg_filegroup_info, "pkg_symlinks"):
+ for psl in pkg_filegroup_info.pkg_symlinks:
+ _process_pkg_symlink(content_map, psl[0], psl[1], default_mode, default_user, default_group)
def process_src(content_map, files, src, origin, default_mode, default_user,
default_group):
diff --git a/tests/BUILD b/tests/BUILD
index d2bd1f1..c6666c6 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -40,6 +40,15 @@ filegroup(
)
filegroup(
+ name = "file_and_link",
+ srcs = [
+ "BUILD",
+ "testdata/outer_BUILD",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
name = "glob_for_texts",
srcs = glob(["**/*.txt"]),
)
diff --git a/tests/mappings/BUILD b/tests/mappings/BUILD
index b742ff5..6ebee0a 100644
--- a/tests/mappings/BUILD
+++ b/tests/mappings/BUILD
@@ -27,7 +27,7 @@ load(
"pkg_mkdirs",
"strip_prefix",
)
-load("//tests/util:defs.bzl", "directory", "write_content_manifest")
+load("//tests/util:defs.bzl", "directory", "link_tree", "write_content_manifest")
load("@rules_python//python:defs.bzl", "py_test")
package(default_applicable_licenses = ["//:license"])
@@ -158,3 +158,30 @@ manifest_golden_test(
expected = "glob_for_texts_manifest.golden",
target = "glob_for_texts_manifest",
)
+
+link_tree(
+ name = "node_modules",
+ links = {
+ "foo": ".pnpm/foo@1.0.0/node_modules/foo",
+ ".pnpm/bar@1.0.0/node_modules/bar": "STORE/bar",
+ ".pnpm/bar@1.0.0/node_modules/qar": "../../qar@2.0.0/node_modules/qar",
+ ".pnpm/foo@1.0.0/node_modules/foo": "STORE/foo",
+ ".pnpm/foo@1.0.0/node_modules/bar": "../../bar@1.0.0/node_modules/bar",
+ ".pnpm/foo@1.0.0/node_modules/qar": "../../qar@2.0.0/node_modules/qar",
+ ".pnpm/qar@2.0.0/node_modules/qar": "STORE/qar",
+ },
+ package_dir = "node_modules",
+)
+
+write_content_manifest(
+ name = "node_modules_manifest",
+ srcs = [
+ ":node_modules",
+ ],
+)
+
+manifest_golden_test(
+ name = "link_tree_test",
+ expected = "node_modules_manifest.golden",
+ target = "node_modules_manifest",
+)
diff --git a/tests/mappings/node_modules_manifest.golden b/tests/mappings/node_modules_manifest.golden
new file mode 100755
index 0000000..fb55d06
--- /dev/null
+++ b/tests/mappings/node_modules_manifest.golden
@@ -0,0 +1,9 @@
+[
+[1,"node_modules/.pnpm/bar@1.0.0/node_modules/bar","STORE/bar","",null,null],
+[1,"node_modules/.pnpm/bar@1.0.0/node_modules/qar","../../qar@2.0.0/node_modules/qar","",null,null],
+[1,"node_modules/.pnpm/foo@1.0.0/node_modules/bar","../../bar@1.0.0/node_modules/bar","",null,null],
+[1,"node_modules/.pnpm/foo@1.0.0/node_modules/foo","STORE/foo","",null,null],
+[1,"node_modules/.pnpm/foo@1.0.0/node_modules/qar","../../qar@2.0.0/node_modules/qar","",null,null],
+[1,"node_modules/.pnpm/qar@2.0.0/node_modules/qar","STORE/qar","",null,null],
+[1,"node_modules/foo",".pnpm/foo@1.0.0/node_modules/foo","",null,null]
+]
diff --git a/tests/tar/BUILD b/tests/tar/BUILD
index 8fc1abf..34defdc 100644
--- a/tests/tar/BUILD
+++ b/tests/tar/BUILD
@@ -18,11 +18,14 @@
load("//pkg:mappings.bzl", "pkg_files", "strip_prefix")
load("//pkg/private/tar:tar.bzl", "SUPPORTED_TAR_COMPRESSIONS", "pkg_tar")
load("//tests:my_package_name.bzl", "my_package_naming")
-load("//tests/util:defs.bzl", "directory", "fake_artifact")
+load("//tests/util:defs.bzl", "directory", "link_tree", "fake_artifact")
load("@rules_python//python:defs.bzl", "py_test")
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
-package(default_applicable_licenses = ["//:license"])
+package(
+ default_applicable_licenses = ["//:license"],
+ default_visibility = ["//visibility:private"],
+)
py_test(
name = "tar_writer_test",
@@ -396,3 +399,49 @@ py_test(
"@bazel_tools//tools/python/runfiles",
],
)
+
+link_tree(
+ name = "node_modules",
+ links = {
+ "foo": ".pnpm/foo@1.0.0/node_modules/foo",
+ ".pnpm/bar@1.0.0/node_modules/bar": "STORE/bar",
+ ".pnpm/foo@1.0.0/node_modules/foo": "STORE/foo",
+ ".pnpm/foo@1.0.0/node_modules/bar": "../../bar@1.0.0/node_modules/bar",
+ },
+ package_dir = "node_modules",
+)
+
+directory(
+ name = "tree_artifact_with_links",
+ contents = "hello there",
+ filenames = [
+ "foo/hello.txt",
+ "foo/bar/baz",
+ ],
+ links = {
+ "foo/bar/hello": "../hello.txt",
+ "foo/bar/alt_baz": "baz",
+ "foo/alt_baz": "bar/baz",
+ },
+)
+
+
+# This target has symlinks 3 ways.
+# - mklinks rules.
+# - source files that are symlinks
+# - tree artifacts
+pkg_tar(
+ name = "relative_links_tar",
+ srcs = [
+ ":node_modules",
+ ":tree_artifact_with_links",
+ "//tests:file_and_link",
+ ],
+)
+
+pkg_tar(
+ name = "relative_links_re_tar",
+ deps = [
+ ":relative_links_tar",
+ ],
+)
diff --git a/tests/testdata/outer_BUILD b/tests/testdata/outer_BUILD
new file mode 120000
index 0000000..c447d20
--- /dev/null
+++ b/tests/testdata/outer_BUILD
@@ -0,0 +1 @@
+../BUILD \ No newline at end of file
diff --git a/tests/util/create_directory_with_contents.py b/tests/util/create_directory_with_contents.py
index 4e436ad..7138884 100644
--- a/tests/util/create_directory_with_contents.py
+++ b/tests/util/create_directory_with_contents.py
@@ -36,9 +36,13 @@ for a in rest_args_iter:
os.makedirs(dirname, exist_ok=True)
for fname, contents in files_contents_map.items():
+ path = os.path.join(dirname, fname)
os.makedirs(
- os.path.join(dirname, os.path.dirname(fname)),
+ os.path.dirname(path),
exist_ok=True,
)
- with open(os.path.join(dirname, fname), 'w') as fh:
- fh.write(contents)
+ if contents.startswith('@@'):
+ os.symlink(contents[2:], path)
+ else:
+ with open(path, 'w') as fh:
+ fh.write(contents)
diff --git a/tests/util/defs.bzl b/tests/util/defs.bzl
index 94076e3..eb3124c 100644
--- a/tests/util/defs.bzl
+++ b/tests/util/defs.bzl
@@ -15,6 +15,7 @@
"""Rules to aid testing"""
load("//pkg/private:pkg_files.bzl", "add_label_list", "write_manifest")
+load("//pkg:providers.bzl", "PackageFilegroupInfo", "PackageSymlinkInfo")
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
load("@rules_python//python:defs.bzl", "py_binary")
@@ -24,10 +25,15 @@ def _directory_impl(ctx):
args = ctx.actions.args()
args.add(out_dir_file.path)
+ # This helper is horrible. We should pass all the args in files.
for fn in ctx.attr.filenames:
args.add(fn)
args.add(ctx.attr.contents)
+ for link, target in ctx.attr.links.items():
+ args.add(link)
+ args.add('@@' + target)
+
ctx.actions.run(
outputs = [out_dir_file],
inputs = [],
@@ -49,6 +55,11 @@ creation capabilities are "unsound".
Paths containing directories will also have the intermediate directories created too.""",
),
+ "links": attr.string_dict(
+ doc = """Set of (virtual) links to create.
+
+The keys of links are paths to create. The values are the target of the links.""",
+ ),
"contents": attr.string(),
"outdir": attr.string(),
"_dir_creator": attr.label(
@@ -101,6 +112,37 @@ cc_binary in complexity, but does not depend on a large toolchain.""",
},
)
+def _link_tree_impl(ctx):
+ links = []
+ prefix = ctx.attr.package_dir or ""
+ if prefix and not prefix.endswith('/'):
+ prefix = prefix + "/"
+ for link, target in ctx.attr.links.items():
+ print(' %s -> %s ' % (link, target))
+ links.append(
+ (PackageSymlinkInfo(destination = prefix + link, target = target),
+ ctx.label))
+ return [PackageFilegroupInfo(pkg_symlinks = links)]
+
+link_tree = rule(
+ doc = """Helper rule to create a lot of fake symlinks.
+
+The inspiration is to create test data for the kinds of layouts needed by
+nodejs. See. https://pnpm.io/symlinked-node-modules-structure
+ """,
+ implementation = _link_tree_impl,
+ attrs = {
+ "links": attr.string_dict(
+ doc = """Set of (virtual) links to create.
+
+The keys of links are paths to create. The values are the target of the links.""",
+ mandatory = True,
+ ),
+ "package_dir": attr.string(doc = """Prefix to apply to all link paths."""),
+ },
+ provides = [PackageFilegroupInfo],
+)
+
def _write_content_manifest_impl(ctx):
content_map = {} # content handled in the manifest
file_deps = [] # inputs we depend on