aboutsummaryrefslogtreecommitdiff
path: root/src/install/dependency.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/install/dependency.zig')
-rw-r--r--src/install/dependency.zig120
1 files changed, 100 insertions, 20 deletions
diff --git a/src/install/dependency.zig b/src/install/dependency.zig
index 8aac4e391..a9c2fa108 100644
--- a/src/install/dependency.zig
+++ b/src/install/dependency.zig
@@ -1,17 +1,19 @@
-const ExternalStringList = @import("./install.zig").ExternalStringList;
+const bun = @import("bun");
+const logger = bun.logger;
+const Environment = @import("../env.zig");
+const Install = @import("./install.zig");
+const ExternalStringList = Install.ExternalStringList;
+const Features = Install.Features;
+const PackageNameHash = Install.PackageNameHash;
+const Repository = @import("./repository.zig").Repository;
const Semver = @import("./semver.zig");
const ExternalString = Semver.ExternalString;
+const SlicedString = Semver.SlicedString;
const String = Semver.String;
const std = @import("std");
-const SlicedString = Semver.SlicedString;
-const PackageNameHash = @import("./install.zig").PackageNameHash;
-const Features = @import("./install.zig").Features;
-const Install = @import("./install.zig");
-const logger = @import("bun").logger;
-const Dependency = @This();
const string = @import("../string_types.zig").string;
const strings = @import("../string_immutable.zig");
-const bun = @import("bun");
+const Dependency = @This();
pub const Pair = struct {
resolution_id: Install.PackageID = Install.invalid_package_id,
@@ -189,7 +191,7 @@ pub const Version = struct {
}
pub fn isLessThan(string_buf: []const u8, lhs: Dependency.Version, rhs: Dependency.Version) bool {
- std.debug.assert(lhs.tag == rhs.tag);
+ if (Environment.allow_assert) std.debug.assert(lhs.tag == rhs.tag);
return strings.cmpStringsAsc({}, lhs.literal.slice(string_buf), rhs.literal.slice(string_buf));
}
@@ -236,6 +238,7 @@ pub const Version = struct {
.npm => strings.eql(lhs.literal.slice(lhs_buf), rhs.literal.slice(rhs_buf)) or
lhs.value.npm.eql(rhs.value.npm, lhs_buf, rhs_buf),
.folder, .dist_tag => lhs.literal.eql(rhs.literal, lhs_buf, rhs_buf),
+ .github => lhs.value.github.eql(rhs.value.github, lhs_buf, rhs_buf),
.tarball => lhs.value.tarball.eql(rhs.value.tarball, lhs_buf, rhs_buf),
.symlink => lhs.value.symlink.eql(rhs.value.symlink, lhs_buf, rhs_buf),
.workspace => lhs.value.workspace.eql(rhs.value.workspace, lhs_buf, rhs_buf),
@@ -274,24 +277,36 @@ pub const Version = struct {
}
pub inline fn isGitHubRepoPath(dependency: string) bool {
+ // Shortest valid expression: u/r
if (dependency.len < 3) return false;
- if (dependency[0] == '/') return false;
+ var hash_index: usize = 0;
var slash_index: usize = 0;
for (dependency) |c, i| {
- // Must be alphanumeric
switch (c) {
'/' => {
+ if (i == 0) return false;
if (slash_index > 0) return false;
slash_index = i;
},
- '\\', 'a'...'z', 'A'...'Z', '0'...'9', '%' => {},
+ '#' => {
+ if (i == 0) return false;
+ if (hash_index > 0) return false;
+ if (slash_index == 0) return false;
+ hash_index = i;
+ },
+ // Not allowed in username
+ '.', '_' => {
+ if (slash_index == 0) return false;
+ },
+ // Must be alphanumeric
+ '-', 'a'...'z', 'A'...'Z', '0'...'9' => {},
else => return false,
}
}
- return slash_index > 0 and slash_index != dependency.len - 1;
+ return hash_index != dependency.len - 1 and slash_index > 0 and slash_index != dependency.len - 1;
}
// this won't work for query string params
@@ -376,7 +391,9 @@ pub const Version = struct {
}
},
'h' => {
- if (strings.hasPrefixComptime(url, "hub:")) return .github;
+ if (strings.hasPrefixComptime(url, "hub:")) {
+ if (isGitHubRepoPath(url["hub:".len..])) return .github;
+ }
},
else => {},
}
@@ -403,7 +420,9 @@ pub const Version = struct {
},
else => {},
}
- if (strings.hasPrefixComptime(url, "github.com/")) return .github;
+ if (strings.hasPrefixComptime(url, "github.com/")) {
+ if (isGitHubRepoPath(url["github.com/".len..])) return .github;
+ }
}
}
},
@@ -489,8 +508,7 @@ pub const Version = struct {
workspace: String,
/// Unsupported, but still parsed so an error can be thrown
git: void,
- /// Unsupported, but still parsed so an error can be thrown
- github: void,
+ github: Repository,
};
};
@@ -625,10 +643,10 @@ pub fn parseWithTag(
alias;
// name should never be empty
- std.debug.assert(!actual.isEmpty());
+ if (Environment.allow_assert) std.debug.assert(!actual.isEmpty());
// tag should never be empty
- std.debug.assert(!tag_to_use.isEmpty());
+ if (Environment.allow_assert) std.debug.assert(!tag_to_use.isEmpty());
return Version{
.literal = sliced.value(),
@@ -641,6 +659,68 @@ pub fn parseWithTag(
.tag = .dist_tag,
};
},
+ .github => {
+ var from_url = false;
+ var input = dependency;
+ if (strings.hasPrefixComptime(input, "github:")) {
+ input = input["github:".len..];
+ } else if (strings.hasPrefixComptime(input, "http")) {
+ var url = input["http".len..];
+ if (url.len > 2) {
+ switch (url[0]) {
+ ':' => {
+ if (strings.hasPrefixComptime(url, "://")) {
+ url = url["://".len..];
+ }
+ },
+ 's' => {
+ if (strings.hasPrefixComptime(url, "s://")) {
+ url = url["s://".len..];
+ }
+ },
+ else => {},
+ }
+ if (strings.hasPrefixComptime(url, "github.com/")) {
+ input = url["github.com/".len..];
+ from_url = true;
+ }
+ }
+ }
+
+ if (Environment.allow_assert) std.debug.assert(Version.Tag.isGitHubRepoPath(input));
+
+ var hash_index: usize = 0;
+ var slash_index: usize = 0;
+ for (input) |c, i| {
+ switch (c) {
+ '/' => {
+ slash_index = i;
+ },
+ '#' => {
+ hash_index = i;
+ break;
+ },
+ else => {},
+ }
+ }
+
+ var repo = if (hash_index == 0) input[slash_index + 1 ..] else input[slash_index + 1 .. hash_index];
+ if (from_url and strings.endsWithComptime(repo, ".git")) {
+ repo = repo[0 .. repo.len - ".git".len];
+ }
+
+ return Version{
+ .literal = sliced.value(),
+ .value = .{
+ .github = .{
+ .owner = sliced.sub(input[0..slash_index]).value(),
+ .repo = sliced.sub(repo).value(),
+ .committish = if (hash_index == 0) String.from("") else sliced.sub(input[hash_index + 1 ..]).value(),
+ },
+ },
+ .tag = .github,
+ };
+ },
.tarball => {
if (strings.hasPrefixComptime(dependency, "https://") or strings.hasPrefixComptime(dependency, "http://")) {
return Version{
@@ -713,7 +793,7 @@ pub fn parseWithTag(
.literal = sliced.value(),
};
},
- .git, .github => {
+ .git => {
if (log_) |log| log.addErrorFmt(null, logger.Loc.Empty, allocator, "Support for dependency type \"{s}\" is not implemented yet (\"{s}\")", .{ @tagName(tag), dependency }) catch unreachable;
return null;
},