diff options
author | 2021-11-08 23:41:46 -0800 | |
---|---|---|
committer | 2021-12-16 19:18:51 -0800 | |
commit | 442f85e89e413ed5c697bbf36181577ef38fd0f1 (patch) | |
tree | cd0dcc38624b423c9c3b0823abf6f2483a354ca8 /src/install | |
parent | 8cf8bf441ec10bd64fe697b5d3cfa007ab4613ac (diff) | |
download | bun-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.zig | 98 |
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()); } |