aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/install/resolvers/folder_resolver.zig31
-rw-r--r--test/bun.js/install/bun-link.test.ts142
-rwxr-xr-xtest/fixtures/bun-link-to-pkg-fixture/bun.lockbbin1549 -> 1527 bytes
3 files changed, 150 insertions, 23 deletions
diff --git a/src/install/resolvers/folder_resolver.zig b/src/install/resolvers/folder_resolver.zig
index 968ee57ca..c16f0c8ed 100644
--- a/src/install/resolvers/folder_resolver.zig
+++ b/src/install/resolvers/folder_resolver.zig
@@ -33,7 +33,7 @@ pub const FolderResolution = union(Tag) {
return std.hash.Wyhash.hash(0, normalized_path);
}
- pub fn NewResolver(comptime tag: Resolution.Tag) type {
+ fn NewResolver(comptime tag: Resolution.Tag) type {
return struct {
folder_path: string,
@@ -50,11 +50,10 @@ pub const FolderResolution = union(Tag) {
};
}
- pub const Resolver = NewResolver(Resolution.Tag.folder);
- pub const SymlinkResolver = NewResolver(Resolution.Tag.symlink);
- pub const WorkspaceResolver = NewResolver(Resolution.Tag.workspace);
- pub const CacheFolderResolver = struct {
- folder_path: []const u8 = "",
+ const Resolver = NewResolver(Resolution.Tag.folder);
+ const SymlinkResolver = NewResolver(Resolution.Tag.symlink);
+ const WorkspaceResolver = NewResolver(Resolution.Tag.workspace);
+ const CacheFolderResolver = struct {
version: Semver.Version,
pub fn resolve(this: @This(), comptime Builder: type, _: Builder, _: JSAst.Expr) !Resolution {
@@ -182,14 +181,18 @@ pub const FolderResolution = union(Tag) {
if (entry.found_existing) return entry.value_ptr.*;
const package: Lockfile.Package = switch (global_or_relative) {
- .global => readPackageJSONFromDisk(
- manager,
- abs,
- version,
- Features.link,
- SymlinkResolver,
- SymlinkResolver{ .folder_path = non_normalized_path },
- ),
+ .global => brk: {
+ var path: [bun.MAX_PATH_BYTES]u8 = undefined;
+ std.mem.copy(u8, &path, non_normalized_path);
+ break :brk readPackageJSONFromDisk(
+ manager,
+ abs,
+ version,
+ Features.link,
+ SymlinkResolver,
+ SymlinkResolver{ .folder_path = path[0..non_normalized_path.len] },
+ );
+ },
.relative => |tag| switch (tag) {
.folder => readPackageJSONFromDisk(
manager,
diff --git a/test/bun.js/install/bun-link.test.ts b/test/bun.js/install/bun-link.test.ts
index c2cf459e2..137242cc4 100644
--- a/test/bun.js/install/bun-link.test.ts
+++ b/test/bun.js/install/bun-link.test.ts
@@ -1,24 +1,35 @@
import { spawn } from "bun";
-import { afterEach, beforeEach, expect, it } from "bun:test";
+import { afterAll, afterEach, beforeAll, beforeEach, expect, it } from "bun:test";
import { bunExe } from "bunExe";
import { bunEnv as env } from "bunEnv";
-import { mkdtemp, realpath, rm, writeFile } from "fs/promises";
+import { access, mkdtemp, readlink, realpath, rm, writeFile } from "fs/promises";
import { basename, join } from "path";
import { tmpdir } from "os";
+import {
+ dummyAfterAll,
+ dummyAfterEach,
+ dummyBeforeAll,
+ dummyBeforeEach,
+ package_dir,
+ readdirSorted,
+} from "./dummy.registry";
-let package_dir, link_dir;
+beforeAll(dummyBeforeAll);
+afterAll(dummyAfterAll);
+
+let link_dir;
beforeEach(async () => {
link_dir = await mkdtemp(join(await realpath(tmpdir()), "bun-link.test"));
- package_dir = await mkdtemp(join(await realpath(tmpdir()), "bun-link.pkg"));
+ await dummyBeforeEach();
});
afterEach(async () => {
await rm(link_dir, { force: true, recursive: true });
- await rm(package_dir, { force: true, recursive: true });
+ await dummyAfterEach();
});
it("should link package", async () => {
- var link_name = basename(link_dir).slice("bun-link.".length);
+ const link_name = basename(link_dir).slice("bun-link.".length);
await writeFile(
join(link_dir, "package.json"),
JSON.stringify({
@@ -114,13 +125,12 @@ it("should link package", async () => {
const err4 = await new Response(stderr4).text();
expect(err4).toContain(`error: package "${link_name}" is not linked`);
expect(stdout4).toBeDefined();
- const out4 = await new Response(stdout4).text();
expect(await new Response(stdout4).text()).toBe("");
expect(await exited4).toBe(1);
});
it("should link scoped package", async () => {
- var link_name = `@${basename(link_dir).slice("bun-link.".length)}/foo`;
+ const link_name = `@${basename(link_dir).slice("bun-link.".length)}/foo`;
await writeFile(
join(link_dir, "package.json"),
JSON.stringify({
@@ -216,7 +226,121 @@ it("should link scoped package", async () => {
const err4 = await new Response(stderr4).text();
expect(err4).toContain(`error: package "${link_name}" is not linked`);
expect(stdout4).toBeDefined();
- const out4 = await new Response(stdout4).text();
expect(await new Response(stdout4).text()).toBe("");
expect(await exited4).toBe(1);
});
+
+it("should link dependency without crashing", async () => {
+ const link_name = basename(link_dir).slice("bun-link.".length) + "-really-long-name";
+ await writeFile(
+ join(link_dir, "package.json"),
+ JSON.stringify({
+ name: link_name,
+ version: "0.0.1",
+ bin: {
+ [link_name]: `${link_name}.js`,
+ },
+ }),
+ );
+ await writeFile(join(link_dir, `${link_name}.js`), "console.log(42);");
+ await writeFile(
+ join(package_dir, "package.json"),
+ JSON.stringify({
+ name: "foo",
+ version: "0.0.2",
+ dependencies: {
+ [link_name]: `link:${link_name}`,
+ },
+ }),
+ );
+
+ const {
+ stdout: stdout1,
+ stderr: stderr1,
+ exited: exited1,
+ } = spawn({
+ cmd: [bunExe(), "link"],
+ cwd: link_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+ expect(stderr1).toBeDefined();
+ const err1 = await new Response(stderr1).text();
+ expect(err1.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]);
+ expect(stdout1).toBeDefined();
+ expect(await new Response(stdout1).text()).toContain(`Success! Registered \\"${link_name}\\"`);
+ expect(await exited1).toBe(0);
+
+ const {
+ stdout: stdout2,
+ stderr: stderr2,
+ exited: exited2,
+ } = spawn({
+ cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
+ cwd: package_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+ expect(stderr2).toBeDefined();
+ const err2 = await new Response(stderr2).text();
+ expect(err2.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun install", " Saved lockfile", ""]);
+ expect(stdout2).toBeDefined();
+ const out2 = await new Response(stdout2).text();
+ expect(out2.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
+ ` + ${link_name}@link:${link_name}`,
+ "",
+ " 1 packages installed",
+ ]);
+ expect(await exited2).toBe(0);
+ expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".bin", ".cache", link_name].sort());
+ expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([link_name]);
+ expect(await readlink(join(package_dir, "node_modules", ".bin", link_name))).toBe(
+ join("..", link_name, `${link_name}.js`),
+ );
+ expect(await readdirSorted(join(package_dir, "node_modules", link_name))).toEqual(
+ ["package.json", `${link_name}.js`].sort(),
+ );
+ await access(join(package_dir, "bun.lockb"));
+
+ const {
+ stdout: stdout3,
+ stderr: stderr3,
+ exited: exited3,
+ } = spawn({
+ cmd: [bunExe(), "unlink"],
+ cwd: link_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+ expect(stderr3).toBeDefined();
+ const err3 = await new Response(stderr3).text();
+ expect(err3.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]);
+ expect(stdout3).toBeDefined();
+ expect(await new Response(stdout3).text()).toContain(`success: unlinked package "${link_name}"`);
+ expect(await exited3).toBe(0);
+
+ const {
+ stdout: stdout4,
+ stderr: stderr4,
+ exited: exited4,
+ } = spawn({
+ cmd: [bunExe(), "install"],
+ cwd: package_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+ expect(stderr4).toBeDefined();
+ const err4 = await new Response(stderr4).text();
+ expect(err4).toContain(`error: FileNotFound installing ${link_name}`);
+ expect(stdout4).toBeDefined();
+ expect(await new Response(stdout4).text()).toBe("");
+ expect(await exited4).toBe(0);
+});
diff --git a/test/fixtures/bun-link-to-pkg-fixture/bun.lockb b/test/fixtures/bun-link-to-pkg-fixture/bun.lockb
index 91f9f0e35..1f6e25aa6 100755
--- a/test/fixtures/bun-link-to-pkg-fixture/bun.lockb
+++ b/test/fixtures/bun-link-to-pkg-fixture/bun.lockb
Binary files differ