mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 20:09:04 +00:00
fix(install): follow symlinks when resolving workspace glob patterns
When using glob patterns like `./*` or `packages/*` in the workspaces array, symlinked directories pointing to packages outside the monorepo were not being discovered. This was because the GlobWalker was initialized with `follow_symlinks: false`. This change enables symlink following in the workspace glob walker, allowing workspace packages that are symlinks to be properly discovered and resolved. Fixes #25801 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -226,7 +226,7 @@ pub fn processNamesArray(
|
||||
var walker: GlobWalker = .{};
|
||||
var cwd = bun.path.dirname(source.path.text, .auto);
|
||||
cwd = if (bun.strings.eql(cwd, "")) bun.fs.FileSystem.instance.top_level_dir else cwd;
|
||||
if ((try walker.initWithCwd(&arena, glob_pattern, cwd, false, false, false, false, true)).asErr()) |e| {
|
||||
if ((try walker.initWithCwd(&arena, glob_pattern, cwd, false, false, true, false, true)).asErr()) |e| {
|
||||
log.addErrorFmt(
|
||||
source,
|
||||
loc,
|
||||
|
||||
96
test/regression/issue/25801.test.ts
Normal file
96
test/regression/issue/25801.test.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
// https://github.com/oven-sh/bun/issues/25801
|
||||
// Workspace packages that are symlinks to directories outside the monorepo
|
||||
// should be discovered during `bun install` when using glob patterns.
|
||||
|
||||
import { expect, test } from "bun:test";
|
||||
import { symlinkSync } from "fs";
|
||||
import { bunEnv, bunExe, tempDir } from "harness";
|
||||
import { join } from "path";
|
||||
|
||||
test("workspace glob patterns should follow symlinks to external directories", async () => {
|
||||
// Create a temporary directory for the external package (outside the monorepo)
|
||||
using externalPkgDir = tempDir("external-pkg", {
|
||||
"package.json": JSON.stringify({
|
||||
name: "backend",
|
||||
version: "1.0.0",
|
||||
}),
|
||||
});
|
||||
|
||||
// Create the monorepo with a glob pattern in workspaces
|
||||
using monorepoDir = tempDir("monorepo", {
|
||||
"package.json": JSON.stringify({
|
||||
name: "monorepo-test",
|
||||
workspaces: ["./*"],
|
||||
dependencies: {
|
||||
backend: "workspace:*",
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
// Create a symlink inside the monorepo pointing to the external package
|
||||
symlinkSync(String(externalPkgDir), join(String(monorepoDir), "backend"));
|
||||
|
||||
// Run bun install
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: String(monorepoDir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
// Should not fail with "Workspace dependency 'backend' not found"
|
||||
expect(stderr).not.toContain("Workspace dependency");
|
||||
expect(stderr).not.toContain("not found");
|
||||
|
||||
// Should succeed
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("workspace glob patterns should follow symlinks in packages directory", async () => {
|
||||
// Create an external package to be symlinked
|
||||
using externalPkgDir = tempDir("external-alias-pkg", {
|
||||
"package.json": JSON.stringify({
|
||||
name: "pkg-alias",
|
||||
version: "2.0.0",
|
||||
}),
|
||||
});
|
||||
|
||||
// Create a monorepo with packages/* glob pattern
|
||||
using monorepoDir = tempDir("monorepo-internal", {
|
||||
"package.json": JSON.stringify({
|
||||
name: "monorepo-internal",
|
||||
workspaces: ["packages/*"],
|
||||
dependencies: {
|
||||
"pkg-alias": "workspace:*",
|
||||
},
|
||||
}),
|
||||
"packages/real-pkg/package.json": JSON.stringify({
|
||||
name: "real-pkg",
|
||||
version: "1.0.0",
|
||||
}),
|
||||
});
|
||||
|
||||
// Create a symlink to the external package inside packages/
|
||||
symlinkSync(String(externalPkgDir), join(String(monorepoDir), "packages", "pkg-alias"));
|
||||
|
||||
// Run bun install
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "install"],
|
||||
cwd: String(monorepoDir),
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
// Should not fail with workspace dependency errors
|
||||
expect(stderr).not.toContain("Workspace dependency");
|
||||
expect(stderr).not.toContain("not found");
|
||||
|
||||
// Should succeed
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
Reference in New Issue
Block a user