aboutsummaryrefslogtreecommitdiff
path: root/src/install
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-11-08 23:41:46 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-12-16 19:18:51 -0800
commit442f85e89e413ed5c697bbf36181577ef38fd0f1 (patch)
treecd0dcc38624b423c9c3b0823abf6f2483a354ca8 /src/install
parent8cf8bf441ec10bd64fe697b5d3cfa007ab4613ac (diff)
downloadbun-442f85e89e413ed5c697bbf36181577ef38fd0f1.tar.gz
bun-442f85e89e413ed5c697bbf36181577ef38fd0f1.tar.zst
bun-442f85e89e413ed5c697bbf36181577ef38fd0f1.zip
[bun install] support hyphen ranges in node-semver
Diffstat (limited to 'src/install')
-rw-r--r--src/install/semver.zig98
1 files changed, 96 insertions, 2 deletions
diff --git a/src/install/semver.zig b/src/install/semver.zig
index e010eced7..880357a09 100644
--- a/src/install/semver.zig
+++ b/src/install/semver.zig
@@ -779,6 +779,7 @@ pub const Query = struct {
var count: u8 = 0;
var skip_round = false;
var is_or = false;
+ var enable_hyphen = false;
var last_non_whitespace: usize = 0;
@@ -860,7 +861,82 @@ pub const Query = struct {
const parse_result = Version.parse(input[i..], allocator);
token.wildcard = parse_result.wildcard;
- if (count == 0 and token.tag == .version) {
+ i += parse_result.stopped_at;
+ const rollback = i;
+
+ const had_space = i < input.len and input[i] == ' ';
+
+ // TODO: can we do this without rolling back?
+ const hyphenate: bool = had_space and possibly_hyphenate: {
+ i += 1;
+ while (i < input.len and input[i] == ' ') : (i += 1) {}
+ if (!(i < input.len and input[i] == '-')) break :possibly_hyphenate false;
+ i += 1;
+ if (!(i < input.len and input[i] == ' ')) break :possibly_hyphenate false;
+ i += 1;
+ while (i < input.len and switch (input[i]) {
+ ' ', 'v', '=' => true,
+ else => false,
+ }) : (i += 1) {}
+ if (!(i < input.len and switch (input[i]) {
+ '0'...'9', 'X', 'x', '*' => true,
+ else => false,
+ })) break :possibly_hyphenate false;
+
+ break :possibly_hyphenate true;
+ };
+
+ if (!hyphenate) i = rollback;
+ i += @as(usize, @boolToInt(!hyphenate));
+
+ if (hyphenate) {
+ var second_version = Version.parse(input[i..], allocator);
+
+ const range: Range = brk: {
+ switch (second_version.wildcard) {
+ .major => {
+ second_version.version.major += 1;
+ break :brk Range{
+ .left = .{ .op = .gte, .version = parse_result.version },
+ .right = .{ .op = .lte, .version = second_version.version },
+ };
+ },
+ .minor => {
+ second_version.version.major += 1;
+ second_version.version.minor = 0;
+ second_version.version.patch = 0;
+
+ break :brk Range{
+ .left = .{ .op = .gte, .version = parse_result.version },
+ .right = .{ .op = .lt, .version = second_version.version },
+ };
+ },
+ .patch => {
+ second_version.version.minor += 1;
+ second_version.version.patch = 0;
+
+ break :brk Range{
+ .left = .{ .op = .gte, .version = parse_result.version },
+ .right = .{ .op = .lt, .version = second_version.version },
+ };
+ },
+ .none => {
+ break :brk Range{
+ .left = .{ .op = .gte, .version = parse_result.version },
+ .right = .{ .op = .lte, .version = second_version.version },
+ };
+ },
+ }
+ };
+
+ if (is_or) {
+ try list.orRange(range);
+ } else {
+ try list.andRange(range);
+ }
+
+ i += second_version.stopped_at + 1;
+ } else if (count == 0 and token.tag == .version) {
switch (parse_result.wildcard) {
.none => {
try list.orVersion(parse_result.version);
@@ -877,7 +953,6 @@ pub const Query = struct {
try list.andRange(token.toRange(parse_result.version));
}
- i += parse_result.stopped_at + 1;
is_or = false;
count += 1;
token.wildcard = .none;
@@ -1171,4 +1246,23 @@ test "Range parsing" {
expect.range("> 2.2 || 2.1.0 || >3", "3.0.1", @src());
expect.range("~2", "2.0.0", @src());
expect.range("~2", "2.1.0", @src());
+
+ expect.range("1.2.0 - 1.3.0", "1.2.2", @src());
+ expect.range("1.2 - 1.3", "1.2.2", @src());
+ expect.range("1 - 1.3", "1.2.2", @src());
+ expect.range("1 - 1.3", "1.3.0", @src());
+ expect.range("1.2 - 1.3", "1.3.1", @src());
+ expect.notRange("1.2 - 1.3", "1.4.0", @src());
+ expect.range("1 - 1.3", "1.3.1", @src());
+
+ expect.notRange("1.2 - 1.3 || 5.0", "6.4.0", @src());
+ expect.range("1.2 - 1.3 || 5.0", "1.2.1", @src());
+ expect.range("5.0 || 1.2 - 1.3", "1.2.1", @src());
+ expect.range("1.2 - 1.3 || 5.0", "5.0", @src());
+ expect.range("5.0 || 1.2 - 1.3", "5.0", @src());
+ expect.range("1.2 - 1.3 || 5.0", "5.0.2", @src());
+ expect.range("5.0 || 1.2 - 1.3", "5.0.2", @src());
+ expect.range("1.2 - 1.3 || 5.0", "5.0.2", @src());
+ expect.range("5.0 || 1.2 - 1.3", "5.0.2", @src());
+ expect.range("5.0 || 1.2 - 1.3 || >8", "9.0.2", @src());
}