Skip to content

Commit 3660b74

Browse files
Claude Botclaude
andcommitted
fix: don't create empty node_modules when no dependencies exist
Fixes #5392 When running `bun install` on a package.json with no dependencies, an empty `node_modules` folder was being created. This change adds checks in both hoisted and isolated install strategies to skip node_modules creation when there are no packages to install. Changes: - Check `hoisted_dependencies.items.len` in hoisted install - Check `store.entries.len` in isolated install - Return early with empty Summary if no dependencies - Add regression test that verifies no node_modules created when empty 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0a307ed commit 3660b74

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/install/hoisted_install.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ pub fn installHoistedPackages(
4343
}
4444
}
4545

46+
// If there are no dependencies to install, don't create node_modules
47+
if (this.lockfile.buffers.hoisted_dependencies.items.len == 0) {
48+
return PackageInstall.Summary{};
49+
}
50+
4651
// If there was already a valid lockfile and so we did not resolve, i.e. there was zero network activity
4752
// the packages could still not be in the cache dir
4853
// this would be a common scenario in a CI environment

src/install/isolated_install.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ pub fn installIsolatedPackages(
614614
};
615615
};
616616

617+
// If there are no packages to install, don't create node_modules
618+
if (store.entries.len == 0) {
619+
return PackageInstall.Summary{};
620+
}
621+
617622
// setup node_modules/.bun
618623
const is_new_bun_modules = is_new_bun_modules: {
619624
const node_modules_path = bun.OSPathLiteral("node_modules");

test/regression/issue/5392.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { expect, test } from "bun:test";
2+
import { bunEnv, bunExe, tempDir } from "harness";
3+
import * as fs from "node:fs";
4+
5+
test("bun install should not create node_modules when there are no dependencies - issue #5392", async () => {
6+
using dir = tempDir("issue-5392", {
7+
"package.json": JSON.stringify({
8+
name: "bun-install-test",
9+
module: "index.ts",
10+
type: "module",
11+
devDependencies: {},
12+
peerDependencies: {},
13+
}),
14+
});
15+
16+
await using proc = Bun.spawn({
17+
cmd: [bunExe(), "install"],
18+
env: bunEnv,
19+
cwd: String(dir),
20+
stderr: "pipe",
21+
stdout: "pipe",
22+
});
23+
24+
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
25+
26+
// node_modules should not exist
27+
const nodeModulesPath = `${dir}/node_modules`;
28+
const nodeModulesExists = fs.existsSync(nodeModulesPath);
29+
30+
expect(nodeModulesExists).toBe(false);
31+
expect(exitCode).toBe(0);
32+
});
33+
34+
test("bun install should create node_modules when there are dependencies", async () => {
35+
using dir = tempDir("issue-5392-with-deps", {
36+
"package.json": JSON.stringify({
37+
name: "bun-install-test-with-deps",
38+
dependencies: {
39+
"is-odd": "^3.0.1",
40+
},
41+
}),
42+
});
43+
44+
await using proc = Bun.spawn({
45+
cmd: [bunExe(), "install"],
46+
env: bunEnv,
47+
cwd: String(dir),
48+
stderr: "pipe",
49+
stdout: "pipe",
50+
});
51+
52+
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
53+
54+
// node_modules should exist
55+
const nodeModulesPath = `${dir}/node_modules`;
56+
const nodeModulesExists = fs.existsSync(nodeModulesPath);
57+
58+
expect(nodeModulesExists).toBe(true);
59+
expect(exitCode).toBe(0);
60+
});

0 commit comments

Comments
 (0)