aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Justin "J.R." Hill <justin@so.dang.cool> 2023-09-27 18:22:50 -0800
committerGravatar GitHub <noreply@github.com> 2023-09-27 19:22:50 -0700
commit1d6d639352d58e65f6bbeff0188c01efbfa59bf8 (patch)
treee7ead427bc25b58f0fcd3d8592c1bb14f86d4cfe
parent7cd1dc2817158f9a27605ec5bac33575b9ef12f3 (diff)
downloadbun-1d6d639352d58e65f6bbeff0188c01efbfa59bf8.tar.gz
bun-1d6d639352d58e65f6bbeff0188c01efbfa59bf8.tar.zst
bun-1d6d639352d58e65f6bbeff0188c01efbfa59bf8.zip
fix(bun install): Handle vercel and github tarball path dependencies (#6122)
* fix(bun install): Handle vercel and github tarball path dependencies * test(bun install): test tarball path with when * Simplify github tarball detection --------- Co-authored-by: bun <noreply@oven.sh>
-rw-r--r--src/install/dependency.zig25
-rw-r--r--test/cli/install/bun-install.test.ts56
2 files changed, 80 insertions, 1 deletions
diff --git a/src/install/dependency.zig b/src/install/dependency.zig
index 9c7bcf479..01c1ecd86 100644
--- a/src/install/dependency.zig
+++ b/src/install/dependency.zig
@@ -221,6 +221,26 @@ pub inline fn isGitHubRepoPath(dependency: string) bool {
return hash_index != dependency.len - 1 and first_slash_index > 0 and first_slash_index != dependency.len - 1;
}
+// Github allows for the following format of URL:
+// https://github.com/<org>/<repo>/tarball/<ref>
+// This is a legacy (but still supported) method of retrieving a tarball of an
+// entire source tree at some git reference. (ref = branch, tag, etc. Note: branch
+// can have arbitrary number of slashes)
+pub inline fn isGitHubTarballPath(dependency: string) bool {
+ var parts = strings.split(dependency, "/");
+
+ var n_parts: usize = 0;
+
+ while (parts.next()) |part| {
+ n_parts += 1;
+ if (n_parts == 3) {
+ return strings.eql(part, "tarball");
+ }
+ }
+
+ return false;
+}
+
// This won't work for query string params, but I'll let someone file an issue
// before I add that.
pub inline fn isTarball(dependency: string) bool {
@@ -494,8 +514,11 @@ pub const Version = struct {
else => {},
}
if (strings.hasPrefixComptime(url, "github.com/")) {
- if (isGitHubRepoPath(url["github.com/".len..])) return .github;
+ const path = url["github.com/".len..];
+ if (isGitHubTarballPath(path)) return .tarball;
+ if (isGitHubRepoPath(path)) return .github;
}
+ return .tarball;
}
}
},
diff --git a/test/cli/install/bun-install.test.ts b/test/cli/install/bun-install.test.ts
index 3c70f8a8c..063f9ad04 100644
--- a/test/cli/install/bun-install.test.ts
+++ b/test/cli/install/bun-install.test.ts
@@ -2850,6 +2850,62 @@ it("should handle GitHub URL in dependencies (git+https://github.com/user/repo.g
await access(join(package_dir, "bun.lockb"));
});
+it("should handle GitHub tarball URL in dependencies (https://github.com/user/repo/tarball/ref)", async () => {
+ const urls: string[] = [];
+ setHandler(dummyRegistry(urls));
+ await writeFile(
+ join(package_dir, "package.json"),
+ JSON.stringify({
+ name: "Foo",
+ version: "0.0.1",
+ dependencies: {
+ when: "https://github.com/cujojs/when/tarball/1.0.2",
+ },
+ }),
+ );
+ const { stdout, stderr, exited } = spawn({
+ cmd: [bunExe(), "install"],
+ cwd: package_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+ expect(stderr).toBeDefined();
+ const err = await new Response(stderr).text();
+ expect(err).toContain("Saved lockfile");
+ expect(stdout).toBeDefined();
+ let out = await new Response(stdout).text();
+ out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "");
+ out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1");
+ expect(out.split(/\r?\n/)).toEqual([
+ " + when@https://github.com/cujojs/when/tarball/1.0.2",
+ "",
+ " 1 packages installed",
+ ]);
+ expect(await exited).toBe(0);
+ expect(urls.sort()).toBeEmpty();
+ expect(requested).toBe(0);
+ expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "when"]);
+ expect(await readdirSorted(join(package_dir, "node_modules", "when"))).toEqual([
+ ".gitignore",
+ ".gitmodules",
+ "LICENSE.txt",
+ "README.md",
+ "apply.js",
+ "cancelable.js",
+ "delay.js",
+ "package.json",
+ "test",
+ "timed.js",
+ "timeout.js",
+ "when.js",
+ ]);
+ const package_json = await file(join(package_dir, "node_modules", "when", "package.json")).json();
+ expect(package_json.name).toBe("when");
+ await access(join(package_dir, "bun.lockb"));
+});
+
it("should handle GitHub URL with existing lockfile", async () => {
const urls: string[] = [];
setHandler(dummyRegistry(urls));