Files
bun.sh/test/cli/install/git-dependency.test.ts
Claude 04d498cfc4 Refactor git operations from blocking to async event loop
This PR refactors git operations in `bun install` from blocking threadpool calls using `std.process.Child` to non-blocking event loop integration using `bun.spawn`.

## Changes

- Created `GitCommandRunner` for async git command execution with event loop integration
- Replaced blocking `fork()` calls with async `bun.spawn`
- Implemented proper two-phase checkout (clone --no-checkout, then checkout)
- Moved post-checkout operations (.git deletion, .bun-tag creation) to appropriate places
- Fixed argv construction to use "git" instead of hardcoded paths
- Added comprehensive tests for git dependencies

## Technical Details

The new implementation:
- Uses tagged pointer unions for process exit handlers
- Properly manages pending task counting for event loop
- Handles both clone and checkout operations asynchronously
- Maintains backward compatibility with existing URL handling

All git operations now integrate properly with Bun's event loop, eliminating blocking operations and improving performance.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-12 00:10:29 +02:00

90 lines
2.5 KiB
TypeScript

import { spawnSync } from "bun";
import { expect, test } from "bun:test";
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
import { join } from "path";
import { existsSync } from "fs";
test("install github dependency", async () => {
const dir = tempDirWithFiles("test-github-install", {
"package.json": JSON.stringify({
name: "test-github-install",
dependencies: {
// Using github: shorthand which downloads as tarball
"awesome-bun": "github:oven-sh/awesome-bun",
},
}),
});
const result = spawnSync({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
expect(result.exitCode).toBe(0);
expect(result.stderr.toString()).not.toContain("error");
// Check that the package was installed
const packagePath = join(dir, "node_modules", "awesome-bun");
expect(existsSync(packagePath)).toBe(true);
// Should have README.md
const readmePath = join(packagePath, "README.md");
expect(existsSync(readmePath)).toBe(true);
});
test("install git+https URL dependency", async () => {
const dir = tempDirWithFiles("test-git-url", {
"package.json": JSON.stringify({
name: "test-git-url",
dependencies: {
// Using git+ prefix which triggers git clone
"bun-types": "git+https://github.com/oven-sh/bun.git#main",
},
}),
});
const result = spawnSync({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
expect(result.exitCode).toBe(0);
expect(result.stderr.toString()).not.toContain("error");
// Check that the package was installed
const packagePath = join(dir, "node_modules", "bun-types");
expect(existsSync(packagePath)).toBe(true);
});
test("install git URL without commit hash", async () => {
const dir = tempDirWithFiles("test-git-no-hash", {
"package.json": JSON.stringify({
name: "test-git-no-hash",
dependencies: {
// Using HEAD of default branch
"awesome-bun-2": "git+https://github.com/oven-sh/awesome-bun.git",
},
}),
});
const result = spawnSync({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: dir,
stdout: "pipe",
stderr: "pipe",
});
expect(result.exitCode).toBe(0);
expect(result.stderr.toString()).not.toContain("error");
// Check that the package was installed
const packagePath = join(dir, "node_modules", "awesome-bun-2");
expect(existsSync(packagePath)).toBe(true);
});