Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
2ca6744041 fix: resolve ENOENT error when using --filter with workspace packages having mixed case names
Fixed an issue where workspace filtering would fail with ENOENT when package
directories had mixed case names (e.g., camelCase, kebab-case). The problem
was in the glob walker's directory iterator which was using lowercase hash map
keys instead of the original case-preserved directory names when constructing
file paths.

The fix changes the DirEntryAccessor to use `nextval.value_ptr.*.base()`
(original case) instead of `nextval.key_ptr.*` (lowercase key) when iterating
over directory entries. This ensures that file system operations use the
correct case-sensitive directory names.

Fixes: https://github.com/oven-sh/bun/issues/21670

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 04:53:20 +00:00
2 changed files with 133 additions and 1 deletions

View File

@@ -211,7 +211,7 @@ pub const DirEntryAccessor = struct {
pub inline fn next(self: *DirIter) Maybe(?IterResult) {
if (self.value) |*value| {
const nextval = value.next() orelse return .{ .result = null };
const name = nextval.key_ptr.*;
const name = nextval.value_ptr.*.base();
const kind = nextval.value_ptr.*.kind(&FS.instance.fs, true);
const fskind = switch (kind) {
.file => std.fs.File.Kind.file,

View File

@@ -0,0 +1,132 @@
import { test, expect } from "bun:test";
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
test("--filter should work with packages containing mixed case names", async () => {
const dir = tempDirWithFiles("filter-workspace-case-sensitivity", {
"package.json": JSON.stringify({
name: "test-workspace",
workspaces: ["packages/*"],
private: true,
}),
"packages/camelCase/package.json": JSON.stringify({
name: "camelCase",
version: "1.0.0",
scripts: {
test: "echo 'camelCase test passed'",
},
}),
"packages/kebab-case/package.json": JSON.stringify({
name: "kebab-case",
version: "1.0.0",
scripts: {
test: "echo 'kebab-case test passed'",
},
}),
"packages/UPPERCASE/package.json": JSON.stringify({
name: "UPPERCASE",
version: "1.0.0",
scripts: {
test: "echo 'UPPERCASE test passed'",
},
}),
});
// Install workspace dependencies
const proc = Bun.spawn({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
await proc.exited;
// Test filtering specific packages by name
for (const packageName of ["camelCase", "kebab-case", "UPPERCASE"]) {
const proc = Bun.spawn({
cmd: [bunExe(), "run", "--filter", packageName, "test"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([
proc.stdout.text(),
proc.stderr.text(),
proc.exited,
]);
expect(exitCode).toBe(0);
expect(stdout).toContain(`${packageName} test passed`);
expect(stderr).not.toContain("error: ENOENT");
}
// Test filtering all packages
const proc2 = Bun.spawn({
cmd: [bunExe(), "run", "--filter", "*", "test"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout2, stderr2, exitCode2] = await Promise.all([
proc2.stdout.text(),
proc2.stderr.text(),
proc2.exited,
]);
expect(exitCode2).toBe(0);
expect(stdout2).toContain("camelCase test passed");
expect(stdout2).toContain("kebab-case test passed");
expect(stdout2).toContain("UPPERCASE test passed");
expect(stderr2).not.toContain("error: ENOENT");
});
test("--filter should work with directory names that differ in case from package names", async () => {
const dir = tempDirWithFiles("filter-workspace-dir-case", {
"package.json": JSON.stringify({
name: "test-workspace",
workspaces: ["packages/*"],
private: true,
}),
// Directory name is lowercase but package name has mixed case
"packages/mixedcase/package.json": JSON.stringify({
name: "MixedCase",
version: "1.0.0",
scripts: {
test: "echo 'MixedCase directory test passed'",
},
}),
});
// Install workspace dependencies
const proc = Bun.spawn({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
await proc.exited;
// Test filtering by package name (not directory name)
const proc2 = Bun.spawn({
cmd: [bunExe(), "run", "--filter", "MixedCase", "test"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([
proc2.stdout.text(),
proc2.stderr.text(),
proc2.exited,
]);
expect(exitCode).toBe(0);
expect(stdout).toContain("MixedCase directory test passed");
expect(stderr).not.toContain("error: ENOENT");
});