fix: bun_install adds node_modules to each directory
This commit is contained in:
@@ -1,5 +1,102 @@
|
||||
"""Repository-rule based bun_install implementation."""
|
||||
|
||||
def _segment_matches(name, pattern):
|
||||
if pattern == "*":
|
||||
return True
|
||||
|
||||
if "*" not in pattern:
|
||||
return name == pattern
|
||||
|
||||
parts = pattern.split("*")
|
||||
if len(parts) == 1:
|
||||
return name == pattern
|
||||
|
||||
pos = 0
|
||||
anchored_start = not pattern.startswith("*")
|
||||
anchored_end = not pattern.endswith("*")
|
||||
|
||||
for i, part in enumerate(parts):
|
||||
if not part:
|
||||
continue
|
||||
|
||||
match_index = name.find(part, pos)
|
||||
if match_index < 0:
|
||||
return False
|
||||
|
||||
if i == 0 and anchored_start and match_index != 0:
|
||||
return False
|
||||
|
||||
pos = match_index + len(part)
|
||||
|
||||
if anchored_end and parts[-1] and not name.endswith(parts[-1]):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _walk_workspace_dirs(root, segments):
|
||||
matches = [root]
|
||||
|
||||
for segment in segments:
|
||||
if segment == "**":
|
||||
fail("bun_install: `**` is not supported in workspace patterns; use explicit segments or `*`")
|
||||
|
||||
next_matches = []
|
||||
for parent in matches:
|
||||
for child in parent.readdir():
|
||||
if child.is_dir and _segment_matches(child.basename, segment):
|
||||
next_matches.append(child)
|
||||
|
||||
matches = next_matches
|
||||
|
||||
return matches
|
||||
|
||||
def _workspace_patterns(repository_ctx, package_json):
|
||||
manifest = json.decode(repository_ctx.read(package_json))
|
||||
workspaces = manifest.get("workspaces", [])
|
||||
|
||||
if type(workspaces) == type({}):
|
||||
workspaces = workspaces.get("packages", [])
|
||||
|
||||
if type(workspaces) != type([]):
|
||||
fail("bun_install: `workspaces` must be a list or an object with a `packages` list")
|
||||
|
||||
patterns = []
|
||||
for pattern in workspaces:
|
||||
if type(pattern) != type(""):
|
||||
fail("bun_install: workspace pattern must be a string, got {}".format(type(pattern)))
|
||||
|
||||
normalized = "/".join([segment for segment in pattern.split("/") if segment and segment != "."])
|
||||
if normalized:
|
||||
patterns.append(normalized)
|
||||
|
||||
return patterns
|
||||
|
||||
def _materialize_workspace_packages(repository_ctx, package_json):
|
||||
package_root = package_json.dirname
|
||||
package_root_str = str(package_root)
|
||||
written = {}
|
||||
|
||||
for pattern in _workspace_patterns(repository_ctx, package_json):
|
||||
segments = pattern.split("/")
|
||||
for workspace_dir in _walk_workspace_dirs(package_root, segments):
|
||||
workspace_package_json = repository_ctx.path(str(workspace_dir) + "/package.json")
|
||||
if not workspace_package_json.exists:
|
||||
continue
|
||||
|
||||
workspace_dir_str = str(workspace_dir)
|
||||
if workspace_dir_str == package_root_str:
|
||||
continue
|
||||
|
||||
relative_dir = workspace_dir_str[len(package_root_str) + 1:]
|
||||
if relative_dir in written:
|
||||
continue
|
||||
|
||||
repository_ctx.file(
|
||||
relative_dir + "/package.json",
|
||||
repository_ctx.read(workspace_package_json),
|
||||
)
|
||||
written[relative_dir] = True
|
||||
|
||||
def _select_bun_binary(repository_ctx):
|
||||
os_name = repository_ctx.os.name.lower()
|
||||
arch = repository_ctx.os.arch.lower()
|
||||
@@ -35,8 +132,9 @@ def _bun_install_repository_impl(repository_ctx):
|
||||
if lockfile_name not in ["bun.lock", "bun.lockb"]:
|
||||
lockfile_name = "bun.lock"
|
||||
|
||||
repository_ctx.symlink(package_json, "package.json")
|
||||
repository_ctx.file("package.json", repository_ctx.read(package_json))
|
||||
repository_ctx.symlink(bun_lockfile, lockfile_name)
|
||||
_materialize_workspace_packages(repository_ctx, package_json)
|
||||
|
||||
result = repository_ctx.execute(
|
||||
[str(bun_bin), "--bun", "install", "--frozen-lockfile", "--no-progress"],
|
||||
|
||||
Reference in New Issue
Block a user