Skip to content

Commit

Permalink
Create an example of the kind of link tree Node users must create (#603)
Browse files Browse the repository at this point in the history
* Create an example of the kind of link tree Node users muse create
  • Loading branch information
aiuto authored Sep 13, 2022
1 parent 60dbd92 commit 46eabd3
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 12 deletions.
15 changes: 9 additions & 6 deletions pkg/private/pkg_files.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
9 changes: 9 additions & 0 deletions tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ filegroup(
visibility = ["//visibility:public"],
)

filegroup(
name = "file_and_link",
srcs = [
"BUILD",
"testdata/outer_BUILD",
],
visibility = ["//visibility:public"],
)

filegroup(
name = "glob_for_texts",
srcs = glob(["**/*.txt"]),
Expand Down
29 changes: 28 additions & 1 deletion tests/mappings/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down Expand Up @@ -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",
)
9 changes: 9 additions & 0 deletions tests/mappings/node_modules_manifest.golden
Original file line number Diff line number Diff line change
@@ -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]
]
53 changes: 51 additions & 2 deletions tests/tar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
],
)
1 change: 1 addition & 0 deletions tests/testdata/outer_BUILD
10 changes: 7 additions & 3 deletions tests/util/create_directory_with_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@
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)
42 changes: 42 additions & 0 deletions tests/util/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand All @@ -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 = [],
Expand All @@ -48,6 +54,11 @@ creation capabilities are "unsound".
doc = """Paths to create in the directory.
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(),
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 46eabd3

Please sign in to comment.